summaryrefslogtreecommitdiffstats
path: root/libmariadb
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:24:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:24:36 +0000
commit06eaf7232e9a920468c0f8d74dcf2fe8b555501c (patch)
treee2c7b5777f728320e5b5542b6213fd3591ba51e2 /libmariadb
parentInitial commit. (diff)
downloadmariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.tar.xz
mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.zip
Adding upstream version 1:10.11.6.upstream/1%10.11.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libmariadb')
-rw-r--r--libmariadb/.gitmodules0
-rw-r--r--libmariadb/.travis.yml109
-rw-r--r--libmariadb/CMakeLists.txt554
-rw-r--r--libmariadb/COPYING.LIB502
-rw-r--r--libmariadb/README15
-rw-r--r--libmariadb/appveyor-download.bat16
-rw-r--r--libmariadb/appveyor.yml41
-rw-r--r--libmariadb/benchmark/README.md53
-rwxr-xr-xlibmariadb/benchmark/build.sh19
-rwxr-xr-xlibmariadb/benchmark/installation.sh17
-rwxr-xr-xlibmariadb/benchmark/launch.sh17
-rw-r--r--libmariadb/benchmark/main-benchmark.cc556
-rw-r--r--libmariadb/client/CMakeLists.txt17
-rw-r--r--libmariadb/client/ma_plugin_info.c211
-rw-r--r--libmariadb/cmake/COPYING-CMAKE-SCRIPTS22
-rw-r--r--libmariadb/cmake/ConnectorName.cmake34
-rw-r--r--libmariadb/cmake/FindGSSAPI.cmake110
-rw-r--r--libmariadb/cmake/FindIconv.cmake82
-rw-r--r--libmariadb/cmake/FindZStd.cmake21
-rw-r--r--libmariadb/cmake/SearchLibrary.cmake29
-rw-r--r--libmariadb/cmake/WindowsCache.cmake391
-rw-r--r--libmariadb/cmake/check_functions.cmake30
-rw-r--r--libmariadb/cmake/check_include_files.cmake53
-rw-r--r--libmariadb/cmake/check_types.cmake62
-rw-r--r--libmariadb/cmake/export.cmake30
-rw-r--r--libmariadb/cmake/install.cmake160
-rw-r--r--libmariadb/cmake/install_plugins.cmake20
-rw-r--r--libmariadb/cmake/libressl_version.c7
-rw-r--r--libmariadb/cmake/linux_x86_toolchain.cmake18
-rw-r--r--libmariadb/cmake/misc.cmake13
-rw-r--r--libmariadb/cmake/plugins.cmake94
-rw-r--r--libmariadb/cmake/sign.cmake20
-rw-r--r--libmariadb/cmake/symlink.cmake35
-rw-r--r--libmariadb/cmake/version_info.cmake44
-rw-r--r--libmariadb/external/zlib/CMakeLists.txt151
-rw-r--r--libmariadb/external/zlib/ChangeLog1578
-rw-r--r--libmariadb/external/zlib/FAQ368
-rw-r--r--libmariadb/external/zlib/INDEX65
-rw-r--r--libmariadb/external/zlib/Makefile.in306
-rw-r--r--libmariadb/external/zlib/README115
-rw-r--r--libmariadb/external/zlib/adler32.c186
-rw-r--r--libmariadb/external/zlib/adler32_simd.c387
-rw-r--r--libmariadb/external/zlib/adler32_simd.h37
-rw-r--r--libmariadb/external/zlib/amiga/Makefile.pup69
-rw-r--r--libmariadb/external/zlib/amiga/Makefile.sas68
-rw-r--r--libmariadb/external/zlib/as400/bndsrc215
-rw-r--r--libmariadb/external/zlib/as400/compile.clp110
-rw-r--r--libmariadb/external/zlib/as400/readme.txt115
-rw-r--r--libmariadb/external/zlib/as400/zlib.inc451
-rw-r--r--libmariadb/external/zlib/chunkcopy.h485
-rw-r--r--libmariadb/external/zlib/compress.c86
-rwxr-xr-xlibmariadb/external/zlib/configure931
-rw-r--r--libmariadb/external/zlib/crc32.c1125
-rw-r--r--libmariadb/external/zlib/crc32.h9446
-rw-r--r--libmariadb/external/zlib/crc32_simd.c244
-rw-r--r--libmariadb/external/zlib/crc32_simd.h69
-rw-r--r--libmariadb/external/zlib/deflate.c2217
-rw-r--r--libmariadb/external/zlib/deflate.h346
-rw-r--r--libmariadb/external/zlib/doc/algorithm.txt209
-rw-r--r--libmariadb/external/zlib/doc/rfc1950.txt619
-rw-r--r--libmariadb/external/zlib/doc/rfc1951.txt955
-rw-r--r--libmariadb/external/zlib/doc/rfc1952.txt675
-rw-r--r--libmariadb/external/zlib/doc/txtvsbin.txt107
-rw-r--r--libmariadb/external/zlib/example.c565
-rw-r--r--libmariadb/external/zlib/examples/README.examples49
-rw-r--r--libmariadb/external/zlib/examples/enough.c572
-rw-r--r--libmariadb/external/zlib/examples/fitblk.c233
-rw-r--r--libmariadb/external/zlib/examples/gun.c702
-rw-r--r--libmariadb/external/zlib/examples/gzappend.c504
-rw-r--r--libmariadb/external/zlib/examples/gzjoin.c449
-rw-r--r--libmariadb/external/zlib/examples/gzlog.c1059
-rw-r--r--libmariadb/external/zlib/examples/gzlog.h91
-rw-r--r--libmariadb/external/zlib/examples/zlib_how.html545
-rw-r--r--libmariadb/external/zlib/examples/zpipe.c205
-rw-r--r--libmariadb/external/zlib/examples/zran.c409
-rw-r--r--libmariadb/external/zlib/gzclose.c25
-rw-r--r--libmariadb/external/zlib/gzguts.h219
-rw-r--r--libmariadb/external/zlib/gzlib.c639
-rw-r--r--libmariadb/external/zlib/gzread.c650
-rw-r--r--libmariadb/external/zlib/gzwrite.c677
-rw-r--r--libmariadb/external/zlib/infback.c644
-rw-r--r--libmariadb/external/zlib/inffast.c323
-rw-r--r--libmariadb/external/zlib/inffast.h11
-rw-r--r--libmariadb/external/zlib/inffast_chunk.c379
-rw-r--r--libmariadb/external/zlib/inffast_chunk.h48
-rw-r--r--libmariadb/external/zlib/inffixed.h94
-rw-r--r--libmariadb/external/zlib/inflate.c1595
-rw-r--r--libmariadb/external/zlib/inflate.h126
-rw-r--r--libmariadb/external/zlib/inftrees.c304
-rw-r--r--libmariadb/external/zlib/inftrees.h62
-rw-r--r--libmariadb/external/zlib/make_vms.com867
-rw-r--r--libmariadb/external/zlib/minigzip.c440
-rw-r--r--libmariadb/external/zlib/msdos/Makefile.bor115
-rw-r--r--libmariadb/external/zlib/msdos/Makefile.dj2104
-rw-r--r--libmariadb/external/zlib/msdos/Makefile.emx69
-rw-r--r--libmariadb/external/zlib/msdos/Makefile.msc112
-rw-r--r--libmariadb/external/zlib/msdos/Makefile.tc100
-rw-r--r--libmariadb/external/zlib/nintendods/README5
-rw-r--r--libmariadb/external/zlib/old/Makefile.emx69
-rw-r--r--libmariadb/external/zlib/old/Makefile.riscos151
-rw-r--r--libmariadb/external/zlib/old/README3
-rw-r--r--libmariadb/external/zlib/old/descrip.mms48
-rw-r--r--libmariadb/external/zlib/old/os2/Makefile.os2136
-rw-r--r--libmariadb/external/zlib/old/os2/zlib.def51
-rw-r--r--libmariadb/external/zlib/old/visual-basic.txt160
-rw-r--r--libmariadb/external/zlib/qnx/package.qpg141
-rw-r--r--libmariadb/external/zlib/treebuild.xml116
-rw-r--r--libmariadb/external/zlib/trees.c1181
-rw-r--r--libmariadb/external/zlib/trees.h128
-rw-r--r--libmariadb/external/zlib/ucm.cmake636
-rw-r--r--libmariadb/external/zlib/uncompr.c93
-rw-r--r--libmariadb/external/zlib/watcom/watcom_f.mak43
-rw-r--r--libmariadb/external/zlib/watcom/watcom_l.mak43
-rw-r--r--libmariadb/external/zlib/win32/DLL_FAQ.txt397
-rw-r--r--libmariadb/external/zlib/win32/Makefile.bor110
-rw-r--r--libmariadb/external/zlib/win32/Makefile.gcc182
-rwxr-xr-xlibmariadb/external/zlib/win32/Makefile.msc163
-rw-r--r--libmariadb/external/zlib/win32/README-WIN32.txt103
-rw-r--r--libmariadb/external/zlib/win32/VisualC.txt3
-rw-r--r--libmariadb/external/zlib/win32/zlib.def86
-rw-r--r--libmariadb/external/zlib/win32/zlib1.rc40
-rw-r--r--libmariadb/external/zlib/zconf.h.cmakein549
-rw-r--r--libmariadb/external/zlib/zlib.3151
-rw-r--r--libmariadb/external/zlib/zlib.3.pdf0
-rw-r--r--libmariadb/external/zlib/zlib.h1935
-rw-r--r--libmariadb/external/zlib/zlib.map100
-rw-r--r--libmariadb/external/zlib/zlib.pc.cmakein13
-rw-r--r--libmariadb/external/zlib/zlib.pc.in13
-rwxr-xr-xlibmariadb/external/zlib/zlib2ansi152
-rw-r--r--libmariadb/external/zlib/zutil.c327
-rw-r--r--libmariadb/external/zlib/zutil.h275
-rw-r--r--libmariadb/include/CMakeLists.txt41
-rw-r--r--libmariadb/include/errmsg.h131
-rw-r--r--libmariadb/include/ma_common.h131
-rw-r--r--libmariadb/include/ma_compress.h48
-rw-r--r--libmariadb/include/ma_config.h.in150
-rw-r--r--libmariadb/include/ma_context.h242
-rw-r--r--libmariadb/include/ma_crypt.h155
-rw-r--r--libmariadb/include/ma_decimal.h64
-rw-r--r--libmariadb/include/ma_global.h1094
-rw-r--r--libmariadb/include/ma_hashtbl.h70
-rw-r--r--libmariadb/include/ma_list.h47
-rw-r--r--libmariadb/include/ma_priv.h70
-rw-r--r--libmariadb/include/ma_pthread.h34
-rw-r--r--libmariadb/include/ma_pvio.h141
-rw-r--r--libmariadb/include/ma_server_error.h2
-rw-r--r--libmariadb/include/ma_sha1.h42
-rw-r--r--libmariadb/include/ma_string.h55
-rw-r--r--libmariadb/include/ma_sys.h539
-rw-r--r--libmariadb/include/ma_tls.h163
-rw-r--r--libmariadb/include/mariadb/ma_io.h55
-rw-r--r--libmariadb/include/mariadb_async.h39
-rw-r--r--libmariadb/include/mariadb_com.h478
-rw-r--r--libmariadb/include/mariadb_ctype.h76
-rw-r--r--libmariadb/include/mariadb_dyncol.h260
-rw-r--r--libmariadb/include/mariadb_rpl.h653
-rw-r--r--libmariadb/include/mariadb_stmt.h255
-rw-r--r--libmariadb/include/mariadb_version.h.in44
-rw-r--r--libmariadb/include/mysql.h907
-rw-r--r--libmariadb/include/mysql/client_plugin.h258
-rw-r--r--libmariadb/include/mysql/plugin_auth.h107
-rw-r--r--libmariadb/include/mysql/plugin_auth_common.h110
-rw-r--r--libmariadb/include/mysqld_error.h1240
-rw-r--r--libmariadb/libmariadb/CMakeLists.txt526
-rw-r--r--libmariadb/libmariadb/bmove_upp.c33
-rw-r--r--libmariadb/libmariadb/get_password.c172
-rw-r--r--libmariadb/libmariadb/ma_alloc.c196
-rw-r--r--libmariadb/libmariadb/ma_array.c172
-rw-r--r--libmariadb/libmariadb/ma_charset.c1603
-rw-r--r--libmariadb/libmariadb/ma_client_plugin.c.in503
-rw-r--r--libmariadb/libmariadb/ma_compress.c113
-rw-r--r--libmariadb/libmariadb/ma_context.c728
-rw-r--r--libmariadb/libmariadb/ma_decimal.c479
-rw-r--r--libmariadb/libmariadb/ma_default.c370
-rw-r--r--libmariadb/libmariadb/ma_dtoa.c1924
-rw-r--r--libmariadb/libmariadb/ma_errmsg.c131
-rw-r--r--libmariadb/libmariadb/ma_hashtbl.c580
-rw-r--r--libmariadb/libmariadb/ma_init.c87
-rw-r--r--libmariadb/libmariadb/ma_io.c224
-rw-r--r--libmariadb/libmariadb/ma_list.c114
-rw-r--r--libmariadb/libmariadb/ma_ll2str.c70
-rw-r--r--libmariadb/libmariadb/ma_loaddata.c265
-rw-r--r--libmariadb/libmariadb/ma_net.c595
-rw-r--r--libmariadb/libmariadb/ma_password.c162
-rw-r--r--libmariadb/libmariadb/ma_pvio.c598
-rw-r--r--libmariadb/libmariadb/ma_sha1.c326
-rw-r--r--libmariadb/libmariadb/ma_stmt_codec.c1362
-rw-r--r--libmariadb/libmariadb/ma_string.c163
-rw-r--r--libmariadb/libmariadb/ma_time.c65
-rw-r--r--libmariadb/libmariadb/ma_tls.c237
-rw-r--r--libmariadb/libmariadb/mariadb_async.c1946
-rw-r--r--libmariadb/libmariadb/mariadb_charset.c74
-rw-r--r--libmariadb/libmariadb/mariadb_dyncol.c4369
-rw-r--r--libmariadb/libmariadb/mariadb_lib.c4979
-rw-r--r--libmariadb/libmariadb/mariadb_rpl.c2099
-rw-r--r--libmariadb/libmariadb/mariadb_stmt.c2636
-rw-r--r--libmariadb/libmariadb/secure/gnutls.c1438
-rw-r--r--libmariadb/libmariadb/secure/gnutls_crypt.c77
-rw-r--r--libmariadb/libmariadb/secure/ma_schannel.c629
-rw-r--r--libmariadb/libmariadb/secure/ma_schannel.h87
-rw-r--r--libmariadb/libmariadb/secure/openssl.c786
-rw-r--r--libmariadb/libmariadb/secure/openssl_crypt.c88
-rw-r--r--libmariadb/libmariadb/secure/schannel.c567
-rw-r--r--libmariadb/libmariadb/secure/schannel_certs.c852
-rw-r--r--libmariadb/libmariadb/secure/schannel_certs.h53
-rw-r--r--libmariadb/libmariadb/secure/win_crypt.c162
-rw-r--r--libmariadb/libmariadb/win32_errmsg.c138
-rw-r--r--libmariadb/libmariadb/win32_errmsg.h2
-rw-r--r--libmariadb/man/CMakeLists.txt123
-rw-r--r--libmariadb/man/mariadb_cancel.336
-rw-r--r--libmariadb/man/mariadb_connection.329
-rw-r--r--libmariadb/man/mariadb_dyncol_check.332
-rw-r--r--libmariadb/man/mariadb_dyncol_column_cmp_named.331
-rw-r--r--libmariadb/man/mariadb_dyncol_column_count.336
-rw-r--r--libmariadb/man/mariadb_dyncol_create_many_named.351
-rw-r--r--libmariadb/man/mariadb_dyncol_create_many_num.351
-rw-r--r--libmariadb/man/mariadb_dyncol_exists_named.333
-rw-r--r--libmariadb/man/mariadb_dyncol_exists_num.333
-rw-r--r--libmariadb/man/mariadb_dyncol_free.330
-rw-r--r--libmariadb/man/mariadb_dyncol_get_named.336
-rw-r--r--libmariadb/man/mariadb_dyncol_get_num.336
-rw-r--r--libmariadb/man/mariadb_dyncol_has_names.329
-rw-r--r--libmariadb/man/mariadb_dyncol_json.333
-rw-r--r--libmariadb/man/mariadb_dyncol_list_named.343
-rw-r--r--libmariadb/man/mariadb_dyncol_list_num.343
-rw-r--r--libmariadb/man/mariadb_dyncol_unpack.350
-rw-r--r--libmariadb/man/mariadb_dyncol_update_many_named.347
-rw-r--r--libmariadb/man/mariadb_dyncol_update_many_num.347
-rw-r--r--libmariadb/man/mariadb_field_attr.392
-rw-r--r--libmariadb/man/mariadb_free_rpl_event.326
-rw-r--r--libmariadb/man/mariadb_get_infov.3325
-rw-r--r--libmariadb/man/mariadb_reconnect.336
-rw-r--r--libmariadb/man/mariadb_rpl_close.331
-rw-r--r--libmariadb/man/mariadb_rpl_fetch.342
-rw-r--r--libmariadb/man/mariadb_rpl_get_optionsv.374
-rw-r--r--libmariadb/man/mariadb_rpl_open.329
-rw-r--r--libmariadb/man/mariadb_rpl_optionsv.375
-rw-r--r--libmariadb/man/mariadb_stmt_execute_direct.381
-rw-r--r--libmariadb/man/mariadb_stmt_fetch_fields.336
-rw-r--r--libmariadb/man/mysql_affected_rows.346
-rw-r--r--libmariadb/man/mysql_autocommit.382
-rw-r--r--libmariadb/man/mysql_change_user.362
-rw-r--r--libmariadb/man/mysql_close.328
-rw-r--r--libmariadb/man/mysql_commit.333
-rw-r--r--libmariadb/man/mysql_data_seek.339
-rw-r--r--libmariadb/man/mysql_eof.329
-rw-r--r--libmariadb/man/mysql_errno.337
-rw-r--r--libmariadb/man/mysql_error.341
-rw-r--r--libmariadb/man/mysql_fetch_field.349
-rw-r--r--libmariadb/man/mysql_fetch_field_direct.336
-rw-r--r--libmariadb/man/mysql_fetch_fields.341
-rw-r--r--libmariadb/man/mysql_fetch_lengths.341
-rw-r--r--libmariadb/man/mysql_fetch_row.344
-rw-r--r--libmariadb/man/mysql_field_count.343
-rw-r--r--libmariadb/man/mysql_field_seek.343
-rw-r--r--libmariadb/man/mysql_field_tell.332
-rw-r--r--libmariadb/man/mysql_free_result.336
-rw-r--r--libmariadb/man/mysql_get_character_set_info.339
-rw-r--r--libmariadb/man/mysql_get_client_info.331
-rw-r--r--libmariadb/man/mysql_get_client_version.332
-rw-r--r--libmariadb/man/mysql_get_host_info.332
-rw-r--r--libmariadb/man/mysql_get_proto_info.333
-rw-r--r--libmariadb/man/mysql_get_server_info.337
-rw-r--r--libmariadb/man/mysql_get_server_version.334
-rw-r--r--libmariadb/man/mysql_get_socket.333
-rw-r--r--libmariadb/man/mysql_get_ssl_cipher.347
-rw-r--r--libmariadb/man/mysql_hex_string.341
-rw-r--r--libmariadb/man/mysql_info.376
-rw-r--r--libmariadb/man/mysql_init.339
-rw-r--r--libmariadb/man/mysql_insert_id.333
-rw-r--r--libmariadb/man/mysql_kill.351
-rw-r--r--libmariadb/man/mysql_more_results.347
-rw-r--r--libmariadb/man/mysql_next_result.345
-rw-r--r--libmariadb/man/mysql_num_fields.331
-rw-r--r--libmariadb/man/mysql_num_rows.335
-rw-r--r--libmariadb/man/mysql_options.337
-rw-r--r--libmariadb/man/mysql_options4.338
-rw-r--r--libmariadb/man/mysql_optionsv.3420
-rw-r--r--libmariadb/man/mysql_ping.344
-rw-r--r--libmariadb/man/mysql_query.356
-rw-r--r--libmariadb/man/mysql_read_query_result.339
-rw-r--r--libmariadb/man/mysql_real_connect.3171
-rw-r--r--libmariadb/man/mysql_real_escape_string.349
-rw-r--r--libmariadb/man/mysql_real_query.350
-rw-r--r--libmariadb/man/mysql_refresh.392
-rw-r--r--libmariadb/man/mysql_reset_connection.348
-rw-r--r--libmariadb/man/mysql_rollback.334
-rw-r--r--libmariadb/man/mysql_row_seek.341
-rw-r--r--libmariadb/man/mysql_row_tell.334
-rw-r--r--libmariadb/man/mysql_select_db.384
-rw-r--r--libmariadb/man/mysql_send_query.352
-rw-r--r--libmariadb/man/mysql_server_end.333
-rw-r--r--libmariadb/man/mysql_server_init.338
-rw-r--r--libmariadb/man/mysql_session_track_get_first.374
-rw-r--r--libmariadb/man/mysql_session_track_get_next.362
-rw-r--r--libmariadb/man/mysql_set_character_set.3251
-rw-r--r--libmariadb/man/mysql_set_server_option.356
-rw-r--r--libmariadb/man/mysql_shutdown.341
-rw-r--r--libmariadb/man/mysql_sqlstate.337
-rw-r--r--libmariadb/man/mysql_ssl_set.357
-rw-r--r--libmariadb/man/mysql_stat.335
-rw-r--r--libmariadb/man/mysql_stmt_affected_rows.342
-rw-r--r--libmariadb/man/mysql_stmt_attr_get.397
-rw-r--r--libmariadb/man/mysql_stmt_attr_set.3131
-rw-r--r--libmariadb/man/mysql_stmt_bind_param.350
-rw-r--r--libmariadb/man/mysql_stmt_bind_result.345
-rw-r--r--libmariadb/man/mysql_stmt_close.339
-rw-r--r--libmariadb/man/mysql_stmt_data_seek.343
-rw-r--r--libmariadb/man/mysql_stmt_errno.338
-rw-r--r--libmariadb/man/mysql_stmt_error.340
-rw-r--r--libmariadb/man/mysql_stmt_execute.343
-rw-r--r--libmariadb/man/mysql_stmt_fetch.348
-rw-r--r--libmariadb/man/mysql_stmt_fetch_column.344
-rw-r--r--libmariadb/man/mysql_stmt_field_count.338
-rw-r--r--libmariadb/man/mysql_stmt_free_result.330
-rw-r--r--libmariadb/man/mysql_stmt_init.343
-rw-r--r--libmariadb/man/mysql_stmt_insert_id.336
-rw-r--r--libmariadb/man/mysql_stmt_more_results.339
-rw-r--r--libmariadb/man/mysql_stmt_next_result.342
-rw-r--r--libmariadb/man/mysql_stmt_num_rows.337
-rw-r--r--libmariadb/man/mysql_stmt_param_count.337
-rw-r--r--libmariadb/man/mysql_stmt_param_metadata.327
-rw-r--r--libmariadb/man/mysql_stmt_prepare.358
-rw-r--r--libmariadb/man/mysql_stmt_reset.344
-rw-r--r--libmariadb/man/mysql_stmt_result_metadata.350
-rw-r--r--libmariadb/man/mysql_stmt_row_seek.340
-rw-r--r--libmariadb/man/mysql_stmt_row_tell.337
-rw-r--r--libmariadb/man/mysql_stmt_send_long_data.351
-rw-r--r--libmariadb/man/mysql_stmt_sqlstate.336
-rw-r--r--libmariadb/man/mysql_stmt_store_result.338
-rw-r--r--libmariadb/man/mysql_stmt_warning_count.338
-rw-r--r--libmariadb/man/mysql_store_result.339
-rw-r--r--libmariadb/man/mysql_thread_end.336
-rw-r--r--libmariadb/man/mysql_thread_id.339
-rw-r--r--libmariadb/man/mysql_thread_init.341
-rw-r--r--libmariadb/man/mysql_use_result.346
-rw-r--r--libmariadb/man/mysql_warning_count.341
-rw-r--r--libmariadb/mariadb_config/CMakeLists.txt67
-rw-r--r--libmariadb/mariadb_config/libmariadb.pc.in20
-rw-r--r--libmariadb/mariadb_config/mariadb_config.c.in319
-rw-r--r--libmariadb/plugins/CMakeLists.txt9
-rw-r--r--libmariadb/plugins/auth/CMakeLists.txt142
-rw-r--r--libmariadb/plugins/auth/auth_gssapi_client.c121
-rw-r--r--libmariadb/plugins/auth/caching_sha2_pw.c464
-rw-r--r--libmariadb/plugins/auth/common.h4
-rw-r--r--libmariadb/plugins/auth/dialog.c222
-rw-r--r--libmariadb/plugins/auth/ed25519.c137
-rw-r--r--libmariadb/plugins/auth/ed25519_common.h26
-rw-r--r--libmariadb/plugins/auth/gssapi_client.c131
-rw-r--r--libmariadb/plugins/auth/gssapi_errmsg.c79
-rw-r--r--libmariadb/plugins/auth/gssapi_errmsg.h29
-rw-r--r--libmariadb/plugins/auth/mariadb_cleartext.c76
-rw-r--r--libmariadb/plugins/auth/my_auth.c741
-rw-r--r--libmariadb/plugins/auth/old_password.c117
-rw-r--r--libmariadb/plugins/auth/ref10/api.h3
-rw-r--r--libmariadb/plugins/auth/ref10/base.h1344
-rw-r--r--libmariadb/plugins/auth/ref10/base2.h40
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_hash_sha512.h7
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_int32.h5
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_int64.h5
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_sign.h13
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_uint32.h5
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_uint64.h5
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_verify.h1
-rw-r--r--libmariadb/plugins/auth/ref10/crypto_verify_32.h2
-rw-r--r--libmariadb/plugins/auth/ref10/d.h1
-rw-r--r--libmariadb/plugins/auth/ref10/d2.h1
-rw-r--r--libmariadb/plugins/auth/ref10/fe.h56
-rw-r--r--libmariadb/plugins/auth/ref10/fe_0.c19
-rw-r--r--libmariadb/plugins/auth/ref10/fe_1.c19
-rw-r--r--libmariadb/plugins/auth/ref10/fe_add.c57
-rw-r--r--libmariadb/plugins/auth/ref10/fe_cmov.c63
-rw-r--r--libmariadb/plugins/auth/ref10/fe_copy.c29
-rw-r--r--libmariadb/plugins/auth/ref10/fe_frombytes.c73
-rw-r--r--libmariadb/plugins/auth/ref10/fe_invert.c14
-rw-r--r--libmariadb/plugins/auth/ref10/fe_isnegative.c16
-rw-r--r--libmariadb/plugins/auth/ref10/fe_isnonzero.c19
-rw-r--r--libmariadb/plugins/auth/ref10/fe_mul.c253
-rw-r--r--libmariadb/plugins/auth/ref10/fe_neg.c45
-rw-r--r--libmariadb/plugins/auth/ref10/fe_pow22523.c13
-rw-r--r--libmariadb/plugins/auth/ref10/fe_sq.c149
-rw-r--r--libmariadb/plugins/auth/ref10/fe_sq2.c160
-rw-r--r--libmariadb/plugins/auth/ref10/fe_sub.c57
-rw-r--r--libmariadb/plugins/auth/ref10/fe_tobytes.c119
-rw-r--r--libmariadb/plugins/auth/ref10/ge.h95
-rw-r--r--libmariadb/plugins/auth/ref10/ge_add.c11
-rw-r--r--libmariadb/plugins/auth/ref10/ge_add.h97
-rw-r--r--libmariadb/plugins/auth/ref10/ge_double_scalarmult.c96
-rw-r--r--libmariadb/plugins/auth/ref10/ge_frombytes.c50
-rw-r--r--libmariadb/plugins/auth/ref10/ge_madd.c11
-rw-r--r--libmariadb/plugins/auth/ref10/ge_madd.h88
-rw-r--r--libmariadb/plugins/auth/ref10/ge_msub.c11
-rw-r--r--libmariadb/plugins/auth/ref10/ge_msub.h88
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p1p1_to_p2.c12
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p1p1_to_p3.c13
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p2_0.c8
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p2_dbl.c11
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p2_dbl.h73
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p3_0.c9
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p3_dbl.c12
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p3_to_cached.c17
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p3_to_p2.c12
-rw-r--r--libmariadb/plugins/auth/ref10/ge_p3_tobytes.c14
-rw-r--r--libmariadb/plugins/auth/ref10/ge_precomp_0.c8
-rw-r--r--libmariadb/plugins/auth/ref10/ge_scalarmult_base.c105
-rw-r--r--libmariadb/plugins/auth/ref10/ge_sub.c11
-rw-r--r--libmariadb/plugins/auth/ref10/ge_sub.h97
-rw-r--r--libmariadb/plugins/auth/ref10/ge_tobytes.c14
-rw-r--r--libmariadb/plugins/auth/ref10/keypair.c23
-rw-r--r--libmariadb/plugins/auth/ref10/open.c36
-rw-r--r--libmariadb/plugins/auth/ref10/pow22523.h168
-rw-r--r--libmariadb/plugins/auth/ref10/pow225521.h166
-rw-r--r--libmariadb/plugins/auth/ref10/sc.h15
-rw-r--r--libmariadb/plugins/auth/ref10/sc_muladd.c368
-rw-r--r--libmariadb/plugins/auth/ref10/sc_reduce.c275
-rw-r--r--libmariadb/plugins/auth/ref10/sign.c39
-rw-r--r--libmariadb/plugins/auth/ref10/sqrtm1.h1
-rw-r--r--libmariadb/plugins/auth/ref10/verify.c40
-rw-r--r--libmariadb/plugins/auth/server_plugin.h51
-rw-r--r--libmariadb/plugins/auth/sha256_pw.c356
-rw-r--r--libmariadb/plugins/auth/sspi_client.c184
-rw-r--r--libmariadb/plugins/auth/sspi_common.h38
-rw-r--r--libmariadb/plugins/auth/sspi_errmsg.c169
-rw-r--r--libmariadb/plugins/compress/CMakeLists.txt23
-rw-r--r--libmariadb/plugins/compress/c_zlib.c99
-rw-r--r--libmariadb/plugins/compress/c_zstd.c128
-rw-r--r--libmariadb/plugins/connection/CMakeLists.txt6
-rw-r--r--libmariadb/plugins/connection/replication.c357
-rw-r--r--libmariadb/plugins/io/CMakeLists.txt15
-rw-r--r--libmariadb/plugins/io/remote_io.c453
-rw-r--r--libmariadb/plugins/plugin.def2
-rw-r--r--libmariadb/plugins/pvio/CMakeLists.txt27
-rw-r--r--libmariadb/plugins/pvio/pvio_npipe.c359
-rw-r--r--libmariadb/plugins/pvio/pvio_plugin.def2
-rw-r--r--libmariadb/plugins/pvio/pvio_shmem.c469
-rw-r--r--libmariadb/plugins/pvio/pvio_socket.c1165
-rw-r--r--libmariadb/plugins/trace/trace_example.c458
-rwxr-xr-xlibmariadb/scripts/create_man54
-rwxr-xr-xlibmariadb/travis.sh107
-rw-r--r--libmariadb/unittest/libmariadb/CMakeLists.txt67
-rw-r--r--libmariadb/unittest/libmariadb/async.c321
-rw-r--r--libmariadb/unittest/libmariadb/basic-t.c885
-rw-r--r--libmariadb/unittest/libmariadb/bulk1.c1099
-rw-r--r--libmariadb/unittest/libmariadb/charset.c881
-rw-r--r--libmariadb/unittest/libmariadb/conc336.c59
-rw-r--r--libmariadb/unittest/libmariadb/connection.c2365
-rw-r--r--libmariadb/unittest/libmariadb/cursor.c1852
-rw-r--r--libmariadb/unittest/libmariadb/data.csv100
-rw-r--r--libmariadb/unittest/libmariadb/dyncol.c323
-rw-r--r--libmariadb/unittest/libmariadb/errors.c299
-rw-r--r--libmariadb/unittest/libmariadb/features-10_2.c255
-rw-r--r--libmariadb/unittest/libmariadb/fetch.c1003
-rw-r--r--libmariadb/unittest/libmariadb/fingerprint.list.in4
-rw-r--r--libmariadb/unittest/libmariadb/getopt.c742
-rw-r--r--libmariadb/unittest/libmariadb/logs.c223
-rw-r--r--libmariadb/unittest/libmariadb/ma_getopt.c741
-rw-r--r--libmariadb/unittest/libmariadb/ma_getopt.h131
-rw-r--r--libmariadb/unittest/libmariadb/misc.c1689
-rw-r--r--libmariadb/unittest/libmariadb/my_test.h770
-rw-r--r--libmariadb/unittest/libmariadb/performance.c76
-rw-r--r--libmariadb/unittest/libmariadb/ps.c5315
-rw-r--r--libmariadb/unittest/libmariadb/ps_bugs.c5846
-rw-r--r--libmariadb/unittest/libmariadb/ps_new.c526
-rw-r--r--libmariadb/unittest/libmariadb/result.c1105
-rw-r--r--libmariadb/unittest/libmariadb/rpl_api.c363
-rw-r--r--libmariadb/unittest/libmariadb/sp.c91
-rw-r--r--libmariadb/unittest/libmariadb/ssl.c1424
-rw-r--r--libmariadb/unittest/libmariadb/t_conc173.c72
-rw-r--r--libmariadb/unittest/libmariadb/thread.c180
-rw-r--r--libmariadb/unittest/libmariadb/view.c723
-rw-r--r--libmariadb/unittest/mytap/CMakeLists.txt19
-rw-r--r--libmariadb/unittest/mytap/Doxyfile1156
-rw-r--r--libmariadb/unittest/mytap/t/basic-t.c33
-rw-r--r--libmariadb/unittest/mytap/tap.c600
-rw-r--r--libmariadb/unittest/mytap/tap.h305
-rw-r--r--libmariadb/win-iconv/iconv.h14
-rw-r--r--libmariadb/win-iconv/mlang.h54
-rw-r--r--libmariadb/win-iconv/win_iconv.c2051
-rw-r--r--libmariadb/win/packaging/CMakeLists.txt107
-rw-r--r--libmariadb/win/packaging/WixUIBannerBmp.jpgbin0 -> 7401 bytes
-rw-r--r--libmariadb/win/packaging/WixUIDialogBmp.jpgbin0 -> 221242 bytes
-rw-r--r--libmariadb/win/packaging/license.rtf464
-rw-r--r--libmariadb/win/packaging/mariadb-connector-c.xml.in85
-rw-r--r--libmariadb/win/resource.rc.in34
484 files changed, 139342 insertions, 0 deletions
diff --git a/libmariadb/.gitmodules b/libmariadb/.gitmodules
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/libmariadb/.gitmodules
diff --git a/libmariadb/.travis.yml b/libmariadb/.travis.yml
new file mode 100644
index 00000000..d084bc17
--- /dev/null
+++ b/libmariadb/.travis.yml
@@ -0,0 +1,109 @@
+os: linux
+dist: focal
+language: c
+services: docker
+addons:
+ hosts:
+ - mariadb.example.com
+
+cache:
+ apt: true
+ ccache: true
+ directories:
+ - $HOME/docker
+
+before_install:
+ - git clone https://github.com/mariadb-corporation/connector-test-machine.git
+ # Load cached docker images
+ - if [[ -d $HOME/docker ]]; then ls $HOME/docker/*.tar.gz | xargs -I {file} sh -c "zcat {file} | docker load"; fi
+
+install:
+ - |-
+ if [ -z "$server_branch" ] ; then
+ case $TRAVIS_OS_NAME in
+ windows)
+ connector-test-machine/launch.bat -t "$srv" -v "$v" -d testc
+ ;;
+ linux)
+ source connector-test-machine/launch.sh -t "$srv" -v "$v" -d testc -l "$local" -n "$native"
+ ;;
+ esac
+ fi
+
+
+env: local=0
+
+stages:
+ - Minimal
+ - name: Enterprise
+ if: type = push AND fork = false
+ - Community
+
+jobs:
+ fast_finish: true
+ allow_failures:
+ - env: srv=maxscale
+ - env: srv=skysql
+ - env: srv=skysql-ha
+ - env: srv=xpand
+ - env: srv=mysql v=5.7
+ - env: srv=mysql v=8.0
+ include:
+ - stage: Minimal
+ env: srv=mariadb v=10.6 packet=8
+ name: "CS 10.6"
+ - env: srv=mariadb-es
+ name: "ES latest"
+ if: type = push AND fork = false
+ - env: server_branch=10.11
+ name: "10.11 Server unit testing"
+
+ - stage: Enterprise
+ env: srv=mariadb-es v=10.4
+ dist: bionic
+ name: "ES 10.4"
+ - env: srv=mariadb-es v=10.5
+ dist: bionic
+ name: "ES 10.5"
+ - env: srv=mariadb-es v=10.6
+ name: "ES 10.6"
+ - env: srv=mariadb-es-test v=23.08
+ name: "ES 23.08"
+ - env: srv=maxscale
+ name: "Maxscale"
+ - env: srv=xpand
+ name: "Xpand"
+
+ - stage: Community
+ env: srv=mariadb v=10.11
+ os: windows
+ language: shell
+ name: "Windows"
+ - env: server_branch=10.6
+ name: "10.6 Server unit testing"
+ - env: server_branch=11.3 TEST_OPTION=--ps-protocol
+ name: "11.3 Server unit testing with ps-protocol"
+ - env: srv=mariadb v=10.4 local=1
+ dist: bionic
+ name: "CS 10.4"
+ - env: srv=mariadb v=10.5 local=1
+ dist: bionic
+ name: "CS 10.5"
+ - env: srv=mariadb v=10.9 local=1
+ name: "CS 10.9"
+ - env: srv=mariadb v=10.10 local=1
+ name: "CS 10.10"
+ - env: srv=mariadb v=10.11 local=1
+ name: "CS 10.11"
+ - env: srv=mariadb v=10.11 local=1 TEST_OPTION=--ps-protocol
+ name: "CS 10.11 with ps-protocol"
+ - env: srv=mariadb v=11.0 local=1
+ name: "CS 11.0"
+ - env: srv=mariadb v=11.1 local=1
+ name: "CS 11.1"
+ - env: srv=mysql v=5.7 native=1
+ name: "MySQL 5.7"
+ - env: srv=mysql v=8.0 native=1
+ name: "MySQL 8.0"
+
+script: ./travis.sh
diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt
new file mode 100644
index 00000000..206e4e03
--- /dev/null
+++ b/libmariadb/CMakeLists.txt
@@ -0,0 +1,554 @@
+# CMakeLists.txt
+
+# This is the LGPL libmariadb project.
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR)
+INCLUDE(CheckFunctionExists)
+IF(COMMAND CMAKE_POLICY)
+ SET(NEW_POLICIES CMP0003 CMP0022 CMP0023 CMP0057 CMP0077 CMP0069 CMP0075)
+ FOREACH(TYPE OLD NEW)
+ FOREACH(P ${${TYPE}_POLICIES})
+ IF(POLICY ${P})
+ CMAKE_POLICY(SET ${P} ${TYPE})
+ ENDIF()
+ ENDFOREACH()
+ ENDFOREACH()
+ENDIF()
+
+
+PROJECT(mariadb-connector-c C)
+
+# Is C/C built as subproject?
+get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)
+
+# do not inherit include directories from the parent project
+SET_PROPERTY(DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
+FOREACH(V WITH_MYSQLCOMPAT WITH_MSI WITH_SIGNCODE WITH_RTC WITH_UNIT_TESTS
+ WITH_DYNCOL WITH_EXTERNAL_ZLIB WITH_CURL WITH_SQLITE WITH_SSL WITH_ICONV
+ DEFAULT_CHARSET INSTALL_LAYOUT WITH_TEST_SRCPKG)
+ SET(${V} ${${OPT}${V}})
+ENDFOREACH()
+
+# SET(PACKAGE_STATUS_SUFFIX "rc1")
+
+SET(CC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+SET(CC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+SET(CPACK_PACKAGE_VERSION_MAJOR 3)
+SET(CPACK_PACKAGE_VERSION_MINOR 3)
+SET(CPACK_PACKAGE_VERSION_PATCH 8)
+SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+MATH(EXPR MARIADB_PACKAGE_VERSION_ID "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 +
+ ${CPACK_PACKAGE_VERSION_MINOR} * 100 +
+ ${CPACK_PACKAGE_VERSION_PATCH}")
+
+MACRO(ADD_OPTION _name _text _default)
+ IF(NOT DEFINED ${_name})
+ OPTION(${OPT}${_name} "${_text}" "${_default}")
+ ELSE()
+ OPTION(${OPT}${_name} "${_text}" "${${_name}}")
+ ENDIF()
+ENDMACRO()
+
+### Options ###
+IF(NOT WIN32)
+ ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" OFF)
+ELSE()
+ ADD_OPTION(WITH_MSI "Build MSI installation package" OFF)
+ ADD_OPTION(WITH_SIGNCODE "digitally sign files" OFF)
+ ADD_OPTION(WITH_RTC "enables run time checks for debug builds" OFF)
+ ADD_OPTION(WITH_ICONV "enables character set conversion" OFF)
+ENDIF()
+
+ADD_OPTION(WITH_UNIT_TESTS "build test suite" ON)
+ADD_OPTION(WITH_DYNCOL "Enables support of dynamic columns" ON)
+ADD_OPTION(WITH_EXTERNAL_ZLIB "Enables use of external zlib" OFF)
+ADD_OPTION(WITH_CURL "Enables use of curl" ON)
+ADD_OPTION(WITH_SSL "Enables use of TLS/SSL library" ON)
+###############
+
+INCLUDE(${CC_SOURCE_DIR}/cmake/misc.cmake)
+INCLUDE(FindCURL)
+
+IF(WITH_SIGNCODE)
+ IF(WIN32 AND NOT SIGN_OPTIONS)
+ SET(SIGN_OPTIONS /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a)
+ ELSE()
+ SEPARATE_ARGUMENTS(SIGN_OPTIONS)
+ ENDIF()
+ MARK_AS_ADVANCED(SIGN_OPTIONS)
+ENDIF()
+
+SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2017 MariaDB Corporation Ab")
+
+IF(WITH_RTC)
+ SET(RTC_OPTIONS "/RTC1 /RTCc")
+ENDIF()
+
+INCLUDE(${CC_SOURCE_DIR}/cmake/plugins.cmake)
+
+
+IF(WIN32)
+ FILE(REMOVE ${CC_BINARY_DIR}/win/packaging/plugin.conf)
+ INCLUDE(${CC_SOURCE_DIR}/cmake/version_info.cmake)
+ENDIF()
+
+IF(NOT IS_SUBPROJECT)
+IF(MSVC)
+ # Speedup system tests
+ INCLUDE(${CC_SOURCE_DIR}/cmake/WindowsCache.cmake)
+ ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN -DNOGDI)
+ IF (MSVC)
+ SET(CONFIG_TYPES "DEBUG" "RELEASE" "RELWITHDEBINFO")
+ FOREACH(BUILD_TYPE ${CONFIG_TYPES})
+ FOREACH(COMPILER CXX C)
+ SET(COMPILER_FLAGS "${CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE}}")
+ IF (NOT COMPILER_FLAGS STREQUAL "")
+ IF(NOT WITH_ASAN)
+ STRING(REPLACE "/MD" "/MT" COMPILER_FLAGS ${COMPILER_FLAGS})
+ IF (BUILD_TYPE STREQUAL "DEBUG")
+ SET(COMPILER_FLAGS "${COMPILER_FLAGS} ${RTC_OPTIONS}")
+ ENDIF()
+ ENDIF()
+ STRING(REPLACE "/Zi" "/Z7" COMPILER_FLAGS ${COMPILER_FLAGS})
+ MESSAGE (STATUS "CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE}= ${COMPILER_FLAGS}")
+ SET(CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE} ${COMPILER_FLAGS})
+ ENDIF()
+ ENDFOREACH()
+ ENDFOREACH()
+ ENDIF()
+ENDIF()
+ELSE()
+ # MDEV-16383
+ IF(WITH_EMBEDDED_SERVER)
+ ADD_DEFINITIONS(-DHAVE_EMBEDDED)
+ ENDIF()
+ENDIF(NOT IS_SUBPROJECT)
+
+# Disable dbug information for release builds
+SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DDBUG_OFF")
+SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF")
+SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
+SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
+
+IF(CMAKE_COMPILER_IS_GNUCC)
+ INCLUDE(CheckCCompilerFlag)
+ SET(GCC_FLAGS -Wunused -Wlogical-op -Wno-uninitialized -Wall -Wextra -Wformat-security -Wno-init-self -Wwrite-strings -Wshift-count-overflow -Wdeclaration-after-statement -Wno-undef -Wno-unknown-pragmas -Wno-stringop-truncation)
+ FOREACH(GCC_FLAG ${GCC_FLAGS})
+ CHECK_C_COMPILER_FLAG("${GCC_FLAG}" HAS_${GCC_FLAG}_FLAG)
+ IF(${HAS_${GCC_FLAG}_FLAG})
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_FLAG}")
+ ENDIF()
+ ENDFOREACH()
+ENDIF()
+
+# If the build type isn't specified, set to Relwithdebinfo as default.
+IF(NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE "RelWithDebInfo")
+ENDIF()
+
+# various defines for generating include/mysql_version.h
+INCLUDE(FindGit)
+IF(GIT_EXECUTABLE AND EXISTS ${CC_SOURCE_DIR}/.git)
+ EXECUTE_PROCESS(
+ COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
+ WORKING_DIRECTORY ${CC_SOURCE_DIR}
+ OUTPUT_VARIABLE OUT RESULT_VARIABLE RES)
+ IF(RES EQUAL 0)
+ STRING(REGEX REPLACE "\n$" "" CC_SOURCE_REVISION "${OUT}")
+ ENDIF()
+ENDIF()
+SET(PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd !
+
+# if C/C is build as subproject inside MariaDB server tree we will
+# use the version defined by server
+IF(MAJOR_VERSION)
+ SET(MARIADB_CLIENT_VERSION_MAJOR ${MAJOR_VERSION})
+ SET(MARIADB_CLIENT_VERSION_MINOR ${MINOR_VERSION})
+ SET(MARIADB_CLIENT_VERSION_PATCH ${PATCH_VERSION})
+ SET(MARIADB_CLIENT_VERSION_EXTRA ${EXTRA_VERSION})
+ELSE()
+ SET(MARIADB_CLIENT_VERSION_MAJOR "10")
+ SET(MARIADB_CLIENT_VERSION_MINOR "8")
+ SET(MARIADB_CLIENT_VERSION_PATCH "8")
+ SET(MARIADB_CLIENT_VERSION_EXTRA "")
+ENDIF()
+
+IF(WIN32)
+ # version in resource files need to be consistent
+ # with server's , so that MSI minor upgrade work.
+ # if this is not a subproject build, C/C version is used.
+ FOREACH(v MAJOR MINOR PATCH TINY)
+ IF(DEFINED ${v}_VERSION)
+ SET(${v}_FILE_VERSION "${${v}_VERSION}")
+ ELSEIF(DEFINED CPACK_PACKAGE_VERSION_${v})
+ SET(${v}_FILE_VERSION "${CPACK_PACKAGE_VERSION_${v}}")
+ ELSE()
+ SET(${v}_FILE_VERSION "0")
+ ENDIF()
+ IF(NOT ${v}_FILE_VERSION MATCHES "^[0-9]+$")
+ MESSAGE(FATAL_ERROR
+ "${v}_FILE_VERSION is not numeric - '${${v}_FILE_VERSION}'")
+ ENDIF()
+ ENDFOREACH()
+ENDIF()
+
+SET(MARIADB_CLIENT_VERSION "${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}.${MARIADB_CLIENT_VERSION_PATCH}${MARIADB_CLIENT_VERSION_EXTRA}")
+SET(MARIADB_BASE_VERSION "mariadb-${MARIADB_CLIENT_VERSION_MAJOR}.${MARIADB_CLIENT_VERSION_MINOR}")
+MATH(EXPR MARIADB_VERSION_ID "${MARIADB_CLIENT_VERSION_MAJOR} * 10000 +
+ ${MARIADB_CLIENT_VERSION_MINOR} * 100 +
+ ${MARIADB_CLIENT_VERSION_PATCH}")
+
+IF (NOT MARIADB_PORT)
+ SET(MARIADB_PORT 3306)
+ENDIF ()
+IF(NOT MARIADB_UNIX_ADDR)
+ SET(MARIADB_UNIX_ADDR "/tmp/mysql.sock")
+ENDIF()
+
+INCLUDE("${CC_SOURCE_DIR}/cmake/install.cmake")
+IF(NOT PLUGINDIR)
+ SET(PLUGINDIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_PLUGINDIR}")
+ENDIF()
+
+# todo: we don't character sets in share - all is compiled in
+SET(SHAREDIR "share")
+SET(DEFAULT_CHARSET_HOME "${CMAKE_INSTALL_PREFIX}")
+
+INCLUDE(${CC_SOURCE_DIR}/cmake/SearchLibrary.cmake)
+
+# Compression plugins: ZSTD, ZLIB
+
+INCLUDE(${CC_SOURCE_DIR}/cmake/FindZStd.cmake)
+
+IF(WITH_EXTERNAL_ZLIB)
+ IF(NOT ZLIB_FOUND)
+ FIND_PACKAGE(ZLIB REQUIRED)
+ ENDIF()
+ SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${ZLIB_LIBRARIES})
+ELSE()
+ SET(ZLIB_INCLUDE_DIR "${CC_SOURCE_DIR}/external/zlib")
+ ADD_SUBDIRECTORY("${CC_SOURCE_DIR}/external/zlib")
+ENDIF()
+INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
+
+IF(NOT WIN32)
+ INCLUDE(TestBigEndian)
+ TEST_BIG_ENDIAN(HAVE_BIGENDIAN)
+ENDIF()
+
+# check for various include files
+INCLUDE(${CC_SOURCE_DIR}/cmake/check_include_files.cmake)
+# check for various functions
+INCLUDE(${CC_SOURCE_DIR}/cmake/check_functions.cmake)
+# check for various types
+INCLUDE(${CC_SOURCE_DIR}/cmake/check_types.cmake)
+
+IF(UNIX)
+ SEARCH_LIBRARY(LIBM floor m)
+ SEARCH_LIBRARY(LIBPTHREAD pthread_getspecific "pthread;pthreads")
+ SEARCH_LIBRARY(LIBNSL gethostbyname_r "nsl_r;nsl")
+ SEARCH_LIBRARY(LIBSOCKET setsockopt socket)
+ FIND_PACKAGE(Threads)
+ SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LIBNSL} ${LIBBIND} ${LIBICONV} ${ZLIB_LIBRARY}
+ ${LIBSOCKET} ${CMAKE_DL_LIBS} ${LIBM} ${LIBPTHREAD})
+ SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBNSL} ${LIBBIND} ${LIBICONV}
+ ${LIBSOCKET} ${CMAKE_DL_LIBS} ${LIBM} ${LIBPTHREAD})
+ #remove possible dups from required libraries
+ LIST(LENGTH CMAKE_REQUIRED_LIBRARIES rllength)
+ IF(${rllength} GREATER 0)
+ LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES)
+ ENDIF()
+ENDIF()
+
+
+IF(CMAKE_HAVE_PTHREAD_H)
+ SET(CMAKE_REQUIRED_INCLUDES pthread.h)
+ENDIF()
+
+IF(DBUG_OFF)
+ ADD_DEFINITIONS(-DDBUG_OFF=1)
+ENDIF()
+
+ADD_DEFINITIONS(-DMARIADB_SYSTEM_TYPE="${CMAKE_SYSTEM_NAME}")
+ADD_DEFINITIONS(-DMARIADB_MACHINE_TYPE="${CMAKE_SYSTEM_PROCESSOR}")
+
+IF(WIN32)
+ SET(HAVE_THREADS 1)
+ ADD_DEFINITIONS(-DHAVE_DLOPEN)
+ ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
+ELSEIF()
+ SET(HAVE_THREADS ${CMAKE_USE_PTHREADS})
+ENDIF()
+
+IF(NOT DEFAULT_CHARSET)
+ SET(DEFAULT_CHARSET "utf8mb4")
+ENDIF()
+
+
+# convert SSL options to uppercase
+IF(WITH_SSL)
+ STRING(TOUPPER ${WITH_SSL} WITH_SSL)
+ENDIF()
+IF(WITH_SSL STREQUAL "ON")
+ IF(WIN32)
+ SET(WITH_SSL "SCHANNEL")
+ ELSE()
+ SET(WITH_SSL "OPENSSL")
+ ENDIF()
+ENDIF()
+
+IF(NOT WITH_SSL STREQUAL "OFF")
+ IF(WITH_SSL STREQUAL "OPENSSL")
+ IF (NOT OPENSSL_FOUND)
+ FIND_PACKAGE(OpenSSL)
+ ENDIF()
+ IF(OPENSSL_FOUND)
+ ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_TLS)
+ SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/openssl.c")
+ SET(SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
+ IF(WIN32)
+ CHECK_INCLUDE_FILES (${OPENSSL_INCLUDE_DIR}/openssl/applink.c HAVE_OPENSSL_APPLINK_C)
+ ENDIF()
+ INCLUDE_DIRECTORIES(BEFORE ${OPENSSL_INCLUDE_DIR})
+
+
+ TRY_RUN(LIBRESSL_RESULT HAVE_LIBRESSL
+ ${CMAKE_BINARY_DIR}
+ ${CC_SOURCE_DIR}/cmake/libressl_version.c
+ COMPILE_DEFINITIONS "-I${OPENSSL_INCLUDE_DIR}"
+ RUN_OUTPUT_VARIABLE LIBRESSL_VERSION)
+ IF(HAVE_LIBRESSL)
+ ADD_DEFINITIONS(-DHAVE_LIBRESSL)
+ SET(TLS_LIBRARY_VERSION ${LIBRESSL_VERSION})
+ ELSE()
+ SET(TLS_LIBRARY_VERSION "OpenSSL ${OPENSSL_VERSION}")
+ ENDIF()
+ ELSE()
+ MESSAGE1(TLS_LIBRARY_VERSION "OpenSSL/LibreSSL not found")
+ ENDIF()
+ ENDIF()
+ IF(WITH_SSL STREQUAL "GNUTLS")
+ FIND_PACKAGE(GnuTLS "3.3.24" REQUIRED)
+ IF(GNUTLS_FOUND)
+ ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_TLS)
+ SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/gnutls.c")
+ SET(SSL_LIBRARIES ${GNUTLS_LIBRARY})
+ SET(TLS_LIBRARY_VERSION "GnuTLS ${GNUTLS_VERSION_STRING}")
+ INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR})
+ ELSE()
+ MESSAGE(FATAL_ERROR "GnuTLS not found")
+ ENDIF()
+ ENDIF()
+ IF(WIN32)
+ IF(WITH_SSL STREQUAL "SCHANNEL")
+ ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_TLS)
+ SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/schannel.c"
+ "${CC_SOURCE_DIR}/libmariadb/secure/ma_schannel.c"
+ "${CC_SOURCE_DIR}/libmariadb/secure/schannel_certs.c")
+ INCLUDE_DIRECTORIES("${CC_SOURCE_DIR}/plugins/pvio/")
+ SET(SSL_LIBRARIES secur32)
+ SET(TLS_LIBRARY_VERSION "Schannel ${CMAKE_SYSTEM_VERSION}")
+ ENDIF()
+ ENDIF()
+ MESSAGE1(TLS_LIBRARY_VERSION "TLS library/version: ${TLS_LIBRARY_VERSION}")
+
+ MARK_AS_ADVANCED(SSL_SOURCES)
+ENDIF()
+
+SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)")
+MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE)
+IF (ENABLED_LOCAL_INFILE MATCHES "^(0|FALSE)$")
+ SET(ENABLED_LOCAL_INFILE OFF)
+ELSEIF(ENABLED_LOCAL_INFILE MATCHES "^(1|TRUE)$")
+ SET(ENABLED_LOCAL_INFILE ON)
+ELSEIF (NOT ENABLED_LOCAL_INFILE MATCHES "^(ON|OFF|AUTO)$")
+ MESSAGE(FATAL_ERROR "ENABLED_LOCAL_INFILE must be one of OFF, ON, AUTO")
+ENDIF()
+
+IF(WITH_ICONV)
+ IF(NOT WIN32)
+ INCLUDE(${CC_SOURCE_DIR}/cmake/FindIconv.cmake)
+ ENDIF()
+ENDIF()
+
+CONFIGURE_FILE(${CC_SOURCE_DIR}/include/ma_config.h.in
+ ${CC_BINARY_DIR}/include/ma_config.h)
+CONFIGURE_FILE(${CC_SOURCE_DIR}/include/ma_config.h.in
+ ${CC_BINARY_DIR}/include/config.h)
+CONFIGURE_FILE(${CC_SOURCE_DIR}/include/mariadb_version.h.in
+ ${CC_BINARY_DIR}/include/mariadb_version.h)
+
+INCLUDE_DIRECTORIES(${CC_BINARY_DIR}/include)
+
+IF(WIN32)
+ SET(SYSTEM_LIBS ws2_32 advapi32 kernel32 shlwapi crypt32 ${LIBZ})
+ELSE()
+ SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBPTHREAD} ${CMAKE_DL_LIBS} ${LIBM})
+ IF(ICONV_EXTERNAL)
+ SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${ICONV_LIBRARIES})
+ ENDIF()
+ENDIF()
+IF(WITH_SSL)
+ SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES})
+ENDIF()
+MESSAGE1(SYSTEM_LIBS "SYSTEM_LIBS ${SYSTEM_LIBS}")
+MARK_AS_ADVANCED(SYSTEM_LIBS)
+
+IF(NOT IS_SUBPROJECT)
+IF ((NOT WIN32) AND (CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "GNU"))
+ SET(WARNING_AS_ERROR "-Werror")
+ELSEIF(CMAKE_C_COMPILER_ID MATCHES "MSVC")
+ SET(WARNING_AS_ERROR "/WX")
+ENDIF()
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_AS_ERROR}")
+ENDIF()
+
+
+IF(NOT REMOTEIO_PLUGIN_TYPE MATCHES "OFF")
+ IF(CURL_FOUND)
+ INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS})
+ IF(REMOTEIO_PLUGIN_TYPE MATCHES "STATIC")
+ SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${CURL_LIBRARIES})
+ ENDIF()
+ ADD_DEFINITIONS("-DHAVE_REMOTEIO=1")
+ ENDIF()
+ENDIF()
+IF(NOT WIN32)
+ IF(NOT AUTH_GSSAPI_PLUGIN_TYPE MATCHES "OFF")
+ INCLUDE(${CC_SOURCE_DIR}/cmake/FindGSSAPI.cmake)
+ IF(GSSAPI_FOUND)
+ INCLUDE_DIRECTORIES(${GSSAPI_INCS})
+ IF(AUTH_GSSAPI_PLUGIN_TYPE MATCHES "STATIC")
+ SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${GSSAPI_LIBS})
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ENDIF()
+INCLUDE(${CC_SOURCE_DIR}/plugins/CMakeLists.txt)
+ADD_SUBDIRECTORY(include)
+ADD_SUBDIRECTORY(libmariadb)
+IF((NOT WIN32) OR CYGWIN)
+ ADD_SUBDIRECTORY(mariadb_config)
+ENDIF()
+
+IF(IS_DIRECTORY ${CC_SOURCE_DIR}/unittest)
+ IF(WITH_UNIT_TESTS)
+ ADD_SUBDIRECTORY(unittest/mytap)
+ ADD_SUBDIRECTORY(unittest/libmariadb)
+ ENDIF()
+ENDIF()
+
+IF(CLIENT_DOCS)
+ INSTALL(DIRECTORY ${CLIENT_DOCS}
+ DESTINATION ${DOCS_INSTALL_DIR_${INSTALL_LAYOUT}}
+ COMPONENT SharedLibraries)
+ENDIF()
+
+IF(UNIX)
+ ADD_SUBDIRECTORY(man)
+ENDIF()
+
+IF(WIN32 AND WITH_MSI AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
+ ADD_SUBDIRECTORY(win/packaging)
+ENDIF()
+MESSAGE1(SYSTEM_PROCESSOR "SYSTEM processor: ${CMAKE_SYSTEM_PROCESSOR}")
+SET(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab")
+SET(CPACK_PACKAGE_DESCRIPTION "MariaDB Connector/C. A library for connecting to MariaDB and MySQL servers")
+SET(CPACK_PACKAGE_NAME "mariadb_connector_c")
+STRING(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
+SET(CPACK_RESOURCE_FILE_LICENSE "${CC_SOURCE_DIR}/COPYING.LIB")
+SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CC_SOURCE_DIR}/README")
+INCLUDE(cmake/ConnectorName.cmake)
+IF(NOT PACKAGE_STATUS_SUFFIX)
+ SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-src")
+ IF(PACKAGE_PLATFORM_SUFFIX)
+ SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_PLATFORM_SUFFIX}")
+ ELSE()
+ SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
+ ENDIF()
+ELSE()
+ SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-src")
+ IF(PACKAGE_PLATFORM_SUFFIX)
+ SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${PACKAGE_PLATFORM_SUFFIX}")
+ ELSE()
+ SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-c-${CPACK_PACKAGE_VERSION}-${PACKAGE_STATUS_SUFFIX}-${system_name}-${CMAKE_SYSTEM_PROCESSOR}")
+ ENDIF()
+ENDIF()
+# Build source packages
+IF(GIT_BUILD_SRCPKG)
+ # get branch name
+ EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} show-branch OUTPUT_VARIABLE git_branch)
+ STRING(REGEX MATCH "\\[([^]]+)\\]" git_branch ${git_branch})
+ STRING(REGEX REPLACE "\\[|\\]" "" GIT_BRANCH ${git_branch})
+ MESSAGE1(GIT_BRANCH "${GIT_BRANCH}")
+ IF(WIN32)
+ EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} archive ${GIT_BRANCH} --format=zip --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip)
+ ELSE()
+ EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} archive ${GIT_BRANCH} --format=zip --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip)
+ EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} archive ${GIT_BRANCH} --format=tar --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar)
+ EXECUTE_PROCESS(COMMAND gzip -9 -f ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar)
+ ENDIF()
+ENDIF()
+
+SET(CPACK_SOURCE_IGNORE_FILES
+\\\\.git/
+\\\\.gitignore
+\\\\.gitattributes
+CMakeCache\\\\.txt
+cmake_dist\\\\.cmake
+CPackConfig\\\\.cmake
+mariadb_config\\\\.c$
+\\\\.build/
+html/
+unittest
+/cmake_install.cmake
+/CTestTestfile.cmake
+/CPackSourceConfig.cmake
+/CMakeFiles/
+/version_resources/
+/_CPack_Packages/
+\\\\.gz$
+\\\\.zip$
+mariadb_config/mariadb_config$
+/CMakeFiles/
+/version_resources/
+/_CPack_Packages/
+Makefile$
+include/my_config\\\\.h$
+)
+
+IF(WITH_TEST_SRCPKG)
+ SET(PACKAGE_FILE ${CC_SOURCE_DIR}/package.name)
+ FILE(REMOVE ${PACKAGE_FILE})
+ FILE(WRITE ${PACKAGE_FILE} ${CPACK_SOURCE_PACKAGE_FILE_NAME})
+ENDIF()
+
+IF(WIN32)
+ SET(CPACK_GENERATOR "ZIP")
+ SET(CPACK_SOURCE_GENERATOR "ZIP")
+ELSE()
+ SET(CPACK_GENERATOR "TGZ")
+ SET(CPACK_SOURCE_GENERATOR "TGZ")
+ENDIF()
+INCLUDE(CPack)
+
+IF(WITH_EXTERNAL_ZLIB)
+ SET(zlib_status ${WITH_EXTERNAL_ZLIB})
+ELSE()
+ SET(zlib_status "yes (using bundled zlib)")
+ENDIF()
+
+MESSAGE1(STATUS "MariaDB Connector/c configuration:
+-- Static PLUGINS ${PLUGINS_STATIC}
+-- Dynamic PLUGINS ${PLUGINS_DYNAMIC}
+-- CPack generation: ${CPACK_GENERATOR}
+-- SSL support: ${WITH_SSL} Libs: ${SSL_LIBRARIES}
+-- Zlib support: ${zlib_status}
+-- ZStd support: ${ZSTD_FOUND}
+-- Installation layout: ${INSTALL_LAYOUT}
+-- Include files will be installed in ${INSTALL_INCLUDEDIR}
+-- Libraries will be installed in ${INSTALL_LIBDIR}
+-- Binaries will be installed in ${INSTALL_BINDIR}
+-- Documentation included from ${CLIENT_DOCS}
+-- Required: ${CMAKE_REQUIRED_LIBRARIES}")
diff --git a/libmariadb/COPYING.LIB b/libmariadb/COPYING.LIB
new file mode 100644
index 00000000..4362b491
--- /dev/null
+++ b/libmariadb/COPYING.LIB
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/libmariadb/README b/libmariadb/README
new file mode 100644
index 00000000..1878ff6e
--- /dev/null
+++ b/libmariadb/README
@@ -0,0 +1,15 @@
+This is LGPL MariaDB client library that can be used to connect to a
+MariaDB or MySQL database server.
+
+This code is based on the LGPL libmysql client library from MySQL 3.23
+and PHP's mysqlnd extension.
+
+This product includes PHP software, freely available from
+<http://www.php.net/software/>
+
+If you want to be part of this development effort, you can discuss this at
+maria-developers@lists.launchpad.org.
+
+To report a bug you'll need to signup for an account at https://jira.mariadb.org
+
+The MariaDB team
diff --git a/libmariadb/appveyor-download.bat b/libmariadb/appveyor-download.bat
new file mode 100644
index 00000000..5cc2dbbb
--- /dev/null
+++ b/libmariadb/appveyor-download.bat
@@ -0,0 +1,16 @@
+@echo off
+set archive=http://ftp.hosteurope.de/mirror/archive.mariadb.org//mariadb-%DB%/winx64-packages/mariadb-%DB%-winx64.msi
+set last=http://mirror.i3d.net/pub/mariadb//mariadb-%DB%/winx64-packages/mariadb-%DB%-winx64.msi
+
+curl -fLsS -o server.msi %archive%
+
+if %ERRORLEVEL% == 0 goto end
+
+curl -fLsS -o server.msi %last%
+if %ERRORLEVEL% == 0 goto end
+
+echo Failure Reason Given is %errorlevel%
+exit /b %errorlevel%
+
+:end
+echo "File found".
diff --git a/libmariadb/appveyor.yml b/libmariadb/appveyor.yml
new file mode 100644
index 00000000..9088b993
--- /dev/null
+++ b/libmariadb/appveyor.yml
@@ -0,0 +1,41 @@
+version: 3.0.8;{build}
+branches:
+ only:
+ - 3.1
+environment:
+ matrix:
+ - DB: '10.2.38'
+ APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
+ - DB: '10.3.29'
+ APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
+ - DB: '10.4.19'
+ APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
+ - DB: '10.5.10'
+ APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ CMAKE_PARAM: 'Visual Studio 15 2017 Win64'
+
+
+configuration: RelWithDebInfo
+clone_folder: c:\projects\mariadb-connector-c
+before_build:
+ - cmd: appveyor-download.bat
+ - cmd: msiexec /i server.msi INSTALLDIR=c:\projects\server SERVICENAME=mariadb ALLOWREMOTEROOTACCESS=true /qn
+ - cmd: "\"c:\\projects\\server\\bin\\mysql.exe\" -e \"create database testc\" --user=root"
+ - cmd: set MARIADB_CC_TEST=1
+ - cmd: set MYSQL_TEST_USER=root
+ - cmd: set MYSQL_TEST_HOST=127.0.0.1
+ - cmd: set MYSQL_TEST_PASSWD=
+ - cmd: set MYSQL_TEST_PORT=3306
+ - cmd: set MYSQL_TEST_DB=testc
+ - cmd: cmake -G "%CMAKE_PARAM%" -DCMAKE_BUILD_TYPE=RelWithDebInfo
+build:
+ project: mariadb-connector-c.sln
+ parallel: true
+ verbosity: minimal
+test_script:
+ - cmd: cd c:\projects\mariadb-connector-c\unittest\libmariadb
+ - cmd: set MARIADB_PLUGIN_DIR=cd c:\projects\mariadb-connector-c\plugins\lib\RelWithDebInfo
+ - cmd: ctest -V
diff --git a/libmariadb/benchmark/README.md b/libmariadb/benchmark/README.md
new file mode 100644
index 00000000..a8444b6b
--- /dev/null
+++ b/libmariadb/benchmark/README.md
@@ -0,0 +1,53 @@
+# Benchmark MariaDB Connector/C
+
+This permits to benchmark MariaDB C connector, along with MySQL connector
+
+## Installation
+To install google benchmark, mysql connector and build current connector :
+```script
+ sudo benchmark/build.sh
+ cd benchmark
+ sudo ./installation.sh
+```
+
+## Basic run
+
+This will runs the benchmark with 50 repetition to ensure stability then display results
+```script
+sudo ./launch.sh
+```
+
+## detailed benchmark
+
+first ensure running cpu to maximum speed:
+```script
+sudo cpupower frequency-set --governor performance || true
+```
+
+default is benchmarking on one thread. adding benchmark on multiple thread can be done setting MAX_THREAD in main-benchmark.cc. Setting it to 256, benchmark will run on 1 to 256 threads.
+
+Set server default environment with the following variables :
+* TEST_DB_PORT (default 3306)
+* TEST_DB_DATABASE (default "bench")
+* TEST_DB_USER (default "root")
+* TEST_DB_HOST (default "localhost")
+* TEST_DB_PASSWORD
+*
+running with MariaDB driver:
+```script
+g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -I/usr/local/include/mariadb -I/usr/local/include/mariadb/mysql -L/usr/local/lib/mariadb/ -lmariadb -lbenchmark -lpthread -o main-benchmark
+./main-benchmark --benchmark_repetitions=10 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mariadb.json
+```
+
+running with MySQL driver:
+```script
+g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread -DBENCHMARK_MYSQL -lmysqlclient -o main-benchmark
+./main-benchmark --benchmark_repetitions=10 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mysql.json
+```
+
+in order to compare results:
+
+```script
+pip3 install -r benchmark/requirements.txt
+benchmark/tools/compare.py -a --no-utest benchmarksfiltered ./mysql.json MySQL ./mariadb.json MariaDB
+```
diff --git a/libmariadb/benchmark/build.sh b/libmariadb/benchmark/build.sh
new file mode 100755
index 00000000..f9a520fb
--- /dev/null
+++ b/libmariadb/benchmark/build.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -ex
+
+mkdir bld
+cd bld
+sudo cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
+sudo cmake --build . --config Release --target install
+sudo apt-get -f -y install linux-tools-common linux-gcp linux-tools-$(uname -r)
+
+echo $LD_LIBRARY_PATH
+export LD_LIBRARY_PATH=/usr/local/lib
+
+sudo install /usr/local/lib/mariadb/libmariadb.so /usr/lib
+sudo install -d /usr/lib/mariadb
+sudo install -d /usr/lib/mariadb/plugin
+
+
+sudo apt install libmysqlclient-dev
diff --git a/libmariadb/benchmark/installation.sh b/libmariadb/benchmark/installation.sh
new file mode 100755
index 00000000..1b54e7d8
--- /dev/null
+++ b/libmariadb/benchmark/installation.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -ex
+
+# Check out the library.
+git clone https://github.com/google/benchmark.git
+# Go to the library root directory
+cd benchmark
+# Make a build directory to place the build output.
+cmake -E make_directory "build"
+# Generate build system files with cmake, and download any dependencies.
+cmake -E chdir "build" cmake -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on -DCMAKE_BUILD_TYPE=Release ../
+# or, starting with CMake 3.13, use a simpler form:
+# cmake -DCMAKE_BUILD_TYPE=Release -S . -B "build"
+# Build the library.
+cmake --build "build" --config Release
+
diff --git a/libmariadb/benchmark/launch.sh b/libmariadb/benchmark/launch.sh
new file mode 100755
index 00000000..15e98c3e
--- /dev/null
+++ b/libmariadb/benchmark/launch.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -ex
+
+sudo cpupower frequency-set --governor performance || true
+
+
+g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -I/usr/local/include/mariadb -I/usr/local/include/mariadb/mysql -L/usr/local/lib/mariadb/ -lmariadb -lbenchmark -lpthread -o main-benchmark
+./main-benchmark --benchmark_repetitions=30 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mariadb.json
+
+
+g++ main-benchmark.cc -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread -DBENCHMARK_MYSQL -lmysqlclient -o main-benchmark
+./main-benchmark --benchmark_repetitions=30 --benchmark_time_unit=us --benchmark_min_warmup_time=10 --benchmark_counters_tabular=true --benchmark_format=json --benchmark_out=mysql.json
+
+
+pip3 install -r benchmark/requirements.txt
+benchmark/tools/compare.py -a --no-utest benchmarksfiltered ./mysql.json MySQL ./mariadb.json MariaDB
diff --git a/libmariadb/benchmark/main-benchmark.cc b/libmariadb/benchmark/main-benchmark.cc
new file mode 100644
index 00000000..3b99ef7f
--- /dev/null
+++ b/libmariadb/benchmark/main-benchmark.cc
@@ -0,0 +1,556 @@
+#include <benchmark/benchmark.h>
+#include <iostream>
+#include <string>
+#include <cstring>
+#include <stdlib.h>
+#include <stdio.h>
+
+const int MAX_THREAD = 1;
+#define OPERATION_PER_SECOND_LABEL "nb operations per second"
+
+std::string GetEnvironmentVariableOrDefault(const std::string& variable_name,
+ const std::string& default_value)
+{
+ const char* value = getenv(variable_name.c_str());
+ return value ? value : default_value;
+}
+
+std::string DB_PORT = GetEnvironmentVariableOrDefault("TEST_DB_PORT", "3306");
+std::string DB_DATABASE = GetEnvironmentVariableOrDefault("TEST_DB_DATABASE", "bench");
+std::string DB_USER = GetEnvironmentVariableOrDefault("TEST_DB_USER", "root");
+std::string DB_HOST = GetEnvironmentVariableOrDefault("TEST_DB_HOST", "127.0.0.1");
+std::string DB_PASSWORD = GetEnvironmentVariableOrDefault("TEST_DB_PASSWORD", "");
+
+#define check_conn_rc(rc, mysql) \
+do {\
+ if (rc)\
+ {\
+ fprintf(stdout,"Error (%d): %s (%d) in %s line %d", rc, mysql_error(mysql), \
+ mysql_errno(mysql), __FILE__, __LINE__);\
+ mysql_close(conn);\
+ exit(1);\
+ }\
+} while(0)
+
+
+#define check_stmt_rc(rc, stmt, mysql) \
+do {\
+ if (rc)\
+ {\
+ fprintf(stdout,"Error (%d): %d (%s) in %s line %d", rc, mysql_stmt_errno(stmt), \
+ mysql_stmt_error(stmt), __FILE__, __LINE__);\
+ mysql_close(conn);\
+ exit(1);\
+ }\
+} while(0)
+
+#ifndef BENCHMARK_MYSQL
+#include <mysql.h>
+const std::string TYPE = "MariaDB";
+
+MYSQL* connect(std::string options) {
+ MYSQL *con = mysql_init(NULL);
+ if (!(con = mysql_init(0))) {
+ fprintf(stderr, "unable to initialize connection struct\n");
+ exit(1);
+ }
+
+ enum mysql_protocol_type prot_type= MYSQL_PROTOCOL_TCP;
+ mysql_optionsv(con, MYSQL_OPT_PROTOCOL, (void *)&prot_type);
+
+ if (mysql_real_connect(con, DB_HOST.c_str(), DB_USER.c_str(), DB_PASSWORD.c_str(),
+ DB_DATABASE.c_str(), atoi(DB_PORT.c_str()), NULL, 0) == NULL) {
+ fprintf(stderr, "%s\n", mysql_error(con));
+ mysql_close(con);
+ exit(1);
+ }
+ return con;
+}
+#endif
+
+#ifdef BENCHMARK_MYSQL
+ #include <mysql/mysql.h>
+const std::string TYPE = "MySQL";
+
+MYSQL* connect(std::string options) {
+ MYSQL *con = mysql_init(NULL);
+
+ if (con == NULL) {
+ fprintf(stderr, "%s\n", mysql_error(con));
+ exit(1);
+ }
+
+ enum mysql_protocol_type prot_type= MYSQL_PROTOCOL_TCP;
+ mysql_options(con, MYSQL_OPT_PROTOCOL, (void *)&prot_type);
+
+ if (mysql_real_connect(con, DB_HOST.c_str(), DB_USER.c_str(), DB_PASSWORD.c_str(),
+ DB_DATABASE.c_str(), atoi(DB_PORT.c_str()), NULL, 0) == NULL) {
+ fprintf(stderr, "%s\n", mysql_error(con));
+ mysql_close(con);
+ exit(1);
+ }
+ return con;
+}
+#endif
+
+
+
+void do_1(benchmark::State& state, MYSQL* conn) {
+ int rc;
+ rc = mysql_query(conn, "DO 1");
+ check_conn_rc(rc, conn);
+
+ int id;
+ benchmark::DoNotOptimize(id = mysql_insert_id(conn));
+}
+
+static void BM_DO_1(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int numOperation = 0;
+ for (auto _ : state) {
+ do_1(state, conn);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+}
+
+BENCHMARK(BM_DO_1)->Name(TYPE + " DO 1")->ThreadRange(1, MAX_THREAD)->UseRealTime();
+
+
+
+
+void select_1(benchmark::State& state, MYSQL* conn) {
+ int rc;
+ rc = mysql_query(conn, "SELECT 1");
+ check_conn_rc(rc, conn);
+
+ MYSQL_RES *result = mysql_store_result(conn);
+ int num_fields = mysql_num_fields(result);
+
+ char* val_name;
+ MYSQL_FIELD *field;
+ while(field = mysql_fetch_field(result)) {
+ benchmark::DoNotOptimize(val_name = field->name);
+ }
+
+ int val;
+ MYSQL_ROW row;
+ while ((row = mysql_fetch_row(result))) {
+ for(int i = 0; i < num_fields; i++) {
+ benchmark::DoNotOptimize(val = atoi(row[i]));
+ }
+ }
+
+ mysql_free_result(result);
+}
+
+static void BM_SELECT_1(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int numOperation = 0;
+ for (auto _ : state) {
+ select_1(state, conn);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+}
+
+BENCHMARK(BM_SELECT_1)->Name(TYPE + " SELECT 1")->ThreadRange(1, MAX_THREAD)->UseRealTime();
+
+
+
+void select_1000_rows(benchmark::State& state, MYSQL* conn) {
+ if (mysql_query(conn, "select seq, 'abcdefghijabcdefghijabcdefghijaa' from seq_1_to_1000")) {
+ fprintf(stderr, "%s\n", mysql_error(conn));
+ mysql_close(conn);
+ exit(1);
+ }
+ MYSQL_RES *result = mysql_store_result(conn);
+ unsigned int num_fields = mysql_num_fields(result);
+
+ if (result == NULL) {
+ fprintf(stderr, "%s\n", mysql_error(conn));
+ mysql_close(conn);
+ exit(1);
+ }
+
+ int val1;
+ std::string val2;
+ MYSQL_ROW row;
+ while ((row = mysql_fetch_row(result))) {
+ benchmark::DoNotOptimize(val1 = atoi(row[0]));
+ benchmark::DoNotOptimize(val2 = row[1]);
+ benchmark::ClobberMemory();
+ }
+
+ mysql_free_result(result);
+}
+
+static void BM_SELECT_1000_ROWS(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int numOperation = 0;
+ for (auto _ : state) {
+ select_1000_rows(state, conn);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+}
+
+BENCHMARK(BM_SELECT_1000_ROWS)->Name(TYPE + " SELECT 1000 rows (int + char(32))")->ThreadRange(1, MAX_THREAD)->UseRealTime();
+
+
+static void setup_select_100_int_cols(const benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int rc;
+
+ rc = mysql_query(conn, "DROP TABLE IF EXISTS test100");
+ check_conn_rc(rc, conn);
+
+ rc = mysql_query(conn, "CREATE TABLE test100 (i1 int,i2 int,i3 int,i4 int,i5 int,i6 int,i7 int,i8 int,i9 int,i10 int,i11 int,i12 int,i13 int,i14 int,i15 int,i16 int,i17 int,i18 int,i19 int,i20 int,i21 int,i22 int,i23 int,i24 int,i25 int,i26 int,i27 int,i28 int,i29 int,i30 int,i31 int,i32 int,i33 int,i34 int,i35 int,i36 int,i37 int,i38 int,i39 int,i40 int,i41 int,i42 int,i43 int,i44 int,i45 int,i46 int,i47 int,i48 int,i49 int,i50 int,i51 int,i52 int,i53 int,i54 int,i55 int,i56 int,i57 int,i58 int,i59 int,i60 int,i61 int,i62 int,i63 int,i64 int,i65 int,i66 int,i67 int,i68 int,i69 int,i70 int,i71 int,i72 int,i73 int,i74 int,i75 int,i76 int,i77 int,i78 int,i79 int,i80 int,i81 int,i82 int,i83 int,i84 int,i85 int,i86 int,i87 int,i88 int,i89 int,i90 int,i91 int,i92 int,i93 int,i94 int,i95 int,i96 int,i97 int,i98 int,i99 int,i100 int)");
+ check_conn_rc(rc, conn);
+
+ rc = mysql_query(conn, "INSERT INTO test100 value (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100)");
+ check_conn_rc(rc, conn);
+
+ mysql_close(conn);
+}
+
+void select_100_int_cols(benchmark::State& state, MYSQL* conn) {
+ int rc;
+ rc = mysql_query(conn, "select * FROM test100");
+ check_conn_rc(rc, conn);
+
+ MYSQL_RES *result = mysql_store_result(conn);
+ unsigned int num_fields = mysql_num_fields(result);
+
+ if (result == NULL) {
+ fprintf(stderr, "%s\n", mysql_error(conn));
+ mysql_close(conn);
+ exit(1);
+ }
+
+ int val1;
+ MYSQL_ROW row;
+ while ((row = mysql_fetch_row(result))) {
+ for (int i=0; i<100; i++)
+ benchmark::DoNotOptimize(val1 = atoi(row[i]));
+ benchmark::ClobberMemory();
+ }
+
+ mysql_free_result(result);
+}
+
+void select_100_int_cols_with_prepare(benchmark::State& state, MYSQL* conn) {
+ MYSQL_STMT *stmt = mysql_stmt_init(conn);
+ std::string query = "select * FROM test100";
+ int rc;
+
+ rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
+ check_conn_rc(rc, conn);
+
+ int int_data[100];
+ unsigned long length[100];
+
+ MYSQL_BIND my_bind[100];
+ memset(my_bind, 0, sizeof(my_bind));
+
+ for (int i = 0; i < 100; i++) {
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].buffer= (char *) &int_data[i];
+ my_bind[i].length= &length[i];
+ }
+
+ rc = mysql_stmt_execute(stmt);
+ check_conn_rc(rc, conn);
+
+ rc = mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt, conn);
+
+ rc = mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt, conn);
+
+ while (mysql_stmt_fetch(stmt)) {
+ //
+ }
+
+ mysql_stmt_close(stmt);
+}
+
+void select_100_int_cols_prepared(benchmark::State& state, MYSQL* conn, MYSQL_STMT* stmt) {
+ int rc;
+ int int_data[100];
+ unsigned long length[100];
+
+ MYSQL_BIND my_bind[100];
+ memset(my_bind, 0, sizeof(my_bind));
+
+ for (int i = 0; i < 100; i++) {
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].buffer= (char *) &int_data[i];
+ my_bind[i].length= &length[i];
+ }
+
+ rc = mysql_stmt_execute(stmt);
+ check_conn_rc(rc, conn);
+
+ rc = mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt, conn);
+
+ rc = mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt, conn);
+
+ while (mysql_stmt_fetch(stmt)) {
+ //
+ }
+}
+
+static void BM_SELECT_100_INT_COLS(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int numOperation = 0;
+ for (auto _ : state) {
+ select_100_int_cols(state, conn);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+}
+
+static void BM_SELECT_100_INT_COLS_WITH_PREPARE(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int numOperation = 0;
+ for (auto _ : state) {
+ select_100_int_cols_with_prepare(state, conn);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+}
+
+static void BM_SELECT_100_INT_COLS_PREPARED(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ MYSQL_STMT *stmt = mysql_stmt_init(conn);
+ std::string query = "select * FROM test100";
+ int rc;
+
+ rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
+ check_conn_rc(rc, conn);
+ int numOperation = 0;
+ for (auto _ : state) {
+ select_100_int_cols_prepared(state, conn, stmt);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_stmt_close(stmt);
+ mysql_close(conn);
+}
+
+BENCHMARK(BM_SELECT_100_INT_COLS)->Name(TYPE + " SELECT 100 int cols")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_select_100_int_cols);
+BENCHMARK(BM_SELECT_100_INT_COLS_WITH_PREPARE)->Name(TYPE + " SELECT 100 int cols - BINARY prepare+execute+close")->ThreadRange(1, MAX_THREAD)->UseRealTime();
+BENCHMARK(BM_SELECT_100_INT_COLS_PREPARED)->Name(TYPE + " SELECT 100 int cols - BINARY execute only")->ThreadRange(1, MAX_THREAD)->UseRealTime();
+
+
+
+
+void do_1000_params(benchmark::State& state, MYSQL* conn, const char* query) {
+ int rc;
+ rc = mysql_query(conn, query);
+ check_conn_rc(rc, conn);
+
+ int id;
+ benchmark::DoNotOptimize(id = mysql_insert_id(conn));
+}
+
+static void BM_DO_1000_PARAMS(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ std::string query = "DO 1";
+ for (int i = 1; i < 1000; i++) {
+ query += "," + std::to_string(i);
+ }
+ const char* queryChar = query.c_str();
+ int rc;
+
+ int numOperation = 0;
+ for (auto _ : state) {
+ do_1000_params(state, conn, queryChar);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+}
+
+BENCHMARK(BM_DO_1000_PARAMS)->Name(TYPE + " DO 1000 params")->ThreadRange(1, MAX_THREAD)->UseRealTime();
+
+
+
+
+static void setup_insert_batch(const benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int rc;
+
+ rc = mysql_query(conn, "DROP TABLE IF EXISTS perfTestTextBatch");
+ check_conn_rc(rc, conn);
+
+ rc = mysql_query(conn, "INSTALL SONAME 'ha_blackhole'");
+ rc = mysql_query(conn, "CREATE TABLE perfTestTextBatch (id MEDIUMINT NOT NULL AUTO_INCREMENT,t0 text, PRIMARY KEY (id)) COLLATE='utf8mb4_unicode_ci' ENGINE = BLACKHOLE");
+ if (rc) {
+ rc = mysql_query(conn, "CREATE TABLE perfTestTextBatch (id MEDIUMINT NOT NULL AUTO_INCREMENT,t0 text, PRIMARY KEY (id)) COLLATE='utf8mb4_unicode_ci'");
+ check_conn_rc(rc, conn);
+ }
+ mysql_close(conn);
+}
+
+std::vector<std::string> chars = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "\\Z", "😎", "🌶", "🎤", "🥂" };
+
+std::string randomString(int length) {
+ std::string result = "";
+ for (int i = length; i > 0; --i) {
+ result += chars[rand() % (chars.size() - 1)];
+ }
+ return result;
+}
+
+void insert_batch_with_prepare(benchmark::State& state, MYSQL* conn) {
+ MYSQL_STMT *stmt = mysql_stmt_init(conn);
+ std::string query = "INSERT INTO perfTestTextBatch(t0) VALUES (?)";
+ int rc;
+
+ rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
+ check_conn_rc(rc, conn);
+
+ std::string randomStringVal = randomString(100);
+ char* randValue = (char *)randomStringVal.c_str();
+ long unsigned randValueLen = randomStringVal.length();
+ MYSQL_BIND my_bind[1];
+ memset(my_bind, 0, sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= randValue;
+ my_bind[0].length= &randValueLen;
+
+ for (int i = 0; i < 100; i++) {
+ rc = mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt, conn);
+
+ rc = mysql_stmt_execute(stmt);
+ check_conn_rc(rc, conn);
+ }
+ mysql_stmt_close(stmt);
+}
+
+static void BM_INSERT_BATCH_WITH_PREPARE(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int numOperation = 0;
+ for (auto _ : state) {
+ insert_batch_with_prepare(state, conn);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+}
+
+BENCHMARK(BM_INSERT_BATCH_WITH_PREPARE)->Name(TYPE + " insert batch looping execute")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_insert_batch);
+
+#ifndef BENCHMARK_MYSQL
+
+ void insert_bulk_batch_with_prepare(benchmark::State& state, MYSQL* conn, MYSQL_STMT *stmt) {
+ int rc;
+ std::string randomStringVal = randomString(100);
+ char* randValue = (char *)randomStringVal.c_str();
+ long randValueLen = randomStringVal.length();
+
+ unsigned int numrows = 100;
+ long unsigned value_len[100];
+ char *valueptr[100];
+ for (int i = 0; i < 100; i++) {
+ valueptr[i]= randValue;
+ value_len[i]= randValueLen;
+ }
+
+ MYSQL_BIND my_bind[1];
+ memset(my_bind, 0, sizeof(my_bind));
+ my_bind[0].u.indicator = 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= valueptr;
+ my_bind[0].length= value_len;
+
+ rc = mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt, conn);
+
+ mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &numrows);
+ rc = mysql_stmt_execute(stmt);
+ check_conn_rc(rc, conn);
+ }
+
+ static void BM_INSERT_BULK_BATCH_WITH_PREPARE(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ MYSQL_STMT *stmt = mysql_stmt_init(conn);
+ std::string query = "INSERT INTO perfTestTextBatch(t0) VALUES (?)";
+ int rc;
+
+ rc = mysql_stmt_prepare(stmt, query.c_str(), (unsigned long)query.size());
+ check_conn_rc(rc, conn);
+
+ int numOperation = 0;
+ for (auto _ : state) {
+ insert_bulk_batch_with_prepare(state, conn, stmt);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_stmt_close(stmt);
+ mysql_close(conn);
+ }
+ BENCHMARK(BM_INSERT_BULK_BATCH_WITH_PREPARE)->Name(TYPE + " insert batch using bulk")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_insert_batch);
+
+ void select_100_int_cols_with_prepare_pipeline(benchmark::State& state, MYSQL* conn) {
+ MYSQL_STMT *stmt = mysql_stmt_init(conn);
+ std::string query = "select * FROM test100";
+ int rc;
+
+ int int_data[100];
+ unsigned long length[100];
+
+ MYSQL_BIND my_bind[100];
+ memset(my_bind, 0, sizeof(my_bind));
+
+ for (int i = 0; i < 100; i++) {
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].buffer= (char *) &int_data[i];
+ my_bind[i].length= &length[i];
+ }
+
+ rc = mariadb_stmt_execute_direct(stmt, query.c_str(), (unsigned long)query.size());
+ check_conn_rc(rc, conn);
+
+ rc = mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt, conn);
+
+ rc = mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt, conn);
+
+ while (mysql_stmt_fetch(stmt)) {
+ //
+ }
+
+ mysql_stmt_close(stmt);
+ }
+
+
+ static void BM_SELECT_100_INT_COLS_WITH_PREPARE_PIPELINE(benchmark::State& state) {
+ MYSQL *conn = connect("");
+ int numOperation = 0;
+ for (auto _ : state) {
+ select_100_int_cols_with_prepare_pipeline(state, conn);
+ numOperation++;
+ }
+ state.counters[OPERATION_PER_SECOND_LABEL] = benchmark::Counter(numOperation, benchmark::Counter::kIsRate);
+ mysql_close(conn);
+ }
+
+ BENCHMARK(BM_SELECT_100_INT_COLS_WITH_PREPARE_PIPELINE)->Name(TYPE + " SELECT 100 int cols - BINARY pipeline prepare+execute+close")->ThreadRange(1, MAX_THREAD)->UseRealTime()->Setup(setup_insert_batch);
+
+#endif
+
+
+BENCHMARK_MAIN();
diff --git a/libmariadb/client/CMakeLists.txt b/libmariadb/client/CMakeLists.txt
new file mode 100644
index 00000000..9a610847
--- /dev/null
+++ b/libmariadb/client/CMakeLists.txt
@@ -0,0 +1,17 @@
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include)
+
+IF(WIN32)
+ SET_VERSION_INFO("TARGET:mariadb_client_plugin_info"
+ "FILE_TYPE:VFT_APP"
+ "SOURCE_FILE:client/ma_plugin_info.c"
+ "ORIGINAL_FILE_NAME:mariadb_client_plugin_info.exe"
+ "FILE_DESCRIPTION:Client plugin viewer")
+ENDIF()
+
+ADD_EXECUTABLE(mariadb_client_plugin_info ${mariadb_client_plugin_info_RC} ma_plugin_info.c)
+TARGET_LINK_LIBRARIES(mariadb_client_plugin_info mariadbclient)
+
+INSTALL(TARGETS mariadb_client_plugin_info
+ DESTINATION ${INSTALL_BINDIR}
+ COMPONENT SharedLibraries)
+SIGN_TARGET(mariadb_client_plugin_info)
diff --git a/libmariadb/client/ma_plugin_info.c b/libmariadb/client/ma_plugin_info.c
new file mode 100644
index 00000000..73834e12
--- /dev/null
+++ b/libmariadb/client/ma_plugin_info.c
@@ -0,0 +1,211 @@
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <my_dir.h>
+#include <ma_string.h>
+
+#define CLIENT_PLUGIN_INFO_VERSION "1.0.0"
+
+static struct option long_options[]=
+{
+ {"all", no_argument, 0, 'a'},
+ {"builtin", no_argument, 0, 'b'},
+ {"dynamic", no_argument, 0, 'd'},
+ {"directory", 1, 0, 'p'},
+ {"plugin_name", 1, 0, 'n'},
+ {"version", no_argument, 0, 'v'},
+ {"help", no_argument, 0, '?'},
+ {NULL, 0, 0, 0}
+};
+
+static char *values[] =
+{
+ "show information for all plugins",
+ "show information for builtin plugins",
+ "show information for dynamic plugins",
+ "show information for dynamic plugins in specified directory",
+ "show information for specified plugin",
+ "show version information",
+ "display this help and exit",
+ NULL
+};
+
+struct st_plugin_type
+{
+ int type;
+ char *typename;
+};
+
+#ifndef _WIN32
+int my_errno=0;
+#endif
+
+static struct st_plugin_type plugin_types[]=
+{
+ {MYSQL_CLIENT_AUTHENTICATION_PLUGIN, "authentication"},
+ {MARIADB_CLIENT_PVIO_PLUGIN, "virtual IO"},
+ {MARIADB_CLIENT_TRACE_PLUGIN, "trace"},
+ {MARIADB_CLIENT_REMOTEIO_PLUGIN, "remote file access"},
+ {MARIADB_CLIENT_CONNECTION_PLUGIN, "connection handler"},
+ {0, "unknown"}
+};
+
+static void version()
+{
+ printf("%s Version %s\n", ma_progname, CLIENT_PLUGIN_INFO_VERSION);
+}
+
+static void usage(void)
+{
+ int i=0;
+ printf("%s Version %s\n", ma_progname, CLIENT_PLUGIN_INFO_VERSION);
+ puts("Copyright 2015 MariaDB Corporation AB");
+ puts("Show client plugin information for MariaDB Connector/C.");
+ printf("Usage: %s [OPTIONS] [plugin_name]\n", ma_progname);
+ while (long_options[i].name)
+ {
+ printf(" --%-12s -%s\n", long_options[i].name, values[i]);
+ i++;
+ }
+}
+
+static char *ma_get_type_name(int type)
+{
+ int i=0;
+ while (plugin_types[i].type)
+ {
+ if (type== plugin_types[i].type)
+ return plugin_types[i].typename;
+ i++;
+ }
+ return plugin_types[i].typename;
+}
+
+static void show_plugin_info(struct st_mysql_client_plugin *plugin, my_bool builtin)
+{
+ printf("Name: %s\n", plugin->name);
+ printf("Type: %s\n", ma_get_type_name(plugin->type));
+ printf("Desc: %s\n", plugin->desc);
+ printf("Author: %s\n", plugin->author);
+ printf("License: %s\n", plugin->license);
+ printf("Version: %d.%d.%d\n", plugin->version[0], plugin->version[1], plugin->version[2]);
+ printf("API Version: 0x%04X\n", plugin->interface_version);
+ printf("Build type: %s\n", builtin ? "builtin" : "dynamic");
+ printf("\n");
+}
+
+static void show_builtin()
+{
+ struct st_mysql_client_plugin **builtin;
+
+ for (builtin= mysql_client_builtins; *builtin; builtin++)
+ show_plugin_info(*builtin, TRUE);
+}
+
+static void show_file(char *filename)
+{
+ char dlpath[FN_REFLEN+1];
+ void *sym, *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+ char *env_plugin_dir= getenv("MARIADB_PLUGIN_DIR");
+ char *has_so_ext= strstr(filename, SO_EXT);
+
+ if (!strchr(filename, FN_LIBCHAR))
+ snprintf(dlpath, sizeof(dlpath) - 1, "%s/%s%s",
+ (env_plugin_dir) ? env_plugin_dir : PLUGINDIR,
+ filename,
+ has_so_ext ? "" : SO_EXT);
+ else
+ strcpy(dlpath, filename);
+ if ((dlhandle= dlopen((const char *)dlpath, RTLD_NOW)))
+ {
+ if (sym= dlsym(dlhandle, plugin_declarations_sym))
+ {
+ plugin= (struct st_mysql_client_plugin *)sym;
+ show_plugin_info(plugin, 0);
+ }
+ dlclose(dlhandle);
+ }
+}
+
+static void show_dynamic(const char *directory)
+{
+ MY_DIR *dir= NULL;
+ unsigned int i;
+ char *plugin_dir= directory ? (char *)directory : getenv("MARIADB_PLUGIN_DIR");
+
+ if (!plugin_dir)
+ plugin_dir= PLUGINDIR;
+
+ printf("plugin_dir %s\n", plugin_dir);
+
+ dir= my_dir(plugin_dir, 0);
+
+ if (!dir || !dir->number_off_files)
+ {
+ printf("No plugins found in %s\n", plugin_dir);
+ goto end;
+ }
+
+ for (i=0; i < dir->number_off_files; i++)
+ {
+ char *p= strstr(dir->dir_entry[i].name, SO_EXT);
+ if (p)
+ show_file(dir->dir_entry[i].name);
+ }
+end:
+ if (dir)
+ my_dirend(dir);
+}
+
+int main(int argc, char *argv[])
+{
+ int option_index= 0;
+ int c;
+ ma_progname= argv[0];
+
+ mysql_server_init(0, NULL, NULL);
+
+ if (argc <= 1)
+ {
+ usage();
+ exit(1);
+ }
+
+ c= getopt_long(argc, argv, "bdapnvh?", long_options, &option_index);
+
+ switch(c) {
+ case 'a': /* all */
+ show_builtin();
+ show_dynamic(NULL);
+ break;
+ case 'b': /* builtin */
+ show_builtin();
+ break;
+ case 'd': /* dynamic */
+ show_dynamic(NULL);
+ break;
+ case 'v':
+ version();
+ break;
+ case 'n':
+ if (argc > 2)
+ show_file(argv[2]);
+ break;
+ case 'p':
+ if (argc > 2)
+ show_dynamic(argv[2]);
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ printf("unrecognized option: %s", argv[1]);
+ exit(1);
+ }
+ exit(0);
+}
diff --git a/libmariadb/cmake/COPYING-CMAKE-SCRIPTS b/libmariadb/cmake/COPYING-CMAKE-SCRIPTS
new file mode 100644
index 00000000..4b417765
--- /dev/null
+++ b/libmariadb/cmake/COPYING-CMAKE-SCRIPTS
@@ -0,0 +1,22 @@
+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 copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
diff --git a/libmariadb/cmake/ConnectorName.cmake b/libmariadb/cmake/ConnectorName.cmake
new file mode 100644
index 00000000..9cbd87e3
--- /dev/null
+++ b/libmariadb/cmake/ConnectorName.cmake
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+MACRO(GET_CONNECTOR_PACKAGE_NAME name)
+# check if we have 64bit
+IF(SIZEOF_VOIDP EQUAL 8)
+ SET(IS64 1)
+ENDIF()
+
+SET (PLATFORM_NAME ${CMAKE_SYSTEM_NAME})
+SET (MACHINE_NAME ${CMAKE_SYSTEM_PROCESSOR})
+SET (CONCAT_SIGN "-")
+
+IF(CMAKE_SYSTEM_NAME MATCHES "Windows")
+ SET(PLATFORM_NAME "win")
+ SET(CONCAT_SIGN "")
+ IF(IS64)
+ IF(CMAKE_C_COMPILER_ARCHITECTURE_ID)
+ STRING(TOLOWER "${CMAKE_C_COMPILER_ARCHITECTURE_ID}" MACHINE_NAME)
+ ELSE()
+ SET(MACHINE_NAME x64)
+ ENDIF()
+ ELSE()
+ SET(MACHINE_NAME "32")
+ ENDIF()
+ENDIF()
+
+SET(product_name "mysql-connector-c-${CPACK_PACKAGE_VERSION}-${PLATFORM_NAME}${CONCAT_SIGN}${MACHINE_NAME}")
+STRING(TOLOWER ${product_name} ${name})
+ENDMACRO()
diff --git a/libmariadb/cmake/FindGSSAPI.cmake b/libmariadb/cmake/FindGSSAPI.cmake
new file mode 100644
index 00000000..7941c20e
--- /dev/null
+++ b/libmariadb/cmake/FindGSSAPI.cmake
@@ -0,0 +1,110 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+# - Try to detect the GSSAPI support
+# Once done this will define
+#
+# GSSAPI_FOUND - system supports GSSAPI
+# GSSAPI_INCS - the GSSAPI include directory
+# GSSAPI_LIBS - the libraries needed to use GSSAPI
+# GSSAPI_FLAVOR - the type of API - MIT or HEIMDAL
+
+# Copyright (c) 2006, Pino Toscano, <toscano.pino@tiscali.it>
+#
+# 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 copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+
+
+if(GSSAPI_LIBS AND GSSAPI_FLAVOR)
+
+ # in cache already
+ set(GSSAPI_FOUND TRUE)
+
+else(GSSAPI_LIBS AND GSSAPI_FLAVOR)
+
+ find_program(KRB5_CONFIG NAMES krb5-config PATHS
+ /opt/local/bin
+ /usr/lib/mit/bin/
+ ONLY_CMAKE_FIND_ROOT_PATH # this is required when cross compiling with cmake 2.6 and ignored with cmake 2.4, Alex
+ )
+ mark_as_advanced(KRB5_CONFIG)
+
+ #reset vars
+ set(GSSAPI_INCS)
+ set(GSSAPI_LIBS)
+ set(GSSAPI_FLAVOR)
+
+ if(KRB5_CONFIG)
+
+ set(HAVE_KRB5_GSSAPI TRUE)
+ exec_program(${KRB5_CONFIG} ARGS --libs gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_LIBS)
+ if(_return_VALUE)
+ message(STATUS "GSSAPI configure check failed.")
+ set(HAVE_KRB5_GSSAPI FALSE)
+ endif(_return_VALUE)
+ IF(CMAKE_SYSTEM_NAME MATCHES AIX)
+ string(REGEX REPLACE "-Wl[A-Za-z0-9_/,:-]*[ $]?" "" GSSAPI_LIBS "${GSSAPI_LIBS}")
+ string(REGEX REPLACE "-L[A-Za-z0-9_/,:-]*[ $]?" "" GSSAPI_LIBS "${GSSAPI_LIBS}")
+ ENDIF()
+
+ exec_program(${KRB5_CONFIG} ARGS --cflags gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_INCS)
+ string(REGEX REPLACE "(\r?\n)+$" "" GSSAPI_INCS "${GSSAPI_INCS}")
+ string(REGEX REPLACE " *-I" ";" GSSAPI_INCS "${GSSAPI_INCS}")
+
+ exec_program(${KRB5_CONFIG} ARGS --vendor RETURN_VALUE _return_VALUE OUTPUT_VARIABLE gssapi_flavor_tmp)
+ set(GSSAPI_FLAVOR_MIT)
+ if(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
+ set(GSSAPI_FLAVOR "MIT")
+ else(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
+ set(GSSAPI_FLAVOR "HEIMDAL")
+ endif(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
+
+ if(NOT HAVE_KRB5_GSSAPI)
+ if (gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
+ message(STATUS "Solaris Kerberos does not have GSSAPI; this is normal.")
+ set(GSSAPI_LIBS)
+ set(GSSAPI_INCS)
+ else(gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
+ message(WARNING "${KRB5_CONFIG} failed unexpectedly.")
+ endif(gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
+ endif(NOT HAVE_KRB5_GSSAPI)
+
+ if(GSSAPI_LIBS) # GSSAPI_INCS can be also empty, so don't rely on that
+ set(GSSAPI_FOUND TRUE CACHE STRING "")
+ message(STATUS "Found GSSAPI: ${GSSAPI_LIBS}")
+
+ set(GSSAPI_INCS ${GSSAPI_INCS} CACHE STRING "")
+ set(GSSAPI_LIBS ${GSSAPI_LIBS} CACHE STRING "")
+ set(GSSAPI_FLAVOR ${GSSAPI_FLAVOR} CACHE STRING "")
+
+ mark_as_advanced(GSSAPI_INCS GSSAPI_LIBS GSSAPI_FLAVOR)
+
+ endif(GSSAPI_LIBS)
+
+ endif(KRB5_CONFIG)
+
+endif(GSSAPI_LIBS AND GSSAPI_FLAVOR)
diff --git a/libmariadb/cmake/FindIconv.cmake b/libmariadb/cmake/FindIconv.cmake
new file mode 100644
index 00000000..dbc7369b
--- /dev/null
+++ b/libmariadb/cmake/FindIconv.cmake
@@ -0,0 +1,82 @@
+#
+# Copyright (C) 2010 Michael Bell <michael.bell@web.de>
+# 2015-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+# ICONV_EXTERNAL - Iconv is an external library (not libc)
+# ICONV_FOUND - system has Iconv
+# ICONV_INCLUDE_DIR - the Iconv include directory
+# ICONV_LIBRARIES - Link these to use Iconv
+# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const
+# ICONV_VERSION - Iconv version string
+
+if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+ # Already in cache, be silent
+ set(ICONV_FIND_QUIETLY TRUE)
+endif (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+
+find_path(ICONV_INCLUDE_DIR iconv.h)
+
+IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
+ # There is some libiconv.so in /usr/local that must
+ # be avoided, iconv routines are in libc
+ELSEIF(APPLE)
+ find_library(ICONV_LIBRARIES NAMES iconv libiconv PATHS
+ /usr/lib/
+ NO_CMAKE_SYSTEM_PATH)
+ SET(ICONV_EXTERNAL TRUE)
+ELSE()
+ find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2)
+ IF(ICONV_LIBRARIES)
+ SET(ICONV_EXTERNAL TRUE)
+ ENDIF()
+ENDIF()
+
+if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+ set (ICONV_FOUND TRUE)
+endif (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+
+set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+IF(ICONV_EXTERNAL)
+ set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
+ENDIF()
+
+if (ICONV_FOUND)
+ include(CheckCSourceCompiles)
+ CHECK_C_SOURCE_COMPILES("
+ #include <iconv.h>
+ int main(){
+ iconv_t conv = 0;
+ const char* in = 0;
+ size_t ilen = 0;
+ char* out = 0;
+ size_t olen = 0;
+ iconv(conv, &in, &ilen, &out, &olen);
+ return 0;
+ }
+" ICONV_SECOND_ARGUMENT_IS_CONST )
+ ADD_DEFINITIONS(-DHAVE_ICONV)
+endif (ICONV_FOUND)
+
+set (CMAKE_REQUIRED_INCLUDES)
+set (CMAKE_REQUIRED_LIBRARIES)
+
+if (ICONV_FOUND)
+ if (NOT ICONV_FIND_QUIETLY)
+ message (STATUS "Found Iconv: ${ICONV_LIBRARIES}")
+ endif (NOT ICONV_FIND_QUIETLY)
+else (ICONV_FOUND)
+ if (Iconv_FIND_REQUIRED)
+ message (FATAL_ERROR "Could not find Iconv")
+ endif (Iconv_FIND_REQUIRED)
+endif (ICONV_FOUND)
+
+MARK_AS_ADVANCED(
+ ICONV_INCLUDE_DIR
+ ICONV_LIBRARIES
+ ICONV_EXTERNAL
+ ICONV_SECOND_ARGUMENT_IS_CONST
+)
diff --git a/libmariadb/cmake/FindZStd.cmake b/libmariadb/cmake/FindZStd.cmake
new file mode 100644
index 00000000..d03e96fc
--- /dev/null
+++ b/libmariadb/cmake/FindZStd.cmake
@@ -0,0 +1,21 @@
+# - Find zstd
+# Find the zstd compression library and includes
+#
+# ZSTD_INCLUDE_DIRS - where to find zstd.h, etc.
+# ZSTD_LIBRARIES - List of libraries when using zstd.
+# ZSTD_FOUND - True if zstd found.
+
+find_path(ZSTD_INCLUDE_DIRS
+ NAMES zstd.h
+ HINTS ${ZSTD_ROOT_DIR}/include)
+
+find_library(ZSTD_LIBRARIES
+ NAMES zstd
+ HINTS ${ZSTD_ROOT_DIR}/lib)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(ZSTD DEFAULT_MSG ZSTD_LIBRARIES ZSTD_INCLUDE_DIRS)
+
+mark_as_advanced(
+ ZSTD_LIBRARIES
+ ZSTD_INCLUDE_DIRS)
diff --git a/libmariadb/cmake/SearchLibrary.cmake b/libmariadb/cmake/SearchLibrary.cmake
new file mode 100644
index 00000000..aa3a240e
--- /dev/null
+++ b/libmariadb/cmake/SearchLibrary.cmake
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+INCLUDE(CheckFunctionExists)
+INCLUDE(CheckLibraryExists)
+
+FUNCTION(SEARCH_LIBRARY library_name function liblist)
+ IF(${${library_name}})
+ RETURN()
+ ENDIF()
+ CHECK_FUNCTION_EXISTS(${function} IS_${function}_LIBC_FUNC)
+ IF(IS_${function}_LIBC_FUNC)
+ SET(${library_name} "" PARENT_SCOPE)
+ RETURN()
+ ENDIF()
+ FOREACH(lib ${liblist})
+ CHECK_LIBRARY_EXISTS(${lib} ${function} "" HAVE_${function}_IN_${lib})
+ IF(HAVE_${function}_IN_${lib})
+ SET(${library_name} ${lib} PARENT_SCOPE)
+ SET(HAVE_${library_name} 1 PARENT_SCOPE)
+ RETURN()
+ ENDIF()
+ ENDFOREACH()
+ENDFUNCTION()
+
diff --git a/libmariadb/cmake/WindowsCache.cmake b/libmariadb/cmake/WindowsCache.cmake
new file mode 100644
index 00000000..2d953c3e
--- /dev/null
+++ b/libmariadb/cmake/WindowsCache.cmake
@@ -0,0 +1,391 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+IF(MSVC)
+SET(BFD_H_EXISTS 0 CACHE INTERNAL "")
+SET(HAVE_ACCESS 1 CACHE INTERNAL "")
+SET(HAVE_AIO_H CACHE INTERNAL "")
+SET(HAVE_AIO_READ CACHE INTERNAL "")
+SET(HAVE_ALARM CACHE INTERNAL "")
+SET(HAVE_ALLOCA_H CACHE INTERNAL "")
+SET(HAVE_ARPA_INET_H CACHE INTERNAL "")
+SET(HAVE_ASM_MSR_H CACHE INTERNAL "")
+SET(HAVE_BACKTRACE CACHE INTERNAL "")
+SET(HAVE_BACKTRACE_SYMBOLS CACHE INTERNAL "")
+SET(HAVE_BACKTRACE_SYMBOLS_FD CACHE INTERNAL "")
+SET(HAVE_BFILL CACHE INTERNAL "")
+SET(HAVE_BMOVE CACHE INTERNAL "")
+SET(HAVE_BSD_SIGNALS CACHE INTERNAL "")
+SET(HAVE_BSEARCH 1 CACHE INTERNAL "")
+SET(HAVE_BSS_START CACHE INTERNAL "")
+SET(HAVE_BZERO CACHE INTERNAL "")
+SET(HAVE_CHOWN CACHE INTERNAL "")
+SET(HAVE_CLOCK_GETTIME CACHE INTERNAL "")
+SET(HAVE_COMPRESS CACHE INTERNAL "")
+SET(HAVE_CRYPT CACHE INTERNAL "")
+SET(HAVE_CRYPT_H CACHE INTERNAL "")
+SET(HAVE_CUSERID CACHE INTERNAL "")
+SET(HAVE_CXX_NEW 1 CACHE INTERNAL "")
+SET(HAVE_DECL_MADVISE CACHE INTERNAL "")
+SET(HAVE_DIRECTIO CACHE INTERNAL "")
+SET(HAVE_DIRENT_H CACHE INTERNAL "")
+SET(HAVE_DLERROR CACHE INTERNAL "")
+SET(HAVE_DLFCN_H CACHE INTERNAL "")
+SET(HAVE_DLOPEN CACHE INTERNAL "")
+SET(HAVE_DOPRNT CACHE INTERNAL "")
+SET(HAVE_EXECINFO_H CACHE INTERNAL "")
+SET(HAVE_FCHMOD CACHE INTERNAL "")
+SET(HAVE_FCNTL CACHE INTERNAL "")
+SET(HAVE_FCNTL_H 1 CACHE INTERNAL "")
+SET(HAVE_FCNTL_NONBLOCK CACHE INTERNAL "")
+SET(HAVE_FCONVERT CACHE INTERNAL "")
+SET(HAVE_FDATASYNC CACHE INTERNAL "")
+SET(HAVE_DECL_FDATASYNC CACHE INTERNAL "")
+SET(HAVE_FEDISABLEEXCEPT CACHE INTERNAL "")
+SET(HAVE_FENV_H CACHE INTERNAL "")
+SET(HAVE_FESETROUND CACHE INTERNAL "")
+SET(HAVE_FGETLN CACHE INTERNAL "")
+SET(HAVE_FINITE CACHE INTERNAL "")
+SET(HAVE_FINITE_IN_MATH_H CACHE INTERNAL "")
+SET(HAVE_FLOATINGPOINT_H CACHE INTERNAL "")
+SET(HAVE_FLOAT_H 1 CACHE INTERNAL "")
+SET(HAVE_FLOCKFILE CACHE INTERNAL "")
+SET(HAVE_FNMATCH_H CACHE INTERNAL "")
+SET(HAVE_FPSETMASK CACHE INTERNAL "")
+SET(HAVE_FPU_CONTROL_H CACHE INTERNAL "")
+SET(HAVE_FSEEKO CACHE INTERNAL "")
+SET(HAVE_FSYNC CACHE INTERNAL "")
+SET(HAVE_FTIME 1 CACHE INTERNAL "")
+SET(HAVE_FTRUNCATE CACHE INTERNAL "")
+SET(HAVE_GETADDRINFO 1 CACHE INTERNAL "")
+SET(HAVE_GETCWD 1 CACHE INTERNAL "")
+SET(HAVE_GETHOSTBYADDR_R CACHE INTERNAL "")
+SET(HAVE_GETHRTIME CACHE INTERNAL "")
+SET(HAVE_GETLINE CACHE INTERNAL "")
+SET(HAVE_GETNAMEINFO CACHE INTERNAL "")
+SET(HAVE_GETPAGESIZE CACHE INTERNAL "")
+SET(HAVE_GETPASS CACHE INTERNAL "")
+SET(HAVE_GETPASSPHRASE CACHE INTERNAL "")
+SET(HAVE_GETPWNAM CACHE INTERNAL "")
+SET(HAVE_GETPWUID CACHE INTERNAL "")
+SET(HAVE_GETRLIMIT CACHE INTERNAL "")
+SET(HAVE_GETRUSAGE CACHE INTERNAL "")
+SET(HAVE_GETTIMEOFDAY CACHE INTERNAL "")
+SET(HAVE_GETWD CACHE INTERNAL "")
+SET(HAVE_GRP_H CACHE INTERNAL "")
+SET(HAVE_IA64INTRIN_H CACHE INTERNAL "")
+SET(HAVE_IEEEFP_H CACHE INTERNAL "")
+SET(HAVE_INDEX CACHE INTERNAL "")
+SET(HAVE_INITGROUPS CACHE INTERNAL "")
+SET(HAVE_INTTYPES_H CACHE INTERNAL "")
+SET(HAVE_IPPROTO_IPV6 CACHE INTERNAL "")
+SET(HAVE_IPV6 TRUE CACHE INTERNAL "")
+SET(HAVE_IPV6_V6ONLY 1 CACHE INTERNAL "")
+SET(HAVE_ISINF CACHE INTERNAL "")
+SET(HAVE_ISSETUGID CACHE INTERNAL "")
+SET(HAVE_GETUID CACHE INTERNAL "")
+SET(HAVE_GETEUID CACHE INTERNAL "")
+SET(HAVE_GETGID CACHE INTERNAL "")
+SET(HAVE_GETEGID CACHE INTERNAL "")
+SET(HAVE_LANGINFO_H CACHE INTERNAL "")
+SET(HAVE_LDIV 1 CACHE INTERNAL "")
+SET(HAVE_LIMITS_H 1 CACHE INTERNAL "")
+SET(HAVE_LOCALE_H 1 CACHE INTERNAL "")
+SET(HAVE_LOG2 CACHE INTERNAL "")
+SET(HAVE_LONGJMP 1 CACHE INTERNAL "")
+SET(HAVE_LRAND48 CACHE INTERNAL "")
+SET(HAVE_LSTAT CACHE INTERNAL "")
+SET(HAVE_MADVISE CACHE INTERNAL "")
+SET(HAVE_MALLINFO CACHE INTERNAL "")
+SET(HAVE_MALLOC_H 1 CACHE INTERNAL "")
+SET(HAVE_MEMALIGN CACHE INTERNAL "")
+SET(HAVE_MEMCPY 1 CACHE INTERNAL "")
+SET(HAVE_MEMMOVE 1 CACHE INTERNAL "")
+SET(HAVE_MEMORY_H 1 CACHE INTERNAL "")
+SET(HAVE_MKSTEMP CACHE INTERNAL "")
+SET(HAVE_MLOCK CACHE INTERNAL "")
+SET(HAVE_MLOCKALL CACHE INTERNAL "")
+SET(HAVE_MMAP CACHE INTERNAL "")
+SET(HAVE_MMAP64 CACHE INTERNAL "")
+SET(HAVE_NETDB_H CACHE INTERNAL "")
+SET(HAVE_NETINET_IN6_H CACHE INTERNAL "")
+SET(HAVE_NETINET_IN_H CACHE INTERNAL "")
+SET(HAVE_NL_LANGINFO CACHE INTERNAL "")
+SET(HAVE_PASE_ENVIRONMENT CACHE INTERNAL "")
+SET(HAVE_PATHS_H CACHE INTERNAL "")
+SET(HAVE_PCLOSE CACHE INTERNAL "")
+SET(HAVE_PERROR 1 CACHE INTERNAL "")
+SET(HAVE_PEERCRED CACHE INTERNAL "")
+SET(HAVE_PAM_APPL_H CACHE INTERNAL "")
+SET(HAVE_POLL_H CACHE INTERNAL "")
+SET(HAVE_POPEN CACHE INTERNAL "")
+SET(HAVE_POLL CACHE INTERNAL "")
+SET(HAVE_PORT_CREATE CACHE INTERNAL "")
+SET(HAVE_PORT_H CACHE INTERNAL "")
+SET(HAVE_POSIX_FALLOCATE CACHE INTERNAL "")
+SET(HAVE_POSIX_SIGNALS CACHE INTERNAL "")
+SET(HAVE_PREAD CACHE INTERNAL "")
+SET(HAVE_PRINTSTACK CACHE INTERNAL "")
+SET(HAVE_PTHREAD_ATTR_CREATE CACHE INTERNAL "")
+SET(HAVE_PTHREAD_ATTR_GETSTACKSIZE CACHE INTERNAL "")
+SET(HAVE_PTHREAD_ATTR_SETSCOPE CACHE INTERNAL "")
+SET(HAVE_PTHREAD_ATTR_SETSTACKSIZE CACHE INTERNAL "")
+SET(HAVE_PTHREAD_CONDATTR_CREATE CACHE INTERNAL "")
+SET(HAVE_PTHREAD_CONDATTR_SETCLOCK CACHE INTERNAL "")
+SET(HAVE_PTHREAD_INIT CACHE INTERNAL "")
+SET(HAVE_PTHREAD_KEY_DELETE CACHE INTERNAL "")
+SET(HAVE_PTHREAD_RWLOCK_RDLOCK CACHE INTERNAL "")
+SET(HAVE_PTHREAD_SIGMASK CACHE INTERNAL "")
+SET(HAVE_PTHREAD_THREADMASK CACHE INTERNAL "")
+SET(HAVE_PTHREAD_YIELD_NP CACHE INTERNAL "")
+SET(HAVE_PTHREAD_YIELD_ZERO_ARG CACHE INTERNAL "")
+SET(HAVE_PUTENV 1 CACHE INTERNAL "")
+SET(HAVE_PWD_H CACHE INTERNAL "")
+SET(HAVE_RDTSCLL CACHE INTERNAL "")
+SET(HAVE_READDIR_R CACHE INTERNAL "")
+SET(HAVE_READLINK CACHE INTERNAL "")
+SET(HAVE_READ_REAL_TIME CACHE INTERNAL "")
+SET(HAVE_REALPATH CACHE INTERNAL "")
+SET(HAVE_REGCOMP CACHE INTERNAL "")
+SET(HAVE_RENAME 1 CACHE INTERNAL "")
+SET(HAVE_RE_COMP CACHE INTERNAL "")
+SET(HAVE_RINT CACHE INTERNAL "")
+SET(HAVE_RWLOCK_INIT CACHE INTERNAL "")
+SET(HAVE_SCHED_H CACHE INTERNAL "")
+SET(HAVE_SCHED_YIELD CACHE INTERNAL "")
+SET(HAVE_SELECT 1 CACHE INTERNAL "")
+SET(HAVE_SELECT_H CACHE INTERNAL "")
+SET(HAVE_SEMAPHORE_H CACHE INTERNAL "")
+SET(HAVE_SETENV CACHE INTERNAL "")
+SET(HAVE_SETFD CACHE INTERNAL "")
+SET(HAVE_SETLOCALE 1 CACHE INTERNAL "")
+SET(HAVE_SHMAT CACHE INTERNAL "")
+SET(HAVE_SHMCTL CACHE INTERNAL "")
+SET(HAVE_SHMDT CACHE INTERNAL "")
+SET(HAVE_SHMGET CACHE INTERNAL "")
+SET(HAVE_SIGACTION CACHE INTERNAL "")
+SET(HAVE_SIGADDSET CACHE INTERNAL "")
+SET(HAVE_SIGEMPTYSET CACHE INTERNAL "")
+SET(HAVE_SIGHOLD CACHE INTERNAL "")
+SET(HAVE_SIGINT 1 CACHE INTERNAL "")
+SET(HAVE_SIGPIPE CACHE INTERNAL "")
+SET(HAVE_SIGQUIT CACHE INTERNAL "")
+SET(HAVE_SIGSET CACHE INTERNAL "")
+SET(HAVE_SIGTERM 1 CACHE INTERNAL "")
+SET(HAVE_SIGTHREADMASK CACHE INTERNAL "")
+SET(HAVE_SIGWAIT CACHE INTERNAL "")
+SET(HAVE_SIZEOF_BOOL FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_CHAR TRUE CACHE INTERNAL "")
+SET(SIZEOF_CHAR 1 CACHE INTERNAL "")
+SET(HAVE_SIZEOF_CHARP TRUE CACHE INTERNAL "")
+SET(SIZEOF_CHARP ${CMAKE_SIZEOF_VOID_P} CACHE INTERNAL "")
+SET(HAVE_SIZEOF_IN6_ADDR TRUE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_INT TRUE CACHE INTERNAL "")
+SET(SIZEOF_INT 4 CACHE INTERNAL "")
+SET(HAVE_SIZEOF_INT16 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_INT32 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_INT64 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_INT8 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_LONG TRUE CACHE INTERNAL "")
+SET(SIZEOF_LONG 4 CACHE INTERNAL "")
+SET(HAVE_SIZEOF_LONG_LONG TRUE CACHE INTERNAL "")
+SET(SIZEOF_LONG_LONG 8 CACHE INTERNAL "")
+SET(HAVE_SIZEOF_MODE_T FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_OFF_T TRUE CACHE INTERNAL "")
+SET(SIZEOF_OFF_T 4 CACHE INTERNAL "")
+SET(HAVE_SIZEOF_SHORT TRUE CACHE INTERNAL "")
+SET(SIZEOF_SHORT 2 CACHE INTERNAL "")
+SET(HAVE_SIZEOF_SIGSET_T FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_SIZE_T TRUE CACHE INTERNAL "")
+SET(SIZEOF_SIZE_T ${CMAKE_SIZEOF_VOID_P} CACHE INTERNAL "")
+SET(HAVE_SIZEOF_SOCKADDR_IN6 TRUE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_SOCKLEN_T FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_UCHAR FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_UINT FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_UINT16 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_UINT32 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_UINT64 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_UINT8 FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_ULONG FALSE CACHE INTERNAL "")
+SET(HAVE_SIZEOF_U_INT32_T FALSE CACHE INTERNAL "")
+SET(HAVE_SIZE_OF_SSIZE_T FALSE CACHE INTERNAL "")
+SET(HAVE_SLEEP CACHE INTERNAL "")
+SET(HAVE_SOCKADDR_STORAGE_SS_FAMILY 1 CACHE INTERNAL "")
+SET(HAVE_SOLARIS_STYLE_GETHOST CACHE INTERNAL "")
+SET(STACK_DIRECTION -1 CACHE INTERNAL "")
+SET(HAVE_STDARG_H 1 CACHE INTERNAL "")
+SET(HAVE_STDDEF_H 1 CACHE INTERNAL "")
+SET(HAVE_STDINT_H CACHE INTERNAL "")
+SET(HAVE_STDLIB_H 1 CACHE INTERNAL "")
+SET(HAVE_STPCPY CACHE INTERNAL "")
+SET(HAVE_STRCASECMP CACHE INTERNAL "")
+SET(HAVE_STRCOLL 1 CACHE INTERNAL "")
+SET(HAVE_STRDUP 1 CACHE INTERNAL "")
+SET(HAVE_STRERROR 1 CACHE INTERNAL "")
+SET(HAVE_STRINGS_H CACHE INTERNAL "")
+SET(HAVE_STRING_H 1 CACHE INTERNAL "")
+SET(HAVE_STRLCAT CACHE INTERNAL "")
+SET(HAVE_STRLCPY CACHE INTERNAL "")
+SET(HAVE_STRNCASECMP CACHE INTERNAL "")
+SET(HAVE_STRNDUP CACHE INTERNAL "")
+IF(MSVC_VERSION GREATER 1310)
+SET(HAVE_STRNLEN 1 CACHE INTERNAL "")
+ENDIF()
+SET(HAVE_STRPBRK 1 CACHE INTERNAL "")
+SET(HAVE_STRSEP CACHE INTERNAL "")
+SET(HAVE_STRSIGNAL CACHE INTERNAL "")
+SET(HAVE_STRSTR 1 CACHE INTERNAL "")
+SET(HAVE_STRTOK_R CACHE INTERNAL "")
+SET(HAVE_STRTOL 1 CACHE INTERNAL "")
+SET(HAVE_STRTOLL CACHE INTERNAL "")
+SET(HAVE_STRTOUL 1 CACHE INTERNAL "")
+SET(HAVE_STRTOULL CACHE INTERNAL "")
+SET(HAVE_SVR3_SIGNALS CACHE INTERNAL "")
+SET(HAVE_SYNCH_H CACHE INTERNAL "")
+SET(HAVE_SYSENT_H CACHE INTERNAL "")
+SET(HAVE_SYS_CDEFS_H CACHE INTERNAL "")
+SET(HAVE_SYS_DIR_H CACHE INTERNAL "")
+SET(HAVE_SYS_ERRLIST CACHE INTERNAL "")
+SET(HAVE_SYS_FILE_H CACHE INTERNAL "")
+SET(HAVE_SYS_FPU_H CACHE INTERNAL "")
+SET(HAVE_SYS_IOCTL_H CACHE INTERNAL "")
+SET(HAVE_SYS_IPC_H CACHE INTERNAL "")
+SET(HAVE_SYS_MALLOC_H CACHE INTERNAL "")
+SET(HAVE_SYS_MMAN_H CACHE INTERNAL "")
+SET(HAVE_SYS_PARAM_H CACHE INTERNAL "")
+SET(HAVE_SYS_PRCTL_H CACHE INTERNAL "")
+SET(HAVE_SYS_PTEM_H CACHE INTERNAL "")
+SET(HAVE_SYS_PTE_H CACHE INTERNAL "")
+SET(HAVE_SYS_RESOURCE_H CACHE INTERNAL "")
+SET(HAVE_SYS_SELECT_H CACHE INTERNAL "")
+SET(HAVE_SYS_SHM_H CACHE INTERNAL "")
+SET(HAVE_SYS_SOCKIO_H CACHE INTERNAL "")
+SET(HAVE_SYS_SOCKET_H CACHE INTERNAL "")
+SET(HAVE_SYS_STAT_H 1 CACHE INTERNAL "")
+SET(HAVE_SYS_STREAM_H CACHE INTERNAL "")
+SET(HAVE_SYS_TERMCAP_H CACHE INTERNAL "")
+SET(HAVE_SYS_TIMEB_H 1 CACHE INTERNAL "")
+SET(HAVE_SYS_TIMES_H CACHE INTERNAL "")
+SET(HAVE_SYS_TIME_H CACHE INTERNAL "")
+SET(HAVE_SYS_TYPES_H 1 CACHE INTERNAL "")
+SET(HAVE_SYS_UN_H CACHE INTERNAL "")
+SET(HAVE_SYS_UTIME_H 1 CACHE INTERNAL "")
+SET(HAVE_SYS_VADVISE_H CACHE INTERNAL "")
+SET(HAVE_SYS_WAIT_H CACHE INTERNAL "")
+SET(HAVE_TCGETATTR CACHE INTERNAL "")
+SET(HAVE_TELL 1 CACHE INTERNAL "")
+SET(HAVE_TEMPNAM 1 CACHE INTERNAL "")
+SET(HAVE_TERMCAP_H CACHE INTERNAL "")
+SET(HAVE_TERMIOS_H CACHE INTERNAL "")
+SET(HAVE_TERMIO_H CACHE INTERNAL "")
+SET(HAVE_TERM_H CACHE INTERNAL "")
+SET(HAVE_THR_SETCONCURRENCY CACHE INTERNAL "")
+SET(HAVE_THR_YIELD CACHE INTERNAL "")
+SET(HAVE_TIME 1 CACHE INTERNAL "")
+SET(HAVE_TIMES CACHE INTERNAL "")
+SET(HAVE_TIMESPEC_TS_SEC CACHE INTERNAL "")
+SET(HAVE_TIME_H 1 CACHE INTERNAL "")
+SET(HAVE_TZNAME 1 CACHE INTERNAL "")
+SET(HAVE_UNISTD_H CACHE INTERNAL "")
+SET(HAVE_UTIME_H CACHE INTERNAL "")
+SET(HAVE_VALLOC CACHE INTERNAL "")
+SET(HAVE_VARARGS_H 1 CACHE INTERNAL "")
+SET(HAVE_VASPRINTF CACHE INTERNAL "")
+SET(HAVE_VPRINTF 1 CACHE INTERNAL "")
+IF(MSVC_VERSION GREATER 1310)
+SET(HAVE_VSNPRINTF 1 CACHE INTERNAL "")
+ENDIF()
+SET(HAVE_WEAK_SYMBOL CACHE INTERNAL "")
+SET(HAVE_BIGENDIAN CACHE INTERNAL "")
+SET(HAVE__S_IFIFO 1 CACHE INTERNAL "")
+SET(HAVE__S_IREAD 1 CACHE INTERNAL "")
+SET(HAVE__finite 1 CACHE INTERNAL "")
+SET(HAVE__pclose 1 CACHE INTERNAL "")
+SET(HAVE__popen 1 CACHE INTERNAL "")
+SET(HAVE__stricmp 1 CACHE INTERNAL "")
+SET(HAVE__strnicmp 1 CACHE INTERNAL "")
+SET(HAVE__strtoi64 1 CACHE INTERNAL "")
+SET(HAVE__strtoui64 1 CACHE INTERNAL "")
+IF(MSVC_VERSION GREATER 1310)
+ SET(HAVE_strtok_s 1 CACHE INTERNAL "")
+ENDIF()
+SET(STDC_HEADERS CACHE 1 INTERNAL "")
+SET(STRUCT_DIRENT_HAS_D_INO CACHE INTERNAL "")
+SET(STRUCT_DIRENT_HAS_D_INO CACHE INTERNAL "")
+SET(STRUCT_DIRENT_HAS_D_NAMLEN CACHE INTERNAL "")
+SET(TIME_WITH_SYS_TIME CACHE INTERNAL "")
+SET(TIME_T_UNSIGNED 1 CACHE INTERNAL "")
+SET(TIOCSTAT_IN_SYS_IOCTL CACHE INTERNAL "")
+SET(HAVE_S_IROTH CACHE INTERNAL "")
+SET(HAVE_S_IFIFO CACHE INTERNAL "")
+SET(QSORT_TYPE_IS_VOID 1 CACHE INTERNAL "")
+SET(SIGNAL_RETURN_TYPE_IS_VOID 1 CACHE INTERNAL "")
+SET(C_HAS_inline CACHE INTERNAL "")
+SET(C_HAS___inline 1 CACHE INTERNAL "")
+SET(FIONREAD_IN_SYS_IOCTL CACHE INTERNAL "")
+SET(FIONREAD_IN_SYS_FILIO CACHE INTERNAL "")
+SET(GWINSZ_IN_SYS_IOCTL CACHE INTERNAL "")
+SET(HAVE_CXXABI_H CACHE INTERNAL "")
+SET(HAVE_NDIR_H CACHE INTERNAL "")
+SET(HAVE_SYS_NDIR_H CACHE INTERNAL "")
+SET(HAVE_SYS_NDIR_H CACHE INTERNAL "")
+SET(HAVE_ASM_TERMBITS_H CACHE INTERNAL "")
+SET(HAVE_TERMBITS_H CACHE INTERNAL "")
+SET(HAVE_VIS_H CACHE INTERNAL "")
+SET(HAVE_WCHAR_H 1 CACHE INTERNAL "")
+SET(HAVE_WCTYPE_H 1 CACHE INTERNAL "")
+SET(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP CACHE INTERNAL "")
+SET(HAVE_SOCKADDR_IN_SIN_LEN CACHE INTERNAL "")
+SET(HAVE_SOCKADDR_IN6_SIN6_LEN CACHE INTERNAL "")
+SET(HAVE_VALGRIND CACHE INTERNAL "")
+SET(HAVE_EVENT_H CACHE INTERNAL "")
+SET(HAVE_LINUX_UNISTD_H CACHE INTERNAL "")
+SET(HAVE_SYS_UTSNAME_H CACHE INTERNAL "")
+SET(HAVE_PTHREAD_ATTR_GETGUARDSIZE CACHE INTERNAL "")
+SET(FIONREAD_IN_SYS_FILIO CACHE INTERNAL "")
+SET(FIONREAD_IN_SYS_IOCTL CACHE INTERNAL "")
+SET(GWINSZ_IN_SYS_IOCTL CACHE INTERNAL "")
+SET(HAVE_ACCESS 1 CACHE INTERNAL "")
+SET(HAVE_AIOWAIT CACHE INTERNAL "")
+SET(HAVE_AIO_H CACHE INTERNAL "")
+SET(HAVE_AIO_READ CACHE INTERNAL "")
+SET(HAVE_ALARM CACHE INTERNAL "")
+SET(HAVE_ALLOCA CACHE INTERNAL "")
+SET(HAVE_ALLOCA_H CACHE INTERNAL "")
+SET(HAVE_ARPA_INET_H CACHE INTERNAL "")
+SET(HAVE_ASM_MSR_H CACHE INTERNAL "")
+SET(HAVE_ASM_TERMBITS_H CACHE INTERNAL "")
+SET(HAVE_BACKTRACE CACHE INTERNAL "")
+SET(HAVE_BACKTRACE_SYMBOLS CACHE INTERNAL "")
+SET(HAVE_BACKTRACE_SYMBOLS_FD CACHE INTERNAL "")
+SET(HAVE_BCMP CACHE INTERNAL "")
+SET(HAVE_BFILL CACHE INTERNAL "")
+SET(HAVE_BMOVE CACHE INTERNAL "")
+SET(HAVE_BSD_SIGNALS CACHE INTERNAL "")
+SET(HAVE_BSEARCH CACHE INTERNAL "")
+SET(HAVE_BSS_START CACHE INTERNAL "")
+SET(HAVE_BZERO CACHE INTERNAL "")
+SET(HAVE_CHOWN CACHE INTERNAL "")
+SET(HAVE_CLOCK_GETTIME CACHE INTERNAL "")
+SET(HAVE_COMPRESS CACHE INTERNAL "")
+SET(HAVE_CRYPT CACHE INTERNAL "")
+SET(HAVE_CRYPT_H CACHE INTERNAL "")
+SET(HAVE_CUSERID CACHE INTERNAL "")
+SET(HAVE_CXXABI_H CACHE INTERNAL "")
+SET(HAVE_DECL_FDATASYNC CACHE INTERNAL "")
+SET(HAVE_SIGNAL_H 1 CACHE INTERNAL "")
+SET(HAVE_GETHOSTBYNAME_R CACHE INTERNAL "")
+SET(HAVE_PTHREAD_ATTR_SETPRIO CACHE INTERNAL "")
+SET(HAVE_PTHREAD_ATTR_SETSCHEDPARAM CACHE INTERNAL "")
+SET(HAVE_PTHREAD_KILL CACHE INTERNAL "")
+SET(HAVE_PTHREAD_SETPRIO_NP CACHE INTERNAL "")
+SET(HAVE_PTHREAD_SETSCHEDPARAM CACHE INTERNAL "")
+SET(HAVE_SETFILEPOINTER CACHE INTERNAL "")
+SET(SIZEOF_U_INT32_T CACHE INTERNAL "")
+SET(IS_VOID_SIGNAL 1 CACHE INTERNAL "")
+SET(IS_VOID_QSORT 1 CACHE INTERNAL "")
+ENDIF()
diff --git a/libmariadb/cmake/check_functions.cmake b/libmariadb/cmake/check_functions.cmake
new file mode 100644
index 00000000..5ea949eb
--- /dev/null
+++ b/libmariadb/cmake/check_functions.cmake
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+
+# This file is included by CMakeLists.txt and
+# checks for various functions.
+# You will find the appropriate defines in
+# include/my_config.h.in
+
+INCLUDE(CheckFunctionExists)
+
+CHECK_FUNCTION_EXISTS (alloca HAVE_ALLOCA)
+CHECK_FUNCTION_EXISTS (dlerror HAVE_DLERROR)
+CHECK_FUNCTION_EXISTS (dlopen HAVE_DLOPEN)
+CHECK_FUNCTION_EXISTS (fcntl HAVE_FCNTL)
+CHECK_FUNCTION_EXISTS (memcpy HAVE_MEMCPY)
+CHECK_FUNCTION_EXISTS (nl_langinfo HAVE_NL_LANGINFO)
+CHECK_FUNCTION_EXISTS (setlocale HAVE_SETLOCALE)
+CHECK_FUNCTION_EXISTS (poll HAVE_POLL)
+CHECK_FUNCTION_EXISTS (getpwuid HAVE_GETPWUID)
+
+IF(HAVE_FILE_UCONTEXT_H)
+ CHECK_FUNCTION_EXISTS (makecontext HAVE_UCONTEXT_H)
+ENDIF()
+
+CHECK_FUNCTION_EXISTS (cuserid HAVE_CUSERID) \ No newline at end of file
diff --git a/libmariadb/cmake/check_include_files.cmake b/libmariadb/cmake/check_include_files.cmake
new file mode 100644
index 00000000..d8bbffcd
--- /dev/null
+++ b/libmariadb/cmake/check_include_files.cmake
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+# This file is included by CMakeLists.txt and
+# checks for various header files.
+# You will find the appropriate defines in
+# include/my_config.h.in
+
+INCLUDE(CheckIncludeFiles)
+
+CHECK_INCLUDE_FILES (alloca.h HAVE_ALLOCA_H)
+CHECK_INCLUDE_FILES (dlfcn.h HAVE_DLFCN_H)
+CHECK_INCLUDE_FILES (fcntl.h HAVE_FCNTL_H)
+CHECK_INCLUDE_FILES (float.h HAVE_FLOAT_H)
+CHECK_INCLUDE_FILES (limits.h HAVE_LIMITS_H)
+CHECK_INCLUDE_FILES (linux/limits.h HAVE_LINUX_LIMITS_H)
+CHECK_INCLUDE_FILES (pwd.h HAVE_PWD_H)
+CHECK_INCLUDE_FILES (select.h HAVE_SELECT_H)
+
+CHECK_INCLUDE_FILES (signal.h INCLUDE_SIGNAL)
+IF(INCLUDE_SIGNAL)
+ SET(CMAKE_EXTRA_INCLUDE_FILES signal.h)
+ENDIF(INCLUDE_SIGNAL)
+
+CHECK_INCLUDE_FILES (stddef.h HAVE_STDDEF_H)
+
+CHECK_INCLUDE_FILES (stdint.h HAVE_STDINT_H)
+IF(HAVE_STDINT_H)
+ SET(CMAKE_EXTRA_INCLUDE_FILES stdint.h)
+ENDIF(HAVE_STDINT_H)
+
+CHECK_INCLUDE_FILES (stdlib.h HAVE_STDLIB_H)
+CHECK_INCLUDE_FILES (string.h HAVE_STRING_H)
+
+CHECK_INCLUDE_FILES (sys/ioctl.h HAVE_SYS_IOCTL_H)
+CHECK_INCLUDE_FILES (sys/select.h HAVE_SYS_SELECT_H)
+CHECK_INCLUDE_FILES (sys/socket.h HAVE_SYS_SOCKET_H)
+CHECK_INCLUDE_FILES (sys/types.h HAVE_SYS_TYPES_H)
+CHECK_INCLUDE_FILES (sys/stat.h HAVE_SYS_STAT_H)
+CHECK_INCLUDE_FILES (sys/un.h HAVE_SYS_UN_H)
+CHECK_INCLUDE_FILES (unistd.h HAVE_UNISTD_H)
+
+IF(APPLE)
+ SET(CMAKE_REQUIRED_DEFINITIONS -D_XOPEN_SOURCE=600)
+ENDIF()
+CHECK_INCLUDE_FILES (ucontext.h HAVE_FILE_UCONTEXT_H)
+IF(NOT HAVE_FILE_UCONTEXT_H)
+ CHECK_INCLUDE_FILES (sys/ucontext.h HAVE_FILE_UCONTEXT_H)
+ENDIF()
diff --git a/libmariadb/cmake/check_types.cmake b/libmariadb/cmake/check_types.cmake
new file mode 100644
index 00000000..3ecedb15
--- /dev/null
+++ b/libmariadb/cmake/check_types.cmake
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+# This file is included by CMakeLists.txt and
+# checks for type sizes.
+# You will find the appropriate defines in
+# include/my_config.h.in
+INCLUDE (CheckTypeSize)
+
+SET(CMAKE_EXTRA_INCLUDE_FILES signal.h)
+
+CHECK_TYPE_SIZE("char *" SIZEOF_CHARP)
+CHECK_TYPE_SIZE(int SIZEOF_INT)
+CHECK_TYPE_SIZE(long SIZEOF_LONG)
+CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
+SET(CMAKE_EXTRA_INCLUDE_FILES stdio.h)
+CHECK_TYPE_SIZE(size_t SIZEOF_SIZE_T)
+SET(CMAKE_EXTRA_INCLUDE_FILES sys/types.h)
+CHECK_TYPE_SIZE(uint SIZEOF_UINT)
+CHECK_TYPE_SIZE(uint SIZEOF_USHORT)
+CHECK_TYPE_SIZE(ulong SIZEOF_ULONG)
+CHECK_TYPE_SIZE(int8 SIZEOF_INT8)
+CHECK_TYPE_SIZE(uint8 SIZEOF_UINT8)
+CHECK_TYPE_SIZE(int16 SIZEOF_INT16)
+CHECK_TYPE_SIZE(uint16 SIZEOF_UINT16)
+CHECK_TYPE_SIZE(int32 SIZEOF_INT32)
+CHECK_TYPE_SIZE(uint32 SIZEOF_UINT32)
+CHECK_TYPE_SIZE(int64 SIZEOF_INT64)
+CHECK_TYPE_SIZE(uint64 SIZEOF_UINT64)
+CHECK_TYPE_SIZE(socklen_t SIZEOF_SOCKLEN_T)
+
+#
+# Compile testing
+#
+INCLUDE (CheckCSourceCompiles)
+
+#
+# SOCKET_SIZE
+#
+IF(WIN32)
+ SET(SOCKET_SIZE_TYPE int)
+ELSE(WIN32)
+ FOREACH(CHECK_TYPE "socklen_t" "size_t" "int")
+ IF (NOT SOCKET_SIZE_TYPE)
+ CHECK_C_SOURCE_COMPILES("
+ #include <sys/socket.h>
+ int main(int argc, char **argv)
+ {
+ getsockname(0, 0, (${CHECK_TYPE} *)0);
+ return 0;
+ }"
+ SOCKET_SIZE_FOUND_${CHECK_TYPE})
+ IF(SOCKET_SIZE_FOUND_${CHECK_TYPE})
+ SET(SOCKET_SIZE_TYPE ${CHECK_TYPE})
+ ENDIF(SOCKET_SIZE_FOUND_${CHECK_TYPE})
+ ENDIF (NOT SOCKET_SIZE_TYPE)
+ ENDFOREACH()
+ENDIF(WIN32)
diff --git a/libmariadb/cmake/export.cmake b/libmariadb/cmake/export.cmake
new file mode 100644
index 00000000..5ae2b74f
--- /dev/null
+++ b/libmariadb/cmake/export.cmake
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+MACRO(CREATE_EXPORT_FILE op outfile version symbols alias_version)
+ IF(WIN32)
+ SET(EXPORT_CONTENT "EXPORTS\n")
+ FOREACH(exp_symbol ${symbols})
+ SET(EXPORT_CONTENT ${EXPORT_CONTENT} "${exp_symbol}\n")
+ ENDFOREACH()
+ ELSE()
+ SET(EXPORT_CONTENT "VERSION {\n${version} {\nglobal:\n")
+ FOREACH(exp_symbol ${symbols})
+ SET(EXPORT_CONTENT "${EXPORT_CONTENT} ${exp_symbol}\\;\n")
+ ENDFOREACH()
+ SET(EXPORT_CONTENT "${EXPORT_CONTENT}local:\n *\\;\n}\\;\n")
+ IF ("${alias_version}" STRGREATER "")
+ SET(EXPORT_CONTENT "${EXPORT_CONTENT}${alias_version} {\n}\\;\n}\\;\n")
+ FOREACH(exp_symbol ${symbols})
+ SET(EXPORT_CONTENT "${EXPORT_CONTENT}\"${exp_symbol}@${alias_version}\" = ${exp_symbol}\\;\n")
+ ENDFOREACH()
+ ELSE()
+ SET(EXPORT_CONTENT "${EXPORT_CONTENT}}\\;\n")
+ ENDIF()
+ ENDIF()
+ FILE(${op} ${CMAKE_CURRENT_BINARY_DIR}/${outfile} ${EXPORT_CONTENT})
+ENDMACRO()
diff --git a/libmariadb/cmake/install.cmake b/libmariadb/cmake/install.cmake
new file mode 100644
index 00000000..90bae8b5
--- /dev/null
+++ b/libmariadb/cmake/install.cmake
@@ -0,0 +1,160 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+
+#
+# This file contains settings for the following layouts:
+#
+# - RPM
+# Built with default prefix=/usr
+#
+#
+# The following va+riables are used and can be overwritten
+#
+# INSTALL_LAYOUT installation layout (DEFAULT = standard for tar.gz and zip packages
+# RPM packages
+#
+# INSTALL_BINDIR location of binaries (mariadb_config)
+# INSTALL_LIBDIR location of libraries
+# INSTALL_PLUGINDIR location of plugins
+# INSTALL_MANDIR location of manpages
+
+IF(NOT INSTALL_LAYOUT)
+ SET(INSTALL_LAYOUT "DEFAULT")
+ENDIF()
+
+SET(INSTALL_LAYOUT ${INSTALL_LAYOUT} CACHE
+ STRING "Installation layout. Currently supported options are DEFAULT (tar.gz and zip), RPM and DEB")
+
+# On Windows we only provide zip and .msi. Latter one uses a different packager.
+IF(UNIX)
+ IF(INSTALL_LAYOUT MATCHES "RPM")
+ SET(libmariadb_prefix "/usr")
+ ELSEIF(INSTALL_LAYOUT MATCHES "DEFAULT|DEB")
+ SET(libmariadb_prefix ${CMAKE_INSTALL_PREFIX})
+ ENDIF()
+ENDIF()
+
+IF(CMAKE_DEFAULT_PREFIX_INITIALIZED_BY_DEFAULT)
+ SET(CMAKE_DEFAULT_PREFIX ${libmariadb_prefix} CACHE PATH "Installation prefix" FORCE)
+ENDIF()
+
+# check if the specified installation layout is valid
+SET(VALID_INSTALL_LAYOUTS "DEFAULT" "RPM" "DEB")
+LIST(FIND VALID_INSTALL_LAYOUTS "${INSTALL_LAYOUT}" layout_no)
+IF(layout_no EQUAL -1)
+ MESSAGE(FATAL_ERROR "Invalid installation layout ${INSTALL_LAYOUT}. Please specify one of the following layouts: ${VALID_INSTALL_LAYOUTS}")
+ENDIF()
+
+
+
+#
+# Todo: We don't generate man pages yet, will fix it
+# later (webhelp to man transformation)
+#
+
+#
+# DEFAULT layout
+#
+
+SET(INSTALL_BINDIR_DEFAULT "bin")
+SET(INSTALL_LIBDIR_DEFAULT "lib/mariadb")
+SET(INSTALL_PCDIR_DEFAULT "lib/pkgconfig")
+SET(INSTALL_INCLUDEDIR_DEFAULT "include/mariadb")
+SET(INSTALL_DOCDIR_DEFAULT "docs")
+SET(INSTALL_MANDIR_DEFAULT "man")
+IF(NOT IS_SUBPROJECT)
+ SET(INSTALL_PLUGINDIR_DEFAULT "lib/mariadb/plugin")
+ELSE()
+ENDIF()
+SET(LIBMARIADB_STATIC_DEFAULT "mariadbclient")
+#
+# RPM layout
+#
+SET(INSTALL_BINDIR_RPM "bin")
+IF((CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "s390x") AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ SET(INSTALL_LIBDIR_RPM "lib64/mariadb")
+ SET(INSTALL_PCDIR_RPM "lib64/pkgconfig")
+ SET(INSTALL_PLUGINDIR_RPM "lib64/mariadb/plugin")
+ELSE()
+ SET(INSTALL_LIBDIR_RPM "lib/mariadb")
+ SET(INSTALL_PCDIR_RPM "lib/pkgconfig")
+ SET(INSTALL_PLUGINDIR_RPM "lib/mariadb/plugin")
+ENDIF()
+SET(INSTALL_INCLUDEDIR_RPM "include")
+SET(INSTALL_DOCDIR_RPM "docs")
+SET(INSTALL_MANDIR_RPM "share/man")
+SET(LIBMARIADB_STATIC_RPM "mariadbclient")
+
+#
+# DEB layout
+#
+SET(INSTALL_BINDIR_DEB "bin")
+SET(INSTALL_LIBDIR_DEB "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
+SET(INSTALL_PCDIR_DEB "lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig")
+SET(INSTALL_PLUGINDIR_DEB "${INSTALL_LIBDIR_DEB}/libmariadb${CPACK_PACKAGE_VERSION_MAJOR}/plugin")
+SET(INSTALL_INCLUDEDIR_DEB "include/mariadb")
+SET(INSTALL_MANDIR_DEB "share/man")
+SET(LIBMARIADB_STATIC_DEB "mariadb")
+
+IF(INSTALL_LAYOUT MATCHES "DEB")
+ SET(INSTALL_PLUGINDIR_CLIENT ${INSTALL_PLUGINDIR_DEB})
+ENDIF()
+
+
+#
+# Overwrite defaults
+#
+IF(INSTALL_LIBDIR)
+ SET(INSTALL_LIBDIR_${INSTALL_LAYOUT} ${INSTALL_LIBDIR})
+ENDIF()
+
+IF(INSTALL_PCDIR)
+ SET(INSTALL_PCDIR_${INSTALL_LAYOUT} ${INSTALL_PCDIR})
+ENDIF()
+
+IF(INSTALL_PLUGINDIR)
+ SET(INSTALL_PLUGINDIR_${INSTALL_LAYOUT} ${INSTALL_PLUGINDIR})
+ENDIF()
+
+# Extra INSTALL_PLUGINDIR_CLIENT that overrides any INSTALL_PLUGINDIR override
+IF(INSTALL_PLUGINDIR_CLIENT)
+ SET(INSTALL_PLUGINDIR_${INSTALL_LAYOUT} ${INSTALL_PLUGINDIR_CLIENT})
+ENDIF()
+
+IF(INSTALL_INCLUDEDIR)
+ SET(INSTALL_INCLUDEDIR_${INSTALL_LAYOUT} ${INSTALL_INCLUDEDIR})
+ENDIF()
+
+IF(INSTALL_BINDIR)
+ SET(INSTALL_BINDIR_${INSTALL_LAYOUT} ${INSTALL_BINDIR})
+ENDIF()
+
+IF(INSTALL_MANDIR)
+ SET(INSTALL_MANDIR_${INSTALL_LAYOUT} ${INSTALL_MANDIR})
+ENDIF()
+
+IF(NOT INSTALL_PREFIXDIR)
+ SET(INSTALL_PREFIXDIR_${INSTALL_LAYOUT} ${libmariadb_prefix})
+ELSE()
+ SET(INSTALL_PREFIXDIR_${INSTALL_LAYOUT} ${INSTALL_PREFIXDIR})
+ENDIF()
+
+IF(DEFINED INSTALL_SUFFIXDIR)
+ SET(INSTALL_SUFFIXDIR_${INSTALL_LAYOUT} ${INSTALL_SUFFIXDIR})
+ENDIF()
+
+FOREACH(dir "BIN" "LIB" "PC" "INCLUDE" "DOCS" "PLUGIN" "MAN")
+ SET(INSTALL_${dir}DIR ${INSTALL_${dir}DIR_${INSTALL_LAYOUT}})
+ MARK_AS_ADVANCED(INSTALL_${dir}DIR)
+ MESSAGE1(INSTALL_${dir}DIR "MariaDB Connector C: INSTALL_${dir}DIR=${INSTALL_${dir}DIR}")
+ENDFOREACH()
+
+SET(LIBMARIADB_STATIC_NAME ${LIBMARIADB_STATIC_${INSTALL_LAYOUT}})
+MARK_AS_ADVANCED(LIBMARIADB_STATIC_NAME)
+
+MESSAGE1(LIBMARIADB_STATIC_NAME "MariaDB Connector C: LIBMARIADB_STATIC_NAME ${LIBMARIADB_STATIC_NAME}")
diff --git a/libmariadb/cmake/install_plugins.cmake b/libmariadb/cmake/install_plugins.cmake
new file mode 100644
index 00000000..b8d15ba1
--- /dev/null
+++ b/libmariadb/cmake/install_plugins.cmake
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+# plugin installation
+
+MACRO(INSTALL_PLUGIN name binary_dir)
+ INSTALL(TARGETS ${name} COMPONENT ClientPlugins DESTINATION ${INSTALL_PLUGINDIR})
+ IF(MSVC)
+ INSTALL(FILES $<TARGET_PDB_FILE:${name}> COMPONENT Debuginfo
+ DESTINATION symbols CONFIGURATIONS Debug RelWithDebInfo)
+ ENDIF()
+ IF(WIN32)
+ FILE(APPEND ${CC_BINARY_DIR}/win/packaging/plugin.conf "<File Id=\"${name}.dll\" Name=\"${name}.dll\" DiskId=\"1\" Source=\"${binary_dir}/${CMAKE_BUILD_TYPE}/${name}.dll\"/>\n")
+ FILE(APPEND ${CC_BINARY_DIR}/win/packaging/plugin.conf "<File Id=\"${name}.pdb\" Name=\"${name}.pdb\" DiskId=\"1\" Source=\"${binary_dir}/${CMAKE_BUILD_TYPE}/${name}.pdb\"/>\n")
+ ENDIF()
+ENDMACRO()
diff --git a/libmariadb/cmake/libressl_version.c b/libmariadb/cmake/libressl_version.c
new file mode 100644
index 00000000..cceac8c3
--- /dev/null
+++ b/libmariadb/cmake/libressl_version.c
@@ -0,0 +1,7 @@
+#include <openssl/opensslv.h>
+#include <stdio.h>
+
+int main()
+{
+ printf("%s", LIBRESSL_VERSION_TEXT);
+}
diff --git a/libmariadb/cmake/linux_x86_toolchain.cmake b/libmariadb/cmake/linux_x86_toolchain.cmake
new file mode 100644
index 00000000..13e0b994
--- /dev/null
+++ b/libmariadb/cmake/linux_x86_toolchain.cmake
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+# toolchain file for building a 32bit version on a 64bit host
+
+# Usage:
+# cmake -DCMAKE_TOOLCHAIN_FILE=linux_86.toolchain.cmake
+
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_VERSION 1)
+set(CMAKE_SYSTEM_PROCESSOR "i686")
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32" CACHE STRING "c++ flags")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32" CACHE STRING "c flags")
diff --git a/libmariadb/cmake/misc.cmake b/libmariadb/cmake/misc.cmake
new file mode 100644
index 00000000..0b7149b2
--- /dev/null
+++ b/libmariadb/cmake/misc.cmake
@@ -0,0 +1,13 @@
+IF ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_LESS "2.8.7")
+ FUNCTION(MESSAGE1 id out)
+ MESSAGE(STATUS "${out}")
+ ENDFUNCTION()
+ELSE()
+ FUNCTION(MESSAGE1 id out)
+ STRING(MD5 hash "${out}")
+ IF(NOT __msg1_${id} STREQUAL "${hash}")
+ MESSAGE(STATUS "${out}")
+ ENDIF()
+ SET(__msg1_${id} ${hash} CACHE INTERNAL "")
+ ENDFUNCTION()
+ENDIF()
diff --git a/libmariadb/cmake/plugins.cmake b/libmariadb/cmake/plugins.cmake
new file mode 100644
index 00000000..1f321b14
--- /dev/null
+++ b/libmariadb/cmake/plugins.cmake
@@ -0,0 +1,94 @@
+#
+# Copyright (C) 2013-2018 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+# plugin configuration
+
+include(${CC_SOURCE_DIR}/cmake/install_plugins.cmake)
+include(${CC_SOURCE_DIR}/cmake/sign.cmake)
+
+FUNCTION(REGISTER_PLUGIN)
+
+ SET(one_value_keywords TARGET DEFAULT TYPE)
+ SET(multi_value_keywords CONFIGURATIONS SOURCES LIBRARIES INCLUDES COMPILE_OPTIONS)
+
+ cmake_parse_arguments(CC_PLUGIN
+ "${options}"
+ "${one_value_keywords}"
+ "${multi_value_keywords}"
+ ${ARGN})
+
+ # overwrite default if it was specified with cmake option
+ string(TOUPPER ${CC_PLUGIN_TARGET} cc_plugin)
+ if(NOT "${CLIENT_PLUGIN_${cc_plugin}}" STREQUAL "")
+ SET(CC_PLUGIN_DEFAULT ${CLIENT_PLUGIN_${cc_plugin}})
+ endif()
+
+ # use uppercase
+ string(TOUPPER ${CC_PLUGIN_TARGET} target_name)
+ string(TOUPPER "${CC_PLUGIN_CONFIGURATIONS}" CC_PLUGIN_CONFIGURATIONS)
+
+ if(NOT ${PLUGIN_${target_name}} STREQUAL "")
+ string(TOUPPER ${PLUGIN_${target_name}} PLUGIN_${target_name})
+ set(CC_PLUGIN_DEFAULT ${PLUGIN_${target_name}})
+ endif()
+
+# check if default value is valid
+ string(TOUPPER ${CC_PLUGIN_DEFAULT} CC_PLUGIN_DEFAULT)
+ list(FIND CC_PLUGIN_CONFIGURATIONS ${CC_PLUGIN_DEFAULT} configuration_found)
+ if(${configuration_found} EQUAL -1)
+ message(FATAL_ERROR "Invalid plugin type ${CC_PLUGIN_DEFAULT}. Allowed plugin types are ${CC_PLUGIN_CONFIGURATIONS}")
+ endif()
+
+ if(NOT ${CC_PLUGIN_DEFAULT} STREQUAL "OFF")
+ set(PLUGIN_${CC_PLUGIN_TARGET}_TYPE ${CC_PLUGIN_TYPE})
+
+ if(${CC_PLUGIN_DEFAULT} STREQUAL "DYNAMIC")
+
+ set(PLUGINS_DYNAMIC ${PLUGINS_DYNAMIC} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
+ if(WIN32)
+ set(target ${CC_PLUGIN_TARGET})
+ set(FILE_TYPE "VFT_DLL")
+ set(FILE_DESCRIPTION "MariaDB client plugin")
+ set(FILE_VERSION ${CPACK_PACKAGE_VERSION})
+ set(ORIGINAL_FILE_NAME "${target}.dll")
+ configure_file(${CC_SOURCE_DIR}/win/resource.rc.in
+ ${CC_BINARY_DIR}/win/${target}.rc
+ @ONLY)
+ set(CC_PLUGIN_SOURCES ${CC_PLUGIN_SOURCES} ${CC_BINARY_DIR}/win/${target}.rc ${CC_SOURCE_DIR}/plugins/plugin.def)
+ endif()
+ add_library(${CC_PLUGIN_TARGET} MODULE ${CC_PLUGIN_SOURCES})
+ target_link_libraries(${CC_PLUGIN_TARGET} ${CC_PLUGIN_LIBRARIES})
+ set_target_properties(${CC_PLUGIN_TARGET} PROPERTIES PREFIX "")
+ set_target_properties(${CC_PLUGIN_TARGET}
+ PROPERTIES COMPILE_FLAGS
+ "-DPLUGIN_DYNAMIC=1 ${CC_PLUGIN_COMPILE_OPTIONS}")
+ if (NOT "${CC_PLUGIN_INCLUDES}" STREQUAL "")
+ if(CMAKE_VERSION VERSION_LESS 2.8.11)
+ include_directories(${CC_PLUGIN_INCLUDES})
+ else()
+ target_include_directories(${CC_PLUGIN_TARGET} PRIVATE ${CC_PLUGIN_INCLUDES})
+ endif()
+ endif()
+ if (${CC_TARGET_COMPILE_OPTIONS})
+ target_compile_options(${CC_PLUGIN_TARGET} ${CC_TARGET_COMPILE_OPTIONS})
+ endif()
+
+ if(WIN32)
+ SIGN_TARGET(${target})
+ endif()
+ INSTALL_PLUGIN(${CC_PLUGIN_TARGET} ${CMAKE_CURRENT_BINARY_DIR})
+ elseif(${CC_PLUGIN_DEFAULT} STREQUAL "STATIC")
+ set(PLUGINS_STATIC ${PLUGINS_STATIC} ${CC_PLUGIN_TARGET} PARENT_SCOPE)
+ set(LIBMARIADB_PLUGIN_CFLAGS ${LIBMARIADB_PLUGIN_CFLAGS} ${CC_PLUGIN_COMPILE_OPTIONS} PARENT_SCOPE)
+ set(LIBMARIADB_PLUGIN_INCLUDES ${LIBMARIADB_PLUGIN_INCLUDES} ${CC_PLUGIN_INCLUDES} PARENT_SCOPE)
+ set(LIBMARIADB_PLUGIN_SOURCES ${LIBMARIADB_PLUGIN_SOURCES} ${CC_PLUGIN_SOURCES} PARENT_SCOPE)
+ set(LIBMARIADB_PLUGIN_LIBS ${LIBMARIADB_PLUGIN_LIBS} ${CC_PLUGIN_LIBRARIES} PARENT_SCOPE)
+ endif()
+ else()
+ set(PLUGINS_OFF ${PLUGINS_OFF} ${CC_PLUGIN_TARGET})
+ endif()
+endfunction()
diff --git a/libmariadb/cmake/sign.cmake b/libmariadb/cmake/sign.cmake
new file mode 100644
index 00000000..7d694118
--- /dev/null
+++ b/libmariadb/cmake/sign.cmake
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+IF(COMMAND SIGN_TARGET)
+ # Do not override server's SIGN_TARGET macro
+ RETURN()
+ENDIF()
+
+MACRO(SIGN_TARGET target)
+ IF(WITH_SIGNCODE)
+ IF(WIN32)
+ SET(target_file $<TARGET_FILE:${target}>)
+ ADD_CUSTOM_COMMAND(TARGET ${target} COMMAND signtool ARGS sign ${SIGN_OPTIONS} ${target_file})
+ ENDIF()
+ ENDIF()
+ENDMACRO()
diff --git a/libmariadb/cmake/symlink.cmake b/libmariadb/cmake/symlink.cmake
new file mode 100644
index 00000000..c1c883d1
--- /dev/null
+++ b/libmariadb/cmake/symlink.cmake
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+MACRO(create_symlink symlink_name target install_path)
+# According to cmake documentation symlinks work on unix systems only
+IF(UNIX)
+ # Get target components
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name}
+ COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${symlink_name}
+ COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink $<TARGET_FILE_NAME:${target}> ${symlink_name}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${target}
+ )
+
+ ADD_CUSTOM_TARGET(SYM_${symlink_name}
+ ALL
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name})
+ SET_TARGET_PROPERTIES(SYM_${symlink_name} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
+
+ IF(CMAKE_GENERATOR MATCHES "Xcode")
+ # For Xcode, replace project config with install config
+ STRING(REPLACE "${CMAKE_CFG_INTDIR}"
+ "\${CMAKE_INSTALL_CONFIG_NAME}" output ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name})
+ ENDIF()
+
+ # presumably this will be used for libmysql*.so symlinks
+ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${symlink_name} DESTINATION ${install_path}
+ COMPONENT Development)
+ENDIF()
+ENDMACRO()
diff --git a/libmariadb/cmake/version_info.cmake b/libmariadb/cmake/version_info.cmake
new file mode 100644
index 00000000..ca0716da
--- /dev/null
+++ b/libmariadb/cmake/version_info.cmake
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2013-2016 MariaDB Corporation AB
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the COPYING-CMAKE-SCRIPTS file.
+#
+FUNCTION(GET_FILE_VERSION FILE_NAME FILE_VERSION)
+
+ # if we build from a git repository, we calculate the file version:
+ # Patch number is number of commits for given file
+ IF(GIT_EXECUTABLE AND EXISTS ${CC_SOURCE_DIR}/.git)
+ EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} --git-dir=${CC_SOURCE_DIR}/.git --work-tree=${CC_SOURCE_DIR} rev-list HEAD --count -- ${FILE_NAME}
+ OUTPUT_VARIABLE FV)
+ STRING(REPLACE "\n" "" FV ${FV})
+ SET(${FILE_VERSION} ${FV} PARENT_SCOPE)
+ ELSE()
+ SET(${FILE_VERSION} 0)
+ ENDIF()
+ENDFUNCTION()
+
+MACRO(SET_VERSION_INFO)
+ SET(FILE_VERSION "0")
+ FOREACH(PROPERTY ${ARGN})
+ IF(${PROPERTY} MATCHES "TARGET:")
+ STRING(REGEX REPLACE "^[TARGET:\\s]" "" TARGET ${PROPERTY})
+ ELSEIF(${PROPERTY} MATCHES "FILE_TYPE:")
+ STRING(REGEX REPLACE "^[FILE_TYPE:\\s]" "" FILE_TYPE ${PROPERTY})
+ ELSEIF(${PROPERTY} MATCHES "ORIGINAL_FILE_NAME:")
+ STRING(REGEX REPLACE "^[ORIGINAL_FILE_NAME:\\s]" "" ORIGINAL_FILE_NAME ${PROPERTY})
+ ELSEIF(${PROPERTY} MATCHES "SOURCE_FILE:")
+ STRING(REGEX REPLACE "^[SOURCE_FILE:\\s]" "" SOURCE ${PROPERTY})
+ GET_FILE_VERSION(${SOURCE} FILE_VERSION)
+ ELSEIF(${PROPERTY} MATCHES "FILE_DESCRIPTION:")
+ STRING(REPLACE "FILE_DESCRIPTION:" "" FILE_DESCRIPTION ${PROPERTY})
+ ENDIF()
+ ENDFOREACH()
+ CONFIGURE_FILE(${CC_SOURCE_DIR}/win/resource.rc.in
+ ${CC_BINARY_DIR}/win/${TARGET}.rc)
+ SET(${TARGET}_RC ${CC_BINARY_DIR}/win/${TARGET}.rc)
+ENDMACRO()
+
+
+
diff --git a/libmariadb/external/zlib/CMakeLists.txt b/libmariadb/external/zlib/CMakeLists.txt
new file mode 100644
index 00000000..360f9fe8
--- /dev/null
+++ b/libmariadb/external/zlib/CMakeLists.txt
@@ -0,0 +1,151 @@
+cmake_minimum_required(VERSION 2.4.4)
+set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
+
+project(zlib C)
+
+set(VERSION "1.2.13")
+
+set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
+set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
+set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
+set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
+set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
+
+include(CheckTypeSize)
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckCSourceCompiles)
+enable_testing()
+
+check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(stddef.h HAVE_STDDEF_H)
+
+#
+# Check to see if we have large file support
+#
+set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
+# We add these other definitions here because CheckTypeSize.cmake
+# in CMake 2.4.x does not automatically do so and we want
+# compatibility with CMake 2.4.x.
+if(HAVE_SYS_TYPES_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
+endif()
+if(HAVE_STDINT_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
+endif()
+if(HAVE_STDDEF_H)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
+endif()
+check_type_size(off64_t OFF64_T)
+if(HAVE_OFF64_T)
+ add_definitions(-D_LARGEFILE64_SOURCE=1)
+endif()
+set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
+
+#
+# Check for fseeko
+#
+check_function_exists(fseeko HAVE_FSEEKO)
+if(NOT HAVE_FSEEKO)
+ add_definitions(-DNO_FSEEKO)
+endif()
+
+#
+# Check for unistd.h
+#
+check_include_file(unistd.h Z_HAVE_UNISTD_H)
+
+if(MSVC)
+ set(CMAKE_DEBUG_POSTFIX "d")
+ add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
+ add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+endif()
+
+if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ # If we're doing an out of source build and the user has a zconf.h
+ # in their source tree...
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
+ message(STATUS "Renaming")
+ message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
+ message(STATUS "to 'zconf.h.included' because this file is included with zlib")
+ message(STATUS "but CMake generates it automatically in the build directory.")
+ file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
+ endif()
+endif()
+
+set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
+configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
+ ${ZLIB_PC} @ONLY)
+configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
+ ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
+
+
+#============================================================================
+# zlib
+#============================================================================
+
+set(ZLIB_PUBLIC_HDRS
+ ${CMAKE_CURRENT_BINARY_DIR}/zconf.h
+ zlib.h
+)
+set(ZLIB_PRIVATE_HDRS
+ crc32.h
+ deflate.h
+ gzguts.h
+ inffast.h
+ inffixed.h
+ inflate.h
+ inftrees.h
+ trees.h
+ zutil.h
+)
+set(ZLIB_SRCS
+ adler32.c
+ compress.c
+ crc32.c
+ deflate.c
+ gzclose.c
+ gzlib.c
+ gzread.c
+ gzwrite.c
+ inflate.c
+ infback.c
+ inftrees.c
+ inffast.c
+ trees.c
+ uncompr.c
+ zutil.c
+)
+
+if(NOT MINGW)
+ set(ZLIB_DLL_SRCS
+ win32/zlib1.rc # If present will override custom build rule below.
+ )
+endif()
+
+# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
+file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
+string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
+ "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
+
+if(MINGW)
+ # This gets us DLL resource information when compiling on MinGW.
+ if(NOT CMAKE_RC_COMPILER)
+ set(CMAKE_RC_COMPILER windres.exe)
+ endif()
+
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
+ COMMAND ${CMAKE_RC_COMPILER}
+ -D GCC_WINDRES
+ -I ${CMAKE_CURRENT_SOURCE_DIR}
+ -I ${CMAKE_CURRENT_BINARY_DIR}
+ -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
+ -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
+ set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
+endif(MINGW)
+
+add_library(zlib STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+
diff --git a/libmariadb/external/zlib/ChangeLog b/libmariadb/external/zlib/ChangeLog
new file mode 100644
index 00000000..f0b0e618
--- /dev/null
+++ b/libmariadb/external/zlib/ChangeLog
@@ -0,0 +1,1578 @@
+
+ ChangeLog file for zlib
+
+Changes in 1.2.12 (27 Mar 2022)
+- Cygwin does not have _wopen(), so do not create gzopen_w() there
+- Permit a deflateParams() parameter change as soon as possible
+- Limit hash table inserts after switch from stored deflate
+- Fix bug when window full in deflate_stored()
+- Fix CLEAR_HASH macro to be usable as a single statement
+- Avoid a conversion error in gzseek when off_t type too small
+- Have Makefile return non-zero error code on test failure
+- Avoid some conversion warnings in gzread.c and gzwrite.c
+- Update use of errno for newer Windows CE versions
+- Small speedup to inflate [psumbera]
+- Return an error if the gzputs string length can't fit in an int
+- Add address checking in clang to -w option of configure
+- Don't compute check value for raw inflate if asked to validate
+- Handle case where inflateSync used when header never processed
+- Avoid the use of ptrdiff_t
+- Avoid an undefined behavior of memcpy() in gzappend()
+- Avoid undefined behaviors of memcpy() in gz*printf()
+- Avoid an undefined behavior of memcpy() in _tr_stored_block()
+- Make the names in functions declarations identical to definitions
+- Remove old assembler code in which bugs have manifested
+- Fix deflateEnd() to not report an error at start of raw deflate
+- Add legal disclaimer to README
+- Emphasize the need to continue decompressing gzip members
+- Correct the initialization requirements for deflateInit2()
+- Fix a bug that can crash deflate on some input when using Z_FIXED
+- Assure that the number of bits for deflatePrime() is valid
+- Use a structure to make globals in enough.c evident
+- Use a macro for the printf format of big_t in enough.c
+- Clean up code style in enough.c, update version
+- Use inline function instead of macro for index in enough.c
+- Clarify that prefix codes are counted in enough.c
+- Show all the codes for the maximum tables size in enough.c
+- Add gznorm.c example, which normalizes gzip files
+- Fix the zran.c example to work on a multiple-member gzip file
+- Add tables for crc32_combine(), to speed it up by a factor of 200
+- Add crc32_combine_gen() and crc32_combine_op() for fast combines
+- Speed up software CRC-32 computation by a factor of 1.5 to 3
+- Use atomic test and set, if available, for dynamic CRC tables
+- Don't bother computing check value after successful inflateSync()
+- Correct comment in crc32.c
+- Add use of the ARMv8 crc32 instructions when requested
+- Use ARM crc32 instructions if the ARM architecture has them
+- Explicitly note that the 32-bit check values are 32 bits
+- Avoid adding empty gzip member after gzflush with Z_FINISH
+- Fix memory leak on error in gzlog.c
+- Fix error in comment on the polynomial representation of a byte
+- Clarify gz* function interfaces, referring to parameter names
+- Change macro name in inflate.c to avoid collision in VxWorks
+- Correct typo in blast.c
+- Improve portability of contrib/minizip
+- Fix indentation in minizip's zip.c
+- Replace black/white with allow/block. (theresa-m)
+- minizip warning fix if MAXU32 already defined. (gvollant)
+- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner)
+- Clean up minizip to reduce warnings for testing
+- Add fallthrough comments for gcc
+- Eliminate use of ULL constants
+- Separate out address sanitizing from warnings in configure
+- Remove destructive aspects of make distclean
+- Check for cc masquerading as gcc or clang in configure
+- Fix crc32.c to compile local functions only if used
+
+Changes in 1.2.11 (15 Jan 2017)
+- Fix deflate stored bug when pulling last block from window
+- Permit immediate deflateParams changes before any deflate input
+
+Changes in 1.2.10 (2 Jan 2017)
+- Avoid warnings on snprintf() return value
+- Fix bug in deflate_stored() for zero-length input
+- Fix bug in gzwrite.c that produced corrupt gzip files
+- Remove files to be installed before copying them in Makefile.in
+- Add warnings when compiling with assembler code
+
+Changes in 1.2.9 (31 Dec 2016)
+- Fix contrib/minizip to permit unzipping with desktop API [Zouzou]
+- Improve contrib/blast to return unused bytes
+- Assure that gzoffset() is correct when appending
+- Improve compress() and uncompress() to support large lengths
+- Fix bug in test/example.c where error code not saved
+- Remedy Coverity warning [Randers-Pehrson]
+- Improve speed of gzprintf() in transparent mode
+- Fix inflateInit2() bug when windowBits is 16 or 32
+- Change DEBUG macro to ZLIB_DEBUG
+- Avoid uninitialized access by gzclose_w()
+- Allow building zlib outside of the source directory
+- Fix bug that accepted invalid zlib header when windowBits is zero
+- Fix gzseek() problem on MinGW due to buggy _lseeki64 there
+- Loop on write() calls in gzwrite.c in case of non-blocking I/O
+- Add --warn (-w) option to ./configure for more compiler warnings
+- Reject a window size of 256 bytes if not using the zlib wrapper
+- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE
+- Add --debug (-d) option to ./configure to define ZLIB_DEBUG
+- Fix bugs in creating a very large gzip header
+- Add uncompress2() function, which returns the input size used
+- Assure that deflateParams() will not switch functions mid-block
+- Dramatically speed up deflation for level 0 (storing)
+- Add gzfread(), duplicating the interface of fread()
+- Add gzfwrite(), duplicating the interface of fwrite()
+- Add deflateGetDictionary() function
+- Use snprintf() for later versions of Microsoft C
+- Fix *Init macros to use z_ prefix when requested
+- Replace as400 with os400 for OS/400 support [Monnerat]
+- Add crc32_z() and adler32_z() functions with size_t lengths
+- Update Visual Studio project files [AraHaan]
+
+Changes in 1.2.8 (28 Apr 2013)
+- Update contrib/minizip/iowin32.c for Windows RT [Vollant]
+- Do not force Z_CONST for C++
+- Clean up contrib/vstudio [Roß]
+- Correct spelling error in zlib.h
+- Fix mixed line endings in contrib/vstudio
+
+Changes in 1.2.7.3 (13 Apr 2013)
+- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc
+
+Changes in 1.2.7.2 (13 Apr 2013)
+- Change check for a four-byte type back to hexadecimal
+- Fix typo in win32/Makefile.msc
+- Add casts in gzwrite.c for pointer differences
+
+Changes in 1.2.7.1 (24 Mar 2013)
+- Replace use of unsafe string functions with snprintf if available
+- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink]
+- Fix gzgetc undefine when Z_PREFIX set [Turk]
+- Eliminate use of mktemp in Makefile (not always available)
+- Fix bug in 'F' mode for gzopen()
+- Add inflateGetDictionary() function
+- Correct comment in deflate.h
+- Use _snprintf for snprintf in Microsoft C
+- On Darwin, only use /usr/bin/libtool if libtool is not Apple
+- Delete "--version" file if created by "ar --version" [Richard G.]
+- Fix configure check for veracity of compiler error return codes
+- Fix CMake compilation of static lib for MSVC2010 x64
+- Remove unused variable in infback9.c
+- Fix argument checks in gzlog_compress() and gzlog_write()
+- Clean up the usage of z_const and respect const usage within zlib
+- Clean up examples/gzlog.[ch] comparisons of different types
+- Avoid shift equal to bits in type (caused endless loop)
+- Fix uninitialized value bug in gzputc() introduced by const patches
+- Fix memory allocation error in examples/zran.c [Nor]
+- Fix bug where gzopen(), gzclose() would write an empty file
+- Fix bug in gzclose() when gzwrite() runs out of memory
+- Check for input buffer malloc failure in examples/gzappend.c
+- Add note to contrib/blast to use binary mode in stdio
+- Fix comparisons of differently signed integers in contrib/blast
+- Check for invalid code length codes in contrib/puff
+- Fix serious but very rare decompression bug in inftrees.c
+- Update inflateBack() comments, since inflate() can be faster
+- Use underscored I/O function names for WINAPI_FAMILY
+- Add _tr_flush_bits to the external symbols prefixed by --zprefix
+- Add contrib/vstudio/vc10 pre-build step for static only
+- Quote --version-script argument in CMakeLists.txt
+- Don't specify --version-script on Apple platforms in CMakeLists.txt
+- Fix casting error in contrib/testzlib/testzlib.c
+- Fix types in contrib/minizip to match result of get_crc_table()
+- Simplify contrib/vstudio/vc10 with 'd' suffix
+- Add TOP support to win32/Makefile.msc
+- Suport i686 and amd64 assembler builds in CMakeLists.txt
+- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h
+- Add vc11 and vc12 build files to contrib/vstudio
+- Add gzvprintf() as an undocumented function in zlib
+- Fix configure for Sun shell
+- Remove runtime check in configure for four-byte integer type
+- Add casts and consts to ease user conversion to C++
+- Add man pages for minizip and miniunzip
+- In Makefile uninstall, don't rm if preceding cd fails
+- Do not return Z_BUF_ERROR if deflateParam() has nothing to write
+
+Changes in 1.2.7 (2 May 2012)
+- Replace use of memmove() with a simple copy for portability
+- Test for existence of strerror
+- Restore gzgetc_ for backward compatibility with 1.2.6
+- Fix build with non-GNU make on Solaris
+- Require gcc 4.0 or later on Mac OS X to use the hidden attribute
+- Include unistd.h for Watcom C
+- Use __WATCOMC__ instead of __WATCOM__
+- Do not use the visibility attribute if NO_VIZ defined
+- Improve the detection of no hidden visibility attribute
+- Avoid using __int64 for gcc or solo compilation
+- Cast to char * in gzprintf to avoid warnings [Zinser]
+- Fix make_vms.com for VAX [Zinser]
+- Don't use library or built-in byte swaps
+- Simplify test and use of gcc hidden attribute
+- Fix bug in gzclose_w() when gzwrite() fails to allocate memory
+- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen()
+- Fix bug in test/minigzip.c for configure --solo
+- Fix contrib/vstudio project link errors [Mohanathas]
+- Add ability to choose the builder in make_vms.com [Schweda]
+- Add DESTDIR support to mingw32 win32/Makefile.gcc
+- Fix comments in win32/Makefile.gcc for proper usage
+- Allow overriding the default install locations for cmake
+- Generate and install the pkg-config file with cmake
+- Build both a static and a shared version of zlib with cmake
+- Include version symbols for cmake builds
+- If using cmake with MSVC, add the source directory to the includes
+- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta]
+- Move obsolete emx makefile to old [Truta]
+- Allow the use of -Wundef when compiling or using zlib
+- Avoid the use of the -u option with mktemp
+- Improve inflate() documentation on the use of Z_FINISH
+- Recognize clang as gcc
+- Add gzopen_w() in Windows for wide character path names
+- Rename zconf.h in CMakeLists.txt to move it out of the way
+- Add source directory in CMakeLists.txt for building examples
+- Look in build directory for zlib.pc in CMakeLists.txt
+- Remove gzflags from zlibvc.def in vc9 and vc10
+- Fix contrib/minizip compilation in the MinGW environment
+- Update ./configure for Solaris, support --64 [Mooney]
+- Remove -R. from Solaris shared build (possible security issue)
+- Avoid race condition for parallel make (-j) running example
+- Fix type mismatch between get_crc_table() and crc_table
+- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler]
+- Fix the path to zlib.map in CMakeLists.txt
+- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe]
+- Add instructions to win32/Makefile.gcc for shared install [Torri]
+
+Changes in 1.2.6.1 (12 Feb 2012)
+- Avoid the use of the Objective-C reserved name "id"
+- Include io.h in gzguts.h for Microsoft compilers
+- Fix problem with ./configure --prefix and gzgetc macro
+- Include gz_header definition when compiling zlib solo
+- Put gzflags() functionality back in zutil.c
+- Avoid library header include in crc32.c for Z_SOLO
+- Use name in GCC_CLASSIC as C compiler for coverage testing, if set
+- Minor cleanup in contrib/minizip/zip.c [Vollant]
+- Update make_vms.com [Zinser]
+- Remove unnecessary gzgetc_ function
+- Use optimized byte swap operations for Microsoft and GNU [Snyder]
+- Fix minor typo in zlib.h comments [Rzesniowiecki]
+
+Changes in 1.2.6 (29 Jan 2012)
+- Update the Pascal interface in contrib/pascal
+- Fix function numbers for gzgetc_ in zlibvc.def files
+- Fix configure.ac for contrib/minizip [Schiffer]
+- Fix large-entry detection in minizip on 64-bit systems [Schiffer]
+- Have ./configure use the compiler return code for error indication
+- Fix CMakeLists.txt for cross compilation [McClure]
+- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes]
+- Fix compilation of contrib/minizip on FreeBSD [Marquez]
+- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath]
+- Include io.h for Turbo C / Borland C on all platforms [Truta]
+- Make version explicit in contrib/minizip/configure.ac [Bosmans]
+- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant]
+- Minor cleanup up contrib/minizip/unzip.c [Vollant]
+- Fix bug when compiling minizip with C++ [Vollant]
+- Protect for long name and extra fields in contrib/minizip [Vollant]
+- Avoid some warnings in contrib/minizip [Vollant]
+- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip
+- Add missing libs to minizip linker command
+- Add support for VPATH builds in contrib/minizip
+- Add an --enable-demos option to contrib/minizip/configure
+- Add the generation of configure.log by ./configure
+- Exit when required parameters not provided to win32/Makefile.gcc
+- Have gzputc return the character written instead of the argument
+- Use the -m option on ldconfig for BSD systems [Tobias]
+- Correct in zlib.map when deflateResetKeep was added
+
+Changes in 1.2.5.3 (15 Jan 2012)
+- Restore gzgetc function for binary compatibility
+- Do not use _lseeki64 under Borland C++ [Truta]
+- Update win32/Makefile.msc to build test/*.c [Truta]
+- Remove old/visualc6 given CMakefile and other alternatives
+- Update AS400 build files and documentation [Monnerat]
+- Update win32/Makefile.gcc to build test/*.c [Truta]
+- Permit stronger flushes after Z_BLOCK flushes
+- Avoid extraneous empty blocks when doing empty flushes
+- Permit Z_NULL arguments to deflatePending
+- Allow deflatePrime() to insert bits in the middle of a stream
+- Remove second empty static block for Z_PARTIAL_FLUSH
+- Write out all of the available bits when using Z_BLOCK
+- Insert the first two strings in the hash table after a flush
+
+Changes in 1.2.5.2 (17 Dec 2011)
+- fix ld error: unable to find version dependency 'ZLIB_1.2.5'
+- use relative symlinks for shared libs
+- Avoid searching past window for Z_RLE strategy
+- Assure that high-water mark initialization is always applied in deflate
+- Add assertions to fill_window() in deflate.c to match comments
+- Update python link in README
+- Correct spelling error in gzread.c
+- Fix bug in gzgets() for a concatenated empty gzip stream
+- Correct error in comment for gz_make()
+- Change gzread() and related to ignore junk after gzip streams
+- Allow gzread() and related to continue after gzclearerr()
+- Allow gzrewind() and gzseek() after a premature end-of-file
+- Simplify gzseek() now that raw after gzip is ignored
+- Change gzgetc() to a macro for speed (~40% speedup in testing)
+- Fix gzclose() to return the actual error last encountered
+- Always add large file support for windows
+- Include zconf.h for windows large file support
+- Include zconf.h.cmakein for windows large file support
+- Update zconf.h.cmakein on make distclean
+- Merge vestigial vsnprintf determination from zutil.h to gzguts.h
+- Clarify how gzopen() appends in zlib.h comments
+- Correct documentation of gzdirect() since junk at end now ignored
+- Add a transparent write mode to gzopen() when 'T' is in the mode
+- Update python link in zlib man page
+- Get inffixed.h and MAKEFIXED result to match
+- Add a ./config --solo option to make zlib subset with no library use
+- Add undocumented inflateResetKeep() function for CAB file decoding
+- Add --cover option to ./configure for gcc coverage testing
+- Add #define ZLIB_CONST option to use const in the z_stream interface
+- Add comment to gzdopen() in zlib.h to use dup() when using fileno()
+- Note behavior of uncompress() to provide as much data as it can
+- Add files in contrib/minizip to aid in building libminizip
+- Split off AR options in Makefile.in and configure
+- Change ON macro to Z_ARG to avoid application conflicts
+- Facilitate compilation with Borland C++ for pragmas and vsnprintf
+- Include io.h for Turbo C / Borland C++
+- Move example.c and minigzip.c to test/
+- Simplify incomplete code table filling in inflate_table()
+- Remove code from inflate.c and infback.c that is impossible to execute
+- Test the inflate code with full coverage
+- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw)
+- Add deflateResetKeep and fix inflateResetKeep to retain dictionary
+- Fix gzwrite.c to accommodate reduced memory zlib compilation
+- Have inflate() with Z_FINISH avoid the allocation of a window
+- Do not set strm->adler when doing raw inflate
+- Fix gzeof() to behave just like feof() when read is not past end of file
+- Fix bug in gzread.c when end-of-file is reached
+- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF
+- Document gzread() capability to read concurrently written files
+- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo]
+
+Changes in 1.2.5.1 (10 Sep 2011)
+- Update FAQ entry on shared builds (#13)
+- Avoid symbolic argument to chmod in Makefile.in
+- Fix bug and add consts in contrib/puff [Oberhumer]
+- Update contrib/puff/zeros.raw test file to have all block types
+- Add full coverage test for puff in contrib/puff/Makefile
+- Fix static-only-build install in Makefile.in
+- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno]
+- Add libz.a dependency to shared in Makefile.in for parallel builds
+- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out
+- Replace $(...) with `...` in configure for non-bash sh [Bowler]
+- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen]
+- Add solaris* to Linux* in configure to allow gcc use [Groffen]
+- Add *bsd* to Linux* case in configure [Bar-Lev]
+- Add inffast.obj to dependencies in win32/Makefile.msc
+- Correct spelling error in deflate.h [Kohler]
+- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc
+- Add test to configure for GNU C looking for gcc in output of $cc -v
+- Add zlib.pc generation to win32/Makefile.gcc [Weigelt]
+- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not
+- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense
+- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser)
+- Make stronger test in zconf.h to include unistd.h for LFS
+- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack]
+- Fix zlib.h LFS support when Z_PREFIX used
+- Add updated as400 support (removed from old) [Monnerat]
+- Avoid deflate sensitivity to volatile input data
+- Avoid division in adler32_combine for NO_DIVIDE
+- Clarify the use of Z_FINISH with deflateBound() amount of space
+- Set binary for output file in puff.c
+- Use u4 type for crc_table to avoid conversion warnings
+- Apply casts in zlib.h to avoid conversion warnings
+- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller]
+- Improve inflateSync() documentation to note indeterminancy
+- Add deflatePending() function to return the amount of pending output
+- Correct the spelling of "specification" in FAQ [Randers-Pehrson]
+- Add a check in configure for stdarg.h, use for gzprintf()
+- Check that pointers fit in ints when gzprint() compiled old style
+- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler]
+- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt]
+- Add debug records in assmebler code [Londer]
+- Update RFC references to use http://tools.ietf.org/html/... [Li]
+- Add --archs option, use of libtool to configure for Mac OS X [Borstel]
+
+Changes in 1.2.5 (19 Apr 2010)
+- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev]
+- Default to libdir as sharedlibdir in configure [Nieder]
+- Update copyright dates on modified source files
+- Update trees.c to be able to generate modified trees.h
+- Exit configure for MinGW, suggesting win32/Makefile.gcc
+- Check for NULL path in gz_open [Homurlu]
+
+Changes in 1.2.4.5 (18 Apr 2010)
+- Set sharedlibdir in configure [Torok]
+- Set LDFLAGS in Makefile.in [Bar-Lev]
+- Avoid mkdir objs race condition in Makefile.in [Bowler]
+- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays
+- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C
+- Don't use hidden attribute when it is a warning generator (e.g. Solaris)
+
+Changes in 1.2.4.4 (18 Apr 2010)
+- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok]
+- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty
+- Try to use bash or ksh regardless of functionality of /bin/sh
+- Fix configure incompatibility with NetBSD sh
+- Remove attempt to run under bash or ksh since have better NetBSD fix
+- Fix win32/Makefile.gcc for MinGW [Bar-Lev]
+- Add diagnostic messages when using CROSS_PREFIX in configure
+- Added --sharedlibdir option to configure [Weigelt]
+- Use hidden visibility attribute when available [Frysinger]
+
+Changes in 1.2.4.3 (10 Apr 2010)
+- Only use CROSS_PREFIX in configure for ar and ranlib if they exist
+- Use CROSS_PREFIX for nm [Bar-Lev]
+- Assume _LARGEFILE64_SOURCE defined is equivalent to true
+- Avoid use of undefined symbols in #if with && and ||
+- Make *64 prototypes in gzguts.h consistent with functions
+- Add -shared load option for MinGW in configure [Bowler]
+- Move z_off64_t to public interface, use instead of off64_t
+- Remove ! from shell test in configure (not portable to Solaris)
+- Change +0 macro tests to -0 for possibly increased portability
+
+Changes in 1.2.4.2 (9 Apr 2010)
+- Add consistent carriage returns to readme.txt's in masmx86 and masmx64
+- Really provide prototypes for *64 functions when building without LFS
+- Only define unlink() in minigzip.c if unistd.h not included
+- Update README to point to contrib/vstudio project files
+- Move projects/vc6 to old/ and remove projects/
+- Include stdlib.h in minigzip.c for setmode() definition under WinCE
+- Clean up assembler builds in win32/Makefile.msc [Rowe]
+- Include sys/types.h for Microsoft for off_t definition
+- Fix memory leak on error in gz_open()
+- Symbolize nm as $NM in configure [Weigelt]
+- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt]
+- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined
+- Fix bug in gzeof() to take into account unused input data
+- Avoid initialization of structures with variables in puff.c
+- Updated win32/README-WIN32.txt [Rowe]
+
+Changes in 1.2.4.1 (28 Mar 2010)
+- Remove the use of [a-z] constructs for sed in configure [gentoo 310225]
+- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech]
+- Restore "for debugging" comment on sprintf() in gzlib.c
+- Remove fdopen for MVS from gzguts.h
+- Put new README-WIN32.txt in win32 [Rowe]
+- Add check for shell to configure and invoke another shell if needed
+- Fix big fat stinking bug in gzseek() on uncompressed files
+- Remove vestigial F_OPEN64 define in zutil.h
+- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE
+- Avoid errors on non-LFS systems when applications define LFS macros
+- Set EXE to ".exe" in configure for MINGW [Kahle]
+- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill]
+- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev]
+- Add DLL install in win32/makefile.gcc [Bar-Lev]
+- Allow Linux* or linux* from uname in configure [Bar-Lev]
+- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev]
+- Add cross-compilation prefixes to configure [Bar-Lev]
+- Match type exactly in gz_load() invocation in gzread.c
+- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func
+- Provide prototypes for *64 functions when building zlib without LFS
+- Don't use -lc when linking shared library on MinGW
+- Remove errno.h check in configure and vestigial errno code in zutil.h
+
+Changes in 1.2.4 (14 Mar 2010)
+- Fix VER3 extraction in configure for no fourth subversion
+- Update zlib.3, add docs to Makefile.in to make .pdf out of it
+- Add zlib.3.pdf to distribution
+- Don't set error code in gzerror() if passed pointer is NULL
+- Apply destination directory fixes to CMakeLists.txt [Lowman]
+- Move #cmakedefine's to a new zconf.in.cmakein
+- Restore zconf.h for builds that don't use configure or cmake
+- Add distclean to dummy Makefile for convenience
+- Update and improve INDEX, README, and FAQ
+- Update CMakeLists.txt for the return of zconf.h [Lowman]
+- Update contrib/vstudio/vc9 and vc10 [Vollant]
+- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc
+- Apply license and readme changes to contrib/asm686 [Raiter]
+- Check file name lengths and add -c option in minigzip.c [Li]
+- Update contrib/amd64 and contrib/masmx86/ [Vollant]
+- Avoid use of "eof" parameter in trees.c to not shadow library variable
+- Update make_vms.com for removal of zlibdefs.h [Zinser]
+- Update assembler code and vstudio projects in contrib [Vollant]
+- Remove outdated assembler code contrib/masm686 and contrib/asm586
+- Remove old vc7 and vc8 from contrib/vstudio
+- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe]
+- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open()
+- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant]
+- Remove *64 functions from win32/zlib.def (they're not 64-bit yet)
+- Fix bug in void-returning vsprintf() case in gzwrite.c
+- Fix name change from inflate.h in contrib/inflate86/inffas86.c
+- Check if temporary file exists before removing in make_vms.com [Zinser]
+- Fix make install and uninstall for --static option
+- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta]
+- Update readme.txt in contrib/masmx64 and masmx86 to assemble
+
+Changes in 1.2.3.9 (21 Feb 2010)
+- Expunge gzio.c
+- Move as400 build information to old
+- Fix updates in contrib/minizip and contrib/vstudio
+- Add const to vsnprintf test in configure to avoid warnings [Weigelt]
+- Delete zconf.h (made by configure) [Weigelt]
+- Change zconf.in.h to zconf.h.in per convention [Weigelt]
+- Check for NULL buf in gzgets()
+- Return empty string for gzgets() with len == 1 (like fgets())
+- Fix description of gzgets() in zlib.h for end-of-file, NULL return
+- Update minizip to 1.1 [Vollant]
+- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c
+- Note in zlib.h that gzerror() should be used to distinguish from EOF
+- Remove use of snprintf() from gzlib.c
+- Fix bug in gzseek()
+- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant]
+- Fix zconf.h generation in CMakeLists.txt [Lowman]
+- Improve comments in zconf.h where modified by configure
+
+Changes in 1.2.3.8 (13 Feb 2010)
+- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer]
+- Use z_off64_t in gz_zero() and gz_skip() to match state->skip
+- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t)
+- Revert to Makefile.in from 1.2.3.6 (live with the clutter)
+- Fix missing error return in gzflush(), add zlib.h note
+- Add *64 functions to zlib.map [Levin]
+- Fix signed/unsigned comparison in gz_comp()
+- Use SFLAGS when testing shared linking in configure
+- Add --64 option to ./configure to use -m64 with gcc
+- Fix ./configure --help to correctly name options
+- Have make fail if a test fails [Levin]
+- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson]
+- Remove assembler object files from contrib
+
+Changes in 1.2.3.7 (24 Jan 2010)
+- Always gzopen() with O_LARGEFILE if available
+- Fix gzdirect() to work immediately after gzopen() or gzdopen()
+- Make gzdirect() more precise when the state changes while reading
+- Improve zlib.h documentation in many places
+- Catch memory allocation failure in gz_open()
+- Complete close operation if seek forward in gzclose_w() fails
+- Return Z_ERRNO from gzclose_r() if close() fails
+- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL
+- Return zero for gzwrite() errors to match zlib.h description
+- Return -1 on gzputs() error to match zlib.h description
+- Add zconf.in.h to allow recovery from configure modification [Weigelt]
+- Fix static library permissions in Makefile.in [Weigelt]
+- Avoid warnings in configure tests that hide functionality [Weigelt]
+- Add *BSD and DragonFly to Linux case in configure [gentoo 123571]
+- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212]
+- Avoid access of uninitialized data for first inflateReset2 call [Gomes]
+- Keep object files in subdirectories to reduce the clutter somewhat
+- Remove default Makefile and zlibdefs.h, add dummy Makefile
+- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_
+- Remove zlibdefs.h completely -- modify zconf.h instead
+
+Changes in 1.2.3.6 (17 Jan 2010)
+- Avoid void * arithmetic in gzread.c and gzwrite.c
+- Make compilers happier with const char * for gz_error message
+- Avoid unused parameter warning in inflate.c
+- Avoid signed-unsigned comparison warning in inflate.c
+- Indent #pragma's for traditional C
+- Fix usage of strwinerror() in glib.c, change to gz_strwinerror()
+- Correct email address in configure for system options
+- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser]
+- Update zlib.map [Brown]
+- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok]
+- Apply various fixes to CMakeLists.txt [Lowman]
+- Add checks on len in gzread() and gzwrite()
+- Add error message for no more room for gzungetc()
+- Remove zlib version check in gzwrite()
+- Defer compression of gzprintf() result until need to
+- Use snprintf() in gzdopen() if available
+- Remove USE_MMAP configuration determination (only used by minigzip)
+- Remove examples/pigz.c (available separately)
+- Update examples/gun.c to 1.6
+
+Changes in 1.2.3.5 (8 Jan 2010)
+- Add space after #if in zutil.h for some compilers
+- Fix relatively harmless bug in deflate_fast() [Exarevsky]
+- Fix same problem in deflate_slow()
+- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown]
+- Add deflate_rle() for faster Z_RLE strategy run-length encoding
+- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding
+- Change name of "write" variable in inffast.c to avoid library collisions
+- Fix premature EOF from gzread() in gzio.c [Brown]
+- Use zlib header window size if windowBits is 0 in inflateInit2()
+- Remove compressBound() call in deflate.c to avoid linking compress.o
+- Replace use of errno in gz* with functions, support WinCE [Alves]
+- Provide alternative to perror() in minigzip.c for WinCE [Alves]
+- Don't use _vsnprintf on later versions of MSVC [Lowman]
+- Add CMake build script and input file [Lowman]
+- Update contrib/minizip to 1.1 [Svensson, Vollant]
+- Moved nintendods directory from contrib to root
+- Replace gzio.c with a new set of routines with the same functionality
+- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above
+- Update contrib/minizip to 1.1b
+- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h
+
+Changes in 1.2.3.4 (21 Dec 2009)
+- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility
+- Update comments in configure and Makefile.in for default --shared
+- Fix test -z's in configure [Marquess]
+- Build examplesh and minigzipsh when not testing
+- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h
+- Import LDFLAGS from the environment in configure
+- Fix configure to populate SFLAGS with discovered CFLAGS options
+- Adapt make_vms.com to the new Makefile.in [Zinser]
+- Add zlib2ansi script for C++ compilation [Marquess]
+- Add _FILE_OFFSET_BITS=64 test to make test (when applicable)
+- Add AMD64 assembler code for longest match to contrib [Teterin]
+- Include options from $SFLAGS when doing $LDSHARED
+- Simplify 64-bit file support by introducing z_off64_t type
+- Make shared object files in objs directory to work around old Sun cc
+- Use only three-part version number for Darwin shared compiles
+- Add rc option to ar in Makefile.in for when ./configure not run
+- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4*
+- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile
+- Protect against _FILE_OFFSET_BITS being defined when compiling zlib
+- Rename Makefile.in targets allstatic to static and allshared to shared
+- Fix static and shared Makefile.in targets to be independent
+- Correct error return bug in gz_open() by setting state [Brown]
+- Put spaces before ;;'s in configure for better sh compatibility
+- Add pigz.c (parallel implementation of gzip) to examples/
+- Correct constant in crc32.c to UL [Leventhal]
+- Reject negative lengths in crc32_combine()
+- Add inflateReset2() function to work like inflateEnd()/inflateInit2()
+- Include sys/types.h for _LARGEFILE64_SOURCE [Brown]
+- Correct typo in doc/algorithm.txt [Janik]
+- Fix bug in adler32_combine() [Zhu]
+- Catch missing-end-of-block-code error in all inflates and in puff
+ Assures that random input to inflate eventually results in an error
+- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/
+- Update ENOUGH and its usage to reflect discovered bounds
+- Fix gzerror() error report on empty input file [Brown]
+- Add ush casts in trees.c to avoid pedantic runtime errors
+- Fix typo in zlib.h uncompress() description [Reiss]
+- Correct inflate() comments with regard to automatic header detection
+- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays)
+- Put new version of gzlog (2.0) in examples with interruption recovery
+- Add puff compile option to permit invalid distance-too-far streams
+- Add puff TEST command options, ability to read piped input
+- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but
+ _LARGEFILE64_SOURCE not defined
+- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart
+- Fix deflateSetDictionary() to use all 32K for output consistency
+- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h)
+- Clear bytes after deflate lookahead to avoid use of uninitialized data
+- Change a limit in inftrees.c to be more transparent to Coverity Prevent
+- Update win32/zlib.def with exported symbols from zlib.h
+- Correct spelling errors in zlib.h [Willem, Sobrado]
+- Allow Z_BLOCK for deflate() to force a new block
+- Allow negative bits in inflatePrime() to delete existing bit buffer
+- Add Z_TREES flush option to inflate() to return at end of trees
+- Add inflateMark() to return current state information for random access
+- Add Makefile for NintendoDS to contrib [Costa]
+- Add -w in configure compile tests to avoid spurious warnings [Beucler]
+- Fix typos in zlib.h comments for deflateSetDictionary()
+- Fix EOF detection in transparent gzread() [Maier]
+
+Changes in 1.2.3.3 (2 October 2006)
+- Make --shared the default for configure, add a --static option
+- Add compile option to permit invalid distance-too-far streams
+- Add inflateUndermine() function which is required to enable above
+- Remove use of "this" variable name for C++ compatibility [Marquess]
+- Add testing of shared library in make test, if shared library built
+- Use ftello() and fseeko() if available instead of ftell() and fseek()
+- Provide two versions of all functions that use the z_off_t type for
+ binary compatibility -- a normal version and a 64-bit offset version,
+ per the Large File Support Extension when _LARGEFILE64_SOURCE is
+ defined; use the 64-bit versions by default when _FILE_OFFSET_BITS
+ is defined to be 64
+- Add a --uname= option to configure to perhaps help with cross-compiling
+
+Changes in 1.2.3.2 (3 September 2006)
+- Turn off silly Borland warnings [Hay]
+- Use off64_t and define _LARGEFILE64_SOURCE when present
+- Fix missing dependency on inffixed.h in Makefile.in
+- Rig configure --shared to build both shared and static [Teredesai, Truta]
+- Remove zconf.in.h and instead create a new zlibdefs.h file
+- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant]
+- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt]
+
+Changes in 1.2.3.1 (16 August 2006)
+- Add watcom directory with OpenWatcom make files [Daniel]
+- Remove #undef of FAR in zconf.in.h for MVS [Fedtke]
+- Update make_vms.com [Zinser]
+- Use -fPIC for shared build in configure [Teredesai, Nicholson]
+- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen]
+- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck]
+- Add some FAQ entries about the contrib directory
+- Update the MVS question in the FAQ
+- Avoid extraneous reads after EOF in gzio.c [Brown]
+- Correct spelling of "successfully" in gzio.c [Randers-Pehrson]
+- Add comments to zlib.h about gzerror() usage [Brown]
+- Set extra flags in gzip header in gzopen() like deflate() does
+- Make configure options more compatible with double-dash conventions
+ [Weigelt]
+- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen]
+- Fix uninstall target in Makefile.in [Truta]
+- Add pkgconfig support [Weigelt]
+- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt]
+- Replace set_data_type() with a more accurate detect_data_type() in
+ trees.c, according to the txtvsbin.txt document [Truta]
+- Swap the order of #include <stdio.h> and #include "zlib.h" in
+ gzio.c, example.c and minigzip.c [Truta]
+- Shut up annoying VS2005 warnings about standard C deprecation [Rowe,
+ Truta] (where?)
+- Fix target "clean" from win32/Makefile.bor [Truta]
+- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe]
+- Update zlib www home address in win32/DLL_FAQ.txt [Truta]
+- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove]
+- Enable browse info in the "Debug" and "ASM Debug" configurations in
+ the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta]
+- Add pkgconfig support [Weigelt]
+- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h,
+ for use in win32/zlib1.rc [Polushin, Rowe, Truta]
+- Add a document that explains the new text detection scheme to
+ doc/txtvsbin.txt [Truta]
+- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta]
+- Move algorithm.txt into doc/ [Truta]
+- Synchronize FAQ with website
+- Fix compressBound(), was low for some pathological cases [Fearnley]
+- Take into account wrapper variations in deflateBound()
+- Set examples/zpipe.c input and output to binary mode for Windows
+- Update examples/zlib_how.html with new zpipe.c (also web site)
+- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems
+ that gcc became pickier in 4.0)
+- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain
+ un-versioned, the patch adds versioning only for symbols introduced in
+ zlib-1.2.0 or later. It also declares as local those symbols which are
+ not designed to be exported." [Levin]
+- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure
+- Do not initialize global static by default in trees.c, add a response
+ NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess]
+- Don't use strerror() in gzio.c under WinCE [Yakimov]
+- Don't use errno.h in zutil.h under WinCE [Yakimov]
+- Move arguments for AR to its usage to allow replacing ar [Marot]
+- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson]
+- Improve inflateInit() and inflateInit2() documentation
+- Fix structure size comment in inflate.h
+- Change configure help option from --h* to --help [Santos]
+
+Changes in 1.2.3 (18 July 2005)
+- Apply security vulnerability fixes to contrib/infback9 as well
+- Clean up some text files (carriage returns, trailing space)
+- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant]
+
+Changes in 1.2.2.4 (11 July 2005)
+- Add inflatePrime() function for starting inflation at bit boundary
+- Avoid some Visual C warnings in deflate.c
+- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
+ compile
+- Fix some spelling errors in comments [Betts]
+- Correct inflateInit2() error return documentation in zlib.h
+- Add zran.c example of compressed data random access to examples
+ directory, shows use of inflatePrime()
+- Fix cast for assignments to strm->state in inflate.c and infback.c
+- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
+- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
+- Add cast in trees.c t avoid a warning [Oberhumer]
+- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
+- Update make_vms.com [Zinser]
+- Initialize state->write in inflateReset() since copied in inflate_fast()
+- Be more strict on incomplete code sets in inflate_table() and increase
+ ENOUGH and MAXD -- this repairs a possible security vulnerability for
+ invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
+ discovering the vulnerability and providing test cases
+- Add ia64 support to configure for HP-UX [Smith]
+- Add error return to gzread() for format or i/o error [Levin]
+- Use malloc.h for OS/2 [Necasek]
+
+Changes in 1.2.2.3 (27 May 2005)
+- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
+- Typecast fread() return values in gzio.c [Vollant]
+- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
+- Fix crc check bug in gzread() after gzungetc() [Heiner]
+- Add the deflateTune() function to adjust internal compression parameters
+- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
+- Remove an incorrect assertion in examples/zpipe.c
+- Add C++ wrapper in infback9.h [Donais]
+- Fix bug in inflateCopy() when decoding fixed codes
+- Note in zlib.h how much deflateSetDictionary() actually uses
+- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
+- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
+- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
+- Add gzdirect() function to indicate transparent reads
+- Update contrib/minizip [Vollant]
+- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
+- Add casts in crc32.c to avoid warnings [Oberhumer]
+- Add contrib/masmx64 [Vollant]
+- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
+
+Changes in 1.2.2.2 (30 December 2004)
+- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
+ avoid implicit memcpy calls (portability for no-library compilation)
+- Increase sprintf() buffer size in gzdopen() to allow for large numbers
+- Add INFLATE_STRICT to check distances against zlib header
+- Improve WinCE errno handling and comments [Chang]
+- Remove comment about no gzip header processing in FAQ
+- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
+- Add updated make_vms.com [Coghlan], update README
+- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
+ fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html
+- Add FAQ entry and comments in deflate.c on uninitialized memory access
+- Add Solaris 9 make options in configure [Gilbert]
+- Allow strerror() usage in gzio.c for STDC
+- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
+- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
+- Use z_off_t for adler32_combine() and crc32_combine() lengths
+- Make adler32() much faster for small len
+- Use OS_CODE in deflate() default gzip header
+
+Changes in 1.2.2.1 (31 October 2004)
+- Allow inflateSetDictionary() call for raw inflate
+- Fix inflate header crc check bug for file names and comments
+- Add deflateSetHeader() and gz_header structure for custom gzip headers
+- Add inflateGetheader() to retrieve gzip headers
+- Add crc32_combine() and adler32_combine() functions
+- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
+- Use zstreamp consistently in zlib.h (inflate_back functions)
+- Remove GUNZIP condition from definition of inflate_mode in inflate.h
+ and in contrib/inflate86/inffast.S [Truta, Anderson]
+- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
+- Update projects/README.projects and projects/visualc6 [Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
+- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
+- Use a new algorithm for setting strm->data_type in trees.c [Truta]
+- Do not define an exit() prototype in zutil.c unless DEBUG defined
+- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
+- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
+- Fix Darwin build version identification [Peterson]
+
+Changes in 1.2.2 (3 October 2004)
+- Update zlib.h comments on gzip in-memory processing
+- Set adler to 1 in inflateReset() to support Java test suite [Walles]
+- Add contrib/dotzlib [Ravn]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update contrib/minizip [Vollant]
+- Move contrib/visual-basic.txt to old/ [Truta]
+- Fix assembler builds in projects/visualc6/ [Truta]
+
+Changes in 1.2.1.2 (9 September 2004)
+- Update INDEX file
+- Fix trees.c to update strm->data_type (no one ever noticed!)
+- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown]
+- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE)
+- Add limited multitasking protection to DYNAMIC_CRC_TABLE
+- Add NO_vsnprintf for VMS in zutil.h [Mozilla]
+- Don't declare strerror() under VMS [Mozilla]
+- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize
+- Update contrib/ada [Anisimkov]
+- Update contrib/minizip [Vollant]
+- Fix configure to not hardcode directories for Darwin [Peterson]
+- Fix gzio.c to not return error on empty files [Brown]
+- Fix indentation; update version in contrib/delphi/ZLib.pas and
+ contrib/pascal/zlibpas.pas [Truta]
+- Update mkasm.bat in contrib/masmx86 [Truta]
+- Update contrib/untgz [Truta]
+- Add projects/README.projects [Truta]
+- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta]
+- Remove an unnecessary assignment to curr in inftrees.c [Truta]
+- Add OS/2 to exe builds in configure [Poltorak]
+- Remove err dummy parameter in zlib.h [Kientzle]
+
+Changes in 1.2.1.1 (9 January 2004)
+- Update email address in README
+- Several FAQ updates
+- Fix a big fat bug in inftrees.c that prevented decoding valid
+ dynamic blocks with only literals and no distance codes --
+ Thanks to "Hot Emu" for the bug report and sample file
+- Add a note to puff.c on no distance codes case
+
+Changes in 1.2.1 (17 November 2003)
+- Remove a tab in contrib/gzappend/gzappend.c
+- Update some interfaces in contrib for new zlib functions
+- Update zlib version number in some contrib entries
+- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
+- Support shared libraries on Hurd and KFreeBSD [Brown]
+- Fix error in NO_DIVIDE option of adler32.c
+
+Changes in 1.2.0.8 (4 November 2003)
+- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas
+- Add experimental NO_DIVIDE #define in adler32.c
+ - Possibly faster on some processors (let me know if it is)
+- Correct Z_BLOCK to not return on first inflate call if no wrap
+- Fix strm->data_type on inflate() return to correctly indicate EOB
+- Add deflatePrime() function for appending in the middle of a byte
+- Add contrib/gzappend for an example of appending to a stream
+- Update win32/DLL_FAQ.txt [Truta]
+- Delete Turbo C comment in README [Truta]
+- Improve some indentation in zconf.h [Truta]
+- Fix infinite loop on bad input in configure script [Church]
+- Fix gzeof() for concatenated gzip files [Johnson]
+- Add example to contrib/visual-basic.txt [Michael B.]
+- Add -p to mkdir's in Makefile.in [vda]
+- Fix configure to properly detect presence or lack of printf functions
+- Add AS400 support [Monnerat]
+- Add a little Cygwin support [Wilson]
+
+Changes in 1.2.0.7 (21 September 2003)
+- Correct some debug formats in contrib/infback9
+- Cast a type in a debug statement in trees.c
+- Change search and replace delimiter in configure from % to # [Beebe]
+- Update contrib/untgz to 0.2 with various fixes [Truta]
+- Add build support for Amiga [Nikl]
+- Remove some directories in old that have been updated to 1.2
+- Add dylib building for Mac OS X in configure and Makefile.in
+- Remove old distribution stuff from Makefile
+- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X
+- Update links in README
+
+Changes in 1.2.0.6 (13 September 2003)
+- Minor FAQ updates
+- Update contrib/minizip to 1.00 [Vollant]
+- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta]
+- Update POSTINC comment for 68060 [Nikl]
+- Add contrib/infback9 with deflate64 decoding (unsupported)
+- For MVS define NO_vsnprintf and undefine FAR [van Burik]
+- Add pragma for fdopen on MVS [van Burik]
+
+Changes in 1.2.0.5 (8 September 2003)
+- Add OF to inflateBackEnd() declaration in zlib.h
+- Remember start when using gzdopen in the middle of a file
+- Use internal off_t counters in gz* functions to properly handle seeks
+- Perform more rigorous check for distance-too-far in inffast.c
+- Add Z_BLOCK flush option to return from inflate at block boundary
+- Set strm->data_type on return from inflate
+ - Indicate bits unused, if at block boundary, and if in last block
+- Replace size_t with ptrdiff_t in crc32.c, and check for correct size
+- Add condition so old NO_DEFLATE define still works for compatibility
+- FAQ update regarding the Windows DLL [Truta]
+- INDEX update: add qnx entry, remove aix entry [Truta]
+- Install zlib.3 into mandir [Wilson]
+- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta]
+- Adapt the zlib interface to the new DLL convention guidelines [Truta]
+- Introduce ZLIB_WINAPI macro to allow the export of functions using
+ the WINAPI calling convention, for Visual Basic [Vollant, Truta]
+- Update msdos and win32 scripts and makefiles [Truta]
+- Export symbols by name, not by ordinal, in win32/zlib.def [Truta]
+- Add contrib/ada [Anisimkov]
+- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta]
+- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant]
+- Add contrib/masm686 [Truta]
+- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm
+ [Truta, Vollant]
+- Update contrib/delphi; rename to contrib/pascal; add example [Truta]
+- Remove contrib/delphi2; add a new contrib/delphi [Truta]
+- Avoid inclusion of the nonstandard <memory.h> in contrib/iostream,
+ and fix some method prototypes [Truta]
+- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip
+ [Truta]
+- Avoid the use of backslash (\) in contrib/minizip [Vollant]
+- Fix file time handling in contrib/untgz; update makefiles [Truta]
+- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines
+ [Vollant]
+- Remove contrib/vstudio/vc15_16 [Vollant]
+- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta]
+- Update README.contrib [Truta]
+- Invert the assignment order of match_head and s->prev[...] in
+ INSERT_STRING [Truta]
+- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings
+ [Truta]
+- Compare function pointers with 0, not with NULL or Z_NULL [Truta]
+- Fix prototype of syncsearch in inflate.c [Truta]
+- Introduce ASMINF macro to be enabled when using an ASM implementation
+ of inflate_fast [Truta]
+- Change NO_DEFLATE to NO_GZCOMPRESS [Truta]
+- Modify test_gzio in example.c to take a single file name as a
+ parameter [Truta]
+- Exit the example.c program if gzopen fails [Truta]
+- Add type casts around strlen in example.c [Truta]
+- Remove casting to sizeof in minigzip.c; give a proper type
+ to the variable compared with SUFFIX_LEN [Truta]
+- Update definitions of STDC and STDC99 in zconf.h [Truta]
+- Synchronize zconf.h with the new Windows DLL interface [Truta]
+- Use SYS16BIT instead of __32BIT__ to distinguish between
+ 16- and 32-bit platforms [Truta]
+- Use far memory allocators in small 16-bit memory models for
+ Turbo C [Truta]
+- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in
+ zlibCompileFlags [Truta]
+- Cygwin has vsnprintf [Wilson]
+- In Windows16, OS_CODE is 0, as in MSDOS [Truta]
+- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson]
+
+Changes in 1.2.0.4 (10 August 2003)
+- Minor FAQ updates
+- Be more strict when checking inflateInit2's windowBits parameter
+- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well
+- Add gzip wrapper option to deflateInit2 using windowBits
+- Add updated QNX rule in configure and qnx directory [Bonnefoy]
+- Make inflate distance-too-far checks more rigorous
+- Clean up FAR usage in inflate
+- Add casting to sizeof() in gzio.c and minigzip.c
+
+Changes in 1.2.0.3 (19 July 2003)
+- Fix silly error in gzungetc() implementation [Vollant]
+- Update contrib/minizip and contrib/vstudio [Vollant]
+- Fix printf format in example.c
+- Correct cdecl support in zconf.in.h [Anisimkov]
+- Minor FAQ updates
+
+Changes in 1.2.0.2 (13 July 2003)
+- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons
+- Attempt to avoid warnings in crc32.c for pointer-int conversion
+- Add AIX to configure, remove aix directory [Bakker]
+- Add some casts to minigzip.c
+- Improve checking after insecure sprintf() or vsprintf() calls
+- Remove #elif's from crc32.c
+- Change leave label to inf_leave in inflate.c and infback.c to avoid
+ library conflicts
+- Remove inflate gzip decoding by default--only enable gzip decoding by
+ special request for stricter backward compatibility
+- Add zlibCompileFlags() function to return compilation information
+- More typecasting in deflate.c to avoid warnings
+- Remove leading underscore from _Capital #defines [Truta]
+- Fix configure to link shared library when testing
+- Add some Windows CE target adjustments [Mai]
+- Remove #define ZLIB_DLL in zconf.h [Vollant]
+- Add zlib.3 [Rodgers]
+- Update RFC URL in deflate.c and algorithm.txt [Mai]
+- Add zlib_dll_FAQ.txt to contrib [Truta]
+- Add UL to some constants [Truta]
+- Update minizip and vstudio [Vollant]
+- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h
+- Expand use of NO_DUMMY_DECL to avoid all dummy structures
+- Added iostream3 to contrib [Schwardt]
+- Replace rewind() with fseek() for WinCE [Truta]
+- Improve setting of zlib format compression level flags
+ - Report 0 for huffman and rle strategies and for level == 0 or 1
+ - Report 2 only for level == 6
+- Only deal with 64K limit when necessary at compile time [Truta]
+- Allow TOO_FAR check to be turned off at compile time [Truta]
+- Add gzclearerr() function [Souza]
+- Add gzungetc() function
+
+Changes in 1.2.0.1 (17 March 2003)
+- Add Z_RLE strategy for run-length encoding [Truta]
+ - When Z_RLE requested, restrict matches to distance one
+ - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
+- Correct FASTEST compilation to allow level == 0
+- Clean up what gets compiled for FASTEST
+- Incorporate changes to zconf.in.h [Vollant]
+ - Refine detection of Turbo C need for dummy returns
+ - Refine ZLIB_DLL compilation
+ - Include additional header file on VMS for off_t typedef
+- Try to use _vsnprintf where it supplants vsprintf [Vollant]
+- Add some casts in inffast.c
+- Enchance comments in zlib.h on what happens if gzprintf() tries to
+ write more than 4095 bytes before compression
+- Remove unused state from inflateBackEnd()
+- Remove exit(0) from minigzip.c, example.c
+- Get rid of all those darn tabs
+- Add "check" target to Makefile.in that does the same thing as "test"
+- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
+- Update contrib/inflate86 [Anderson]
+- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
+- Add msdos and win32 directories with makefiles [Truta]
+- More additions and improvements to the FAQ
+
+Changes in 1.2.0 (9 March 2003)
+- New and improved inflate code
+ - About 20% faster
+ - Does not allocate 32K window unless and until needed
+ - Automatically detects and decompresses gzip streams
+ - Raw inflate no longer needs an extra dummy byte at end
+ - Added inflateBack functions using a callback interface--even faster
+ than inflate, useful for file utilities (gzip, zip)
+ - Added inflateCopy() function to record state for random access on
+ externally generated deflate streams (e.g. in gzip files)
+ - More readable code (I hope)
+- New and improved crc32()
+ - About 50% faster, thanks to suggestions from Rodney Brown
+- Add deflateBound() and compressBound() functions
+- Fix memory leak in deflateInit2()
+- Permit setting dictionary for raw deflate (for parallel deflate)
+- Fix const declaration for gzwrite()
+- Check for some malloc() failures in gzio.c
+- Fix bug in gzopen() on single-byte file 0x1f
+- Fix bug in gzread() on concatenated file with 0x1f at end of buffer
+ and next buffer doesn't start with 0x8b
+- Fix uncompress() to return Z_DATA_ERROR on truncated input
+- Free memory at end of example.c
+- Remove MAX #define in trees.c (conflicted with some libraries)
+- Fix static const's in deflate.c, gzio.c, and zutil.[ch]
+- Declare malloc() and free() in gzio.c if STDC not defined
+- Use malloc() instead of calloc() in zutil.c if int big enough
+- Define STDC for AIX
+- Add aix/ with approach for compiling shared library on AIX
+- Add HP-UX support for shared libraries in configure
+- Add OpenUNIX support for shared libraries in configure
+- Use $cc instead of gcc to build shared library
+- Make prefix directory if needed when installing
+- Correct Macintosh avoidance of typedef Byte in zconf.h
+- Correct Turbo C memory allocation when under Linux
+- Use libz.a instead of -lz in Makefile (assure use of compiled library)
+- Update configure to check for snprintf or vsnprintf functions and their
+ return value, warn during make if using an insecure function
+- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that
+ is lost when library is used--resolution is to build new zconf.h
+- Documentation improvements (in zlib.h):
+ - Document raw deflate and inflate
+ - Update RFCs URL
+ - Point out that zlib and gzip formats are different
+ - Note that Z_BUF_ERROR is not fatal
+ - Document string limit for gzprintf() and possible buffer overflow
+ - Note requirement on avail_out when flushing
+ - Note permitted values of flush parameter of inflate()
+- Add some FAQs (and even answers) to the FAQ
+- Add contrib/inflate86/ for x86 faster inflate
+- Add contrib/blast/ for PKWare Data Compression Library decompression
+- Add contrib/puff/ simple inflate for deflate format description
+
+Changes in 1.1.4 (11 March 2002)
+- ZFREE was repeated on same allocation on some error conditions
+ This creates a security problem described in
+ http://www.zlib.org/advisory-2002-03-11.txt
+- Returned incorrect error (Z_MEM_ERROR) on some invalid data
+- Avoid accesses before window for invalid distances with inflate window
+ less than 32K
+- force windowBits > 8 to avoid a bug in the encoder for a window size
+ of 256 bytes. (A complete fix will be available in 1.1.5)
+
+Changes in 1.1.3 (9 July 1998)
+- fix "an inflate input buffer bug that shows up on rare but persistent
+ occasions" (Mark)
+- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
+- fix gzseek(..., SEEK_SET) in write mode
+- fix crc check after a gzeek (Frank Faubert)
+- fix miniunzip when the last entry in a zip file is itself a zip file
+ (J Lillge)
+- add contrib/asm586 and contrib/asm686 (Brian Raiter)
+ See http://www.muppetlabs.com/~breadbox/software/assembly.html
+- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
+- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
+- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
+- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
+- added a FAQ file
+
+- Support gzdopen on Mac with Metrowerks (Jason Linhart)
+- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
+- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
+- avoid some warnings with Borland C (Tom Tanner)
+- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
+- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant)
+- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
+- use libdir and includedir in Makefile.in (Tim Mooney)
+- support shared libraries on OSF1 V4 (Tim Mooney)
+- remove so_locations in "make clean" (Tim Mooney)
+- fix maketree.c compilation error (Glenn, Mark)
+- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
+- new Makefile.riscos (Rich Walker)
+- initialize static descriptors in trees.c for embedded targets (Nick Smith)
+- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
+- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
+- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
+- fix maketree.c to allow clean compilation of inffixed.h (Mark)
+- fix parameter check in deflateCopy (Gunther Nikl)
+- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
+- Many portability patches by Christian Spieler:
+ . zutil.c, zutil.h: added "const" for zmem*
+ . Make_vms.com: fixed some typos
+ . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
+ . msdos/Makefile.msc: remove "default rtl link library" info from obj files
+ . msdos/Makefile.*: use model-dependent name for the built zlib library
+ . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
+ new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
+- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
+- replace __far with _far for better portability (Christian Spieler, Tom Lane)
+- fix test for errno.h in configure (Tim Newsham)
+
+Changes in 1.1.2 (19 March 98)
+- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
+ See http://www.winimage.com/zLibDll/unzip.html
+- preinitialize the inflate tables for fixed codes, to make the code
+ completely thread safe (Mark)
+- some simplifications and slight speed-up to the inflate code (Mark)
+- fix gzeof on non-compressed files (Allan Schrum)
+- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
+- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
+- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
+- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
+- do not wrap extern "C" around system includes (Tom Lane)
+- mention zlib binding for TCL in README (Andreas Kupries)
+- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
+- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
+- allow "configure --prefix $HOME" (Tim Mooney)
+- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
+- move Makefile.sas to amiga/Makefile.sas
+
+Changes in 1.1.1 (27 Feb 98)
+- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
+- remove block truncation heuristic which had very marginal effect for zlib
+ (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
+ compression ratio on some files. This also allows inlining _tr_tally for
+ matches in deflate_slow
+- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
+
+Changes in 1.1.0 (24 Feb 98)
+- do not return STREAM_END prematurely in inflate (John Bowler)
+- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
+- compile with -DFASTEST to get compression code optimized for speed only
+- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
+- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
+ on Sun but significant on HP)
+
+- add a pointer to experimental unzip library in README (Gilles Vollant)
+- initialize variable gcc in configure (Chris Herborth)
+
+Changes in 1.0.9 (17 Feb 1998)
+- added gzputs and gzgets functions
+- do not clear eof flag in gzseek (Mark Diekhans)
+- fix gzseek for files in transparent mode (Mark Diekhans)
+- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
+- replace EXPORT with ZEXPORT to avoid conflict with other programs
+- added compress2 in zconf.h, zlib.def, zlib.dnt
+- new asm code from Gilles Vollant in contrib/asm386
+- simplify the inflate code (Mark):
+ . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
+ . ZALLOC the length list in inflate_trees_fixed() instead of using stack
+ . ZALLOC the value area for huft_build() instead of using stack
+ . Simplify Z_FINISH check in inflate()
+
+- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
+- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
+- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
+ the declaration of FAR (Gilles VOllant)
+- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
+- read_buf buf parameter of type Bytef* instead of charf*
+- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
+- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
+- fix check for presence of directories in "make install" (Ian Willis)
+
+Changes in 1.0.8 (27 Jan 1998)
+- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
+- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
+- added compress2() to allow setting the compression level
+- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
+- use constant arrays for the static trees in trees.c instead of computing
+ them at run time (thanks to Ken Raeburn for this suggestion). To create
+ trees.h, compile with GEN_TREES_H and run "make test"
+- check return code of example in "make test" and display result
+- pass minigzip command line options to file_compress
+- simplifying code of inflateSync to avoid gcc 2.8 bug
+
+- support CC="gcc -Wall" in configure -s (QingLong)
+- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
+- fix test for shared library support to avoid compiler warnings
+- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
+- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
+- do not use fdopen for Metrowerks on Mac (Brad Pettit))
+- add checks for gzputc and gzputc in example.c
+- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
+- use const for the CRC table (Ken Raeburn)
+- fixed "make uninstall" for shared libraries
+- use Tracev instead of Trace in infblock.c
+- in example.c use correct compressed length for test_sync
+- suppress +vnocompatwarnings in configure for HPUX (not always supported)
+
+Changes in 1.0.7 (20 Jan 1998)
+- fix gzseek which was broken in write mode
+- return error for gzseek to negative absolute position
+- fix configure for Linux (Chun-Chung Chen)
+- increase stack space for MSC (Tim Wegner)
+- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
+- define EXPORTVA for gzprintf (Gilles Vollant)
+- added man page zlib.3 (Rick Rodgers)
+- for contrib/untgz, fix makedir() and improve Makefile
+
+- check gzseek in write mode in example.c
+- allocate extra buffer for seeks only if gzseek is actually called
+- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
+- add inflateSyncPoint in zconf.h
+- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
+
+Changes in 1.0.6 (19 Jan 1998)
+- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
+ gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
+- Fix a deflate bug occurring only with compression level 0 (thanks to
+ Andy Buckler for finding this one)
+- In minigzip, pass transparently also the first byte for .Z files
+- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
+- check Z_FINISH in inflate (thanks to Marc Schluper)
+- Implement deflateCopy (thanks to Adam Costello)
+- make static libraries by default in configure, add --shared option
+- move MSDOS or Windows specific files to directory msdos
+- suppress the notion of partial flush to simplify the interface
+ (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
+- suppress history buffer provided by application to simplify the interface
+ (this feature was not implemented anyway in 1.0.4)
+- next_in and avail_in must be initialized before calling inflateInit or
+ inflateInit2
+- add EXPORT in all exported functions (for Windows DLL)
+- added Makefile.nt (thanks to Stephen Williams)
+- added the unsupported "contrib" directory:
+ contrib/asm386/ by Gilles Vollant <info@winimage.com>
+ 386 asm code replacing longest_match()
+ contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
+ A C++ I/O streams interface to the zlib gz* functions
+ contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
+ Another C++ I/O streams interface
+ contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
+ A very simple tar.gz file extractor using zlib
+ contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
+ How to use compress(), uncompress() and the gz* functions from VB
+- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
+ level) in minigzip (thanks to Tom Lane)
+
+- use const for rommable constants in deflate
+- added test for gzseek and gztell in example.c
+- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
+- add undocumented function zError to convert error code to string
+ (for Tim Smithers)
+- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code
+- Use default memcpy for Symantec MSDOS compiler
+- Add EXPORT keyword for check_func (needed for Windows DLL)
+- add current directory to LD_LIBRARY_PATH for "make test"
+- create also a link for libz.so.1
+- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
+- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
+- added -soname for Linux in configure (Chun-Chung Chen,
+- assign numbers to the exported functions in zlib.def (for Windows DLL)
+- add advice in zlib.h for best usage of deflateSetDictionary
+- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
+- allow compilation with ANSI keywords only enabled for TurboC in large model
+- avoid "versionString"[0] (Borland bug)
+- add NEED_DUMMY_RETURN for Borland
+- use variable z_verbose for tracing in debug mode (L. Peter Deutsch)
+- allow compilation with CC
+- defined STDC for OS/2 (David Charlap)
+- limit external names to 8 chars for MVS (Thomas Lund)
+- in minigzip.c, use static buffers only for 16-bit systems
+- fix suffix check for "minigzip -d foo.gz"
+- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
+- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
+- added makelcc.bat for lcc-win32 (Tom St Denis)
+- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
+- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion
+- check for unistd.h in configure (for off_t)
+- remove useless check parameter in inflate_blocks_free
+- avoid useless assignment of s->check to itself in inflate_blocks_new
+- do not flush twice in gzclose (thanks to Ken Raeburn)
+- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
+- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
+- work around buggy fclose on pipes for HP/UX
+- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
+- fix configure if CC is already equal to gcc
+
+Changes in 1.0.5 (3 Jan 98)
+- Fix inflate to terminate gracefully when fed corrupted or invalid data
+- Use const for rommable constants in inflate
+- Eliminate memory leaks on error conditions in inflate
+- Removed some vestigial code in inflate
+- Update web address in README
+
+Changes in 1.0.4 (24 Jul 96)
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+ bit, so the decompressor could decompress all the correct data but went
+ on to attempt decompressing extra garbage data. This affected minigzip too
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+- use z_error only for DEBUG (avoid problem with DLLs)
+
+Changes in 1.0.3 (2 Jul 96)
+- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
+ small and medium models; this makes the library incompatible with previous
+ versions for these models. (No effect in large model or on other systems.)
+- return OK instead of BUF_ERROR if previous deflate call returned with
+ avail_out as zero but there is nothing to do
+- added memcmp for non STDC compilers
+- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
+- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
+- better check for 16-bit mode MSC (avoids problem with Symantec)
+
+Changes in 1.0.2 (23 May 96)
+- added Windows DLL support
+- added a function zlibVersion (for the DLL support)
+- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
+- Bytef is define's instead of typedef'd only for Borland C
+- avoid reading uninitialized memory in example.c
+- mention in README that the zlib format is now RFC1950
+- updated Makefile.dj2
+- added algorithm.doc
+
+Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
+- fix array overlay in deflate.c which sometimes caused bad compressed data
+- fix inflate bug with empty stored block
+- fix MSDOS medium model which was broken in 0.99
+- fix deflateParams() which could generate bad compressed data
+- Bytef is define'd instead of typedef'ed (work around Borland bug)
+- added an INDEX file
+- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
+ Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
+- speed up adler32 for modern machines without auto-increment
+- added -ansi for IRIX in configure
+- static_init_done in trees.c is an int
+- define unlink as delete for VMS
+- fix configure for QNX
+- add configure branch for SCO and HPUX
+- avoid many warnings (unused variables, dead assignments, etc...)
+- no fdopen for BeOS
+- fix the Watcom fix for 32 bit mode (define FAR as empty)
+- removed redefinition of Byte for MKWERKS
+- work around an MWKERKS bug (incorrect merge of all .h files)
+
+Changes in 0.99 (27 Jan 96)
+- allow preset dictionary shared between compressor and decompressor
+- allow compression level 0 (no compression)
+- add deflateParams in zlib.h: allow dynamic change of compression level
+ and compression strategy
+- test large buffers and deflateParams in example.c
+- add optional "configure" to build zlib as a shared library
+- suppress Makefile.qnx, use configure instead
+- fixed deflate for 64-bit systems (detected on Cray)
+- fixed inflate_blocks for 64-bit systems (detected on Alpha)
+- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
+- always return Z_BUF_ERROR when deflate() has nothing to do
+- deflateInit and inflateInit are now macros to allow version checking
+- prefix all global functions and types with z_ with -DZ_PREFIX
+- make falloc completely reentrant (inftrees.c)
+- fixed very unlikely race condition in ct_static_init
+- free in reverse order of allocation to help memory manager
+- use zlib-1.0/* instead of zlib/* inside the tar.gz
+- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
+ -Wconversion -Wstrict-prototypes -Wmissing-prototypes"
+- allow gzread on concatenated .gz files
+- deflateEnd now returns Z_DATA_ERROR if it was premature
+- deflate is finally (?) fully deterministic (no matches beyond end of input)
+- Document Z_SYNC_FLUSH
+- add uninstall in Makefile
+- Check for __cpluplus in zlib.h
+- Better test in ct_align for partial flush
+- avoid harmless warnings for Borland C++
+- initialize hash_head in deflate.c
+- avoid warning on fdopen (gzio.c) for HP cc -Aa
+- include stdlib.h for STDC compilers
+- include errno.h for Cray
+- ignore error if ranlib doesn't exist
+- call ranlib twice for NeXTSTEP
+- use exec_prefix instead of prefix for libz.a
+- renamed ct_* as _tr_* to avoid conflict with applications
+- clear z->msg in inflateInit2 before any error return
+- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
+- fixed typo in zconf.h (_GNUC__ => __GNUC__)
+- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
+- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
+- in fcalloc, normalize pointer if size > 65520 bytes
+- don't use special fcalloc for 32 bit Borland C++
+- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
+- use Z_BINARY instead of BINARY
+- document that gzclose after gzdopen will close the file
+- allow "a" as mode in gzopen
+- fix error checking in gzread
+- allow skipping .gz extra-field on pipes
+- added reference to Perl interface in README
+- put the crc table in FAR data (I dislike more and more the medium model :)
+- added get_crc_table
+- added a dimension to all arrays (Borland C can't count)
+- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
+- guard against multiple inclusion of *.h (for precompiled header on Mac)
+- Watcom C pretends to be Microsoft C small model even in 32 bit mode
+- don't use unsized arrays to avoid silly warnings by Visual C++:
+ warning C4746: 'inflate_mask' : unsized array treated as '__far'
+ (what's wrong with far data in far model?)
+- define enum out of inflate_blocks_state to allow compilation with C++
+
+Changes in 0.95 (16 Aug 95)
+- fix MSDOS small and medium model (now easier to adapt to any compiler)
+- inlined send_bits
+- fix the final (:-) bug for deflate with flush (output was correct but
+ not completely flushed in rare occasions)
+- default window size is same for compression and decompression
+ (it's now sufficient to set MAX_WBITS in zconf.h)
+- voidp -> voidpf and voidnp -> voidp (for consistency with other
+ typedefs and because voidnp was not near in large model)
+
+Changes in 0.94 (13 Aug 95)
+- support MSDOS medium model
+- fix deflate with flush (could sometimes generate bad output)
+- fix deflateReset (zlib header was incorrectly suppressed)
+- added support for VMS
+- allow a compression level in gzopen()
+- gzflush now calls fflush
+- For deflate with flush, flush even if no more input is provided
+- rename libgz.a as libz.a
+- avoid complex expression in infcodes.c triggering Turbo C bug
+- work around a problem with gcc on Alpha (in INSERT_STRING)
+- don't use inline functions (problem with some gcc versions)
+- allow renaming of Byte, uInt, etc... with #define
+- avoid warning about (unused) pointer before start of array in deflate.c
+- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
+- avoid reserved word 'new' in trees.c
+
+Changes in 0.93 (25 June 95)
+- temporarily disable inline functions
+- make deflate deterministic
+- give enough lookahead for PARTIAL_FLUSH
+- Set binary mode for stdin/stdout in minigzip.c for OS/2
+- don't even use signed char in inflate (not portable enough)
+- fix inflate memory leak for segmented architectures
+
+Changes in 0.92 (3 May 95)
+- don't assume that char is signed (problem on SGI)
+- Clear bit buffer when starting a stored block
+- no memcpy on Pyramid
+- suppressed inftest.c
+- optimized fill_window, put longest_match inline for gcc
+- optimized inflate on stored blocks
+- untabify all sources to simplify patches
+
+Changes in 0.91 (2 May 95)
+- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
+- Document the memory requirements in zconf.h
+- added "make install"
+- fix sync search logic in inflateSync
+- deflate(Z_FULL_FLUSH) now works even if output buffer too short
+- after inflateSync, don't scare people with just "lo world"
+- added support for DJGPP
+
+Changes in 0.9 (1 May 95)
+- don't assume that zalloc clears the allocated memory (the TurboC bug
+ was Mark's bug after all :)
+- let again gzread copy uncompressed data unchanged (was working in 0.71)
+- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
+- added a test of inflateSync in example.c
+- moved MAX_WBITS to zconf.h because users might want to change that
+- document explicitly that zalloc(64K) on MSDOS must return a normalized
+ pointer (zero offset)
+- added Makefiles for Microsoft C, Turbo C, Borland C++
+- faster crc32()
+
+Changes in 0.8 (29 April 95)
+- added fast inflate (inffast.c)
+- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
+ is incompatible with previous versions of zlib which returned Z_OK
+- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
+ (actually that was not a compiler bug, see 0.81 above)
+- gzread no longer reads one extra byte in certain cases
+- In gzio destroy(), don't reference a freed structure
+- avoid many warnings for MSDOS
+- avoid the ERROR symbol which is used by MS Windows
+
+Changes in 0.71 (14 April 95)
+- Fixed more MSDOS compilation problems :( There is still a bug with
+ TurboC large model
+
+Changes in 0.7 (14 April 95)
+- Added full inflate support
+- Simplified the crc32() interface. The pre- and post-conditioning
+ (one's complement) is now done inside crc32(). WARNING: this is
+ incompatible with previous versions; see zlib.h for the new usage
+
+Changes in 0.61 (12 April 95)
+- workaround for a bug in TurboC. example and minigzip now work on MSDOS
+
+Changes in 0.6 (11 April 95)
+- added minigzip.c
+- added gzdopen to reopen a file descriptor as gzFile
+- added transparent reading of non-gziped files in gzread
+- fixed bug in gzread (don't read crc as data)
+- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose)
+- don't allocate big arrays in the stack (for MSDOS)
+- fix some MSDOS compilation problems
+
+Changes in 0.5:
+- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
+ not yet Z_FULL_FLUSH
+- support decompression but only in a single step (forced Z_FINISH)
+- added opaque object for zalloc and zfree
+- added deflateReset and inflateReset
+- added a variable zlib_version for consistency checking
+- renamed the 'filter' parameter of deflateInit2 as 'strategy'
+ Added Z_FILTERED and Z_HUFFMAN_ONLY constants
+
+Changes in 0.4:
+- avoid "zip" everywhere, use zlib instead of ziplib
+- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
+ if compression method == 8
+- added adler32 and crc32
+- renamed deflateOptions as deflateInit2, call one or the other but not both
+- added the method parameter for deflateInit2
+- added inflateInit2
+- simplied considerably deflateInit and inflateInit by not supporting
+ user-provided history buffer. This is supported only in deflateInit2
+ and inflateInit2
+
+Changes in 0.3:
+- prefix all macro names with Z_
+- use Z_FINISH instead of deflateEnd to finish compression
+- added Z_HUFFMAN_ONLY
+- added gzerror()
diff --git a/libmariadb/external/zlib/FAQ b/libmariadb/external/zlib/FAQ
new file mode 100644
index 00000000..99b7cf92
--- /dev/null
+++ b/libmariadb/external/zlib/FAQ
@@ -0,0 +1,368 @@
+
+ Frequently Asked Questions about zlib
+
+
+If your question is not there, please check the zlib home page
+http://zlib.net/ which may have more recent information.
+The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
+
+
+ 1. Is zlib Y2K-compliant?
+
+ Yes. zlib doesn't handle dates.
+
+ 2. Where can I get a Windows DLL version?
+
+ The zlib sources can be compiled without change to produce a DLL. See the
+ file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
+ precompiled DLL are found in the zlib web site at http://zlib.net/ .
+
+ 3. Where can I get a Visual Basic interface to zlib?
+
+ See
+ * http://marknelson.us/1997/01/01/zlib-engine/
+ * win32/DLL_FAQ.txt in the zlib distribution
+
+ 4. compress() returns Z_BUF_ERROR.
+
+ Make sure that before the call of compress(), the length of the compressed
+ buffer is equal to the available size of the compressed buffer and not
+ zero. For Visual Basic, check that this parameter is passed by reference
+ ("as any"), not by value ("as long").
+
+ 5. deflate() or inflate() returns Z_BUF_ERROR.
+
+ Before making the call, make sure that avail_in and avail_out are not zero.
+ When setting the parameter flush equal to Z_FINISH, also make sure that
+ avail_out is big enough to allow processing all pending input. Note that a
+ Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
+ made with more input or output space. A Z_BUF_ERROR may in fact be
+ unavoidable depending on how the functions are used, since it is not
+ possible to tell whether or not there is more output pending when
+ strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a
+ heavily annotated example.
+
+ 6. Where's the zlib documentation (man pages, etc.)?
+
+ It's in zlib.h . Examples of zlib usage are in the files test/example.c
+ and test/minigzip.c, with more in examples/ .
+
+ 7. Why don't you use GNU autoconf or libtool or ...?
+
+ Because we would like to keep zlib as a very small and simple package.
+ zlib is rather portable and doesn't need much configuration.
+
+ 8. I found a bug in zlib.
+
+ Most of the time, such problems are due to an incorrect usage of zlib.
+ Please try to reproduce the problem with a small program and send the
+ corresponding source to us at zlib@gzip.org . Do not send multi-megabyte
+ data files without prior agreement.
+
+ 9. Why do I get "undefined reference to gzputc"?
+
+ If "make test" produces something like
+
+ example.o(.text+0x154): undefined reference to `gzputc'
+
+ check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
+ /usr/X11R6/lib. Remove any old versions, then do "make install".
+
+10. I need a Delphi interface to zlib.
+
+ See the contrib/delphi directory in the zlib distribution.
+
+11. Can zlib handle .zip archives?
+
+ Not by itself, no. See the directory contrib/minizip in the zlib
+ distribution.
+
+12. Can zlib handle .Z files?
+
+ No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
+ the code of uncompress on your own.
+
+13. How can I make a Unix shared library?
+
+ By default a shared (and a static) library is built for Unix. So:
+
+ make distclean
+ ./configure
+ make
+
+14. How do I install a shared zlib library on Unix?
+
+ After the above, then:
+
+ make install
+
+ However, many flavors of Unix come with a shared zlib already installed.
+ Before going to the trouble of compiling a shared version of zlib and
+ trying to install it, you may want to check if it's already there! If you
+ can #include <zlib.h>, it's there. The -lz option will probably link to
+ it. You can check the version at the top of zlib.h or with the
+ ZLIB_VERSION symbol defined in zlib.h .
+
+15. I have a question about OttoPDF.
+
+ We are not the authors of OttoPDF. The real author is on the OttoPDF web
+ site: Joel Hainley, jhainley@myndkryme.com.
+
+16. Can zlib decode Flate data in an Adobe PDF file?
+
+ Yes. See http://www.pdflib.com/ . To modify PDF forms, see
+ http://sourceforge.net/projects/acroformtool/ .
+
+17. Why am I getting this "register_frame_info not found" error on Solaris?
+
+ After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
+ generates an error such as:
+
+ ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
+ symbol __register_frame_info: referenced symbol not found
+
+ The symbol __register_frame_info is not part of zlib, it is generated by
+ the C compiler (cc or gcc). You must recompile applications using zlib
+ which have this problem. This problem is specific to Solaris. See
+ http://www.sunfreeware.com for Solaris versions of zlib and applications
+ using zlib.
+
+18. Why does gzip give an error on a file I make with compress/deflate?
+
+ The compress and deflate functions produce data in the zlib format, which
+ is different and incompatible with the gzip format. The gz* functions in
+ zlib on the other hand use the gzip format. Both the zlib and gzip formats
+ use the same compressed data format internally, but have different headers
+ and trailers around the compressed data.
+
+19. Ok, so why are there two different formats?
+
+ The gzip format was designed to retain the directory information about a
+ single file, such as the name and last modification date. The zlib format
+ on the other hand was designed for in-memory and communication channel
+ applications, and has a much more compact header and trailer and uses a
+ faster integrity check than gzip.
+
+20. Well that's nice, but how do I make a gzip file in memory?
+
+ You can request that deflate write the gzip format instead of the zlib
+ format using deflateInit2(). You can also request that inflate decode the
+ gzip format using inflateInit2(). Read zlib.h for more details.
+
+21. Is zlib thread-safe?
+
+ Yes. However any library routines that zlib uses and any application-
+ provided memory allocation routines must also be thread-safe. zlib's gz*
+ functions use stdio library routines, and most of zlib's functions use the
+ library memory allocation routines by default. zlib's *Init* functions
+ allow for the application to provide custom memory allocation routines.
+
+ Of course, you should only operate on any given zlib or gzip stream from a
+ single thread at a time.
+
+22. Can I use zlib in my commercial application?
+
+ Yes. Please read the license in zlib.h.
+
+23. Is zlib under the GNU license?
+
+ No. Please read the license in zlib.h.
+
+24. The license says that altered source versions must be "plainly marked". So
+ what exactly do I need to do to meet that requirement?
+
+ You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
+ particular, the final version number needs to be changed to "f", and an
+ identification string should be appended to ZLIB_VERSION. Version numbers
+ x.x.x.f are reserved for modifications to zlib by others than the zlib
+ maintainers. For example, if the version of the base zlib you are altering
+ is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
+ ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
+ update the version strings in deflate.c and inftrees.c.
+
+ For altered source distributions, you should also note the origin and
+ nature of the changes in zlib.h, as well as in ChangeLog and README, along
+ with the dates of the alterations. The origin should include at least your
+ name (or your company's name), and an email address to contact for help or
+ issues with the library.
+
+ Note that distributing a compiled zlib library along with zlib.h and
+ zconf.h is also a source distribution, and so you should change
+ ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
+ in zlib.h as you would for a full source distribution.
+
+25. Will zlib work on a big-endian or little-endian architecture, and can I
+ exchange compressed data between them?
+
+ Yes and yes.
+
+26. Will zlib work on a 64-bit machine?
+
+ Yes. It has been tested on 64-bit machines, and has no dependence on any
+ data types being limited to 32-bits in length. If you have any
+ difficulties, please provide a complete problem report to zlib@gzip.org
+
+27. Will zlib decompress data from the PKWare Data Compression Library?
+
+ No. The PKWare DCL uses a completely different compressed data format than
+ does PKZIP and zlib. However, you can look in zlib's contrib/blast
+ directory for a possible solution to your problem.
+
+28. Can I access data randomly in a compressed stream?
+
+ No, not without some preparation. If when compressing you periodically use
+ Z_FULL_FLUSH, carefully write all the pending data at those points, and
+ keep an index of those locations, then you can start decompression at those
+ points. You have to be careful to not use Z_FULL_FLUSH too often, since it
+ can significantly degrade compression. Alternatively, you can scan a
+ deflate stream once to generate an index, and then use that index for
+ random access. See examples/zran.c .
+
+29. Does zlib work on MVS, OS/390, CICS, etc.?
+
+ It has in the past, but we have not heard of any recent evidence. There
+ were working ports of zlib 1.1.4 to MVS, but those links no longer work.
+ If you know of recent, successful applications of zlib on these operating
+ systems, please let us know. Thanks.
+
+30. Is there some simpler, easier to read version of inflate I can look at to
+ understand the deflate format?
+
+ First off, you should read RFC 1951. Second, yes. Look in zlib's
+ contrib/puff directory.
+
+31. Does zlib infringe on any patents?
+
+ As far as we know, no. In fact, that was originally the whole point behind
+ zlib. Look here for some more information:
+
+ http://www.gzip.org/#faq11
+
+32. Can zlib work with greater than 4 GB of data?
+
+ Yes. inflate() and deflate() will process any amount of data correctly.
+ Each call of inflate() or deflate() is limited to input and output chunks
+ of the maximum value that can be stored in the compiler's "unsigned int"
+ type, but there is no limit to the number of chunks. Note however that the
+ strm.total_in and strm_total_out counters may be limited to 4 GB. These
+ counters are provided as a convenience and are not used internally by
+ inflate() or deflate(). The application can easily set up its own counters
+ updated after each call of inflate() or deflate() to count beyond 4 GB.
+ compress() and uncompress() may be limited to 4 GB, since they operate in a
+ single call. gzseek() and gztell() may be limited to 4 GB depending on how
+ zlib is compiled. See the zlibCompileFlags() function in zlib.h.
+
+ The word "may" appears several times above since there is a 4 GB limit only
+ if the compiler's "long" type is 32 bits. If the compiler's "long" type is
+ 64 bits, then the limit is 16 exabytes.
+
+33. Does zlib have any security vulnerabilities?
+
+ The only one that we are aware of is potentially in gzprintf(). If zlib is
+ compiled to use sprintf() or vsprintf(), then there is no protection
+ against a buffer overflow of an 8K string space (or other value as set by
+ gzbuffer()), other than the caller of gzprintf() assuring that the output
+ will not exceed 8K. On the other hand, if zlib is compiled to use
+ snprintf() or vsnprintf(), which should normally be the case, then there is
+ no vulnerability. The ./configure script will display warnings if an
+ insecure variation of sprintf() will be used by gzprintf(). Also the
+ zlibCompileFlags() function will return information on what variant of
+ sprintf() is used by gzprintf().
+
+ If you don't have snprintf() or vsnprintf() and would like one, you can
+ find a portable implementation here:
+
+ http://www.ijs.si/software/snprintf/
+
+ Note that you should be using the most recent version of zlib. Versions
+ 1.1.3 and before were subject to a double-free vulnerability, and versions
+ 1.2.1 and 1.2.2 were subject to an access exception when decompressing
+ invalid compressed data.
+
+34. Is there a Java version of zlib?
+
+ Probably what you want is to use zlib in Java. zlib is already included
+ as part of the Java SDK in the java.util.zip package. If you really want
+ a version of zlib written in the Java language, look on the zlib home
+ page for links: http://zlib.net/ .
+
+35. I get this or that compiler or source-code scanner warning when I crank it
+ up to maximally-pedantic. Can't you guys write proper code?
+
+ Many years ago, we gave up attempting to avoid warnings on every compiler
+ in the universe. It just got to be a waste of time, and some compilers
+ were downright silly as well as contradicted each other. So now, we simply
+ make sure that the code always works.
+
+36. Valgrind (or some similar memory access checker) says that deflate is
+ performing a conditional jump that depends on an uninitialized value.
+ Isn't that a bug?
+
+ No. That is intentional for performance reasons, and the output of deflate
+ is not affected. This only started showing up recently since zlib 1.2.x
+ uses malloc() by default for allocations, whereas earlier versions used
+ calloc(), which zeros out the allocated memory. Even though the code was
+ correct, versions 1.2.4 and later was changed to not stimulate these
+ checkers.
+
+37. Will zlib read the (insert any ancient or arcane format here) compressed
+ data format?
+
+ Probably not. Look in the comp.compression FAQ for pointers to various
+ formats and associated software.
+
+38. How can I encrypt/decrypt zip files with zlib?
+
+ zlib doesn't support encryption. The original PKZIP encryption is very
+ weak and can be broken with freely available programs. To get strong
+ encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
+ compression. For PKZIP compatible "encryption", look at
+ http://www.info-zip.org/
+
+39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
+
+ "gzip" is the gzip format, and "deflate" is the zlib format. They should
+ probably have called the second one "zlib" instead to avoid confusion with
+ the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
+ correctly points to the zlib specification in RFC 1950 for the "deflate"
+ transfer encoding, there have been reports of servers and browsers that
+ incorrectly produce or expect raw deflate data per the deflate
+ specification in RFC 1951, most notably Microsoft. So even though the
+ "deflate" transfer encoding using the zlib format would be the more
+ efficient approach (and in fact exactly what the zlib format was designed
+ for), using the "gzip" transfer encoding is probably more reliable due to
+ an unfortunate choice of name on the part of the HTTP 1.1 authors.
+
+ Bottom line: use the gzip format for HTTP 1.1 encoding.
+
+40. Does zlib support the new "Deflate64" format introduced by PKWare?
+
+ No. PKWare has apparently decided to keep that format proprietary, since
+ they have not documented it as they have previous compression formats. In
+ any case, the compression improvements are so modest compared to other more
+ modern approaches, that it's not worth the effort to implement.
+
+41. I'm having a problem with the zip functions in zlib, can you help?
+
+ There are no zip functions in zlib. You are probably using minizip by
+ Giles Vollant, which is found in the contrib directory of zlib. It is not
+ part of zlib. In fact none of the stuff in contrib is part of zlib. The
+ files in there are not supported by the zlib authors. You need to contact
+ the authors of the respective contribution for help.
+
+42. The match.asm code in contrib is under the GNU General Public License.
+ Since it's part of zlib, doesn't that mean that all of zlib falls under the
+ GNU GPL?
+
+ No. The files in contrib are not part of zlib. They were contributed by
+ other authors and are provided as a convenience to the user within the zlib
+ distribution. Each item in contrib has its own license.
+
+43. Is zlib subject to export controls? What is its ECCN?
+
+ zlib is not subject to export controls, and so is classified as EAR99.
+
+44. Can you please sign these lengthy legal documents and fax them back to us
+ so that we can use your software in our product?
+
+ No. Go away. Shoo.
diff --git a/libmariadb/external/zlib/INDEX b/libmariadb/external/zlib/INDEX
new file mode 100644
index 00000000..f6c51ca1
--- /dev/null
+++ b/libmariadb/external/zlib/INDEX
@@ -0,0 +1,65 @@
+CMakeLists.txt cmake build file
+ChangeLog history of changes
+FAQ Frequently Asked Questions about zlib
+INDEX this file
+Makefile dummy Makefile that tells you to ./configure
+Makefile.in template for Unix Makefile
+README guess what
+configure configure script for Unix
+make_vms.com makefile for VMS
+treebuild.xml XML description of source file dependencies
+zconf.h.cmakein zconf.h template for cmake
+zconf.h.in zconf.h template for configure
+zlib.3 Man page for zlib
+zlib.3.pdf Man page in PDF format
+zlib.map Linux symbol information
+zlib.pc.in Template for pkg-config descriptor
+zlib2ansi perl script to convert source files for C++ compilation
+
+amiga/ makefiles for Amiga SAS C
+doc/ documentation for formats and algorithms
+msdos/ makefiles for MSDOS
+nintendods/ makefile for Nintendo DS
+old/ makefiles for various architectures and zlib documentation
+ files that have not yet been updated for zlib 1.2.x
+qnx/ makefiles for QNX
+watcom/ makefiles for OpenWatcom
+win32/ makefiles for Windows
+
+ zlib public header files (required for library use):
+zconf.h
+zlib.h
+
+ private source files used to build the zlib library:
+adler32.c
+compress.c
+crc32.c
+crc32.h
+deflate.c
+deflate.h
+gzclose.c
+gzguts.h
+gzlib.c
+gzread.c
+gzwrite.c
+infback.c
+inffast.c
+inffast.h
+inffixed.h
+inflate.c
+inflate.h
+inftrees.c
+inftrees.h
+trees.c
+trees.h
+uncompr.c
+zutil.c
+zutil.h
+
+ source files for sample programs:
+example.c
+minigzip.c
+See examples/README.examples for more
+
+ unsupported contribution by third parties
+See contrib/README.contrib
diff --git a/libmariadb/external/zlib/Makefile.in b/libmariadb/external/zlib/Makefile.in
new file mode 100644
index 00000000..22d1d794
--- /dev/null
+++ b/libmariadb/external/zlib/Makefile.in
@@ -0,0 +1,306 @@
+# Makefile for zlib
+# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile and test, type:
+# ./configure; make test
+# Normally configure builds both a static and a shared library.
+# If you want to build just a static library, use: ./configure --static
+
+
+# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
+# make install
+# To install in $HOME instead of /usr/local, use:
+# make install prefix=$HOME
+
+TGT_ARCH=
+CC=cc
+
+CFLAGS=-O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DDEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+SFLAGS=-O
+LDFLAGS=
+TEST_LDFLAGS=-L. libz.a
+LDSHARED=$(CC)
+CPP=$(CC) -E
+
+STATICLIB=libz.a
+SHAREDLIB=libz.so
+SHAREDLIBV=libz.so.1.2.8
+SHAREDLIBM=libz.so.1
+LIBS=$(STATICLIB) $(SHAREDLIBV)
+
+AR=ar
+ARFLAGS=rc
+RANLIB=ranlib
+LDCONFIG=ldconfig
+LDSHAREDLIBC=-lc
+TAR=tar
+SHELL=/bin/sh
+EXE=
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+libdir = ${exec_prefix}/lib
+sharedlibdir = ${libdir}
+includedir = ${prefix}/include
+mandir = ${prefix}/share/man
+man3dir = ${mandir}/man3
+pkgconfigdir = ${libdir}/pkgconfig
+
+OBJZ = adler32.o adler32_simd.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o
+OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
+
+PIC_OBJZ = adler32.lo adler32_simd.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo
+PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo
+
+ifneq ($(findstring -DINFLATE_CHUNK_SIMD_NEON, $(CFLAGS)),)
+ OBJZ += inffast_chunk.o
+ PIC_OBJZ += inffast_chunk.lo
+endif
+
+ifneq ($(findstring -DINFLATE_CHUNK_SIMD_SSE2, $(CFLAGS)),)
+ OBJZ += inffast_chunk.o
+ PIC_OBJZ += inffast_chunk.lo
+endif
+
+ifneq ($(findstring -DHAS_PCLMUL, $(CFLAGS)),)
+ OBJZ += crc32_simd.o
+ PIC_OBJZ += crc32_simd.lo
+endif
+
+OBJC = $(OBJZ) $(OBJG)
+PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG)
+
+# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo
+OBJA =
+PIC_OBJA =
+
+OBJS = $(OBJC) $(OBJA)
+
+PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA)
+
+all: static shared
+
+static: example$(EXE) minigzip$(EXE)
+
+shared: examplesh$(EXE) minigzipsh$(EXE)
+
+all64: example64$(EXE) minigzip64$(EXE)
+
+check: test
+
+test: all teststatic testshared
+
+teststatic: static
+ @TMPST=tmpst_$$; \
+ if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \
+ echo ' *** zlib test OK ***'; \
+ else \
+ echo ' *** zlib test FAILED ***'; false; \
+ fi; \
+ rm -f $$TMPST
+
+testshared: shared
+ @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+ LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
+ DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
+ SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \
+ TMPSH=tmpsh_$$; \
+ if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \
+ echo ' *** zlib shared test OK ***'; \
+ else \
+ echo ' *** zlib shared test FAILED ***'; false; \
+ fi; \
+ rm -f $$TMPSH
+
+test64: all64
+ @TMP64=tmp64_$$; \
+ if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \
+ echo ' *** zlib 64-bit test OK ***'; \
+ else \
+ echo ' *** zlib 64-bit test FAILED ***'; false; \
+ fi; \
+ rm -f $$TMP64
+
+infcover.o: test/infcover.c zlib.h zconf.h
+ $(CC) $(CFLAGS) -I. -c -o $@ test/infcover.c
+
+infcover: infcover.o libz.a
+ $(CC) $(CFLAGS) -o $@ infcover.o libz.a
+
+cover: infcover
+ rm -f *.gcda
+ ./infcover
+ gcov inf*.c
+
+libz.a: $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+ -@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+match.o: match.S
+ $(CPP) match.S > _match.s
+ $(CC) -c _match.s
+ mv _match.o match.o
+ rm -f _match.s
+
+match.lo: match.S
+ $(CPP) match.S > _match.s
+ $(CC) -c -fPIC _match.s
+ mv _match.o match.lo
+ rm -f _match.s
+
+example.o: test/example.c zlib.h zconf.h
+ $(CC) $(CFLAGS) -I. -c -o $@ test/example.c
+
+minigzip.o: test/minigzip.c zlib.h zconf.h
+ $(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c
+
+example64.o: test/example.c zlib.h zconf.h
+ $(CC) $(CFLAGS) -I. -D_FILE_OFFSET_BITS=64 -c -o $@ test/example.c
+
+minigzip64.o: test/minigzip.c zlib.h zconf.h
+ $(CC) $(CFLAGS) -I. -D_FILE_OFFSET_BITS=64 -c -o $@ test/minigzip.c
+
+.SUFFIXES: .lo
+
+.c.lo:
+ -@mkdir objs 2>/dev/null || test -d objs
+ $(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $<
+ -@mv objs/$*.o $@
+
+placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a
+ $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS)
+ rm -f $(SHAREDLIB) $(SHAREDLIBM)
+ ln -s $@ $(SHAREDLIB)
+ ln -s $@ $(SHAREDLIBM)
+ -@rmdir objs
+
+example$(EXE): example.o $(STATICLIB)
+ $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
+
+minigzip$(EXE): minigzip.o $(STATICLIB)
+ $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
+
+examplesh$(EXE): example.o $(SHAREDLIBV)
+ $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)
+
+minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
+ $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)
+
+example64$(EXE): example64.o $(STATICLIB)
+ $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
+
+minigzip64$(EXE): minigzip64.o $(STATICLIB)
+ $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
+
+install-libs: $(LIBS)
+ -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
+ -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
+ -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
+ -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi
+ -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi
+ cp $(STATICLIB) $(DESTDIR)$(libdir)
+ chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB)
+ -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1
+ -@if test -n "$(SHAREDLIBV)"; then \
+ cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \
+ echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \
+ chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \
+ echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \
+ rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
+ ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \
+ ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
+ ($(LDCONFIG) || true) >/dev/null 2>&1; \
+ fi
+ cp zlib.3 $(DESTDIR)$(man3dir)
+ chmod 644 $(DESTDIR)$(man3dir)/zlib.3
+ cp zlib.pc $(DESTDIR)$(pkgconfigdir)
+ chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc
+# The ranlib in install is needed on NeXTSTEP which checks file times
+# ldconfig is for Linux
+
+install: install-libs
+ -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi
+ cp zlib.h zconf.h $(DESTDIR)$(includedir)
+ chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
+
+uninstall:
+ cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h
+ cd $(DESTDIR)$(libdir) && rm -f libz.a; \
+ if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \
+ rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
+ fi
+ cd $(DESTDIR)$(man3dir) && rm -f zlib.3
+ cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc
+
+docs: zlib.3.pdf
+
+zlib.3.pdf: zlib.3
+ groff -mandoc -f H -T ps zlib.3 | ps2pdf - zlib.3.pdf
+
+zconf.h.cmakein: zconf.h.in
+ -@ TEMPFILE=zconfh_$$; \
+ echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\
+ sed -f $$TEMPFILE zconf.h.in > zconf.h.cmakein &&\
+ touch -r zconf.h.in zconf.h.cmakein &&\
+ rm $$TEMPFILE
+
+zconf: zconf.h.in
+ cp -p zconf.h.in zconf.h
+
+mostlyclean: clean
+clean:
+ rm -f *.o *.lo *~ \
+ example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
+ example64$(EXE) minigzip64$(EXE) \
+ infcover \
+ libz.* foo.gz so_locations \
+ _match.s maketree contrib/infback9/*.o
+ rm -rf objs
+ rm -f *.gcda *.gcno *.gcov
+ rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov
+
+maintainer-clean: distclean
+distclean: clean zconf zconf.h.cmakein docs
+ rm -f Makefile zlib.pc configure.log
+ -@rm -f .DS_Store
+ -@printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile
+ -@printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile
+ -@touch -r Makefile.in Makefile
+
+tags:
+ etags *.[ch]
+
+depend:
+ makedepend -- $(CFLAGS) -- *.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o zutil.o: zutil.h zlib.h zconf.h
+adler32_simd.o: zlib.h
+gzclose.o gzlib.o gzread.o gzwrite.o: zlib.h zconf.h gzguts.h
+compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h
+crc32.o: zutil.h zlib.h zconf.h crc32.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+infback.o inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h inffast_chunk.h chunkcopy.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inffast_chunk.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast_chunk.h chunkcopy.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+
+adler32.lo zutil.lo: zutil.h zlib.h zconf.h
+adler32_simd.o: zlib.h
+gzclose.lo gzlib.lo gzread.lo gzwrite.lo: zlib.h zconf.h gzguts.h
+compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h
+crc32.lo: zutil.h zlib.h zconf.h crc32.h
+deflate.lo: deflate.h zutil.h zlib.h zconf.h
+infback.lo inflate.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h inffast_chunk.h chunkcopy.h
+inffast.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inffast_chunk.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast_chunk.h chunkcopy.h
+inftrees.lo: zutil.h zlib.h zconf.h inftrees.h
+trees.lo: deflate.h zutil.h zlib.h zconf.h trees.h
diff --git a/libmariadb/external/zlib/README b/libmariadb/external/zlib/README
new file mode 100644
index 00000000..51106de4
--- /dev/null
+++ b/libmariadb/external/zlib/README
@@ -0,0 +1,115 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.11 is a general purpose data compression library. All the code is
+thread safe. The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
+rfc1952 (gzip format).
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
+of the library is given in the file test/example.c which also tests that
+the library is working correctly. Another example is given in the file
+test/minigzip.c. The compression library itself is composed of all source
+files in the root directory.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile.in. In short "./configure; make test", and if that goes
+well, "make install" should work for most flavors of Unix. For Windows, use
+one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
+make_vms.com.
+
+Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
+<info@winimage.com> for the Windows DLL version. The zlib home page is
+http://zlib.net/ . Before reporting a problem, please check this site to
+verify that you have the latest version of zlib; otherwise get the latest
+version and check whether the problem still exists or not.
+
+PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
+
+Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
+issue of Dr. Dobb's Journal; a copy of the article is available at
+http://marknelson.us/1997/01/01/zlib-engine/ .
+
+The changes made in version 1.2.11 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory contrib/ .
+
+zlib is available in Java using the java.util.zip package, documented at
+http://java.sun.com/developer/technicalArticles/Programming/compression/ .
+
+A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
+at CPAN (Comprehensive Perl Archive Network) sites, including
+http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
+
+A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
+available in Python 1.5 and later versions, see
+http://docs.python.org/library/zlib.html .
+
+zlib is built into tcl: http://wiki.tcl.tk/4610 .
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info@winimage.com>, is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+ -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+ compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+ when compiled with cc.
+
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+ necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+ other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS or BEOS.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+
+Acknowledgments:
+
+ The deflate format used by zlib was defined by Phil Katz. The deflate and
+ zlib specifications were written by L. Peter Deutsch. Thanks to all the
+ people who reported problems and suggested various improvements in zlib; they
+ are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2017 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
diff --git a/libmariadb/external/zlib/adler32.c b/libmariadb/external/zlib/adler32.c
new file mode 100644
index 00000000..d0be4380
--- /dev/null
+++ b/libmariadb/external/zlib/adler32.c
@@ -0,0 +1,186 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2011, 2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
+
+#define BASE 65521U /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware --
+ try it both ways to see which is faster */
+#ifdef NO_DIVIDE
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+ (thank you to John Reiser for pointing this out) */
+# define CHOP(a) \
+ do { \
+ unsigned long tmp = a >> 16; \
+ a &= 0xffffUL; \
+ a += (tmp << 4) - tmp; \
+ } while (0)
+# define MOD28(a) \
+ do { \
+ CHOP(a); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD(a) \
+ do { \
+ CHOP(a); \
+ MOD28(a); \
+ } while (0)
+# define MOD63(a) \
+ do { /* this assumes a is not negative */ \
+ z_off64_t tmp = a >> 32; \
+ a &= 0xffffffffL; \
+ a += (tmp << 8) - (tmp << 5) + tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD28(a) a %= BASE
+# define MOD63(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_z(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ z_size_t len;
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD28(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ return adler32_z(adler, buf, len);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off64_t len2;
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* for negative len, return invalid adler32 as a clue for debugging */
+ if (len2 < 0)
+ return 0xffffffffUL;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ MOD63(len2); /* assumes len2 >= 0 */
+ rem = (unsigned)len2;
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
+ if (sum2 >= BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off_t len2;
+{
+ return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off64_t len2;
+{
+ return adler32_combine_(adler1, adler2, len2);
+}
diff --git a/libmariadb/external/zlib/adler32_simd.c b/libmariadb/external/zlib/adler32_simd.c
new file mode 100644
index 00000000..5f8c06d0
--- /dev/null
+++ b/libmariadb/external/zlib/adler32_simd.c
@@ -0,0 +1,387 @@
+/* adler32_simd.c
+ *
+ * (C) 1995-2013 Jean-loup Gailly and Mark Adler
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Jean-loup Gailly Mark Adler
+ * jloup@gzip.org madler@alumni.caltech.edu
+ *
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the Chromium source repository LICENSE file.
+ *
+ * Per http://en.wikipedia.org/wiki/Adler-32 the adler32 A value (aka s1) is
+ * the sum of N input data bytes D1 ... DN,
+ *
+ * A = A0 + D1 + D2 + ... + DN
+ *
+ * where A0 is the initial value.
+ *
+ * SSE2 _mm_sad_epu8() can be used for byte sums (see http://bit.ly/2wpUOeD,
+ * for example) and accumulating the byte sums can use SSE shuffle-adds (see
+ * the "Integer" section of http://bit.ly/2erPT8t for details). Arm NEON has
+ * similar instructions.
+ *
+ * The adler32 B value (aka s2) sums the A values from each step:
+ *
+ * B0 + (A0 + D1) + (A0 + D1 + D2) + ... + (A0 + D1 + D2 + ... + DN) or
+ *
+ * B0 + N.A0 + N.D1 + (N-1).D2 + (N-2).D3 + ... + (N-(N-1)).DN
+ *
+ * B0 being the initial value. For 32 bytes (ideal for garden-variety SIMD):
+ *
+ * B = B0 + 32.A0 + [D1 D2 D3 ... D32] x [32 31 30 ... 1].
+ *
+ * Adjacent blocks of 32 input bytes can be iterated with the expressions to
+ * compute the adler32 s1 s2 of M >> 32 input bytes [1].
+ *
+ * As M grows, the s1 s2 sums grow. If left unchecked, they would eventually
+ * overflow the precision of their integer representation (bad). However, s1
+ * and s2 also need to be computed modulo the adler BASE value (reduced). If
+ * at most NMAX bytes are processed before a reduce, s1 s2 _cannot_ overflow
+ * a uint32_t type (the NMAX constraint) [2].
+ *
+ * [1] the iterative equations for s2 contain constant factors; these can be
+ * hoisted from the n-blocks do loop of the SIMD code.
+ *
+ * [2] zlib adler32_z() uses this fact to implement NMAX-block-based updates
+ * of the adler s1 s2 of uint32_t type (see adler32.c).
+ */
+
+#include "adler32_simd.h"
+
+/* Definitions from adler32.c: largest prime smaller than 65536 */
+#define BASE 65521U
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+#define NMAX 5552
+
+#if defined(ADLER32_SIMD_SSSE3)
+
+#include <tmmintrin.h>
+
+uint32_t ZLIB_INTERNAL adler32_simd_( /* SSSE3 */
+ uint32_t adler,
+ const unsigned char *buf,
+ unsigned long len)
+{
+ /*
+ * Split Adler-32 into component sums.
+ */
+ uint32_t s1 = adler & 0xffff;
+ uint32_t s2 = adler >> 16;
+
+ /*
+ * Process the data in blocks.
+ */
+ const unsigned BLOCK_SIZE = 1 << 5;
+
+ unsigned long blocks = len / BLOCK_SIZE;
+ len -= blocks * BLOCK_SIZE;
+
+ while (blocks)
+ {
+ unsigned n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */
+ if (n > blocks)
+ n = (unsigned) blocks;
+ blocks -= n;
+
+ const __m128i tap1 =
+ _mm_setr_epi8(32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17);
+ const __m128i tap2 =
+ _mm_setr_epi8(16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
+ const __m128i zero =
+ _mm_setr_epi8( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ const __m128i ones =
+ _mm_set_epi16( 1, 1, 1, 1, 1, 1, 1, 1);
+
+ /*
+ * Process n blocks of data. At most NMAX data bytes can be
+ * processed before s2 must be reduced modulo BASE.
+ */
+ __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n);
+ __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2);
+ __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0);
+
+ do {
+ /*
+ * Load 32 input bytes.
+ */
+ const __m128i bytes1 = _mm_loadu_si128((__m128i*)(buf));
+ const __m128i bytes2 = _mm_loadu_si128((__m128i*)(buf + 16));
+
+ /*
+ * Add previous block byte sum to v_ps.
+ */
+ v_ps = _mm_add_epi32(v_ps, v_s1);
+
+ /*
+ * Horizontally add the bytes for s1, multiply-adds the
+ * bytes by [ 32, 31, 30, ... ] for s2.
+ */
+ v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero));
+ const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1);
+ v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones));
+
+ v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero));
+ const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2);
+ v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones));
+
+ buf += BLOCK_SIZE;
+
+ } while (--n);
+
+ v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
+
+ /*
+ * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
+ */
+
+#define S23O1 _MM_SHUFFLE(2,3,0,1) /* A B C D -> B A D C */
+#define S1O32 _MM_SHUFFLE(1,0,3,2) /* A B C D -> C D A B */
+
+ v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S23O1));
+ v_s1 = _mm_add_epi32(v_s1, _mm_shuffle_epi32(v_s1, S1O32));
+
+ s1 += _mm_cvtsi128_si32(v_s1);
+
+ v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S23O1));
+ v_s2 = _mm_add_epi32(v_s2, _mm_shuffle_epi32(v_s2, S1O32));
+
+ s2 = _mm_cvtsi128_si32(v_s2);
+
+#undef S23O1
+#undef S1O32
+
+ /*
+ * Reduce.
+ */
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+
+ /*
+ * Handle leftover data.
+ */
+ if (len) {
+ if (len >= 16) {
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ len -= 16;
+ }
+
+ while (len--) {
+ s2 += (s1 += *buf++);
+ }
+
+ if (s1 >= BASE)
+ s1 -= BASE;
+ s2 %= BASE;
+ }
+
+ /*
+ * Return the recombined sums.
+ */
+ return s1 | (s2 << 16);
+}
+
+#elif defined(ADLER32_SIMD_NEON)
+
+#include <arm_neon.h>
+
+uint32_t ZLIB_INTERNAL adler32_simd_( /* NEON */
+ uint32_t adler,
+ const unsigned char *buf,
+ unsigned long len)
+{
+ /*
+ * Split Adler-32 into component sums.
+ */
+ uint32_t s1 = adler & 0xffff;
+ uint32_t s2 = adler >> 16;
+
+ /*
+ * Serially compute s1 & s2, until the data is 16-byte aligned.
+ */
+ if ((uintptr_t)buf & 15) {
+ while ((uintptr_t)buf & 15) {
+ s2 += (s1 += *buf++);
+ --len;
+ }
+
+ if (s1 >= BASE)
+ s1 -= BASE;
+ s2 %= BASE;
+ }
+
+ /*
+ * Process the data in blocks.
+ */
+ const unsigned BLOCK_SIZE = 1 << 5;
+
+ unsigned long blocks = len / BLOCK_SIZE;
+ len -= blocks * BLOCK_SIZE;
+
+ while (blocks)
+ {
+ unsigned n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */
+ if (n > blocks)
+ n = blocks;
+ blocks -= n;
+
+ /*
+ * Process n blocks of data. At most NMAX data bytes can be
+ * processed before s2 must be reduced modulo BASE.
+ */
+ uint32x4_t v_s2 = (uint32x4_t) { 0, 0, 0, s1 * n };
+ uint32x4_t v_s1 = (uint32x4_t) { 0, 0, 0, 0 };
+
+ uint16x8_t v_column_sum_1 = vdupq_n_u16(0);
+ uint16x8_t v_column_sum_2 = vdupq_n_u16(0);
+ uint16x8_t v_column_sum_3 = vdupq_n_u16(0);
+ uint16x8_t v_column_sum_4 = vdupq_n_u16(0);
+
+ do {
+ /*
+ * Load 32 input bytes.
+ */
+ const uint8x16_t bytes1 = vld1q_u8((uint8_t*)(buf));
+ const uint8x16_t bytes2 = vld1q_u8((uint8_t*)(buf + 16));
+
+ /*
+ * Add previous block byte sum to v_s2.
+ */
+ v_s2 = vaddq_u32(v_s2, v_s1);
+
+ /*
+ * Horizontally add the bytes for s1.
+ */
+ v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2));
+
+ /*
+ * Vertically add the bytes for s2.
+ */
+ v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8 (bytes1));
+ v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1));
+ v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8 (bytes2));
+ v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2));
+
+ buf += BLOCK_SIZE;
+
+ } while (--n);
+
+ v_s2 = vshlq_n_u32(v_s2, 5);
+
+ /*
+ * Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
+ */
+ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_1),
+ (uint16x4_t) { 32, 31, 30, 29 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_1),
+ (uint16x4_t) { 28, 27, 26, 25 });
+ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_2),
+ (uint16x4_t) { 24, 23, 22, 21 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_2),
+ (uint16x4_t) { 20, 19, 18, 17 });
+ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_3),
+ (uint16x4_t) { 16, 15, 14, 13 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_3),
+ (uint16x4_t) { 12, 11, 10, 9 });
+ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_4),
+ (uint16x4_t) { 8, 7, 6, 5 });
+ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_4),
+ (uint16x4_t) { 4, 3, 2, 1 });
+
+ /*
+ * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
+ */
+ uint32x2_t sum1 = vpadd_u32(vget_low_u32(v_s1), vget_high_u32(v_s1));
+ uint32x2_t sum2 = vpadd_u32(vget_low_u32(v_s2), vget_high_u32(v_s2));
+ uint32x2_t s1s2 = vpadd_u32(sum1, sum2);
+
+ s1 += vget_lane_u32(s1s2, 0);
+ s2 += vget_lane_u32(s1s2, 1);
+
+ /*
+ * Reduce.
+ */
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+
+ /*
+ * Handle leftover data.
+ */
+ if (len) {
+ if (len >= 16) {
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+ s2 += (s1 += *buf++);
+
+ len -= 16;
+ }
+
+ while (len--) {
+ s2 += (s1 += *buf++);
+ }
+
+ if (s1 >= BASE)
+ s1 -= BASE;
+ s2 %= BASE;
+ }
+
+ /*
+ * Return the recombined sums.
+ */
+ return s1 | (s2 << 16);
+}
+
+#endif /* ADLER32_SIMD_SSSE3 */
diff --git a/libmariadb/external/zlib/adler32_simd.h b/libmariadb/external/zlib/adler32_simd.h
new file mode 100644
index 00000000..285e392d
--- /dev/null
+++ b/libmariadb/external/zlib/adler32_simd.h
@@ -0,0 +1,37 @@
+/* adler32_simd.h
+ *
+ * (C) 1995-2013 Jean-loup Gailly and Mark Adler
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Jean-loup Gailly Mark Adler
+ * jloup@gzip.org madler@alumni.caltech.edu
+ *
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the Chromium source repository LICENSE file.
+ */
+
+#include <stdint.h>
+
+#include "zconf.h"
+#include "zutil.h"
+
+uint32_t ZLIB_INTERNAL adler32_simd_(
+ uint32_t adler,
+ const unsigned char *buf,
+ unsigned long len);
diff --git a/libmariadb/external/zlib/amiga/Makefile.pup b/libmariadb/external/zlib/amiga/Makefile.pup
new file mode 100644
index 00000000..8940c120
--- /dev/null
+++ b/libmariadb/external/zlib/amiga/Makefile.pup
@@ -0,0 +1,69 @@
+# Amiga powerUP (TM) Makefile
+# makefile for libpng and SAS C V6.58/7.00 PPC compiler
+# Copyright (C) 1998 by Andreas R. Kleinert
+
+LIBNAME = libzip.a
+
+CC = scppc
+CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \
+ OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER
+AR = ppc-amigaos-ar cr
+RANLIB = ppc-amigaos-ranlib
+LD = ppc-amigaos-ld -r
+LDFLAGS = -o
+LDLIBS = LIB:scppc.a LIB:end.o
+RM = delete quiet
+
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example minigzip
+
+check: test
+test: all
+ example
+ echo hello world | minigzip | minigzip -d
+
+$(LIBNAME): $(OBJS)
+ $(AR) $@ $(OBJS)
+ -$(RANLIB) $@
+
+example: example.o $(LIBNAME)
+ $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
+
+minigzip: minigzip.o $(LIBNAME)
+ $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
+
+mostlyclean: clean
+clean:
+ $(RM) *.o example minigzip $(LIBNAME) foo.gz
+
+zip:
+ zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \
+ descrip.mms *.[ch]
+
+tgz:
+ cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \
+ zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzclose.o: zlib.h zconf.h gzguts.h
+gzlib.o: zlib.h zconf.h gzguts.h
+gzread.o: zlib.h zconf.h gzguts.h
+gzwrite.o: zlib.h zconf.h gzguts.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/libmariadb/external/zlib/amiga/Makefile.sas b/libmariadb/external/zlib/amiga/Makefile.sas
new file mode 100644
index 00000000..749e2915
--- /dev/null
+++ b/libmariadb/external/zlib/amiga/Makefile.sas
@@ -0,0 +1,68 @@
+# SMakefile for zlib
+# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly
+# Osma Ahvenlampi <Osma.Ahvenlampi@hut.fi>
+# Amiga, SAS/C 6.56 & Smake
+
+CC=sc
+CFLAGS=OPT
+#CFLAGS=OPT CPU=68030
+#CFLAGS=DEBUG=LINE
+LDFLAGS=LIB z.lib
+
+SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
+ NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \
+ DEF=POSTINC
+
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: SCOPTIONS example minigzip
+
+check: test
+test: all
+ example
+ echo hello world | minigzip | minigzip -d
+
+install: z.lib
+ copy clone zlib.h zconf.h INCLUDE:
+ copy clone z.lib LIB:
+
+z.lib: $(OBJS)
+ oml z.lib r $(OBJS)
+
+example: example.o z.lib
+ $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS)
+
+minigzip: minigzip.o z.lib
+ $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS)
+
+mostlyclean: clean
+clean:
+ -delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS
+
+SCOPTIONS: Makefile.sas
+ copy to $@ <from <
+$(SCOPTIONS)
+<
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzclose.o: zlib.h zconf.h gzguts.h
+gzlib.o: zlib.h zconf.h gzguts.h
+gzread.o: zlib.h zconf.h gzguts.h
+gzwrite.o: zlib.h zconf.h gzguts.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/libmariadb/external/zlib/as400/bndsrc b/libmariadb/external/zlib/as400/bndsrc
new file mode 100644
index 00000000..98814fd4
--- /dev/null
+++ b/libmariadb/external/zlib/as400/bndsrc
@@ -0,0 +1,215 @@
+STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB')
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/* Version 1.1.3 entry points. */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/* *MODULE ADLER32 ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("adler32")
+
+/********************************************************************/
+/* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("compress")
+ EXPORT SYMBOL("compress2")
+
+/********************************************************************/
+/* *MODULE CRC32 ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("crc32")
+ EXPORT SYMBOL("get_crc_table")
+
+/********************************************************************/
+/* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("deflate")
+ EXPORT SYMBOL("deflateEnd")
+ EXPORT SYMBOL("deflateSetDictionary")
+ EXPORT SYMBOL("deflateCopy")
+ EXPORT SYMBOL("deflateReset")
+ EXPORT SYMBOL("deflateParams")
+ EXPORT SYMBOL("deflatePrime")
+ EXPORT SYMBOL("deflateInit_")
+ EXPORT SYMBOL("deflateInit2_")
+
+/********************************************************************/
+/* *MODULE GZIO ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("gzopen")
+ EXPORT SYMBOL("gzdopen")
+ EXPORT SYMBOL("gzsetparams")
+ EXPORT SYMBOL("gzread")
+ EXPORT SYMBOL("gzwrite")
+ EXPORT SYMBOL("gzprintf")
+ EXPORT SYMBOL("gzputs")
+ EXPORT SYMBOL("gzgets")
+ EXPORT SYMBOL("gzputc")
+ EXPORT SYMBOL("gzgetc")
+ EXPORT SYMBOL("gzflush")
+ EXPORT SYMBOL("gzseek")
+ EXPORT SYMBOL("gzrewind")
+ EXPORT SYMBOL("gztell")
+ EXPORT SYMBOL("gzeof")
+ EXPORT SYMBOL("gzclose")
+ EXPORT SYMBOL("gzerror")
+
+/********************************************************************/
+/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("inflate")
+ EXPORT SYMBOL("inflateEnd")
+ EXPORT SYMBOL("inflateSetDictionary")
+ EXPORT SYMBOL("inflateSync")
+ EXPORT SYMBOL("inflateReset")
+ EXPORT SYMBOL("inflateInit_")
+ EXPORT SYMBOL("inflateInit2_")
+ EXPORT SYMBOL("inflateSyncPoint")
+
+/********************************************************************/
+/* *MODULE UNCOMPR ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("uncompress")
+
+/********************************************************************/
+/* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("zlibVersion")
+ EXPORT SYMBOL("zError")
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/* Version 1.2.1 additional entry points. */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("compressBound")
+
+/********************************************************************/
+/* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("deflateBound")
+
+/********************************************************************/
+/* *MODULE GZIO ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("gzungetc")
+ EXPORT SYMBOL("gzclearerr")
+
+/********************************************************************/
+/* *MODULE INFBACK ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("inflateBack")
+ EXPORT SYMBOL("inflateBackEnd")
+ EXPORT SYMBOL("inflateBackInit_")
+
+/********************************************************************/
+/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("inflateCopy")
+
+/********************************************************************/
+/* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("zlibCompileFlags")
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/* Version 1.2.5 additional entry points. */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/* *MODULE ADLER32 ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("adler32_combine")
+ EXPORT SYMBOL("adler32_combine64")
+
+/********************************************************************/
+/* *MODULE CRC32 ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("crc32_combine")
+ EXPORT SYMBOL("crc32_combine64")
+
+/********************************************************************/
+/* *MODULE GZLIB ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("gzbuffer")
+ EXPORT SYMBOL("gzoffset")
+ EXPORT SYMBOL("gzoffset64")
+ EXPORT SYMBOL("gzopen64")
+ EXPORT SYMBOL("gzseek64")
+ EXPORT SYMBOL("gztell64")
+
+/********************************************************************/
+/* *MODULE GZREAD ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("gzclose_r")
+
+/********************************************************************/
+/* *MODULE GZWRITE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("gzclose_w")
+
+/********************************************************************/
+/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("inflateMark")
+ EXPORT SYMBOL("inflatePrime")
+ EXPORT SYMBOL("inflateReset2")
+ EXPORT SYMBOL("inflateUndermine")
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/* Version 1.2.6 additional entry points. */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("deflateResetKeep")
+ EXPORT SYMBOL("deflatePending")
+
+/********************************************************************/
+/* *MODULE GZWRITE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("gzgetc_")
+
+/********************************************************************/
+/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("inflateResetKeep")
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/* Version 1.2.8 additional entry points. */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */
+/********************************************************************/
+
+ EXPORT SYMBOL("inflateGetDictionary")
+
+ENDPGMEXP
diff --git a/libmariadb/external/zlib/as400/compile.clp b/libmariadb/external/zlib/as400/compile.clp
new file mode 100644
index 00000000..e3f47c63
--- /dev/null
+++ b/libmariadb/external/zlib/as400/compile.clp
@@ -0,0 +1,110 @@
+/******************************************************************************/
+/* */
+/* ZLIB */
+/* */
+/* Compile sources into modules and link them into a service program. */
+/* */
+/******************************************************************************/
+
+ PGM
+
+/* Configuration adjustable parameters. */
+
+ DCL VAR(&SRCLIB) TYPE(*CHAR) LEN(10) +
+ VALUE('ZLIB') /* Source library. */
+ DCL VAR(&SRCFILE) TYPE(*CHAR) LEN(10) +
+ VALUE('SOURCES') /* Source member file. */
+ DCL VAR(&CTLFILE) TYPE(*CHAR) LEN(10) +
+ VALUE('TOOLS') /* Control member file. */
+
+ DCL VAR(&MODLIB) TYPE(*CHAR) LEN(10) +
+ VALUE('ZLIB') /* Module library. */
+
+ DCL VAR(&SRVLIB) TYPE(*CHAR) LEN(10) +
+ VALUE('LGPL') /* Service program library. */
+
+ DCL VAR(&CFLAGS) TYPE(*CHAR) +
+ VALUE('OPTIMIZE(40)') /* Compile options. */
+
+ DCL VAR(&TGTRLS) TYPE(*CHAR) +
+ VALUE('V5R3M0') /* Target release. */
+
+
+/* Working storage. */
+
+ DCL VAR(&CMDLEN) TYPE(*DEC) LEN(15 5) VALUE(300) /* Command length. */
+ DCL VAR(&CMD) TYPE(*CHAR) LEN(512)
+ DCL VAR(&FIXDCMD) TYPE(*CHAR) LEN(512)
+
+
+/* Compile sources into modules. */
+
+ CHGVAR VAR(&FIXDCMD) VALUE('CRTCMOD' *BCAT &CFLAGS *BCAT +
+ 'SYSIFCOPT(*IFS64IO)' *BCAT +
+ 'DEFINE(''_LARGEFILE64_SOURCE''' *BCAT +
+ '''_LFS64_LARGEFILE=1'') TGTRLS(' *TCAT &TGTRLS *TCAT +
+ ') SRCFILE(' *TCAT &SRCLIB *TCAT '/' *TCAT +
+ &SRCFILE *TCAT ') MODULE(' *TCAT &MODLIB *TCAT '/')
+
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'ADLER32)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'COMPRESS)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'CRC32)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'DEFLATE)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZCLOSE)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZLIB)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZREAD)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZWRITE)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFBACK)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFFAST)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFLATE)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFTREES)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'TREES)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'UNCOMPR)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+ CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'ZUTIL)')
+ CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+
+/* Link modules into a service program. */
+
+ CRTSRVPGM SRVPGM(&SRVLIB/ZLIB) +
+ MODULE(&MODLIB/ADLER32 &MODLIB/COMPRESS +
+ &MODLIB/CRC32 &MODLIB/DEFLATE +
+ &MODLIB/GZCLOSE &MODLIB/GZLIB +
+ &MODLIB/GZREAD &MODLIB/GZWRITE +
+ &MODLIB/INFBACK &MODLIB/INFFAST +
+ &MODLIB/INFLATE &MODLIB/INFTREES +
+ &MODLIB/TREES &MODLIB/UNCOMPR +
+ &MODLIB/ZUTIL) +
+ SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC) +
+ TEXT('ZLIB 1.2.8') TGTRLS(&TGTRLS)
+
+ ENDPGM
diff --git a/libmariadb/external/zlib/as400/readme.txt b/libmariadb/external/zlib/as400/readme.txt
new file mode 100644
index 00000000..7b5d93bf
--- /dev/null
+++ b/libmariadb/external/zlib/as400/readme.txt
@@ -0,0 +1,115 @@
+ ZLIB version 1.2.8 for AS400 installation instructions
+
+I) From an AS400 *SAVF file:
+
+1) Unpacking archive to an AS400 save file
+
+On the AS400:
+
+_ Create the ZLIB AS400 library:
+
+ CRTLIB LIB(ZLIB) TYPE(*PROD) TEXT('ZLIB compression API library')
+
+_ Create a work save file, for example:
+
+ CRTSAVF FILE(ZLIB/ZLIBSAVF)
+
+On a PC connected to the target AS400:
+
+_ Unpack the save file image to a PC file "ZLIBSAVF"
+_ Upload this file into the save file on the AS400, for example
+ using ftp in BINARY mode.
+
+
+2) Populating the ZLIB AS400 source library
+
+On the AS400:
+
+_ Extract the saved objects into the ZLIB AS400 library using:
+
+RSTOBJ OBJ(*ALL) SAVLIB(ZLIB) DEV(*SAVF) SAVF(ZLIB/ZLIBSAVF) RSTLIB(ZLIB)
+
+
+3) Customize installation:
+
+_ Edit CL member ZLIB/TOOLS(COMPILE) and change parameters if needed,
+ according to the comments.
+
+_ Compile this member with:
+
+ CRTCLPGM PGM(ZLIB/COMPILE) SRCFILE(ZLIB/TOOLS) SRCMBR(COMPILE)
+
+
+4) Compile and generate the service program:
+
+_ This can now be done by executing:
+
+ CALL PGM(ZLIB/COMPILE)
+
+
+
+II) From the original source distribution:
+
+1) On the AS400, create the source library:
+
+ CRTLIB LIB(ZLIB) TYPE(*PROD) TEXT('ZLIB compression API library')
+
+2) Create the source files:
+
+ CRTSRCPF FILE(ZLIB/SOURCES) RCDLEN(112) TEXT('ZLIB library modules')
+ CRTSRCPF FILE(ZLIB/H) RCDLEN(112) TEXT('ZLIB library includes')
+ CRTSRCPF FILE(ZLIB/TOOLS) RCDLEN(112) TEXT('ZLIB library control utilities')
+
+3) From the machine hosting the distribution files, upload them (with
+ FTP in text mode, for example) according to the following table:
+
+ Original AS400 AS400 AS400 AS400
+ file file member type description
+ SOURCES Original ZLIB C subprogram sources
+ adler32.c ADLER32 C ZLIB - Compute the Adler-32 checksum of a dta strm
+ compress.c COMPRESS C ZLIB - Compress a memory buffer
+ crc32.c CRC32 C ZLIB - Compute the CRC-32 of a data stream
+ deflate.c DEFLATE C ZLIB - Compress data using the deflation algorithm
+ gzclose.c GZCLOSE C ZLIB - Close .gz files
+ gzlib.c GZLIB C ZLIB - Miscellaneous .gz files IO support
+ gzread.c GZREAD C ZLIB - Read .gz files
+ gzwrite.c GZWRITE C ZLIB - Write .gz files
+ infback.c INFBACK C ZLIB - Inflate using a callback interface
+ inffast.c INFFAST C ZLIB - Fast proc. literals & length/distance pairs
+ inflate.c INFLATE C ZLIB - Interface to inflate modules
+ inftrees.c INFTREES C ZLIB - Generate Huffman trees for efficient decode
+ trees.c TREES C ZLIB - Output deflated data using Huffman coding
+ uncompr.c UNCOMPR C ZLIB - Decompress a memory buffer
+ zutil.c ZUTIL C ZLIB - Target dependent utility functions
+ H Original ZLIB C and ILE/RPG include files
+ crc32.h CRC32 C ZLIB - CRC32 tables
+ deflate.h DEFLATE C ZLIB - Internal compression state
+ gzguts.h GZGUTS C ZLIB - Definitions for the gzclose module
+ inffast.h INFFAST C ZLIB - Header to use inffast.c
+ inffixed.h INFFIXED C ZLIB - Table for decoding fixed codes
+ inflate.h INFLATE C ZLIB - Internal inflate state definitions
+ inftrees.h INFTREES C ZLIB - Header to use inftrees.c
+ trees.h TREES C ZLIB - Created automatically with -DGEN_TREES_H
+ zconf.h ZCONF C ZLIB - Compression library configuration
+ zlib.h ZLIB C ZLIB - Compression library C user interface
+ as400/zlib.inc ZLIB.INC RPGLE ZLIB - Compression library ILE RPG user interface
+ zutil.h ZUTIL C ZLIB - Internal interface and configuration
+ TOOLS Building source software & AS/400 README
+ as400/bndsrc BNDSRC Entry point exportation list
+ as400/compile.clp COMPILE CLP Compile sources & generate service program
+ as400/readme.txt README TXT Installation instructions
+
+4) Continue as in I)3).
+
+
+
+
+Notes: For AS400 ILE RPG programmers, a /copy member defining the ZLIB
+ API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC).
+ Please read comments in this member for more information.
+
+ Remember that most foreign textual data are ASCII coded: this
+ implementation does not handle conversion from/to ASCII, so
+ text data code conversions must be done explicitely.
+
+ Mainly for the reason above, always open zipped files in binary mode.
diff --git a/libmariadb/external/zlib/as400/zlib.inc b/libmariadb/external/zlib/as400/zlib.inc
new file mode 100644
index 00000000..7341a6d8
--- /dev/null
+++ b/libmariadb/external/zlib/as400/zlib.inc
@@ -0,0 +1,451 @@
+ * ZLIB.INC - Interface to the general purpose compression library
+ *
+ * ILE RPG400 version by Patrick Monnerat, DATASPHERE.
+ * Version 1.2.8
+ *
+ *
+ * WARNING:
+ * Procedures inflateInit(), inflateInit2(), deflateInit(),
+ * deflateInit2() and inflateBackInit() need to be called with
+ * two additional arguments:
+ * the package version string and the stream control structure.
+ * size. This is needed because RPG lacks some macro feature.
+ * Call these procedures as:
+ * inflateInit(...: ZLIB_VERSION: %size(z_stream))
+ *
+ /if not defined(ZLIB_H_)
+ /define ZLIB_H_
+ *
+ **************************************************************************
+ * Constants
+ **************************************************************************
+ *
+ * Versioning information.
+ *
+ D ZLIB_VERSION C '1.2.8'
+ D ZLIB_VERNUM C X'1280'
+ D ZLIB_VER_MAJOR C 1
+ D ZLIB_VER_MINOR C 2
+ D ZLIB_VER_REVISION...
+ D C 8
+ D ZLIB_VER_SUBREVISION...
+ D C 0
+ *
+ * Other equates.
+ *
+ D Z_NO_FLUSH C 0
+ D Z_PARTIAL_FLUSH...
+ D C 1
+ D Z_SYNC_FLUSH C 2
+ D Z_FULL_FLUSH C 3
+ D Z_FINISH C 4
+ D Z_BLOCK C 5
+ D Z_TREES C 6
+ *
+ D Z_OK C 0
+ D Z_STREAM_END C 1
+ D Z_NEED_DICT C 2
+ D Z_ERRNO C -1
+ D Z_STREAM_ERROR C -2
+ D Z_DATA_ERROR C -3
+ D Z_MEM_ERROR C -4
+ D Z_BUF_ERROR C -5
+ DZ_VERSION_ERROR C -6
+ *
+ D Z_NO_COMPRESSION...
+ D C 0
+ D Z_BEST_SPEED C 1
+ D Z_BEST_COMPRESSION...
+ D C 9
+ D Z_DEFAULT_COMPRESSION...
+ D C -1
+ *
+ D Z_FILTERED C 1
+ D Z_HUFFMAN_ONLY C 2
+ D Z_RLE C 3
+ D Z_DEFAULT_STRATEGY...
+ D C 0
+ *
+ D Z_BINARY C 0
+ D Z_ASCII C 1
+ D Z_UNKNOWN C 2
+ *
+ D Z_DEFLATED C 8
+ *
+ D Z_NULL C 0
+ *
+ **************************************************************************
+ * Types
+ **************************************************************************
+ *
+ D z_streamp S * Stream struct ptr
+ D gzFile S * File pointer
+ D z_off_t S 10i 0 Stream offsets
+ D z_off64_t S 20i 0 Stream offsets
+ *
+ **************************************************************************
+ * Structures
+ **************************************************************************
+ *
+ * The GZIP encode/decode stream support structure.
+ *
+ D z_stream DS align based(z_streamp)
+ D zs_next_in * Next input byte
+ D zs_avail_in 10U 0 Byte cnt at next_in
+ D zs_total_in 10U 0 Total bytes read
+ D zs_next_out * Output buffer ptr
+ D zs_avail_out 10U 0 Room left @ next_out
+ D zs_total_out 10U 0 Total bytes written
+ D zs_msg * Last errmsg or null
+ D zs_state * Internal state
+ D zs_zalloc * procptr Int. state allocator
+ D zs_free * procptr Int. state dealloc.
+ D zs_opaque * Private alloc. data
+ D zs_data_type 10i 0 ASC/BIN best guess
+ D zs_adler 10u 0 Uncompr. adler32 val
+ D 10U 0 Reserved
+ D 10U 0 Ptr. alignment
+ *
+ **************************************************************************
+ * Utility function prototypes
+ **************************************************************************
+ *
+ D compress PR 10I 0 extproc('compress')
+ D dest 65535 options(*varsize) Destination buffer
+ D destLen 10U 0 Destination length
+ D source 65535 const options(*varsize) Source buffer
+ D sourceLen 10u 0 value Source length
+ *
+ D compress2 PR 10I 0 extproc('compress2')
+ D dest 65535 options(*varsize) Destination buffer
+ D destLen 10U 0 Destination length
+ D source 65535 const options(*varsize) Source buffer
+ D sourceLen 10U 0 value Source length
+ D level 10I 0 value Compression level
+ *
+ D compressBound PR 10U 0 extproc('compressBound')
+ D sourceLen 10U 0 value
+ *
+ D uncompress PR 10I 0 extproc('uncompress')
+ D dest 65535 options(*varsize) Destination buffer
+ D destLen 10U 0 Destination length
+ D source 65535 const options(*varsize) Source buffer
+ D sourceLen 10U 0 value Source length
+ *
+ /if not defined(LARGE_FILES)
+ D gzopen PR extproc('gzopen')
+ D like(gzFile)
+ D path * value options(*string) File pathname
+ D mode * value options(*string) Open mode
+ /else
+ D gzopen PR extproc('gzopen64')
+ D like(gzFile)
+ D path * value options(*string) File pathname
+ D mode * value options(*string) Open mode
+ *
+ D gzopen64 PR extproc('gzopen64')
+ D like(gzFile)
+ D path * value options(*string) File pathname
+ D mode * value options(*string) Open mode
+ /endif
+ *
+ D gzdopen PR extproc('gzdopen')
+ D like(gzFile)
+ D fd 10I 0 value File descriptor
+ D mode * value options(*string) Open mode
+ *
+ D gzbuffer PR 10I 0 extproc('gzbuffer')
+ D file value like(gzFile) File pointer
+ D size 10U 0 value
+ *
+ D gzsetparams PR 10I 0 extproc('gzsetparams')
+ D file value like(gzFile) File pointer
+ D level 10I 0 value
+ D strategy 10I 0 value
+ *
+ D gzread PR 10I 0 extproc('gzread')
+ D file value like(gzFile) File pointer
+ D buf 65535 options(*varsize) Buffer
+ D len 10u 0 value Buffer length
+ *
+ D gzwrite PR 10I 0 extproc('gzwrite')
+ D file value like(gzFile) File pointer
+ D buf 65535 const options(*varsize) Buffer
+ D len 10u 0 value Buffer length
+ *
+ D gzputs PR 10I 0 extproc('gzputs')
+ D file value like(gzFile) File pointer
+ D s * value options(*string) String to output
+ *
+ D gzgets PR * extproc('gzgets')
+ D file value like(gzFile) File pointer
+ D buf 65535 options(*varsize) Read buffer
+ D len 10i 0 value Buffer length
+ *
+ D gzputc PR 10i 0 extproc('gzputc')
+ D file value like(gzFile) File pointer
+ D c 10I 0 value Character to write
+ *
+ D gzgetc PR 10i 0 extproc('gzgetc')
+ D file value like(gzFile) File pointer
+ *
+ D gzgetc_ PR 10i 0 extproc('gzgetc_')
+ D file value like(gzFile) File pointer
+ *
+ D gzungetc PR 10i 0 extproc('gzungetc')
+ D c 10I 0 value Character to push
+ D file value like(gzFile) File pointer
+ *
+ D gzflush PR 10i 0 extproc('gzflush')
+ D file value like(gzFile) File pointer
+ D flush 10I 0 value Type of flush
+ *
+ /if not defined(LARGE_FILES)
+ D gzseek PR extproc('gzseek')
+ D like(z_off_t)
+ D file value like(gzFile) File pointer
+ D offset value like(z_off_t) Offset
+ D whence 10i 0 value Origin
+ /else
+ D gzseek PR extproc('gzseek64')
+ D like(z_off_t)
+ D file value like(gzFile) File pointer
+ D offset value like(z_off_t) Offset
+ D whence 10i 0 value Origin
+ *
+ D gzseek64 PR extproc('gzseek64')
+ D like(z_off64_t)
+ D file value like(gzFile) File pointer
+ D offset value like(z_off64_t) Offset
+ D whence 10i 0 value Origin
+ /endif
+ *
+ D gzrewind PR 10i 0 extproc('gzrewind')
+ D file value like(gzFile) File pointer
+ *
+ /if not defined(LARGE_FILES)
+ D gztell PR extproc('gztell')
+ D like(z_off_t)
+ D file value like(gzFile) File pointer
+ /else
+ D gztell PR extproc('gztell64')
+ D like(z_off_t)
+ D file value like(gzFile) File pointer
+ *
+ D gztell64 PR extproc('gztell64')
+ D like(z_off64_t)
+ D file value like(gzFile) File pointer
+ /endif
+ *
+ /if not defined(LARGE_FILES)
+ D gzoffset PR extproc('gzoffset')
+ D like(z_off_t)
+ D file value like(gzFile) File pointer
+ /else
+ D gzoffset PR extproc('gzoffset64')
+ D like(z_off_t)
+ D file value like(gzFile) File pointer
+ *
+ D gzoffset64 PR extproc('gzoffset64')
+ D like(z_off64_t)
+ D file value like(gzFile) File pointer
+ /endif
+ *
+ D gzeof PR 10i 0 extproc('gzeof')
+ D file value like(gzFile) File pointer
+ *
+ D gzclose_r PR 10i 0 extproc('gzclose_r')
+ D file value like(gzFile) File pointer
+ *
+ D gzclose_w PR 10i 0 extproc('gzclose_w')
+ D file value like(gzFile) File pointer
+ *
+ D gzclose PR 10i 0 extproc('gzclose')
+ D file value like(gzFile) File pointer
+ *
+ D gzerror PR * extproc('gzerror') Error string
+ D file value like(gzFile) File pointer
+ D errnum 10I 0 Error code
+ *
+ D gzclearerr PR extproc('gzclearerr')
+ D file value like(gzFile) File pointer
+ *
+ **************************************************************************
+ * Basic function prototypes
+ **************************************************************************
+ *
+ D zlibVersion PR * extproc('zlibVersion') Version string
+ *
+ D deflateInit PR 10I 0 extproc('deflateInit_') Init. compression
+ D strm like(z_stream) Compression stream
+ D level 10I 0 value Compression level
+ D version * value options(*string) Version string
+ D stream_size 10i 0 value Stream struct. size
+ *
+ D deflate PR 10I 0 extproc('deflate') Compress data
+ D strm like(z_stream) Compression stream
+ D flush 10I 0 value Flush type required
+ *
+ D deflateEnd PR 10I 0 extproc('deflateEnd') Termin. compression
+ D strm like(z_stream) Compression stream
+ *
+ D inflateInit PR 10I 0 extproc('inflateInit_') Init. expansion
+ D strm like(z_stream) Expansion stream
+ D version * value options(*string) Version string
+ D stream_size 10i 0 value Stream struct. size
+ *
+ D inflate PR 10I 0 extproc('inflate') Expand data
+ D strm like(z_stream) Expansion stream
+ D flush 10I 0 value Flush type required
+ *
+ D inflateEnd PR 10I 0 extproc('inflateEnd') Termin. expansion
+ D strm like(z_stream) Expansion stream
+ *
+ **************************************************************************
+ * Advanced function prototypes
+ **************************************************************************
+ *
+ D deflateInit2 PR 10I 0 extproc('deflateInit2_') Init. compression
+ D strm like(z_stream) Compression stream
+ D level 10I 0 value Compression level
+ D method 10I 0 value Compression method
+ D windowBits 10I 0 value log2(window size)
+ D memLevel 10I 0 value Mem/cmpress tradeoff
+ D strategy 10I 0 value Compression stategy
+ D version * value options(*string) Version string
+ D stream_size 10i 0 value Stream struct. size
+ *
+ D deflateSetDictionary...
+ D PR 10I 0 extproc('deflateSetDictionary') Init. dictionary
+ D strm like(z_stream) Compression stream
+ D dictionary 65535 const options(*varsize) Dictionary bytes
+ D dictLength 10U 0 value Dictionary length
+ *
+ D deflateCopy PR 10I 0 extproc('deflateCopy') Compress strm 2 strm
+ D dest like(z_stream) Destination stream
+ D source like(z_stream) Source stream
+ *
+ D deflateReset PR 10I 0 extproc('deflateReset') End and init. stream
+ D strm like(z_stream) Compression stream
+ *
+ D deflateParams PR 10I 0 extproc('deflateParams') Change level & strat
+ D strm like(z_stream) Compression stream
+ D level 10I 0 value Compression level
+ D strategy 10I 0 value Compression stategy
+ *
+ D deflateBound PR 10U 0 extproc('deflateBound') Change level & strat
+ D strm like(z_stream) Compression stream
+ D sourcelen 10U 0 value Compression level
+ *
+ D deflatePending PR 10I 0 extproc('deflatePending') Change level & strat
+ D strm like(z_stream) Compression stream
+ D pending 10U 0 Pending bytes
+ D bits 10I 0 Pending bits
+ *
+ D deflatePrime PR 10I 0 extproc('deflatePrime') Change level & strat
+ D strm like(z_stream) Compression stream
+ D bits 10I 0 value # of bits to insert
+ D value 10I 0 value Bits to insert
+ *
+ D inflateInit2 PR 10I 0 extproc('inflateInit2_') Init. expansion
+ D strm like(z_stream) Expansion stream
+ D windowBits 10I 0 value log2(window size)
+ D version * value options(*string) Version string
+ D stream_size 10i 0 value Stream struct. size
+ *
+ D inflateSetDictionary...
+ D PR 10I 0 extproc('inflateSetDictionary') Init. dictionary
+ D strm like(z_stream) Expansion stream
+ D dictionary 65535 const options(*varsize) Dictionary bytes
+ D dictLength 10U 0 value Dictionary length
+ *
+ D inflateGetDictionary...
+ D PR 10I 0 extproc('inflateGetDictionary') Get dictionary
+ D strm like(z_stream) Expansion stream
+ D dictionary 65535 options(*varsize) Dictionary bytes
+ D dictLength 10U 0 Dictionary length
+ *
+ D inflateSync PR 10I 0 extproc('inflateSync') Sync. expansion
+ D strm like(z_stream) Expansion stream
+ *
+ D inflateCopy PR 10I 0 extproc('inflateCopy')
+ D dest like(z_stream) Destination stream
+ D source like(z_stream) Source stream
+ *
+ D inflateReset PR 10I 0 extproc('inflateReset') End and init. stream
+ D strm like(z_stream) Expansion stream
+ *
+ D inflateReset2 PR 10I 0 extproc('inflateReset2') End and init. stream
+ D strm like(z_stream) Expansion stream
+ D windowBits 10I 0 value Log2(buffer size)
+ *
+ D inflatePrime PR 10I 0 extproc('inflatePrime') Insert bits
+ D strm like(z_stream) Expansion stream
+ D bits 10I 0 value Bit count
+ D value 10I 0 value Bits to insert
+ *
+ D inflateMark PR 10I 0 extproc('inflateMark') Get inflate info
+ D strm like(z_stream) Expansion stream
+ *
+ D inflateBackInit...
+ D PR 10I 0 extproc('inflateBackInit_')
+ D strm like(z_stream) Expansion stream
+ D windowBits 10I 0 value Log2(buffer size)
+ D window 65535 options(*varsize) Buffer
+ D version * value options(*string) Version string
+ D stream_size 10i 0 value Stream struct. size
+ *
+ D inflateBack PR 10I 0 extproc('inflateBack')
+ D strm like(z_stream) Expansion stream
+ D in * value procptr Input function
+ D in_desc * value Input descriptor
+ D out * value procptr Output function
+ D out_desc * value Output descriptor
+ *
+ D inflateBackEnd PR 10I 0 extproc('inflateBackEnd')
+ D strm like(z_stream) Expansion stream
+ *
+ D zlibCompileFlags...
+ D PR 10U 0 extproc('zlibCompileFlags')
+ *
+ **************************************************************************
+ * Checksum function prototypes
+ **************************************************************************
+ *
+ D adler32 PR 10U 0 extproc('adler32') New checksum
+ D adler 10U 0 value Old checksum
+ D buf 65535 const options(*varsize) Bytes to accumulate
+ D len 10U 0 value Buffer length
+ *
+ D crc32 PR 10U 0 extproc('crc32') New checksum
+ D crc 10U 0 value Old checksum
+ D buf 65535 const options(*varsize) Bytes to accumulate
+ D len 10U 0 value Buffer length
+ *
+ **************************************************************************
+ * Miscellaneous function prototypes
+ **************************************************************************
+ *
+ D zError PR * extproc('zError') Error string
+ D err 10I 0 value Error code
+ *
+ D inflateSyncPoint...
+ D PR 10I 0 extproc('inflateSyncPoint')
+ D strm like(z_stream) Expansion stream
+ *
+ D get_crc_table PR * extproc('get_crc_table') Ptr to ulongs
+ *
+ D inflateUndermine...
+ D PR 10I 0 extproc('inflateUndermine')
+ D strm like(z_stream) Expansion stream
+ D arg 10I 0 value Error code
+ *
+ D inflateResetKeep...
+ D PR 10I 0 extproc('inflateResetKeep') End and init. stream
+ D strm like(z_stream) Expansion stream
+ *
+ D deflateResetKeep...
+ D PR 10I 0 extproc('deflateResetKeep') End and init. stream
+ D strm like(z_stream) Expansion stream
+ *
+ /endif
diff --git a/libmariadb/external/zlib/chunkcopy.h b/libmariadb/external/zlib/chunkcopy.h
new file mode 100644
index 00000000..8fd1a0d3
--- /dev/null
+++ b/libmariadb/external/zlib/chunkcopy.h
@@ -0,0 +1,485 @@
+/* chunkcopy.h -- fast chunk copy and set operations
+ *
+ * (C) 1995-2013 Jean-loup Gailly and Mark Adler
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Jean-loup Gailly Mark Adler
+ * jloup@gzip.org madler@alumni.caltech.edu
+ *
+ * Copyright (C) 2017 ARM, Inc.
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the Chromium source repository LICENSE file.
+ */
+
+#ifndef CHUNKCOPY_H
+#define CHUNKCOPY_H
+
+#include <stdint.h>
+#include "zutil.h"
+
+#define Z_STATIC_ASSERT(name, assert) typedef char name[(assert) ? 1 : -1]
+
+#if __STDC_VERSION__ >= 199901L
+#define Z_RESTRICT restrict
+#else
+#define Z_RESTRICT
+#endif
+
+#if defined(__clang__) || defined(__GNUC__) || defined(__llvm__)
+#define Z_BUILTIN_MEMCPY __builtin_memcpy
+#else
+#define Z_BUILTIN_MEMCPY zmemcpy
+#endif
+
+#if defined(INFLATE_CHUNK_SIMD_NEON)
+#include <arm_neon.h>
+typedef uint8x16_t z_vec128i_t;
+#elif defined(INFLATE_CHUNK_SIMD_SSE2)
+#include <emmintrin.h>
+typedef __m128i z_vec128i_t;
+#else
+#error chunkcopy.h inflate chunk SIMD is not defined for your build target
+#endif
+
+/*
+ * chunk copy type: the z_vec128i_t type size should be exactly 128-bits
+ * and equal to CHUNKCOPY_CHUNK_SIZE.
+ */
+#define CHUNKCOPY_CHUNK_SIZE sizeof(z_vec128i_t)
+
+Z_STATIC_ASSERT(vector_128_bits_wide,
+ CHUNKCOPY_CHUNK_SIZE == sizeof(int8_t) * 16);
+
+/*
+ * Ask the compiler to perform a wide, unaligned load with a machine
+ * instruction appropriate for the z_vec128i_t type.
+ */
+static inline z_vec128i_t loadchunk(
+ const unsigned char FAR* s) {
+ z_vec128i_t v;
+ Z_BUILTIN_MEMCPY(&v, s, sizeof(v));
+ return v;
+}
+
+/*
+ * Ask the compiler to perform a wide, unaligned store with a machine
+ * instruction appropriate for the z_vec128i_t type.
+ */
+static inline void storechunk(
+ unsigned char FAR* d,
+ const z_vec128i_t v) {
+ Z_BUILTIN_MEMCPY(d, &v, sizeof(v));
+}
+
+/*
+ * Perform a memcpy-like operation, assuming that length is non-zero and that
+ * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
+ * the length is shorter than this.
+ *
+ * It also guarantees that it will properly unroll the data if the distance
+ * between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on
+ * in chunkcopy_relaxed().
+ *
+ * Aside from better memory bus utilisation, this means that short copies
+ * (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop
+ * without iteration, which will hopefully make the branch prediction more
+ * reliable.
+ */
+static inline unsigned char FAR* chunkcopy_core(
+ unsigned char FAR* out,
+ const unsigned char FAR* from,
+ unsigned len) {
+ const int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1;
+ storechunk(out, loadchunk(from));
+ out += bump;
+ from += bump;
+ len /= CHUNKCOPY_CHUNK_SIZE;
+ while (len-- > 0) {
+ storechunk(out, loadchunk(from));
+ out += CHUNKCOPY_CHUNK_SIZE;
+ from += CHUNKCOPY_CHUNK_SIZE;
+ }
+ return out;
+}
+
+/*
+ * Like chunkcopy_core(), but avoid writing beyond of legal output.
+ *
+ * Accepts an additional pointer to the end of safe output. A generic safe
+ * copy would use (out + len), but it's normally the case that the end of the
+ * output buffer is beyond the end of the current copy, and this can still be
+ * exploited.
+ */
+static inline unsigned char FAR* chunkcopy_core_safe(
+ unsigned char FAR* out,
+ const unsigned char FAR* from,
+ unsigned len,
+ unsigned char FAR* limit) {
+ Assert(out + len <= limit, "chunk copy exceeds safety limit");
+ if ((limit - out) < (ptrdiff_t)CHUNKCOPY_CHUNK_SIZE) {
+ const unsigned char FAR* Z_RESTRICT rfrom = from;
+ if (len & 8) {
+ Z_BUILTIN_MEMCPY(out, rfrom, 8);
+ out += 8;
+ rfrom += 8;
+ }
+ if (len & 4) {
+ Z_BUILTIN_MEMCPY(out, rfrom, 4);
+ out += 4;
+ rfrom += 4;
+ }
+ if (len & 2) {
+ Z_BUILTIN_MEMCPY(out, rfrom, 2);
+ out += 2;
+ rfrom += 2;
+ }
+ if (len & 1) {
+ *out++ = *rfrom++;
+ }
+ return out;
+ }
+ return chunkcopy_core(out, from, len);
+}
+
+/*
+ * Perform short copies until distance can be rewritten as being at least
+ * CHUNKCOPY_CHUNK_SIZE.
+ *
+ * Assumes it's OK to overwrite at least the first 2*CHUNKCOPY_CHUNK_SIZE
+ * bytes of output even if the copy is shorter than this. This assumption
+ * holds within zlib inflate_fast(), which starts every iteration with at
+ * least 258 bytes of output space available (258 being the maximum length
+ * output from a single token; see inffast.c).
+ */
+static inline unsigned char FAR* chunkunroll_relaxed(
+ unsigned char FAR* out,
+ unsigned FAR* dist,
+ unsigned FAR* len) {
+ const unsigned char FAR* from = out - *dist;
+ while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) {
+ storechunk(out, loadchunk(from));
+ out += *dist;
+ *len -= *dist;
+ *dist += *dist;
+ }
+ return out;
+}
+
+#if defined(INFLATE_CHUNK_SIMD_NEON)
+/*
+ * v_load64_dup(): load *src as an unaligned 64-bit int and duplicate it in
+ * every 64-bit component of the 128-bit result (64-bit int splat).
+ */
+static inline z_vec128i_t v_load64_dup(const void* src) {
+ return vcombine_u8(vld1_u8(src), vld1_u8(src));
+}
+
+/*
+ * v_load32_dup(): load *src as an unaligned 32-bit int and duplicate it in
+ * every 32-bit component of the 128-bit result (32-bit int splat).
+ */
+static inline z_vec128i_t v_load32_dup(const void* src) {
+ int32_t i32;
+ Z_BUILTIN_MEMCPY(&i32, src, sizeof(i32));
+ return vreinterpretq_u8_s32(vdupq_n_s32(i32));
+}
+
+/*
+ * v_load16_dup(): load *src as an unaligned 16-bit int and duplicate it in
+ * every 16-bit component of the 128-bit result (16-bit int splat).
+ */
+static inline z_vec128i_t v_load16_dup(const void* src) {
+ int16_t i16;
+ Z_BUILTIN_MEMCPY(&i16, src, sizeof(i16));
+ return vreinterpretq_u8_s16(vdupq_n_s16(i16));
+}
+
+/*
+ * v_load8_dup(): load the 8-bit int *src and duplicate it in every 8-bit
+ * component of the 128-bit result (8-bit int splat).
+ */
+static inline z_vec128i_t v_load8_dup(const void* src) {
+ return vld1q_dup_u8((const uint8_t*)src);
+}
+
+/*
+ * v_store_128(): store the 128-bit vec in a memory destination (that might
+ * not be 16-byte aligned) void* out.
+ */
+static inline void v_store_128(void* out, const z_vec128i_t vec) {
+ vst1q_u8(out, vec);
+}
+#elif defined (INFLATE_CHUNK_SIMD_SSE2)
+/*
+ * v_load64_dup(): load *src as an unaligned 64-bit int and duplicate it in
+ * every 64-bit component of the 128-bit result (64-bit int splat).
+ */
+static inline z_vec128i_t v_load64_dup(const void* src) {
+ int64_t i64;
+ Z_BUILTIN_MEMCPY(&i64, src, sizeof(i64));
+ return _mm_set1_epi64x(i64);
+}
+
+/*
+ * v_load32_dup(): load *src as an unaligned 32-bit int and duplicate it in
+ * every 32-bit component of the 128-bit result (32-bit int splat).
+ */
+static inline z_vec128i_t v_load32_dup(const void* src) {
+ int32_t i32;
+ Z_BUILTIN_MEMCPY(&i32, src, sizeof(i32));
+ return _mm_set1_epi32(i32);
+}
+
+/*
+ * v_load16_dup(): load *src as an unaligned 16-bit int and duplicate it in
+ * every 16-bit component of the 128-bit result (16-bit int splat).
+ */
+static inline z_vec128i_t v_load16_dup(const void* src) {
+ int16_t i16;
+ Z_BUILTIN_MEMCPY(&i16, src, sizeof(i16));
+ return _mm_set1_epi16(i16);
+}
+
+/*
+ * v_load8_dup(): load the 8-bit int *src and duplicate it in every 8-bit
+ * component of the 128-bit result (8-bit int splat).
+ */
+static inline z_vec128i_t v_load8_dup(const void* src) {
+ return _mm_set1_epi8(*(const char*)src);
+}
+
+/*
+ * v_store_128(): store the 128-bit vec in a memory destination (that might
+ * not be 16-byte aligned) void* out.
+ */
+static inline void v_store_128(void* out, const z_vec128i_t vec) {
+ _mm_storeu_si128((__m128i*)out, vec);
+}
+#endif
+
+/*
+ * Perform an overlapping copy which behaves as a memset() operation, but
+ * supporting periods other than one, and assume that length is non-zero and
+ * that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output
+ * even if the length is shorter than this.
+ */
+static inline unsigned char FAR* chunkset_core(
+ unsigned char FAR* out,
+ unsigned period,
+ unsigned len) {
+ z_vec128i_t v;
+ const int bump = ((len - 1) % sizeof(v)) + 1;
+
+ switch (period) {
+ case 1:
+ v = v_load8_dup(out - 1);
+ v_store_128(out, v);
+ out += bump;
+ len -= bump;
+ while (len > 0) {
+ v_store_128(out, v);
+ out += sizeof(v);
+ len -= sizeof(v);
+ }
+ return out;
+ case 2:
+ v = v_load16_dup(out - 2);
+ v_store_128(out, v);
+ out += bump;
+ len -= bump;
+ if (len > 0) {
+ v = v_load16_dup(out - 2);
+ do {
+ v_store_128(out, v);
+ out += sizeof(v);
+ len -= sizeof(v);
+ } while (len > 0);
+ }
+ return out;
+ case 4:
+ v = v_load32_dup(out - 4);
+ v_store_128(out, v);
+ out += bump;
+ len -= bump;
+ if (len > 0) {
+ v = v_load32_dup(out - 4);
+ do {
+ v_store_128(out, v);
+ out += sizeof(v);
+ len -= sizeof(v);
+ } while (len > 0);
+ }
+ return out;
+ case 8:
+ v = v_load64_dup(out - 8);
+ v_store_128(out, v);
+ out += bump;
+ len -= bump;
+ if (len > 0) {
+ v = v_load64_dup(out - 8);
+ do {
+ v_store_128(out, v);
+ out += sizeof(v);
+ len -= sizeof(v);
+ } while (len > 0);
+ }
+ return out;
+ }
+ out = chunkunroll_relaxed(out, &period, &len);
+ return chunkcopy_core(out, out - period, len);
+}
+
+/*
+ * Perform a memcpy-like operation, but assume that length is non-zero and that
+ * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
+ * the length is shorter than this.
+ *
+ * Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour
+ * of overlapping buffers, regardless of the distance between the pointers.
+ * This is reflected in the `restrict`-qualified pointers, allowing the
+ * compiler to re-order loads and stores.
+ */
+static inline unsigned char FAR* chunkcopy_relaxed(
+ unsigned char FAR* Z_RESTRICT out,
+ const unsigned char FAR* Z_RESTRICT from,
+ unsigned len) {
+ return chunkcopy_core(out, from, len);
+}
+
+/*
+ * Like chunkcopy_relaxed(), but avoid writing beyond of legal output.
+ *
+ * Unlike chunkcopy_core_safe() above, no guarantee is made regarding the
+ * behaviour of overlapping buffers, regardless of the distance between the
+ * pointers. This is reflected in the `restrict`-qualified pointers, allowing
+ * the compiler to re-order loads and stores.
+ *
+ * Accepts an additional pointer to the end of safe output. A generic safe
+ * copy would use (out + len), but it's normally the case that the end of the
+ * output buffer is beyond the end of the current copy, and this can still be
+ * exploited.
+ */
+static inline unsigned char FAR* chunkcopy_safe(
+ unsigned char FAR* out,
+ const unsigned char FAR* Z_RESTRICT from,
+ unsigned len,
+ unsigned char FAR* limit) {
+ Assert(out + len <= limit, "chunk copy exceeds safety limit");
+ return chunkcopy_core_safe(out, from, len, limit);
+}
+
+/*
+ * Perform chunky copy within the same buffer, where the source and destination
+ * may potentially overlap.
+ *
+ * Assumes that len > 0 on entry, and that it's safe to write at least
+ * CHUNKCOPY_CHUNK_SIZE*3 bytes to the output.
+ */
+static inline unsigned char FAR* chunkcopy_lapped_relaxed(
+ unsigned char FAR* out,
+ unsigned dist,
+ unsigned len) {
+ if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) {
+ return chunkset_core(out, dist, len);
+ }
+ return chunkcopy_core(out, out - dist, len);
+}
+
+/*
+ * Behave like chunkcopy_lapped_relaxed(), but avoid writing beyond of legal
+ * output.
+ *
+ * Accepts an additional pointer to the end of safe output. A generic safe
+ * copy would use (out + len), but it's normally the case that the end of the
+ * output buffer is beyond the end of the current copy, and this can still be
+ * exploited.
+ */
+static inline unsigned char FAR* chunkcopy_lapped_safe(
+ unsigned char FAR* out,
+ unsigned dist,
+ unsigned len,
+ unsigned char FAR* limit) {
+ Assert(out + len <= limit, "chunk copy exceeds safety limit");
+ if ((limit - out) < (ptrdiff_t)(3 * CHUNKCOPY_CHUNK_SIZE)) {
+ /* TODO(cavalcantii): try harder to optimise this */
+ while (len-- > 0) {
+ *out = *(out - dist);
+ out++;
+ }
+ return out;
+ }
+ return chunkcopy_lapped_relaxed(out, dist, len);
+}
+
+/* TODO(cavalcanti): see crbug.com/1110083. */
+static inline unsigned char FAR* chunkcopy_safe_ugly(unsigned char FAR* out,
+ unsigned dist,
+ unsigned len,
+ unsigned char FAR* limit) {
+#if defined(__GNUC__) && !defined(__clang__)
+ /* Speed is the same as using chunkcopy_safe
+ w/ GCC on ARM (tested gcc 6.3 and 7.5) and avoids
+ undefined behavior.
+ */
+ return chunkcopy_core_safe(out, out - dist, len, limit);
+#elif defined(__clang__) && !defined(__aarch64__)
+ /* Seems to perform better on 32bit (i.e. Android). */
+ return chunkcopy_core_safe(out, out - dist, len, limit);
+#else
+ /* Seems to perform better on 64-bit. */
+ return chunkcopy_lapped_safe(out, dist, len, limit);
+#endif
+}
+
+/*
+ * The chunk-copy code above deals with writing the decoded DEFLATE data to
+ * the output with SIMD methods to increase decode speed. Reading the input
+ * to the DEFLATE decoder with a wide, SIMD method can also increase decode
+ * speed. This option is supported on little endian machines, and reads the
+ * input data in 64-bit (8 byte) chunks.
+ */
+
+#ifdef INFLATE_CHUNK_READ_64LE
+/*
+ * Buffer the input in a uint64_t (8 bytes) in the wide input reading case.
+ */
+typedef uint64_t inflate_holder_t;
+
+/*
+ * Ask the compiler to perform a wide, unaligned load of a uint64_t using a
+ * machine instruction appropriate for the uint64_t type.
+ */
+static inline inflate_holder_t read64le(const unsigned char FAR *in) {
+ inflate_holder_t input;
+ Z_BUILTIN_MEMCPY(&input, in, sizeof(input));
+ return input;
+}
+#else
+/*
+ * Otherwise, buffer the input bits using zlib's default input buffer type.
+ */
+typedef unsigned long inflate_holder_t;
+
+#endif /* INFLATE_CHUNK_READ_64LE */
+
+#undef Z_STATIC_ASSERT
+#undef Z_RESTRICT
+#undef Z_BUILTIN_MEMCPY
+
+#endif /* CHUNKCOPY_H */
diff --git a/libmariadb/external/zlib/compress.c b/libmariadb/external/zlib/compress.c
new file mode 100644
index 00000000..2ad5326c
--- /dev/null
+++ b/libmariadb/external/zlib/compress.c
@@ -0,0 +1,86 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2(dest, destLen, source, sourceLen, level)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+ int level;
+{
+ z_stream stream;
+ int err;
+ const uInt max = (uInt)-1;
+ uLong left;
+
+ left = *destLen;
+ *destLen = 0;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ stream.next_out = dest;
+ stream.avail_out = 0;
+ stream.next_in = (z_const Bytef *)source;
+ stream.avail_in = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > (uLong)max ? max : (uInt)left;
+ left -= stream.avail_out;
+ }
+ if (stream.avail_in == 0) {
+ stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
+ sourceLen -= stream.avail_in;
+ }
+ err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
+ } while (err == Z_OK);
+
+ *destLen = stream.total_out;
+ deflateEnd(&stream);
+ return err == Z_STREAM_END ? Z_OK : err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress(dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound(sourceLen)
+ uLong sourceLen;
+{
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13;
+}
diff --git a/libmariadb/external/zlib/configure b/libmariadb/external/zlib/configure
new file mode 100755
index 00000000..6e22cbdf
--- /dev/null
+++ b/libmariadb/external/zlib/configure
@@ -0,0 +1,931 @@
+#!/bin/sh
+# configure script for zlib.
+#
+# Normally configure builds both a static and a shared library.
+# If you want to build just a static library, use: ./configure --static
+#
+# To impose specific compiler or flags or install directory, use for example:
+# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
+# or for csh/tcsh users:
+# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
+
+# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
+# If you have problems, try without defining CC and CFLAGS before reporting
+# an error.
+
+# start off configure.log
+echo -------------------- >> configure.log
+echo $0 $* >> configure.log
+date >> configure.log
+
+# set command prefix for cross-compilation
+if [ -n "${CHOST}" ]; then
+ uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`"
+ CROSS_PREFIX="${CHOST}-"
+fi
+
+# destination name for static library
+STATICLIB=libz.a
+
+# extract zlib version numbers from zlib.h
+VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`
+VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < zlib.h`
+VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h`
+VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h`
+
+# establish commands for library building
+if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
+ AR=${AR-"${CROSS_PREFIX}ar"}
+ test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
+else
+ AR=${AR-"ar"}
+ test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
+fi
+ARFLAGS=${ARFLAGS-"rc"}
+if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then
+ RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"}
+ test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log
+else
+ RANLIB=${RANLIB-"ranlib"}
+fi
+if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then
+ NM=${NM-"${CROSS_PREFIX}nm"}
+ test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log
+else
+ NM=${NM-"nm"}
+fi
+
+# set defaults before processing command line options
+LDCONFIG=${LDCONFIG-"ldconfig"}
+LDSHAREDLIBC="${LDSHAREDLIBC--lc}"
+ARCHS= # target specific flags
+TGT_ARCH=$(uname -m) # the name of target architecture
+prefix=${prefix-/usr/local}
+exec_prefix=${exec_prefix-'${prefix}'}
+libdir=${libdir-'${exec_prefix}/lib'}
+sharedlibdir=${sharedlibdir-'${libdir}'}
+includedir=${includedir-'${prefix}/include'}
+mandir=${mandir-'${prefix}/share/man'}
+shared_ext='.so'
+shared=1
+solo=0
+cover=0
+zprefix=0
+zconst=0
+build64=0
+gcc=0
+old_cc="$CC"
+old_cflags="$CFLAGS"
+OBJC='$(OBJZ) $(OBJG)'
+PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)'
+
+# leave this script, optionally in a bad way
+leave()
+{
+ if test "$*" != "0"; then
+ echo "** $0 aborting." | tee -a configure.log
+ fi
+ rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version
+ echo -------------------- >> configure.log
+ echo >> configure.log
+ echo >> configure.log
+ exit $1
+}
+
+# process command line options
+while test $# -ge 1
+do
+case "$1" in
+ -h* | --help)
+ echo 'usage:' | tee -a configure.log
+ echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log
+ echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log
+ echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log
+ exit 0 ;;
+ -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
+ -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
+ -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;;
+ --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;;
+ -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;;
+ -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;;
+ -p* | --prefix) prefix="$2"; shift; shift ;;
+ -e* | --eprefix) exec_prefix="$2"; shift; shift ;;
+ -l* | --libdir) libdir="$2"; shift; shift ;;
+ -i* | --includedir) includedir="$2"; shift; shift ;;
+ -s* | --shared | --enable-shared) shared=1; shift ;;
+ -t | --static) shared=0; shift ;;
+ --solo) solo=1; shift ;;
+ --cover) cover=1; shift ;;
+ -z* | --zprefix) zprefix=1; shift ;;
+ -6* | --64) build64=1; shift ;;
+ -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;;
+ -T*=* | --target=*) TGT_ARCH=`echo $1 | sed 's/.*=//'`; shift ;;
+ --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;;
+ --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;;
+ -c* | --const) zconst=1; shift ;;
+ *)
+ echo "unknown option: $1" | tee -a configure.log
+ echo "$0 --help for help" | tee -a configure.log
+ leave 1;;
+ esac
+done
+
+# temporary file name
+test=ztest$$
+
+# put arguments in log, also put test file in log if used in arguments
+show()
+{
+ case "$*" in
+ *$test.c*)
+ echo === $test.c === >> configure.log
+ cat $test.c >> configure.log
+ echo === >> configure.log;;
+ esac
+ echo $* >> configure.log
+}
+
+# check for gcc vs. cc and set compile and link flags based on the system identified by uname
+cat > $test.c <<EOF
+extern int getchar();
+int hello() {return getchar();}
+EOF
+
+test -z "$CC" && echo Checking for ${CROSS_PREFIX}gcc... | tee -a configure.log
+cc=${CC-${CROSS_PREFIX}gcc}
+cflags=${CFLAGS-"-O3"}
+# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
+case "$cc" in
+ *gcc*) gcc=1 ;;
+ *clang*) gcc=1 ;;
+esac
+case `$cc -v 2>&1` in
+ *gcc*) gcc=1 ;;
+esac
+
+show $cc -c $test.c
+if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then
+ echo ... using gcc >> configure.log
+ CC="$cc"
+ CFLAGS="${CFLAGS--O3} ${ARCHS}"
+ SFLAGS="${CFLAGS--O3} -fPIC"
+ LDFLAGS="${LDFLAGS} ${ARCHS}"
+ if test $build64 -eq 1; then
+ CFLAGS="${CFLAGS} -m64"
+ SFLAGS="${SFLAGS} -m64"
+ fi
+ if test "${ZLIBGCCWARN}" = "YES"; then
+ if test "$zconst" -eq 1; then
+ CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST"
+ else
+ CFLAGS="${CFLAGS} -Wall -Wextra -pedantic"
+ fi
+ fi
+ if test -z "$uname"; then
+ uname=`(uname -s || echo unknown) 2>/dev/null`
+ fi
+ case "$uname" in
+ Linux* | linux* | GNU | GNU/* | solaris*)
+ LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"} ;;
+ *BSD | *bsd* | DragonFly)
+ LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"}
+ LDCONFIG="ldconfig -m" ;;
+ CYGWIN* | Cygwin* | cygwin* | OS/2*)
+ EXE='.exe' ;;
+ MINGW* | mingw*)
+# temporary bypass
+ rm -f $test.[co] $test $test$shared_ext
+ echo "Please use win32/Makefile.gcc instead." | tee -a configure.log
+ leave 1
+ LDSHARED=${LDSHARED-"$cc -shared"}
+ LDSHAREDLIBC=""
+ EXE='.exe' ;;
+ QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
+ # (alain.bonnefoy@icbt.com)
+ LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;;
+ HP-UX*)
+ LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
+ case `(uname -m || echo unknown) 2>/dev/null` in
+ ia64)
+ shared_ext='.so'
+ SHAREDLIB='libz.so' ;;
+ *)
+ shared_ext='.sl'
+ SHAREDLIB='libz.sl' ;;
+ esac ;;
+ Darwin* | darwin*)
+ shared_ext='.dylib'
+ SHAREDLIB=libz$shared_ext
+ SHAREDLIBV=libz.$VER$shared_ext
+ SHAREDLIBM=libz.$VER1$shared_ext
+ LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
+ if libtool -V 2>&1 | grep Apple > /dev/null; then
+ AR="libtool"
+ else
+ AR="/usr/bin/libtool"
+ fi
+ ARFLAGS="-o" ;;
+ *) LDSHARED=${LDSHARED-"$cc -shared"} ;;
+ esac
+else
+ # find system name and corresponding cc options
+ CC=${CC-cc}
+ gcc=0
+ echo ... using $CC >> configure.log
+ if test -z "$uname"; then
+ uname=`(uname -sr || echo unknown) 2>/dev/null`
+ fi
+ case "$uname" in
+ HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
+ CFLAGS=${CFLAGS-"-O"}
+# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
+ LDSHARED=${LDSHARED-"ld -b"}
+ case `(uname -m || echo unknown) 2>/dev/null` in
+ ia64)
+ shared_ext='.so'
+ SHAREDLIB='libz.so' ;;
+ *)
+ shared_ext='.sl'
+ SHAREDLIB='libz.sl' ;;
+ esac ;;
+ IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
+ CFLAGS=${CFLAGS-"-ansi -O2"}
+ LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
+ OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
+ CFLAGS=${CFLAGS-"-O -std1"}
+ LDFLAGS="${LDFLAGS} -Wl,-rpath,."
+ LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;;
+ OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
+ CFLAGS=${CFLAGS-"-O -std1"}
+ LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
+ QNX*) SFLAGS=${CFLAGS-"-4 -O"}
+ CFLAGS=${CFLAGS-"-4 -O"}
+ LDSHARED=${LDSHARED-"cc"}
+ RANLIB=${RANLIB-"true"}
+ AR="cc"
+ ARFLAGS="-A" ;;
+ SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
+ CFLAGS=${CFLAGS-"-O3"}
+ LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;;
+ SunOS\ 5* | solaris*)
+ LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"}
+ SFLAGS=${CFLAGS-"-fast -KPIC"}
+ CFLAGS=${CFLAGS-"-fast"}
+ if test $build64 -eq 1; then
+ # old versions of SunPRO/Workshop/Studio don't support -m64,
+ # but newer ones do. Check for it.
+ flag64=`$CC -flags | egrep -- '^-m64'`
+ if test x"$flag64" != x"" ; then
+ CFLAGS="${CFLAGS} -m64"
+ SFLAGS="${SFLAGS} -m64"
+ else
+ case `(uname -m || echo unknown) 2>/dev/null` in
+ i86*)
+ SFLAGS="$SFLAGS -xarch=amd64"
+ CFLAGS="$CFLAGS -xarch=amd64" ;;
+ *)
+ SFLAGS="$SFLAGS -xarch=v9"
+ CFLAGS="$CFLAGS -xarch=v9" ;;
+ esac
+ fi
+ fi
+ ;;
+ SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
+ CFLAGS=${CFLAGS-"-O2"}
+ LDSHARED=${LDSHARED-"ld"} ;;
+ SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
+ CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"}
+ LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;;
+ UNIX_System_V\ 4.2.0)
+ SFLAGS=${CFLAGS-"-KPIC -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"} ;;
+ UNIX_SV\ 4.2MP)
+ SFLAGS=${CFLAGS-"-Kconform_pic -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"} ;;
+ OpenUNIX\ 5)
+ SFLAGS=${CFLAGS-"-KPIC -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"} ;;
+ AIX*) # Courtesy of dbakker@arrayasolutions.com
+ SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
+ CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
+ LDSHARED=${LDSHARED-"xlc -G"} ;;
+ # send working options for other systems to zlib@gzip.org
+ *) SFLAGS=${CFLAGS-"-O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -shared"} ;;
+ esac
+fi
+
+# destination names for shared library if not defined above
+SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
+SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
+SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
+
+echo >> configure.log
+
+# define functions for testing compiler and library characteristics and logging the results
+
+cat > $test.c <<EOF
+#error error
+EOF
+if ($CC -c $CFLAGS $test.c) 2>/dev/null; then
+ try()
+ {
+ show $*
+ test "`( $* ) 2>&1 | tee -a configure.log`" = ""
+ }
+ echo - using any output from compiler to indicate an error >> configure.log
+else
+try()
+{
+ show $*
+ ( $* ) >> configure.log 2>&1
+ ret=$?
+ if test $ret -ne 0; then
+ echo "(exit code "$ret")" >> configure.log
+ fi
+ return $ret
+}
+fi
+
+tryboth()
+{
+ show $*
+ got=`( $* ) 2>&1`
+ ret=$?
+ printf %s "$got" >> configure.log
+ if test $ret -ne 0; then
+ return $ret
+ fi
+ test "$got" = ""
+}
+
+cat > $test.c << EOF
+int foo() { return 0; }
+EOF
+echo "Checking for obsessive-compulsive compiler options..." >> configure.log
+if try $CC -c $CFLAGS $test.c; then
+ :
+else
+ echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log
+ leave 1
+fi
+
+echo >> configure.log
+
+# see if shared library build supported
+cat > $test.c <<EOF
+extern int getchar();
+int hello() {return getchar();}
+EOF
+if test $shared -eq 1; then
+ echo Checking for shared library support... | tee -a configure.log
+ # we must test in two steps (cc then ld), required at least on SunOS 4.x
+ if try $CC -w -c $SFLAGS $test.c &&
+ try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
+ echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
+ elif test -z "$old_cc" -a -z "$old_cflags"; then
+ echo No shared library support. | tee -a configure.log
+ shared=0;
+ else
+ echo 'No shared library support; try without defining CC and CFLAGS' | tee -a configure.log
+ shared=0;
+ fi
+fi
+if test $shared -eq 0; then
+ LDSHARED="$CC"
+ ALL="static"
+ TEST="all teststatic"
+ SHAREDLIB=""
+ SHAREDLIBV=""
+ SHAREDLIBM=""
+ echo Building static library $STATICLIB version $VER with $CC. | tee -a configure.log
+else
+ ALL="static shared"
+ TEST="all teststatic testshared"
+fi
+
+# check for underscores in external names for use by assembler code
+CPP=${CPP-"$CC -E"}
+case $CFLAGS in
+ *ASMV*)
+ echo >> configure.log
+ show "$NM $test.o | grep _hello"
+ if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then
+ CPP="$CPP -DNO_UNDERLINE"
+ echo Checking for underline in external names... No. | tee -a configure.log
+ else
+ echo Checking for underline in external names... Yes. | tee -a configure.log
+ fi ;;
+esac
+
+echo >> configure.log
+
+# check for large file support, and if none, check for fseeko()
+cat > $test.c <<EOF
+#include <sys/types.h>
+off64_t dummy = 0;
+EOF
+if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then
+ CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1"
+ SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1"
+ ALL="${ALL} all64"
+ TEST="${TEST} test64"
+ echo "Checking for off64_t... Yes." | tee -a configure.log
+ echo "Checking for fseeko... Yes." | tee -a configure.log
+else
+ echo "Checking for off64_t... No." | tee -a configure.log
+ echo >> configure.log
+ cat > $test.c <<EOF
+#include <stdio.h>
+int main(void) {
+ fseeko(NULL, 0, 0);
+ return 0;
+}
+EOF
+ if try $CC $CFLAGS -o $test $test.c; then
+ echo "Checking for fseeko... Yes." | tee -a configure.log
+ else
+ CFLAGS="${CFLAGS} -DNO_FSEEKO"
+ SFLAGS="${SFLAGS} -DNO_FSEEKO"
+ echo "Checking for fseeko... No." | tee -a configure.log
+ fi
+fi
+
+echo >> configure.log
+
+# check for strerror() for use by gz* functions
+cat > $test.c <<EOF
+#include <string.h>
+#include <errno.h>
+int main() { return strlen(strerror(errno)); }
+EOF
+if try $CC $CFLAGS -o $test $test.c; then
+ echo "Checking for strerror... Yes." | tee -a configure.log
+else
+ CFLAGS="${CFLAGS} -DNO_STRERROR"
+ SFLAGS="${SFLAGS} -DNO_STRERROR"
+ echo "Checking for strerror... No." | tee -a configure.log
+fi
+
+# copy clean zconf.h for subsequent edits
+cp -p zconf.h.in zconf.h
+
+echo >> configure.log
+
+# check for unistd.h and save result in zconf.h
+cat > $test.c <<EOF
+#include <unistd.h>
+int main() { return 0; }
+EOF
+if try $CC -c $CFLAGS $test.c; then
+ sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
+ mv zconf.temp.h zconf.h
+ echo "Checking for unistd.h... Yes." | tee -a configure.log
+else
+ echo "Checking for unistd.h... No." | tee -a configure.log
+fi
+
+echo >> configure.log
+
+# check for stdarg.h and save result in zconf.h
+cat > $test.c <<EOF
+#include <stdarg.h>
+int main() { return 0; }
+EOF
+if try $CC -c $CFLAGS $test.c; then
+ sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
+ mv zconf.temp.h zconf.h
+ echo "Checking for stdarg.h... Yes." | tee -a configure.log
+else
+ echo "Checking for stdarg.h... No." | tee -a configure.log
+fi
+
+# if the z_ prefix was requested, save that in zconf.h
+if test $zprefix -eq 1; then
+ sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h
+ mv zconf.temp.h zconf.h
+ echo >> configure.log
+ echo "Using z_ prefix on all symbols." | tee -a configure.log
+fi
+
+# if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists
+if test $solo -eq 1; then
+ sed '/#define ZCONF_H/a\
+#define Z_SOLO
+
+' < zconf.h > zconf.temp.h
+ mv zconf.temp.h zconf.h
+OBJC='$(OBJZ)'
+PIC_OBJC='$(PIC_OBJZ)'
+fi
+
+# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X
+if test $cover -eq 1; then
+ CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage"
+ if test -n "$GCC_CLASSIC"; then
+ CC=$GCC_CLASSIC
+ fi
+fi
+
+echo >> configure.log
+
+# conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions
+# (using stdarg or not), with or without "n" (proving size of buffer), and with or without a
+# return value. The most secure result is vsnprintf() with a return value. snprintf() with a
+# return value is secure as well, but then gzprintf() will be limited to 20 arguments.
+cat > $test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+#include "zconf.h"
+int main()
+{
+#ifndef STDC
+ choke me
+#endif
+ return 0;
+}
+EOF
+if try $CC -c $CFLAGS $test.c; then
+ echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log
+
+ echo >> configure.log
+ cat > $test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+int mytest(const char *fmt, ...)
+{
+ char buf[20];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ return 0;
+}
+int main()
+{
+ return (mytest("Hello%d\n", 1));
+}
+EOF
+ if try $CC $CFLAGS -o $test $test.c; then
+ echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log
+
+ echo >> configure.log
+ cat >$test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+int mytest(const char *fmt, ...)
+{
+ int n;
+ char buf[20];
+ va_list ap;
+ va_start(ap, fmt);
+ n = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ return n;
+}
+int main()
+{
+ return (mytest("Hello%d\n", 1));
+}
+EOF
+
+ if try $CC -c $CFLAGS $test.c; then
+ echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log
+ else
+ CFLAGS="$CFLAGS -DHAS_vsnprintf_void"
+ SFLAGS="$SFLAGS -DHAS_vsnprintf_void"
+ echo "Checking for return value of vsnprintf()... No." | tee -a configure.log
+ echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log
+ echo " can build but will be open to possible string-format security" | tee -a configure.log
+ echo " vulnerabilities." | tee -a configure.log
+ fi
+ else
+ CFLAGS="$CFLAGS -DNO_vsnprintf"
+ SFLAGS="$SFLAGS -DNO_vsnprintf"
+ echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log
+ echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log
+ echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log
+ echo " vulnerabilities." | tee -a configure.log
+
+ echo >> configure.log
+ cat >$test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+int mytest(const char *fmt, ...)
+{
+ int n;
+ char buf[20];
+ va_list ap;
+ va_start(ap, fmt);
+ n = vsprintf(buf, fmt, ap);
+ va_end(ap);
+ return n;
+}
+int main()
+{
+ return (mytest("Hello%d\n", 1));
+}
+EOF
+
+ if try $CC -c $CFLAGS $test.c; then
+ echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log
+ else
+ CFLAGS="$CFLAGS -DHAS_vsprintf_void"
+ SFLAGS="$SFLAGS -DHAS_vsprintf_void"
+ echo "Checking for return value of vsprintf()... No." | tee -a configure.log
+ echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log
+ echo " can build but will be open to possible string-format security" | tee -a configure.log
+ echo " vulnerabilities." | tee -a configure.log
+ fi
+ fi
+else
+ echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log
+
+ echo >> configure.log
+ cat >$test.c <<EOF
+#include <stdio.h>
+int mytest()
+{
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%s", "foo");
+ return 0;
+}
+int main()
+{
+ return (mytest());
+}
+EOF
+
+ if try $CC $CFLAGS -o $test $test.c; then
+ echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log
+
+ echo >> configure.log
+ cat >$test.c <<EOF
+#include <stdio.h>
+int mytest()
+{
+ char buf[20];
+ return snprintf(buf, sizeof(buf), "%s", "foo");
+}
+int main()
+{
+ return (mytest());
+}
+EOF
+
+ if try $CC -c $CFLAGS $test.c; then
+ echo "Checking for return value of snprintf()... Yes." | tee -a configure.log
+ else
+ CFLAGS="$CFLAGS -DHAS_snprintf_void"
+ SFLAGS="$SFLAGS -DHAS_snprintf_void"
+ echo "Checking for return value of snprintf()... No." | tee -a configure.log
+ echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log
+ echo " can build but will be open to possible string-format security" | tee -a configure.log
+ echo " vulnerabilities." | tee -a configure.log
+ fi
+ else
+ CFLAGS="$CFLAGS -DNO_snprintf"
+ SFLAGS="$SFLAGS -DNO_snprintf"
+ echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log
+ echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log
+ echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log
+ echo " vulnerabilities." | tee -a configure.log
+
+ echo >> configure.log
+ cat >$test.c <<EOF
+#include <stdio.h>
+int mytest()
+{
+ char buf[20];
+ return sprintf(buf, "%s", "foo");
+}
+int main()
+{
+ return (mytest());
+}
+EOF
+
+ if try $CC -c $CFLAGS $test.c; then
+ echo "Checking for return value of sprintf()... Yes." | tee -a configure.log
+ else
+ CFLAGS="$CFLAGS -DHAS_sprintf_void"
+ SFLAGS="$SFLAGS -DHAS_sprintf_void"
+ echo "Checking for return value of sprintf()... No." | tee -a configure.log
+ echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log
+ echo " can build but will be open to possible string-format security" | tee -a configure.log
+ echo " vulnerabilities." | tee -a configure.log
+ fi
+ fi
+fi
+
+# see if we can hide zlib internal symbols that are linked between separate source files
+if test "$gcc" -eq 1; then
+ echo >> configure.log
+ cat > $test.c <<EOF
+#define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+int ZLIB_INTERNAL foo;
+int main()
+{
+ return 0;
+}
+EOF
+ if tryboth $CC -c $CFLAGS $test.c; then
+ CFLAGS="$CFLAGS -DHAVE_HIDDEN"
+ SFLAGS="$SFLAGS -DHAVE_HIDDEN"
+ echo "Checking for attribute(visibility) support... Yes." | tee -a configure.log
+ else
+ echo "Checking for attribute(visibility) support... No." | tee -a configure.log
+ fi
+fi
+
+# Check for AMD64 hardware support.
+if [ x$TGT_ARCH = "xx86_64" -o x$TGT_ARCH = "xamd64" ] ; then
+
+cat > $test.c << EOF
+#include <emmintrin.h>
+void foo(void) {
+ __m64 a, b;
+ _mm_add_si64(a, b);
+}
+EOF
+ if try $CC -msse2 $CFLAGS $test.c -c $test; then
+ CFLAGS="-DINFLATE_CHUNK_SIMD_SSE2 -msse2 -DINFLATE_CHUNK_READ_64LE $CFLAGS"
+ SFLAGS="-DINFLATE_CHUNK_SIMD_SSE2 -msse2 -DINFLATE_CHUNK_READ_64LE $SFLAGS"
+ echo "Checking for SSE2 support ... Yes" | tee -a configure.log
+ else
+ echo "Checking for SSE2 support ... No" | tee -a configure.log
+ leave 1
+ fi
+
+# Check for SSSE3 support
+cat > $test.c << EOF
+#include <tmmintrin.h>
+void foo(void) {
+ __m128i a;
+ _mm_abs_epi8(a);
+}
+EOF
+ if try $CC -mssse3 $CFLAGS $test.c -c $test; then
+ CFLAGS="-DADLER32_SIMD_SSSE3 -mssse3 $CFLAGS"
+ SFLAGS="-DADLER32_SIMD_SSSE3 -mssse3 $SFLAGS"
+ echo "Checking for SSSE3 support ... Yes" | tee -a configure.log
+ else
+ echo "Checking for SSSE3 support ... No" | tee -a configure.log
+ leave 1
+ fi
+
+ # Check for SSE4.2 and CRC support
+cat > $test.c << EOF
+#include <immintrin.h>
+void foo(void) {
+ _mm_crc32_u32(0, 0);
+}
+EOF
+
+ if try $CC -msse4.2 $CFLAGS $test.c -c $test; then
+ CFLAGS="-DHAS_SSE42 -msse4.2 $CFLAGS"
+ SFLAGS="-DHAS_SSE42 -msse4.2 $SFLAGS"
+ echo "Checking for CRC and SSE4.2 support ... Yes" | tee -a configure.log
+ else
+ echo "Checking for CRC and SSE4.2 support ... No" | tee -a configure.log
+ echo "CRC and SSE4.2 support is required" | tee -a configure.log
+ leave 1
+ fi
+#Project copied from zlib-ng:
+# Check for PCLMUL support
+cat > $test.c << EOF
+#include <immintrin.h>
+int main(void) {
+ __m128i a = _mm_setzero_si128();
+ __m128i b = _mm_setzero_si128();
+ __m128i c = _mm_clmulepi64_si128(a, b, 0x10);
+ (void)c;
+ return 0;
+}
+EOF
+ if try $CC -c -mpclmul $CFLAGS $test.c ; then
+ CFLAGS="-DHAS_PCLMUL -mpclmul $CFLAGS"
+ SFLAGS="-DHAS_PCLMUL -mpclmul $SFLAGS"
+ echo "Checking for PCLMUL support ... Yes" | tee -a configure.log
+ else
+ echo "Checking for PCLMUL support ... No" | tee -a configure.log
+ fi
+
+elif [ x$TGT_ARCH = "xaarch64" ] ; then
+
+ # Check for NEON and CRC support
+cat > $test.c << EOF
+#include <arm_neon.h>
+#include <arm_acle.h>
+void foo(void) {
+ __crc32cw(0, 0);
+ vqsubq_u16(vmovq_n_u16(1), vmovq_n_u16(2));
+}
+EOF
+
+ if try $CC -march=armv8-a+crc $CFLAGS $test.c -c $test; then
+ CFLAGS="-march=armv8-a+crc -DADLER32_SIMD_NEON -DINFLATE_CHUNK_SIMD_NEON -DINFLATE_CHUNK_READ_64LE $CFLAGS"
+ SFLAGS="-march=armv8-a+crc -DADLER32_SIMD_NEON -DINFLATE_CHUNK_SIMD_NEON -DINFLATE_CHUNK_READ_64LE $SFLAGS"
+ echo "Checking for CRC and NEON support ... Yes" | tee -a configure.log
+ else
+ echo "Checking for CRC and NEON support ... No" | tee -a configure.log
+ echo "CRC and NEON support is required" | tee -a configure.log
+ leave 1
+ fi
+
+fi # end of "Check amd64 hardware support"
+
+# show the results in the log
+echo >> configure.log
+echo ALL = $ALL >> configure.log
+echo AR = $AR >> configure.log
+echo ARFLAGS = $ARFLAGS >> configure.log
+echo CC = $CC >> configure.log
+echo CFLAGS = $CFLAGS >> configure.log
+echo CPP = $CPP >> configure.log
+echo EXE = $EXE >> configure.log
+echo LDCONFIG = $LDCONFIG >> configure.log
+echo LDFLAGS = $LDFLAGS >> configure.log
+echo LDSHARED = $LDSHARED >> configure.log
+echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log
+echo OBJC = $OBJC >> configure.log
+echo PIC_OBJC = $PIC_OBJC >> configure.log
+echo RANLIB = $RANLIB >> configure.log
+echo SFLAGS = $SFLAGS >> configure.log
+echo SHAREDLIB = $SHAREDLIB >> configure.log
+echo SHAREDLIBM = $SHAREDLIBM >> configure.log
+echo SHAREDLIBV = $SHAREDLIBV >> configure.log
+echo STATICLIB = $STATICLIB >> configure.log
+echo TEST = $TEST >> configure.log
+echo VER = $VER >> configure.log
+echo Z_U4 = $Z_U4 >> configure.log
+echo exec_prefix = $exec_prefix >> configure.log
+echo includedir = $includedir >> configure.log
+echo libdir = $libdir >> configure.log
+echo mandir = $mandir >> configure.log
+echo prefix = $prefix >> configure.log
+echo sharedlibdir = $sharedlibdir >> configure.log
+echo uname = $uname >> configure.log
+
+# udpate Makefile with the configure results
+sed < Makefile.in "
+/^TGT_ARCH *=/s#=.*#=$TGT_ARCH#
+/^CC *=/s#=.*#=$CC#
+/^CFLAGS *=/s#=.*#=$CFLAGS#
+/^SFLAGS *=/s#=.*#=$SFLAGS#
+/^LDFLAGS *=/s#=.*#=$LDFLAGS#
+/^LDSHARED *=/s#=.*#=$LDSHARED#
+/^CPP *=/s#=.*#=$CPP#
+/^STATICLIB *=/s#=.*#=$STATICLIB#
+/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
+/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
+/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
+/^AR *=/s#=.*#=$AR#
+/^ARFLAGS *=/s#=.*#=$ARFLAGS#
+/^RANLIB *=/s#=.*#=$RANLIB#
+/^LDCONFIG *=/s#=.*#=$LDCONFIG#
+/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC#
+/^EXE *=/s#=.*#=$EXE#
+/^prefix *=/s#=.*#=$prefix#
+/^exec_prefix *=/s#=.*#=$exec_prefix#
+/^libdir *=/s#=.*#=$libdir#
+/^sharedlibdir *=/s#=.*#=$sharedlibdir#
+/^includedir *=/s#=.*#=$includedir#
+/^mandir *=/s#=.*#=$mandir#
+/^OBJC *=/s#=.*#= $OBJC#
+/^PIC_OBJC *=/s#=.*#= $PIC_OBJC#
+/^all: */s#:.*#: $ALL#
+/^test: */s#:.*#: $TEST#
+" > Makefile
+
+# create zlib.pc with the configure results
+sed < zlib.pc.in "
+/^CC *=/s#=.*#=$CC#
+/^CFLAGS *=/s#=.*#=$CFLAGS#
+/^CPP *=/s#=.*#=$CPP#
+/^LDSHARED *=/s#=.*#=$LDSHARED#
+/^STATICLIB *=/s#=.*#=$STATICLIB#
+/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
+/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
+/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
+/^AR *=/s#=.*#=$AR#
+/^ARFLAGS *=/s#=.*#=$ARFLAGS#
+/^RANLIB *=/s#=.*#=$RANLIB#
+/^EXE *=/s#=.*#=$EXE#
+/^prefix *=/s#=.*#=$prefix#
+/^exec_prefix *=/s#=.*#=$exec_prefix#
+/^libdir *=/s#=.*#=$libdir#
+/^sharedlibdir *=/s#=.*#=$sharedlibdir#
+/^includedir *=/s#=.*#=$includedir#
+/^mandir *=/s#=.*#=$mandir#
+/^LDFLAGS *=/s#=.*#=$LDFLAGS#
+" | sed -e "
+s/\@VERSION\@/$VER/g;
+" > zlib.pc
+
+# done
+leave 0
diff --git a/libmariadb/external/zlib/crc32.c b/libmariadb/external/zlib/crc32.c
new file mode 100644
index 00000000..f8357b08
--- /dev/null
+++ b/libmariadb/external/zlib/crc32.c
@@ -0,0 +1,1125 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * This interleaved implementation of a CRC makes use of pipelined multiple
+ * arithmetic-logic units, commonly found in modern CPU cores. It is due to
+ * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
+ */
+
+/* @(#) $Id$ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+
+ MAKECRCH can be #defined to write out crc32.h. A main() routine is also
+ produced, so that this one source file can be compiled to an executable.
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
+
+ /*
+ A CRC of a message is computed on N braids of words in the message, where
+ each word consists of W bytes (4 or 8). If N is 3, for example, then three
+ running sparse CRCs are calculated respectively on each braid, at these
+ indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
+ This is done starting at a word boundary, and continues until as many blocks
+ of N * W bytes as are available have been processed. The results are combined
+ into a single CRC at the end. For this code, N must be in the range 1..6 and
+ W must be 4 or 8. The upper limit on N can be increased if desired by adding
+ more #if blocks, extending the patterns apparent in the code. In addition,
+ crc32.h would need to be regenerated, if the maximum N value is increased.
+
+ N and W are chosen empirically by benchmarking the execution time on a given
+ processor. The choices for N and W below were based on testing on Intel Kaby
+ Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
+ Octeon II processors. The Intel, AMD, and ARM processors were all fastest
+ with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
+ They were all tested with either gcc or clang, all using the -O3 optimization
+ level. Your mileage may vary.
+ */
+
+/* Define N */
+#ifdef Z_TESTN
+# define N Z_TESTN
+#else
+# define N 5
+#endif
+#if N < 1 || N > 6
+# error N must be in 1..6
+#endif
+
+/*
+ z_crc_t must be at least 32 bits. z_word_t must be at least as long as
+ z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
+ that bytes are eight bits.
+ */
+
+/*
+ Define W and the associated z_word_t type. If W is not defined, then a
+ braided calculation is not used, and the associated tables and code are not
+ compiled.
+ */
+#ifdef Z_TESTW
+# if Z_TESTW-1 != -1
+# define W Z_TESTW
+# endif
+#else
+# ifdef MAKECRCH
+# define W 8 /* required for MAKECRCH */
+# else
+# if defined(__x86_64__) || defined(__aarch64__)
+# define W 8
+# else
+# define W 4
+# endif
+# endif
+#endif
+#ifdef W
+# if W == 8 && defined(Z_U8)
+ typedef Z_U8 z_word_t;
+# elif defined(Z_U4)
+# undef W
+# define W 4
+ typedef Z_U4 z_word_t;
+# else
+# undef W
+# endif
+#endif
+
+/* If available, use the ARM processor CRC32 instruction. */
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
+# define ARMCRC32
+#endif
+
+/* Local functions. */
+local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
+local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
+
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+ local z_word_t byte_swap OF((z_word_t word));
+#endif
+
+#if defined(W) && !defined(ARMCRC32)
+ local z_crc_t crc_word OF((z_word_t data));
+ local z_word_t crc_word_big OF((z_word_t data));
+#endif
+
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+/*
+ Swap the bytes in a z_word_t to convert between little and big endian. Any
+ self-respecting compiler will optimize this to a single machine byte-swap
+ instruction, if one is available. This assumes that word_t is either 32 bits
+ or 64 bits.
+ */
+local z_word_t byte_swap(word)
+ z_word_t word;
+{
+# if W == 8
+ return
+ (word & 0xff00000000000000) >> 56 |
+ (word & 0xff000000000000) >> 40 |
+ (word & 0xff0000000000) >> 24 |
+ (word & 0xff00000000) >> 8 |
+ (word & 0xff000000) << 8 |
+ (word & 0xff0000) << 24 |
+ (word & 0xff00) << 40 |
+ (word & 0xff) << 56;
+# else /* W == 4 */
+ return
+ (word & 0xff000000) >> 24 |
+ (word & 0xff0000) >> 8 |
+ (word & 0xff00) << 8 |
+ (word & 0xff) << 24;
+# endif
+}
+#endif
+
+/* CRC polynomial. */
+#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local z_crc_t FAR crc_table[256];
+local z_crc_t FAR x2n_table[32];
+local void make_crc_table OF((void));
+#ifdef W
+ local z_word_t FAR crc_big_table[256];
+ local z_crc_t FAR crc_braid_table[W][256];
+ local z_word_t FAR crc_braid_big_table[W][256];
+ local void braid OF((z_crc_t [][256], z_word_t [][256], int, int));
+#endif
+#ifdef MAKECRCH
+ local void write_table OF((FILE *, const z_crc_t FAR *, int));
+ local void write_table32hi OF((FILE *, const z_word_t FAR *, int));
+ local void write_table64 OF((FILE *, const z_word_t FAR *, int));
+#endif /* MAKECRCH */
+
+/*
+ Define a once() function depending on the availability of atomics. If this is
+ compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
+ multiple threads, and if atomics are not available, then get_crc_table() must
+ be called to initialize the tables and must return before any threads are
+ allowed to compute or combine CRCs.
+ */
+
+/* Definition of once functionality. */
+typedef struct once_s once_t;
+local void once OF((once_t *, void (*)(void)));
+
+/* Check for the availability of atomics. */
+#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
+ !defined(__STDC_NO_ATOMICS__)
+
+#include <stdatomic.h>
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ atomic_flag begun;
+ atomic_int done;
+};
+#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
+
+/*
+ Run the provided init() function exactly once, even if multiple threads
+ invoke once() at the same time. The state must be a once_t initialized with
+ ONCE_INIT.
+ */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!atomic_load(&state->done)) {
+ if (atomic_flag_test_and_set(&state->begun))
+ while (!atomic_load(&state->done))
+ ;
+ else {
+ init();
+ atomic_store(&state->done, 1);
+ }
+ }
+}
+
+#else /* no atomics */
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ volatile int begun;
+ volatile int done;
+};
+#define ONCE_INIT {0, 0}
+
+/* Test and set. Alas, not atomic, but tries to minimize the period of
+ vulnerability. */
+local int test_and_set OF((int volatile *));
+local int test_and_set(flag)
+ int volatile *flag;
+{
+ int was;
+
+ was = *flag;
+ *flag = 1;
+ return was;
+}
+
+/* Run the provided init() function once. This is not thread-safe. */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!state->done) {
+ if (test_and_set(&state->begun))
+ while (!state->done)
+ ;
+ else {
+ init();
+ state->done = 1;
+ }
+ }
+}
+
+#endif
+
+/* State for once(). */
+local once_t made = ONCE_INIT;
+
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
+ (which is shifting right by one and adding x^32 mod p if the bit shifted out
+ is a one). We start with the highest power (least significant bit) of q and
+ repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all the
+ information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+ */
+
+local void make_crc_table()
+{
+ unsigned i, j, n;
+ z_crc_t p;
+
+ /* initialize the CRC of bytes tables */
+ for (i = 0; i < 256; i++) {
+ p = i;
+ for (j = 0; j < 8; j++)
+ p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
+ crc_table[i] = p;
+#ifdef W
+ crc_big_table[i] = byte_swap(p);
+#endif
+ }
+
+ /* initialize the x^2^n mod p(x) table */
+ p = (z_crc_t)1 << 30; /* x^1 */
+ x2n_table[0] = p;
+ for (n = 1; n < 32; n++)
+ x2n_table[n] = p = multmodp(p, p);
+
+#ifdef W
+ /* initialize the braiding tables -- needs x2n_table[] */
+ braid(crc_braid_table, crc_braid_big_table, N, W);
+#endif
+
+#ifdef MAKECRCH
+ {
+ /*
+ The crc32.h header file contains tables for both 32-bit and 64-bit
+ z_word_t's, and so requires a 64-bit type be available. In that case,
+ z_word_t must be defined to be 64-bits. This code then also generates
+ and writes out the tables for the case that z_word_t is 32 bits.
+ */
+#if !defined(W) || W != 8
+# error Need a 64-bit integer type in order to generate crc32.h.
+#endif
+ FILE *out;
+ int k, n;
+ z_crc_t ltl[8][256];
+ z_word_t big[8][256];
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+
+ /* write out little-endian CRC table to crc32.h */
+ fprintf(out,
+ "/* crc32.h -- tables for rapid CRC calculation\n"
+ " * Generated automatically by crc32.c\n */\n"
+ "\n"
+ "local const z_crc_t FAR crc_table[] = {\n"
+ " ");
+ write_table(out, crc_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#ifdef W\n"
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table64(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table32hi(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n");
+
+ /* write out braid tables for each value of N */
+ for (n = 1; n <= 6; n++) {
+ fprintf(out,
+ "\n"
+ "#if N == %d\n", n);
+
+ /* compute braid tables for this N and 64-bit word_t */
+ braid(ltl, big, n, 8);
+
+ /* write out braid tables for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table64(out, big[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n");
+
+ /* compute braid tables for this N and 32-bit word_t */
+ braid(ltl, big, n, 4);
+
+ /* write out braid tables for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table32hi(out, big[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n"
+ "\n"
+ "#endif\n");
+ }
+ fprintf(out,
+ "\n"
+ "#endif\n");
+
+ /* write out zeros operator table to crc32.h */
+ fprintf(out,
+ "\n"
+ "local const z_crc_t FAR x2n_table[] = {\n"
+ " ");
+ write_table(out, x2n_table, 32);
+ fprintf(out,
+ "};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+
+/*
+ Write the 32-bit values in table[0..k-1] to out, five per line in
+ hexadecimal separated by commas.
+ */
+local void write_table(out, table, k)
+ FILE *out;
+ const z_crc_t FAR *table;
+ int k;
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n]),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the high 32-bits of each value in table[0..k-1] to out, five per line
+ in hexadecimal separated by commas.
+ */
+local void write_table32hi(out, table, k)
+FILE *out;
+const z_word_t FAR *table;
+int k;
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n] >> 32),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the 64-bit values in table[0..k-1] to out, three per line in
+ hexadecimal separated by commas. This assumes that if there is a 64-bit
+ type, then there is also a long long integer type, and it is at least 64
+ bits. If not, then the type cast and format string can be adjusted
+ accordingly.
+ */
+local void write_table64(out, table, k)
+ FILE *out;
+ const z_word_t FAR *table;
+ int k;
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
+ (unsigned long long)(table[n]),
+ n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
+}
+
+/* Actually do the deed. */
+int main()
+{
+ make_crc_table();
+ return 0;
+}
+
+#endif /* MAKECRCH */
+
+#ifdef W
+/*
+ Generate the little and big-endian braid tables for the given n and z_word_t
+ size w. Each array must have room for w blocks of 256 elements.
+ */
+local void braid(ltl, big, n, w)
+ z_crc_t ltl[][256];
+ z_word_t big[][256];
+ int n;
+ int w;
+{
+ int k;
+ z_crc_t i, p, q;
+ for (k = 0; k < w; k++) {
+ p = x2nmodp((n * w + 3 - k) << 3, 0);
+ ltl[k][0] = 0;
+ big[w - 1 - k][0] = 0;
+ for (i = 1; i < 256; i++) {
+ ltl[k][i] = q = multmodp(i << 24, p);
+ big[w - 1 - k][i] = byte_swap(q);
+ }
+ }
+}
+#endif
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
+ * of x for combining CRC-32s, all made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* ========================================================================
+ * Routines used for CRC calculation. Some are also required for the table
+ * generation above.
+ */
+
+/*
+ Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
+ reflected. For speed, this requires that a not be zero.
+ */
+local z_crc_t multmodp(a, b)
+ z_crc_t a;
+ z_crc_t b;
+{
+ z_crc_t m, p;
+
+ m = (z_crc_t)1 << 31;
+ p = 0;
+ for (;;) {
+ if (a & m) {
+ p ^= b;
+ if ((a & (m - 1)) == 0)
+ break;
+ }
+ m >>= 1;
+ b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
+ }
+ return p;
+}
+
+/*
+ Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
+ initialized.
+ */
+local z_crc_t x2nmodp(n, k)
+ z_off64_t n;
+ unsigned k;
+{
+ z_crc_t p;
+
+ p = (z_crc_t)1 << 31; /* x^0 == 1 */
+ while (n) {
+ if (n & 1)
+ p = multmodp(x2n_table[k & 31], p);
+ n >>= 1;
+ k++;
+ }
+ return p;
+}
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32(), and to force the
+ * generation of the CRC tables in a threaded application.
+ */
+const z_crc_t FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const z_crc_t FAR *)crc_table;
+}
+
+/* =========================================================================
+ * Use ARM machine instructions if available. This will compute the CRC about
+ * ten times faster than the braided calculation. This code does not check for
+ * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
+ * only be defined if the compilation specifies an ARM processor architecture
+ * that has the instructions. For example, compiling with -march=armv8.1-a or
+ * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
+ * instructions.
+ */
+#ifdef ARMCRC32
+
+/*
+ Constants empirically determined to maximize speed. These values are from
+ measurements on a Cortex-A57. Your mileage may vary.
+ */
+#define Z_BATCH 3990 /* number of words in a batch */
+#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
+#define Z_BATCH_MIN 800 /* fewest words in a final batch */
+
+unsigned long ZEXPORT crc32_z(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ z_size_t len;
+{
+ z_crc_t val;
+ z_word_t crc1, crc2;
+ const z_word_t *word;
+ z_word_t val0, val1, val2;
+ z_size_t last, last2, i;
+ z_size_t num;
+
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc = (~crc) & 0xffffffff;
+
+ /* Compute the CRC up to a word boundary. */
+ while (len && ((z_size_t)buf & 7) != 0) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
+ word = (z_word_t const *)buf;
+ num = len >> 3;
+ len &= 7;
+
+ /* Do three interleaved CRCs to realize the throughput of one crc32x
+ instruction per cycle. Each CRC is calculated on Z_BATCH words. The
+ three CRCs are combined into a single CRC after each set of batches. */
+ while (num >= 3 * Z_BATCH) {
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < Z_BATCH; i++) {
+ val0 = word[i];
+ val1 = word[i + Z_BATCH];
+ val2 = word[i + 2 * Z_BATCH];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * Z_BATCH;
+ num -= 3 * Z_BATCH;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
+ }
+
+ /* Do one last smaller batch with the remaining words, if there are enough
+ to pay for the combination of CRCs. */
+ last = num / 3;
+ if (last >= Z_BATCH_MIN) {
+ last2 = last << 1;
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < last; i++) {
+ val0 = word[i];
+ val1 = word[i + last];
+ val2 = word[i + last2];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * last;
+ num -= 3 * last;
+ val = x2nmodp(last, 6);
+ crc = multmodp(val, crc) ^ crc1;
+ crc = multmodp(val, crc) ^ crc2;
+ }
+
+ /* Compute the CRC on any remaining words. */
+ for (i = 0; i < num; i++) {
+ val0 = word[i];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ }
+ word += num;
+
+ /* Complete the CRC on any remaining bytes. */
+ buf = (const unsigned char FAR *)word;
+ while (len) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#else
+
+#ifdef W
+
+/*
+ Return the CRC of the W bytes in the word_t data, taking the
+ least-significant byte of the word as the first byte of data, without any pre
+ or post conditioning. This is used to combine the CRCs of each braid.
+ */
+local z_crc_t crc_word(data)
+ z_word_t data;
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data >> 8) ^ crc_table[data & 0xff];
+ return (z_crc_t)data;
+}
+
+local z_word_t crc_word_big(data)
+ z_word_t data;
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data << 8) ^
+ crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
+ return data;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32_z(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ z_size_t len;
+{
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc = (~crc) & 0xffffffff;
+
+#ifdef W
+
+ /* If provided enough bytes, do a braided CRC calculation. */
+ if (len >= N * W + W - 1) {
+ z_size_t blks;
+ z_word_t const *words;
+ unsigned endian;
+ int k;
+
+ /* Compute the CRC up to a z_word_t boundary. */
+ while (len && ((z_size_t)buf & (W - 1)) != 0) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Compute the CRC on as many N z_word_t blocks as are available. */
+ blks = len / (N * W);
+ len -= blks * N * W;
+ words = (z_word_t const *)buf;
+
+ /* Do endian check at execution time instead of compile time, since ARM
+ processors can change the endianess at execution time. If the
+ compiler knows what the endianess will be, it can optimize out the
+ check and the unused branch. */
+ endian = 1;
+ if (*(unsigned char *)&endian) {
+ /* Little endian. */
+
+ z_crc_t crc0;
+ z_word_t word0;
+#if N > 1
+ z_crc_t crc1;
+ z_word_t word1;
+#if N > 2
+ z_crc_t crc2;
+ z_word_t word2;
+#if N > 3
+ z_crc_t crc3;
+ z_word_t word3;
+#if N > 4
+ z_crc_t crc4;
+ z_word_t word4;
+#if N > 5
+ z_crc_t crc5;
+ z_word_t word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = crc;
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ crc = crc_word(crc0 ^ words[0]);
+#if N > 1
+ crc = crc_word(crc1 ^ words[1] ^ crc);
+#if N > 2
+ crc = crc_word(crc2 ^ words[2] ^ crc);
+#if N > 3
+ crc = crc_word(crc3 ^ words[3] ^ crc);
+#if N > 4
+ crc = crc_word(crc4 ^ words[4] ^ crc);
+#if N > 5
+ crc = crc_word(crc5 ^ words[5] ^ crc);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ }
+ else {
+ /* Big endian. */
+
+ z_word_t crc0, word0, comb;
+#if N > 1
+ z_word_t crc1, word1;
+#if N > 2
+ z_word_t crc2, word2;
+#if N > 3
+ z_word_t crc3, word3;
+#if N > 4
+ z_word_t crc4, word4;
+#if N > 5
+ z_word_t crc5, word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = byte_swap(crc);
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_big_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_big_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_big_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_big_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_big_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_big_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ comb = crc_word_big(crc0 ^ words[0]);
+#if N > 1
+ comb = crc_word_big(crc1 ^ words[1] ^ comb);
+#if N > 2
+ comb = crc_word_big(crc2 ^ words[2] ^ comb);
+#if N > 3
+ comb = crc_word_big(crc3 ^ words[3] ^ comb);
+#if N > 4
+ comb = crc_word_big(crc4 ^ words[4] ^ comb);
+#if N > 5
+ comb = crc_word_big(crc5 ^ words[5] ^ comb);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ crc = byte_swap(comb);
+ }
+
+ /*
+ Update the pointer to the remaining bytes to process.
+ */
+ buf = (unsigned char const *)words;
+ }
+
+#endif /* W */
+
+ /* Complete the computation of the CRC on any remaining bytes. */
+ while (len >= 8) {
+ len -= 8;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+ while (len) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ uInt len;
+{
+ return crc32_z(crc, buf, len);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off64_t len2;
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off_t len2;
+{
+ return crc32_combine64(crc1, crc2, (z_off64_t)len2);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen64(len2)
+ z_off64_t len2;
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return x2nmodp(len2, 3);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen(len2)
+ z_off_t len2;
+{
+ return crc32_combine_gen64((z_off64_t)len2);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_op(crc1, crc2, op)
+ uLong crc1;
+ uLong crc2;
+ uLong op;
+{
+ return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
+}
diff --git a/libmariadb/external/zlib/crc32.h b/libmariadb/external/zlib/crc32.h
new file mode 100644
index 00000000..137df68d
--- /dev/null
+++ b/libmariadb/external/zlib/crc32.h
@@ -0,0 +1,9446 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const z_crc_t FAR crc_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d};
+
+#ifdef W
+
+#if W == 8
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000};
+
+#else /* W == 4 */
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d};
+
+#endif
+
+#if N == 1
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c},
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000},
+ {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,
+ 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,
+ 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,
+ 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,
+ 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,
+ 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,
+ 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,
+ 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,
+ 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,
+ 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,
+ 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,
+ 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,
+ 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,
+ 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,
+ 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,
+ 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,
+ 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,
+ 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,
+ 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,
+ 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,
+ 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,
+ 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,
+ 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,
+ 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,
+ 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,
+ 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,
+ 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,
+ 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,
+ 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,
+ 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,
+ 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,
+ 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,
+ 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,
+ 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,
+ 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,
+ 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,
+ 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,
+ 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,
+ 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,
+ 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,
+ 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,
+ 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,
+ 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,
+ 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,
+ 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,
+ 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,
+ 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,
+ 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,
+ 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,
+ 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,
+ 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,
+ 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,
+ 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,
+ 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,
+ 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,
+ 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,
+ 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,
+ 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,
+ 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,
+ 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,
+ 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,
+ 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,
+ 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,
+ 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,
+ 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,
+ 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,
+ 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,
+ 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,
+ 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,
+ 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,
+ 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,
+ 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,
+ 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,
+ 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,
+ 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,
+ 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,
+ 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,
+ 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,
+ 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,
+ 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,
+ 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,
+ 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,
+ 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,
+ 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,
+ 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,
+ 0x72fd249300000000},
+ {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,
+ 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,
+ 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,
+ 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,
+ 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,
+ 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,
+ 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,
+ 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,
+ 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,
+ 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,
+ 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,
+ 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,
+ 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,
+ 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,
+ 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,
+ 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,
+ 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,
+ 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,
+ 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,
+ 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,
+ 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,
+ 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,
+ 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,
+ 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,
+ 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,
+ 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,
+ 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,
+ 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,
+ 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,
+ 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,
+ 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,
+ 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,
+ 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,
+ 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,
+ 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,
+ 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,
+ 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,
+ 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,
+ 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,
+ 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,
+ 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,
+ 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,
+ 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,
+ 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,
+ 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,
+ 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,
+ 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,
+ 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,
+ 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,
+ 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,
+ 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,
+ 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,
+ 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,
+ 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,
+ 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,
+ 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,
+ 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,
+ 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,
+ 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,
+ 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,
+ 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,
+ 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,
+ 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,
+ 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,
+ 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,
+ 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,
+ 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,
+ 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,
+ 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,
+ 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,
+ 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,
+ 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,
+ 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,
+ 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,
+ 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,
+ 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,
+ 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,
+ 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,
+ 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,
+ 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,
+ 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,
+ 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,
+ 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,
+ 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,
+ 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,
+ 0xed3498be00000000},
+ {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,
+ 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,
+ 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,
+ 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,
+ 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,
+ 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,
+ 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,
+ 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,
+ 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,
+ 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,
+ 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,
+ 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,
+ 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,
+ 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,
+ 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,
+ 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,
+ 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,
+ 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,
+ 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,
+ 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,
+ 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,
+ 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,
+ 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,
+ 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,
+ 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,
+ 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,
+ 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,
+ 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,
+ 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,
+ 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,
+ 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,
+ 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,
+ 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,
+ 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,
+ 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,
+ 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,
+ 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,
+ 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,
+ 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,
+ 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,
+ 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,
+ 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,
+ 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,
+ 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,
+ 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,
+ 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,
+ 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,
+ 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,
+ 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,
+ 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,
+ 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,
+ 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,
+ 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,
+ 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,
+ 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,
+ 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,
+ 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,
+ 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,
+ 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,
+ 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,
+ 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,
+ 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,
+ 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,
+ 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,
+ 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,
+ 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,
+ 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,
+ 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,
+ 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,
+ 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,
+ 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,
+ 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,
+ 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,
+ 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,
+ 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,
+ 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,
+ 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,
+ 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,
+ 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,
+ 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,
+ 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,
+ 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,
+ 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,
+ 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,
+ 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,
+ 0xf10605de00000000},
+ {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,
+ 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,
+ 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,
+ 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,
+ 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,
+ 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,
+ 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,
+ 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,
+ 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,
+ 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,
+ 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,
+ 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,
+ 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,
+ 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,
+ 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,
+ 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,
+ 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,
+ 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,
+ 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,
+ 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,
+ 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,
+ 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,
+ 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,
+ 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,
+ 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,
+ 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,
+ 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,
+ 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,
+ 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,
+ 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,
+ 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,
+ 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,
+ 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,
+ 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,
+ 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,
+ 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,
+ 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,
+ 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,
+ 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,
+ 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,
+ 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,
+ 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,
+ 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,
+ 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,
+ 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,
+ 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,
+ 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,
+ 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,
+ 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,
+ 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,
+ 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,
+ 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,
+ 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,
+ 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,
+ 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,
+ 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,
+ 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,
+ 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,
+ 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,
+ 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,
+ 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,
+ 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,
+ 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,
+ 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,
+ 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,
+ 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,
+ 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,
+ 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,
+ 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,
+ 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,
+ 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,
+ 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,
+ 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,
+ 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,
+ 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,
+ 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,
+ 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,
+ 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,
+ 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,
+ 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,
+ 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,
+ 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,
+ 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,
+ 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,
+ 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,
+ 0x8cc764ca00000000},
+ {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,
+ 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,
+ 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,
+ 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,
+ 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,
+ 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,
+ 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,
+ 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,
+ 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,
+ 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,
+ 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,
+ 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,
+ 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,
+ 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,
+ 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,
+ 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,
+ 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,
+ 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,
+ 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,
+ 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,
+ 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,
+ 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,
+ 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,
+ 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,
+ 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,
+ 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,
+ 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,
+ 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,
+ 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,
+ 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,
+ 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,
+ 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,
+ 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,
+ 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,
+ 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,
+ 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,
+ 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,
+ 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,
+ 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,
+ 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,
+ 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,
+ 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,
+ 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,
+ 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,
+ 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,
+ 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,
+ 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,
+ 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,
+ 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,
+ 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,
+ 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,
+ 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,
+ 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,
+ 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,
+ 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,
+ 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,
+ 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,
+ 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,
+ 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,
+ 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,
+ 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,
+ 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,
+ 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,
+ 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,
+ 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,
+ 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,
+ 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,
+ 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,
+ 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,
+ 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,
+ 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,
+ 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,
+ 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,
+ 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,
+ 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,
+ 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,
+ 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,
+ 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,
+ 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,
+ 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,
+ 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,
+ 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,
+ 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,
+ 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,
+ 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,
+ 0xccabc4e400000000},
+ {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,
+ 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,
+ 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,
+ 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,
+ 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,
+ 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,
+ 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,
+ 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,
+ 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,
+ 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,
+ 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,
+ 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,
+ 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,
+ 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,
+ 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,
+ 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,
+ 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,
+ 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,
+ 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,
+ 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,
+ 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,
+ 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,
+ 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,
+ 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,
+ 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,
+ 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,
+ 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,
+ 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,
+ 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,
+ 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,
+ 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,
+ 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,
+ 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,
+ 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,
+ 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,
+ 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,
+ 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,
+ 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,
+ 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,
+ 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,
+ 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,
+ 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,
+ 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,
+ 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,
+ 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,
+ 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,
+ 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,
+ 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,
+ 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,
+ 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,
+ 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,
+ 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,
+ 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,
+ 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,
+ 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,
+ 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,
+ 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,
+ 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,
+ 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,
+ 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,
+ 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,
+ 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,
+ 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,
+ 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,
+ 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,
+ 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,
+ 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,
+ 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,
+ 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,
+ 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,
+ 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,
+ 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,
+ 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,
+ 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,
+ 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,
+ 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,
+ 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,
+ 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,
+ 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,
+ 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,
+ 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,
+ 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,
+ 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,
+ 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,
+ 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,
+ 0x304a369200000000},
+ {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,
+ 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,
+ 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,
+ 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,
+ 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,
+ 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,
+ 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,
+ 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,
+ 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,
+ 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,
+ 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,
+ 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,
+ 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,
+ 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,
+ 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,
+ 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,
+ 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,
+ 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,
+ 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,
+ 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,
+ 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,
+ 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,
+ 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,
+ 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,
+ 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,
+ 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,
+ 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,
+ 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,
+ 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,
+ 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,
+ 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,
+ 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,
+ 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,
+ 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,
+ 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,
+ 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,
+ 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,
+ 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,
+ 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,
+ 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,
+ 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,
+ 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,
+ 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,
+ 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,
+ 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,
+ 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,
+ 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,
+ 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,
+ 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,
+ 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,
+ 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,
+ 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,
+ 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,
+ 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,
+ 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,
+ 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,
+ 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,
+ 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,
+ 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,
+ 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,
+ 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,
+ 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,
+ 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,
+ 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,
+ 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,
+ 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,
+ 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,
+ 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,
+ 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,
+ 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,
+ 0x6171384400000000, 0xff71928800000000, 0xe678578200000000,
+ 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,
+ 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,
+ 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,
+ 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,
+ 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,
+ 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,
+ 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,
+ 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,
+ 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,
+ 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,
+ 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,
+ 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,
+ 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,
+ 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,
+ 0xe6064b2600000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d},
+ {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
+ 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
+ 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
+ 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
+ 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
+ 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
+ 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
+ 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
+ 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
+ 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
+ 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
+ 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
+ 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
+ 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
+ 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
+ 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
+ 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
+ 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
+ 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
+ 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
+ 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
+ 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
+ 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
+ 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
+ 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
+ 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
+ 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
+ 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
+ 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
+ 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
+ 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
+ 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
+ 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
+ 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
+ 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
+ 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
+ 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
+ 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
+ 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
+ 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
+ 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
+ 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
+ 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
+ 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
+ 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
+ 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
+ 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
+ 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
+ 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
+ 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
+ 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
+ 0x72fd2493},
+ {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
+ 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
+ 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
+ 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
+ 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
+ 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
+ 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
+ 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
+ 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
+ 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
+ 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
+ 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
+ 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
+ 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
+ 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
+ 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
+ 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
+ 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
+ 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
+ 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
+ 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
+ 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
+ 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
+ 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
+ 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
+ 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
+ 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
+ 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
+ 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
+ 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
+ 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
+ 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
+ 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
+ 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
+ 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
+ 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
+ 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
+ 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
+ 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
+ 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
+ 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
+ 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
+ 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
+ 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
+ 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
+ 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
+ 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
+ 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
+ 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
+ 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
+ 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
+ 0xed3498be},
+ {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
+ 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
+ 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
+ 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
+ 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
+ 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
+ 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
+ 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
+ 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
+ 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
+ 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
+ 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
+ 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
+ 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
+ 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
+ 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
+ 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
+ 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
+ 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
+ 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
+ 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
+ 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
+ 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
+ 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
+ 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
+ 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
+ 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
+ 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
+ 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
+ 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
+ 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
+ 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
+ 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
+ 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
+ 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
+ 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
+ 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
+ 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
+ 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
+ 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
+ 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
+ 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
+ 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
+ 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
+ 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
+ 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
+ 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
+ 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
+ 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
+ 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
+ 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
+ 0xf10605de}};
+
+#endif
+
+#endif
+
+#if N == 2
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6},
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,
+ 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,
+ 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,
+ 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,
+ 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,
+ 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,
+ 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,
+ 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,
+ 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,
+ 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,
+ 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,
+ 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,
+ 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,
+ 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,
+ 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,
+ 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,
+ 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,
+ 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,
+ 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,
+ 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,
+ 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,
+ 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,
+ 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,
+ 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,
+ 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,
+ 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,
+ 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,
+ 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,
+ 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,
+ 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,
+ 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,
+ 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,
+ 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,
+ 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,
+ 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,
+ 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,
+ 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,
+ 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,
+ 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,
+ 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,
+ 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,
+ 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,
+ 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,
+ 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,
+ 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,
+ 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,
+ 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,
+ 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,
+ 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,
+ 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,
+ 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,
+ 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,
+ 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,
+ 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,
+ 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,
+ 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,
+ 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,
+ 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,
+ 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,
+ 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,
+ 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,
+ 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,
+ 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,
+ 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,
+ 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,
+ 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,
+ 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,
+ 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,
+ 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,
+ 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,
+ 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,
+ 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,
+ 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,
+ 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,
+ 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,
+ 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,
+ 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,
+ 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,
+ 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,
+ 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,
+ 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,
+ 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,
+ 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,
+ 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,
+ 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,
+ 0x4b0c4f4900000000},
+ {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,
+ 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,
+ 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,
+ 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,
+ 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,
+ 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,
+ 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,
+ 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,
+ 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,
+ 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,
+ 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,
+ 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,
+ 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,
+ 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,
+ 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,
+ 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,
+ 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,
+ 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,
+ 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,
+ 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,
+ 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,
+ 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,
+ 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,
+ 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,
+ 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,
+ 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,
+ 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,
+ 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,
+ 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,
+ 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,
+ 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,
+ 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,
+ 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,
+ 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,
+ 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,
+ 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,
+ 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,
+ 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,
+ 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,
+ 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,
+ 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,
+ 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,
+ 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,
+ 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,
+ 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,
+ 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,
+ 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,
+ 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,
+ 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,
+ 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,
+ 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,
+ 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,
+ 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,
+ 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,
+ 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,
+ 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,
+ 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,
+ 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,
+ 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,
+ 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,
+ 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,
+ 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,
+ 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,
+ 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,
+ 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,
+ 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,
+ 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,
+ 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,
+ 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,
+ 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,
+ 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,
+ 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,
+ 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,
+ 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,
+ 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,
+ 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,
+ 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,
+ 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,
+ 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,
+ 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,
+ 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,
+ 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,
+ 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,
+ 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,
+ 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,
+ 0x14d747e100000000},
+ {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,
+ 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,
+ 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,
+ 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,
+ 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,
+ 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,
+ 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,
+ 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,
+ 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,
+ 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,
+ 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,
+ 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,
+ 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,
+ 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,
+ 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,
+ 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,
+ 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,
+ 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,
+ 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,
+ 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,
+ 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,
+ 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,
+ 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,
+ 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,
+ 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,
+ 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,
+ 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,
+ 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,
+ 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,
+ 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,
+ 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,
+ 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,
+ 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,
+ 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,
+ 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,
+ 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,
+ 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,
+ 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,
+ 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,
+ 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,
+ 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,
+ 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,
+ 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,
+ 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,
+ 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,
+ 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,
+ 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,
+ 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,
+ 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,
+ 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,
+ 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,
+ 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,
+ 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,
+ 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,
+ 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,
+ 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,
+ 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,
+ 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,
+ 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,
+ 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,
+ 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,
+ 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,
+ 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,
+ 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,
+ 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,
+ 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,
+ 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,
+ 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,
+ 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,
+ 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,
+ 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,
+ 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,
+ 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,
+ 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,
+ 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,
+ 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,
+ 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,
+ 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,
+ 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,
+ 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,
+ 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,
+ 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,
+ 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,
+ 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,
+ 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,
+ 0xaa933b1a00000000},
+ {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,
+ 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,
+ 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,
+ 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,
+ 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,
+ 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,
+ 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,
+ 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,
+ 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,
+ 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,
+ 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,
+ 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,
+ 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,
+ 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,
+ 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,
+ 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,
+ 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,
+ 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,
+ 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,
+ 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,
+ 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,
+ 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,
+ 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,
+ 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,
+ 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,
+ 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,
+ 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,
+ 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,
+ 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,
+ 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,
+ 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,
+ 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,
+ 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,
+ 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,
+ 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,
+ 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,
+ 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,
+ 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,
+ 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,
+ 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,
+ 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,
+ 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,
+ 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,
+ 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,
+ 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,
+ 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,
+ 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,
+ 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,
+ 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,
+ 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,
+ 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,
+ 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,
+ 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,
+ 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,
+ 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,
+ 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,
+ 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,
+ 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,
+ 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,
+ 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,
+ 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,
+ 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,
+ 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,
+ 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,
+ 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,
+ 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,
+ 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,
+ 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,
+ 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,
+ 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,
+ 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,
+ 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,
+ 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,
+ 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,
+ 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,
+ 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,
+ 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,
+ 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,
+ 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,
+ 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,
+ 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,
+ 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,
+ 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,
+ 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,
+ 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,
+ 0x6571193600000000},
+ {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,
+ 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,
+ 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,
+ 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,
+ 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,
+ 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,
+ 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,
+ 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,
+ 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,
+ 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,
+ 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,
+ 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,
+ 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,
+ 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,
+ 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,
+ 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,
+ 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,
+ 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,
+ 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,
+ 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,
+ 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,
+ 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,
+ 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,
+ 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,
+ 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,
+ 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,
+ 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,
+ 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,
+ 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,
+ 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,
+ 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,
+ 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,
+ 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,
+ 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,
+ 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,
+ 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,
+ 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,
+ 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,
+ 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,
+ 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,
+ 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,
+ 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,
+ 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,
+ 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,
+ 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,
+ 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,
+ 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,
+ 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,
+ 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,
+ 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,
+ 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,
+ 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,
+ 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,
+ 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,
+ 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,
+ 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,
+ 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,
+ 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,
+ 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,
+ 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,
+ 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,
+ 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,
+ 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,
+ 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,
+ 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,
+ 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,
+ 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,
+ 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,
+ 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,
+ 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,
+ 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,
+ 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,
+ 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,
+ 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,
+ 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,
+ 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,
+ 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,
+ 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,
+ 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,
+ 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,
+ 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,
+ 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,
+ 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,
+ 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,
+ 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,
+ 0xa68cee3d00000000},
+ {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,
+ 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,
+ 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,
+ 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,
+ 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,
+ 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,
+ 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,
+ 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,
+ 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,
+ 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,
+ 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,
+ 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,
+ 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,
+ 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,
+ 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,
+ 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,
+ 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,
+ 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,
+ 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,
+ 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,
+ 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,
+ 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,
+ 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,
+ 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,
+ 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,
+ 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,
+ 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,
+ 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,
+ 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,
+ 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,
+ 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,
+ 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,
+ 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,
+ 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,
+ 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,
+ 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,
+ 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,
+ 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,
+ 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,
+ 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,
+ 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,
+ 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,
+ 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,
+ 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,
+ 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,
+ 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,
+ 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,
+ 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,
+ 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,
+ 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,
+ 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,
+ 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,
+ 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,
+ 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,
+ 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,
+ 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,
+ 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,
+ 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,
+ 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,
+ 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,
+ 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,
+ 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,
+ 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,
+ 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,
+ 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,
+ 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,
+ 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,
+ 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,
+ 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,
+ 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,
+ 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,
+ 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,
+ 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,
+ 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,
+ 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,
+ 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,
+ 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,
+ 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,
+ 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,
+ 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,
+ 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,
+ 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,
+ 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,
+ 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,
+ 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,
+ 0x51e8883f00000000},
+ {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,
+ 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,
+ 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,
+ 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,
+ 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,
+ 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,
+ 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,
+ 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,
+ 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,
+ 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,
+ 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,
+ 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,
+ 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,
+ 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,
+ 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,
+ 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,
+ 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,
+ 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,
+ 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,
+ 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,
+ 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,
+ 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,
+ 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,
+ 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,
+ 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,
+ 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,
+ 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,
+ 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,
+ 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,
+ 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,
+ 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,
+ 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,
+ 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,
+ 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,
+ 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,
+ 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,
+ 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,
+ 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,
+ 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,
+ 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,
+ 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,
+ 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,
+ 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,
+ 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,
+ 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,
+ 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,
+ 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,
+ 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,
+ 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,
+ 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,
+ 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,
+ 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,
+ 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,
+ 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,
+ 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,
+ 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,
+ 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,
+ 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,
+ 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,
+ 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,
+ 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,
+ 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,
+ 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,
+ 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,
+ 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,
+ 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,
+ 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,
+ 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,
+ 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,
+ 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,
+ 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,
+ 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,
+ 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,
+ 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,
+ 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,
+ 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,
+ 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,
+ 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,
+ 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,
+ 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,
+ 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,
+ 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,
+ 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,
+ 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,
+ 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,
+ 0x8ae9531c00000000},
+ {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,
+ 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,
+ 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,
+ 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,
+ 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,
+ 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,
+ 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,
+ 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,
+ 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,
+ 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,
+ 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,
+ 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,
+ 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,
+ 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,
+ 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,
+ 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,
+ 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,
+ 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,
+ 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,
+ 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,
+ 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,
+ 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,
+ 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,
+ 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,
+ 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,
+ 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,
+ 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,
+ 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,
+ 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,
+ 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,
+ 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,
+ 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,
+ 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,
+ 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,
+ 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,
+ 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,
+ 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,
+ 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,
+ 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,
+ 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,
+ 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,
+ 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,
+ 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,
+ 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,
+ 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,
+ 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,
+ 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,
+ 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,
+ 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,
+ 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,
+ 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,
+ 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,
+ 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,
+ 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,
+ 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,
+ 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,
+ 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,
+ 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,
+ 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,
+ 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,
+ 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,
+ 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,
+ 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,
+ 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,
+ 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,
+ 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,
+ 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,
+ 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,
+ 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,
+ 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,
+ 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,
+ 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,
+ 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,
+ 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,
+ 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,
+ 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,
+ 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,
+ 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,
+ 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,
+ 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,
+ 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,
+ 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,
+ 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,
+ 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,
+ 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,
+ 0xd739710d00000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,
+ 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,
+ 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,
+ 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,
+ 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,
+ 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,
+ 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,
+ 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,
+ 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,
+ 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,
+ 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,
+ 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,
+ 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,
+ 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,
+ 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,
+ 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,
+ 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,
+ 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,
+ 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,
+ 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,
+ 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,
+ 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,
+ 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,
+ 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,
+ 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,
+ 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,
+ 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,
+ 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,
+ 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,
+ 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,
+ 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,
+ 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,
+ 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,
+ 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,
+ 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,
+ 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,
+ 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,
+ 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,
+ 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,
+ 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,
+ 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,
+ 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,
+ 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,
+ 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,
+ 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,
+ 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,
+ 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,
+ 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,
+ 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,
+ 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,
+ 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,
+ 0x8cc764ca},
+ {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,
+ 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,
+ 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,
+ 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,
+ 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,
+ 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,
+ 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,
+ 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,
+ 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,
+ 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,
+ 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,
+ 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,
+ 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,
+ 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,
+ 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,
+ 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,
+ 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,
+ 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,
+ 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,
+ 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,
+ 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,
+ 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,
+ 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,
+ 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,
+ 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,
+ 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,
+ 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,
+ 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,
+ 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,
+ 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,
+ 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,
+ 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,
+ 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,
+ 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,
+ 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,
+ 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,
+ 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,
+ 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,
+ 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,
+ 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,
+ 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,
+ 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,
+ 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,
+ 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,
+ 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,
+ 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,
+ 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,
+ 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,
+ 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,
+ 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,
+ 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,
+ 0xccabc4e4},
+ {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,
+ 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,
+ 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,
+ 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,
+ 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,
+ 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,
+ 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,
+ 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,
+ 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,
+ 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,
+ 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,
+ 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,
+ 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,
+ 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,
+ 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,
+ 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,
+ 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,
+ 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,
+ 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,
+ 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,
+ 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,
+ 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,
+ 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,
+ 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,
+ 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,
+ 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,
+ 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,
+ 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,
+ 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,
+ 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,
+ 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,
+ 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,
+ 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,
+ 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,
+ 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,
+ 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,
+ 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,
+ 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,
+ 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,
+ 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,
+ 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,
+ 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,
+ 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,
+ 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,
+ 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,
+ 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,
+ 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,
+ 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,
+ 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,
+ 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,
+ 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,
+ 0x304a3692},
+ {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,
+ 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,
+ 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,
+ 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,
+ 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,
+ 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,
+ 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,
+ 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,
+ 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,
+ 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,
+ 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,
+ 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,
+ 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,
+ 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,
+ 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,
+ 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,
+ 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,
+ 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,
+ 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,
+ 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,
+ 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,
+ 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,
+ 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,
+ 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,
+ 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,
+ 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,
+ 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,
+ 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,
+ 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,
+ 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,
+ 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,
+ 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,
+ 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,
+ 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,
+ 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,
+ 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,
+ 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,
+ 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,
+ 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,
+ 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,
+ 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,
+ 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,
+ 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,
+ 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,
+ 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,
+ 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,
+ 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,
+ 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,
+ 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,
+ 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,
+ 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,
+ 0xe6064b26}};
+
+#endif
+
+#endif
+
+#if N == 3
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848},
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,
+ 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,
+ 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,
+ 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,
+ 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,
+ 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,
+ 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,
+ 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,
+ 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,
+ 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,
+ 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,
+ 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,
+ 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,
+ 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,
+ 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,
+ 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,
+ 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,
+ 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,
+ 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,
+ 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,
+ 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,
+ 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,
+ 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,
+ 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,
+ 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,
+ 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,
+ 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,
+ 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,
+ 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,
+ 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,
+ 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,
+ 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,
+ 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,
+ 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,
+ 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,
+ 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,
+ 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,
+ 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,
+ 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,
+ 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,
+ 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,
+ 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,
+ 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,
+ 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,
+ 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,
+ 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,
+ 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,
+ 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,
+ 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,
+ 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,
+ 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,
+ 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,
+ 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,
+ 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,
+ 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,
+ 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,
+ 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,
+ 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,
+ 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,
+ 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,
+ 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,
+ 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,
+ 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,
+ 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,
+ 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,
+ 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,
+ 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,
+ 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,
+ 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,
+ 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,
+ 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,
+ 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,
+ 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,
+ 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,
+ 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,
+ 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,
+ 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,
+ 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,
+ 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,
+ 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,
+ 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,
+ 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,
+ 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,
+ 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,
+ 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,
+ 0x4e36ba1800000000},
+ {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,
+ 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,
+ 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,
+ 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,
+ 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,
+ 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,
+ 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,
+ 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,
+ 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,
+ 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,
+ 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,
+ 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,
+ 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,
+ 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,
+ 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,
+ 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,
+ 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,
+ 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,
+ 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,
+ 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,
+ 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,
+ 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,
+ 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,
+ 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,
+ 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,
+ 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,
+ 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,
+ 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,
+ 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,
+ 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,
+ 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,
+ 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,
+ 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,
+ 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,
+ 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,
+ 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,
+ 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,
+ 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,
+ 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,
+ 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,
+ 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,
+ 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,
+ 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,
+ 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,
+ 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,
+ 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,
+ 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,
+ 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,
+ 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,
+ 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,
+ 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,
+ 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,
+ 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,
+ 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,
+ 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,
+ 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,
+ 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,
+ 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,
+ 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,
+ 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,
+ 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,
+ 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,
+ 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,
+ 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,
+ 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,
+ 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,
+ 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,
+ 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,
+ 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,
+ 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,
+ 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,
+ 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,
+ 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,
+ 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,
+ 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,
+ 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,
+ 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,
+ 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,
+ 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,
+ 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,
+ 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,
+ 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,
+ 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,
+ 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,
+ 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,
+ 0xa1d67c9100000000},
+ {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,
+ 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,
+ 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,
+ 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,
+ 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,
+ 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,
+ 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,
+ 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,
+ 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,
+ 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,
+ 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,
+ 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,
+ 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,
+ 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,
+ 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,
+ 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,
+ 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,
+ 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,
+ 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,
+ 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,
+ 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,
+ 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,
+ 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,
+ 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,
+ 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,
+ 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,
+ 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,
+ 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,
+ 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,
+ 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,
+ 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,
+ 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,
+ 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,
+ 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,
+ 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,
+ 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,
+ 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,
+ 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,
+ 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,
+ 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,
+ 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,
+ 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,
+ 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,
+ 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,
+ 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,
+ 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,
+ 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,
+ 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,
+ 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,
+ 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,
+ 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,
+ 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,
+ 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,
+ 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,
+ 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,
+ 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,
+ 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,
+ 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,
+ 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,
+ 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,
+ 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,
+ 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,
+ 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,
+ 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,
+ 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,
+ 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,
+ 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,
+ 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,
+ 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,
+ 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,
+ 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,
+ 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,
+ 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,
+ 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,
+ 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,
+ 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,
+ 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,
+ 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,
+ 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,
+ 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,
+ 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,
+ 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,
+ 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,
+ 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,
+ 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,
+ 0xa8ef40a100000000},
+ {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,
+ 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,
+ 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,
+ 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,
+ 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,
+ 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,
+ 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,
+ 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,
+ 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,
+ 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,
+ 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,
+ 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,
+ 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,
+ 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,
+ 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,
+ 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,
+ 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,
+ 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,
+ 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,
+ 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,
+ 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,
+ 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,
+ 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,
+ 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,
+ 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,
+ 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,
+ 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,
+ 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,
+ 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,
+ 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,
+ 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,
+ 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,
+ 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,
+ 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,
+ 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,
+ 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,
+ 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,
+ 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,
+ 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,
+ 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,
+ 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,
+ 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,
+ 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,
+ 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,
+ 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,
+ 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,
+ 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,
+ 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,
+ 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,
+ 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,
+ 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,
+ 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,
+ 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,
+ 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,
+ 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,
+ 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,
+ 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,
+ 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,
+ 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,
+ 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,
+ 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,
+ 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,
+ 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,
+ 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,
+ 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,
+ 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,
+ 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,
+ 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,
+ 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,
+ 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,
+ 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,
+ 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,
+ 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,
+ 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,
+ 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,
+ 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,
+ 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,
+ 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,
+ 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,
+ 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,
+ 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,
+ 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,
+ 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,
+ 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,
+ 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,
+ 0x356bacd800000000},
+ {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,
+ 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,
+ 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,
+ 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,
+ 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,
+ 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,
+ 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,
+ 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,
+ 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,
+ 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,
+ 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,
+ 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,
+ 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,
+ 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,
+ 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,
+ 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,
+ 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,
+ 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,
+ 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,
+ 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,
+ 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,
+ 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,
+ 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,
+ 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,
+ 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,
+ 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,
+ 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,
+ 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,
+ 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,
+ 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,
+ 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,
+ 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,
+ 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,
+ 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,
+ 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,
+ 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,
+ 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,
+ 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,
+ 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,
+ 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,
+ 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,
+ 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,
+ 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,
+ 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,
+ 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,
+ 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,
+ 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,
+ 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,
+ 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,
+ 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,
+ 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,
+ 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,
+ 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,
+ 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,
+ 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,
+ 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,
+ 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,
+ 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,
+ 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,
+ 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,
+ 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,
+ 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,
+ 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,
+ 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,
+ 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,
+ 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,
+ 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,
+ 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,
+ 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,
+ 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,
+ 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,
+ 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,
+ 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,
+ 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,
+ 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,
+ 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,
+ 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,
+ 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,
+ 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,
+ 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,
+ 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,
+ 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,
+ 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,
+ 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,
+ 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,
+ 0x48686b5600000000},
+ {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,
+ 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,
+ 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,
+ 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,
+ 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,
+ 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,
+ 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,
+ 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,
+ 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,
+ 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,
+ 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,
+ 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,
+ 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,
+ 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,
+ 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,
+ 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,
+ 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,
+ 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,
+ 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,
+ 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,
+ 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,
+ 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,
+ 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,
+ 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,
+ 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,
+ 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,
+ 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,
+ 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,
+ 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,
+ 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,
+ 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,
+ 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,
+ 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,
+ 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,
+ 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,
+ 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,
+ 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,
+ 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,
+ 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,
+ 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,
+ 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,
+ 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,
+ 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,
+ 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,
+ 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,
+ 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,
+ 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,
+ 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,
+ 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,
+ 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,
+ 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,
+ 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,
+ 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,
+ 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,
+ 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,
+ 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,
+ 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,
+ 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,
+ 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,
+ 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,
+ 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,
+ 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,
+ 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,
+ 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,
+ 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,
+ 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,
+ 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,
+ 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,
+ 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,
+ 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,
+ 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,
+ 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,
+ 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,
+ 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,
+ 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,
+ 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,
+ 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,
+ 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,
+ 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,
+ 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,
+ 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,
+ 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,
+ 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,
+ 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,
+ 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,
+ 0xcaa2517800000000},
+ {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,
+ 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,
+ 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,
+ 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,
+ 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,
+ 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,
+ 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,
+ 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,
+ 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,
+ 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,
+ 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,
+ 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,
+ 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,
+ 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,
+ 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,
+ 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,
+ 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,
+ 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,
+ 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,
+ 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,
+ 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,
+ 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,
+ 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,
+ 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,
+ 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,
+ 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,
+ 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,
+ 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,
+ 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,
+ 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,
+ 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,
+ 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,
+ 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,
+ 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,
+ 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,
+ 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,
+ 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,
+ 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,
+ 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,
+ 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,
+ 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,
+ 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,
+ 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,
+ 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,
+ 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,
+ 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,
+ 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,
+ 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,
+ 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,
+ 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,
+ 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,
+ 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,
+ 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,
+ 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,
+ 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,
+ 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,
+ 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,
+ 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,
+ 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,
+ 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,
+ 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,
+ 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,
+ 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,
+ 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,
+ 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,
+ 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,
+ 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,
+ 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,
+ 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,
+ 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,
+ 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,
+ 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,
+ 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,
+ 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,
+ 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,
+ 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,
+ 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,
+ 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,
+ 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,
+ 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,
+ 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,
+ 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,
+ 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,
+ 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,
+ 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,
+ 0x0c7ac97b00000000},
+ {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,
+ 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,
+ 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,
+ 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,
+ 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,
+ 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,
+ 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,
+ 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,
+ 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,
+ 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,
+ 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,
+ 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,
+ 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,
+ 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,
+ 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,
+ 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,
+ 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,
+ 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,
+ 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,
+ 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,
+ 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,
+ 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,
+ 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,
+ 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,
+ 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,
+ 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,
+ 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,
+ 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,
+ 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,
+ 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,
+ 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,
+ 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,
+ 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,
+ 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,
+ 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,
+ 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,
+ 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,
+ 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,
+ 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,
+ 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,
+ 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,
+ 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,
+ 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,
+ 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,
+ 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,
+ 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,
+ 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,
+ 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,
+ 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,
+ 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,
+ 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,
+ 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,
+ 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,
+ 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,
+ 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,
+ 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,
+ 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,
+ 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,
+ 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,
+ 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,
+ 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,
+ 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,
+ 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,
+ 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,
+ 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,
+ 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,
+ 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,
+ 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,
+ 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,
+ 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,
+ 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,
+ 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,
+ 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,
+ 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,
+ 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,
+ 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,
+ 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,
+ 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,
+ 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,
+ 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,
+ 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,
+ 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,
+ 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,
+ 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,
+ 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,
+ 0x5185cd0900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,
+ 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,
+ 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,
+ 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,
+ 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,
+ 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,
+ 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,
+ 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,
+ 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,
+ 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,
+ 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,
+ 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,
+ 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,
+ 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,
+ 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,
+ 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,
+ 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,
+ 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,
+ 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,
+ 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,
+ 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,
+ 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,
+ 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,
+ 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,
+ 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,
+ 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,
+ 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,
+ 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,
+ 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,
+ 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,
+ 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,
+ 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,
+ 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,
+ 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,
+ 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,
+ 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,
+ 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,
+ 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,
+ 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,
+ 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,
+ 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,
+ 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,
+ 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,
+ 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,
+ 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,
+ 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,
+ 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,
+ 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,
+ 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,
+ 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,
+ 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,
+ 0x4b0c4f49},
+ {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,
+ 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,
+ 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,
+ 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,
+ 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,
+ 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,
+ 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,
+ 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,
+ 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,
+ 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,
+ 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,
+ 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,
+ 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,
+ 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,
+ 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,
+ 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,
+ 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,
+ 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,
+ 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,
+ 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,
+ 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,
+ 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,
+ 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,
+ 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,
+ 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,
+ 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,
+ 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,
+ 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,
+ 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,
+ 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,
+ 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,
+ 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,
+ 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,
+ 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,
+ 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,
+ 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,
+ 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,
+ 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,
+ 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,
+ 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,
+ 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,
+ 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,
+ 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,
+ 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,
+ 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,
+ 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,
+ 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,
+ 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,
+ 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,
+ 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,
+ 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,
+ 0x14d747e1},
+ {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,
+ 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,
+ 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,
+ 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,
+ 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,
+ 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,
+ 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,
+ 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,
+ 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,
+ 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,
+ 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,
+ 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,
+ 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,
+ 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,
+ 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,
+ 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,
+ 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,
+ 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,
+ 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,
+ 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,
+ 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,
+ 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,
+ 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,
+ 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,
+ 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,
+ 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,
+ 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,
+ 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,
+ 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,
+ 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,
+ 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,
+ 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,
+ 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,
+ 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,
+ 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,
+ 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,
+ 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,
+ 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,
+ 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,
+ 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,
+ 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,
+ 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,
+ 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,
+ 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,
+ 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,
+ 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,
+ 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,
+ 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,
+ 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,
+ 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,
+ 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,
+ 0xaa933b1a},
+ {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,
+ 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,
+ 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,
+ 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,
+ 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,
+ 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,
+ 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,
+ 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,
+ 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,
+ 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,
+ 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,
+ 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,
+ 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,
+ 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,
+ 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,
+ 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,
+ 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,
+ 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,
+ 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,
+ 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,
+ 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,
+ 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,
+ 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,
+ 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,
+ 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,
+ 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,
+ 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,
+ 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,
+ 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,
+ 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,
+ 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,
+ 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,
+ 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,
+ 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,
+ 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,
+ 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,
+ 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,
+ 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,
+ 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,
+ 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,
+ 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,
+ 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,
+ 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,
+ 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,
+ 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,
+ 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,
+ 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,
+ 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,
+ 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,
+ 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,
+ 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,
+ 0x65711936}};
+
+#endif
+
+#endif
+
+#if N == 4
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,
+ 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,
+ 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,
+ 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,
+ 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,
+ 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,
+ 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,
+ 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,
+ 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,
+ 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,
+ 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,
+ 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,
+ 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,
+ 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,
+ 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,
+ 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,
+ 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,
+ 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,
+ 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,
+ 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,
+ 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,
+ 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,
+ 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,
+ 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,
+ 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,
+ 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,
+ 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,
+ 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,
+ 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,
+ 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,
+ 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,
+ 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,
+ 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,
+ 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,
+ 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,
+ 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,
+ 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,
+ 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,
+ 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,
+ 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,
+ 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,
+ 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,
+ 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,
+ 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,
+ 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,
+ 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,
+ 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,
+ 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,
+ 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,
+ 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,
+ 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,
+ 0xe3c45916},
+ {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,
+ 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,
+ 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,
+ 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,
+ 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,
+ 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,
+ 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,
+ 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,
+ 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,
+ 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,
+ 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,
+ 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,
+ 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,
+ 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,
+ 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,
+ 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,
+ 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,
+ 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,
+ 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,
+ 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,
+ 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,
+ 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,
+ 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,
+ 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,
+ 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,
+ 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,
+ 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,
+ 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,
+ 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,
+ 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,
+ 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,
+ 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,
+ 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,
+ 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,
+ 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,
+ 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,
+ 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,
+ 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,
+ 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,
+ 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,
+ 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,
+ 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,
+ 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,
+ 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,
+ 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,
+ 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,
+ 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,
+ 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,
+ 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,
+ 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,
+ 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,
+ 0xa7520488},
+ {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,
+ 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,
+ 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,
+ 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,
+ 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,
+ 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,
+ 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,
+ 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,
+ 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,
+ 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,
+ 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,
+ 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,
+ 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,
+ 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,
+ 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,
+ 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,
+ 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,
+ 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,
+ 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,
+ 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,
+ 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,
+ 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,
+ 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,
+ 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,
+ 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,
+ 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,
+ 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,
+ 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,
+ 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,
+ 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,
+ 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,
+ 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,
+ 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,
+ 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,
+ 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,
+ 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,
+ 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,
+ 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,
+ 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,
+ 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,
+ 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,
+ 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,
+ 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,
+ 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,
+ 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,
+ 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,
+ 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,
+ 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,
+ 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,
+ 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,
+ 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,
+ 0x3522e9e4},
+ {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,
+ 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,
+ 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,
+ 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,
+ 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,
+ 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,
+ 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,
+ 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,
+ 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,
+ 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,
+ 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,
+ 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,
+ 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,
+ 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,
+ 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,
+ 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,
+ 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,
+ 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,
+ 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,
+ 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,
+ 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,
+ 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,
+ 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,
+ 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,
+ 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,
+ 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,
+ 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,
+ 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,
+ 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,
+ 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,
+ 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,
+ 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,
+ 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,
+ 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,
+ 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,
+ 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,
+ 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,
+ 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,
+ 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,
+ 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,
+ 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,
+ 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,
+ 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,
+ 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,
+ 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,
+ 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,
+ 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,
+ 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,
+ 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,
+ 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,
+ 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,
+ 0x97411e28},
+ {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,
+ 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,
+ 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,
+ 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,
+ 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,
+ 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,
+ 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,
+ 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,
+ 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,
+ 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,
+ 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,
+ 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,
+ 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,
+ 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,
+ 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,
+ 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,
+ 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,
+ 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,
+ 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,
+ 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,
+ 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,
+ 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,
+ 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,
+ 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,
+ 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,
+ 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,
+ 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,
+ 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,
+ 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,
+ 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,
+ 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,
+ 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,
+ 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,
+ 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,
+ 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,
+ 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,
+ 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,
+ 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,
+ 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,
+ 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,
+ 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,
+ 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,
+ 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,
+ 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,
+ 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,
+ 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,
+ 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,
+ 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,
+ 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,
+ 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,
+ 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,
+ 0x93c7a00b},
+ {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,
+ 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,
+ 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,
+ 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,
+ 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,
+ 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,
+ 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,
+ 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,
+ 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,
+ 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,
+ 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,
+ 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,
+ 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,
+ 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,
+ 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,
+ 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,
+ 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,
+ 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,
+ 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,
+ 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,
+ 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,
+ 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,
+ 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,
+ 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,
+ 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,
+ 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,
+ 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,
+ 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,
+ 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,
+ 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,
+ 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,
+ 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,
+ 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,
+ 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,
+ 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,
+ 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,
+ 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,
+ 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,
+ 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,
+ 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,
+ 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,
+ 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,
+ 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,
+ 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,
+ 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,
+ 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,
+ 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,
+ 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,
+ 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,
+ 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,
+ 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,
+ 0xce5f968d},
+ {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,
+ 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,
+ 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,
+ 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,
+ 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,
+ 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,
+ 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,
+ 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,
+ 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,
+ 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,
+ 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,
+ 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,
+ 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,
+ 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,
+ 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,
+ 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,
+ 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,
+ 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,
+ 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,
+ 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,
+ 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,
+ 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,
+ 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,
+ 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,
+ 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,
+ 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,
+ 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,
+ 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,
+ 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,
+ 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,
+ 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,
+ 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,
+ 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,
+ 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,
+ 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,
+ 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,
+ 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,
+ 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,
+ 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,
+ 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,
+ 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,
+ 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,
+ 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,
+ 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,
+ 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,
+ 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,
+ 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,
+ 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,
+ 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,
+ 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,
+ 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,
+ 0x3e721277},
+ {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,
+ 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,
+ 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,
+ 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,
+ 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,
+ 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,
+ 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,
+ 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,
+ 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,
+ 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,
+ 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,
+ 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,
+ 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,
+ 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,
+ 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,
+ 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,
+ 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,
+ 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,
+ 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,
+ 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,
+ 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,
+ 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,
+ 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,
+ 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,
+ 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,
+ 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,
+ 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,
+ 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,
+ 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,
+ 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,
+ 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,
+ 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,
+ 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,
+ 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,
+ 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,
+ 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,
+ 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,
+ 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,
+ 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,
+ 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,
+ 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,
+ 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,
+ 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,
+ 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,
+ 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,
+ 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,
+ 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,
+ 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,
+ 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,
+ 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,
+ 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,
+ 0x1c65ace7}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,
+ 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,
+ 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,
+ 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,
+ 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,
+ 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,
+ 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,
+ 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,
+ 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,
+ 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,
+ 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,
+ 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,
+ 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,
+ 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,
+ 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,
+ 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,
+ 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,
+ 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,
+ 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,
+ 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,
+ 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,
+ 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,
+ 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,
+ 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,
+ 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,
+ 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,
+ 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,
+ 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,
+ 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,
+ 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,
+ 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,
+ 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,
+ 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,
+ 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,
+ 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,
+ 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,
+ 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,
+ 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,
+ 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,
+ 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,
+ 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,
+ 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,
+ 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,
+ 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,
+ 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,
+ 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,
+ 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,
+ 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,
+ 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,
+ 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,
+ 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,
+ 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,
+ 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,
+ 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,
+ 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,
+ 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,
+ 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,
+ 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,
+ 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,
+ 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,
+ 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,
+ 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,
+ 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,
+ 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,
+ 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,
+ 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,
+ 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,
+ 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,
+ 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,
+ 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,
+ 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,
+ 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,
+ 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,
+ 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,
+ 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,
+ 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,
+ 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,
+ 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,
+ 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,
+ 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,
+ 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,
+ 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,
+ 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,
+ 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,
+ 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,
+ 0xe7ac651c00000000},
+ {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,
+ 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,
+ 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,
+ 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,
+ 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,
+ 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,
+ 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,
+ 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,
+ 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,
+ 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,
+ 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,
+ 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,
+ 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,
+ 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,
+ 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,
+ 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,
+ 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,
+ 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,
+ 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,
+ 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,
+ 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,
+ 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,
+ 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,
+ 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,
+ 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,
+ 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,
+ 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,
+ 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,
+ 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,
+ 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,
+ 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,
+ 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,
+ 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,
+ 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,
+ 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,
+ 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,
+ 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,
+ 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,
+ 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,
+ 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,
+ 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,
+ 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,
+ 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,
+ 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,
+ 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,
+ 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,
+ 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,
+ 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,
+ 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,
+ 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,
+ 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,
+ 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,
+ 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,
+ 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,
+ 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,
+ 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,
+ 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,
+ 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,
+ 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,
+ 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,
+ 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,
+ 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,
+ 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,
+ 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,
+ 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,
+ 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,
+ 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,
+ 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,
+ 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,
+ 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,
+ 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,
+ 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,
+ 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,
+ 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,
+ 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,
+ 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,
+ 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,
+ 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,
+ 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,
+ 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,
+ 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,
+ 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,
+ 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,
+ 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,
+ 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,
+ 0x7712723e00000000},
+ {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,
+ 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,
+ 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,
+ 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,
+ 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,
+ 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,
+ 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,
+ 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,
+ 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,
+ 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,
+ 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,
+ 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,
+ 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,
+ 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,
+ 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,
+ 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,
+ 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,
+ 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,
+ 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,
+ 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,
+ 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,
+ 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,
+ 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,
+ 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,
+ 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,
+ 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,
+ 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,
+ 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,
+ 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,
+ 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,
+ 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,
+ 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,
+ 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,
+ 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,
+ 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,
+ 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,
+ 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,
+ 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,
+ 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,
+ 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,
+ 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,
+ 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,
+ 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,
+ 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,
+ 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,
+ 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,
+ 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,
+ 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,
+ 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,
+ 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,
+ 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,
+ 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,
+ 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,
+ 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,
+ 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,
+ 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,
+ 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,
+ 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,
+ 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,
+ 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,
+ 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,
+ 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,
+ 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,
+ 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,
+ 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,
+ 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,
+ 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,
+ 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,
+ 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,
+ 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,
+ 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,
+ 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,
+ 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,
+ 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,
+ 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,
+ 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,
+ 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,
+ 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,
+ 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,
+ 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,
+ 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,
+ 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,
+ 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,
+ 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,
+ 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,
+ 0x8d965fce00000000},
+ {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,
+ 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,
+ 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,
+ 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,
+ 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,
+ 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,
+ 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,
+ 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,
+ 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,
+ 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,
+ 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,
+ 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,
+ 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,
+ 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,
+ 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,
+ 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,
+ 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,
+ 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,
+ 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,
+ 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,
+ 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,
+ 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,
+ 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,
+ 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,
+ 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,
+ 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,
+ 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,
+ 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,
+ 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,
+ 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,
+ 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,
+ 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,
+ 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,
+ 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,
+ 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,
+ 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,
+ 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,
+ 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,
+ 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,
+ 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,
+ 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,
+ 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,
+ 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,
+ 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,
+ 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,
+ 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,
+ 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,
+ 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,
+ 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,
+ 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,
+ 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,
+ 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,
+ 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,
+ 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,
+ 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,
+ 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,
+ 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,
+ 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,
+ 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,
+ 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,
+ 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,
+ 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,
+ 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,
+ 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,
+ 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,
+ 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,
+ 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,
+ 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,
+ 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,
+ 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,
+ 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,
+ 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,
+ 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,
+ 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,
+ 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,
+ 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,
+ 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,
+ 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,
+ 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,
+ 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,
+ 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,
+ 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,
+ 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,
+ 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,
+ 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,
+ 0x0ba0c79300000000},
+ {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,
+ 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,
+ 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,
+ 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,
+ 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,
+ 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,
+ 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,
+ 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,
+ 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,
+ 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,
+ 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,
+ 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,
+ 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,
+ 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,
+ 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,
+ 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,
+ 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,
+ 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,
+ 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,
+ 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,
+ 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,
+ 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,
+ 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,
+ 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,
+ 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,
+ 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,
+ 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,
+ 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,
+ 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,
+ 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,
+ 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,
+ 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,
+ 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,
+ 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,
+ 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,
+ 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,
+ 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,
+ 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,
+ 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,
+ 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,
+ 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,
+ 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,
+ 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,
+ 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,
+ 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,
+ 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,
+ 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,
+ 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,
+ 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,
+ 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,
+ 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,
+ 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,
+ 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,
+ 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,
+ 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,
+ 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,
+ 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,
+ 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,
+ 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,
+ 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,
+ 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,
+ 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,
+ 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,
+ 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,
+ 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,
+ 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,
+ 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,
+ 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,
+ 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,
+ 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,
+ 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,
+ 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,
+ 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,
+ 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,
+ 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,
+ 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,
+ 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,
+ 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,
+ 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,
+ 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,
+ 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,
+ 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,
+ 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,
+ 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,
+ 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,
+ 0x281e419700000000},
+ {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,
+ 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,
+ 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,
+ 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,
+ 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,
+ 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,
+ 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,
+ 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,
+ 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,
+ 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,
+ 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,
+ 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,
+ 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,
+ 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,
+ 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,
+ 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,
+ 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,
+ 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,
+ 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,
+ 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,
+ 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,
+ 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,
+ 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,
+ 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,
+ 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,
+ 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,
+ 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,
+ 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,
+ 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,
+ 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,
+ 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,
+ 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,
+ 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,
+ 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,
+ 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,
+ 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,
+ 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,
+ 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,
+ 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,
+ 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,
+ 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,
+ 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,
+ 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,
+ 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,
+ 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,
+ 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,
+ 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,
+ 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,
+ 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,
+ 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,
+ 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,
+ 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,
+ 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,
+ 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,
+ 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,
+ 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,
+ 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,
+ 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,
+ 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,
+ 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,
+ 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,
+ 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,
+ 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,
+ 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,
+ 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,
+ 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,
+ 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,
+ 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,
+ 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,
+ 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,
+ 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,
+ 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,
+ 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,
+ 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,
+ 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,
+ 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,
+ 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,
+ 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,
+ 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,
+ 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,
+ 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,
+ 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,
+ 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,
+ 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,
+ 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,
+ 0xe4e9223500000000},
+ {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,
+ 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,
+ 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,
+ 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,
+ 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,
+ 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,
+ 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,
+ 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,
+ 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,
+ 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,
+ 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,
+ 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,
+ 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,
+ 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,
+ 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,
+ 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,
+ 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,
+ 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,
+ 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,
+ 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,
+ 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,
+ 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,
+ 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,
+ 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,
+ 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,
+ 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,
+ 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,
+ 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,
+ 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,
+ 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,
+ 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,
+ 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,
+ 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,
+ 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,
+ 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,
+ 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,
+ 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,
+ 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,
+ 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,
+ 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,
+ 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,
+ 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,
+ 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,
+ 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,
+ 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,
+ 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,
+ 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,
+ 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,
+ 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,
+ 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,
+ 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,
+ 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,
+ 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,
+ 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,
+ 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,
+ 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,
+ 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,
+ 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,
+ 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,
+ 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,
+ 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,
+ 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,
+ 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,
+ 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,
+ 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,
+ 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,
+ 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,
+ 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,
+ 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,
+ 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,
+ 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,
+ 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,
+ 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,
+ 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,
+ 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,
+ 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,
+ 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,
+ 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,
+ 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,
+ 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,
+ 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,
+ 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,
+ 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,
+ 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,
+ 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,
+ 0x880452a700000000},
+ {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,
+ 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,
+ 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,
+ 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,
+ 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,
+ 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,
+ 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,
+ 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,
+ 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,
+ 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,
+ 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,
+ 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,
+ 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,
+ 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,
+ 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,
+ 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,
+ 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,
+ 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,
+ 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,
+ 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,
+ 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,
+ 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,
+ 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,
+ 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,
+ 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,
+ 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,
+ 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,
+ 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,
+ 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,
+ 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,
+ 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,
+ 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,
+ 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,
+ 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,
+ 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,
+ 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,
+ 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,
+ 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,
+ 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,
+ 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,
+ 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,
+ 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,
+ 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,
+ 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,
+ 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,
+ 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,
+ 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,
+ 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,
+ 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,
+ 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,
+ 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,
+ 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,
+ 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,
+ 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,
+ 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,
+ 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,
+ 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,
+ 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,
+ 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,
+ 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,
+ 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,
+ 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,
+ 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,
+ 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,
+ 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,
+ 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,
+ 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,
+ 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,
+ 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,
+ 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,
+ 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,
+ 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,
+ 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,
+ 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,
+ 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,
+ 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,
+ 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,
+ 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,
+ 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,
+ 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,
+ 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,
+ 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,
+ 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,
+ 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,
+ 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,
+ 0x1659c4e300000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,
+ 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,
+ 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,
+ 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,
+ 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,
+ 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,
+ 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,
+ 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,
+ 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,
+ 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,
+ 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,
+ 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,
+ 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,
+ 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,
+ 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,
+ 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,
+ 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,
+ 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,
+ 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,
+ 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,
+ 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,
+ 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,
+ 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,
+ 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,
+ 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,
+ 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,
+ 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,
+ 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,
+ 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,
+ 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,
+ 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,
+ 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,
+ 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,
+ 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,
+ 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,
+ 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,
+ 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,
+ 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,
+ 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,
+ 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,
+ 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,
+ 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,
+ 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,
+ 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,
+ 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,
+ 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,
+ 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,
+ 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,
+ 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,
+ 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,
+ 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,
+ 0xa68cee3d},
+ {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,
+ 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,
+ 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,
+ 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,
+ 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,
+ 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,
+ 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,
+ 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,
+ 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,
+ 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,
+ 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,
+ 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,
+ 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,
+ 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,
+ 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,
+ 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,
+ 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,
+ 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,
+ 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,
+ 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,
+ 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,
+ 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,
+ 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,
+ 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,
+ 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,
+ 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,
+ 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,
+ 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,
+ 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,
+ 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,
+ 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,
+ 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,
+ 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,
+ 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,
+ 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,
+ 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,
+ 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,
+ 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,
+ 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,
+ 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,
+ 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,
+ 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,
+ 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,
+ 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,
+ 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,
+ 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,
+ 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,
+ 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,
+ 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,
+ 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,
+ 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,
+ 0x51e8883f},
+ {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,
+ 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,
+ 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,
+ 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,
+ 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,
+ 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,
+ 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,
+ 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,
+ 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,
+ 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,
+ 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,
+ 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,
+ 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,
+ 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,
+ 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,
+ 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,
+ 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,
+ 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,
+ 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,
+ 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,
+ 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,
+ 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,
+ 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,
+ 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,
+ 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,
+ 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,
+ 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,
+ 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,
+ 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,
+ 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,
+ 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,
+ 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,
+ 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,
+ 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,
+ 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,
+ 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,
+ 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,
+ 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,
+ 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,
+ 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,
+ 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,
+ 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,
+ 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,
+ 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,
+ 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,
+ 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,
+ 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,
+ 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,
+ 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,
+ 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,
+ 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,
+ 0x8ae9531c},
+ {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,
+ 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,
+ 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,
+ 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,
+ 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,
+ 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,
+ 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,
+ 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,
+ 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,
+ 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,
+ 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,
+ 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,
+ 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,
+ 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,
+ 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,
+ 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,
+ 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,
+ 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,
+ 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,
+ 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,
+ 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,
+ 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,
+ 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,
+ 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,
+ 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,
+ 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,
+ 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,
+ 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,
+ 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,
+ 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,
+ 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,
+ 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,
+ 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,
+ 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,
+ 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,
+ 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,
+ 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,
+ 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,
+ 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,
+ 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,
+ 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,
+ 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,
+ 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,
+ 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,
+ 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,
+ 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,
+ 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,
+ 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,
+ 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,
+ 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,
+ 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,
+ 0xd739710d}};
+
+#endif
+
+#endif
+
+#if N == 5
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,
+ 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,
+ 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,
+ 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,
+ 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,
+ 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,
+ 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,
+ 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,
+ 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,
+ 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,
+ 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,
+ 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,
+ 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,
+ 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,
+ 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,
+ 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,
+ 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,
+ 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,
+ 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,
+ 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,
+ 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,
+ 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,
+ 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,
+ 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,
+ 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,
+ 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,
+ 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,
+ 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,
+ 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,
+ 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,
+ 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,
+ 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,
+ 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,
+ 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,
+ 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,
+ 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,
+ 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,
+ 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,
+ 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,
+ 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,
+ 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,
+ 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,
+ 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,
+ 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,
+ 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,
+ 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,
+ 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,
+ 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,
+ 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,
+ 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,
+ 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,
+ 0xe9947565},
+ {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,
+ 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,
+ 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,
+ 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,
+ 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,
+ 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,
+ 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,
+ 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,
+ 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,
+ 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,
+ 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,
+ 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,
+ 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,
+ 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,
+ 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,
+ 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,
+ 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,
+ 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,
+ 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,
+ 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,
+ 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,
+ 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,
+ 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,
+ 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,
+ 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,
+ 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,
+ 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,
+ 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,
+ 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,
+ 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,
+ 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,
+ 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,
+ 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,
+ 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,
+ 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,
+ 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,
+ 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,
+ 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,
+ 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,
+ 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,
+ 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,
+ 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,
+ 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,
+ 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,
+ 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,
+ 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,
+ 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,
+ 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,
+ 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,
+ 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,
+ 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,
+ 0xf7d05006},
+ {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,
+ 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,
+ 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,
+ 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,
+ 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,
+ 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,
+ 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,
+ 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,
+ 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,
+ 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,
+ 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,
+ 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,
+ 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,
+ 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,
+ 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,
+ 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,
+ 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,
+ 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,
+ 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,
+ 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,
+ 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,
+ 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,
+ 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,
+ 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,
+ 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,
+ 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,
+ 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,
+ 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,
+ 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,
+ 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,
+ 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,
+ 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,
+ 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,
+ 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,
+ 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,
+ 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,
+ 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,
+ 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,
+ 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,
+ 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,
+ 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,
+ 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,
+ 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,
+ 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,
+ 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,
+ 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,
+ 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,
+ 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,
+ 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,
+ 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,
+ 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,
+ 0xb2075b94},
+ {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,
+ 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,
+ 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,
+ 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,
+ 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,
+ 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,
+ 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,
+ 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,
+ 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,
+ 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,
+ 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,
+ 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,
+ 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,
+ 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,
+ 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,
+ 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,
+ 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,
+ 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,
+ 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,
+ 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,
+ 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,
+ 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,
+ 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,
+ 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,
+ 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,
+ 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,
+ 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,
+ 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,
+ 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,
+ 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,
+ 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,
+ 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,
+ 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,
+ 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,
+ 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,
+ 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,
+ 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,
+ 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,
+ 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,
+ 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,
+ 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,
+ 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,
+ 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,
+ 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,
+ 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,
+ 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,
+ 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,
+ 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,
+ 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,
+ 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,
+ 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,
+ 0xba50bcb9},
+ {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,
+ 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,
+ 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,
+ 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,
+ 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,
+ 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,
+ 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,
+ 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,
+ 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,
+ 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,
+ 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,
+ 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,
+ 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,
+ 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,
+ 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,
+ 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,
+ 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,
+ 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,
+ 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,
+ 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,
+ 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,
+ 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,
+ 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,
+ 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,
+ 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,
+ 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,
+ 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,
+ 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,
+ 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,
+ 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,
+ 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,
+ 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,
+ 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,
+ 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,
+ 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,
+ 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,
+ 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,
+ 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,
+ 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,
+ 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,
+ 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,
+ 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,
+ 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,
+ 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,
+ 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,
+ 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,
+ 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,
+ 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,
+ 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,
+ 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,
+ 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,
+ 0x808abcf4},
+ {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,
+ 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,
+ 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,
+ 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,
+ 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,
+ 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,
+ 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,
+ 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,
+ 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,
+ 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,
+ 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,
+ 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,
+ 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,
+ 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,
+ 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,
+ 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,
+ 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,
+ 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,
+ 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,
+ 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,
+ 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,
+ 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,
+ 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,
+ 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,
+ 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,
+ 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,
+ 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,
+ 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,
+ 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,
+ 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,
+ 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,
+ 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,
+ 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,
+ 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,
+ 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,
+ 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,
+ 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,
+ 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,
+ 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,
+ 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,
+ 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,
+ 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,
+ 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,
+ 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,
+ 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,
+ 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,
+ 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,
+ 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,
+ 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,
+ 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,
+ 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,
+ 0xefdb3f95},
+ {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,
+ 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,
+ 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,
+ 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,
+ 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,
+ 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,
+ 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,
+ 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,
+ 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,
+ 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,
+ 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,
+ 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,
+ 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,
+ 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,
+ 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,
+ 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,
+ 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,
+ 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,
+ 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,
+ 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,
+ 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,
+ 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,
+ 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,
+ 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,
+ 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,
+ 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,
+ 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,
+ 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,
+ 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,
+ 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,
+ 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,
+ 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,
+ 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,
+ 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,
+ 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,
+ 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,
+ 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,
+ 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,
+ 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,
+ 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,
+ 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,
+ 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,
+ 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,
+ 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,
+ 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,
+ 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,
+ 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,
+ 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,
+ 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,
+ 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,
+ 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,
+ 0x0e2fbf43},
+ {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,
+ 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,
+ 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,
+ 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,
+ 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,
+ 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,
+ 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,
+ 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,
+ 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,
+ 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,
+ 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,
+ 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,
+ 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,
+ 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,
+ 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,
+ 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,
+ 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,
+ 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,
+ 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,
+ 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,
+ 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,
+ 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,
+ 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,
+ 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,
+ 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,
+ 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,
+ 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,
+ 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,
+ 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,
+ 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,
+ 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,
+ 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,
+ 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,
+ 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,
+ 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,
+ 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,
+ 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,
+ 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,
+ 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,
+ 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,
+ 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,
+ 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,
+ 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,
+ 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,
+ 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,
+ 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,
+ 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,
+ 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,
+ 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,
+ 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,
+ 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,
+ 0xf4377108}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,
+ 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,
+ 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,
+ 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,
+ 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,
+ 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,
+ 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,
+ 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,
+ 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,
+ 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,
+ 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,
+ 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,
+ 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,
+ 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,
+ 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,
+ 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,
+ 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,
+ 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,
+ 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,
+ 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,
+ 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,
+ 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,
+ 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,
+ 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,
+ 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,
+ 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,
+ 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,
+ 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,
+ 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,
+ 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,
+ 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,
+ 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,
+ 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,
+ 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,
+ 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,
+ 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,
+ 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,
+ 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,
+ 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,
+ 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,
+ 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,
+ 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,
+ 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,
+ 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,
+ 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,
+ 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,
+ 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,
+ 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,
+ 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,
+ 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,
+ 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,
+ 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,
+ 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,
+ 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,
+ 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,
+ 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,
+ 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,
+ 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,
+ 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,
+ 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,
+ 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,
+ 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,
+ 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,
+ 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,
+ 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,
+ 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,
+ 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,
+ 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,
+ 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,
+ 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,
+ 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,
+ 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,
+ 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,
+ 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,
+ 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,
+ 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,
+ 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,
+ 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,
+ 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,
+ 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,
+ 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,
+ 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,
+ 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,
+ 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,
+ 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,
+ 0x087137f400000000},
+ {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,
+ 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,
+ 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,
+ 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,
+ 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,
+ 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,
+ 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,
+ 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,
+ 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,
+ 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,
+ 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,
+ 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,
+ 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,
+ 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,
+ 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,
+ 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,
+ 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,
+ 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,
+ 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,
+ 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,
+ 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,
+ 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,
+ 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,
+ 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,
+ 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,
+ 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,
+ 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,
+ 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,
+ 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,
+ 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,
+ 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,
+ 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,
+ 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,
+ 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,
+ 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,
+ 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,
+ 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,
+ 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,
+ 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,
+ 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,
+ 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,
+ 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,
+ 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,
+ 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,
+ 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,
+ 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,
+ 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,
+ 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,
+ 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,
+ 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,
+ 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,
+ 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,
+ 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,
+ 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,
+ 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,
+ 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,
+ 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,
+ 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,
+ 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,
+ 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,
+ 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,
+ 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,
+ 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,
+ 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,
+ 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,
+ 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,
+ 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,
+ 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,
+ 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,
+ 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,
+ 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,
+ 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,
+ 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,
+ 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,
+ 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,
+ 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,
+ 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,
+ 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,
+ 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,
+ 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,
+ 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,
+ 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,
+ 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,
+ 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,
+ 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,
+ 0x43bf2f0e00000000},
+ {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,
+ 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,
+ 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,
+ 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,
+ 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,
+ 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,
+ 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,
+ 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,
+ 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,
+ 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,
+ 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,
+ 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,
+ 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,
+ 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,
+ 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,
+ 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,
+ 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,
+ 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,
+ 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,
+ 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,
+ 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,
+ 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,
+ 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,
+ 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,
+ 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,
+ 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,
+ 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,
+ 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,
+ 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,
+ 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,
+ 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,
+ 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,
+ 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,
+ 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,
+ 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,
+ 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,
+ 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,
+ 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,
+ 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,
+ 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,
+ 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,
+ 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,
+ 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,
+ 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,
+ 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,
+ 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,
+ 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,
+ 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,
+ 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,
+ 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,
+ 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,
+ 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,
+ 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,
+ 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,
+ 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,
+ 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,
+ 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,
+ 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,
+ 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,
+ 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,
+ 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,
+ 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,
+ 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,
+ 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,
+ 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,
+ 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,
+ 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,
+ 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,
+ 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,
+ 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,
+ 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,
+ 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,
+ 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,
+ 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,
+ 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,
+ 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,
+ 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,
+ 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,
+ 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,
+ 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,
+ 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,
+ 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,
+ 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,
+ 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,
+ 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,
+ 0x953fdbef00000000},
+ {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,
+ 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,
+ 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,
+ 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,
+ 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,
+ 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,
+ 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,
+ 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,
+ 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,
+ 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,
+ 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,
+ 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,
+ 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,
+ 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,
+ 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,
+ 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,
+ 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,
+ 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,
+ 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,
+ 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,
+ 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,
+ 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,
+ 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,
+ 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,
+ 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,
+ 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,
+ 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,
+ 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,
+ 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,
+ 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,
+ 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,
+ 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,
+ 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,
+ 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,
+ 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,
+ 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,
+ 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,
+ 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,
+ 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,
+ 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,
+ 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,
+ 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,
+ 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,
+ 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,
+ 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,
+ 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,
+ 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,
+ 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,
+ 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,
+ 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,
+ 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,
+ 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,
+ 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,
+ 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,
+ 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,
+ 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,
+ 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,
+ 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,
+ 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,
+ 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,
+ 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,
+ 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,
+ 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,
+ 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,
+ 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,
+ 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,
+ 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,
+ 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,
+ 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,
+ 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,
+ 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,
+ 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,
+ 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,
+ 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,
+ 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,
+ 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,
+ 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,
+ 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,
+ 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,
+ 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,
+ 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,
+ 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,
+ 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,
+ 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,
+ 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,
+ 0xf4bc8a8000000000},
+ {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,
+ 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,
+ 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,
+ 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,
+ 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,
+ 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,
+ 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,
+ 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,
+ 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,
+ 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,
+ 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,
+ 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,
+ 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,
+ 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,
+ 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,
+ 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,
+ 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,
+ 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,
+ 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,
+ 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,
+ 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,
+ 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,
+ 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,
+ 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,
+ 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,
+ 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,
+ 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,
+ 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,
+ 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,
+ 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,
+ 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,
+ 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,
+ 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,
+ 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,
+ 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,
+ 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,
+ 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,
+ 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,
+ 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,
+ 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,
+ 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,
+ 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,
+ 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,
+ 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,
+ 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,
+ 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,
+ 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,
+ 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,
+ 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,
+ 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,
+ 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,
+ 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,
+ 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,
+ 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,
+ 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,
+ 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,
+ 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,
+ 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,
+ 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,
+ 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,
+ 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,
+ 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,
+ 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,
+ 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,
+ 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,
+ 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,
+ 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,
+ 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,
+ 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,
+ 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,
+ 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,
+ 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,
+ 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,
+ 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,
+ 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,
+ 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,
+ 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,
+ 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,
+ 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,
+ 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,
+ 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,
+ 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,
+ 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,
+ 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,
+ 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,
+ 0xb9bc50ba00000000},
+ {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,
+ 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,
+ 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,
+ 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,
+ 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,
+ 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,
+ 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,
+ 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,
+ 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,
+ 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,
+ 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,
+ 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,
+ 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,
+ 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,
+ 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,
+ 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,
+ 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,
+ 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,
+ 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,
+ 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,
+ 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,
+ 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,
+ 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,
+ 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,
+ 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,
+ 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,
+ 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,
+ 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,
+ 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,
+ 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,
+ 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,
+ 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,
+ 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,
+ 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,
+ 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,
+ 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,
+ 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,
+ 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,
+ 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,
+ 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,
+ 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,
+ 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,
+ 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,
+ 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,
+ 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,
+ 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,
+ 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,
+ 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,
+ 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,
+ 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,
+ 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,
+ 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,
+ 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,
+ 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,
+ 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,
+ 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,
+ 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,
+ 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,
+ 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,
+ 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,
+ 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,
+ 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,
+ 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,
+ 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,
+ 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,
+ 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,
+ 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,
+ 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,
+ 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,
+ 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,
+ 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,
+ 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,
+ 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,
+ 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,
+ 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,
+ 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,
+ 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,
+ 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,
+ 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,
+ 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,
+ 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,
+ 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,
+ 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,
+ 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,
+ 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,
+ 0x945b07b200000000},
+ {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,
+ 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,
+ 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,
+ 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,
+ 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,
+ 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,
+ 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,
+ 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,
+ 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,
+ 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,
+ 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,
+ 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,
+ 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,
+ 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,
+ 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,
+ 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,
+ 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,
+ 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,
+ 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,
+ 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,
+ 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,
+ 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,
+ 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,
+ 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,
+ 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,
+ 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,
+ 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,
+ 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,
+ 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,
+ 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,
+ 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,
+ 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,
+ 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,
+ 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,
+ 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,
+ 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,
+ 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,
+ 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,
+ 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,
+ 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,
+ 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,
+ 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,
+ 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,
+ 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,
+ 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,
+ 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,
+ 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,
+ 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,
+ 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,
+ 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,
+ 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,
+ 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,
+ 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,
+ 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,
+ 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,
+ 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,
+ 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,
+ 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,
+ 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,
+ 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,
+ 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,
+ 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,
+ 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,
+ 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,
+ 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,
+ 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,
+ 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,
+ 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,
+ 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,
+ 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,
+ 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,
+ 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,
+ 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,
+ 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,
+ 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,
+ 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,
+ 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,
+ 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,
+ 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,
+ 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,
+ 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,
+ 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,
+ 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,
+ 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,
+ 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,
+ 0x0650d0f700000000},
+ {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,
+ 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,
+ 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,
+ 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,
+ 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,
+ 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,
+ 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,
+ 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,
+ 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,
+ 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,
+ 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,
+ 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,
+ 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,
+ 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,
+ 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,
+ 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,
+ 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,
+ 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,
+ 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,
+ 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,
+ 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,
+ 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,
+ 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,
+ 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,
+ 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,
+ 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,
+ 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,
+ 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,
+ 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,
+ 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,
+ 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,
+ 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,
+ 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,
+ 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,
+ 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,
+ 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,
+ 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,
+ 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,
+ 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,
+ 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,
+ 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,
+ 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,
+ 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,
+ 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,
+ 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,
+ 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,
+ 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,
+ 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,
+ 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,
+ 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,
+ 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,
+ 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,
+ 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,
+ 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,
+ 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,
+ 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,
+ 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,
+ 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,
+ 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,
+ 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,
+ 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,
+ 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,
+ 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,
+ 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,
+ 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,
+ 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,
+ 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,
+ 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,
+ 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,
+ 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,
+ 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,
+ 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,
+ 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,
+ 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,
+ 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,
+ 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,
+ 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,
+ 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,
+ 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,
+ 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,
+ 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,
+ 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,
+ 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,
+ 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,
+ 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,
+ 0x657594e900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,
+ 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,
+ 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,
+ 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,
+ 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,
+ 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,
+ 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,
+ 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,
+ 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,
+ 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,
+ 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,
+ 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,
+ 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,
+ 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,
+ 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,
+ 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,
+ 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,
+ 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,
+ 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,
+ 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,
+ 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,
+ 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,
+ 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,
+ 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,
+ 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,
+ 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,
+ 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,
+ 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,
+ 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,
+ 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,
+ 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,
+ 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,
+ 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,
+ 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,
+ 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,
+ 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,
+ 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,
+ 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,
+ 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,
+ 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,
+ 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,
+ 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,
+ 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,
+ 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,
+ 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,
+ 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,
+ 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,
+ 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,
+ 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,
+ 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,
+ 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,
+ 0x4e36ba18},
+ {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,
+ 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,
+ 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,
+ 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,
+ 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,
+ 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,
+ 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,
+ 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,
+ 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,
+ 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,
+ 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,
+ 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,
+ 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,
+ 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,
+ 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,
+ 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,
+ 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,
+ 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,
+ 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,
+ 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,
+ 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,
+ 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,
+ 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,
+ 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,
+ 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,
+ 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,
+ 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,
+ 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,
+ 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,
+ 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,
+ 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,
+ 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,
+ 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,
+ 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,
+ 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,
+ 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,
+ 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,
+ 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,
+ 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,
+ 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,
+ 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,
+ 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,
+ 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,
+ 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,
+ 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,
+ 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,
+ 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,
+ 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,
+ 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,
+ 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,
+ 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,
+ 0xa1d67c91},
+ {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,
+ 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,
+ 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,
+ 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,
+ 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,
+ 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,
+ 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,
+ 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,
+ 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,
+ 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,
+ 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,
+ 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,
+ 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,
+ 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,
+ 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,
+ 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,
+ 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,
+ 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,
+ 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,
+ 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,
+ 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,
+ 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,
+ 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,
+ 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,
+ 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,
+ 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,
+ 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,
+ 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,
+ 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,
+ 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,
+ 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,
+ 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,
+ 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,
+ 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,
+ 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,
+ 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,
+ 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,
+ 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,
+ 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,
+ 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,
+ 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,
+ 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,
+ 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,
+ 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,
+ 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,
+ 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,
+ 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,
+ 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,
+ 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,
+ 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,
+ 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,
+ 0xa8ef40a1},
+ {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,
+ 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,
+ 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,
+ 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,
+ 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,
+ 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,
+ 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,
+ 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,
+ 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,
+ 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,
+ 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,
+ 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,
+ 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,
+ 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,
+ 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,
+ 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,
+ 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,
+ 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,
+ 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,
+ 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,
+ 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,
+ 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,
+ 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,
+ 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,
+ 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,
+ 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,
+ 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,
+ 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,
+ 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,
+ 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,
+ 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,
+ 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,
+ 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,
+ 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,
+ 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,
+ 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,
+ 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,
+ 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,
+ 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,
+ 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,
+ 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,
+ 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,
+ 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,
+ 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,
+ 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,
+ 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,
+ 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,
+ 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,
+ 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,
+ 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,
+ 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,
+ 0x356bacd8}};
+
+#endif
+
+#endif
+
+#if N == 6
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,
+ 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,
+ 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,
+ 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,
+ 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,
+ 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,
+ 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,
+ 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,
+ 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,
+ 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,
+ 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,
+ 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,
+ 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,
+ 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,
+ 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,
+ 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,
+ 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,
+ 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,
+ 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,
+ 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,
+ 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,
+ 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,
+ 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,
+ 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,
+ 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,
+ 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,
+ 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,
+ 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,
+ 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,
+ 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,
+ 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,
+ 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,
+ 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,
+ 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,
+ 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,
+ 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,
+ 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,
+ 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,
+ 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,
+ 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,
+ 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,
+ 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,
+ 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,
+ 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,
+ 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,
+ 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,
+ 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,
+ 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,
+ 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,
+ 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,
+ 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,
+ 0x8568a0a8},
+ {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,
+ 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,
+ 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,
+ 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,
+ 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,
+ 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,
+ 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,
+ 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,
+ 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,
+ 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,
+ 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,
+ 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,
+ 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,
+ 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,
+ 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,
+ 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,
+ 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,
+ 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,
+ 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,
+ 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,
+ 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,
+ 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,
+ 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,
+ 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,
+ 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,
+ 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,
+ 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,
+ 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,
+ 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,
+ 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,
+ 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,
+ 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,
+ 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,
+ 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,
+ 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,
+ 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,
+ 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,
+ 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,
+ 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,
+ 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,
+ 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,
+ 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,
+ 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,
+ 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,
+ 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,
+ 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,
+ 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,
+ 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,
+ 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,
+ 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,
+ 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,
+ 0x0d907052},
+ {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,
+ 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,
+ 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,
+ 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,
+ 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,
+ 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,
+ 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,
+ 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,
+ 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,
+ 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,
+ 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,
+ 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,
+ 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,
+ 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,
+ 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,
+ 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,
+ 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,
+ 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,
+ 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,
+ 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,
+ 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,
+ 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,
+ 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,
+ 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,
+ 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,
+ 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,
+ 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,
+ 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,
+ 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,
+ 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,
+ 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,
+ 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,
+ 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,
+ 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,
+ 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,
+ 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,
+ 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,
+ 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,
+ 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,
+ 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,
+ 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,
+ 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,
+ 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,
+ 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,
+ 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,
+ 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,
+ 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,
+ 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,
+ 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,
+ 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,
+ 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,
+ 0xfd1a6c8a},
+ {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,
+ 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,
+ 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,
+ 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,
+ 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,
+ 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,
+ 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,
+ 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,
+ 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,
+ 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,
+ 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,
+ 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,
+ 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,
+ 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,
+ 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,
+ 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,
+ 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,
+ 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,
+ 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,
+ 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,
+ 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,
+ 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,
+ 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,
+ 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,
+ 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,
+ 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,
+ 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,
+ 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,
+ 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,
+ 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,
+ 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,
+ 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,
+ 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,
+ 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,
+ 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,
+ 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,
+ 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,
+ 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,
+ 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,
+ 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,
+ 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,
+ 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,
+ 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,
+ 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,
+ 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,
+ 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,
+ 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,
+ 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,
+ 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,
+ 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,
+ 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,
+ 0x7895f01a},
+ {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,
+ 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,
+ 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,
+ 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,
+ 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,
+ 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,
+ 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,
+ 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,
+ 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,
+ 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,
+ 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,
+ 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,
+ 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,
+ 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,
+ 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,
+ 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,
+ 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,
+ 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,
+ 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,
+ 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,
+ 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,
+ 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,
+ 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,
+ 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,
+ 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,
+ 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,
+ 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,
+ 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,
+ 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,
+ 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,
+ 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,
+ 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,
+ 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,
+ 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,
+ 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,
+ 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,
+ 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,
+ 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,
+ 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,
+ 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,
+ 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,
+ 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,
+ 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,
+ 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,
+ 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,
+ 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,
+ 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,
+ 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,
+ 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,
+ 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,
+ 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,
+ 0x9239b848},
+ {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,
+ 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,
+ 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,
+ 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,
+ 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,
+ 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,
+ 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,
+ 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,
+ 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,
+ 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,
+ 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,
+ 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,
+ 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,
+ 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,
+ 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,
+ 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,
+ 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,
+ 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,
+ 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,
+ 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,
+ 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,
+ 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,
+ 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,
+ 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,
+ 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,
+ 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,
+ 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,
+ 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,
+ 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,
+ 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,
+ 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,
+ 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,
+ 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,
+ 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,
+ 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,
+ 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,
+ 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,
+ 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,
+ 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,
+ 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,
+ 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,
+ 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,
+ 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,
+ 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,
+ 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,
+ 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,
+ 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,
+ 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,
+ 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,
+ 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,
+ 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,
+ 0xeb36d3cc},
+ {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,
+ 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,
+ 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,
+ 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,
+ 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,
+ 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,
+ 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,
+ 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,
+ 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,
+ 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,
+ 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,
+ 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,
+ 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,
+ 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,
+ 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,
+ 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,
+ 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,
+ 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,
+ 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,
+ 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,
+ 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,
+ 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,
+ 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,
+ 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,
+ 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,
+ 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,
+ 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,
+ 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,
+ 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,
+ 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,
+ 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,
+ 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,
+ 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,
+ 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,
+ 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,
+ 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,
+ 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,
+ 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,
+ 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,
+ 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,
+ 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,
+ 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,
+ 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,
+ 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,
+ 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,
+ 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,
+ 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,
+ 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,
+ 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,
+ 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,
+ 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,
+ 0x38e5f3c5},
+ {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,
+ 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,
+ 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,
+ 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,
+ 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,
+ 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,
+ 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,
+ 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,
+ 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,
+ 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,
+ 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,
+ 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,
+ 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,
+ 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,
+ 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,
+ 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,
+ 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,
+ 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,
+ 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,
+ 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,
+ 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,
+ 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,
+ 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,
+ 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,
+ 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,
+ 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,
+ 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,
+ 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,
+ 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,
+ 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,
+ 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,
+ 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,
+ 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,
+ 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,
+ 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,
+ 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,
+ 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,
+ 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,
+ 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,
+ 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,
+ 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,
+ 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,
+ 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,
+ 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,
+ 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,
+ 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,
+ 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,
+ 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,
+ 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,
+ 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,
+ 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,
+ 0x3d3101a2}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,
+ 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,
+ 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,
+ 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,
+ 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,
+ 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,
+ 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,
+ 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,
+ 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,
+ 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,
+ 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,
+ 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,
+ 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,
+ 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,
+ 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,
+ 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,
+ 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,
+ 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,
+ 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,
+ 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,
+ 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,
+ 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,
+ 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,
+ 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,
+ 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,
+ 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,
+ 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,
+ 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,
+ 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,
+ 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,
+ 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,
+ 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,
+ 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,
+ 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,
+ 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,
+ 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,
+ 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,
+ 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,
+ 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,
+ 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,
+ 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,
+ 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,
+ 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,
+ 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,
+ 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,
+ 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,
+ 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,
+ 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,
+ 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,
+ 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,
+ 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,
+ 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,
+ 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,
+ 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,
+ 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,
+ 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,
+ 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,
+ 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,
+ 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,
+ 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,
+ 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,
+ 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,
+ 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,
+ 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,
+ 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,
+ 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,
+ 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,
+ 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,
+ 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,
+ 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,
+ 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,
+ 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,
+ 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,
+ 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,
+ 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,
+ 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,
+ 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,
+ 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,
+ 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,
+ 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,
+ 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,
+ 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,
+ 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,
+ 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,
+ 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,
+ 0xa201313d00000000},
+ {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,
+ 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,
+ 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,
+ 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,
+ 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,
+ 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,
+ 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,
+ 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,
+ 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,
+ 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,
+ 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,
+ 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,
+ 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,
+ 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,
+ 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,
+ 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,
+ 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,
+ 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,
+ 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,
+ 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,
+ 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,
+ 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,
+ 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,
+ 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,
+ 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,
+ 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,
+ 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,
+ 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,
+ 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,
+ 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,
+ 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,
+ 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,
+ 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,
+ 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,
+ 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,
+ 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,
+ 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,
+ 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,
+ 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,
+ 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,
+ 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,
+ 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,
+ 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,
+ 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,
+ 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,
+ 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,
+ 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,
+ 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,
+ 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,
+ 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,
+ 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,
+ 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,
+ 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,
+ 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,
+ 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,
+ 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,
+ 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,
+ 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,
+ 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,
+ 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,
+ 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,
+ 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,
+ 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,
+ 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,
+ 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,
+ 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,
+ 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,
+ 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,
+ 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,
+ 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,
+ 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,
+ 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,
+ 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,
+ 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,
+ 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,
+ 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,
+ 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,
+ 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,
+ 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,
+ 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,
+ 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,
+ 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,
+ 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,
+ 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,
+ 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,
+ 0xc5f3e53800000000},
+ {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,
+ 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,
+ 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,
+ 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,
+ 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,
+ 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,
+ 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,
+ 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,
+ 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,
+ 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,
+ 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,
+ 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,
+ 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,
+ 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,
+ 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,
+ 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,
+ 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,
+ 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,
+ 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,
+ 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,
+ 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,
+ 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,
+ 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,
+ 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,
+ 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,
+ 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,
+ 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,
+ 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,
+ 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,
+ 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,
+ 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,
+ 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,
+ 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,
+ 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,
+ 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,
+ 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,
+ 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,
+ 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,
+ 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,
+ 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,
+ 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,
+ 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,
+ 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,
+ 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,
+ 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,
+ 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,
+ 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,
+ 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,
+ 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,
+ 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,
+ 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,
+ 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,
+ 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,
+ 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,
+ 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,
+ 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,
+ 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,
+ 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,
+ 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,
+ 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,
+ 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,
+ 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,
+ 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,
+ 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,
+ 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,
+ 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,
+ 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,
+ 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,
+ 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,
+ 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,
+ 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,
+ 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,
+ 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,
+ 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,
+ 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,
+ 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,
+ 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,
+ 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,
+ 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,
+ 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,
+ 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,
+ 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,
+ 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,
+ 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,
+ 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,
+ 0xccd336eb00000000},
+ {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,
+ 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,
+ 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,
+ 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,
+ 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,
+ 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,
+ 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,
+ 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,
+ 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,
+ 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,
+ 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,
+ 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,
+ 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,
+ 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,
+ 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,
+ 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,
+ 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,
+ 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,
+ 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,
+ 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,
+ 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,
+ 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,
+ 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,
+ 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,
+ 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,
+ 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,
+ 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,
+ 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,
+ 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,
+ 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,
+ 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,
+ 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,
+ 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,
+ 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,
+ 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,
+ 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,
+ 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,
+ 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,
+ 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,
+ 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,
+ 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,
+ 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,
+ 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,
+ 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,
+ 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,
+ 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,
+ 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,
+ 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,
+ 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,
+ 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,
+ 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,
+ 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,
+ 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,
+ 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,
+ 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,
+ 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,
+ 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,
+ 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,
+ 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,
+ 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,
+ 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,
+ 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,
+ 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,
+ 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,
+ 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,
+ 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,
+ 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,
+ 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,
+ 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,
+ 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,
+ 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,
+ 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,
+ 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,
+ 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,
+ 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,
+ 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,
+ 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,
+ 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,
+ 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,
+ 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,
+ 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,
+ 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,
+ 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,
+ 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,
+ 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,
+ 0x48b8399200000000},
+ {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,
+ 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,
+ 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,
+ 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,
+ 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,
+ 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,
+ 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,
+ 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,
+ 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,
+ 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,
+ 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,
+ 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,
+ 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,
+ 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,
+ 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,
+ 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,
+ 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,
+ 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,
+ 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,
+ 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,
+ 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,
+ 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,
+ 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,
+ 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,
+ 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,
+ 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,
+ 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,
+ 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,
+ 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,
+ 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,
+ 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,
+ 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,
+ 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,
+ 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,
+ 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,
+ 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,
+ 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,
+ 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,
+ 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,
+ 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,
+ 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,
+ 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,
+ 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,
+ 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,
+ 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,
+ 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,
+ 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,
+ 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,
+ 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,
+ 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,
+ 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,
+ 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,
+ 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,
+ 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,
+ 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,
+ 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,
+ 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,
+ 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,
+ 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,
+ 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,
+ 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,
+ 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,
+ 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,
+ 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,
+ 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,
+ 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,
+ 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,
+ 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,
+ 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,
+ 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,
+ 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,
+ 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,
+ 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,
+ 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,
+ 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,
+ 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,
+ 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,
+ 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,
+ 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,
+ 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,
+ 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,
+ 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,
+ 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,
+ 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,
+ 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,
+ 0x1af0957800000000},
+ {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,
+ 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,
+ 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,
+ 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,
+ 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,
+ 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,
+ 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,
+ 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,
+ 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,
+ 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,
+ 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,
+ 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,
+ 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,
+ 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,
+ 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,
+ 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,
+ 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,
+ 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,
+ 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,
+ 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,
+ 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,
+ 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,
+ 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,
+ 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,
+ 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,
+ 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,
+ 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,
+ 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,
+ 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,
+ 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,
+ 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,
+ 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,
+ 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,
+ 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,
+ 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,
+ 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,
+ 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,
+ 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,
+ 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,
+ 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,
+ 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,
+ 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,
+ 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,
+ 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,
+ 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,
+ 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,
+ 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,
+ 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,
+ 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,
+ 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,
+ 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,
+ 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,
+ 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,
+ 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,
+ 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,
+ 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,
+ 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,
+ 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,
+ 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,
+ 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,
+ 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,
+ 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,
+ 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,
+ 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,
+ 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,
+ 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,
+ 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,
+ 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,
+ 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,
+ 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,
+ 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,
+ 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,
+ 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,
+ 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,
+ 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,
+ 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,
+ 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,
+ 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,
+ 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,
+ 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,
+ 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,
+ 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,
+ 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,
+ 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,
+ 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,
+ 0x8a6c1afd00000000},
+ {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,
+ 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,
+ 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,
+ 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,
+ 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,
+ 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,
+ 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,
+ 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,
+ 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,
+ 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,
+ 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,
+ 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,
+ 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,
+ 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,
+ 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,
+ 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,
+ 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,
+ 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,
+ 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,
+ 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,
+ 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,
+ 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,
+ 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,
+ 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,
+ 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,
+ 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,
+ 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,
+ 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,
+ 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,
+ 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,
+ 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,
+ 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,
+ 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,
+ 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,
+ 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,
+ 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,
+ 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,
+ 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,
+ 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,
+ 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,
+ 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,
+ 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,
+ 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,
+ 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,
+ 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,
+ 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,
+ 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,
+ 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,
+ 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,
+ 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,
+ 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,
+ 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,
+ 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,
+ 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,
+ 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,
+ 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,
+ 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,
+ 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,
+ 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,
+ 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,
+ 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,
+ 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,
+ 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,
+ 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,
+ 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,
+ 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,
+ 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,
+ 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,
+ 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,
+ 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,
+ 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,
+ 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,
+ 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,
+ 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,
+ 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,
+ 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,
+ 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,
+ 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,
+ 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,
+ 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,
+ 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,
+ 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,
+ 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,
+ 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,
+ 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,
+ 0x5270900d00000000},
+ {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,
+ 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,
+ 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,
+ 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,
+ 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,
+ 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,
+ 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,
+ 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,
+ 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,
+ 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,
+ 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,
+ 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,
+ 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,
+ 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,
+ 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,
+ 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,
+ 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,
+ 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,
+ 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,
+ 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,
+ 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,
+ 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,
+ 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,
+ 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,
+ 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,
+ 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,
+ 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,
+ 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,
+ 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,
+ 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,
+ 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,
+ 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,
+ 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,
+ 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,
+ 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,
+ 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,
+ 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,
+ 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,
+ 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,
+ 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,
+ 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,
+ 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,
+ 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,
+ 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,
+ 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,
+ 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,
+ 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,
+ 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,
+ 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,
+ 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,
+ 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,
+ 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,
+ 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,
+ 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,
+ 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,
+ 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,
+ 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,
+ 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,
+ 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,
+ 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,
+ 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,
+ 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,
+ 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,
+ 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,
+ 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,
+ 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,
+ 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,
+ 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,
+ 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,
+ 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,
+ 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,
+ 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,
+ 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,
+ 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,
+ 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,
+ 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,
+ 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,
+ 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,
+ 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,
+ 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,
+ 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,
+ 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,
+ 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,
+ 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,
+ 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,
+ 0xa8a0688500000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,
+ 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,
+ 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,
+ 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,
+ 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,
+ 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,
+ 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,
+ 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,
+ 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,
+ 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,
+ 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,
+ 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,
+ 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,
+ 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,
+ 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,
+ 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,
+ 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,
+ 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,
+ 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,
+ 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,
+ 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,
+ 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,
+ 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,
+ 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,
+ 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,
+ 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,
+ 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,
+ 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,
+ 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,
+ 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,
+ 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,
+ 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,
+ 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,
+ 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,
+ 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,
+ 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,
+ 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,
+ 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,
+ 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,
+ 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,
+ 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,
+ 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,
+ 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,
+ 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,
+ 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,
+ 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,
+ 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,
+ 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,
+ 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,
+ 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,
+ 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,
+ 0x48686b56},
+ {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,
+ 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,
+ 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,
+ 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,
+ 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,
+ 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,
+ 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,
+ 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,
+ 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,
+ 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,
+ 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,
+ 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,
+ 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,
+ 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,
+ 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,
+ 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,
+ 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,
+ 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,
+ 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,
+ 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,
+ 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,
+ 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,
+ 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,
+ 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,
+ 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,
+ 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,
+ 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,
+ 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,
+ 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,
+ 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,
+ 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,
+ 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,
+ 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,
+ 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,
+ 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,
+ 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,
+ 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,
+ 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,
+ 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,
+ 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,
+ 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,
+ 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,
+ 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,
+ 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,
+ 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,
+ 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,
+ 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,
+ 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,
+ 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,
+ 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,
+ 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,
+ 0xcaa25178},
+ {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,
+ 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,
+ 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,
+ 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,
+ 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,
+ 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,
+ 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,
+ 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,
+ 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,
+ 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,
+ 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,
+ 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,
+ 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,
+ 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,
+ 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,
+ 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,
+ 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,
+ 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,
+ 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,
+ 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,
+ 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,
+ 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,
+ 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,
+ 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,
+ 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,
+ 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,
+ 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,
+ 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,
+ 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,
+ 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,
+ 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,
+ 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,
+ 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,
+ 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,
+ 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,
+ 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,
+ 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,
+ 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,
+ 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,
+ 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,
+ 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,
+ 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,
+ 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,
+ 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,
+ 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,
+ 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,
+ 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,
+ 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,
+ 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,
+ 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,
+ 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,
+ 0x0c7ac97b},
+ {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,
+ 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,
+ 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,
+ 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,
+ 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,
+ 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,
+ 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,
+ 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,
+ 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,
+ 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,
+ 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,
+ 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,
+ 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,
+ 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,
+ 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,
+ 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,
+ 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,
+ 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,
+ 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,
+ 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,
+ 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,
+ 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,
+ 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,
+ 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,
+ 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,
+ 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,
+ 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,
+ 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,
+ 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,
+ 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,
+ 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,
+ 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,
+ 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,
+ 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,
+ 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,
+ 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,
+ 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,
+ 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,
+ 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,
+ 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,
+ 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,
+ 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,
+ 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,
+ 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,
+ 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,
+ 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,
+ 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,
+ 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,
+ 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,
+ 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,
+ 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,
+ 0x5185cd09}};
+
+#endif
+
+#endif
+
+#endif
+
+local const z_crc_t FAR x2n_table[] = {
+ 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,
+ 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,
+ 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,
+ 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,
+ 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,
+ 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,
+ 0xc40ba6d0, 0xc4e22c3c};
diff --git a/libmariadb/external/zlib/crc32_simd.c b/libmariadb/external/zlib/crc32_simd.c
new file mode 100644
index 00000000..cc68d4fc
--- /dev/null
+++ b/libmariadb/external/zlib/crc32_simd.c
@@ -0,0 +1,244 @@
+/* crc32_simd.c
+ *
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the Chromium source repository LICENSE file.
+ */
+
+
+#include "crc32_simd.h"
+
+#if defined(CRC32_SIMD_SSE42_PCLMUL)
+
+/*
+ * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer
+ * length must be at least 64, and a multiple of 16. Based on:
+ *
+ * "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction"
+ * V. Gopal, E. Ozturk, et al., 2009, http://intel.ly/2ySEwL0
+ */
+
+#include <emmintrin.h>
+#include <smmintrin.h>
+#include <wmmintrin.h>
+
+uint32_t ZLIB_INTERNAL crc32_sse42_simd_( /* SSE4.2+PCLMUL */
+ const unsigned char *buf,
+ z_size_t len,
+ uint32_t crc)
+{
+ /*
+ * Definitions of the bit-reflected domain constants k1,k2,k3, etc and
+ * the CRC32+Barrett polynomials given at the end of the paper.
+ */
+ static const uint64_t zalign(16) k1k2[] = { 0x0154442bd4, 0x01c6e41596 };
+ static const uint64_t zalign(16) k3k4[] = { 0x01751997d0, 0x00ccaa009e };
+ static const uint64_t zalign(16) k5k0[] = { 0x0163cd6124, 0x0000000000 };
+ static const uint64_t zalign(16) poly[] = { 0x01db710641, 0x01f7011641 };
+
+ __m128i x0, x1, x2, x3, x4, x5, x6, x7, x8, y5, y6, y7, y8;
+
+ /*
+ * There's at least one block of 64.
+ */
+ x1 = _mm_loadu_si128((__m128i *)(buf + 0x00));
+ x2 = _mm_loadu_si128((__m128i *)(buf + 0x10));
+ x3 = _mm_loadu_si128((__m128i *)(buf + 0x20));
+ x4 = _mm_loadu_si128((__m128i *)(buf + 0x30));
+
+ x1 = _mm_xor_si128(x1, _mm_cvtsi32_si128(crc));
+
+ x0 = _mm_load_si128((__m128i *)k1k2);
+
+ buf += 64;
+ len -= 64;
+
+ /*
+ * Parallel fold blocks of 64, if any.
+ */
+ while (len >= 64)
+ {
+ x5 = _mm_clmulepi64_si128(x1, x0, 0x00);
+ x6 = _mm_clmulepi64_si128(x2, x0, 0x00);
+ x7 = _mm_clmulepi64_si128(x3, x0, 0x00);
+ x8 = _mm_clmulepi64_si128(x4, x0, 0x00);
+
+ x1 = _mm_clmulepi64_si128(x1, x0, 0x11);
+ x2 = _mm_clmulepi64_si128(x2, x0, 0x11);
+ x3 = _mm_clmulepi64_si128(x3, x0, 0x11);
+ x4 = _mm_clmulepi64_si128(x4, x0, 0x11);
+
+ y5 = _mm_loadu_si128((__m128i *)(buf + 0x00));
+ y6 = _mm_loadu_si128((__m128i *)(buf + 0x10));
+ y7 = _mm_loadu_si128((__m128i *)(buf + 0x20));
+ y8 = _mm_loadu_si128((__m128i *)(buf + 0x30));
+
+ x1 = _mm_xor_si128(x1, x5);
+ x2 = _mm_xor_si128(x2, x6);
+ x3 = _mm_xor_si128(x3, x7);
+ x4 = _mm_xor_si128(x4, x8);
+
+ x1 = _mm_xor_si128(x1, y5);
+ x2 = _mm_xor_si128(x2, y6);
+ x3 = _mm_xor_si128(x3, y7);
+ x4 = _mm_xor_si128(x4, y8);
+
+ buf += 64;
+ len -= 64;
+ }
+
+ /*
+ * Fold into 128-bits.
+ */
+ x0 = _mm_load_si128((__m128i *)k3k4);
+
+ x5 = _mm_clmulepi64_si128(x1, x0, 0x00);
+ x1 = _mm_clmulepi64_si128(x1, x0, 0x11);
+ x1 = _mm_xor_si128(x1, x2);
+ x1 = _mm_xor_si128(x1, x5);
+
+ x5 = _mm_clmulepi64_si128(x1, x0, 0x00);
+ x1 = _mm_clmulepi64_si128(x1, x0, 0x11);
+ x1 = _mm_xor_si128(x1, x3);
+ x1 = _mm_xor_si128(x1, x5);
+
+ x5 = _mm_clmulepi64_si128(x1, x0, 0x00);
+ x1 = _mm_clmulepi64_si128(x1, x0, 0x11);
+ x1 = _mm_xor_si128(x1, x4);
+ x1 = _mm_xor_si128(x1, x5);
+
+ /*
+ * Single fold blocks of 16, if any.
+ */
+ while (len >= 16)
+ {
+ x2 = _mm_loadu_si128((__m128i *)buf);
+
+ x5 = _mm_clmulepi64_si128(x1, x0, 0x00);
+ x1 = _mm_clmulepi64_si128(x1, x0, 0x11);
+ x1 = _mm_xor_si128(x1, x2);
+ x1 = _mm_xor_si128(x1, x5);
+
+ buf += 16;
+ len -= 16;
+ }
+
+ /*
+ * Fold 128-bits to 64-bits.
+ */
+ x2 = _mm_clmulepi64_si128(x1, x0, 0x10);
+ x3 = _mm_setr_epi32(~0, 0, ~0, 0);
+ x1 = _mm_srli_si128(x1, 8);
+ x1 = _mm_xor_si128(x1, x2);
+
+ x0 = _mm_loadl_epi64((__m128i*)k5k0);
+
+ x2 = _mm_srli_si128(x1, 4);
+ x1 = _mm_and_si128(x1, x3);
+ x1 = _mm_clmulepi64_si128(x1, x0, 0x00);
+ x1 = _mm_xor_si128(x1, x2);
+
+ /*
+ * Barret reduce to 32-bits.
+ */
+ x0 = _mm_load_si128((__m128i*)poly);
+
+ x2 = _mm_and_si128(x1, x3);
+ x2 = _mm_clmulepi64_si128(x2, x0, 0x10);
+ x2 = _mm_and_si128(x2, x3);
+ x2 = _mm_clmulepi64_si128(x2, x0, 0x00);
+ x1 = _mm_xor_si128(x1, x2);
+
+ /*
+ * Return the crc32.
+ */
+ return _mm_extract_epi32(x1, 1);
+}
+
+#elif defined(CRC32_ARMV8_CRC32)
+
+/* CRC32 checksums using ARMv8-a crypto instructions.
+ *
+ * TODO: implement a version using the PMULL instruction.
+ */
+
+#if defined(__clang__)
+/* CRC32 intrinsics are #ifdef'ed out of arm_acle.h unless we build with an
+ * armv8 target, which is incompatible with ThinLTO optimizations on Android.
+ * (Namely, mixing and matching different module-level targets makes ThinLTO
+ * warn, and Android defaults to armv7-a. This restriction does not apply to
+ * function-level `target`s, however.)
+ *
+ * Since we only need four crc intrinsics, and since clang's implementation of
+ * those are just wrappers around compiler builtins, it's simplest to #define
+ * those builtins directly. If this #define list grows too much (or we depend on
+ * an intrinsic that isn't a trivial wrapper), we may have to find a better way
+ * to go about this.
+ *
+ * NOTE: clang currently complains that "'+soft-float-abi' is not a recognized
+ * feature for this target (ignoring feature)." This appears to be a harmless
+ * bug in clang.
+ */
+#define __crc32b __builtin_arm_crc32b
+#define __crc32d __builtin_arm_crc32d
+#define __crc32w __builtin_arm_crc32w
+#define __crc32cw __builtin_arm_crc32cw
+
+#if defined(__aarch64__)
+#define TARGET_ARMV8_WITH_CRC __attribute__((target("crc")))
+#else // !defined(__aarch64__)
+#define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc")))
+#endif // defined(__aarch64__)
+
+#elif defined(__GNUC__)
+/* For GCC, we are setting CRC extensions at module level, so ThinLTO is not
+ * allowed. We can just include arm_acle.h.
+ */
+#include <arm_acle.h>
+#define TARGET_ARMV8_WITH_CRC
+#else // !defined(__GNUC__) && !defined(_aarch64__)
+#error ARM CRC32 SIMD extensions only supported for Clang and GCC
+#endif
+
+TARGET_ARMV8_WITH_CRC
+uint32_t ZLIB_INTERNAL armv8_crc32_little(unsigned long crc,
+ const unsigned char *buf,
+ z_size_t len)
+{
+ uint32_t c = (uint32_t) ~crc;
+
+ while (len && ((uintptr_t)buf & 7)) {
+ c = __crc32b(c, *buf++);
+ --len;
+ }
+
+ const uint64_t *buf8 = (const uint64_t *)buf;
+
+ while (len >= 64) {
+ c = __crc32d(c, *buf8++);
+ c = __crc32d(c, *buf8++);
+ c = __crc32d(c, *buf8++);
+ c = __crc32d(c, *buf8++);
+
+ c = __crc32d(c, *buf8++);
+ c = __crc32d(c, *buf8++);
+ c = __crc32d(c, *buf8++);
+ c = __crc32d(c, *buf8++);
+ len -= 64;
+ }
+
+ while (len >= 8) {
+ c = __crc32d(c, *buf8++);
+ len -= 8;
+ }
+
+ buf = (const unsigned char *)buf8;
+
+ while (len--) {
+ c = __crc32b(c, *buf++);
+ }
+
+ return ~c;
+}
+
+#endif \ No newline at end of file
diff --git a/libmariadb/external/zlib/crc32_simd.h b/libmariadb/external/zlib/crc32_simd.h
new file mode 100644
index 00000000..c8b35015
--- /dev/null
+++ b/libmariadb/external/zlib/crc32_simd.h
@@ -0,0 +1,69 @@
+//https://cs.chromium.org/chromium/src/third_party/zlib/crc32_simd.c
+/* crc32_simd.h
+ *
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the Chromium source repository LICENSE file.
+ */
+#ifndef CRC32_SIMD_H
+#define CRC32_SIMD_H
+
+
+#include <stdint.h>
+
+//#include "zconf.h"
+//#include "zutil.h"
+#include "deflate.h"
+
+//#ifndef local
+// #define local static
+//#endif
+
+//#ifndef z_crc_t
+// #ifdef Z_U4
+// typedef Z_U4 z_crc_t;
+// #else
+// typedef unsigned long z_crc_t;
+// #endif
+//#endif
+#ifdef HAS_PCLMUL
+ #define CRC32_SIMD_SSE42_PCLMUL
+#endif
+
+#ifndef z_size_t
+ #define z_size_t size_t
+#endif
+#ifndef zalign
+ #ifdef _MSC_VER
+ #define zalign(x) __declspec(align(x))
+ #else
+ #define zalign(x) __attribute__((aligned((x))))
+ #endif
+#endif
+
+
+
+/*
+ * crc32_sse42_simd_(): compute the crc32 of the buffer, where the buffer
+ * length must be at least 64, and a multiple of 16.
+ */
+uint32_t ZLIB_INTERNAL crc32_sse42_simd_(
+ const unsigned char *buf,
+ z_size_t len,
+ uint32_t crc);
+
+/*
+ * crc32_sse42_simd_ buffer size constraints: see the use in zlib/crc32.c
+ * for computing the crc32 of an arbitrary length buffer.
+ */
+#define Z_CRC32_SSE42_MINIMUM_LENGTH 64
+#define Z_CRC32_SSE42_CHUNKSIZE_MASK 15
+
+/*
+ * CRC32 checksums using ARMv8-a crypto instructions.
+ */
+uint32_t ZLIB_INTERNAL armv8_crc32_little(unsigned long crc,
+ const unsigned char* buf,
+ z_size_t len);
+
+#endif /* CRC32_SIMD_H */ \ No newline at end of file
diff --git a/libmariadb/external/zlib/deflate.c b/libmariadb/external/zlib/deflate.c
new file mode 100644
index 00000000..4a689db3
--- /dev/null
+++ b/libmariadb/external/zlib/deflate.c
@@ -0,0 +1,2217 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://tools.ietf.org/html/rfc1951
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local int deflateStateCheck OF((z_streamp strm));
+local void slide_hash OF((deflate_state *s));
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow OF((deflate_state *s, int flush));
+#endif
+local block_state deflate_rle OF((deflate_state *s, int flush));
+local block_state deflate_huff OF((deflate_state *s, int flush));
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+
+#ifdef ZLIB_DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
+#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to UPDATE_HASH are made with consecutive input
+ * characters, so that a running hash key can be computed from the previous
+ * key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to INSERT_STRING are made with consecutive input
+ * characters and the first MIN_MATCH bytes of str are valid (except for
+ * the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ do { \
+ s->head[s->hash_size - 1] = NIL; \
+ zmemzero((Bytef *)s->head, \
+ (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \
+ } while (0)
+
+/* ===========================================================================
+ * Slide the hash table when sliding the window down (could be avoided with 32
+ * bit values at the expense of memory usage). We slide even when level == 0 to
+ * keep the hash table consistent if we switch back to level > 0 later.
+ */
+local void slide_hash(s)
+ deflate_state *s;
+{
+ unsigned n, m;
+ Posf *p;
+ uInt wsize = s->w_size;
+
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m - wsize : NIL);
+ } while (--n);
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m - wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+ s->status = INIT_STATE; /* to pass state test in deflateReset() */
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = (uInt)windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = (uInt)memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->high_water = 0; /* nothing written to s->window yet */
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ /* We overlay pending_buf and sym_buf. This works since the average size
+ * for length/distance pairs over any compressed block is assured to be 31
+ * bits or less.
+ *
+ * Analysis: The longest fixed codes are a length code of 8 bits plus 5
+ * extra bits, for lengths 131 to 257. The longest fixed distance codes are
+ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
+ * possible fixed-codes length/distance pair is then 31 bits total.
+ *
+ * sym_buf starts one-fourth of the way into pending_buf. So there are
+ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
+ * in sym_buf is three bytes -- two for the distance and one for the
+ * literal/length. As each symbol is consumed, the pointer to the next
+ * sym_buf value to read moves forward three bytes. From that symbol, up to
+ * 31 bits are written to pending_buf. The closest the written pending_buf
+ * bits gets to the next sym_buf symbol to read is just before the last
+ * code is written. At that time, 31*(n - 2) bits have been written, just
+ * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at
+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1
+ * symbols are written.) The closest the writing gets to what is unread is
+ * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and
+ * can range from 128 to 32768.
+ *
+ * Therefore, at a minimum, there are 142 bits of space between what is
+ * written and what is read in the overlain buffers, so the symbols cannot
+ * be overwritten by the compressed data. That space is actually 139 bits,
+ * due to the three-bit fixed-code block header.
+ *
+ * That covers the case where either Z_FIXED is specified, forcing fixed
+ * codes, or when the use of fixed codes is chosen, because that choice
+ * results in a smaller compressed block than dynamic codes. That latter
+ * condition then assures that the above analysis also covers all dynamic
+ * blocks. A dynamic-code block will only be chosen to be emitted if it has
+ * fewer bits than a fixed-code block would for the same set of symbols.
+ * Therefore its average symbol length is assured to be less than 31. So
+ * the compressed data for a dynamic block also cannot overwrite the
+ * symbols from which it is being constructed.
+ */
+
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
+ s->pending_buf_size = (ulg)s->lit_bufsize * 4;
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->sym_buf = s->pending_buf + s->lit_bufsize;
+ s->sym_end = (s->lit_bufsize - 1) * 3;
+ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* =========================================================================
+ * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
+ */
+local int deflateStateCheck(strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+ if (strm == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+ return 1;
+ s = strm->state;
+ if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&
+#ifdef GZIP
+ s->status != GZIP_STATE &&
+#endif
+ s->status != EXTRA_STATE &&
+ s->status != NAME_STATE &&
+ s->status != COMMENT_STATE &&
+ s->status != HCRC_STATE &&
+ s->status != BUSY_STATE &&
+ s->status != FINISH_STATE))
+ return 1;
+ return 0;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt str, n;
+ int wrap;
+ unsigned avail;
+ z_const unsigned char *next;
+
+ if (deflateStateCheck(strm) || dictionary == Z_NULL)
+ return Z_STREAM_ERROR;
+ s = strm->state;
+ wrap = s->wrap;
+ if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
+ return Z_STREAM_ERROR;
+
+ /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+ if (wrap == 1)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+ s->wrap = 0; /* avoid computing Adler-32 in read_buf */
+
+ /* if dictionary would fill window, just replace the history */
+ if (dictLength >= s->w_size) {
+ if (wrap == 0) { /* already empty otherwise */
+ CLEAR_HASH(s);
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ dictionary += dictLength - s->w_size; /* use the tail */
+ dictLength = s->w_size;
+ }
+
+ /* insert dictionary into window and hash */
+ avail = strm->avail_in;
+ next = strm->next_in;
+ strm->avail_in = dictLength;
+ strm->next_in = (z_const Bytef *)dictionary;
+ fill_window(s);
+ while (s->lookahead >= MIN_MATCH) {
+ str = s->strstart;
+ n = s->lookahead - (MIN_MATCH-1);
+ do {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ } while (--n);
+ s->strstart = str;
+ s->lookahead = MIN_MATCH-1;
+ fill_window(s);
+ }
+ s->strstart += s->lookahead;
+ s->block_start = (long)s->strstart;
+ s->insert = s->lookahead;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ strm->next_in = next;
+ strm->avail_in = avail;
+ s->wrap = wrap;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength)
+ z_streamp strm;
+ Bytef *dictionary;
+ uInt *dictLength;
+{
+ deflate_state *s;
+ uInt len;
+
+ if (deflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ s = strm->state;
+ len = s->strstart + s->lookahead;
+ if (len > s->w_size)
+ len = s->w_size;
+ if (dictionary != Z_NULL && len)
+ zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);
+ if (dictLength != Z_NULL)
+ *dictLength = len;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateResetKeep(strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (deflateStateCheck(strm)) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status =
+#ifdef GZIP
+ s->wrap == 2 ? GZIP_STATE :
+#endif
+ INIT_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = -2;
+
+ _tr_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset(strm)
+ z_streamp strm;
+{
+ int ret;
+
+ ret = deflateResetKeep(strm);
+ if (ret == Z_OK)
+ lm_init(strm->state);
+ return ret;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader(strm, head)
+ z_streamp strm;
+ gz_headerp head;
+{
+ if (deflateStateCheck(strm) || strm->state->wrap != 2)
+ return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePending(strm, pending, bits)
+ unsigned *pending;
+ int *bits;
+ z_streamp strm;
+{
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ if (pending != Z_NULL)
+ *pending = strm->state->pending;
+ if (bits != Z_NULL)
+ *bits = strm->state->bi_valid;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime(strm, bits, value)
+ z_streamp strm;
+ int bits;
+ int value;
+{
+ deflate_state *s;
+ int put;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+ if (bits < 0 || bits > 16 ||
+ s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
+ return Z_BUF_ERROR;
+ do {
+ put = Buf_size - s->bi_valid;
+ if (put > bits)
+ put = bits;
+ s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
+ s->bi_valid += put;
+ _tr_flush_bits(s);
+ value >>= put;
+ bits -= put;
+ } while (bits);
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if ((strategy != s->strategy || func != configuration_table[level].func) &&
+ s->last_flush != -2) {
+ /* Flush the last buffer: */
+ int err = deflate(strm, Z_BLOCK);
+ if (err == Z_STREAM_ERROR)
+ return err;
+ if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
+ return Z_BUF_ERROR;
+ }
+ if (s->level != level) {
+ if (s->level == 0 && s->matches != 0) {
+ if (s->matches == 1)
+ slide_hash(s);
+ else
+ CLEAR_HASH(s);
+ s->matches = 0;
+ }
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+ z_streamp strm;
+ int good_length;
+ int max_lazy;
+ int nice_length;
+ int max_chain;
+{
+ deflate_state *s;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = (uInt)good_length;
+ s->max_lazy_match = (uInt)max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = (uInt)max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns a
+ * close to exact, as well as small, upper bound on the compressed size. This
+ * is an expansion of ~0.03%, plus a small constant.
+ *
+ * For any setting other than those defaults for windowBits and memLevel, one
+ * of two worst case bounds is returned. This is at most an expansion of ~4% or
+ * ~13%, plus a small constant.
+ *
+ * Both the 0.03% and 4% derive from the overhead of stored blocks. The first
+ * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second
+ * is for stored blocks of 127 bytes (the worst case memLevel == 1). The
+ * expansion results from five bytes of header for each stored block.
+ *
+ * The larger expansion of 13% results from a window size less than or equal to
+ * the symbols buffer size (windowBits <= memLevel + 7). In that case some of
+ * the data being compressed may have slid out of the sliding window, impeding
+ * a stored block from being emitted. Then the only choice is a fixed or
+ * dynamic block, where a fixed block limits the maximum expansion to 9 bits
+ * per 8-bit byte, plus 10 bits for every block. The smallest block size for
+ * which this can occur is 255 (memLevel == 2).
+ *
+ * Shifts are used to approximate divisions, for speed.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+ z_streamp strm;
+ uLong sourceLen;
+{
+ deflate_state *s;
+ uLong fixedlen, storelen, wraplen;
+
+ /* upper bound for fixed blocks with 9-bit literals and length 255
+ (memLevel == 2, which is the lowest that may not use stored blocks) --
+ ~13% overhead plus a small constant */
+ fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
+ (sourceLen >> 9) + 4;
+
+ /* upper bound for stored blocks with length 127 (memLevel == 1) --
+ ~4% overhead plus a small constant */
+ storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
+ (sourceLen >> 11) + 7;
+
+ /* if can't get parameters, return larger bound plus a zlib wrapper */
+ if (deflateStateCheck(strm))
+ return (fixedlen > storelen ? fixedlen : storelen) + 6;
+
+ /* compute wrapper length */
+ s = strm->state;
+ switch (s->wrap) {
+ case 0: /* raw deflate */
+ wraplen = 0;
+ break;
+ case 1: /* zlib wrapper */
+ wraplen = 6 + (s->strstart ? 4 : 0);
+ break;
+#ifdef GZIP
+ case 2: /* gzip wrapper */
+ wraplen = 18;
+ if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
+ Bytef *str;
+ if (s->gzhead->extra != Z_NULL)
+ wraplen += 2 + s->gzhead->extra_len;
+ str = s->gzhead->name;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ str = s->gzhead->comment;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ if (s->gzhead->hcrc)
+ wraplen += 2;
+ }
+ break;
+#endif
+ default: /* for compiler happiness */
+ wraplen = 6;
+ }
+
+ /* if not default parameters, return one of the conservative bounds */
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen;
+
+ /* default settings: return tight bound for that case -- ~0.03% overhead
+ plus a small constant */
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB(s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output, except for
+ * some deflate_stored() output, goes through this function so some
+ * applications may wish to modify it to avoid allocating a large
+ * strm->next_out buffer and copying into it. (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len;
+ deflate_state *s = strm->state;
+
+ _tr_flush_bits(s);
+ len = s->pending;
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, s->pending_out, len);
+ strm->next_out += len;
+ s->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ s->pending -= len;
+ if (s->pending == 0) {
+ s->pending_out = s->pending_buf;
+ }
+}
+
+/* ===========================================================================
+ * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].
+ */
+#define HCRC_UPDATE(beg) \
+ do { \
+ if (s->gzhead->hcrc && s->pending > (beg)) \
+ strm->adler = crc32(strm->adler, s->pending_buf + (beg), \
+ s->pending - (beg)); \
+ } while (0)
+
+/* ========================================================================= */
+int ZEXPORT deflate(strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->avail_in != 0 && strm->next_in == Z_NULL) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Write the header */
+ if (s->status == INIT_STATE && s->wrap == 0)
+ s->status = BUSY_STATE;
+ if (s->status == INIT_STATE) {
+ /* zlib header */
+ uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#ifdef GZIP
+ if (s->status == GZIP_STATE) {
+ /* gzip header */
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == Z_NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != Z_NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;
+ while (s->pending + left > s->pending_buf_size) {
+ uInt copy = s->pending_buf_size - s->pending;
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, copy);
+ s->pending = s->pending_buf_size;
+ HCRC_UPDATE(beg);
+ s->gzindex += copy;
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ left -= copy;
+ }
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, left);
+ s->pending += left;
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ }
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size) {
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ }
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#endif
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = s->level == 0 ? deflate_stored(s, flush) :
+ s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+ s->strategy == Z_RLE ? deflate_rle(s, flush) :
+ (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ if (s->lookahead == 0) {
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd(strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy(dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+
+
+ if (deflateStateCheck(source) || dest == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local unsigned read_buf(strm, buf, size)
+ z_streamp strm;
+ Bytef *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ zmemcpy(buf, strm->next_in, len);
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, buf, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, buf, len);
+ }
+#endif
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init(s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->insert = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = (int)s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan + best_len - 1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len - 1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match + best_len - 1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart + 3, + 5, up to strstart + 257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window + strstart + 257 */
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend - scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len - 1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len - 1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart + 258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan + best_len - 1);
+#else
+ scan_end1 = scan[best_len - 1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len - 1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart + 258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef ZLIB_DEBUG
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start - match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* ZLIB_DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ unsigned n;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize + MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ slide_hash(s);
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) break;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead + s->insert >= MIN_MATCH) {
+ uInt str = s->strstart - s->insert;
+ s->ins_h = s->window[str];
+ UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ while (s->insert) {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ s->insert--;
+ if (s->lookahead + s->insert < MIN_MATCH)
+ break;
+ }
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+ /* If the WIN_INIT bytes after the end of the current data have never been
+ * written, then zero those bytes in order to avoid memory check reports of
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by
+ * the longest match routines. Update the high water mark for the next
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+ */
+ if (s->high_water < s->window_size) {
+ ulg curr = s->strstart + (ulg)(s->lookahead);
+ ulg init;
+
+ if (s->high_water < curr) {
+ /* Previous high water mark below current data -- zero WIN_INIT
+ * bytes or up to end of window, whichever is less.
+ */
+ init = s->window_size - curr;
+ if (init > WIN_INIT)
+ init = WIN_INIT;
+ zmemzero(s->window + curr, (unsigned)init);
+ s->high_water = curr + init;
+ }
+ else if (s->high_water < (ulg)curr + WIN_INIT) {
+ /* High water mark at or above current data, but below current data
+ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+ * to end of window, whichever is less.
+ */
+ init = (ulg)curr + WIN_INIT - s->high_water;
+ if (init > s->window_size - s->high_water)
+ init = s->window_size - s->high_water;
+ zmemzero(s->window + s->high_water, (unsigned)init);
+ s->high_water += init;
+ }
+ }
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "not enough room for search");
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (last)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+ FLUSH_BLOCK_ONLY(s, last); \
+ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* Maximum stored block length in deflate format (not including header). */
+#define MAX_STORED 65535
+
+/* Minimum of a and b. */
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ *
+ * In case deflateParams() is used to later switch to a non-zero compression
+ * level, s->matches (otherwise unused when storing) keeps track of the number
+ * of hash table slides to perform. If s->matches is 1, then one hash table
+ * slide will be done when switching. If s->matches is 2, the maximum value
+ * allowed here, then the hash table will be cleared, since two or more slides
+ * is the same as a clear.
+ *
+ * deflate_stored() is written to minimize the number of times an input byte is
+ * copied. It is most efficient with large input and output buffers, which
+ * maximizes the opportunities to have a single copy from next_in to next_out.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ /* Smallest worthy block size when not flushing or finishing. By default
+ * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
+ * large input and output buffers, the stored block size will be larger.
+ */
+ unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);
+
+ /* Copy as many min_block or larger stored blocks directly to next_out as
+ * possible. If flushing, copy the remaining available input to next_out as
+ * stored blocks, if there is enough space.
+ */
+ unsigned len, left, have, last = 0;
+ unsigned used = s->strm->avail_in;
+ do {
+ /* Set len to the maximum size block that we can copy directly with the
+ * available input data and output space. Set left to how much of that
+ * would be copied from what's left in the window.
+ */
+ len = MAX_STORED; /* maximum deflate stored block length */
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */
+ if (s->strm->avail_out < have) /* need room for header */
+ break;
+ /* maximum stored block length that will fit in avail_out: */
+ have = s->strm->avail_out - have;
+ left = s->strstart - s->block_start; /* bytes left in window */
+ if (len > (ulg)left + s->strm->avail_in)
+ len = left + s->strm->avail_in; /* limit len to the input */
+ if (len > have)
+ len = have; /* limit len to the output */
+
+ /* If the stored block would be less than min_block in length, or if
+ * unable to copy all of the available input when flushing, then try
+ * copying to the window and the pending buffer instead. Also don't
+ * write an empty block when flushing -- deflate() does that.
+ */
+ if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
+ flush == Z_NO_FLUSH ||
+ len != left + s->strm->avail_in))
+ break;
+
+ /* Make a dummy stored block in pending to get the header bytes,
+ * including any pending bits. This also updates the debugging counts.
+ */
+ last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;
+ _tr_stored_block(s, (char *)0, 0L, last);
+
+ /* Replace the lengths in the dummy stored block with len. */
+ s->pending_buf[s->pending - 4] = len;
+ s->pending_buf[s->pending - 3] = len >> 8;
+ s->pending_buf[s->pending - 2] = ~len;
+ s->pending_buf[s->pending - 1] = ~len >> 8;
+
+ /* Write the stored block header bytes. */
+ flush_pending(s->strm);
+
+#ifdef ZLIB_DEBUG
+ /* Update debugging counts for the data about to be copied. */
+ s->compressed_len += len << 3;
+ s->bits_sent += len << 3;
+#endif
+
+ /* Copy uncompressed bytes from the window to next_out. */
+ if (left) {
+ if (left > len)
+ left = len;
+ zmemcpy(s->strm->next_out, s->window + s->block_start, left);
+ s->strm->next_out += left;
+ s->strm->avail_out -= left;
+ s->strm->total_out += left;
+ s->block_start += left;
+ len -= left;
+ }
+
+ /* Copy uncompressed bytes directly from next_in to next_out, updating
+ * the check value.
+ */
+ if (len) {
+ read_buf(s->strm, s->strm->next_out, len);
+ s->strm->next_out += len;
+ s->strm->avail_out -= len;
+ s->strm->total_out += len;
+ }
+ } while (last == 0);
+
+ /* Update the sliding window with the last s->w_size bytes of the copied
+ * data, or append all of the copied data to the existing window if less
+ * than s->w_size bytes were copied. Also update the number of bytes to
+ * insert in the hash tables, in the event that deflateParams() switches to
+ * a non-zero compression level.
+ */
+ used -= s->strm->avail_in; /* number of input bytes directly copied */
+ if (used) {
+ /* If any input was used, then no unused input remains in the window,
+ * therefore s->block_start == s->strstart.
+ */
+ if (used >= s->w_size) { /* supplant the previous history */
+ s->matches = 2; /* clear hash */
+ zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
+ s->strstart = s->w_size;
+ s->insert = s->strstart;
+ }
+ else {
+ if (s->window_size - s->strstart <= used) {
+ /* Slide the window down. */
+ s->strstart -= s->w_size;
+ zmemcpy(s->window, s->window + s->w_size, s->strstart);
+ if (s->matches < 2)
+ s->matches++; /* add a pending slide_hash() */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ }
+ zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
+ s->strstart += used;
+ s->insert += MIN(used, s->w_size - s->insert);
+ }
+ s->block_start = s->strstart;
+ }
+ if (s->high_water < s->strstart)
+ s->high_water = s->strstart;
+
+ /* If the last block was written to next_out, then done. */
+ if (last)
+ return finish_done;
+
+ /* If flushing and all input has been consumed, then done. */
+ if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
+ s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
+ return block_done;
+
+ /* Fill the window with any remaining input. */
+ have = s->window_size - s->strstart;
+ if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
+ /* Slide the window down. */
+ s->block_start -= s->w_size;
+ s->strstart -= s->w_size;
+ zmemcpy(s->window, s->window + s->w_size, s->strstart);
+ if (s->matches < 2)
+ s->matches++; /* add a pending slide_hash() */
+ have += s->w_size; /* more space now */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ }
+ if (have > s->strm->avail_in)
+ have = s->strm->avail_in;
+ if (have) {
+ read_buf(s->strm, s->window + s->strstart, have);
+ s->strstart += have;
+ s->insert += MIN(have, s->w_size - s->insert);
+ }
+ if (s->high_water < s->strstart)
+ s->high_water = s->strstart;
+
+ /* There was not enough avail_out to write a complete worthy or flushed
+ * stored block to next_out. Write a stored block to pending instead, if we
+ * have enough input for a worthy block, or if flushing and there is enough
+ * room for the remaining input as a stored block in the pending buffer.
+ */
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */
+ /* maximum stored block length that will fit in pending: */
+ have = MIN(s->pending_buf_size - have, MAX_STORED);
+ min_block = MIN(have, s->w_size);
+ left = s->strstart - s->block_start;
+ if (left >= min_block ||
+ ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&
+ s->strm->avail_in == 0 && left <= have)) {
+ len = MIN(left, have);
+ last = flush == Z_FINISH && s->strm->avail_in == 0 &&
+ len == left ? 1 : 0;
+ _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);
+ s->block_start += len;
+ flush_pending(s->strm);
+ }
+
+ /* We've done all we can with the available input and output. */
+ return last ? finish_started : need_more;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart + 2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart + 2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart - 1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart - 1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart - 1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length - 1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
+ s->match_available = 0;
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan, *strend; /* scan goes up to strend for length of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest run, plus one for the unrolled loop.
+ */
+ if (s->lookahead <= MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ s->match_length = 0;
+ if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+ scan = s->window + s->strstart - 1;
+ prev = *scan;
+ if (prev == *++scan && prev == *++scan && prev == *++scan) {
+ strend = s->window + s->strstart + MAX_MATCH;
+ do {
+ } while (prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ scan < strend);
+ s->match_length = MAX_MATCH - (uInt)(strend - scan);
+ if (s->match_length > s->lookahead)
+ s->match_length = s->lookahead;
+ }
+ Assert(scan <= s->window + (uInt)(s->window_size - 1),
+ "wild scan");
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+ _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we have a literal to write. */
+ if (s->lookahead == 0) {
+ fill_window(s);
+ if (s->lookahead == 0) {
+ if (flush == Z_NO_FLUSH)
+ return need_more;
+ break; /* flush the current block */
+ }
+ }
+
+ /* Output a literal byte */
+ s->match_length = 0;
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
diff --git a/libmariadb/external/zlib/deflate.h b/libmariadb/external/zlib/deflate.h
new file mode 100644
index 00000000..1a06cd5f
--- /dev/null
+++ b/libmariadb/external/zlib/deflate.h
@@ -0,0 +1,346 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2018 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define Buf_size 16
+/* size of bit buffer in bi_buf */
+
+#define INIT_STATE 42 /* zlib header -> BUSY_STATE */
+#ifdef GZIP
+# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */
+#endif
+#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */
+#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */
+#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */
+#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */
+#define BUSY_STATE 113 /* deflate -> FINISH_STATE */
+#define FINISH_STATE 666 /* stream complete */
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ const static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ ulg pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ ulg gzindex; /* where in extra, name, or comment */
+ Byte method; /* can only be DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to suppress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *sym_buf; /* buffer for distances and literals/lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt sym_next; /* running index in sym_buf */
+ uInt sym_end; /* symbol table full when sym_next reaches this */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ uInt insert; /* bytes at end of window left to insert */
+
+#ifdef ZLIB_DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+ ulg high_water;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+ memory checker errors from longest match routines */
+
+ /* in trees.c */
+void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
+int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
+ ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+ ulg stored_len, int last));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef ZLIB_DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch ZLIB_INTERNAL _length_code[];
+ extern uch ZLIB_INTERNAL _dist_code[];
+#else
+ extern const uch ZLIB_INTERNAL _length_code[];
+ extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (uch)(length); \
+ ush dist = (ush)(distance); \
+ s->sym_buf[s->sym_next++] = (uch)dist; \
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
+ s->sym_buf[s->sym_next++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/libmariadb/external/zlib/doc/algorithm.txt b/libmariadb/external/zlib/doc/algorithm.txt
new file mode 100644
index 00000000..c97f4950
--- /dev/null
+++ b/libmariadb/external/zlib/doc/algorithm.txt
@@ -0,0 +1,209 @@
+1. Compression algorithm (deflate)
+
+The deflation algorithm used by gzip (also zip and zlib) is a variation of
+LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
+the input data. The second occurrence of a string is replaced by a
+pointer to the previous string, in the form of a pair (distance,
+length). Distances are limited to 32K bytes, and lengths are limited
+to 258 bytes. When a string does not occur anywhere in the previous
+32K bytes, it is emitted as a sequence of literal bytes. (In this
+description, `string' must be taken as an arbitrary sequence of bytes,
+and is not restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when deflate() determines that
+it would be useful to start another block with fresh trees. (This is
+somewhat similar to the behavior of LZW-based _compress_.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (level
+parameter of deflateInit). So deflate() does not always find the longest
+possible match but generally finds a match which is long enough.
+
+deflate() also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, deflate() searches for
+a longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the process of lazy evaluation begins again. Otherwise,
+the original match is kept, and the next match search is attempted only N
+steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, deflate() reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, deflate() attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (level parameter 1 to 3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+
+2. Decompression algorithm (inflate)
+
+2.1 Introduction
+
+The key question is how to represent a Huffman code (or any prefix code) so
+that you can decode fast. The most important characteristic is that shorter
+codes are much more common than longer codes, so pay attention to decoding the
+short codes fast, and let the long codes take longer to decode.
+
+inflate() sets up a first level table that covers some number of bits of
+input less than the length of longest code. It gets that many bits from the
+stream, and looks it up in the table. The table will tell if the next
+code is that many bits or less and how many, and if it is, it will tell
+the value, else it will point to the next level table for which inflate()
+grabs more bits and tries to decode a longer code.
+
+How many bits to make the first lookup is a tradeoff between the time it
+takes to decode and the time it takes to build the table. If building the
+table took no time (and if you had infinite memory), then there would only
+be a first level table to cover all the way to the longest code. However,
+building the table ends up taking a lot longer for more bits since short
+codes are replicated many times in such a table. What inflate() does is
+simply to make the number of bits in the first table a variable, and then
+to set that variable for the maximum speed.
+
+For inflate, which has 286 possible codes for the literal/length tree, the size
+of the first table is nine bits. Also the distance trees have 30 possible
+values, and the size of the first table is six bits. Note that for each of
+those cases, the table ended up one bit longer than the ``average'' code
+length, i.e. the code length of an approximately flat code which would be a
+little more than eight bits for 286 symbols and a little less than five bits
+for 30 symbols.
+
+
+2.2 More details on the inflate table lookup
+
+Ok, you want to know what this cleverly obfuscated inflate tree actually
+looks like. You are correct that it's not a Huffman tree. It is simply a
+lookup table for the first, let's say, nine bits of a Huffman symbol. The
+symbol could be as short as one bit or as long as 15 bits. If a particular
+symbol is shorter than nine bits, then that symbol's translation is duplicated
+in all those entries that start with that symbol's bits. For example, if the
+symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
+symbol is nine bits long, it appears in the table once.
+
+If the symbol is longer than nine bits, then that entry in the table points
+to another similar table for the remaining bits. Again, there are duplicated
+entries as needed. The idea is that most of the time the symbol will be short
+and there will only be one table look up. (That's whole idea behind data
+compression in the first place.) For the less frequent long symbols, there
+will be two lookups. If you had a compression method with really long
+symbols, you could have as many levels of lookups as is efficient. For
+inflate, two is enough.
+
+So a table entry either points to another table (in which case nine bits in
+the above example are gobbled), or it contains the translation for the symbol
+and the number of bits to gobble. Then you start again with the next
+ungobbled bit.
+
+You may wonder: why not just have one lookup table for how ever many bits the
+longest symbol is? The reason is that if you do that, you end up spending
+more time filling in duplicate symbol entries than you do actually decoding.
+At least for deflate's output that generates new trees every several 10's of
+kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
+would take too long if you're only decoding several thousand symbols. At the
+other extreme, you could make a new table for every bit in the code. In fact,
+that's essentially a Huffman tree. But then you spend too much time
+traversing the tree while decoding, even for short symbols.
+
+So the number of bits for the first lookup table is a trade of the time to
+fill out the table vs. the time spent looking at the second level and above of
+the table.
+
+Here is an example, scaled down:
+
+The code being decoded, with 10 symbols, from 1 to 6 bits long:
+
+A: 0
+B: 10
+C: 1100
+D: 11010
+E: 11011
+F: 11100
+G: 11101
+H: 11110
+I: 111110
+J: 111111
+
+Let's make the first table three bits long (eight entries):
+
+000: A,1
+001: A,1
+010: A,1
+011: A,1
+100: B,2
+101: B,2
+110: -> table X (gobble 3 bits)
+111: -> table Y (gobble 3 bits)
+
+Each entry is what the bits decode as and how many bits that is, i.e. how
+many bits to gobble. Or the entry points to another table, with the number of
+bits to gobble implicit in the size of the table.
+
+Table X is two bits long since the longest code starting with 110 is five bits
+long:
+
+00: C,1
+01: C,1
+10: D,2
+11: E,2
+
+Table Y is three bits long since the longest code starting with 111 is six
+bits long:
+
+000: F,2
+001: F,2
+010: G,2
+011: G,2
+100: H,2
+101: H,2
+110: I,3
+111: J,3
+
+So what we have here are three tables with a total of 20 entries that had to
+be constructed. That's compared to 64 entries for a single table. Or
+compared to 16 entries for a Huffman tree (six two entry tables and one four
+entry table). Assuming that the code ideally represents the probability of
+the symbols, it takes on the average 1.25 lookups per symbol. That's compared
+to one lookup for the single table, or 1.66 lookups per symbol for the
+Huffman tree.
+
+There, I think that gives you a picture of what's going on. For inflate, the
+meaning of a particular symbol is often more than just a letter. It can be a
+byte (a "literal"), or it can be either a length or a distance which
+indicates a base value and a number of bits to fetch after the code that is
+added to the base value. Or it might be the special end-of-block code. The
+data structures created in inftrees.c try to encode all that information
+compactly in the tables.
+
+
+Jean-loup Gailly Mark Adler
+jloup@gzip.org madler@alumni.caltech.edu
+
+
+References:
+
+[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
+Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
+pp. 337-343.
+
+``DEFLATE Compressed Data Format Specification'' available in
+http://tools.ietf.org/html/rfc1951
diff --git a/libmariadb/external/zlib/doc/rfc1950.txt b/libmariadb/external/zlib/doc/rfc1950.txt
new file mode 100644
index 00000000..ce6428a0
--- /dev/null
+++ b/libmariadb/external/zlib/doc/rfc1950.txt
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group P. Deutsch
+Request for Comments: 1950 Aladdin Enterprises
+Category: Informational J-L. Gailly
+ Info-ZIP
+ May 1996
+
+
+ ZLIB Compressed Data Format Specification version 3.3
+
+Status of This Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+IESG Note:
+
+ The IESG takes no position on the validity of any Intellectual
+ Property Rights statements contained in this document.
+
+Notices
+
+ Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly
+
+ Permission is granted to copy and distribute this document for any
+ purpose and without charge, including translations into other
+ languages and incorporation into compilations, provided that the
+ copyright notice and this notice are preserved, and that any
+ substantive changes or deletions from the original are clearly
+ marked.
+
+ A pointer to the latest version of this and related documentation in
+ HTML format can be found at the URL
+ <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
+
+Abstract
+
+ This specification defines a lossless compressed data format. The
+ data can be produced or consumed, even for an arbitrarily long
+ sequentially presented input data stream, using only an a priori
+ bounded amount of intermediate storage. The format presently uses
+ the DEFLATE compression method but can be easily extended to use
+ other compression methods. It can be implemented readily in a manner
+ not covered by patents. This specification also defines the ADLER-32
+ checksum (an extension and improvement of the Fletcher checksum),
+ used for detection of data corruption, and provides an algorithm for
+ computing it.
+
+
+
+
+Deutsch & Gailly Informational [Page 1]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+Table of Contents
+
+ 1. Introduction ................................................... 2
+ 1.1. Purpose ................................................... 2
+ 1.2. Intended audience ......................................... 3
+ 1.3. Scope ..................................................... 3
+ 1.4. Compliance ................................................ 3
+ 1.5. Definitions of terms and conventions used ................ 3
+ 1.6. Changes from previous versions ............................ 3
+ 2. Detailed specification ......................................... 3
+ 2.1. Overall conventions ....................................... 3
+ 2.2. Data format ............................................... 4
+ 2.3. Compliance ................................................ 7
+ 3. References ..................................................... 7
+ 4. Source code .................................................... 8
+ 5. Security Considerations ........................................ 8
+ 6. Acknowledgements ............................................... 8
+ 7. Authors' Addresses ............................................. 8
+ 8. Appendix: Rationale ............................................ 9
+ 9. Appendix: Sample code ..........................................10
+
+1. Introduction
+
+ 1.1. Purpose
+
+ The purpose of this specification is to define a lossless
+ compressed data format that:
+
+ * Is independent of CPU type, operating system, file system,
+ and character set, and hence can be used for interchange;
+
+ * Can be produced or consumed, even for an arbitrarily long
+ sequentially presented input data stream, using only an a
+ priori bounded amount of intermediate storage, and hence can
+ be used in data communications or similar structures such as
+ Unix filters;
+
+ * Can use a number of different compression methods;
+
+ * Can be implemented readily in a manner not covered by
+ patents, and hence can be practiced freely.
+
+ The data format defined by this specification does not attempt to
+ allow random access to compressed data.
+
+
+
+
+
+
+
+Deutsch & Gailly Informational [Page 2]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+ 1.2. Intended audience
+
+ This specification is intended for use by implementors of software
+ to compress data into zlib format and/or decompress data from zlib
+ format.
+
+ The text of the specification assumes a basic background in
+ programming at the level of bits and other primitive data
+ representations.
+
+ 1.3. Scope
+
+ The specification specifies a compressed data format that can be
+ used for in-memory compression of a sequence of arbitrary bytes.
+
+ 1.4. Compliance
+
+ Unless otherwise indicated below, a compliant decompressor must be
+ able to accept and decompress any data set that conforms to all
+ the specifications presented here; a compliant compressor must
+ produce data sets that conform to all the specifications presented
+ here.
+
+ 1.5. Definitions of terms and conventions used
+
+ byte: 8 bits stored or transmitted as a unit (same as an octet).
+ (For this specification, a byte is exactly 8 bits, even on
+ machines which store a character on a number of bits different
+ from 8.) See below, for the numbering of bits within a byte.
+
+ 1.6. Changes from previous versions
+
+ Version 3.1 was the first public release of this specification.
+ In version 3.2, some terminology was changed and the Adler-32
+ sample code was rewritten for clarity. In version 3.3, the
+ support for a preset dictionary was introduced, and the
+ specification was converted to RFC style.
+
+2. Detailed specification
+
+ 2.1. Overall conventions
+
+ In the diagrams below, a box like this:
+
+ +---+
+ | | <-- the vertical bars might be missing
+ +---+
+
+
+
+
+Deutsch & Gailly Informational [Page 3]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+ represents one byte; a box like this:
+
+ +==============+
+ | |
+ +==============+
+
+ represents a variable number of bytes.
+
+ Bytes stored within a computer do not have a "bit order", since
+ they are always treated as a unit. However, a byte considered as
+ an integer between 0 and 255 does have a most- and least-
+ significant bit, and since we write numbers with the most-
+ significant digit on the left, we also write bytes with the most-
+ significant bit on the left. In the diagrams below, we number the
+ bits of a byte so that bit 0 is the least-significant bit, i.e.,
+ the bits are numbered:
+
+ +--------+
+ |76543210|
+ +--------+
+
+ Within a computer, a number may occupy multiple bytes. All
+ multi-byte numbers in the format described here are stored with
+ the MOST-significant byte first (at the lower memory address).
+ For example, the decimal number 520 is stored as:
+
+ 0 1
+ +--------+--------+
+ |00000010|00001000|
+ +--------+--------+
+ ^ ^
+ | |
+ | + less significant byte = 8
+ + more significant byte = 2 x 256
+
+ 2.2. Data format
+
+ A zlib stream has the following structure:
+
+ 0 1
+ +---+---+
+ |CMF|FLG| (more-->)
+ +---+---+
+
+
+
+
+
+
+
+
+Deutsch & Gailly Informational [Page 4]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+ (if FLG.FDICT set)
+
+ 0 1 2 3
+ +---+---+---+---+
+ | DICTID | (more-->)
+ +---+---+---+---+
+
+ +=====================+---+---+---+---+
+ |...compressed data...| ADLER32 |
+ +=====================+---+---+---+---+
+
+ Any data which may appear after ADLER32 are not part of the zlib
+ stream.
+
+ CMF (Compression Method and flags)
+ This byte is divided into a 4-bit compression method and a 4-
+ bit information field depending on the compression method.
+
+ bits 0 to 3 CM Compression method
+ bits 4 to 7 CINFO Compression info
+
+ CM (Compression method)
+ This identifies the compression method used in the file. CM = 8
+ denotes the "deflate" compression method with a window size up
+ to 32K. This is the method used by gzip and PNG (see
+ references [1] and [2] in Chapter 3, below, for the reference
+ documents). CM = 15 is reserved. It might be used in a future
+ version of this specification to indicate the presence of an
+ extra field before the compressed data.
+
+ CINFO (Compression info)
+ For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
+ size, minus eight (CINFO=7 indicates a 32K window size). Values
+ of CINFO above 7 are not allowed in this version of the
+ specification. CINFO is not defined in this specification for
+ CM not equal to 8.
+
+ FLG (FLaGs)
+ This flag byte is divided as follows:
+
+ bits 0 to 4 FCHECK (check bits for CMF and FLG)
+ bit 5 FDICT (preset dictionary)
+ bits 6 to 7 FLEVEL (compression level)
+
+ The FCHECK value must be such that CMF and FLG, when viewed as
+ a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
+ is a multiple of 31.
+
+
+
+
+Deutsch & Gailly Informational [Page 5]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+ FDICT (Preset dictionary)
+ If FDICT is set, a DICT dictionary identifier is present
+ immediately after the FLG byte. The dictionary is a sequence of
+ bytes which are initially fed to the compressor without
+ producing any compressed output. DICT is the Adler-32 checksum
+ of this sequence of bytes (see the definition of ADLER32
+ below). The decompressor can use this identifier to determine
+ which dictionary has been used by the compressor.
+
+ FLEVEL (Compression level)
+ These flags are available for use by specific compression
+ methods. The "deflate" method (CM = 8) sets these flags as
+ follows:
+
+ 0 - compressor used fastest algorithm
+ 1 - compressor used fast algorithm
+ 2 - compressor used default algorithm
+ 3 - compressor used maximum compression, slowest algorithm
+
+ The information in FLEVEL is not needed for decompression; it
+ is there to indicate if recompression might be worthwhile.
+
+ compressed data
+ For compression method 8, the compressed data is stored in the
+ deflate compressed data format as described in the document
+ "DEFLATE Compressed Data Format Specification" by L. Peter
+ Deutsch. (See reference [3] in Chapter 3, below)
+
+ Other compressed data formats are not specified in this version
+ of the zlib specification.
+
+ ADLER32 (Adler-32 checksum)
+ This contains a checksum value of the uncompressed data
+ (excluding any dictionary data) computed according to Adler-32
+ algorithm. This algorithm is a 32-bit extension and improvement
+ of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
+ standard. See references [4] and [5] in Chapter 3, below)
+
+ Adler-32 is composed of two sums accumulated per byte: s1 is
+ the sum of all bytes, s2 is the sum of all s1 values. Both sums
+ are done modulo 65521. s1 is initialized to 1, s2 to zero. The
+ Adler-32 checksum is stored as s2*65536 + s1 in most-
+ significant-byte first (network) order.
+
+
+
+
+
+
+
+
+Deutsch & Gailly Informational [Page 6]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+ 2.3. Compliance
+
+ A compliant compressor must produce streams with correct CMF, FLG
+ and ADLER32, but need not support preset dictionaries. When the
+ zlib data format is used as part of another standard data format,
+ the compressor may use only preset dictionaries that are specified
+ by this other data format. If this other format does not use the
+ preset dictionary feature, the compressor must not set the FDICT
+ flag.
+
+ A compliant decompressor must check CMF, FLG, and ADLER32, and
+ provide an error indication if any of these have incorrect values.
+ A compliant decompressor must give an error indication if CM is
+ not one of the values defined in this specification (only the
+ value 8 is permitted in this version), since another value could
+ indicate the presence of new features that would cause subsequent
+ data to be interpreted incorrectly. A compliant decompressor must
+ give an error indication if FDICT is set and DICTID is not the
+ identifier of a known preset dictionary. A decompressor may
+ ignore FLEVEL and still be compliant. When the zlib data format
+ is being used as a part of another standard format, a compliant
+ decompressor must support all the preset dictionaries specified by
+ the other format. When the other format does not use the preset
+ dictionary feature, a compliant decompressor must reject any
+ stream in which the FDICT flag is set.
+
+3. References
+
+ [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification",
+ available in ftp://ftp.uu.net/pub/archiving/zip/doc/
+
+ [2] Thomas Boutell, "PNG (Portable Network Graphics) specification",
+ available in ftp://ftp.uu.net/graphics/png/documents/
+
+ [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
+ available in ftp://ftp.uu.net/pub/archiving/zip/doc/
+
+ [4] Fletcher, J. G., "An Arithmetic Checksum for Serial
+ Transmissions," IEEE Transactions on Communications, Vol. COM-30,
+ No. 1, January 1982, pp. 247-252.
+
+ [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms,"
+ November, 1993, pp. 144, 145. (Available from
+ gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073.
+
+
+
+
+
+
+
+Deutsch & Gailly Informational [Page 7]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+4. Source code
+
+ Source code for a C language implementation of a "zlib" compliant
+ library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/.
+
+5. Security Considerations
+
+ A decoder that fails to check the ADLER32 checksum value may be
+ subject to undetected data corruption.
+
+6. Acknowledgements
+
+ Trademarks cited in this document are the property of their
+ respective owners.
+
+ Jean-Loup Gailly and Mark Adler designed the zlib format and wrote
+ the related software described in this specification. Glenn
+ Randers-Pehrson converted this document to RFC and HTML format.
+
+7. Authors' Addresses
+
+ L. Peter Deutsch
+ Aladdin Enterprises
+ 203 Santa Margarita Ave.
+ Menlo Park, CA 94025
+
+ Phone: (415) 322-0103 (AM only)
+ FAX: (415) 322-1734
+ EMail: <ghost@aladdin.com>
+
+
+ Jean-Loup Gailly
+
+ EMail: <gzip@prep.ai.mit.edu>
+
+ Questions about the technical content of this specification can be
+ sent by email to
+
+ Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
+ Mark Adler <madler@alumni.caltech.edu>
+
+ Editorial comments on this specification can be sent by email to
+
+ L. Peter Deutsch <ghost@aladdin.com> and
+ Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
+
+
+
+
+
+
+Deutsch & Gailly Informational [Page 8]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+8. Appendix: Rationale
+
+ 8.1. Preset dictionaries
+
+ A preset dictionary is specially useful to compress short input
+ sequences. The compressor can take advantage of the dictionary
+ context to encode the input in a more compact manner. The
+ decompressor can be initialized with the appropriate context by
+ virtually decompressing a compressed version of the dictionary
+ without producing any output. However for certain compression
+ algorithms such as the deflate algorithm this operation can be
+ achieved without actually performing any decompression.
+
+ The compressor and the decompressor must use exactly the same
+ dictionary. The dictionary may be fixed or may be chosen among a
+ certain number of predefined dictionaries, according to the kind
+ of input data. The decompressor can determine which dictionary has
+ been chosen by the compressor by checking the dictionary
+ identifier. This document does not specify the contents of
+ predefined dictionaries, since the optimal dictionaries are
+ application specific. Standard data formats using this feature of
+ the zlib specification must precisely define the allowed
+ dictionaries.
+
+ 8.2. The Adler-32 algorithm
+
+ The Adler-32 algorithm is much faster than the CRC32 algorithm yet
+ still provides an extremely low probability of undetected errors.
+
+ The modulo on unsigned long accumulators can be delayed for 5552
+ bytes, so the modulo operation time is negligible. If the bytes
+ are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
+ and order sensitive, unlike the first sum, which is just a
+ checksum. That 65521 is prime is important to avoid a possible
+ large class of two-byte errors that leave the check unchanged.
+ (The Fletcher checksum uses 255, which is not prime and which also
+ makes the Fletcher check insensitive to single byte changes 0 <->
+ 255.)
+
+ The sum s1 is initialized to 1 instead of zero to make the length
+ of the sequence part of s2, so that the length does not have to be
+ checked separately. (Any sequence of zeroes has a Fletcher
+ checksum of zero.)
+
+
+
+
+
+
+
+
+Deutsch & Gailly Informational [Page 9]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+9. Appendix: Sample code
+
+ The following C code computes the Adler-32 checksum of a data buffer.
+ It is written for clarity, not for speed. The sample code is in the
+ ANSI C programming language. Non C users may find it easier to read
+ with these hints:
+
+ & Bitwise AND operator.
+ >> Bitwise right shift operator. When applied to an
+ unsigned quantity, as here, right shift inserts zero bit(s)
+ at the left.
+ << Bitwise left shift operator. Left shift inserts zero
+ bit(s) at the right.
+ ++ "n++" increments the variable n.
+ % modulo operator: a % b is the remainder of a divided by b.
+
+ #define BASE 65521 /* largest prime smaller than 65536 */
+
+ /*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1]
+ and return the updated checksum. The Adler-32 checksum should be
+ initialized to 1.
+
+ Usage example:
+
+ unsigned long adler = 1L;
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = update_adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+ */
+ unsigned long update_adler32(unsigned long adler,
+ unsigned char *buf, int len)
+ {
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int n;
+
+ for (n = 0; n < len; n++) {
+ s1 = (s1 + buf[n]) % BASE;
+ s2 = (s2 + s1) % BASE;
+ }
+ return (s2 << 16) + s1;
+ }
+
+ /* Return the adler32 of the bytes buf[0..len-1] */
+
+
+
+
+Deutsch & Gailly Informational [Page 10]
+
+RFC 1950 ZLIB Compressed Data Format Specification May 1996
+
+
+ unsigned long adler32(unsigned char *buf, int len)
+ {
+ return update_adler32(1L, buf, len);
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Deutsch & Gailly Informational [Page 11]
+
diff --git a/libmariadb/external/zlib/doc/rfc1951.txt b/libmariadb/external/zlib/doc/rfc1951.txt
new file mode 100644
index 00000000..403c8c72
--- /dev/null
+++ b/libmariadb/external/zlib/doc/rfc1951.txt
@@ -0,0 +1,955 @@
+
+
+
+
+
+
+Network Working Group P. Deutsch
+Request for Comments: 1951 Aladdin Enterprises
+Category: Informational May 1996
+
+
+ DEFLATE Compressed Data Format Specification version 1.3
+
+Status of This Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+IESG Note:
+
+ The IESG takes no position on the validity of any Intellectual
+ Property Rights statements contained in this document.
+
+Notices
+
+ Copyright (c) 1996 L. Peter Deutsch
+
+ Permission is granted to copy and distribute this document for any
+ purpose and without charge, including translations into other
+ languages and incorporation into compilations, provided that the
+ copyright notice and this notice are preserved, and that any
+ substantive changes or deletions from the original are clearly
+ marked.
+
+ A pointer to the latest version of this and related documentation in
+ HTML format can be found at the URL
+ <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
+
+Abstract
+
+ This specification defines a lossless compressed data format that
+ compresses data using a combination of the LZ77 algorithm and Huffman
+ coding, with efficiency comparable to the best currently available
+ general-purpose compression methods. The data can be produced or
+ consumed, even for an arbitrarily long sequentially presented input
+ data stream, using only an a priori bounded amount of intermediate
+ storage. The format can be implemented readily in a manner not
+ covered by patents.
+
+
+
+
+
+
+
+
+Deutsch Informational [Page 1]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+Table of Contents
+
+ 1. Introduction ................................................... 2
+ 1.1. Purpose ................................................... 2
+ 1.2. Intended audience ......................................... 3
+ 1.3. Scope ..................................................... 3
+ 1.4. Compliance ................................................ 3
+ 1.5. Definitions of terms and conventions used ................ 3
+ 1.6. Changes from previous versions ............................ 4
+ 2. Compressed representation overview ............................. 4
+ 3. Detailed specification ......................................... 5
+ 3.1. Overall conventions ....................................... 5
+ 3.1.1. Packing into bytes .................................. 5
+ 3.2. Compressed block format ................................... 6
+ 3.2.1. Synopsis of prefix and Huffman coding ............... 6
+ 3.2.2. Use of Huffman coding in the "deflate" format ....... 7
+ 3.2.3. Details of block format ............................. 9
+ 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11
+ 3.2.5. Compressed blocks (length and distance codes) ...... 11
+ 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12
+ 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13
+ 3.3. Compliance ............................................... 14
+ 4. Compression algorithm details ................................. 14
+ 5. References .................................................... 16
+ 6. Security Considerations ....................................... 16
+ 7. Source code ................................................... 16
+ 8. Acknowledgements .............................................. 16
+ 9. Author's Address .............................................. 17
+
+1. Introduction
+
+ 1.1. Purpose
+
+ The purpose of this specification is to define a lossless
+ compressed data format that:
+ * Is independent of CPU type, operating system, file system,
+ and character set, and hence can be used for interchange;
+ * Can be produced or consumed, even for an arbitrarily long
+ sequentially presented input data stream, using only an a
+ priori bounded amount of intermediate storage, and hence
+ can be used in data communications or similar structures
+ such as Unix filters;
+ * Compresses data with efficiency comparable to the best
+ currently available general-purpose compression methods,
+ and in particular considerably better than the "compress"
+ program;
+ * Can be implemented readily in a manner not covered by
+ patents, and hence can be practiced freely;
+
+
+
+Deutsch Informational [Page 2]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ * Is compatible with the file format produced by the current
+ widely used gzip utility, in that conforming decompressors
+ will be able to read data produced by the existing gzip
+ compressor.
+
+ The data format defined by this specification does not attempt to:
+
+ * Allow random access to compressed data;
+ * Compress specialized data (e.g., raster graphics) as well
+ as the best currently available specialized algorithms.
+
+ A simple counting argument shows that no lossless compression
+ algorithm can compress every possible input data set. For the
+ format defined here, the worst case expansion is 5 bytes per 32K-
+ byte block, i.e., a size increase of 0.015% for large data sets.
+ English text usually compresses by a factor of 2.5 to 3;
+ executable files usually compress somewhat less; graphical data
+ such as raster images may compress much more.
+
+ 1.2. Intended audience
+
+ This specification is intended for use by implementors of software
+ to compress data into "deflate" format and/or decompress data from
+ "deflate" format.
+
+ The text of the specification assumes a basic background in
+ programming at the level of bits and other primitive data
+ representations. Familiarity with the technique of Huffman coding
+ is helpful but not required.
+
+ 1.3. Scope
+
+ The specification specifies a method for representing a sequence
+ of bytes as a (usually shorter) sequence of bits, and a method for
+ packing the latter bit sequence into bytes.
+
+ 1.4. Compliance
+
+ Unless otherwise indicated below, a compliant decompressor must be
+ able to accept and decompress any data set that conforms to all
+ the specifications presented here; a compliant compressor must
+ produce data sets that conform to all the specifications presented
+ here.
+
+ 1.5. Definitions of terms and conventions used
+
+ Byte: 8 bits stored or transmitted as a unit (same as an octet).
+ For this specification, a byte is exactly 8 bits, even on machines
+
+
+
+Deutsch Informational [Page 3]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ which store a character on a number of bits different from eight.
+ See below, for the numbering of bits within a byte.
+
+ String: a sequence of arbitrary bytes.
+
+ 1.6. Changes from previous versions
+
+ There have been no technical changes to the deflate format since
+ version 1.1 of this specification. In version 1.2, some
+ terminology was changed. Version 1.3 is a conversion of the
+ specification to RFC style.
+
+2. Compressed representation overview
+
+ A compressed data set consists of a series of blocks, corresponding
+ to successive blocks of input data. The block sizes are arbitrary,
+ except that non-compressible blocks are limited to 65,535 bytes.
+
+ Each block is compressed using a combination of the LZ77 algorithm
+ and Huffman coding. The Huffman trees for each block are independent
+ of those for previous or subsequent blocks; the LZ77 algorithm may
+ use a reference to a duplicated string occurring in a previous block,
+ up to 32K input bytes before.
+
+ Each block consists of two parts: a pair of Huffman code trees that
+ describe the representation of the compressed data part, and a
+ compressed data part. (The Huffman trees themselves are compressed
+ using Huffman encoding.) The compressed data consists of a series of
+ elements of two types: literal bytes (of strings that have not been
+ detected as duplicated within the previous 32K input bytes), and
+ pointers to duplicated strings, where a pointer is represented as a
+ pair <length, backward distance>. The representation used in the
+ "deflate" format limits distances to 32K bytes and lengths to 258
+ bytes, but does not limit the size of a block, except for
+ uncompressible blocks, which are limited as noted above.
+
+ Each type of value (literals, distances, and lengths) in the
+ compressed data is represented using a Huffman code, using one code
+ tree for literals and lengths and a separate code tree for distances.
+ The code trees for each block appear in a compact form just before
+ the compressed data for that block.
+
+
+
+
+
+
+
+
+
+
+Deutsch Informational [Page 4]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+3. Detailed specification
+
+ 3.1. Overall conventions In the diagrams below, a box like this:
+
+ +---+
+ | | <-- the vertical bars might be missing
+ +---+
+
+ represents one byte; a box like this:
+
+ +==============+
+ | |
+ +==============+
+
+ represents a variable number of bytes.
+
+ Bytes stored within a computer do not have a "bit order", since
+ they are always treated as a unit. However, a byte considered as
+ an integer between 0 and 255 does have a most- and least-
+ significant bit, and since we write numbers with the most-
+ significant digit on the left, we also write bytes with the most-
+ significant bit on the left. In the diagrams below, we number the
+ bits of a byte so that bit 0 is the least-significant bit, i.e.,
+ the bits are numbered:
+
+ +--------+
+ |76543210|
+ +--------+
+
+ Within a computer, a number may occupy multiple bytes. All
+ multi-byte numbers in the format described here are stored with
+ the least-significant byte first (at the lower memory address).
+ For example, the decimal number 520 is stored as:
+
+ 0 1
+ +--------+--------+
+ |00001000|00000010|
+ +--------+--------+
+ ^ ^
+ | |
+ | + more significant byte = 2 x 256
+ + less significant byte = 8
+
+ 3.1.1. Packing into bytes
+
+ This document does not address the issue of the order in which
+ bits of a byte are transmitted on a bit-sequential medium,
+ since the final data format described here is byte- rather than
+
+
+
+Deutsch Informational [Page 5]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ bit-oriented. However, we describe the compressed block format
+ in below, as a sequence of data elements of various bit
+ lengths, not a sequence of bytes. We must therefore specify
+ how to pack these data elements into bytes to form the final
+ compressed byte sequence:
+
+ * Data elements are packed into bytes in order of
+ increasing bit number within the byte, i.e., starting
+ with the least-significant bit of the byte.
+ * Data elements other than Huffman codes are packed
+ starting with the least-significant bit of the data
+ element.
+ * Huffman codes are packed starting with the most-
+ significant bit of the code.
+
+ In other words, if one were to print out the compressed data as
+ a sequence of bytes, starting with the first byte at the
+ *right* margin and proceeding to the *left*, with the most-
+ significant bit of each byte on the left as usual, one would be
+ able to parse the result from right to left, with fixed-width
+ elements in the correct MSB-to-LSB order and Huffman codes in
+ bit-reversed order (i.e., with the first bit of the code in the
+ relative LSB position).
+
+ 3.2. Compressed block format
+
+ 3.2.1. Synopsis of prefix and Huffman coding
+
+ Prefix coding represents symbols from an a priori known
+ alphabet by bit sequences (codes), one code for each symbol, in
+ a manner such that different symbols may be represented by bit
+ sequences of different lengths, but a parser can always parse
+ an encoded string unambiguously symbol-by-symbol.
+
+ We define a prefix code in terms of a binary tree in which the
+ two edges descending from each non-leaf node are labeled 0 and
+ 1 and in which the leaf nodes correspond one-for-one with (are
+ labeled with) the symbols of the alphabet; then the code for a
+ symbol is the sequence of 0's and 1's on the edges leading from
+ the root to the leaf labeled with that symbol. For example:
+
+
+
+
+
+
+
+
+
+
+
+Deutsch Informational [Page 6]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ /\ Symbol Code
+ 0 1 ------ ----
+ / \ A 00
+ /\ B B 1
+ 0 1 C 011
+ / \ D 010
+ A /\
+ 0 1
+ / \
+ D C
+
+ A parser can decode the next symbol from an encoded input
+ stream by walking down the tree from the root, at each step
+ choosing the edge corresponding to the next input bit.
+
+ Given an alphabet with known symbol frequencies, the Huffman
+ algorithm allows the construction of an optimal prefix code
+ (one which represents strings with those symbol frequencies
+ using the fewest bits of any possible prefix codes for that
+ alphabet). Such a code is called a Huffman code. (See
+ reference [1] in Chapter 5, references for additional
+ information on Huffman codes.)
+
+ Note that in the "deflate" format, the Huffman codes for the
+ various alphabets must not exceed certain maximum code lengths.
+ This constraint complicates the algorithm for computing code
+ lengths from symbol frequencies. Again, see Chapter 5,
+ references for details.
+
+ 3.2.2. Use of Huffman coding in the "deflate" format
+
+ The Huffman codes used for each alphabet in the "deflate"
+ format have two additional rules:
+
+ * All codes of a given bit length have lexicographically
+ consecutive values, in the same order as the symbols
+ they represent;
+
+ * Shorter codes lexicographically precede longer codes.
+
+
+
+
+
+
+
+
+
+
+
+
+Deutsch Informational [Page 7]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ We could recode the example above to follow this rule as
+ follows, assuming that the order of the alphabet is ABCD:
+
+ Symbol Code
+ ------ ----
+ A 10
+ B 0
+ C 110
+ D 111
+
+ I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are
+ lexicographically consecutive.
+
+ Given this rule, we can define the Huffman code for an alphabet
+ just by giving the bit lengths of the codes for each symbol of
+ the alphabet in order; this is sufficient to determine the
+ actual codes. In our example, the code is completely defined
+ by the sequence of bit lengths (2, 1, 3, 3). The following
+ algorithm generates the codes as integers, intended to be read
+ from most- to least-significant bit. The code lengths are
+ initially in tree[I].Len; the codes are produced in
+ tree[I].Code.
+
+ 1) Count the number of codes for each code length. Let
+ bl_count[N] be the number of codes of length N, N >= 1.
+
+ 2) Find the numerical value of the smallest code for each
+ code length:
+
+ code = 0;
+ bl_count[0] = 0;
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ code = (code + bl_count[bits-1]) << 1;
+ next_code[bits] = code;
+ }
+
+ 3) Assign numerical values to all codes, using consecutive
+ values for all codes of the same length with the base
+ values determined at step 2. Codes that are never used
+ (which have a bit length of zero) must not be assigned a
+ value.
+
+ for (n = 0; n <= max_code; n++) {
+ len = tree[n].Len;
+ if (len != 0) {
+ tree[n].Code = next_code[len];
+ next_code[len]++;
+ }
+
+
+
+Deutsch Informational [Page 8]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ }
+
+ Example:
+
+ Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3,
+ 3, 2, 4, 4). After step 1, we have:
+
+ N bl_count[N]
+ - -----------
+ 2 1
+ 3 5
+ 4 2
+
+ Step 2 computes the following next_code values:
+
+ N next_code[N]
+ - ------------
+ 1 0
+ 2 0
+ 3 2
+ 4 14
+
+ Step 3 produces the following code values:
+
+ Symbol Length Code
+ ------ ------ ----
+ A 3 010
+ B 3 011
+ C 3 100
+ D 3 101
+ E 3 110
+ F 2 00
+ G 4 1110
+ H 4 1111
+
+ 3.2.3. Details of block format
+
+ Each block of compressed data begins with 3 header bits
+ containing the following data:
+
+ first bit BFINAL
+ next 2 bits BTYPE
+
+ Note that the header bits do not necessarily begin on a byte
+ boundary, since a block does not necessarily occupy an integral
+ number of bytes.
+
+
+
+
+
+Deutsch Informational [Page 9]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ BFINAL is set if and only if this is the last block of the data
+ set.
+
+ BTYPE specifies how the data are compressed, as follows:
+
+ 00 - no compression
+ 01 - compressed with fixed Huffman codes
+ 10 - compressed with dynamic Huffman codes
+ 11 - reserved (error)
+
+ The only difference between the two compressed cases is how the
+ Huffman codes for the literal/length and distance alphabets are
+ defined.
+
+ In all cases, the decoding algorithm for the actual data is as
+ follows:
+
+ do
+ read block header from input stream.
+ if stored with no compression
+ skip any remaining bits in current partially
+ processed byte
+ read LEN and NLEN (see next section)
+ copy LEN bytes of data to output
+ otherwise
+ if compressed with dynamic Huffman codes
+ read representation of code trees (see
+ subsection below)
+ loop (until end of block code recognized)
+ decode literal/length value from input stream
+ if value < 256
+ copy value (literal byte) to output stream
+ otherwise
+ if value = end of block (256)
+ break from loop
+ otherwise (value = 257..285)
+ decode distance from input stream
+
+ move backwards distance bytes in the output
+ stream, and copy length bytes from this
+ position to the output stream.
+ end loop
+ while not last block
+
+ Note that a duplicated string reference may refer to a string
+ in a previous block; i.e., the backward distance may cross one
+ or more block boundaries. However a distance cannot refer past
+ the beginning of the output stream. (An application using a
+
+
+
+Deutsch Informational [Page 10]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ preset dictionary might discard part of the output stream; a
+ distance can refer to that part of the output stream anyway)
+ Note also that the referenced string may overlap the current
+ position; for example, if the last 2 bytes decoded have values
+ X and Y, a string reference with <length = 5, distance = 2>
+ adds X,Y,X,Y,X to the output stream.
+
+ We now specify each compression method in turn.
+
+ 3.2.4. Non-compressed blocks (BTYPE=00)
+
+ Any bits of input up to the next byte boundary are ignored.
+ The rest of the block consists of the following information:
+
+ 0 1 2 3 4...
+ +---+---+---+---+================================+
+ | LEN | NLEN |... LEN bytes of literal data...|
+ +---+---+---+---+================================+
+
+ LEN is the number of data bytes in the block. NLEN is the
+ one's complement of LEN.
+
+ 3.2.5. Compressed blocks (length and distance codes)
+
+ As noted above, encoded data blocks in the "deflate" format
+ consist of sequences of symbols drawn from three conceptually
+ distinct alphabets: either literal bytes, from the alphabet of
+ byte values (0..255), or <length, backward distance> pairs,
+ where the length is drawn from (3..258) and the distance is
+ drawn from (1..32,768). In fact, the literal and length
+ alphabets are merged into a single alphabet (0..285), where
+ values 0..255 represent literal bytes, the value 256 indicates
+ end-of-block, and values 257..285 represent length codes
+ (possibly in conjunction with extra bits following the symbol
+ code) as follows:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Deutsch Informational [Page 11]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ Extra Extra Extra
+ Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
+ ---- ---- ------ ---- ---- ------- ---- ---- -------
+ 257 0 3 267 1 15,16 277 4 67-82
+ 258 0 4 268 1 17,18 278 4 83-98
+ 259 0 5 269 2 19-22 279 4 99-114
+ 260 0 6 270 2 23-26 280 4 115-130
+ 261 0 7 271 2 27-30 281 5 131-162
+ 262 0 8 272 2 31-34 282 5 163-194
+ 263 0 9 273 3 35-42 283 5 195-226
+ 264 0 10 274 3 43-50 284 5 227-257
+ 265 1 11,12 275 3 51-58 285 0 258
+ 266 1 13,14 276 3 59-66
+
+ The extra bits should be interpreted as a machine integer
+ stored with the most-significant bit first, e.g., bits 1110
+ represent the value 14.
+
+ Extra Extra Extra
+ Code Bits Dist Code Bits Dist Code Bits Distance
+ ---- ---- ---- ---- ---- ------ ---- ---- --------
+ 0 0 1 10 4 33-48 20 9 1025-1536
+ 1 0 2 11 4 49-64 21 9 1537-2048
+ 2 0 3 12 5 65-96 22 10 2049-3072
+ 3 0 4 13 5 97-128 23 10 3073-4096
+ 4 1 5,6 14 6 129-192 24 11 4097-6144
+ 5 1 7,8 15 6 193-256 25 11 6145-8192
+ 6 2 9-12 16 7 257-384 26 12 8193-12288
+ 7 2 13-16 17 7 385-512 27 12 12289-16384
+ 8 3 17-24 18 8 513-768 28 13 16385-24576
+ 9 3 25-32 19 8 769-1024 29 13 24577-32768
+
+ 3.2.6. Compression with fixed Huffman codes (BTYPE=01)
+
+ The Huffman codes for the two alphabets are fixed, and are not
+ represented explicitly in the data. The Huffman code lengths
+ for the literal/length alphabet are:
+
+ Lit Value Bits Codes
+ --------- ---- -----
+ 0 - 143 8 00110000 through
+ 10111111
+ 144 - 255 9 110010000 through
+ 111111111
+ 256 - 279 7 0000000 through
+ 0010111
+ 280 - 287 8 11000000 through
+ 11000111
+
+
+
+Deutsch Informational [Page 12]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ The code lengths are sufficient to generate the actual codes,
+ as described above; we show the codes in the table for added
+ clarity. Literal/length values 286-287 will never actually
+ occur in the compressed data, but participate in the code
+ construction.
+
+ Distance codes 0-31 are represented by (fixed-length) 5-bit
+ codes, with possible additional bits as shown in the table
+ shown in Paragraph 3.2.5, above. Note that distance codes 30-
+ 31 will never actually occur in the compressed data.
+
+ 3.2.7. Compression with dynamic Huffman codes (BTYPE=10)
+
+ The Huffman codes for the two alphabets appear in the block
+ immediately after the header bits and before the actual
+ compressed data, first the literal/length code and then the
+ distance code. Each code is defined by a sequence of code
+ lengths, as discussed in Paragraph 3.2.2, above. For even
+ greater compactness, the code length sequences themselves are
+ compressed using a Huffman code. The alphabet for code lengths
+ is as follows:
+
+ 0 - 15: Represent code lengths of 0 - 15
+ 16: Copy the previous code length 3 - 6 times.
+ The next 2 bits indicate repeat length
+ (0 = 3, ... , 3 = 6)
+ Example: Codes 8, 16 (+2 bits 11),
+ 16 (+2 bits 10) will expand to
+ 12 code lengths of 8 (1 + 6 + 5)
+ 17: Repeat a code length of 0 for 3 - 10 times.
+ (3 bits of length)
+ 18: Repeat a code length of 0 for 11 - 138 times
+ (7 bits of length)
+
+ A code length of 0 indicates that the corresponding symbol in
+ the literal/length or distance alphabet will not occur in the
+ block, and should not participate in the Huffman code
+ construction algorithm given earlier. If only one distance
+ code is used, it is encoded using one bit, not zero bits; in
+ this case there is a single code length of one, with one unused
+ code. One distance code of zero bits means that there are no
+ distance codes used at all (the data is all literals).
+
+ We can now define the format of the block:
+
+ 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286)
+ 5 Bits: HDIST, # of Distance codes - 1 (1 - 32)
+ 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19)
+
+
+
+Deutsch Informational [Page 13]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ (HCLEN + 4) x 3 bits: code lengths for the code length
+ alphabet given just above, in the order: 16, 17, 18,
+ 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+
+ These code lengths are interpreted as 3-bit integers
+ (0-7); as above, a code length of 0 means the
+ corresponding symbol (literal/length or distance code
+ length) is not used.
+
+ HLIT + 257 code lengths for the literal/length alphabet,
+ encoded using the code length Huffman code
+
+ HDIST + 1 code lengths for the distance alphabet,
+ encoded using the code length Huffman code
+
+ The actual compressed data of the block,
+ encoded using the literal/length and distance Huffman
+ codes
+
+ The literal/length symbol 256 (end of data),
+ encoded using the literal/length Huffman code
+
+ The code length repeat codes can cross from HLIT + 257 to the
+ HDIST + 1 code lengths. In other words, all code lengths form
+ a single sequence of HLIT + HDIST + 258 values.
+
+ 3.3. Compliance
+
+ A compressor may limit further the ranges of values specified in
+ the previous section and still be compliant; for example, it may
+ limit the range of backward pointers to some value smaller than
+ 32K. Similarly, a compressor may limit the size of blocks so that
+ a compressible block fits in memory.
+
+ A compliant decompressor must accept the full range of possible
+ values defined in the previous section, and must accept blocks of
+ arbitrary size.
+
+4. Compression algorithm details
+
+ While it is the intent of this document to define the "deflate"
+ compressed data format without reference to any particular
+ compression algorithm, the format is related to the compressed
+ formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below);
+ since many variations of LZ77 are patented, it is strongly
+ recommended that the implementor of a compressor follow the general
+ algorithm presented here, which is known not to be patented per se.
+ The material in this section is not part of the definition of the
+
+
+
+Deutsch Informational [Page 14]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+ specification per se, and a compressor need not follow it in order to
+ be compliant.
+
+ The compressor terminates a block when it determines that starting a
+ new block with fresh trees would be useful, or when the block size
+ fills up the compressor's block buffer.
+
+ The compressor uses a chained hash table to find duplicated strings,
+ using a hash function that operates on 3-byte sequences. At any
+ given point during compression, let XYZ be the next 3 input bytes to
+ be examined (not necessarily all different, of course). First, the
+ compressor examines the hash chain for XYZ. If the chain is empty,
+ the compressor simply writes out X as a literal byte and advances one
+ byte in the input. If the hash chain is not empty, indicating that
+ the sequence XYZ (or, if we are unlucky, some other 3 bytes with the
+ same hash function value) has occurred recently, the compressor
+ compares all strings on the XYZ hash chain with the actual input data
+ sequence starting at the current point, and selects the longest
+ match.
+
+ The compressor searches the hash chains starting with the most recent
+ strings, to favor small distances and thus take advantage of the
+ Huffman encoding. The hash chains are singly linked. There are no
+ deletions from the hash chains; the algorithm simply discards matches
+ that are too old. To avoid a worst-case situation, very long hash
+ chains are arbitrarily truncated at a certain length, determined by a
+ run-time parameter.
+
+ To improve overall compression, the compressor optionally defers the
+ selection of matches ("lazy matching"): after a match of length N has
+ been found, the compressor searches for a longer match starting at
+ the next input byte. If it finds a longer match, it truncates the
+ previous match to a length of one (thus producing a single literal
+ byte) and then emits the longer match. Otherwise, it emits the
+ original match, and, as described above, advances N bytes before
+ continuing.
+
+ Run-time parameters also control this "lazy match" procedure. If
+ compression ratio is most important, the compressor attempts a
+ complete second search regardless of the length of the first match.
+ In the normal case, if the current match is "long enough", the
+ compressor reduces the search for a longer match, thus speeding up
+ the process. If speed is most important, the compressor inserts new
+ strings in the hash table only when no match was found, or when the
+ match is not "too long". This degrades the compression ratio but
+ saves time since there are both fewer insertions and fewer searches.
+
+
+
+
+
+Deutsch Informational [Page 15]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+5. References
+
+ [1] Huffman, D. A., "A Method for the Construction of Minimum
+ Redundancy Codes", Proceedings of the Institute of Radio
+ Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101.
+
+ [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
+ Compression", IEEE Transactions on Information Theory, Vol. 23,
+ No. 3, pp. 337-343.
+
+ [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources,
+ available in ftp://ftp.uu.net/pub/archiving/zip/doc/
+
+ [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources,
+ available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/
+
+ [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix
+ encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169.
+
+ [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes,"
+ Comm. ACM, 33,4, April 1990, pp. 449-459.
+
+6. Security Considerations
+
+ Any data compression method involves the reduction of redundancy in
+ the data. Consequently, any corruption of the data is likely to have
+ severe effects and be difficult to correct. Uncompressed text, on
+ the other hand, will probably still be readable despite the presence
+ of some corrupted bytes.
+
+ It is recommended that systems using this data format provide some
+ means of validating the integrity of the compressed data. See
+ reference [3], for example.
+
+7. Source code
+
+ Source code for a C language implementation of a "deflate" compliant
+ compressor and decompressor is available within the zlib package at
+ ftp://ftp.uu.net/pub/archiving/zip/zlib/.
+
+8. Acknowledgements
+
+ Trademarks cited in this document are the property of their
+ respective owners.
+
+ Phil Katz designed the deflate format. Jean-Loup Gailly and Mark
+ Adler wrote the related software described in this specification.
+ Glenn Randers-Pehrson converted this document to RFC and HTML format.
+
+
+
+Deutsch Informational [Page 16]
+
+RFC 1951 DEFLATE Compressed Data Format Specification May 1996
+
+
+9. Author's Address
+
+ L. Peter Deutsch
+ Aladdin Enterprises
+ 203 Santa Margarita Ave.
+ Menlo Park, CA 94025
+
+ Phone: (415) 322-0103 (AM only)
+ FAX: (415) 322-1734
+ EMail: <ghost@aladdin.com>
+
+ Questions about the technical content of this specification can be
+ sent by email to:
+
+ Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
+ Mark Adler <madler@alumni.caltech.edu>
+
+ Editorial comments on this specification can be sent by email to:
+
+ L. Peter Deutsch <ghost@aladdin.com> and
+ Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Deutsch Informational [Page 17]
+
diff --git a/libmariadb/external/zlib/doc/rfc1952.txt b/libmariadb/external/zlib/doc/rfc1952.txt
new file mode 100644
index 00000000..a8e51b45
--- /dev/null
+++ b/libmariadb/external/zlib/doc/rfc1952.txt
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+Network Working Group P. Deutsch
+Request for Comments: 1952 Aladdin Enterprises
+Category: Informational May 1996
+
+
+ GZIP file format specification version 4.3
+
+Status of This Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+IESG Note:
+
+ The IESG takes no position on the validity of any Intellectual
+ Property Rights statements contained in this document.
+
+Notices
+
+ Copyright (c) 1996 L. Peter Deutsch
+
+ Permission is granted to copy and distribute this document for any
+ purpose and without charge, including translations into other
+ languages and incorporation into compilations, provided that the
+ copyright notice and this notice are preserved, and that any
+ substantive changes or deletions from the original are clearly
+ marked.
+
+ A pointer to the latest version of this and related documentation in
+ HTML format can be found at the URL
+ <ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.
+
+Abstract
+
+ This specification defines a lossless compressed data format that is
+ compatible with the widely used GZIP utility. The format includes a
+ cyclic redundancy check value for detecting data corruption. The
+ format presently uses the DEFLATE method of compression but can be
+ easily extended to use other compression methods. The format can be
+ implemented readily in a manner not covered by patents.
+
+
+
+
+
+
+
+
+
+
+Deutsch Informational [Page 1]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+Table of Contents
+
+ 1. Introduction ................................................... 2
+ 1.1. Purpose ................................................... 2
+ 1.2. Intended audience ......................................... 3
+ 1.3. Scope ..................................................... 3
+ 1.4. Compliance ................................................ 3
+ 1.5. Definitions of terms and conventions used ................. 3
+ 1.6. Changes from previous versions ............................ 3
+ 2. Detailed specification ......................................... 4
+ 2.1. Overall conventions ....................................... 4
+ 2.2. File format ............................................... 5
+ 2.3. Member format ............................................. 5
+ 2.3.1. Member header and trailer ........................... 6
+ 2.3.1.1. Extra field ................................... 8
+ 2.3.1.2. Compliance .................................... 9
+ 3. References .................................................. 9
+ 4. Security Considerations .................................... 10
+ 5. Acknowledgements ........................................... 10
+ 6. Author's Address ........................................... 10
+ 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11
+ 8. Appendix: Sample CRC Code .................................. 11
+
+1. Introduction
+
+ 1.1. Purpose
+
+ The purpose of this specification is to define a lossless
+ compressed data format that:
+
+ * Is independent of CPU type, operating system, file system,
+ and character set, and hence can be used for interchange;
+ * Can compress or decompress a data stream (as opposed to a
+ randomly accessible file) to produce another data stream,
+ using only an a priori bounded amount of intermediate
+ storage, and hence can be used in data communications or
+ similar structures such as Unix filters;
+ * Compresses data with efficiency comparable to the best
+ currently available general-purpose compression methods,
+ and in particular considerably better than the "compress"
+ program;
+ * Can be implemented readily in a manner not covered by
+ patents, and hence can be practiced freely;
+ * Is compatible with the file format produced by the current
+ widely used gzip utility, in that conforming decompressors
+ will be able to read data produced by the existing gzip
+ compressor.
+
+
+
+
+Deutsch Informational [Page 2]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ The data format defined by this specification does not attempt to:
+
+ * Provide random access to compressed data;
+ * Compress specialized data (e.g., raster graphics) as well as
+ the best currently available specialized algorithms.
+
+ 1.2. Intended audience
+
+ This specification is intended for use by implementors of software
+ to compress data into gzip format and/or decompress data from gzip
+ format.
+
+ The text of the specification assumes a basic background in
+ programming at the level of bits and other primitive data
+ representations.
+
+ 1.3. Scope
+
+ The specification specifies a compression method and a file format
+ (the latter assuming only that a file can store a sequence of
+ arbitrary bytes). It does not specify any particular interface to
+ a file system or anything about character sets or encodings
+ (except for file names and comments, which are optional).
+
+ 1.4. Compliance
+
+ Unless otherwise indicated below, a compliant decompressor must be
+ able to accept and decompress any file that conforms to all the
+ specifications presented here; a compliant compressor must produce
+ files that conform to all the specifications presented here. The
+ material in the appendices is not part of the specification per se
+ and is not relevant to compliance.
+
+ 1.5. Definitions of terms and conventions used
+
+ byte: 8 bits stored or transmitted as a unit (same as an octet).
+ (For this specification, a byte is exactly 8 bits, even on
+ machines which store a character on a number of bits different
+ from 8.) See below for the numbering of bits within a byte.
+
+ 1.6. Changes from previous versions
+
+ There have been no technical changes to the gzip format since
+ version 4.1 of this specification. In version 4.2, some
+ terminology was changed, and the sample CRC code was rewritten for
+ clarity and to eliminate the requirement for the caller to do pre-
+ and post-conditioning. Version 4.3 is a conversion of the
+ specification to RFC style.
+
+
+
+Deutsch Informational [Page 3]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+2. Detailed specification
+
+ 2.1. Overall conventions
+
+ In the diagrams below, a box like this:
+
+ +---+
+ | | <-- the vertical bars might be missing
+ +---+
+
+ represents one byte; a box like this:
+
+ +==============+
+ | |
+ +==============+
+
+ represents a variable number of bytes.
+
+ Bytes stored within a computer do not have a "bit order", since
+ they are always treated as a unit. However, a byte considered as
+ an integer between 0 and 255 does have a most- and least-
+ significant bit, and since we write numbers with the most-
+ significant digit on the left, we also write bytes with the most-
+ significant bit on the left. In the diagrams below, we number the
+ bits of a byte so that bit 0 is the least-significant bit, i.e.,
+ the bits are numbered:
+
+ +--------+
+ |76543210|
+ +--------+
+
+ This document does not address the issue of the order in which
+ bits of a byte are transmitted on a bit-sequential medium, since
+ the data format described here is byte- rather than bit-oriented.
+
+ Within a computer, a number may occupy multiple bytes. All
+ multi-byte numbers in the format described here are stored with
+ the least-significant byte first (at the lower memory address).
+ For example, the decimal number 520 is stored as:
+
+ 0 1
+ +--------+--------+
+ |00001000|00000010|
+ +--------+--------+
+ ^ ^
+ | |
+ | + more significant byte = 2 x 256
+ + less significant byte = 8
+
+
+
+Deutsch Informational [Page 4]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ 2.2. File format
+
+ A gzip file consists of a series of "members" (compressed data
+ sets). The format of each member is specified in the following
+ section. The members simply appear one after another in the file,
+ with no additional information before, between, or after them.
+
+ 2.3. Member format
+
+ Each member has the following structure:
+
+ +---+---+---+---+---+---+---+---+---+---+
+ |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->)
+ +---+---+---+---+---+---+---+---+---+---+
+
+ (if FLG.FEXTRA set)
+
+ +---+---+=================================+
+ | XLEN |...XLEN bytes of "extra field"...| (more-->)
+ +---+---+=================================+
+
+ (if FLG.FNAME set)
+
+ +=========================================+
+ |...original file name, zero-terminated...| (more-->)
+ +=========================================+
+
+ (if FLG.FCOMMENT set)
+
+ +===================================+
+ |...file comment, zero-terminated...| (more-->)
+ +===================================+
+
+ (if FLG.FHCRC set)
+
+ +---+---+
+ | CRC16 |
+ +---+---+
+
+ +=======================+
+ |...compressed blocks...| (more-->)
+ +=======================+
+
+ 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+
+ | CRC32 | ISIZE |
+ +---+---+---+---+---+---+---+---+
+
+
+
+
+Deutsch Informational [Page 5]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ 2.3.1. Member header and trailer
+
+ ID1 (IDentification 1)
+ ID2 (IDentification 2)
+ These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139
+ (0x8b, \213), to identify the file as being in gzip format.
+
+ CM (Compression Method)
+ This identifies the compression method used in the file. CM
+ = 0-7 are reserved. CM = 8 denotes the "deflate"
+ compression method, which is the one customarily used by
+ gzip and which is documented elsewhere.
+
+ FLG (FLaGs)
+ This flag byte is divided into individual bits as follows:
+
+ bit 0 FTEXT
+ bit 1 FHCRC
+ bit 2 FEXTRA
+ bit 3 FNAME
+ bit 4 FCOMMENT
+ bit 5 reserved
+ bit 6 reserved
+ bit 7 reserved
+
+ If FTEXT is set, the file is probably ASCII text. This is
+ an optional indication, which the compressor may set by
+ checking a small amount of the input data to see whether any
+ non-ASCII characters are present. In case of doubt, FTEXT
+ is cleared, indicating binary data. For systems which have
+ different file formats for ascii text and binary data, the
+ decompressor can use FTEXT to choose the appropriate format.
+ We deliberately do not specify the algorithm used to set
+ this bit, since a compressor always has the option of
+ leaving it cleared and a decompressor always has the option
+ of ignoring it and letting some other program handle issues
+ of data conversion.
+
+ If FHCRC is set, a CRC16 for the gzip header is present,
+ immediately before the compressed data. The CRC16 consists
+ of the two least significant bytes of the CRC32 for all
+ bytes of the gzip header up to and not including the CRC16.
+ [The FHCRC bit was never set by versions of gzip up to
+ 1.2.4, even though it was documented with a different
+ meaning in gzip 1.2.4.]
+
+ If FEXTRA is set, optional extra fields are present, as
+ described in a following section.
+
+
+
+Deutsch Informational [Page 6]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ If FNAME is set, an original file name is present,
+ terminated by a zero byte. The name must consist of ISO
+ 8859-1 (LATIN-1) characters; on operating systems using
+ EBCDIC or any other character set for file names, the name
+ must be translated to the ISO LATIN-1 character set. This
+ is the original name of the file being compressed, with any
+ directory components removed, and, if the file being
+ compressed is on a file system with case insensitive names,
+ forced to lower case. There is no original file name if the
+ data was compressed from a source other than a named file;
+ for example, if the source was stdin on a Unix system, there
+ is no file name.
+
+ If FCOMMENT is set, a zero-terminated file comment is
+ present. This comment is not interpreted; it is only
+ intended for human consumption. The comment must consist of
+ ISO 8859-1 (LATIN-1) characters. Line breaks should be
+ denoted by a single line feed character (10 decimal).
+
+ Reserved FLG bits must be zero.
+
+ MTIME (Modification TIME)
+ This gives the most recent modification time of the original
+ file being compressed. The time is in Unix format, i.e.,
+ seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this
+ may cause problems for MS-DOS and other systems that use
+ local rather than Universal time.) If the compressed data
+ did not come from a file, MTIME is set to the time at which
+ compression started. MTIME = 0 means no time stamp is
+ available.
+
+ XFL (eXtra FLags)
+ These flags are available for use by specific compression
+ methods. The "deflate" method (CM = 8) sets these flags as
+ follows:
+
+ XFL = 2 - compressor used maximum compression,
+ slowest algorithm
+ XFL = 4 - compressor used fastest algorithm
+
+ OS (Operating System)
+ This identifies the type of file system on which compression
+ took place. This may be useful in determining end-of-line
+ convention for text files. The currently defined values are
+ as follows:
+
+
+
+
+
+
+Deutsch Informational [Page 7]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
+ 1 - Amiga
+ 2 - VMS (or OpenVMS)
+ 3 - Unix
+ 4 - VM/CMS
+ 5 - Atari TOS
+ 6 - HPFS filesystem (OS/2, NT)
+ 7 - Macintosh
+ 8 - Z-System
+ 9 - CP/M
+ 10 - TOPS-20
+ 11 - NTFS filesystem (NT)
+ 12 - QDOS
+ 13 - Acorn RISCOS
+ 255 - unknown
+
+ XLEN (eXtra LENgth)
+ If FLG.FEXTRA is set, this gives the length of the optional
+ extra field. See below for details.
+
+ CRC32 (CRC-32)
+ This contains a Cyclic Redundancy Check value of the
+ uncompressed data computed according to CRC-32 algorithm
+ used in the ISO 3309 standard and in section 8.1.1.6.2 of
+ ITU-T recommendation V.42. (See http://www.iso.ch for
+ ordering ISO documents. See gopher://info.itu.ch for an
+ online version of ITU-T V.42.)
+
+ ISIZE (Input SIZE)
+ This contains the size of the original (uncompressed) input
+ data modulo 2^32.
+
+ 2.3.1.1. Extra field
+
+ If the FLG.FEXTRA bit is set, an "extra field" is present in
+ the header, with total length XLEN bytes. It consists of a
+ series of subfields, each of the form:
+
+ +---+---+---+---+==================================+
+ |SI1|SI2| LEN |... LEN bytes of subfield data ...|
+ +---+---+---+---+==================================+
+
+ SI1 and SI2 provide a subfield ID, typically two ASCII letters
+ with some mnemonic value. Jean-Loup Gailly
+ <gzip@prep.ai.mit.edu> is maintaining a registry of subfield
+ IDs; please send him any subfield ID you wish to use. Subfield
+ IDs with SI2 = 0 are reserved for future use. The following
+ IDs are currently defined:
+
+
+
+Deutsch Informational [Page 8]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ SI1 SI2 Data
+ ---------- ---------- ----
+ 0x41 ('A') 0x70 ('P') Apollo file type information
+
+ LEN gives the length of the subfield data, excluding the 4
+ initial bytes.
+
+ 2.3.1.2. Compliance
+
+ A compliant compressor must produce files with correct ID1,
+ ID2, CM, CRC32, and ISIZE, but may set all the other fields in
+ the fixed-length part of the header to default values (255 for
+ OS, 0 for all others). The compressor must set all reserved
+ bits to zero.
+
+ A compliant decompressor must check ID1, ID2, and CM, and
+ provide an error indication if any of these have incorrect
+ values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC
+ at least so it can skip over the optional fields if they are
+ present. It need not examine any other part of the header or
+ trailer; in particular, a decompressor may ignore FTEXT and OS
+ and always produce binary output, and still be compliant. A
+ compliant decompressor must give an error indication if any
+ reserved bit is non-zero, since such a bit could indicate the
+ presence of a new field that would cause subsequent data to be
+ interpreted incorrectly.
+
+3. References
+
+ [1] "Information Processing - 8-bit single-byte coded graphic
+ character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987).
+ The ISO 8859-1 (Latin-1) character set is a superset of 7-bit
+ ASCII. Files defining this character set are available as
+ iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/
+
+ [2] ISO 3309
+
+ [3] ITU-T recommendation V.42
+
+ [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification",
+ available in ftp://ftp.uu.net/pub/archiving/zip/doc/
+
+ [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in
+ ftp://prep.ai.mit.edu/pub/gnu/
+
+ [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table
+ Look-Up", Communications of the ACM, 31(8), pp.1008-1013.
+
+
+
+
+Deutsch Informational [Page 9]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal,
+ pp.118-133.
+
+ [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt,
+ describing the CRC concept.
+
+4. Security Considerations
+
+ Any data compression method involves the reduction of redundancy in
+ the data. Consequently, any corruption of the data is likely to have
+ severe effects and be difficult to correct. Uncompressed text, on
+ the other hand, will probably still be readable despite the presence
+ of some corrupted bytes.
+
+ It is recommended that systems using this data format provide some
+ means of validating the integrity of the compressed data, such as by
+ setting and checking the CRC-32 check value.
+
+5. Acknowledgements
+
+ Trademarks cited in this document are the property of their
+ respective owners.
+
+ Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler,
+ the related software described in this specification. Glenn
+ Randers-Pehrson converted this document to RFC and HTML format.
+
+6. Author's Address
+
+ L. Peter Deutsch
+ Aladdin Enterprises
+ 203 Santa Margarita Ave.
+ Menlo Park, CA 94025
+
+ Phone: (415) 322-0103 (AM only)
+ FAX: (415) 322-1734
+ EMail: <ghost@aladdin.com>
+
+ Questions about the technical content of this specification can be
+ sent by email to:
+
+ Jean-Loup Gailly <gzip@prep.ai.mit.edu> and
+ Mark Adler <madler@alumni.caltech.edu>
+
+ Editorial comments on this specification can be sent by email to:
+
+ L. Peter Deutsch <ghost@aladdin.com> and
+ Glenn Randers-Pehrson <randeg@alumni.rpi.edu>
+
+
+
+Deutsch Informational [Page 10]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+7. Appendix: Jean-Loup Gailly's gzip utility
+
+ The most widely used implementation of gzip compression, and the
+ original documentation on which this specification is based, were
+ created by Jean-Loup Gailly <gzip@prep.ai.mit.edu>. Since this
+ implementation is a de facto standard, we mention some more of its
+ features here. Again, the material in this section is not part of
+ the specification per se, and implementations need not follow it to
+ be compliant.
+
+ When compressing or decompressing a file, gzip preserves the
+ protection, ownership, and modification time attributes on the local
+ file system, since there is no provision for representing protection
+ attributes in the gzip file format itself. Since the file format
+ includes a modification time, the gzip decompressor provides a
+ command line switch that assigns the modification time from the file,
+ rather than the local modification time of the compressed input, to
+ the decompressed output.
+
+8. Appendix: Sample CRC Code
+
+ The following sample code represents a practical implementation of
+ the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42
+ for a formal specification.)
+
+ The sample code is in the ANSI C programming language. Non C users
+ may find it easier to read with these hints:
+
+ & Bitwise AND operator.
+ ^ Bitwise exclusive-OR operator.
+ >> Bitwise right shift operator. When applied to an
+ unsigned quantity, as here, right shift inserts zero
+ bit(s) at the left.
+ ! Logical NOT operator.
+ ++ "n++" increments the variable n.
+ 0xNNN 0x introduces a hexadecimal (base 16) constant.
+ Suffix L indicates a long value (at least 32 bits).
+
+ /* Table of CRCs of all 8-bit messages. */
+ unsigned long crc_table[256];
+
+ /* Flag: has the table been computed? Initially false. */
+ int crc_table_computed = 0;
+
+ /* Make the table for a fast CRC. */
+ void make_crc_table(void)
+ {
+ unsigned long c;
+
+
+
+Deutsch Informational [Page 11]
+
+RFC 1952 GZIP File Format Specification May 1996
+
+
+ int n, k;
+ for (n = 0; n < 256; n++) {
+ c = (unsigned long) n;
+ for (k = 0; k < 8; k++) {
+ if (c & 1) {
+ c = 0xedb88320L ^ (c >> 1);
+ } else {
+ c = c >> 1;
+ }
+ }
+ crc_table[n] = c;
+ }
+ crc_table_computed = 1;
+ }
+
+ /*
+ Update a running crc with the bytes buf[0..len-1] and return
+ the updated crc. The crc should be initialized to zero. Pre- and
+ post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the caller. Usage example:
+
+ unsigned long crc = 0L;
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = update_crc(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+ */
+ unsigned long update_crc(unsigned long crc,
+ unsigned char *buf, int len)
+ {
+ unsigned long c = crc ^ 0xffffffffL;
+ int n;
+
+ if (!crc_table_computed)
+ make_crc_table();
+ for (n = 0; n < len; n++) {
+ c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
+ }
+ return c ^ 0xffffffffL;
+ }
+
+ /* Return the CRC of the bytes buf[0..len-1]. */
+ unsigned long crc(unsigned char *buf, int len)
+ {
+ return update_crc(0L, buf, len);
+ }
+
+
+
+
+Deutsch Informational [Page 12]
+
diff --git a/libmariadb/external/zlib/doc/txtvsbin.txt b/libmariadb/external/zlib/doc/txtvsbin.txt
new file mode 100644
index 00000000..3d0f0634
--- /dev/null
+++ b/libmariadb/external/zlib/doc/txtvsbin.txt
@@ -0,0 +1,107 @@
+A Fast Method for Identifying Plain Text Files
+==============================================
+
+
+Introduction
+------------
+
+Given a file coming from an unknown source, it is sometimes desirable
+to find out whether the format of that file is plain text. Although
+this may appear like a simple task, a fully accurate detection of the
+file type requires heavy-duty semantic analysis on the file contents.
+It is, however, possible to obtain satisfactory results by employing
+various heuristics.
+
+Previous versions of PKZip and other zip-compatible compression tools
+were using a crude detection scheme: if more than 80% (4/5) of the bytes
+found in a certain buffer are within the range [7..127], the file is
+labeled as plain text, otherwise it is labeled as binary. A prominent
+limitation of this scheme is the restriction to Latin-based alphabets.
+Other alphabets, like Greek, Cyrillic or Asian, make extensive use of
+the bytes within the range [128..255], and texts using these alphabets
+are most often misidentified by this scheme; in other words, the rate
+of false negatives is sometimes too high, which means that the recall
+is low. Another weakness of this scheme is a reduced precision, due to
+the false positives that may occur when binary files containing large
+amounts of textual characters are misidentified as plain text.
+
+In this article we propose a new, simple detection scheme that features
+a much increased precision and a near-100% recall. This scheme is
+designed to work on ASCII, Unicode and other ASCII-derived alphabets,
+and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.)
+and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings
+(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however.
+
+
+The Algorithm
+-------------
+
+The algorithm works by dividing the set of bytecodes [0..255] into three
+categories:
+- The white list of textual bytecodes:
+ 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255.
+- The gray list of tolerated bytecodes:
+ 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC).
+- The black list of undesired, non-textual bytecodes:
+ 0 (NUL) to 6, 14 to 31.
+
+If a file contains at least one byte that belongs to the white list and
+no byte that belongs to the black list, then the file is categorized as
+plain text; otherwise, it is categorized as binary. (The boundary case,
+when the file is empty, automatically falls into the latter category.)
+
+
+Rationale
+---------
+
+The idea behind this algorithm relies on two observations.
+
+The first observation is that, although the full range of 7-bit codes
+[0..127] is properly specified by the ASCII standard, most control
+characters in the range [0..31] are not used in practice. The only
+widely-used, almost universally-portable control codes are 9 (TAB),
+10 (LF) and 13 (CR). There are a few more control codes that are
+recognized on a reduced range of platforms and text viewers/editors:
+7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these
+codes are rarely (if ever) used alone, without being accompanied by
+some printable text. Even the newer, portable text formats such as
+XML avoid using control characters outside the list mentioned here.
+
+The second observation is that most of the binary files tend to contain
+control characters, especially 0 (NUL). Even though the older text
+detection schemes observe the presence of non-ASCII codes from the range
+[128..255], the precision rarely has to suffer if this upper range is
+labeled as textual, because the files that are genuinely binary tend to
+contain both control characters and codes from the upper range. On the
+other hand, the upper range needs to be labeled as textual, because it
+is used by virtually all ASCII extensions. In particular, this range is
+used for encoding non-Latin scripts.
+
+Since there is no counting involved, other than simply observing the
+presence or the absence of some byte values, the algorithm produces
+consistent results, regardless what alphabet encoding is being used.
+(If counting were involved, it could be possible to obtain different
+results on a text encoded, say, using ISO-8859-16 versus UTF-8.)
+
+There is an extra category of plain text files that are "polluted" with
+one or more black-listed codes, either by mistake or by peculiar design
+considerations. In such cases, a scheme that tolerates a small fraction
+of black-listed codes would provide an increased recall (i.e. more true
+positives). This, however, incurs a reduced precision overall, since
+false positives are more likely to appear in binary files that contain
+large chunks of textual data. Furthermore, "polluted" plain text should
+be regarded as binary by general-purpose text detection schemes, because
+general-purpose text processing algorithms might not be applicable.
+Under this premise, it is safe to say that our detection method provides
+a near-100% recall.
+
+Experiments have been run on many files coming from various platforms
+and applications. We tried plain text files, system logs, source code,
+formatted office documents, compiled object code, etc. The results
+confirm the optimistic assumptions about the capabilities of this
+algorithm.
+
+
+--
+Cosmin Truta
+Last updated: 2006-May-28
diff --git a/libmariadb/external/zlib/example.c b/libmariadb/external/zlib/example.c
new file mode 100644
index 00000000..604736f1
--- /dev/null
+++ b/libmariadb/external/zlib/example.c
@@ -0,0 +1,565 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-2006 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+#include <stdio.h>
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+# define TESTFILE "foo-gz"
+#else
+# define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_compress OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_gzio OF((const char *fname,
+ Byte *uncompr, uLong uncomprLen));
+void test_deflate OF((Byte *compr, uLong comprLen));
+void test_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_flush OF((Byte *compr, uLong *comprLen));
+void test_sync OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate OF((Byte *compr, uLong comprLen));
+void test_dict_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ uLong len = (uLong)strlen(hello)+1;
+
+ err = compress(compr, &comprLen, (const Bytef*)hello, len);
+ CHECK_ERR(err, "compress");
+
+ strcpy((char*)uncompr, "garbage");
+
+ err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+ CHECK_ERR(err, "uncompress");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad uncompress\n");
+ exit(1);
+ } else {
+ printf("uncompress(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(fname, uncompr, uncomprLen)
+ const char *fname; /* compressed file name */
+ Byte *uncompr;
+ uLong uncomprLen;
+{
+#ifdef NO_GZCOMPRESS
+ fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
+#else
+ int err;
+ int len = (int)strlen(hello)+1;
+ gzFile file;
+ z_off_t pos;
+
+ file = gzopen(fname, "wb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+ gzputc(file, 'h');
+ if (gzputs(file, "ello") != 4) {
+ fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (gzprintf(file, ", %s!", "hello") != 8) {
+ fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+ gzclose(file);
+
+ file = gzopen(fname, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+ strcpy((char*)uncompr, "garbage");
+
+ if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
+ fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+ exit(1);
+ } else {
+ printf("gzread(): %s\n", (char*)uncompr);
+ }
+
+ pos = gzseek(file, -8L, SEEK_CUR);
+ if (pos != 6 || gztell(file) != pos) {
+ fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+ (long)pos, (long)gztell(file));
+ exit(1);
+ }
+
+ if (gzgetc(file) != ' ') {
+ fprintf(stderr, "gzgetc error\n");
+ exit(1);
+ }
+
+ if (gzungetc(' ', file) != ' ') {
+ fprintf(stderr, "gzungetc error\n");
+ exit(1);
+ }
+
+ gzgets(file, (char*)uncompr, (int)uncomprLen);
+ if (strlen((char*)uncompr) != 7) { /* " hello!" */
+ fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello + 6)) {
+ fprintf(stderr, "bad gzgets after gzseek\n");
+ exit(1);
+ } else {
+ printf("gzgets() after gzseek: %s\n", (char*)uncompr);
+ }
+
+ gzclose(file);
+#endif
+}
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ uLong len = (uLong)strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+
+ while (c_stream.total_in != len && c_stream.total_out < comprLen) {
+ c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ }
+ /* Finish the stream, still forcing small buffers: */
+ for (;;) {
+ c_stream.avail_out = 1;
+ err = deflate(&c_stream, Z_FINISH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "deflate");
+ }
+
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 0;
+ d_stream.next_out = uncompr;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+ d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate\n");
+ exit(1);
+ } else {
+ printf("inflate(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_SPEED);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ /* At this point, uncompr is still mostly zeroes, so it should compress
+ * very well:
+ */
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ if (c_stream.avail_in != 0) {
+ fprintf(stderr, "deflate not greedy\n");
+ exit(1);
+ }
+
+ /* Feed in already compressed data and switch to no compression: */
+ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ c_stream.next_in = compr;
+ c_stream.avail_in = (uInt)comprLen/2;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ /* Switch back to compressing mode: */
+ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ for (;;) {
+ d_stream.next_out = uncompr; /* discard the output */
+ d_stream.avail_out = (uInt)uncomprLen;
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "large inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+ fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+ exit(1);
+ } else {
+ printf("large_inflate(): OK\n");
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+ Byte *compr;
+ uLong *comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ uInt len = (uInt)strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+ c_stream.avail_in = 3;
+ c_stream.avail_out = (uInt)*comprLen;
+ err = deflate(&c_stream, Z_FULL_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ compr[3]++; /* force an error in first compressed block */
+ c_stream.avail_in = len - 3;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ CHECK_ERR(err, "deflate");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+
+ *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 2; /* just read the zlib header */
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ inflate(&d_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "inflate");
+
+ d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
+ err = inflateSync(&d_stream); /* but skip the damaged part */
+ CHECK_ERR(err, "inflateSync");
+
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_DATA_ERROR) {
+ fprintf(stderr, "inflate should report DATA_ERROR\n");
+ /* Because of incorrect adler32 */
+ exit(1);
+ }
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ err = deflateSetDictionary(&c_stream,
+ (const Bytef*)dictionary, sizeof(dictionary));
+ CHECK_ERR(err, "deflateSetDictionary");
+
+ dictId = c_stream.adler;
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.avail_in = (uInt)strlen(hello)+1;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ for (;;) {
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ if (err == Z_NEED_DICT) {
+ if (d_stream.adler != dictId) {
+ fprintf(stderr, "unexpected dictionary");
+ exit(1);
+ }
+ err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+ sizeof(dictionary));
+ }
+ CHECK_ERR(err, "inflate with dict");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate with dict\n");
+ exit(1);
+ } else {
+ printf("inflate with dictionary: %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Usage: example [output.gz [input.gz]]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ Byte *compr, *uncompr;
+ uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+ uLong uncomprLen = comprLen;
+ static const char* myVersion = ZLIB_VERSION;
+
+ if (zlibVersion()[0] != myVersion[0]) {
+ fprintf(stderr, "incompatible zlib version\n");
+ exit(1);
+
+ } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+ fprintf(stderr, "warning: different zlib version\n");
+ }
+
+ printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
+ ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
+
+ compr = (Byte*)calloc((uInt)comprLen, 1);
+ uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
+ /* compr and uncompr are cleared to avoid reading uninitialized
+ * data and to ensure that uncompr compresses well.
+ */
+ if (compr == Z_NULL || uncompr == Z_NULL) {
+ printf("out of memory\n");
+ exit(1);
+ }
+ test_compress(compr, comprLen, uncompr, uncomprLen);
+
+ test_gzio((argc > 1 ? argv[1] : TESTFILE),
+ uncompr, uncomprLen);
+
+ test_deflate(compr, comprLen);
+ test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_flush(compr, &comprLen);
+ test_sync(compr, comprLen, uncompr, uncomprLen);
+ comprLen = uncomprLen;
+
+ test_dict_deflate(compr, comprLen);
+ test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ free(compr);
+ free(uncompr);
+
+ return 0;
+}
diff --git a/libmariadb/external/zlib/examples/README.examples b/libmariadb/external/zlib/examples/README.examples
new file mode 100644
index 00000000..56a31714
--- /dev/null
+++ b/libmariadb/external/zlib/examples/README.examples
@@ -0,0 +1,49 @@
+This directory contains examples of the use of zlib and other relevant
+programs and documentation.
+
+enough.c
+ calculation and justification of ENOUGH parameter in inftrees.h
+ - calculates the maximum table space used in inflate tree
+ construction over all possible Huffman codes
+
+fitblk.c
+ compress just enough input to nearly fill a requested output size
+ - zlib isn't designed to do this, but fitblk does it anyway
+
+gun.c
+ uncompress a gzip file
+ - illustrates the use of inflateBack() for high speed file-to-file
+ decompression using call-back functions
+ - is approximately twice as fast as gzip -d
+ - also provides Unix uncompress functionality, again twice as fast
+
+gzappend.c
+ append to a gzip file
+ - illustrates the use of the Z_BLOCK flush parameter for inflate()
+ - illustrates the use of deflatePrime() to start at any bit
+
+gzjoin.c
+ join gzip files without recalculating the crc or recompressing
+ - illustrates the use of the Z_BLOCK flush parameter for inflate()
+ - illustrates the use of crc32_combine()
+
+gzlog.c
+gzlog.h
+ efficiently and robustly maintain a message log file in gzip format
+ - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(),
+ and deflateSetDictionary()
+ - illustrates use of a gzip header extra field
+
+zlib_how.html
+ painfully comprehensive description of zpipe.c (see below)
+ - describes in excruciating detail the use of deflate() and inflate()
+
+zpipe.c
+ reads and writes zlib streams from stdin to stdout
+ - illustrates the proper use of deflate() and inflate()
+ - deeply commented in zlib_how.html (see above)
+
+zran.c
+ index a zlib or gzip stream and randomly access it
+ - illustrates the use of Z_BLOCK, inflatePrime(), and
+ inflateSetDictionary() to provide random access
diff --git a/libmariadb/external/zlib/examples/enough.c b/libmariadb/external/zlib/examples/enough.c
new file mode 100644
index 00000000..b9911443
--- /dev/null
+++ b/libmariadb/external/zlib/examples/enough.c
@@ -0,0 +1,572 @@
+/* enough.c -- determine the maximum size of inflate's Huffman code tables over
+ * all possible valid and complete Huffman codes, subject to a length limit.
+ * Copyright (C) 2007, 2008, 2012 Mark Adler
+ * Version 1.4 18 August 2012 Mark Adler
+ */
+
+/* Version history:
+ 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4)
+ 1.1 4 Jan 2007 Use faster incremental table usage computation
+ Prune examine() search on previously visited states
+ 1.2 5 Jan 2007 Comments clean up
+ As inflate does, decrease root for short codes
+ Refuse cases where inflate would increase root
+ 1.3 17 Feb 2008 Add argument for initial root table size
+ Fix bug for initial root table size == max - 1
+ Use a macro to compute the history index
+ 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!)
+ Clean up comparisons of different types
+ Clean up code indentation
+ */
+
+/*
+ Examine all possible Huffman codes for a given number of symbols and a
+ maximum code length in bits to determine the maximum table size for zilb's
+ inflate. Only complete Huffman codes are counted.
+
+ Two codes are considered distinct if the vectors of the number of codes per
+ length are not identical. So permutations of the symbol assignments result
+ in the same code for the counting, as do permutations of the assignments of
+ the bit values to the codes (i.e. only canonical codes are counted).
+
+ We build a code from shorter to longer lengths, determining how many symbols
+ are coded at each length. At each step, we have how many symbols remain to
+ be coded, what the last code length used was, and how many bit patterns of
+ that length remain unused. Then we add one to the code length and double the
+ number of unused patterns to graduate to the next code length. We then
+ assign all portions of the remaining symbols to that code length that
+ preserve the properties of a correct and eventually complete code. Those
+ properties are: we cannot use more bit patterns than are available; and when
+ all the symbols are used, there are exactly zero possible bit patterns
+ remaining.
+
+ The inflate Huffman decoding algorithm uses two-level lookup tables for
+ speed. There is a single first-level table to decode codes up to root bits
+ in length (root == 9 in the current inflate implementation). The table
+ has 1 << root entries and is indexed by the next root bits of input. Codes
+ shorter than root bits have replicated table entries, so that the correct
+ entry is pointed to regardless of the bits that follow the short code. If
+ the code is longer than root bits, then the table entry points to a second-
+ level table. The size of that table is determined by the longest code with
+ that root-bit prefix. If that longest code has length len, then the table
+ has size 1 << (len - root), to index the remaining bits in that set of
+ codes. Each subsequent root-bit prefix then has its own sub-table. The
+ total number of table entries required by the code is calculated
+ incrementally as the number of codes at each bit length is populated. When
+ all of the codes are shorter than root bits, then root is reduced to the
+ longest code length, resulting in a single, smaller, one-level table.
+
+ The inflate algorithm also provides for small values of root (relative to
+ the log2 of the number of symbols), where the shortest code has more bits
+ than root. In that case, root is increased to the length of the shortest
+ code. This program, by design, does not handle that case, so it is verified
+ that the number of symbols is less than 2^(root + 1).
+
+ In order to speed up the examination (by about ten orders of magnitude for
+ the default arguments), the intermediate states in the build-up of a code
+ are remembered and previously visited branches are pruned. The memory
+ required for this will increase rapidly with the total number of symbols and
+ the maximum code length in bits. However this is a very small price to pay
+ for the vast speedup.
+
+ First, all of the possible Huffman codes are counted, and reachable
+ intermediate states are noted by a non-zero count in a saved-results array.
+ Second, the intermediate states that lead to (root + 1) bit or longer codes
+ are used to look at all sub-codes from those junctures for their inflate
+ memory usage. (The amount of memory used is not affected by the number of
+ codes of root bits or less in length.) Third, the visited states in the
+ construction of those sub-codes and the associated calculation of the table
+ size is recalled in order to avoid recalculating from the same juncture.
+ Beginning the code examination at (root + 1) bit codes, which is enabled by
+ identifying the reachable nodes, accounts for about six of the orders of
+ magnitude of improvement for the default arguments. About another four
+ orders of magnitude come from not revisiting previous states. Out of
+ approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes
+ need to be examined to cover all of the possible table memory usage cases
+ for the default arguments of 286 symbols limited to 15-bit codes.
+
+ Note that an unsigned long long type is used for counting. It is quite easy
+ to exceed the capacity of an eight-byte integer with a large number of
+ symbols and a large maximum code length, so multiple-precision arithmetic
+ would need to replace the unsigned long long arithmetic in that case. This
+ program will abort if an overflow occurs. The big_t type identifies where
+ the counting takes place.
+
+ An unsigned long long type is also used for calculating the number of
+ possible codes remaining at the maximum length. This limits the maximum
+ code length to the number of bits in a long long minus the number of bits
+ needed to represent the symbols in a flat code. The code_t type identifies
+ where the bit pattern counting takes place.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define local static
+
+/* special data types */
+typedef unsigned long long big_t; /* type for code counting */
+typedef unsigned long long code_t; /* type for bit pattern counting */
+struct tab { /* type for been here check */
+ size_t len; /* length of bit vector in char's */
+ char *vec; /* allocated bit vector */
+};
+
+/* The array for saving results, num[], is indexed with this triplet:
+
+ syms: number of symbols remaining to code
+ left: number of available bit patterns at length len
+ len: number of bits in the codes currently being assigned
+
+ Those indices are constrained thusly when saving results:
+
+ syms: 3..totsym (totsym == total symbols to code)
+ left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6)
+ len: 1..max - 1 (max == maximum code length in bits)
+
+ syms == 2 is not saved since that immediately leads to a single code. left
+ must be even, since it represents the number of available bit patterns at
+ the current length, which is double the number at the previous length.
+ left ends at syms-1 since left == syms immediately results in a single code.
+ (left > sym is not allowed since that would result in an incomplete code.)
+ len is less than max, since the code completes immediately when len == max.
+
+ The offset into the array is calculated for the three indices with the
+ first one (syms) being outermost, and the last one (len) being innermost.
+ We build the array with length max-1 lists for the len index, with syms-3
+ of those for each symbol. There are totsym-2 of those, with each one
+ varying in length as a function of sym. See the calculation of index in
+ count() for the index, and the calculation of size in main() for the size
+ of the array.
+
+ For the deflate example of 286 symbols limited to 15-bit codes, the array
+ has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than
+ half of the space allocated for saved results is actually used -- not all
+ possible triplets are reached in the generation of valid Huffman codes.
+ */
+
+/* The array for tracking visited states, done[], is itself indexed identically
+ to the num[] array as described above for the (syms, left, len) triplet.
+ Each element in the array is further indexed by the (mem, rem) doublet,
+ where mem is the amount of inflate table space used so far, and rem is the
+ remaining unused entries in the current inflate sub-table. Each indexed
+ element is simply one bit indicating whether the state has been visited or
+ not. Since the ranges for mem and rem are not known a priori, each bit
+ vector is of a variable size, and grows as needed to accommodate the visited
+ states. mem and rem are used to calculate a single index in a triangular
+ array. Since the range of mem is expected in the default case to be about
+ ten times larger than the range of rem, the array is skewed to reduce the
+ memory usage, with eight times the range for mem than for rem. See the
+ calculations for offset and bit in beenhere() for the details.
+
+ For the deflate example of 286 symbols limited to 15-bit codes, the bit
+ vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[]
+ array itself.
+ */
+
+/* Globals to avoid propagating constants or constant pointers recursively */
+local int max; /* maximum allowed bit length for the codes */
+local int root; /* size of base code table in bits */
+local int large; /* largest code table so far */
+local size_t size; /* number of elements in num and done */
+local int *code; /* number of symbols assigned to each bit length */
+local big_t *num; /* saved results array for code counting */
+local struct tab *done; /* states already evaluated array */
+
+/* Index function for num[] and done[] */
+#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1)
+
+/* Free allocated space. Uses globals code, num, and done. */
+local void cleanup(void)
+{
+ size_t n;
+
+ if (done != NULL) {
+ for (n = 0; n < size; n++)
+ if (done[n].len)
+ free(done[n].vec);
+ free(done);
+ }
+ if (num != NULL)
+ free(num);
+ if (code != NULL)
+ free(code);
+}
+
+/* Return the number of possible Huffman codes using bit patterns of lengths
+ len through max inclusive, coding syms symbols, with left bit patterns of
+ length len unused -- return -1 if there is an overflow in the counting.
+ Keep a record of previous results in num to prevent repeating the same
+ calculation. Uses the globals max and num. */
+local big_t count(int syms, int len, int left)
+{
+ big_t sum; /* number of possible codes from this juncture */
+ big_t got; /* value returned from count() */
+ int least; /* least number of syms to use at this juncture */
+ int most; /* most number of syms to use at this juncture */
+ int use; /* number of bit patterns to use in next call */
+ size_t index; /* index of this case in *num */
+
+ /* see if only one possible code */
+ if (syms == left)
+ return 1;
+
+ /* note and verify the expected state */
+ assert(syms > left && left > 0 && len < max);
+
+ /* see if we've done this one already */
+ index = INDEX(syms, left, len);
+ got = num[index];
+ if (got)
+ return got; /* we have -- return the saved result */
+
+ /* we need to use at least this many bit patterns so that the code won't be
+ incomplete at the next length (more bit patterns than symbols) */
+ least = (left << 1) - syms;
+ if (least < 0)
+ least = 0;
+
+ /* we can use at most this many bit patterns, lest there not be enough
+ available for the remaining symbols at the maximum length (if there were
+ no limit to the code length, this would become: most = left - 1) */
+ most = (((code_t)left << (max - len)) - syms) /
+ (((code_t)1 << (max - len)) - 1);
+
+ /* count all possible codes from this juncture and add them up */
+ sum = 0;
+ for (use = least; use <= most; use++) {
+ got = count(syms - use, len + 1, (left - use) << 1);
+ sum += got;
+ if (got == (big_t)0 - 1 || sum < got) /* overflow */
+ return (big_t)0 - 1;
+ }
+
+ /* verify that all recursive calls are productive */
+ assert(sum != 0);
+
+ /* save the result and return it */
+ num[index] = sum;
+ return sum;
+}
+
+/* Return true if we've been here before, set to true if not. Set a bit in a
+ bit vector to indicate visiting this state. Each (syms,len,left) state
+ has a variable size bit vector indexed by (mem,rem). The bit vector is
+ lengthened if needed to allow setting the (mem,rem) bit. */
+local int beenhere(int syms, int len, int left, int mem, int rem)
+{
+ size_t index; /* index for this state's bit vector */
+ size_t offset; /* offset in this state's bit vector */
+ int bit; /* mask for this state's bit */
+ size_t length; /* length of the bit vector in bytes */
+ char *vector; /* new or enlarged bit vector */
+
+ /* point to vector for (syms,left,len), bit in vector for (mem,rem) */
+ index = INDEX(syms, left, len);
+ mem -= 1 << root;
+ offset = (mem >> 3) + rem;
+ offset = ((offset * (offset + 1)) >> 1) + rem;
+ bit = 1 << (mem & 7);
+
+ /* see if we've been here */
+ length = done[index].len;
+ if (offset < length && (done[index].vec[offset] & bit) != 0)
+ return 1; /* done this! */
+
+ /* we haven't been here before -- set the bit to show we have now */
+
+ /* see if we need to lengthen the vector in order to set the bit */
+ if (length <= offset) {
+ /* if we have one already, enlarge it, zero out the appended space */
+ if (length) {
+ do {
+ length <<= 1;
+ } while (length <= offset);
+ vector = realloc(done[index].vec, length);
+ if (vector != NULL)
+ memset(vector + done[index].len, 0, length - done[index].len);
+ }
+
+ /* otherwise we need to make a new vector and zero it out */
+ else {
+ length = 1 << (len - root);
+ while (length <= offset)
+ length <<= 1;
+ vector = calloc(length, sizeof(char));
+ }
+
+ /* in either case, bail if we can't get the memory */
+ if (vector == NULL) {
+ fputs("abort: unable to allocate enough memory\n", stderr);
+ cleanup();
+ exit(1);
+ }
+
+ /* install the new vector */
+ done[index].len = length;
+ done[index].vec = vector;
+ }
+
+ /* set the bit */
+ done[index].vec[offset] |= bit;
+ return 0;
+}
+
+/* Examine all possible codes from the given node (syms, len, left). Compute
+ the amount of memory required to build inflate's decoding tables, where the
+ number of code structures used so far is mem, and the number remaining in
+ the current sub-table is rem. Uses the globals max, code, root, large, and
+ done. */
+local void examine(int syms, int len, int left, int mem, int rem)
+{
+ int least; /* least number of syms to use at this juncture */
+ int most; /* most number of syms to use at this juncture */
+ int use; /* number of bit patterns to use in next call */
+
+ /* see if we have a complete code */
+ if (syms == left) {
+ /* set the last code entry */
+ code[len] = left;
+
+ /* complete computation of memory used by this code */
+ while (rem < left) {
+ left -= rem;
+ rem = 1 << (len - root);
+ mem += rem;
+ }
+ assert(rem == left);
+
+ /* if this is a new maximum, show the entries used and the sub-code */
+ if (mem > large) {
+ large = mem;
+ printf("max %d: ", mem);
+ for (use = root + 1; use <= max; use++)
+ if (code[use])
+ printf("%d[%d] ", code[use], use);
+ putchar('\n');
+ fflush(stdout);
+ }
+
+ /* remove entries as we drop back down in the recursion */
+ code[len] = 0;
+ return;
+ }
+
+ /* prune the tree if we can */
+ if (beenhere(syms, len, left, mem, rem))
+ return;
+
+ /* we need to use at least this many bit patterns so that the code won't be
+ incomplete at the next length (more bit patterns than symbols) */
+ least = (left << 1) - syms;
+ if (least < 0)
+ least = 0;
+
+ /* we can use at most this many bit patterns, lest there not be enough
+ available for the remaining symbols at the maximum length (if there were
+ no limit to the code length, this would become: most = left - 1) */
+ most = (((code_t)left << (max - len)) - syms) /
+ (((code_t)1 << (max - len)) - 1);
+
+ /* occupy least table spaces, creating new sub-tables as needed */
+ use = least;
+ while (rem < use) {
+ use -= rem;
+ rem = 1 << (len - root);
+ mem += rem;
+ }
+ rem -= use;
+
+ /* examine codes from here, updating table space as we go */
+ for (use = least; use <= most; use++) {
+ code[len] = use;
+ examine(syms - use, len + 1, (left - use) << 1,
+ mem + (rem ? 1 << (len - root) : 0), rem << 1);
+ if (rem == 0) {
+ rem = 1 << (len - root);
+ mem += rem;
+ }
+ rem--;
+ }
+
+ /* remove entries as we drop back down in the recursion */
+ code[len] = 0;
+}
+
+/* Look at all sub-codes starting with root + 1 bits. Look at only the valid
+ intermediate code states (syms, left, len). For each completed code,
+ calculate the amount of memory required by inflate to build the decoding
+ tables. Find the maximum amount of memory required and show the code that
+ requires that maximum. Uses the globals max, root, and num. */
+local void enough(int syms)
+{
+ int n; /* number of remaing symbols for this node */
+ int left; /* number of unused bit patterns at this length */
+ size_t index; /* index of this case in *num */
+
+ /* clear code */
+ for (n = 0; n <= max; n++)
+ code[n] = 0;
+
+ /* look at all (root + 1) bit and longer codes */
+ large = 1 << root; /* base table */
+ if (root < max) /* otherwise, there's only a base table */
+ for (n = 3; n <= syms; n++)
+ for (left = 2; left < n; left += 2)
+ {
+ /* look at all reachable (root + 1) bit nodes, and the
+ resulting codes (complete at root + 2 or more) */
+ index = INDEX(n, left, root + 1);
+ if (root + 1 < max && num[index]) /* reachable node */
+ examine(n, root + 1, left, 1 << root, 0);
+
+ /* also look at root bit codes with completions at root + 1
+ bits (not saved in num, since complete), just in case */
+ if (num[index - 1] && n <= left << 1)
+ examine((n - left) << 1, root + 1, (n - left) << 1,
+ 1 << root, 0);
+ }
+
+ /* done */
+ printf("done: maximum of %d table entries\n", large);
+}
+
+/*
+ Examine and show the total number of possible Huffman codes for a given
+ maximum number of symbols, initial root table size, and maximum code length
+ in bits -- those are the command arguments in that order. The default
+ values are 286, 9, and 15 respectively, for the deflate literal/length code.
+ The possible codes are counted for each number of coded symbols from two to
+ the maximum. The counts for each of those and the total number of codes are
+ shown. The maximum number of inflate table entires is then calculated
+ across all possible codes. Each new maximum number of table entries and the
+ associated sub-code (starting at root + 1 == 10 bits) is shown.
+
+ To count and examine Huffman codes that are not length-limited, provide a
+ maximum length equal to the number of symbols minus one.
+
+ For the deflate literal/length code, use "enough". For the deflate distance
+ code, use "enough 30 6".
+
+ This uses the %llu printf format to print big_t numbers, which assumes that
+ big_t is an unsigned long long. If the big_t type is changed (for example
+ to a multiple precision type), the method of printing will also need to be
+ updated.
+ */
+int main(int argc, char **argv)
+{
+ int syms; /* total number of symbols to code */
+ int n; /* number of symbols to code for this run */
+ big_t got; /* return value of count() */
+ big_t sum; /* accumulated number of codes over n */
+ code_t word; /* for counting bits in code_t */
+
+ /* set up globals for cleanup() */
+ code = NULL;
+ num = NULL;
+ done = NULL;
+
+ /* get arguments -- default to the deflate literal/length code */
+ syms = 286;
+ root = 9;
+ max = 15;
+ if (argc > 1) {
+ syms = atoi(argv[1]);
+ if (argc > 2) {
+ root = atoi(argv[2]);
+ if (argc > 3)
+ max = atoi(argv[3]);
+ }
+ }
+ if (argc > 4 || syms < 2 || root < 1 || max < 1) {
+ fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n",
+ stderr);
+ return 1;
+ }
+
+ /* if not restricting the code length, the longest is syms - 1 */
+ if (max > syms - 1)
+ max = syms - 1;
+
+ /* determine the number of bits in a code_t */
+ for (n = 0, word = 1; word; n++, word <<= 1)
+ ;
+
+ /* make sure that the calculation of most will not overflow */
+ if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) {
+ fputs("abort: code length too long for internal types\n", stderr);
+ return 1;
+ }
+
+ /* reject impossible code requests */
+ if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) {
+ fprintf(stderr, "%d symbols cannot be coded in %d bits\n",
+ syms, max);
+ return 1;
+ }
+
+ /* allocate code vector */
+ code = calloc(max + 1, sizeof(int));
+ if (code == NULL) {
+ fputs("abort: unable to allocate enough memory\n", stderr);
+ return 1;
+ }
+
+ /* determine size of saved results array, checking for overflows,
+ allocate and clear the array (set all to zero with calloc()) */
+ if (syms == 2) /* iff max == 1 */
+ num = NULL; /* won't be saving any results */
+ else {
+ size = syms >> 1;
+ if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) ||
+ (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) ||
+ (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) ||
+ (num = calloc(size, sizeof(big_t))) == NULL) {
+ fputs("abort: unable to allocate enough memory\n", stderr);
+ cleanup();
+ return 1;
+ }
+ }
+
+ /* count possible codes for all numbers of symbols, add up counts */
+ sum = 0;
+ for (n = 2; n <= syms; n++) {
+ got = count(n, 1, 2);
+ sum += got;
+ if (got == (big_t)0 - 1 || sum < got) { /* overflow */
+ fputs("abort: can't count that high!\n", stderr);
+ cleanup();
+ return 1;
+ }
+ printf("%llu %d-codes\n", got, n);
+ }
+ printf("%llu total codes for 2 to %d symbols", sum, syms);
+ if (max < syms - 1)
+ printf(" (%d-bit length limit)\n", max);
+ else
+ puts(" (no length limit)");
+
+ /* allocate and clear done array for beenhere() */
+ if (syms == 2)
+ done = NULL;
+ else if (size > ((size_t)0 - 1) / sizeof(struct tab) ||
+ (done = calloc(size, sizeof(struct tab))) == NULL) {
+ fputs("abort: unable to allocate enough memory\n", stderr);
+ cleanup();
+ return 1;
+ }
+
+ /* find and show maximum inflate table usage */
+ if (root > max) /* reduce root to max length */
+ root = max;
+ if ((code_t)syms < ((code_t)1 << (root + 1)))
+ enough(syms);
+ else
+ puts("cannot handle minimum code lengths > root");
+
+ /* done */
+ cleanup();
+ return 0;
+}
diff --git a/libmariadb/external/zlib/examples/fitblk.c b/libmariadb/external/zlib/examples/fitblk.c
new file mode 100644
index 00000000..c61de5c9
--- /dev/null
+++ b/libmariadb/external/zlib/examples/fitblk.c
@@ -0,0 +1,233 @@
+/* fitblk.c: example of fitting compressed output to a specified size
+ Not copyrighted -- provided to the public domain
+ Version 1.1 25 November 2004 Mark Adler */
+
+/* Version history:
+ 1.0 24 Nov 2004 First version
+ 1.1 25 Nov 2004 Change deflateInit2() to deflateInit()
+ Use fixed-size, stack-allocated raw buffers
+ Simplify code moving compression to subroutines
+ Use assert() for internal errors
+ Add detailed description of approach
+ */
+
+/* Approach to just fitting a requested compressed size:
+
+ fitblk performs three compression passes on a portion of the input
+ data in order to determine how much of that input will compress to
+ nearly the requested output block size. The first pass generates
+ enough deflate blocks to produce output to fill the requested
+ output size plus a specfied excess amount (see the EXCESS define
+ below). The last deflate block may go quite a bit past that, but
+ is discarded. The second pass decompresses and recompresses just
+ the compressed data that fit in the requested plus excess sized
+ buffer. The deflate process is terminated after that amount of
+ input, which is less than the amount consumed on the first pass.
+ The last deflate block of the result will be of a comparable size
+ to the final product, so that the header for that deflate block and
+ the compression ratio for that block will be about the same as in
+ the final product. The third compression pass decompresses the
+ result of the second step, but only the compressed data up to the
+ requested size minus an amount to allow the compressed stream to
+ complete (see the MARGIN define below). That will result in a
+ final compressed stream whose length is less than or equal to the
+ requested size. Assuming sufficient input and a requested size
+ greater than a few hundred bytes, the shortfall will typically be
+ less than ten bytes.
+
+ If the input is short enough that the first compression completes
+ before filling the requested output size, then that compressed
+ stream is return with no recompression.
+
+ EXCESS is chosen to be just greater than the shortfall seen in a
+ two pass approach similar to the above. That shortfall is due to
+ the last deflate block compressing more efficiently with a smaller
+ header on the second pass. EXCESS is set to be large enough so
+ that there is enough uncompressed data for the second pass to fill
+ out the requested size, and small enough so that the final deflate
+ block of the second pass will be close in size to the final deflate
+ block of the third and final pass. MARGIN is chosen to be just
+ large enough to assure that the final compression has enough room
+ to complete in all cases.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "zlib.h"
+
+#define local static
+
+/* print nastygram and leave */
+local void quit(char *why)
+{
+ fprintf(stderr, "fitblk abort: %s\n", why);
+ exit(1);
+}
+
+#define RAWLEN 4096 /* intermediate uncompressed buffer size */
+
+/* compress from file to def until provided buffer is full or end of
+ input reached; return last deflate() return value, or Z_ERRNO if
+ there was read error on the file */
+local int partcompress(FILE *in, z_streamp def)
+{
+ int ret, flush;
+ unsigned char raw[RAWLEN];
+
+ flush = Z_NO_FLUSH;
+ do {
+ def->avail_in = fread(raw, 1, RAWLEN, in);
+ if (ferror(in))
+ return Z_ERRNO;
+ def->next_in = raw;
+ if (feof(in))
+ flush = Z_FINISH;
+ ret = deflate(def, flush);
+ assert(ret != Z_STREAM_ERROR);
+ } while (def->avail_out != 0 && flush == Z_NO_FLUSH);
+ return ret;
+}
+
+/* recompress from inf's input to def's output; the input for inf and
+ the output for def are set in those structures before calling;
+ return last deflate() return value, or Z_MEM_ERROR if inflate()
+ was not able to allocate enough memory when it needed to */
+local int recompress(z_streamp inf, z_streamp def)
+{
+ int ret, flush;
+ unsigned char raw[RAWLEN];
+
+ flush = Z_NO_FLUSH;
+ do {
+ /* decompress */
+ inf->avail_out = RAWLEN;
+ inf->next_out = raw;
+ ret = inflate(inf, Z_NO_FLUSH);
+ assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&
+ ret != Z_NEED_DICT);
+ if (ret == Z_MEM_ERROR)
+ return ret;
+
+ /* compress what was decompresed until done or no room */
+ def->avail_in = RAWLEN - inf->avail_out;
+ def->next_in = raw;
+ if (inf->avail_out != 0)
+ flush = Z_FINISH;
+ ret = deflate(def, flush);
+ assert(ret != Z_STREAM_ERROR);
+ } while (ret != Z_STREAM_END && def->avail_out != 0);
+ return ret;
+}
+
+#define EXCESS 256 /* empirically determined stream overage */
+#define MARGIN 8 /* amount to back off for completion */
+
+/* compress from stdin to fixed-size block on stdout */
+int main(int argc, char **argv)
+{
+ int ret; /* return code */
+ unsigned size; /* requested fixed output block size */
+ unsigned have; /* bytes written by deflate() call */
+ unsigned char *blk; /* intermediate and final stream */
+ unsigned char *tmp; /* close to desired size stream */
+ z_stream def, inf; /* zlib deflate and inflate states */
+
+ /* get requested output size */
+ if (argc != 2)
+ quit("need one argument: size of output block");
+ ret = strtol(argv[1], argv + 1, 10);
+ if (argv[1][0] != 0)
+ quit("argument must be a number");
+ if (ret < 8) /* 8 is minimum zlib stream size */
+ quit("need positive size of 8 or greater");
+ size = (unsigned)ret;
+
+ /* allocate memory for buffers and compression engine */
+ blk = malloc(size + EXCESS);
+ def.zalloc = Z_NULL;
+ def.zfree = Z_NULL;
+ def.opaque = Z_NULL;
+ ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);
+ if (ret != Z_OK || blk == NULL)
+ quit("out of memory");
+
+ /* compress from stdin until output full, or no more input */
+ def.avail_out = size + EXCESS;
+ def.next_out = blk;
+ ret = partcompress(stdin, &def);
+ if (ret == Z_ERRNO)
+ quit("error reading input");
+
+ /* if it all fit, then size was undersubscribed -- done! */
+ if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {
+ /* write block to stdout */
+ have = size + EXCESS - def.avail_out;
+ if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
+ quit("error writing output");
+
+ /* clean up and print results to stderr */
+ ret = deflateEnd(&def);
+ assert(ret != Z_STREAM_ERROR);
+ free(blk);
+ fprintf(stderr,
+ "%u bytes unused out of %u requested (all input)\n",
+ size - have, size);
+ return 0;
+ }
+
+ /* it didn't all fit -- set up for recompression */
+ inf.zalloc = Z_NULL;
+ inf.zfree = Z_NULL;
+ inf.opaque = Z_NULL;
+ inf.avail_in = 0;
+ inf.next_in = Z_NULL;
+ ret = inflateInit(&inf);
+ tmp = malloc(size + EXCESS);
+ if (ret != Z_OK || tmp == NULL)
+ quit("out of memory");
+ ret = deflateReset(&def);
+ assert(ret != Z_STREAM_ERROR);
+
+ /* do first recompression close to the right amount */
+ inf.avail_in = size + EXCESS;
+ inf.next_in = blk;
+ def.avail_out = size + EXCESS;
+ def.next_out = tmp;
+ ret = recompress(&inf, &def);
+ if (ret == Z_MEM_ERROR)
+ quit("out of memory");
+
+ /* set up for next reocmpression */
+ ret = inflateReset(&inf);
+ assert(ret != Z_STREAM_ERROR);
+ ret = deflateReset(&def);
+ assert(ret != Z_STREAM_ERROR);
+
+ /* do second and final recompression (third compression) */
+ inf.avail_in = size - MARGIN; /* assure stream will complete */
+ inf.next_in = tmp;
+ def.avail_out = size;
+ def.next_out = blk;
+ ret = recompress(&inf, &def);
+ if (ret == Z_MEM_ERROR)
+ quit("out of memory");
+ assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */
+
+ /* done -- write block to stdout */
+ have = size - def.avail_out;
+ if (fwrite(blk, 1, have, stdout) != have || ferror(stdout))
+ quit("error writing output");
+
+ /* clean up and print results to stderr */
+ free(tmp);
+ ret = inflateEnd(&inf);
+ assert(ret != Z_STREAM_ERROR);
+ ret = deflateEnd(&def);
+ assert(ret != Z_STREAM_ERROR);
+ free(blk);
+ fprintf(stderr,
+ "%u bytes unused out of %u requested (%lu input)\n",
+ size - have, size, def.total_in);
+ return 0;
+}
diff --git a/libmariadb/external/zlib/examples/gun.c b/libmariadb/external/zlib/examples/gun.c
new file mode 100644
index 00000000..89e484fe
--- /dev/null
+++ b/libmariadb/external/zlib/examples/gun.c
@@ -0,0 +1,702 @@
+/* gun.c -- simple gunzip to give an example of the use of inflateBack()
+ * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ Version 1.7 12 August 2012 Mark Adler */
+
+/* Version history:
+ 1.0 16 Feb 2003 First version for testing of inflateBack()
+ 1.1 21 Feb 2005 Decompress concatenated gzip streams
+ Remove use of "this" variable (C++ keyword)
+ Fix return value for in()
+ Improve allocation failure checking
+ Add typecasting for void * structures
+ Add -h option for command version and usage
+ Add a bunch of comments
+ 1.2 20 Mar 2005 Add Unix compress (LZW) decompression
+ Copy file attributes from input file to output file
+ 1.3 12 Jun 2005 Add casts for error messages [Oberhumer]
+ 1.4 8 Dec 2006 LZW decompression speed improvements
+ 1.5 9 Feb 2008 Avoid warning in latest version of gcc
+ 1.6 17 Jan 2010 Avoid signed/unsigned comparison warnings
+ 1.7 12 Aug 2012 Update for z_const usage in zlib 1.2.8
+ */
+
+/*
+ gun [ -t ] [ name ... ]
+
+ decompresses the data in the named gzip files. If no arguments are given,
+ gun will decompress from stdin to stdout. The names must end in .gz, -gz,
+ .z, -z, _z, or .Z. The uncompressed data will be written to a file name
+ with the suffix stripped. On success, the original file is deleted. On
+ failure, the output file is deleted. For most failures, the command will
+ continue to process the remaining names on the command line. A memory
+ allocation failure will abort the command. If -t is specified, then the
+ listed files or stdin will be tested as gzip files for integrity (without
+ checking for a proper suffix), no output will be written, and no files
+ will be deleted.
+
+ Like gzip, gun allows concatenated gzip streams and will decompress them,
+ writing all of the uncompressed data to the output. Unlike gzip, gun allows
+ an empty file on input, and will produce no error writing an empty output
+ file.
+
+ gun will also decompress files made by Unix compress, which uses LZW
+ compression. These files are automatically detected by virtue of their
+ magic header bytes. Since the end of Unix compress stream is marked by the
+ end-of-file, they cannot be concantenated. If a Unix compress stream is
+ encountered in an input file, it is the last stream in that file.
+
+ Like gunzip and uncompress, the file attributes of the orignal compressed
+ file are maintained in the final uncompressed file, to the extent that the
+ user permissions allow it.
+
+ On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version
+ 1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the
+ LZW decompression provided by gun is about twice as fast as the standard
+ Unix uncompress command.
+ */
+
+/* external functions and related types and constants */
+#include <stdio.h> /* fprintf() */
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h> /* strerror(), strcmp(), strlen(), memcpy() */
+#include <errno.h> /* errno */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* read(), write(), close(), chown(), unlink() */
+#include <sys/types.h>
+#include <sys/stat.h> /* stat(), chmod() */
+#include <utime.h> /* utime() */
+#include "zlib.h" /* inflateBackInit(), inflateBack(), */
+ /* inflateBackEnd(), crc32() */
+
+/* function declaration */
+#define local static
+
+/* buffer constants */
+#define SIZE 32768U /* input and output buffer sizes */
+#define PIECE 16384 /* limits i/o chunks for 16-bit int case */
+
+/* structure for infback() to pass to input function in() -- it maintains the
+ input file and a buffer of size SIZE */
+struct ind {
+ int infile;
+ unsigned char *inbuf;
+};
+
+/* Load input buffer, assumed to be empty, and return bytes loaded and a
+ pointer to them. read() is called until the buffer is full, or until it
+ returns end-of-file or error. Return 0 on error. */
+local unsigned in(void *in_desc, z_const unsigned char **buf)
+{
+ int ret;
+ unsigned len;
+ unsigned char *next;
+ struct ind *me = (struct ind *)in_desc;
+
+ next = me->inbuf;
+ *buf = next;
+ len = 0;
+ do {
+ ret = PIECE;
+ if ((unsigned)ret > SIZE - len)
+ ret = (int)(SIZE - len);
+ ret = (int)read(me->infile, next, ret);
+ if (ret == -1) {
+ len = 0;
+ break;
+ }
+ next += ret;
+ len += ret;
+ } while (ret != 0 && len < SIZE);
+ return len;
+}
+
+/* structure for infback() to pass to output function out() -- it maintains the
+ output file, a running CRC-32 check on the output and the total number of
+ bytes output, both for checking against the gzip trailer. (The length in
+ the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and
+ the output is greater than 4 GB.) */
+struct outd {
+ int outfile;
+ int check; /* true if checking crc and total */
+ unsigned long crc;
+ unsigned long total;
+};
+
+/* Write output buffer and update the CRC-32 and total bytes written. write()
+ is called until all of the output is written or an error is encountered.
+ On success out() returns 0. For a write failure, out() returns 1. If the
+ output file descriptor is -1, then nothing is written.
+ */
+local int out(void *out_desc, unsigned char *buf, unsigned len)
+{
+ int ret;
+ struct outd *me = (struct outd *)out_desc;
+
+ if (me->check) {
+ me->crc = crc32(me->crc, buf, len);
+ me->total += len;
+ }
+ if (me->outfile != -1)
+ do {
+ ret = PIECE;
+ if ((unsigned)ret > len)
+ ret = (int)len;
+ ret = (int)write(me->outfile, buf, ret);
+ if (ret == -1)
+ return 1;
+ buf += ret;
+ len -= ret;
+ } while (len != 0);
+ return 0;
+}
+
+/* next input byte macro for use inside lunpipe() and gunpipe() */
+#define NEXT() (have ? 0 : (have = in(indp, &next)), \
+ last = have ? (have--, (int)(*next++)) : -1)
+
+/* memory for gunpipe() and lunpipe() --
+ the first 256 entries of prefix[] and suffix[] are never used, could
+ have offset the index, but it's faster to waste the memory */
+unsigned char inbuf[SIZE]; /* input buffer */
+unsigned char outbuf[SIZE]; /* output buffer */
+unsigned short prefix[65536]; /* index to LZW prefix string */
+unsigned char suffix[65536]; /* one-character LZW suffix */
+unsigned char match[65280 + 2]; /* buffer for reversed match or gzip
+ 32K sliding window */
+
+/* throw out what's left in the current bits byte buffer (this is a vestigial
+ aspect of the compressed data format derived from an implementation that
+ made use of a special VAX machine instruction!) */
+#define FLUSHCODE() \
+ do { \
+ left = 0; \
+ rem = 0; \
+ if (chunk > have) { \
+ chunk -= have; \
+ have = 0; \
+ if (NEXT() == -1) \
+ break; \
+ chunk--; \
+ if (chunk > have) { \
+ chunk = have = 0; \
+ break; \
+ } \
+ } \
+ have -= chunk; \
+ next += chunk; \
+ chunk = 0; \
+ } while (0)
+
+/* Decompress a compress (LZW) file from indp to outfile. The compress magic
+ header (two bytes) has already been read and verified. There are have bytes
+ of buffered input at next. strm is used for passing error information back
+ to gunpipe().
+
+ lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of
+ file, read error, or write error (a write error indicated by strm->next_in
+ not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
+ */
+local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp,
+ int outfile, z_stream *strm)
+{
+ int last; /* last byte read by NEXT(), or -1 if EOF */
+ unsigned chunk; /* bytes left in current chunk */
+ int left; /* bits left in rem */
+ unsigned rem; /* unused bits from input */
+ int bits; /* current bits per code */
+ unsigned code; /* code, table traversal index */
+ unsigned mask; /* mask for current bits codes */
+ int max; /* maximum bits per code for this stream */
+ unsigned flags; /* compress flags, then block compress flag */
+ unsigned end; /* last valid entry in prefix/suffix tables */
+ unsigned temp; /* current code */
+ unsigned prev; /* previous code */
+ unsigned final; /* last character written for previous code */
+ unsigned stack; /* next position for reversed string */
+ unsigned outcnt; /* bytes in output buffer */
+ struct outd outd; /* output structure */
+ unsigned char *p;
+
+ /* set up output */
+ outd.outfile = outfile;
+ outd.check = 0;
+
+ /* process remainder of compress header -- a flags byte */
+ flags = NEXT();
+ if (last == -1)
+ return Z_BUF_ERROR;
+ if (flags & 0x60) {
+ strm->msg = (char *)"unknown lzw flags set";
+ return Z_DATA_ERROR;
+ }
+ max = flags & 0x1f;
+ if (max < 9 || max > 16) {
+ strm->msg = (char *)"lzw bits out of range";
+ return Z_DATA_ERROR;
+ }
+ if (max == 9) /* 9 doesn't really mean 9 */
+ max = 10;
+ flags &= 0x80; /* true if block compress */
+
+ /* clear table */
+ bits = 9;
+ mask = 0x1ff;
+ end = flags ? 256 : 255;
+
+ /* set up: get first 9-bit code, which is the first decompressed byte, but
+ don't create a table entry until the next code */
+ if (NEXT() == -1) /* no compressed data is ok */
+ return Z_OK;
+ final = prev = (unsigned)last; /* low 8 bits of code */
+ if (NEXT() == -1) /* missing a bit */
+ return Z_BUF_ERROR;
+ if (last & 1) { /* code must be < 256 */
+ strm->msg = (char *)"invalid lzw code";
+ return Z_DATA_ERROR;
+ }
+ rem = (unsigned)last >> 1; /* remaining 7 bits */
+ left = 7;
+ chunk = bits - 2; /* 7 bytes left in this chunk */
+ outbuf[0] = (unsigned char)final; /* write first decompressed byte */
+ outcnt = 1;
+
+ /* decode codes */
+ stack = 0;
+ for (;;) {
+ /* if the table will be full after this, increment the code size */
+ if (end >= mask && bits < max) {
+ FLUSHCODE();
+ bits++;
+ mask <<= 1;
+ mask++;
+ }
+
+ /* get a code of length bits */
+ if (chunk == 0) /* decrement chunk modulo bits */
+ chunk = bits;
+ code = rem; /* low bits of code */
+ if (NEXT() == -1) { /* EOF is end of compressed data */
+ /* write remaining buffered output */
+ if (outcnt && out(&outd, outbuf, outcnt)) {
+ strm->next_in = outbuf; /* signal write error */
+ return Z_BUF_ERROR;
+ }
+ return Z_OK;
+ }
+ code += (unsigned)last << left; /* middle (or high) bits of code */
+ left += 8;
+ chunk--;
+ if (bits > left) { /* need more bits */
+ if (NEXT() == -1) /* can't end in middle of code */
+ return Z_BUF_ERROR;
+ code += (unsigned)last << left; /* high bits of code */
+ left += 8;
+ chunk--;
+ }
+ code &= mask; /* mask to current code length */
+ left -= bits; /* number of unused bits */
+ rem = (unsigned)last >> (8 - left); /* unused bits from last byte */
+
+ /* process clear code (256) */
+ if (code == 256 && flags) {
+ FLUSHCODE();
+ bits = 9; /* initialize bits and mask */
+ mask = 0x1ff;
+ end = 255; /* empty table */
+ continue; /* get next code */
+ }
+
+ /* special code to reuse last match */
+ temp = code; /* save the current code */
+ if (code > end) {
+ /* Be picky on the allowed code here, and make sure that the code
+ we drop through (prev) will be a valid index so that random
+ input does not cause an exception. The code != end + 1 check is
+ empirically derived, and not checked in the original uncompress
+ code. If this ever causes a problem, that check could be safely
+ removed. Leaving this check in greatly improves gun's ability
+ to detect random or corrupted input after a compress header.
+ In any case, the prev > end check must be retained. */
+ if (code != end + 1 || prev > end) {
+ strm->msg = (char *)"invalid lzw code";
+ return Z_DATA_ERROR;
+ }
+ match[stack++] = (unsigned char)final;
+ code = prev;
+ }
+
+ /* walk through linked list to generate output in reverse order */
+ p = match + stack;
+ while (code >= 256) {
+ *p++ = suffix[code];
+ code = prefix[code];
+ }
+ stack = p - match;
+ match[stack++] = (unsigned char)code;
+ final = code;
+
+ /* link new table entry */
+ if (end < mask) {
+ end++;
+ prefix[end] = (unsigned short)prev;
+ suffix[end] = (unsigned char)final;
+ }
+
+ /* set previous code for next iteration */
+ prev = temp;
+
+ /* write output in forward order */
+ while (stack > SIZE - outcnt) {
+ while (outcnt < SIZE)
+ outbuf[outcnt++] = match[--stack];
+ if (out(&outd, outbuf, outcnt)) {
+ strm->next_in = outbuf; /* signal write error */
+ return Z_BUF_ERROR;
+ }
+ outcnt = 0;
+ }
+ p = match + stack;
+ do {
+ outbuf[outcnt++] = *--p;
+ } while (p > match);
+ stack = 0;
+
+ /* loop for next code with final and prev as the last match, rem and
+ left provide the first 0..7 bits of the next code, end is the last
+ valid table entry */
+ }
+}
+
+/* Decompress a gzip file from infile to outfile. strm is assumed to have been
+ successfully initialized with inflateBackInit(). The input file may consist
+ of a series of gzip streams, in which case all of them will be decompressed
+ to the output file. If outfile is -1, then the gzip stream(s) integrity is
+ checked and nothing is written.
+
+ The return value is a zlib error code: Z_MEM_ERROR if out of memory,
+ Z_DATA_ERROR if the header or the compressed data is invalid, or if the
+ trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends
+ prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip
+ stream) follows a valid gzip stream.
+ */
+local int gunpipe(z_stream *strm, int infile, int outfile)
+{
+ int ret, first, last;
+ unsigned have, flags, len;
+ z_const unsigned char *next = NULL;
+ struct ind ind, *indp;
+ struct outd outd;
+
+ /* setup input buffer */
+ ind.infile = infile;
+ ind.inbuf = inbuf;
+ indp = &ind;
+
+ /* decompress concatenated gzip streams */
+ have = 0; /* no input data read in yet */
+ first = 1; /* looking for first gzip header */
+ strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */
+ for (;;) {
+ /* look for the two magic header bytes for a gzip stream */
+ if (NEXT() == -1) {
+ ret = Z_OK;
+ break; /* empty gzip stream is ok */
+ }
+ if (last != 31 || (NEXT() != 139 && last != 157)) {
+ strm->msg = (char *)"incorrect header check";
+ ret = first ? Z_DATA_ERROR : Z_ERRNO;
+ break; /* not a gzip or compress header */
+ }
+ first = 0; /* next non-header is junk */
+
+ /* process a compress (LZW) file -- can't be concatenated after this */
+ if (last == 157) {
+ ret = lunpipe(have, next, indp, outfile, strm);
+ break;
+ }
+
+ /* process remainder of gzip header */
+ ret = Z_BUF_ERROR;
+ if (NEXT() != 8) { /* only deflate method allowed */
+ if (last == -1) break;
+ strm->msg = (char *)"unknown compression method";
+ ret = Z_DATA_ERROR;
+ break;
+ }
+ flags = NEXT(); /* header flags */
+ NEXT(); /* discard mod time, xflgs, os */
+ NEXT();
+ NEXT();
+ NEXT();
+ NEXT();
+ NEXT();
+ if (last == -1) break;
+ if (flags & 0xe0) {
+ strm->msg = (char *)"unknown header flags set";
+ ret = Z_DATA_ERROR;
+ break;
+ }
+ if (flags & 4) { /* extra field */
+ len = NEXT();
+ len += (unsigned)(NEXT()) << 8;
+ if (last == -1) break;
+ while (len > have) {
+ len -= have;
+ have = 0;
+ if (NEXT() == -1) break;
+ len--;
+ }
+ if (last == -1) break;
+ have -= len;
+ next += len;
+ }
+ if (flags & 8) /* file name */
+ while (NEXT() != 0 && last != -1)
+ ;
+ if (flags & 16) /* comment */
+ while (NEXT() != 0 && last != -1)
+ ;
+ if (flags & 2) { /* header crc */
+ NEXT();
+ NEXT();
+ }
+ if (last == -1) break;
+
+ /* set up output */
+ outd.outfile = outfile;
+ outd.check = 1;
+ outd.crc = crc32(0L, Z_NULL, 0);
+ outd.total = 0;
+
+ /* decompress data to output */
+ strm->next_in = next;
+ strm->avail_in = have;
+ ret = inflateBack(strm, in, indp, out, &outd);
+ if (ret != Z_STREAM_END) break;
+ next = strm->next_in;
+ have = strm->avail_in;
+ strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */
+
+ /* check trailer */
+ ret = Z_BUF_ERROR;
+ if (NEXT() != (int)(outd.crc & 0xff) ||
+ NEXT() != (int)((outd.crc >> 8) & 0xff) ||
+ NEXT() != (int)((outd.crc >> 16) & 0xff) ||
+ NEXT() != (int)((outd.crc >> 24) & 0xff)) {
+ /* crc error */
+ if (last != -1) {
+ strm->msg = (char *)"incorrect data check";
+ ret = Z_DATA_ERROR;
+ }
+ break;
+ }
+ if (NEXT() != (int)(outd.total & 0xff) ||
+ NEXT() != (int)((outd.total >> 8) & 0xff) ||
+ NEXT() != (int)((outd.total >> 16) & 0xff) ||
+ NEXT() != (int)((outd.total >> 24) & 0xff)) {
+ /* length error */
+ if (last != -1) {
+ strm->msg = (char *)"incorrect length check";
+ ret = Z_DATA_ERROR;
+ }
+ break;
+ }
+
+ /* go back and look for another gzip stream */
+ }
+
+ /* clean up and return */
+ return ret;
+}
+
+/* Copy file attributes, from -> to, as best we can. This is best effort, so
+ no errors are reported. The mode bits, including suid, sgid, and the sticky
+ bit are copied (if allowed), the owner's user id and group id are copied
+ (again if allowed), and the access and modify times are copied. */
+local void copymeta(char *from, char *to)
+{
+ struct stat was;
+ struct utimbuf when;
+
+ /* get all of from's Unix meta data, return if not a regular file */
+ if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
+ return;
+
+ /* set to's mode bits, ignore errors */
+ (void)chmod(to, was.st_mode & 07777);
+
+ /* copy owner's user and group, ignore errors */
+ (void)chown(to, was.st_uid, was.st_gid);
+
+ /* copy access and modify times, ignore errors */
+ when.actime = was.st_atime;
+ when.modtime = was.st_mtime;
+ (void)utime(to, &when);
+}
+
+/* Decompress the file inname to the file outnname, of if test is true, just
+ decompress without writing and check the gzip trailer for integrity. If
+ inname is NULL or an empty string, read from stdin. If outname is NULL or
+ an empty string, write to stdout. strm is a pre-initialized inflateBack
+ structure. When appropriate, copy the file attributes from inname to
+ outname.
+
+ gunzip() returns 1 if there is an out-of-memory error or an unexpected
+ return code from gunpipe(). Otherwise it returns 0.
+ */
+local int gunzip(z_stream *strm, char *inname, char *outname, int test)
+{
+ int ret;
+ int infile, outfile;
+
+ /* open files */
+ if (inname == NULL || *inname == 0) {
+ inname = "-";
+ infile = 0; /* stdin */
+ }
+ else {
+ infile = open(inname, O_RDONLY, 0);
+ if (infile == -1) {
+ fprintf(stderr, "gun cannot open %s\n", inname);
+ return 0;
+ }
+ }
+ if (test)
+ outfile = -1;
+ else if (outname == NULL || *outname == 0) {
+ outname = "-";
+ outfile = 1; /* stdout */
+ }
+ else {
+ outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (outfile == -1) {
+ close(infile);
+ fprintf(stderr, "gun cannot create %s\n", outname);
+ return 0;
+ }
+ }
+ errno = 0;
+
+ /* decompress */
+ ret = gunpipe(strm, infile, outfile);
+ if (outfile > 2) close(outfile);
+ if (infile > 2) close(infile);
+
+ /* interpret result */
+ switch (ret) {
+ case Z_OK:
+ case Z_ERRNO:
+ if (infile > 2 && outfile > 2) {
+ copymeta(inname, outname); /* copy attributes */
+ unlink(inname);
+ }
+ if (ret == Z_ERRNO)
+ fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
+ inname);
+ break;
+ case Z_DATA_ERROR:
+ if (outfile > 2) unlink(outname);
+ fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
+ break;
+ case Z_MEM_ERROR:
+ if (outfile > 2) unlink(outname);
+ fprintf(stderr, "gun out of memory error--aborting\n");
+ return 1;
+ case Z_BUF_ERROR:
+ if (outfile > 2) unlink(outname);
+ if (strm->next_in != Z_NULL) {
+ fprintf(stderr, "gun write error on %s: %s\n",
+ outname, strerror(errno));
+ }
+ else if (errno) {
+ fprintf(stderr, "gun read error on %s: %s\n",
+ inname, strerror(errno));
+ }
+ else {
+ fprintf(stderr, "gun unexpected end of file on %s\n",
+ inname);
+ }
+ break;
+ default:
+ if (outfile > 2) unlink(outname);
+ fprintf(stderr, "gun internal error--aborting\n");
+ return 1;
+ }
+ return 0;
+}
+
+/* Process the gun command line arguments. See the command syntax near the
+ beginning of this source file. */
+int main(int argc, char **argv)
+{
+ int ret, len, test;
+ char *outname;
+ unsigned char *window;
+ z_stream strm;
+
+ /* initialize inflateBack state for repeated use */
+ window = match; /* reuse LZW match buffer */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ ret = inflateBackInit(&strm, 15, window);
+ if (ret != Z_OK) {
+ fprintf(stderr, "gun out of memory error--aborting\n");
+ return 1;
+ }
+
+ /* decompress each file to the same name with the suffix removed */
+ argc--;
+ argv++;
+ test = 0;
+ if (argc && strcmp(*argv, "-h") == 0) {
+ fprintf(stderr, "gun 1.6 (17 Jan 2010)\n");
+ fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n");
+ fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
+ return 0;
+ }
+ if (argc && strcmp(*argv, "-t") == 0) {
+ test = 1;
+ argc--;
+ argv++;
+ }
+ if (argc)
+ do {
+ if (test)
+ outname = NULL;
+ else {
+ len = (int)strlen(*argv);
+ if (strcmp(*argv + len - 3, ".gz") == 0 ||
+ strcmp(*argv + len - 3, "-gz") == 0)
+ len -= 3;
+ else if (strcmp(*argv + len - 2, ".z") == 0 ||
+ strcmp(*argv + len - 2, "-z") == 0 ||
+ strcmp(*argv + len - 2, "_z") == 0 ||
+ strcmp(*argv + len - 2, ".Z") == 0)
+ len -= 2;
+ else {
+ fprintf(stderr, "gun error: no gz type on %s--skipping\n",
+ *argv);
+ continue;
+ }
+ outname = malloc(len + 1);
+ if (outname == NULL) {
+ fprintf(stderr, "gun out of memory error--aborting\n");
+ ret = 1;
+ break;
+ }
+ memcpy(outname, *argv, len);
+ outname[len] = 0;
+ }
+ ret = gunzip(&strm, *argv, outname, test);
+ if (outname != NULL) free(outname);
+ if (ret) break;
+ } while (argv++, --argc);
+ else
+ ret = gunzip(&strm, NULL, NULL, test);
+
+ /* clean up */
+ inflateBackEnd(&strm);
+ return ret;
+}
diff --git a/libmariadb/external/zlib/examples/gzappend.c b/libmariadb/external/zlib/examples/gzappend.c
new file mode 100644
index 00000000..662dec37
--- /dev/null
+++ b/libmariadb/external/zlib/examples/gzappend.c
@@ -0,0 +1,504 @@
+/* gzappend -- command to append to a gzip file
+
+ Copyright (C) 2003, 2012 Mark Adler, all rights reserved
+ version 1.2, 11 Oct 2012
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Mark Adler madler@alumni.caltech.edu
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0 19 Oct 2003 - First version
+ * 1.1 4 Nov 2003 - Expand and clarify some comments and notes
+ * - Add version and copyright to help
+ * - Send help to stdout instead of stderr
+ * - Add some preemptive typecasts
+ * - Add L to constants in lseek() calls
+ * - Remove some debugging information in error messages
+ * - Use new data_type definition for zlib 1.2.1
+ * - Simplfy and unify file operations
+ * - Finish off gzip file in gztack()
+ * - Use deflatePrime() instead of adding empty blocks
+ * - Keep gzip file clean on appended file read errors
+ * - Use in-place rotate instead of auxiliary buffer
+ * (Why you ask? Because it was fun to write!)
+ * 1.2 11 Oct 2012 - Fix for proper z_const usage
+ * - Check for input buffer malloc failure
+ */
+
+/*
+ gzappend takes a gzip file and appends to it, compressing files from the
+ command line or data from stdin. The gzip file is written to directly, to
+ avoid copying that file, in case it's large. Note that this results in the
+ unfriendly behavior that if gzappend fails, the gzip file is corrupted.
+
+ This program was written to illustrate the use of the new Z_BLOCK option of
+ zlib 1.2.x's inflate() function. This option returns from inflate() at each
+ block boundary to facilitate locating and modifying the last block bit at
+ the start of the final deflate block. Also whether using Z_BLOCK or not,
+ another required feature of zlib 1.2.x is that inflate() now provides the
+ number of unusued bits in the last input byte used. gzappend will not work
+ with versions of zlib earlier than 1.2.1.
+
+ gzappend first decompresses the gzip file internally, discarding all but
+ the last 32K of uncompressed data, and noting the location of the last block
+ bit and the number of unused bits in the last byte of the compressed data.
+ The gzip trailer containing the CRC-32 and length of the uncompressed data
+ is verified. This trailer will be later overwritten.
+
+ Then the last block bit is cleared by seeking back in the file and rewriting
+ the byte that contains it. Seeking forward, the last byte of the compressed
+ data is saved along with the number of unused bits to initialize deflate.
+
+ A deflate process is initialized, using the last 32K of the uncompressed
+ data from the gzip file to initialize the dictionary. If the total
+ uncompressed data was less than 32K, then all of it is used to initialize
+ the dictionary. The deflate output bit buffer is also initialized with the
+ last bits from the original deflate stream. From here on, the data to
+ append is simply compressed using deflate, and written to the gzip file.
+ When that is complete, the new CRC-32 and uncompressed length are written
+ as the trailer of the gzip file.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "zlib.h"
+
+#define local static
+#define LGCHUNK 14
+#define CHUNK (1U << LGCHUNK)
+#define DSIZE 32768U
+
+/* print an error message and terminate with extreme prejudice */
+local void bye(char *msg1, char *msg2)
+{
+ fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2);
+ exit(1);
+}
+
+/* return the greatest common divisor of a and b using Euclid's algorithm,
+ modified to be fast when one argument much greater than the other, and
+ coded to avoid unnecessary swapping */
+local unsigned gcd(unsigned a, unsigned b)
+{
+ unsigned c;
+
+ while (a && b)
+ if (a > b) {
+ c = b;
+ while (a - c >= c)
+ c <<= 1;
+ a -= c;
+ }
+ else {
+ c = a;
+ while (b - c >= c)
+ c <<= 1;
+ b -= c;
+ }
+ return a + b;
+}
+
+/* rotate list[0..len-1] left by rot positions, in place */
+local void rotate(unsigned char *list, unsigned len, unsigned rot)
+{
+ unsigned char tmp;
+ unsigned cycles;
+ unsigned char *start, *last, *to, *from;
+
+ /* normalize rot and handle degenerate cases */
+ if (len < 2) return;
+ if (rot >= len) rot %= len;
+ if (rot == 0) return;
+
+ /* pointer to last entry in list */
+ last = list + (len - 1);
+
+ /* do simple left shift by one */
+ if (rot == 1) {
+ tmp = *list;
+ memcpy(list, list + 1, len - 1);
+ *last = tmp;
+ return;
+ }
+
+ /* do simple right shift by one */
+ if (rot == len - 1) {
+ tmp = *last;
+ memmove(list + 1, list, len - 1);
+ *list = tmp;
+ return;
+ }
+
+ /* otherwise do rotate as a set of cycles in place */
+ cycles = gcd(len, rot); /* number of cycles */
+ do {
+ start = from = list + cycles; /* start index is arbitrary */
+ tmp = *from; /* save entry to be overwritten */
+ for (;;) {
+ to = from; /* next step in cycle */
+ from += rot; /* go right rot positions */
+ if (from > last) from -= len; /* (pointer better not wrap) */
+ if (from == start) break; /* all but one shifted */
+ *to = *from; /* shift left */
+ }
+ *to = tmp; /* complete the circle */
+ } while (--cycles);
+}
+
+/* structure for gzip file read operations */
+typedef struct {
+ int fd; /* file descriptor */
+ int size; /* 1 << size is bytes in buf */
+ unsigned left; /* bytes available at next */
+ unsigned char *buf; /* buffer */
+ z_const unsigned char *next; /* next byte in buffer */
+ char *name; /* file name for error messages */
+} file;
+
+/* reload buffer */
+local int readin(file *in)
+{
+ int len;
+
+ len = read(in->fd, in->buf, 1 << in->size);
+ if (len == -1) bye("error reading ", in->name);
+ in->left = (unsigned)len;
+ in->next = in->buf;
+ return len;
+}
+
+/* read from file in, exit if end-of-file */
+local int readmore(file *in)
+{
+ if (readin(in) == 0) bye("unexpected end of ", in->name);
+ return 0;
+}
+
+#define read1(in) (in->left == 0 ? readmore(in) : 0, \
+ in->left--, *(in->next)++)
+
+/* skip over n bytes of in */
+local void skip(file *in, unsigned n)
+{
+ unsigned bypass;
+
+ if (n > in->left) {
+ n -= in->left;
+ bypass = n & ~((1U << in->size) - 1);
+ if (bypass) {
+ if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1)
+ bye("seeking ", in->name);
+ n -= bypass;
+ }
+ readmore(in);
+ if (n > in->left)
+ bye("unexpected end of ", in->name);
+ }
+ in->left -= n;
+ in->next += n;
+}
+
+/* read a four-byte unsigned integer, little-endian, from in */
+unsigned long read4(file *in)
+{
+ unsigned long val;
+
+ val = read1(in);
+ val += (unsigned)read1(in) << 8;
+ val += (unsigned long)read1(in) << 16;
+ val += (unsigned long)read1(in) << 24;
+ return val;
+}
+
+/* skip over gzip header */
+local void gzheader(file *in)
+{
+ int flags;
+ unsigned n;
+
+ if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file");
+ if (read1(in) != 8) bye("unknown compression method in", in->name);
+ flags = read1(in);
+ if (flags & 0xe0) bye("unknown header flags set in", in->name);
+ skip(in, 6);
+ if (flags & 4) {
+ n = read1(in);
+ n += (unsigned)(read1(in)) << 8;
+ skip(in, n);
+ }
+ if (flags & 8) while (read1(in) != 0) ;
+ if (flags & 16) while (read1(in) != 0) ;
+ if (flags & 2) skip(in, 2);
+}
+
+/* decompress gzip file "name", return strm with a deflate stream ready to
+ continue compression of the data in the gzip file, and return a file
+ descriptor pointing to where to write the compressed data -- the deflate
+ stream is initialized to compress using level "level" */
+local int gzscan(char *name, z_stream *strm, int level)
+{
+ int ret, lastbit, left, full;
+ unsigned have;
+ unsigned long crc, tot;
+ unsigned char *window;
+ off_t lastoff, end;
+ file gz;
+
+ /* open gzip file */
+ gz.name = name;
+ gz.fd = open(name, O_RDWR, 0);
+ if (gz.fd == -1) bye("cannot open ", name);
+ gz.buf = malloc(CHUNK);
+ if (gz.buf == NULL) bye("out of memory", "");
+ gz.size = LGCHUNK;
+ gz.left = 0;
+
+ /* skip gzip header */
+ gzheader(&gz);
+
+ /* prepare to decompress */
+ window = malloc(DSIZE);
+ if (window == NULL) bye("out of memory", "");
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ ret = inflateInit2(strm, -15);
+ if (ret != Z_OK) bye("out of memory", " or library mismatch");
+
+ /* decompress the deflate stream, saving append information */
+ lastbit = 0;
+ lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
+ left = 0;
+ strm->avail_in = gz.left;
+ strm->next_in = gz.next;
+ crc = crc32(0L, Z_NULL, 0);
+ have = full = 0;
+ do {
+ /* if needed, get more input */
+ if (strm->avail_in == 0) {
+ readmore(&gz);
+ strm->avail_in = gz.left;
+ strm->next_in = gz.next;
+ }
+
+ /* set up output to next available section of sliding window */
+ strm->avail_out = DSIZE - have;
+ strm->next_out = window + have;
+
+ /* inflate and check for errors */
+ ret = inflate(strm, Z_BLOCK);
+ if (ret == Z_STREAM_ERROR) bye("internal stream error!", "");
+ if (ret == Z_MEM_ERROR) bye("out of memory", "");
+ if (ret == Z_DATA_ERROR)
+ bye("invalid compressed data--format violated in", name);
+
+ /* update crc and sliding window pointer */
+ crc = crc32(crc, window + have, DSIZE - have - strm->avail_out);
+ if (strm->avail_out)
+ have = DSIZE - strm->avail_out;
+ else {
+ have = 0;
+ full = 1;
+ }
+
+ /* process end of block */
+ if (strm->data_type & 128) {
+ if (strm->data_type & 64)
+ left = strm->data_type & 0x1f;
+ else {
+ lastbit = strm->data_type & 0x1f;
+ lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in;
+ }
+ }
+ } while (ret != Z_STREAM_END);
+ inflateEnd(strm);
+ gz.left = strm->avail_in;
+ gz.next = strm->next_in;
+
+ /* save the location of the end of the compressed data */
+ end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
+
+ /* check gzip trailer and save total for deflate */
+ if (crc != read4(&gz))
+ bye("invalid compressed data--crc mismatch in ", name);
+ tot = strm->total_out;
+ if ((tot & 0xffffffffUL) != read4(&gz))
+ bye("invalid compressed data--length mismatch in", name);
+
+ /* if not at end of file, warn */
+ if (gz.left || readin(&gz))
+ fprintf(stderr,
+ "gzappend warning: junk at end of gzip file overwritten\n");
+
+ /* clear last block bit */
+ lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET);
+ if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
+ *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7)));
+ lseek(gz.fd, -1L, SEEK_CUR);
+ if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name);
+
+ /* if window wrapped, build dictionary from window by rotating */
+ if (full) {
+ rotate(window, DSIZE, have);
+ have = DSIZE;
+ }
+
+ /* set up deflate stream with window, crc, total_in, and leftover bits */
+ ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK) bye("out of memory", "");
+ deflateSetDictionary(strm, window, have);
+ strm->adler = crc;
+ strm->total_in = tot;
+ if (left) {
+ lseek(gz.fd, --end, SEEK_SET);
+ if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
+ deflatePrime(strm, 8 - left, *gz.buf);
+ }
+ lseek(gz.fd, end, SEEK_SET);
+
+ /* clean up and return */
+ free(window);
+ free(gz.buf);
+ return gz.fd;
+}
+
+/* append file "name" to gzip file gd using deflate stream strm -- if last
+ is true, then finish off the deflate stream at the end */
+local void gztack(char *name, int gd, z_stream *strm, int last)
+{
+ int fd, len, ret;
+ unsigned left;
+ unsigned char *in, *out;
+
+ /* open file to compress and append */
+ fd = 0;
+ if (name != NULL) {
+ fd = open(name, O_RDONLY, 0);
+ if (fd == -1)
+ fprintf(stderr, "gzappend warning: %s not found, skipping ...\n",
+ name);
+ }
+
+ /* allocate buffers */
+ in = malloc(CHUNK);
+ out = malloc(CHUNK);
+ if (in == NULL || out == NULL) bye("out of memory", "");
+
+ /* compress input file and append to gzip file */
+ do {
+ /* get more input */
+ len = read(fd, in, CHUNK);
+ if (len == -1) {
+ fprintf(stderr,
+ "gzappend warning: error reading %s, skipping rest ...\n",
+ name);
+ len = 0;
+ }
+ strm->avail_in = (unsigned)len;
+ strm->next_in = in;
+ if (len) strm->adler = crc32(strm->adler, in, (unsigned)len);
+
+ /* compress and write all available output */
+ do {
+ strm->avail_out = CHUNK;
+ strm->next_out = out;
+ ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH);
+ left = CHUNK - strm->avail_out;
+ while (left) {
+ len = write(gd, out + CHUNK - strm->avail_out - left, left);
+ if (len == -1) bye("writing gzip file", "");
+ left -= (unsigned)len;
+ }
+ } while (strm->avail_out == 0 && ret != Z_STREAM_END);
+ } while (len != 0);
+
+ /* write trailer after last entry */
+ if (last) {
+ deflateEnd(strm);
+ out[0] = (unsigned char)(strm->adler);
+ out[1] = (unsigned char)(strm->adler >> 8);
+ out[2] = (unsigned char)(strm->adler >> 16);
+ out[3] = (unsigned char)(strm->adler >> 24);
+ out[4] = (unsigned char)(strm->total_in);
+ out[5] = (unsigned char)(strm->total_in >> 8);
+ out[6] = (unsigned char)(strm->total_in >> 16);
+ out[7] = (unsigned char)(strm->total_in >> 24);
+ len = 8;
+ do {
+ ret = write(gd, out + 8 - len, len);
+ if (ret == -1) bye("writing gzip file", "");
+ len -= ret;
+ } while (len);
+ close(gd);
+ }
+
+ /* clean up and return */
+ free(out);
+ free(in);
+ if (fd > 0) close(fd);
+}
+
+/* process the compression level option if present, scan the gzip file, and
+ append the specified files, or append the data from stdin if no other file
+ names are provided on the command line -- the gzip file must be writable
+ and seekable */
+int main(int argc, char **argv)
+{
+ int gd, level;
+ z_stream strm;
+
+ /* ignore command name */
+ argc--; argv++;
+
+ /* provide usage if no arguments */
+ if (*argv == NULL) {
+ printf(
+ "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n"
+ );
+ printf(
+ "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n");
+ return 0;
+ }
+
+ /* set compression level */
+ level = Z_DEFAULT_COMPRESSION;
+ if (argv[0][0] == '-') {
+ if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0)
+ bye("invalid compression level", "");
+ level = argv[0][1] - '0';
+ if (*++argv == NULL) bye("no gzip file name after options", "");
+ }
+
+ /* prepare to append to gzip file */
+ gd = gzscan(*argv++, &strm, level);
+
+ /* append files on command line, or from stdin if none */
+ if (*argv == NULL)
+ gztack(NULL, gd, &strm, 1);
+ else
+ do {
+ gztack(*argv, gd, &strm, argv[1] == NULL);
+ } while (*++argv != NULL);
+ return 0;
+}
diff --git a/libmariadb/external/zlib/examples/gzjoin.c b/libmariadb/external/zlib/examples/gzjoin.c
new file mode 100644
index 00000000..89e80984
--- /dev/null
+++ b/libmariadb/external/zlib/examples/gzjoin.c
@@ -0,0 +1,449 @@
+/* gzjoin -- command to join gzip files into one gzip file
+
+ Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved
+ version 1.2, 14 Aug 2012
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Mark Adler madler@alumni.caltech.edu
+ */
+
+/*
+ * Change history:
+ *
+ * 1.0 11 Dec 2004 - First version
+ * 1.1 12 Jun 2005 - Changed ssize_t to long for portability
+ * 1.2 14 Aug 2012 - Clean up for z_const usage
+ */
+
+/*
+ gzjoin takes one or more gzip files on the command line and writes out a
+ single gzip file that will uncompress to the concatenation of the
+ uncompressed data from the individual gzip files. gzjoin does this without
+ having to recompress any of the data and without having to calculate a new
+ crc32 for the concatenated uncompressed data. gzjoin does however have to
+ decompress all of the input data in order to find the bits in the compressed
+ data that need to be modified to concatenate the streams.
+
+ gzjoin does not do an integrity check on the input gzip files other than
+ checking the gzip header and decompressing the compressed data. They are
+ otherwise assumed to be complete and correct.
+
+ Each joint between gzip files removes at least 18 bytes of previous trailer
+ and subsequent header, and inserts an average of about three bytes to the
+ compressed data in order to connect the streams. The output gzip file
+ has a minimal ten-byte gzip header with no file name or modification time.
+
+ This program was written to illustrate the use of the Z_BLOCK option of
+ inflate() and the crc32_combine() function. gzjoin will not compile with
+ versions of zlib earlier than 1.2.3.
+ */
+
+#include <stdio.h> /* fputs(), fprintf(), fwrite(), putc() */
+#include <stdlib.h> /* exit(), malloc(), free() */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* close(), read(), lseek() */
+#include "zlib.h"
+ /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */
+
+#define local static
+
+/* exit with an error (return a value to allow use in an expression) */
+local int bail(char *why1, char *why2)
+{
+ fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2);
+ exit(1);
+ return 0;
+}
+
+/* -- simple buffered file input with access to the buffer -- */
+
+#define CHUNK 32768 /* must be a power of two and fit in unsigned */
+
+/* bin buffered input file type */
+typedef struct {
+ char *name; /* name of file for error messages */
+ int fd; /* file descriptor */
+ unsigned left; /* bytes remaining at next */
+ unsigned char *next; /* next byte to read */
+ unsigned char *buf; /* allocated buffer of length CHUNK */
+} bin;
+
+/* close a buffered file and free allocated memory */
+local void bclose(bin *in)
+{
+ if (in != NULL) {
+ if (in->fd != -1)
+ close(in->fd);
+ if (in->buf != NULL)
+ free(in->buf);
+ free(in);
+ }
+}
+
+/* open a buffered file for input, return a pointer to type bin, or NULL on
+ failure */
+local bin *bopen(char *name)
+{
+ bin *in;
+
+ in = malloc(sizeof(bin));
+ if (in == NULL)
+ return NULL;
+ in->buf = malloc(CHUNK);
+ in->fd = open(name, O_RDONLY, 0);
+ if (in->buf == NULL || in->fd == -1) {
+ bclose(in);
+ return NULL;
+ }
+ in->left = 0;
+ in->next = in->buf;
+ in->name = name;
+ return in;
+}
+
+/* load buffer from file, return -1 on read error, 0 or 1 on success, with
+ 1 indicating that end-of-file was reached */
+local int bload(bin *in)
+{
+ long len;
+
+ if (in == NULL)
+ return -1;
+ if (in->left != 0)
+ return 0;
+ in->next = in->buf;
+ do {
+ len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left);
+ if (len < 0)
+ return -1;
+ in->left += (unsigned)len;
+ } while (len != 0 && in->left < CHUNK);
+ return len == 0 ? 1 : 0;
+}
+
+/* get a byte from the file, bail if end of file */
+#define bget(in) (in->left ? 0 : bload(in), \
+ in->left ? (in->left--, *(in->next)++) : \
+ bail("unexpected end of file on ", in->name))
+
+/* get a four-byte little-endian unsigned integer from file */
+local unsigned long bget4(bin *in)
+{
+ unsigned long val;
+
+ val = bget(in);
+ val += (unsigned long)(bget(in)) << 8;
+ val += (unsigned long)(bget(in)) << 16;
+ val += (unsigned long)(bget(in)) << 24;
+ return val;
+}
+
+/* skip bytes in file */
+local void bskip(bin *in, unsigned skip)
+{
+ /* check pointer */
+ if (in == NULL)
+ return;
+
+ /* easy case -- skip bytes in buffer */
+ if (skip <= in->left) {
+ in->left -= skip;
+ in->next += skip;
+ return;
+ }
+
+ /* skip what's in buffer, discard buffer contents */
+ skip -= in->left;
+ in->left = 0;
+
+ /* seek past multiples of CHUNK bytes */
+ if (skip > CHUNK) {
+ unsigned left;
+
+ left = skip & (CHUNK - 1);
+ if (left == 0) {
+ /* exact number of chunks: seek all the way minus one byte to check
+ for end-of-file with a read */
+ lseek(in->fd, skip - 1, SEEK_CUR);
+ if (read(in->fd, in->buf, 1) != 1)
+ bail("unexpected end of file on ", in->name);
+ return;
+ }
+
+ /* skip the integral chunks, update skip with remainder */
+ lseek(in->fd, skip - left, SEEK_CUR);
+ skip = left;
+ }
+
+ /* read more input and skip remainder */
+ bload(in);
+ if (skip > in->left)
+ bail("unexpected end of file on ", in->name);
+ in->left -= skip;
+ in->next += skip;
+}
+
+/* -- end of buffered input functions -- */
+
+/* skip the gzip header from file in */
+local void gzhead(bin *in)
+{
+ int flags;
+
+ /* verify gzip magic header and compression method */
+ if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8)
+ bail(in->name, " is not a valid gzip file");
+
+ /* get and verify flags */
+ flags = bget(in);
+ if ((flags & 0xe0) != 0)
+ bail("unknown reserved bits set in ", in->name);
+
+ /* skip modification time, extra flags, and os */
+ bskip(in, 6);
+
+ /* skip extra field if present */
+ if (flags & 4) {
+ unsigned len;
+
+ len = bget(in);
+ len += (unsigned)(bget(in)) << 8;
+ bskip(in, len);
+ }
+
+ /* skip file name if present */
+ if (flags & 8)
+ while (bget(in) != 0)
+ ;
+
+ /* skip comment if present */
+ if (flags & 16)
+ while (bget(in) != 0)
+ ;
+
+ /* skip header crc if present */
+ if (flags & 2)
+ bskip(in, 2);
+}
+
+/* write a four-byte little-endian unsigned integer to out */
+local void put4(unsigned long val, FILE *out)
+{
+ putc(val & 0xff, out);
+ putc((val >> 8) & 0xff, out);
+ putc((val >> 16) & 0xff, out);
+ putc((val >> 24) & 0xff, out);
+}
+
+/* Load up zlib stream from buffered input, bail if end of file */
+local void zpull(z_streamp strm, bin *in)
+{
+ if (in->left == 0)
+ bload(in);
+ if (in->left == 0)
+ bail("unexpected end of file on ", in->name);
+ strm->avail_in = in->left;
+ strm->next_in = in->next;
+}
+
+/* Write header for gzip file to out and initialize trailer. */
+local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out)
+{
+ fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out);
+ *crc = crc32(0L, Z_NULL, 0);
+ *tot = 0;
+}
+
+/* Copy the compressed data from name, zeroing the last block bit of the last
+ block if clr is true, and adding empty blocks as needed to get to a byte
+ boundary. If clr is false, then the last block becomes the last block of
+ the output, and the gzip trailer is written. crc and tot maintains the
+ crc and length (modulo 2^32) of the output for the trailer. The resulting
+ gzip file is written to out. gzinit() must be called before the first call
+ of gzcopy() to write the gzip header and to initialize crc and tot. */
+local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
+ FILE *out)
+{
+ int ret; /* return value from zlib functions */
+ int pos; /* where the "last block" bit is in byte */
+ int last; /* true if processing the last block */
+ bin *in; /* buffered input file */
+ unsigned char *start; /* start of compressed data in buffer */
+ unsigned char *junk; /* buffer for uncompressed data -- discarded */
+ z_off_t len; /* length of uncompressed data (support > 4 GB) */
+ z_stream strm; /* zlib inflate stream */
+
+ /* open gzip file and skip header */
+ in = bopen(name);
+ if (in == NULL)
+ bail("could not open ", name);
+ gzhead(in);
+
+ /* allocate buffer for uncompressed data and initialize raw inflate
+ stream */
+ junk = malloc(CHUNK);
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+ ret = inflateInit2(&strm, -15);
+ if (junk == NULL || ret != Z_OK)
+ bail("out of memory", "");
+
+ /* inflate and copy compressed data, clear last-block bit if requested */
+ len = 0;
+ zpull(&strm, in);
+ start = in->next;
+ last = start[0] & 1;
+ if (last && clr)
+ start[0] &= ~1;
+ strm.avail_out = 0;
+ for (;;) {
+ /* if input used and output done, write used input and get more */
+ if (strm.avail_in == 0 && strm.avail_out != 0) {
+ fwrite(start, 1, strm.next_in - start, out);
+ start = in->buf;
+ in->left = 0;
+ zpull(&strm, in);
+ }
+
+ /* decompress -- return early when end-of-block reached */
+ strm.avail_out = CHUNK;
+ strm.next_out = junk;
+ ret = inflate(&strm, Z_BLOCK);
+ switch (ret) {
+ case Z_MEM_ERROR:
+ bail("out of memory", "");
+ case Z_DATA_ERROR:
+ bail("invalid compressed data in ", in->name);
+ }
+
+ /* update length of uncompressed data */
+ len += CHUNK - strm.avail_out;
+
+ /* check for block boundary (only get this when block copied out) */
+ if (strm.data_type & 128) {
+ /* if that was the last block, then done */
+ if (last)
+ break;
+
+ /* number of unused bits in last byte */
+ pos = strm.data_type & 7;
+
+ /* find the next last-block bit */
+ if (pos != 0) {
+ /* next last-block bit is in last used byte */
+ pos = 0x100 >> pos;
+ last = strm.next_in[-1] & pos;
+ if (last && clr)
+ in->buf[strm.next_in - in->buf - 1] &= ~pos;
+ }
+ else {
+ /* next last-block bit is in next unused byte */
+ if (strm.avail_in == 0) {
+ /* don't have that byte yet -- get it */
+ fwrite(start, 1, strm.next_in - start, out);
+ start = in->buf;
+ in->left = 0;
+ zpull(&strm, in);
+ }
+ last = strm.next_in[0] & 1;
+ if (last && clr)
+ in->buf[strm.next_in - in->buf] &= ~1;
+ }
+ }
+ }
+
+ /* update buffer with unused input */
+ in->left = strm.avail_in;
+ in->next = in->buf + (strm.next_in - in->buf);
+
+ /* copy used input, write empty blocks to get to byte boundary */
+ pos = strm.data_type & 7;
+ fwrite(start, 1, in->next - start - 1, out);
+ last = in->next[-1];
+ if (pos == 0 || !clr)
+ /* already at byte boundary, or last file: write last byte */
+ putc(last, out);
+ else {
+ /* append empty blocks to last byte */
+ last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */
+ if (pos & 1) {
+ /* odd -- append an empty stored block */
+ putc(last, out);
+ if (pos == 1)
+ putc(0, out); /* two more bits in block header */
+ fwrite("\0\0\xff\xff", 1, 4, out);
+ }
+ else {
+ /* even -- append 1, 2, or 3 empty fixed blocks */
+ switch (pos) {
+ case 6:
+ putc(last | 8, out);
+ last = 0;
+ case 4:
+ putc(last | 0x20, out);
+ last = 0;
+ case 2:
+ putc(last | 0x80, out);
+ putc(0, out);
+ }
+ }
+ }
+
+ /* update crc and tot */
+ *crc = crc32_combine(*crc, bget4(in), len);
+ *tot += (unsigned long)len;
+
+ /* clean up */
+ inflateEnd(&strm);
+ free(junk);
+ bclose(in);
+
+ /* write trailer if this is the last gzip file */
+ if (!clr) {
+ put4(*crc, out);
+ put4(*tot, out);
+ }
+}
+
+/* join the gzip files on the command line, write result to stdout */
+int main(int argc, char **argv)
+{
+ unsigned long crc, tot; /* running crc and total uncompressed length */
+
+ /* skip command name */
+ argc--;
+ argv++;
+
+ /* show usage if no arguments */
+ if (argc == 0) {
+ fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n",
+ stderr);
+ return 0;
+ }
+
+ /* join gzip files on command line and write to stdout */
+ gzinit(&crc, &tot, stdout);
+ while (argc--)
+ gzcopy(*argv++, argc, &crc, &tot, stdout);
+
+ /* done */
+ return 0;
+}
diff --git a/libmariadb/external/zlib/examples/gzlog.c b/libmariadb/external/zlib/examples/gzlog.c
new file mode 100644
index 00000000..922f878d
--- /dev/null
+++ b/libmariadb/external/zlib/examples/gzlog.c
@@ -0,0 +1,1059 @@
+/*
+ * gzlog.c
+ * Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved
+ * For conditions of distribution and use, see copyright notice in gzlog.h
+ * version 2.2, 14 Aug 2012
+ */
+
+/*
+ gzlog provides a mechanism for frequently appending short strings to a gzip
+ file that is efficient both in execution time and compression ratio. The
+ strategy is to write the short strings in an uncompressed form to the end of
+ the gzip file, only compressing when the amount of uncompressed data has
+ reached a given threshold.
+
+ gzlog also provides protection against interruptions in the process due to
+ system crashes. The status of the operation is recorded in an extra field
+ in the gzip file, and is only updated once the gzip file is brought to a
+ valid state. The last data to be appended or compressed is saved in an
+ auxiliary file, so that if the operation is interrupted, it can be completed
+ the next time an append operation is attempted.
+
+ gzlog maintains another auxiliary file with the last 32K of data from the
+ compressed portion, which is preloaded for the compression of the subsequent
+ data. This minimizes the impact to the compression ratio of appending.
+ */
+
+/*
+ Operations Concept:
+
+ Files (log name "foo"):
+ foo.gz -- gzip file with the complete log
+ foo.add -- last message to append or last data to compress
+ foo.dict -- dictionary of the last 32K of data for next compression
+ foo.temp -- temporary dictionary file for compression after this one
+ foo.lock -- lock file for reading and writing the other files
+ foo.repairs -- log file for log file recovery operations (not compressed)
+
+ gzip file structure:
+ - fixed-length (no file name) header with extra field (see below)
+ - compressed data ending initially with empty stored block
+ - uncompressed data filling out originally empty stored block and
+ subsequent stored blocks as needed (16K max each)
+ - gzip trailer
+ - no junk at end (no other gzip streams)
+
+ When appending data, the information in the first three items above plus the
+ foo.add file are sufficient to recover an interrupted append operation. The
+ extra field has the necessary information to restore the start of the last
+ stored block and determine where to append the data in the foo.add file, as
+ well as the crc and length of the gzip data before the append operation.
+
+ The foo.add file is created before the gzip file is marked for append, and
+ deleted after the gzip file is marked as complete. So if the append
+ operation is interrupted, the data to add will still be there. If due to
+ some external force, the foo.add file gets deleted between when the append
+ operation was interrupted and when recovery is attempted, the gzip file will
+ still be restored, but without the appended data.
+
+ When compressing data, the information in the first two items above plus the
+ foo.add file are sufficient to recover an interrupted compress operation.
+ The extra field has the necessary information to find the end of the
+ compressed data, and contains both the crc and length of just the compressed
+ data and of the complete set of data including the contents of the foo.add
+ file.
+
+ Again, the foo.add file is maintained during the compress operation in case
+ of an interruption. If in the unlikely event the foo.add file with the data
+ to be compressed is missing due to some external force, a gzip file with
+ just the previous compressed data will be reconstructed. In this case, all
+ of the data that was to be compressed is lost (approximately one megabyte).
+ This will not occur if all that happened was an interruption of the compress
+ operation.
+
+ The third state that is marked is the replacement of the old dictionary with
+ the new dictionary after a compress operation. Once compression is
+ complete, the gzip file is marked as being in the replace state. This
+ completes the gzip file, so an interrupt after being so marked does not
+ result in recompression. Then the dictionary file is replaced, and the gzip
+ file is marked as completed. This state prevents the possibility of
+ restarting compression with the wrong dictionary file.
+
+ All three operations are wrapped by a lock/unlock procedure. In order to
+ gain exclusive access to the log files, first a foo.lock file must be
+ exclusively created. When all operations are complete, the lock is
+ released by deleting the foo.lock file. If when attempting to create the
+ lock file, it already exists and the modify time of the lock file is more
+ than five minutes old (set by the PATIENCE define below), then the old
+ lock file is considered stale and deleted, and the exclusive creation of
+ the lock file is retried. To assure that there are no false assessments
+ of the staleness of the lock file, the operations periodically touch the
+ lock file to update the modified date.
+
+ Following is the definition of the extra field with all of the information
+ required to enable the above append and compress operations and their
+ recovery if interrupted. Multi-byte values are stored little endian
+ (consistent with the gzip format). File pointers are eight bytes long.
+ The crc's and lengths for the gzip trailer are four bytes long. (Note that
+ the length at the end of a gzip file is used for error checking only, and
+ for large files is actually the length modulo 2^32.) The stored block
+ length is two bytes long. The gzip extra field two-byte identification is
+ "ap" for append. It is assumed that writing the extra field to the file is
+ an "atomic" operation. That is, either all of the extra field is written
+ to the file, or none of it is, if the operation is interrupted right at the
+ point of updating the extra field. This is a reasonable assumption, since
+ the extra field is within the first 52 bytes of the file, which is smaller
+ than any expected block size for a mass storage device (usually 512 bytes or
+ larger).
+
+ Extra field (35 bytes):
+ - Pointer to first stored block length -- this points to the two-byte length
+ of the first stored block, which is followed by the two-byte, one's
+ complement of that length. The stored block length is preceded by the
+ three-bit header of the stored block, which is the actual start of the
+ stored block in the deflate format. See the bit offset field below.
+ - Pointer to the last stored block length. This is the same as above, but
+ for the last stored block of the uncompressed data in the gzip file.
+ Initially this is the same as the first stored block length pointer.
+ When the stored block gets to 16K (see the MAX_STORE define), then a new
+ stored block as added, at which point the last stored block length pointer
+ is different from the first stored block length pointer. When they are
+ different, the first bit of the last stored block header is eight bits, or
+ one byte back from the block length.
+ - Compressed data crc and length. This is the crc and length of the data
+ that is in the compressed portion of the deflate stream. These are used
+ only in the event that the foo.add file containing the data to compress is
+ lost after a compress operation is interrupted.
+ - Total data crc and length. This is the crc and length of all of the data
+ stored in the gzip file, compressed and uncompressed. It is used to
+ reconstruct the gzip trailer when compressing, as well as when recovering
+ interrupted operations.
+ - Final stored block length. This is used to quickly find where to append,
+ and allows the restoration of the original final stored block state when
+ an append operation is interrupted.
+ - First stored block start as the number of bits back from the final stored
+ block first length byte. This value is in the range of 3..10, and is
+ stored as the low three bits of the final byte of the extra field after
+ subtracting three (0..7). This allows the last-block bit of the stored
+ block header to be updated when a new stored block is added, for the case
+ when the first stored block and the last stored block are the same. (When
+ they are different, the numbers of bits back is known to be eight.) This
+ also allows for new compressed data to be appended to the old compressed
+ data in the compress operation, overwriting the previous first stored
+ block, or for the compressed data to be terminated and a valid gzip file
+ reconstructed on the off chance that a compression operation was
+ interrupted and the data to compress in the foo.add file was deleted.
+ - The operation in process. This is the next two bits in the last byte (the
+ bits under the mask 0x18). The are interpreted as 0: nothing in process,
+ 1: append in process, 2: compress in process, 3: replace in process.
+ - The top three bits of the last byte in the extra field are reserved and
+ are currently set to zero.
+
+ Main procedure:
+ - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of
+ the system open() call. If the modify time of an existing lock file is
+ more than PATIENCE seconds old, then the lock file is deleted and the
+ exclusive create is retried.
+ - Load the extra field from the foo.gz file, and see if an operation was in
+ progress but not completed. If so, apply the recovery procedure below.
+ - Perform the append procedure with the provided data.
+ - If the uncompressed data in the foo.gz file is 1MB or more, apply the
+ compress procedure.
+ - Delete the foo.lock file.
+
+ Append procedure:
+ - Put what to append in the foo.add file so that the operation can be
+ restarted if this procedure is interrupted.
+ - Mark the foo.gz extra field with the append operation in progress.
+ + Restore the original last-block bit and stored block length of the last
+ stored block from the information in the extra field, in case a previous
+ append operation was interrupted.
+ - Append the provided data to the last stored block, creating new stored
+ blocks as needed and updating the stored blocks last-block bits and
+ lengths.
+ - Update the crc and length with the new data, and write the gzip trailer.
+ - Write over the extra field (with a single write operation) with the new
+ pointers, lengths, and crc's, and mark the gzip file as not in process.
+ Though there is still a foo.add file, it will be ignored since nothing
+ is in process. If a foo.add file is leftover from a previously
+ completed operation, it is truncated when writing new data to it.
+ - Delete the foo.add file.
+
+ Compress and replace procedures:
+ - Read all of the uncompressed data in the stored blocks in foo.gz and write
+ it to foo.add. Also write foo.temp with the last 32K of that data to
+ provide a dictionary for the next invocation of this procedure.
+ - Rewrite the extra field marking foo.gz with a compression in process.
+ * If there is no data provided to compress (due to a missing foo.add file
+ when recovering), reconstruct and truncate the foo.gz file to contain
+ only the previous compressed data and proceed to the step after the next
+ one. Otherwise ...
+ - Compress the data with the dictionary in foo.dict, and write to the
+ foo.gz file starting at the bit immediately following the last previously
+ compressed block. If there is no foo.dict, proceed anyway with the
+ compression at slightly reduced efficiency. (For the foo.dict file to be
+ missing requires some external failure beyond simply the interruption of
+ a compress operation.) During this process, the foo.lock file is
+ periodically touched to assure that that file is not considered stale by
+ another process before we're done. The deflation is terminated with a
+ non-last empty static block (10 bits long), that is then located and
+ written over by a last-bit-set empty stored block.
+ - Append the crc and length of the data in the gzip file (previously
+ calculated during the append operations).
+ - Write over the extra field with the updated stored block offsets, bits
+ back, crc's, and lengths, and mark foo.gz as in process for a replacement
+ of the dictionary.
+ @ Delete the foo.add file.
+ - Replace foo.dict with foo.temp.
+ - Write over the extra field, marking foo.gz as complete.
+
+ Recovery procedure:
+ - If not a replace recovery, read in the foo.add file, and provide that data
+ to the appropriate recovery below. If there is no foo.add file, provide
+ a zero data length to the recovery. In that case, the append recovery
+ restores the foo.gz to the previous compressed + uncompressed data state.
+ For the the compress recovery, a missing foo.add file results in foo.gz
+ being restored to the previous compressed-only data state.
+ - Append recovery:
+ - Pick up append at + step above
+ - Compress recovery:
+ - Pick up compress at * step above
+ - Replace recovery:
+ - Pick up compress at @ step above
+ - Log the repair with a date stamp in foo.repairs
+ */
+
+#include <sys/types.h>
+#include <stdio.h> /* rename, fopen, fprintf, fclose */
+#include <stdlib.h> /* malloc, free */
+#include <string.h> /* strlen, strrchr, strcpy, strncpy, strcmp */
+#include <fcntl.h> /* open */
+#include <unistd.h> /* lseek, read, write, close, unlink, sleep, */
+ /* ftruncate, fsync */
+#include <errno.h> /* errno */
+#include <time.h> /* time, ctime */
+#include <sys/stat.h> /* stat */
+#include <sys/time.h> /* utimes */
+#include "zlib.h" /* crc32 */
+
+#include "gzlog.h" /* header for external access */
+
+#define local static
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+/* Macro for debugging to deterministically force recovery operations */
+#ifdef DEBUG
+ #include <setjmp.h> /* longjmp */
+ jmp_buf gzlog_jump; /* where to go back to */
+ int gzlog_bail = 0; /* which point to bail at (1..8) */
+ int gzlog_count = -1; /* number of times through to wait */
+# define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \
+ longjmp(gzlog_jump, gzlog_bail); } while (0)
+#else
+# define BAIL(n)
+#endif
+
+/* how old the lock file can be in seconds before considering it stale */
+#define PATIENCE 300
+
+/* maximum stored block size in Kbytes -- must be in 1..63 */
+#define MAX_STORE 16
+
+/* number of stored Kbytes to trigger compression (must be >= 32 to allow
+ dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to
+ discard the stored block headers contribution of five bytes each) */
+#define TRIGGER 1024
+
+/* size of a deflate dictionary (this cannot be changed) */
+#define DICT 32768U
+
+/* values for the operation (2 bits) */
+#define NO_OP 0
+#define APPEND_OP 1
+#define COMPRESS_OP 2
+#define REPLACE_OP 3
+
+/* macros to extract little-endian integers from an unsigned byte buffer */
+#define PULL2(p) ((p)[0]+((uint)((p)[1])<<8))
+#define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16))
+#define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32))
+
+/* macros to store integers into a byte buffer in little-endian order */
+#define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0)
+#define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0)
+#define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0)
+
+/* internal structure for log information */
+#define LOGID "\106\035\172" /* should be three non-zero characters */
+struct log {
+ char id[4]; /* contains LOGID to detect inadvertent overwrites */
+ int fd; /* file descriptor for .gz file, opened read/write */
+ char *path; /* allocated path, e.g. "/var/log/foo" or "foo" */
+ char *end; /* end of path, for appending suffices such as ".gz" */
+ off_t first; /* offset of first stored block first length byte */
+ int back; /* location of first block id in bits back from first */
+ uint stored; /* bytes currently in last stored block */
+ off_t last; /* offset of last stored block first length byte */
+ ulong ccrc; /* crc of compressed data */
+ ulong clen; /* length (modulo 2^32) of compressed data */
+ ulong tcrc; /* crc of total data */
+ ulong tlen; /* length (modulo 2^32) of total data */
+ time_t lock; /* last modify time of our lock file */
+};
+
+/* gzip header for gzlog */
+local unsigned char log_gzhead[] = {
+ 0x1f, 0x8b, /* magic gzip id */
+ 8, /* compression method is deflate */
+ 4, /* there is an extra field (no file name) */
+ 0, 0, 0, 0, /* no modification time provided */
+ 0, 0xff, /* no extra flags, no OS specified */
+ 39, 0, 'a', 'p', 35, 0 /* extra field with "ap" subfield */
+ /* 35 is EXTRA, 39 is EXTRA + 4 */
+};
+
+#define HEAD sizeof(log_gzhead) /* should be 16 */
+
+/* initial gzip extra field content (52 == HEAD + EXTRA + 1) */
+local unsigned char log_gzext[] = {
+ 52, 0, 0, 0, 0, 0, 0, 0, /* offset of first stored block length */
+ 52, 0, 0, 0, 0, 0, 0, 0, /* offset of last stored block length */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* compressed data crc and length */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* total data crc and length */
+ 0, 0, /* final stored block data length */
+ 5 /* op is NO_OP, last bit 8 bits back */
+};
+
+#define EXTRA sizeof(log_gzext) /* should be 35 */
+
+/* initial gzip data and trailer */
+local unsigned char log_gzbody[] = {
+ 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */
+ 0, 0, 0, 0, /* crc */
+ 0, 0, 0, 0 /* uncompressed length */
+};
+
+#define BODY sizeof(log_gzbody)
+
+/* Exclusively create foo.lock in order to negotiate exclusive access to the
+ foo.* files. If the modify time of an existing lock file is greater than
+ PATIENCE seconds in the past, then consider the lock file to have been
+ abandoned, delete it, and try the exclusive create again. Save the lock
+ file modify time for verification of ownership. Return 0 on success, or -1
+ on failure, usually due to an access restriction or invalid path. Note that
+ if stat() or unlink() fails, it may be due to another process noticing the
+ abandoned lock file a smidge sooner and deleting it, so those are not
+ flagged as an error. */
+local int log_lock(struct log *log)
+{
+ int fd;
+ struct stat st;
+
+ strcpy(log->end, ".lock");
+ while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) {
+ if (errno != EEXIST)
+ return -1;
+ if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) {
+ unlink(log->path);
+ continue;
+ }
+ sleep(2); /* relinquish the CPU for two seconds while waiting */
+ }
+ close(fd);
+ if (stat(log->path, &st) == 0)
+ log->lock = st.st_mtime;
+ return 0;
+}
+
+/* Update the modify time of the lock file to now, in order to prevent another
+ task from thinking that the lock is stale. Save the lock file modify time
+ for verification of ownership. */
+local void log_touch(struct log *log)
+{
+ struct stat st;
+
+ strcpy(log->end, ".lock");
+ utimes(log->path, NULL);
+ if (stat(log->path, &st) == 0)
+ log->lock = st.st_mtime;
+}
+
+/* Check the log file modify time against what is expected. Return true if
+ this is not our lock. If it is our lock, touch it to keep it. */
+local int log_check(struct log *log)
+{
+ struct stat st;
+
+ strcpy(log->end, ".lock");
+ if (stat(log->path, &st) || st.st_mtime != log->lock)
+ return 1;
+ log_touch(log);
+ return 0;
+}
+
+/* Unlock a previously acquired lock, but only if it's ours. */
+local void log_unlock(struct log *log)
+{
+ if (log_check(log))
+ return;
+ strcpy(log->end, ".lock");
+ unlink(log->path);
+ log->lock = 0;
+}
+
+/* Check the gzip header and read in the extra field, filling in the values in
+ the log structure. Return op on success or -1 if the gzip header was not as
+ expected. op is the current operation in progress last written to the extra
+ field. This assumes that the gzip file has already been opened, with the
+ file descriptor log->fd. */
+local int log_head(struct log *log)
+{
+ int op;
+ unsigned char buf[HEAD + EXTRA];
+
+ if (lseek(log->fd, 0, SEEK_SET) < 0 ||
+ read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA ||
+ memcmp(buf, log_gzhead, HEAD)) {
+ return -1;
+ }
+ log->first = PULL8(buf + HEAD);
+ log->last = PULL8(buf + HEAD + 8);
+ log->ccrc = PULL4(buf + HEAD + 16);
+ log->clen = PULL4(buf + HEAD + 20);
+ log->tcrc = PULL4(buf + HEAD + 24);
+ log->tlen = PULL4(buf + HEAD + 28);
+ log->stored = PULL2(buf + HEAD + 32);
+ log->back = 3 + (buf[HEAD + 34] & 7);
+ op = (buf[HEAD + 34] >> 3) & 3;
+ return op;
+}
+
+/* Write over the extra field contents, marking the operation as op. Use fsync
+ to assure that the device is written to, and in the requested order. This
+ operation, and only this operation, is assumed to be atomic in order to
+ assure that the log is recoverable in the event of an interruption at any
+ point in the process. Return -1 if the write to foo.gz failed. */
+local int log_mark(struct log *log, int op)
+{
+ int ret;
+ unsigned char ext[EXTRA];
+
+ PUT8(ext, log->first);
+ PUT8(ext + 8, log->last);
+ PUT4(ext + 16, log->ccrc);
+ PUT4(ext + 20, log->clen);
+ PUT4(ext + 24, log->tcrc);
+ PUT4(ext + 28, log->tlen);
+ PUT2(ext + 32, log->stored);
+ ext[34] = log->back - 3 + (op << 3);
+ fsync(log->fd);
+ ret = lseek(log->fd, HEAD, SEEK_SET) < 0 ||
+ write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0;
+ fsync(log->fd);
+ return ret;
+}
+
+/* Rewrite the last block header bits and subsequent zero bits to get to a byte
+ boundary, setting the last block bit if last is true, and then write the
+ remainder of the stored block header (length and one's complement). Leave
+ the file pointer after the end of the last stored block data. Return -1 if
+ there is a read or write failure on the foo.gz file */
+local int log_last(struct log *log, int last)
+{
+ int back, len, mask;
+ unsigned char buf[6];
+
+ /* determine the locations of the bytes and bits to modify */
+ back = log->last == log->first ? log->back : 8;
+ len = back > 8 ? 2 : 1; /* bytes back from log->last */
+ mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */
+
+ /* get the byte to modify (one or two back) into buf[0] -- don't need to
+ read the byte if the last-bit is eight bits back, since in that case
+ the entire byte will be modified */
+ buf[0] = 0;
+ if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
+ read(log->fd, buf, 1) != 1))
+ return -1;
+
+ /* change the last-bit of the last stored block as requested -- note
+ that all bits above the last-bit are set to zero, per the type bits
+ of a stored block being 00 and per the convention that the bits to
+ bring the stream to a byte boundary are also zeros */
+ buf[1] = 0;
+ buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0);
+
+ /* write the modified stored block header and lengths, move the file
+ pointer to after the last stored block data */
+ PUT2(buf + 2, log->stored);
+ PUT2(buf + 4, log->stored ^ 0xffff);
+ return lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
+ write(log->fd, buf + 2 - len, len + 4) != len + 4 ||
+ lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0;
+}
+
+/* Append len bytes from data to the locked and open log file. len may be zero
+ if recovering and no .add file was found. In that case, the previous state
+ of the foo.gz file is restored. The data is appended uncompressed in
+ deflate stored blocks. Return -1 if there was an error reading or writing
+ the foo.gz file. */
+local int log_append(struct log *log, unsigned char *data, size_t len)
+{
+ uint put;
+ off_t end;
+ unsigned char buf[8];
+
+ /* set the last block last-bit and length, in case recovering an
+ interrupted append, then position the file pointer to append to the
+ block */
+ if (log_last(log, 1))
+ return -1;
+
+ /* append, adding stored blocks and updating the offset of the last stored
+ block as needed, and update the total crc and length */
+ while (len) {
+ /* append as much as we can to the last block */
+ put = (MAX_STORE << 10) - log->stored;
+ if (put > len)
+ put = (uint)len;
+ if (put) {
+ if (write(log->fd, data, put) != put)
+ return -1;
+ BAIL(1);
+ log->tcrc = crc32(log->tcrc, data, put);
+ log->tlen += put;
+ log->stored += put;
+ data += put;
+ len -= put;
+ }
+
+ /* if we need to, add a new empty stored block */
+ if (len) {
+ /* mark current block as not last */
+ if (log_last(log, 0))
+ return -1;
+
+ /* point to new, empty stored block */
+ log->last += 4 + log->stored + 1;
+ log->stored = 0;
+ }
+
+ /* mark last block as last, update its length */
+ if (log_last(log, 1))
+ return -1;
+ BAIL(2);
+ }
+
+ /* write the new crc and length trailer, and truncate just in case (could
+ be recovering from partial append with a missing foo.add file) */
+ PUT4(buf, log->tcrc);
+ PUT4(buf + 4, log->tlen);
+ if (write(log->fd, buf, 8) != 8 ||
+ (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end))
+ return -1;
+
+ /* write the extra field, marking the log file as done, delete .add file */
+ if (log_mark(log, NO_OP))
+ return -1;
+ strcpy(log->end, ".add");
+ unlink(log->path); /* ignore error, since may not exist */
+ return 0;
+}
+
+/* Replace the foo.dict file with the foo.temp file. Also delete the foo.add
+ file, since the compress operation may have been interrupted before that was
+ done. Returns 1 if memory could not be allocated, or -1 if reading or
+ writing foo.gz fails, or if the rename fails for some reason other than
+ foo.temp not existing. foo.temp not existing is a permitted error, since
+ the replace operation may have been interrupted after the rename is done,
+ but before foo.gz is marked as complete. */
+local int log_replace(struct log *log)
+{
+ int ret;
+ char *dest;
+
+ /* delete foo.add file */
+ strcpy(log->end, ".add");
+ unlink(log->path); /* ignore error, since may not exist */
+ BAIL(3);
+
+ /* rename foo.name to foo.dict, replacing foo.dict if it exists */
+ strcpy(log->end, ".dict");
+ dest = malloc(strlen(log->path) + 1);
+ if (dest == NULL)
+ return -2;
+ strcpy(dest, log->path);
+ strcpy(log->end, ".temp");
+ ret = rename(log->path, dest);
+ free(dest);
+ if (ret && errno != ENOENT)
+ return -1;
+ BAIL(4);
+
+ /* mark the foo.gz file as done */
+ return log_mark(log, NO_OP);
+}
+
+/* Compress the len bytes at data and append the compressed data to the
+ foo.gz deflate data immediately after the previous compressed data. This
+ overwrites the previous uncompressed data, which was stored in foo.add
+ and is the data provided in data[0..len-1]. If this operation is
+ interrupted, it picks up at the start of this routine, with the foo.add
+ file read in again. If there is no data to compress (len == 0), then we
+ simply terminate the foo.gz file after the previously compressed data,
+ appending a final empty stored block and the gzip trailer. Return -1 if
+ reading or writing the log.gz file failed, or -2 if there was a memory
+ allocation failure. */
+local int log_compress(struct log *log, unsigned char *data, size_t len)
+{
+ int fd;
+ uint got, max;
+ ssize_t dict;
+ off_t end;
+ z_stream strm;
+ unsigned char buf[DICT];
+
+ /* compress and append compressed data */
+ if (len) {
+ /* set up for deflate, allocating memory */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8,
+ Z_DEFAULT_STRATEGY) != Z_OK)
+ return -2;
+
+ /* read in dictionary (last 32K of data that was compressed) */
+ strcpy(log->end, ".dict");
+ fd = open(log->path, O_RDONLY, 0);
+ if (fd >= 0) {
+ dict = read(fd, buf, DICT);
+ close(fd);
+ if (dict < 0) {
+ deflateEnd(&strm);
+ return -1;
+ }
+ if (dict)
+ deflateSetDictionary(&strm, buf, (uint)dict);
+ }
+ log_touch(log);
+
+ /* prime deflate with last bits of previous block, position write
+ pointer to write those bits and overwrite what follows */
+ if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1),
+ SEEK_SET) < 0 ||
+ read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) {
+ deflateEnd(&strm);
+ return -1;
+ }
+ deflatePrime(&strm, (8 - log->back) & 7, *buf);
+
+ /* compress, finishing with a partial non-last empty static block */
+ strm.next_in = data;
+ max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */
+ do {
+ strm.avail_in = len > max ? max : (uint)len;
+ len -= strm.avail_in;
+ do {
+ strm.avail_out = DICT;
+ strm.next_out = buf;
+ deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH);
+ got = DICT - strm.avail_out;
+ if (got && write(log->fd, buf, got) != got) {
+ deflateEnd(&strm);
+ return -1;
+ }
+ log_touch(log);
+ } while (strm.avail_out == 0);
+ } while (len);
+ deflateEnd(&strm);
+ BAIL(5);
+
+ /* find start of empty static block -- scanning backwards the first one
+ bit is the second bit of the block, if the last byte is zero, then
+ we know the byte before that has a one in the top bit, since an
+ empty static block is ten bits long */
+ if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 ||
+ read(log->fd, buf, 1) != 1)
+ return -1;
+ log->first++;
+ if (*buf) {
+ log->back = 1;
+ while ((*buf & ((uint)1 << (8 - log->back++))) == 0)
+ ; /* guaranteed to terminate, since *buf != 0 */
+ }
+ else
+ log->back = 10;
+
+ /* update compressed crc and length */
+ log->ccrc = log->tcrc;
+ log->clen = log->tlen;
+ }
+ else {
+ /* no data to compress -- fix up existing gzip stream */
+ log->tcrc = log->ccrc;
+ log->tlen = log->clen;
+ }
+
+ /* complete and truncate gzip stream */
+ log->last = log->first;
+ log->stored = 0;
+ PUT4(buf, log->tcrc);
+ PUT4(buf + 4, log->tlen);
+ if (log_last(log, 1) || write(log->fd, buf, 8) != 8 ||
+ (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end))
+ return -1;
+ BAIL(6);
+
+ /* mark as being in the replace operation */
+ if (log_mark(log, REPLACE_OP))
+ return -1;
+
+ /* execute the replace operation and mark the file as done */
+ return log_replace(log);
+}
+
+/* log a repair record to the .repairs file */
+local void log_log(struct log *log, int op, char *record)
+{
+ time_t now;
+ FILE *rec;
+
+ now = time(NULL);
+ strcpy(log->end, ".repairs");
+ rec = fopen(log->path, "a");
+ if (rec == NULL)
+ return;
+ fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ?
+ "append" : (op == COMPRESS_OP ? "compress" : "replace"), record);
+ fclose(rec);
+ return;
+}
+
+/* Recover the interrupted operation op. First read foo.add for recovering an
+ append or compress operation. Return -1 if there was an error reading or
+ writing foo.gz or reading an existing foo.add, or -2 if there was a memory
+ allocation failure. */
+local int log_recover(struct log *log, int op)
+{
+ int fd, ret = 0;
+ unsigned char *data = NULL;
+ size_t len = 0;
+ struct stat st;
+
+ /* log recovery */
+ log_log(log, op, "start");
+
+ /* load foo.add file if expected and present */
+ if (op == APPEND_OP || op == COMPRESS_OP) {
+ strcpy(log->end, ".add");
+ if (stat(log->path, &st) == 0 && st.st_size) {
+ len = (size_t)(st.st_size);
+ if ((off_t)len != st.st_size ||
+ (data = malloc(st.st_size)) == NULL) {
+ log_log(log, op, "allocation failure");
+ return -2;
+ }
+ if ((fd = open(log->path, O_RDONLY, 0)) < 0) {
+ log_log(log, op, ".add file read failure");
+ return -1;
+ }
+ ret = (size_t)read(fd, data, len) != len;
+ close(fd);
+ if (ret) {
+ log_log(log, op, ".add file read failure");
+ return -1;
+ }
+ log_log(log, op, "loaded .add file");
+ }
+ else
+ log_log(log, op, "missing .add file!");
+ }
+
+ /* recover the interrupted operation */
+ switch (op) {
+ case APPEND_OP:
+ ret = log_append(log, data, len);
+ break;
+ case COMPRESS_OP:
+ ret = log_compress(log, data, len);
+ break;
+ case REPLACE_OP:
+ ret = log_replace(log);
+ }
+
+ /* log status */
+ log_log(log, op, ret ? "failure" : "complete");
+
+ /* clean up */
+ if (data != NULL)
+ free(data);
+ return ret;
+}
+
+/* Close the foo.gz file (if open) and release the lock. */
+local void log_close(struct log *log)
+{
+ if (log->fd >= 0)
+ close(log->fd);
+ log->fd = -1;
+ log_unlock(log);
+}
+
+/* Open foo.gz, verify the header, and load the extra field contents, after
+ first creating the foo.lock file to gain exclusive access to the foo.*
+ files. If foo.gz does not exist or is empty, then write the initial header,
+ extra, and body content of an empty foo.gz log file. If there is an error
+ creating the lock file due to access restrictions, or an error reading or
+ writing the foo.gz file, or if the foo.gz file is not a proper log file for
+ this object (e.g. not a gzip file or does not contain the expected extra
+ field), then return true. If there is an error, the lock is released.
+ Otherwise, the lock is left in place. */
+local int log_open(struct log *log)
+{
+ int op;
+
+ /* release open file resource if left over -- can occur if lock lost
+ between gzlog_open() and gzlog_write() */
+ if (log->fd >= 0)
+ close(log->fd);
+ log->fd = -1;
+
+ /* negotiate exclusive access */
+ if (log_lock(log) < 0)
+ return -1;
+
+ /* open the log file, foo.gz */
+ strcpy(log->end, ".gz");
+ log->fd = open(log->path, O_RDWR | O_CREAT, 0644);
+ if (log->fd < 0) {
+ log_close(log);
+ return -1;
+ }
+
+ /* if new, initialize foo.gz with an empty log, delete old dictionary */
+ if (lseek(log->fd, 0, SEEK_END) == 0) {
+ if (write(log->fd, log_gzhead, HEAD) != HEAD ||
+ write(log->fd, log_gzext, EXTRA) != EXTRA ||
+ write(log->fd, log_gzbody, BODY) != BODY) {
+ log_close(log);
+ return -1;
+ }
+ strcpy(log->end, ".dict");
+ unlink(log->path);
+ }
+
+ /* verify log file and load extra field information */
+ if ((op = log_head(log)) < 0) {
+ log_close(log);
+ return -1;
+ }
+
+ /* check for interrupted process and if so, recover */
+ if (op != NO_OP && log_recover(log, op)) {
+ log_close(log);
+ return -1;
+ }
+
+ /* touch the lock file to prevent another process from grabbing it */
+ log_touch(log);
+ return 0;
+}
+
+/* See gzlog.h for the description of the external methods below */
+gzlog *gzlog_open(char *path)
+{
+ size_t n;
+ struct log *log;
+
+ /* check arguments */
+ if (path == NULL || *path == 0)
+ return NULL;
+
+ /* allocate and initialize log structure */
+ log = malloc(sizeof(struct log));
+ if (log == NULL)
+ return NULL;
+ strcpy(log->id, LOGID);
+ log->fd = -1;
+
+ /* save path and end of path for name construction */
+ n = strlen(path);
+ log->path = malloc(n + 9); /* allow for ".repairs" */
+ if (log->path == NULL) {
+ free(log);
+ return NULL;
+ }
+ strcpy(log->path, path);
+ log->end = log->path + n;
+
+ /* gain exclusive access and verify log file -- may perform a
+ recovery operation if needed */
+ if (log_open(log)) {
+ free(log->path);
+ free(log);
+ return NULL;
+ }
+
+ /* return pointer to log structure */
+ return log;
+}
+
+/* gzlog_compress() return values:
+ 0: all good
+ -1: file i/o error (usually access issue)
+ -2: memory allocation failure
+ -3: invalid log pointer argument */
+int gzlog_compress(gzlog *logd)
+{
+ int fd, ret;
+ uint block;
+ size_t len, next;
+ unsigned char *data, buf[5];
+ struct log *log = logd;
+
+ /* check arguments */
+ if (log == NULL || strcmp(log->id, LOGID))
+ return -3;
+
+ /* see if we lost the lock -- if so get it again and reload the extra
+ field information (it probably changed), recover last operation if
+ necessary */
+ if (log_check(log) && log_open(log))
+ return -1;
+
+ /* create space for uncompressed data */
+ len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) +
+ log->stored;
+ if ((data = malloc(len)) == NULL)
+ return -2;
+
+ /* do statement here is just a cheap trick for error handling */
+ do {
+ /* read in the uncompressed data */
+ if (lseek(log->fd, log->first - 1, SEEK_SET) < 0)
+ break;
+ next = 0;
+ while (next < len) {
+ if (read(log->fd, buf, 5) != 5)
+ break;
+ block = PULL2(buf + 1);
+ if (next + block > len ||
+ read(log->fd, (char *)data + next, block) != block)
+ break;
+ next += block;
+ }
+ if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored)
+ break;
+ log_touch(log);
+
+ /* write the uncompressed data to the .add file */
+ strcpy(log->end, ".add");
+ fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0)
+ break;
+ ret = (size_t)write(fd, data, len) != len;
+ if (ret | close(fd))
+ break;
+ log_touch(log);
+
+ /* write the dictionary for the next compress to the .temp file */
+ strcpy(log->end, ".temp");
+ fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0)
+ break;
+ next = DICT > len ? len : DICT;
+ ret = (size_t)write(fd, (char *)data + len - next, next) != next;
+ if (ret | close(fd))
+ break;
+ log_touch(log);
+
+ /* roll back to compressed data, mark the compress in progress */
+ log->last = log->first;
+ log->stored = 0;
+ if (log_mark(log, COMPRESS_OP))
+ break;
+ BAIL(7);
+
+ /* compress and append the data (clears mark) */
+ ret = log_compress(log, data, len);
+ free(data);
+ return ret;
+ } while (0);
+
+ /* broke out of do above on i/o error */
+ free(data);
+ return -1;
+}
+
+/* gzlog_write() return values:
+ 0: all good
+ -1: file i/o error (usually access issue)
+ -2: memory allocation failure
+ -3: invalid log pointer argument */
+int gzlog_write(gzlog *logd, void *data, size_t len)
+{
+ int fd, ret;
+ struct log *log = logd;
+
+ /* check arguments */
+ if (log == NULL || strcmp(log->id, LOGID))
+ return -3;
+ if (data == NULL || len <= 0)
+ return 0;
+
+ /* see if we lost the lock -- if so get it again and reload the extra
+ field information (it probably changed), recover last operation if
+ necessary */
+ if (log_check(log) && log_open(log))
+ return -1;
+
+ /* create and write .add file */
+ strcpy(log->end, ".add");
+ fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0)
+ return -1;
+ ret = (size_t)write(fd, data, len) != len;
+ if (ret | close(fd))
+ return -1;
+ log_touch(log);
+
+ /* mark log file with append in progress */
+ if (log_mark(log, APPEND_OP))
+ return -1;
+ BAIL(8);
+
+ /* append data (clears mark) */
+ if (log_append(log, data, len))
+ return -1;
+
+ /* check to see if it's time to compress -- if not, then done */
+ if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER)
+ return 0;
+
+ /* time to compress */
+ return gzlog_compress(log);
+}
+
+/* gzlog_close() return values:
+ 0: ok
+ -3: invalid log pointer argument */
+int gzlog_close(gzlog *logd)
+{
+ struct log *log = logd;
+
+ /* check arguments */
+ if (log == NULL || strcmp(log->id, LOGID))
+ return -3;
+
+ /* close the log file and release the lock */
+ log_close(log);
+
+ /* free structure and return */
+ if (log->path != NULL)
+ free(log->path);
+ strcpy(log->id, "bad");
+ free(log);
+ return 0;
+}
diff --git a/libmariadb/external/zlib/examples/gzlog.h b/libmariadb/external/zlib/examples/gzlog.h
new file mode 100644
index 00000000..86f0cecb
--- /dev/null
+++ b/libmariadb/external/zlib/examples/gzlog.h
@@ -0,0 +1,91 @@
+/* gzlog.h
+ Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved
+ version 2.2, 14 Aug 2012
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Mark Adler madler@alumni.caltech.edu
+ */
+
+/* Version History:
+ 1.0 26 Nov 2004 First version
+ 2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations
+ Interface changed slightly in that now path is a prefix
+ Compression now occurs as needed during gzlog_write()
+ gzlog_write() now always leaves the log file as valid gzip
+ 2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write()
+ 2.2 14 Aug 2012 Clean up signed comparisons
+ */
+
+/*
+ The gzlog object allows writing short messages to a gzipped log file,
+ opening the log file locked for small bursts, and then closing it. The log
+ object works by appending stored (uncompressed) data to the gzip file until
+ 1 MB has been accumulated. At that time, the stored data is compressed, and
+ replaces the uncompressed data in the file. The log file is truncated to
+ its new size at that time. After each write operation, the log file is a
+ valid gzip file that can decompressed to recover what was written.
+
+ The gzlog operations can be interupted at any point due to an application or
+ system crash, and the log file will be recovered the next time the log is
+ opened with gzlog_open().
+ */
+
+#ifndef GZLOG_H
+#define GZLOG_H
+
+/* gzlog object type */
+typedef void gzlog;
+
+/* Open a gzlog object, creating the log file if it does not exist. Return
+ NULL on error. Note that gzlog_open() could take a while to complete if it
+ has to wait to verify that a lock is stale (possibly for five minutes), or
+ if there is significant contention with other instantiations of this object
+ when locking the resource. path is the prefix of the file names created by
+ this object. If path is "foo", then the log file will be "foo.gz", and
+ other auxiliary files will be created and destroyed during the process:
+ "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next)
+ dictionary, "foo.add" for data being added or compressed, "foo.lock" for the
+ lock file, and "foo.repairs" to log recovery operations performed due to
+ interrupted gzlog operations. A gzlog_open() followed by a gzlog_close()
+ will recover a previously interrupted operation, if any. */
+gzlog *gzlog_open(char *path);
+
+/* Write to a gzlog object. Return zero on success, -1 if there is a file i/o
+ error on any of the gzlog files (this should not happen if gzlog_open()
+ succeeded, unless the device has run out of space or leftover auxiliary
+ files have permissions or ownership that prevent their use), -2 if there is
+ a memory allocation failure, or -3 if the log argument is invalid (e.g. if
+ it was not created by gzlog_open()). This function will write data to the
+ file uncompressed, until 1 MB has been accumulated, at which time that data
+ will be compressed. The log file will be a valid gzip file upon successful
+ return. */
+int gzlog_write(gzlog *log, void *data, size_t len);
+
+/* Force compression of any uncompressed data in the log. This should be used
+ sparingly, if at all. The main application would be when a log file will
+ not be appended to again. If this is used to compress frequently while
+ appending, it will both significantly increase the execution time and
+ reduce the compression ratio. The return codes are the same as for
+ gzlog_write(). */
+int gzlog_compress(gzlog *log);
+
+/* Close a gzlog object. Return zero on success, -3 if the log argument is
+ invalid. The log object is freed, and so cannot be referenced again. */
+int gzlog_close(gzlog *log);
+
+#endif
diff --git a/libmariadb/external/zlib/examples/zlib_how.html b/libmariadb/external/zlib/examples/zlib_how.html
new file mode 100644
index 00000000..444ff1c9
--- /dev/null
+++ b/libmariadb/external/zlib/examples/zlib_how.html
@@ -0,0 +1,545 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+ "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>zlib Usage Example</title>
+<!-- Copyright (c) 2004, 2005 Mark Adler. -->
+</head>
+<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#00A000">
+<h2 align="center"> zlib Usage Example </h2>
+We often get questions about how the <tt>deflate()</tt> and <tt>inflate()</tt> functions should be used.
+Users wonder when they should provide more input, when they should use more output,
+what to do with a <tt>Z_BUF_ERROR</tt>, how to make sure the process terminates properly, and
+so on. So for those who have read <tt>zlib.h</tt> (a few times), and
+would like further edification, below is an annotated example in C of simple routines to compress and decompress
+from an input file to an output file using <tt>deflate()</tt> and <tt>inflate()</tt> respectively. The
+annotations are interspersed between lines of the code. So please read between the lines.
+We hope this helps explain some of the intricacies of <em>zlib</em>.
+<p>
+Without further adieu, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a>:
+<pre><b>
+/* zpipe.c: example of proper use of zlib's inflate() and deflate()
+ Not copyrighted -- provided to the public domain
+ Version 1.4 11 December 2005 Mark Adler */
+
+/* Version history:
+ 1.0 30 Oct 2004 First version
+ 1.1 8 Nov 2004 Add void casting for unused return values
+ Use switch statement for inflate() return values
+ 1.2 9 Nov 2004 Add assertions to document zlib guarantees
+ 1.3 6 Apr 2005 Remove incorrect assertion in inf()
+ 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions
+ Avoid some compiler warnings for input and output buffers
+ */
+</b></pre><!-- -->
+We now include the header files for the required definitions. From
+<tt>stdio.h</tt> we use <tt>fopen()</tt>, <tt>fread()</tt>, <tt>fwrite()</tt>,
+<tt>feof()</tt>, <tt>ferror()</tt>, and <tt>fclose()</tt> for file i/o, and
+<tt>fputs()</tt> for error messages. From <tt>string.h</tt> we use
+<tt>strcmp()</tt> for command line argument processing.
+From <tt>assert.h</tt> we use the <tt>assert()</tt> macro.
+From <tt>zlib.h</tt>
+we use the basic compression functions <tt>deflateInit()</tt>,
+<tt>deflate()</tt>, and <tt>deflateEnd()</tt>, and the basic decompression
+functions <tt>inflateInit()</tt>, <tt>inflate()</tt>, and
+<tt>inflateEnd()</tt>.
+<pre><b>
+#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;
+#include &lt;assert.h&gt;
+#include "zlib.h"
+</b></pre><!-- -->
+This is an ugly hack required to avoid corruption of the input and output data on
+Windows/MS-DOS systems. Without this, those systems would assume that the input and output
+files are text, and try to convert the end-of-line characters from one standard to
+another. That would corrupt binary data, and in particular would render the compressed data unusable.
+This sets the input and output to binary which suppresses the end-of-line conversions.
+<tt>SET_BINARY_MODE()</tt> will be used later on <tt>stdin</tt> and <tt>stdout</tt>, at the beginning of <tt>main()</tt>.
+<pre><b>
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+# include &lt;fcntl.h&gt;
+# include &lt;io.h&gt;
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+</b></pre><!-- -->
+<tt>CHUNK</tt> is simply the buffer size for feeding data to and pulling data
+from the <em>zlib</em> routines. Larger buffer sizes would be more efficient,
+especially for <tt>inflate()</tt>. If the memory is available, buffers sizes
+on the order of 128K or 256K bytes should be used.
+<pre><b>
+#define CHUNK 16384
+</b></pre><!-- -->
+The <tt>def()</tt> routine compresses data from an input file to an output file. The output data
+will be in the <em>zlib</em> format, which is different from the <em>gzip</em> or <em>zip</em>
+formats. The <em>zlib</em> format has a very small header of only two bytes to identify it as
+a <em>zlib</em> stream and to provide decoding information, and a four-byte trailer with a fast
+check value to verify the integrity of the uncompressed data after decoding.
+<pre><b>
+/* Compress from file source to file dest until EOF on source.
+ def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+ allocated for processing, Z_STREAM_ERROR if an invalid compression
+ level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+ version of the library linked do not match, or Z_ERRNO if there is
+ an error reading or writing the files. */
+int def(FILE *source, FILE *dest, int level)
+{
+</b></pre>
+Here are the local variables for <tt>def()</tt>. <tt>ret</tt> will be used for <em>zlib</em>
+return codes. <tt>flush</tt> will keep track of the current flushing state for <tt>deflate()</tt>,
+which is either no flushing, or flush to completion after the end of the input file is reached.
+<tt>have</tt> is the amount of data returned from <tt>deflate()</tt>. The <tt>strm</tt> structure
+is used to pass information to and from the <em>zlib</em> routines, and to maintain the
+<tt>deflate()</tt> state. <tt>in</tt> and <tt>out</tt> are the input and output buffers for
+<tt>deflate()</tt>.
+<pre><b>
+ int ret, flush;
+ unsigned have;
+ z_stream strm;
+ unsigned char in[CHUNK];
+ unsigned char out[CHUNK];
+</b></pre><!-- -->
+The first thing we do is to initialize the <em>zlib</em> state for compression using
+<tt>deflateInit()</tt>. This must be done before the first use of <tt>deflate()</tt>.
+The <tt>zalloc</tt>, <tt>zfree</tt>, and <tt>opaque</tt> fields in the <tt>strm</tt>
+structure must be initialized before calling <tt>deflateInit()</tt>. Here they are
+set to the <em>zlib</em> constant <tt>Z_NULL</tt> to request that <em>zlib</em> use
+the default memory allocation routines. An application may also choose to provide
+custom memory allocation routines here. <tt>deflateInit()</tt> will allocate on the
+order of 256K bytes for the internal state.
+(See <a href="zlib_tech.html"><em>zlib Technical Details</em></a>.)
+<p>
+<tt>deflateInit()</tt> is called with a pointer to the structure to be initialized and
+the compression level, which is an integer in the range of -1 to 9. Lower compression
+levels result in faster execution, but less compression. Higher levels result in
+greater compression, but slower execution. The <em>zlib</em> constant Z_DEFAULT_COMPRESSION,
+equal to -1,
+provides a good compromise between compression and speed and is equivalent to level 6.
+Level 0 actually does no compression at all, and in fact expands the data slightly to produce
+the <em>zlib</em> format (it is not a byte-for-byte copy of the input).
+More advanced applications of <em>zlib</em>
+may use <tt>deflateInit2()</tt> here instead. Such an application may want to reduce how
+much memory will be used, at some price in compression. Or it may need to request a
+<em>gzip</em> header and trailer instead of a <em>zlib</em> header and trailer, or raw
+encoding with no header or trailer at all.
+<p>
+We must check the return value of <tt>deflateInit()</tt> against the <em>zlib</em> constant
+<tt>Z_OK</tt> to make sure that it was able to
+allocate memory for the internal state, and that the provided arguments were valid.
+<tt>deflateInit()</tt> will also check that the version of <em>zlib</em> that the <tt>zlib.h</tt>
+file came from matches the version of <em>zlib</em> actually linked with the program. This
+is especially important for environments in which <em>zlib</em> is a shared library.
+<p>
+Note that an application can initialize multiple, independent <em>zlib</em> streams, which can
+operate in parallel. The state information maintained in the structure allows the <em>zlib</em>
+routines to be reentrant.
+<pre><b>
+ /* allocate deflate state */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ ret = deflateInit(&amp;strm, level);
+ if (ret != Z_OK)
+ return ret;
+</b></pre><!-- -->
+With the pleasantries out of the way, now we can get down to business. The outer <tt>do</tt>-loop
+reads all of the input file and exits at the bottom of the loop once end-of-file is reached.
+This loop contains the only call of <tt>deflate()</tt>. So we must make sure that all of the
+input data has been processed and that all of the output data has been generated and consumed
+before we fall out of the loop at the bottom.
+<pre><b>
+ /* compress until end of file */
+ do {
+</b></pre>
+We start off by reading data from the input file. The number of bytes read is put directly
+into <tt>avail_in</tt>, and a pointer to those bytes is put into <tt>next_in</tt>. We also
+check to see if end-of-file on the input has been reached. If we are at the end of file, then <tt>flush</tt> is set to the
+<em>zlib</em> constant <tt>Z_FINISH</tt>, which is later passed to <tt>deflate()</tt> to
+indicate that this is the last chunk of input data to compress. We need to use <tt>feof()</tt>
+to check for end-of-file as opposed to seeing if fewer than <tt>CHUNK</tt> bytes have been read. The
+reason is that if the input file length is an exact multiple of <tt>CHUNK</tt>, we will miss
+the fact that we got to the end-of-file, and not know to tell <tt>deflate()</tt> to finish
+up the compressed stream. If we are not yet at the end of the input, then the <em>zlib</em>
+constant <tt>Z_NO_FLUSH</tt> will be passed to <tt>deflate</tt> to indicate that we are still
+in the middle of the uncompressed data.
+<p>
+If there is an error in reading from the input file, the process is aborted with
+<tt>deflateEnd()</tt> being called to free the allocated <em>zlib</em> state before returning
+the error. We wouldn't want a memory leak, now would we? <tt>deflateEnd()</tt> can be called
+at any time after the state has been initialized. Once that's done, <tt>deflateInit()</tt> (or
+<tt>deflateInit2()</tt>) would have to be called to start a new compression process. There is
+no point here in checking the <tt>deflateEnd()</tt> return code. The deallocation can't fail.
+<pre><b>
+ strm.avail_in = fread(in, 1, CHUNK, source);
+ if (ferror(source)) {
+ (void)deflateEnd(&amp;strm);
+ return Z_ERRNO;
+ }
+ flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
+ strm.next_in = in;
+</b></pre><!-- -->
+The inner <tt>do</tt>-loop passes our chunk of input data to <tt>deflate()</tt>, and then
+keeps calling <tt>deflate()</tt> until it is done producing output. Once there is no more
+new output, <tt>deflate()</tt> is guaranteed to have consumed all of the input, i.e.,
+<tt>avail_in</tt> will be zero.
+<pre><b>
+ /* run deflate() on input until output buffer not full, finish
+ compression if all of source has been read in */
+ do {
+</b></pre>
+Output space is provided to <tt>deflate()</tt> by setting <tt>avail_out</tt> to the number
+of available output bytes and <tt>next_out</tt> to a pointer to that space.
+<pre><b>
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+</b></pre>
+Now we call the compression engine itself, <tt>deflate()</tt>. It takes as many of the
+<tt>avail_in</tt> bytes at <tt>next_in</tt> as it can process, and writes as many as
+<tt>avail_out</tt> bytes to <tt>next_out</tt>. Those counters and pointers are then
+updated past the input data consumed and the output data written. It is the amount of
+output space available that may limit how much input is consumed.
+Hence the inner loop to make sure that
+all of the input is consumed by providing more output space each time. Since <tt>avail_in</tt>
+and <tt>next_in</tt> are updated by <tt>deflate()</tt>, we don't have to mess with those
+between <tt>deflate()</tt> calls until it's all used up.
+<p>
+The parameters to <tt>deflate()</tt> are a pointer to the <tt>strm</tt> structure containing
+the input and output information and the internal compression engine state, and a parameter
+indicating whether and how to flush data to the output. Normally <tt>deflate</tt> will consume
+several K bytes of input data before producing any output (except for the header), in order
+to accumulate statistics on the data for optimum compression. It will then put out a burst of
+compressed data, and proceed to consume more input before the next burst. Eventually,
+<tt>deflate()</tt>
+must be told to terminate the stream, complete the compression with provided input data, and
+write out the trailer check value. <tt>deflate()</tt> will continue to compress normally as long
+as the flush parameter is <tt>Z_NO_FLUSH</tt>. Once the <tt>Z_FINISH</tt> parameter is provided,
+<tt>deflate()</tt> will begin to complete the compressed output stream. However depending on how
+much output space is provided, <tt>deflate()</tt> may have to be called several times until it
+has provided the complete compressed stream, even after it has consumed all of the input. The flush
+parameter must continue to be <tt>Z_FINISH</tt> for those subsequent calls.
+<p>
+There are other values of the flush parameter that are used in more advanced applications. You can
+force <tt>deflate()</tt> to produce a burst of output that encodes all of the input data provided
+so far, even if it wouldn't have otherwise, for example to control data latency on a link with
+compressed data. You can also ask that <tt>deflate()</tt> do that as well as erase any history up to
+that point so that what follows can be decompressed independently, for example for random access
+applications. Both requests will degrade compression by an amount depending on how often such
+requests are made.
+<p>
+<tt>deflate()</tt> has a return value that can indicate errors, yet we do not check it here. Why
+not? Well, it turns out that <tt>deflate()</tt> can do no wrong here. Let's go through
+<tt>deflate()</tt>'s return values and dispense with them one by one. The possible values are
+<tt>Z_OK</tt>, <tt>Z_STREAM_END</tt>, <tt>Z_STREAM_ERROR</tt>, or <tt>Z_BUF_ERROR</tt>. <tt>Z_OK</tt>
+is, well, ok. <tt>Z_STREAM_END</tt> is also ok and will be returned for the last call of
+<tt>deflate()</tt>. This is already guaranteed by calling <tt>deflate()</tt> with <tt>Z_FINISH</tt>
+until it has no more output. <tt>Z_STREAM_ERROR</tt> is only possible if the stream is not
+initialized properly, but we did initialize it properly. There is no harm in checking for
+<tt>Z_STREAM_ERROR</tt> here, for example to check for the possibility that some
+other part of the application inadvertently clobbered the memory containing the <em>zlib</em> state.
+<tt>Z_BUF_ERROR</tt> will be explained further below, but
+suffice it to say that this is simply an indication that <tt>deflate()</tt> could not consume
+more input or produce more output. <tt>deflate()</tt> can be called again with more output space
+or more available input, which it will be in this code.
+<pre><b>
+ ret = deflate(&amp;strm, flush); /* no bad return value */
+ assert(ret != Z_STREAM_ERROR); /* state not clobbered */
+</b></pre>
+Now we compute how much output <tt>deflate()</tt> provided on the last call, which is the
+difference between how much space was provided before the call, and how much output space
+is still available after the call. Then that data, if any, is written to the output file.
+We can then reuse the output buffer for the next call of <tt>deflate()</tt>. Again if there
+is a file i/o error, we call <tt>deflateEnd()</tt> before returning to avoid a memory leak.
+<pre><b>
+ have = CHUNK - strm.avail_out;
+ if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+ (void)deflateEnd(&amp;strm);
+ return Z_ERRNO;
+ }
+</b></pre>
+The inner <tt>do</tt>-loop is repeated until the last <tt>deflate()</tt> call fails to fill the
+provided output buffer. Then we know that <tt>deflate()</tt> has done as much as it can with
+the provided input, and that all of that input has been consumed. We can then fall out of this
+loop and reuse the input buffer.
+<p>
+The way we tell that <tt>deflate()</tt> has no more output is by seeing that it did not fill
+the output buffer, leaving <tt>avail_out</tt> greater than zero. However suppose that
+<tt>deflate()</tt> has no more output, but just so happened to exactly fill the output buffer!
+<tt>avail_out</tt> is zero, and we can't tell that <tt>deflate()</tt> has done all it can.
+As far as we know, <tt>deflate()</tt>
+has more output for us. So we call it again. But now <tt>deflate()</tt> produces no output
+at all, and <tt>avail_out</tt> remains unchanged as <tt>CHUNK</tt>. That <tt>deflate()</tt> call
+wasn't able to do anything, either consume input or produce output, and so it returns
+<tt>Z_BUF_ERROR</tt>. (See, I told you I'd cover this later.) However this is not a problem at
+all. Now we finally have the desired indication that <tt>deflate()</tt> is really done,
+and so we drop out of the inner loop to provide more input to <tt>deflate()</tt>.
+<p>
+With <tt>flush</tt> set to <tt>Z_FINISH</tt>, this final set of <tt>deflate()</tt> calls will
+complete the output stream. Once that is done, subsequent calls of <tt>deflate()</tt> would return
+<tt>Z_STREAM_ERROR</tt> if the flush parameter is not <tt>Z_FINISH</tt>, and do no more processing
+until the state is reinitialized.
+<p>
+Some applications of <em>zlib</em> have two loops that call <tt>deflate()</tt>
+instead of the single inner loop we have here. The first loop would call
+without flushing and feed all of the data to <tt>deflate()</tt>. The second loop would call
+<tt>deflate()</tt> with no more
+data and the <tt>Z_FINISH</tt> parameter to complete the process. As you can see from this
+example, that can be avoided by simply keeping track of the current flush state.
+<pre><b>
+ } while (strm.avail_out == 0);
+ assert(strm.avail_in == 0); /* all input will be used */
+</b></pre><!-- -->
+Now we check to see if we have already processed all of the input file. That information was
+saved in the <tt>flush</tt> variable, so we see if that was set to <tt>Z_FINISH</tt>. If so,
+then we're done and we fall out of the outer loop. We're guaranteed to get <tt>Z_STREAM_END</tt>
+from the last <tt>deflate()</tt> call, since we ran it until the last chunk of input was
+consumed and all of the output was generated.
+<pre><b>
+ /* done when last data in file processed */
+ } while (flush != Z_FINISH);
+ assert(ret == Z_STREAM_END); /* stream will be complete */
+</b></pre><!-- -->
+The process is complete, but we still need to deallocate the state to avoid a memory leak
+(or rather more like a memory hemorrhage if you didn't do this). Then
+finally we can return with a happy return value.
+<pre><b>
+ /* clean up and return */
+ (void)deflateEnd(&amp;strm);
+ return Z_OK;
+}
+</b></pre><!-- -->
+Now we do the same thing for decompression in the <tt>inf()</tt> routine. <tt>inf()</tt>
+decompresses what is hopefully a valid <em>zlib</em> stream from the input file and writes the
+uncompressed data to the output file. Much of the discussion above for <tt>def()</tt>
+applies to <tt>inf()</tt> as well, so the discussion here will focus on the differences between
+the two.
+<pre><b>
+/* Decompress from file source to file dest until stream ends or EOF.
+ inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+ allocated for processing, Z_DATA_ERROR if the deflate data is
+ invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+ the version of the library linked do not match, or Z_ERRNO if there
+ is an error reading or writing the files. */
+int inf(FILE *source, FILE *dest)
+{
+</b></pre>
+The local variables have the same functionality as they do for <tt>def()</tt>. The
+only difference is that there is no <tt>flush</tt> variable, since <tt>inflate()</tt>
+can tell from the <em>zlib</em> stream itself when the stream is complete.
+<pre><b>
+ int ret;
+ unsigned have;
+ z_stream strm;
+ unsigned char in[CHUNK];
+ unsigned char out[CHUNK];
+</b></pre><!-- -->
+The initialization of the state is the same, except that there is no compression level,
+of course, and two more elements of the structure are initialized. <tt>avail_in</tt>
+and <tt>next_in</tt> must be initialized before calling <tt>inflateInit()</tt>. This
+is because the application has the option to provide the start of the zlib stream in
+order for <tt>inflateInit()</tt> to have access to information about the compression
+method to aid in memory allocation. In the current implementation of <em>zlib</em>
+(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of
+<tt>inflate()</tt> anyway. However those fields must be initialized since later versions
+of <em>zlib</em> that provide more compression methods may take advantage of this interface.
+In any case, no decompression is performed by <tt>inflateInit()</tt>, so the
+<tt>avail_out</tt> and <tt>next_out</tt> fields do not need to be initialized before calling.
+<p>
+Here <tt>avail_in</tt> is set to zero and <tt>next_in</tt> is set to <tt>Z_NULL</tt> to
+indicate that no input data is being provided.
+<pre><b>
+ /* allocate inflate state */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+ ret = inflateInit(&amp;strm);
+ if (ret != Z_OK)
+ return ret;
+</b></pre><!-- -->
+The outer <tt>do</tt>-loop decompresses input until <tt>inflate()</tt> indicates
+that it has reached the end of the compressed data and has produced all of the uncompressed
+output. This is in contrast to <tt>def()</tt> which processes all of the input file.
+If end-of-file is reached before the compressed data self-terminates, then the compressed
+data is incomplete and an error is returned.
+<pre><b>
+ /* decompress until deflate stream ends or end of file */
+ do {
+</b></pre>
+We read input data and set the <tt>strm</tt> structure accordingly. If we've reached the
+end of the input file, then we leave the outer loop and report an error, since the
+compressed data is incomplete. Note that we may read more data than is eventually consumed
+by <tt>inflate()</tt>, if the input file continues past the <em>zlib</em> stream.
+For applications where <em>zlib</em> streams are embedded in other data, this routine would
+need to be modified to return the unused data, or at least indicate how much of the input
+data was not used, so the application would know where to pick up after the <em>zlib</em> stream.
+<pre><b>
+ strm.avail_in = fread(in, 1, CHUNK, source);
+ if (ferror(source)) {
+ (void)inflateEnd(&amp;strm);
+ return Z_ERRNO;
+ }
+ if (strm.avail_in == 0)
+ break;
+ strm.next_in = in;
+</b></pre><!-- -->
+The inner <tt>do</tt>-loop has the same function it did in <tt>def()</tt>, which is to
+keep calling <tt>inflate()</tt> until has generated all of the output it can with the
+provided input.
+<pre><b>
+ /* run inflate() on input until output buffer not full */
+ do {
+</b></pre>
+Just like in <tt>def()</tt>, the same output space is provided for each call of <tt>inflate()</tt>.
+<pre><b>
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+</b></pre>
+Now we run the decompression engine itself. There is no need to adjust the flush parameter, since
+the <em>zlib</em> format is self-terminating. The main difference here is that there are
+return values that we need to pay attention to. <tt>Z_DATA_ERROR</tt>
+indicates that <tt>inflate()</tt> detected an error in the <em>zlib</em> compressed data format,
+which means that either the data is not a <em>zlib</em> stream to begin with, or that the data was
+corrupted somewhere along the way since it was compressed. The other error to be processed is
+<tt>Z_MEM_ERROR</tt>, which can occur since memory allocation is deferred until <tt>inflate()</tt>
+needs it, unlike <tt>deflate()</tt>, whose memory is allocated at the start by <tt>deflateInit()</tt>.
+<p>
+Advanced applications may use
+<tt>deflateSetDictionary()</tt> to prime <tt>deflate()</tt> with a set of likely data to improve the
+first 32K or so of compression. This is noted in the <em>zlib</em> header, so <tt>inflate()</tt>
+requests that that dictionary be provided before it can start to decompress. Without the dictionary,
+correct decompression is not possible. For this routine, we have no idea what the dictionary is,
+so the <tt>Z_NEED_DICT</tt> indication is converted to a <tt>Z_DATA_ERROR</tt>.
+<p>
+<tt>inflate()</tt> can also return <tt>Z_STREAM_ERROR</tt>, which should not be possible here,
+but could be checked for as noted above for <tt>def()</tt>. <tt>Z_BUF_ERROR</tt> does not need to be
+checked for here, for the same reasons noted for <tt>def()</tt>. <tt>Z_STREAM_END</tt> will be
+checked for later.
+<pre><b>
+ ret = inflate(&amp;strm, Z_NO_FLUSH);
+ assert(ret != Z_STREAM_ERROR); /* state not clobbered */
+ switch (ret) {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR; /* and fall through */
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ (void)inflateEnd(&amp;strm);
+ return ret;
+ }
+</b></pre>
+The output of <tt>inflate()</tt> is handled identically to that of <tt>deflate()</tt>.
+<pre><b>
+ have = CHUNK - strm.avail_out;
+ if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+ (void)inflateEnd(&amp;strm);
+ return Z_ERRNO;
+ }
+</b></pre>
+The inner <tt>do</tt>-loop ends when <tt>inflate()</tt> has no more output as indicated
+by not filling the output buffer, just as for <tt>deflate()</tt>. In this case, we cannot
+assert that <tt>strm.avail_in</tt> will be zero, since the deflate stream may end before the file
+does.
+<pre><b>
+ } while (strm.avail_out == 0);
+</b></pre><!-- -->
+The outer <tt>do</tt>-loop ends when <tt>inflate()</tt> reports that it has reached the
+end of the input <em>zlib</em> stream, has completed the decompression and integrity
+check, and has provided all of the output. This is indicated by the <tt>inflate()</tt>
+return value <tt>Z_STREAM_END</tt>. The inner loop is guaranteed to leave <tt>ret</tt>
+equal to <tt>Z_STREAM_END</tt> if the last chunk of the input file read contained the end
+of the <em>zlib</em> stream. So if the return value is not <tt>Z_STREAM_END</tt>, the
+loop continues to read more input.
+<pre><b>
+ /* done when inflate() says it's done */
+ } while (ret != Z_STREAM_END);
+</b></pre><!-- -->
+At this point, decompression successfully completed, or we broke out of the loop due to no
+more data being available from the input file. If the last <tt>inflate()</tt> return value
+is not <tt>Z_STREAM_END</tt>, then the <em>zlib</em> stream was incomplete and a data error
+is returned. Otherwise, we return with a happy return value. Of course, <tt>inflateEnd()</tt>
+is called first to avoid a memory leak.
+<pre><b>
+ /* clean up and return */
+ (void)inflateEnd(&amp;strm);
+ return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+</b></pre><!-- -->
+That ends the routines that directly use <em>zlib</em>. The following routines make this
+a command-line program by running data through the above routines from <tt>stdin</tt> to
+<tt>stdout</tt>, and handling any errors reported by <tt>def()</tt> or <tt>inf()</tt>.
+<p>
+<tt>zerr()</tt> is used to interpret the possible error codes from <tt>def()</tt>
+and <tt>inf()</tt>, as detailed in their comments above, and print out an error message.
+Note that these are only a subset of the possible return values from <tt>deflate()</tt>
+and <tt>inflate()</tt>.
+<pre><b>
+/* report a zlib or i/o error */
+void zerr(int ret)
+{
+ fputs("zpipe: ", stderr);
+ switch (ret) {
+ case Z_ERRNO:
+ if (ferror(stdin))
+ fputs("error reading stdin\n", stderr);
+ if (ferror(stdout))
+ fputs("error writing stdout\n", stderr);
+ break;
+ case Z_STREAM_ERROR:
+ fputs("invalid compression level\n", stderr);
+ break;
+ case Z_DATA_ERROR:
+ fputs("invalid or incomplete deflate data\n", stderr);
+ break;
+ case Z_MEM_ERROR:
+ fputs("out of memory\n", stderr);
+ break;
+ case Z_VERSION_ERROR:
+ fputs("zlib version mismatch!\n", stderr);
+ }
+}
+</b></pre><!-- -->
+Here is the <tt>main()</tt> routine used to test <tt>def()</tt> and <tt>inf()</tt>. The
+<tt>zpipe</tt> command is simply a compression pipe from <tt>stdin</tt> to <tt>stdout</tt>, if
+no arguments are given, or it is a decompression pipe if <tt>zpipe -d</tt> is used. If any other
+arguments are provided, no compression or decompression is performed. Instead a usage
+message is displayed. Examples are <tt>zpipe < foo.txt > foo.txt.z</tt> to compress, and
+<tt>zpipe -d < foo.txt.z > foo.txt</tt> to decompress.
+<pre><b>
+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+ int ret;
+
+ /* avoid end-of-line conversions */
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+
+ /* do compression if no arguments */
+ if (argc == 1) {
+ ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
+ if (ret != Z_OK)
+ zerr(ret);
+ return ret;
+ }
+
+ /* do decompression if -d specified */
+ else if (argc == 2 &amp;&amp; strcmp(argv[1], "-d") == 0) {
+ ret = inf(stdin, stdout);
+ if (ret != Z_OK)
+ zerr(ret);
+ return ret;
+ }
+
+ /* otherwise, report usage */
+ else {
+ fputs("zpipe usage: zpipe [-d] &lt; source &gt; dest\n", stderr);
+ return 1;
+ }
+}
+</b></pre>
+<hr>
+<i>Copyright (c) 2004, 2005 by Mark Adler<br>Last modified 11 December 2005</i>
+</body>
+</html>
diff --git a/libmariadb/external/zlib/examples/zpipe.c b/libmariadb/external/zlib/examples/zpipe.c
new file mode 100644
index 00000000..83535d16
--- /dev/null
+++ b/libmariadb/external/zlib/examples/zpipe.c
@@ -0,0 +1,205 @@
+/* zpipe.c: example of proper use of zlib's inflate() and deflate()
+ Not copyrighted -- provided to the public domain
+ Version 1.4 11 December 2005 Mark Adler */
+
+/* Version history:
+ 1.0 30 Oct 2004 First version
+ 1.1 8 Nov 2004 Add void casting for unused return values
+ Use switch statement for inflate() return values
+ 1.2 9 Nov 2004 Add assertions to document zlib guarantees
+ 1.3 6 Apr 2005 Remove incorrect assertion in inf()
+ 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions
+ Avoid some compiler warnings for input and output buffers
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "zlib.h"
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#define CHUNK 16384
+
+/* Compress from file source to file dest until EOF on source.
+ def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+ allocated for processing, Z_STREAM_ERROR if an invalid compression
+ level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+ version of the library linked do not match, or Z_ERRNO if there is
+ an error reading or writing the files. */
+int def(FILE *source, FILE *dest, int level)
+{
+ int ret, flush;
+ unsigned have;
+ z_stream strm;
+ unsigned char in[CHUNK];
+ unsigned char out[CHUNK];
+
+ /* allocate deflate state */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ ret = deflateInit(&strm, level);
+ if (ret != Z_OK)
+ return ret;
+
+ /* compress until end of file */
+ do {
+ strm.avail_in = fread(in, 1, CHUNK, source);
+ if (ferror(source)) {
+ (void)deflateEnd(&strm);
+ return Z_ERRNO;
+ }
+ flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
+ strm.next_in = in;
+
+ /* run deflate() on input until output buffer not full, finish
+ compression if all of source has been read in */
+ do {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+ ret = deflate(&strm, flush); /* no bad return value */
+ assert(ret != Z_STREAM_ERROR); /* state not clobbered */
+ have = CHUNK - strm.avail_out;
+ if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+ (void)deflateEnd(&strm);
+ return Z_ERRNO;
+ }
+ } while (strm.avail_out == 0);
+ assert(strm.avail_in == 0); /* all input will be used */
+
+ /* done when last data in file processed */
+ } while (flush != Z_FINISH);
+ assert(ret == Z_STREAM_END); /* stream will be complete */
+
+ /* clean up and return */
+ (void)deflateEnd(&strm);
+ return Z_OK;
+}
+
+/* Decompress from file source to file dest until stream ends or EOF.
+ inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+ allocated for processing, Z_DATA_ERROR if the deflate data is
+ invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+ the version of the library linked do not match, or Z_ERRNO if there
+ is an error reading or writing the files. */
+int inf(FILE *source, FILE *dest)
+{
+ int ret;
+ unsigned have;
+ z_stream strm;
+ unsigned char in[CHUNK];
+ unsigned char out[CHUNK];
+
+ /* allocate inflate state */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+ ret = inflateInit(&strm);
+ if (ret != Z_OK)
+ return ret;
+
+ /* decompress until deflate stream ends or end of file */
+ do {
+ strm.avail_in = fread(in, 1, CHUNK, source);
+ if (ferror(source)) {
+ (void)inflateEnd(&strm);
+ return Z_ERRNO;
+ }
+ if (strm.avail_in == 0)
+ break;
+ strm.next_in = in;
+
+ /* run inflate() on input until output buffer not full */
+ do {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+ ret = inflate(&strm, Z_NO_FLUSH);
+ assert(ret != Z_STREAM_ERROR); /* state not clobbered */
+ switch (ret) {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR; /* and fall through */
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ (void)inflateEnd(&strm);
+ return ret;
+ }
+ have = CHUNK - strm.avail_out;
+ if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+ (void)inflateEnd(&strm);
+ return Z_ERRNO;
+ }
+ } while (strm.avail_out == 0);
+
+ /* done when inflate() says it's done */
+ } while (ret != Z_STREAM_END);
+
+ /* clean up and return */
+ (void)inflateEnd(&strm);
+ return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+
+/* report a zlib or i/o error */
+void zerr(int ret)
+{
+ fputs("zpipe: ", stderr);
+ switch (ret) {
+ case Z_ERRNO:
+ if (ferror(stdin))
+ fputs("error reading stdin\n", stderr);
+ if (ferror(stdout))
+ fputs("error writing stdout\n", stderr);
+ break;
+ case Z_STREAM_ERROR:
+ fputs("invalid compression level\n", stderr);
+ break;
+ case Z_DATA_ERROR:
+ fputs("invalid or incomplete deflate data\n", stderr);
+ break;
+ case Z_MEM_ERROR:
+ fputs("out of memory\n", stderr);
+ break;
+ case Z_VERSION_ERROR:
+ fputs("zlib version mismatch!\n", stderr);
+ }
+}
+
+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+ int ret;
+
+ /* avoid end-of-line conversions */
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+
+ /* do compression if no arguments */
+ if (argc == 1) {
+ ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
+ if (ret != Z_OK)
+ zerr(ret);
+ return ret;
+ }
+
+ /* do decompression if -d specified */
+ else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
+ ret = inf(stdin, stdout);
+ if (ret != Z_OK)
+ zerr(ret);
+ return ret;
+ }
+
+ /* otherwise, report usage */
+ else {
+ fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
+ return 1;
+ }
+}
diff --git a/libmariadb/external/zlib/examples/zran.c b/libmariadb/external/zlib/examples/zran.c
new file mode 100644
index 00000000..278f9ad0
--- /dev/null
+++ b/libmariadb/external/zlib/examples/zran.c
@@ -0,0 +1,409 @@
+/* zran.c -- example of zlib/gzip stream indexing and random access
+ * Copyright (C) 2005, 2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ Version 1.1 29 Sep 2012 Mark Adler */
+
+/* Version History:
+ 1.0 29 May 2005 First version
+ 1.1 29 Sep 2012 Fix memory reallocation error
+ */
+
+/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
+ for random access of a compressed file. A file containing a zlib or gzip
+ stream is provided on the command line. The compressed stream is decoded in
+ its entirety, and an index built with access points about every SPAN bytes
+ in the uncompressed output. The compressed file is left open, and can then
+ be read randomly, having to decompress on the average SPAN/2 uncompressed
+ bytes before getting to the desired block of data.
+
+ An access point can be created at the start of any deflate block, by saving
+ the starting file offset and bit of that block, and the 32K bytes of
+ uncompressed data that precede that block. Also the uncompressed offset of
+ that block is saved to provide a referece for locating a desired starting
+ point in the uncompressed stream. build_index() works by decompressing the
+ input zlib or gzip stream a block at a time, and at the end of each block
+ deciding if enough uncompressed data has gone by to justify the creation of
+ a new access point. If so, that point is saved in a data structure that
+ grows as needed to accommodate the points.
+
+ To use the index, an offset in the uncompressed data is provided, for which
+ the latest accees point at or preceding that offset is located in the index.
+ The input file is positioned to the specified location in the index, and if
+ necessary the first few bits of the compressed data is read from the file.
+ inflate is initialized with those bits and the 32K of uncompressed data, and
+ the decompression then proceeds until the desired offset in the file is
+ reached. Then the decompression continues to read the desired uncompressed
+ data from the file.
+
+ Another approach would be to generate the index on demand. In that case,
+ requests for random access reads from the compressed data would try to use
+ the index, but if a read far enough past the end of the index is required,
+ then further index entries would be generated and added.
+
+ There is some fair bit of overhead to starting inflation for the random
+ access, mainly copying the 32K byte dictionary. So if small pieces of the
+ file are being accessed, it would make sense to implement a cache to hold
+ some lookahead and avoid many calls to extract() for small lengths.
+
+ Another way to build an index would be to use inflateCopy(). That would
+ not be constrained to have access points at block boundaries, but requires
+ more memory per access point, and also cannot be saved to file due to the
+ use of pointers in the state. The approach here allows for storage of the
+ index in a file.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+
+#define local static
+
+#define SPAN 1048576L /* desired distance between access points */
+#define WINSIZE 32768U /* sliding window size */
+#define CHUNK 16384 /* file input buffer size */
+
+/* access point entry */
+struct point {
+ off_t out; /* corresponding offset in uncompressed data */
+ off_t in; /* offset in input file of first full byte */
+ int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
+ unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */
+};
+
+/* access point list */
+struct access {
+ int have; /* number of list entries filled in */
+ int size; /* number of list entries allocated */
+ struct point *list; /* allocated list */
+};
+
+/* Deallocate an index built by build_index() */
+local void free_index(struct access *index)
+{
+ if (index != NULL) {
+ free(index->list);
+ free(index);
+ }
+}
+
+/* Add an entry to the access point list. If out of memory, deallocate the
+ existing list and return NULL. */
+local struct access *addpoint(struct access *index, int bits,
+ off_t in, off_t out, unsigned left, unsigned char *window)
+{
+ struct point *next;
+
+ /* if list is empty, create it (start with eight points) */
+ if (index == NULL) {
+ index = malloc(sizeof(struct access));
+ if (index == NULL) return NULL;
+ index->list = malloc(sizeof(struct point) << 3);
+ if (index->list == NULL) {
+ free(index);
+ return NULL;
+ }
+ index->size = 8;
+ index->have = 0;
+ }
+
+ /* if list is full, make it bigger */
+ else if (index->have == index->size) {
+ index->size <<= 1;
+ next = realloc(index->list, sizeof(struct point) * index->size);
+ if (next == NULL) {
+ free_index(index);
+ return NULL;
+ }
+ index->list = next;
+ }
+
+ /* fill in entry and increment how many we have */
+ next = index->list + index->have;
+ next->bits = bits;
+ next->in = in;
+ next->out = out;
+ if (left)
+ memcpy(next->window, window + WINSIZE - left, left);
+ if (left < WINSIZE)
+ memcpy(next->window + left, window, WINSIZE - left);
+ index->have++;
+
+ /* return list, possibly reallocated */
+ return index;
+}
+
+/* Make one entire pass through the compressed stream and build an index, with
+ access points about every span bytes of uncompressed output -- span is
+ chosen to balance the speed of random access against the memory requirements
+ of the list, about 32K bytes per access point. Note that data after the end
+ of the first zlib or gzip stream in the file is ignored. build_index()
+ returns the number of access points on success (>= 1), Z_MEM_ERROR for out
+ of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
+ file read error. On success, *built points to the resulting index. */
+local int build_index(FILE *in, off_t span, struct access **built)
+{
+ int ret;
+ off_t totin, totout; /* our own total counters to avoid 4GB limit */
+ off_t last; /* totout value of last access point */
+ struct access *index; /* access points being generated */
+ z_stream strm;
+ unsigned char input[CHUNK];
+ unsigned char window[WINSIZE];
+
+ /* initialize inflate */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+ ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */
+ if (ret != Z_OK)
+ return ret;
+
+ /* inflate the input, maintain a sliding window, and build an index -- this
+ also validates the integrity of the compressed data using the check
+ information at the end of the gzip or zlib stream */
+ totin = totout = last = 0;
+ index = NULL; /* will be allocated by first addpoint() */
+ strm.avail_out = 0;
+ do {
+ /* get some compressed data from input file */
+ strm.avail_in = fread(input, 1, CHUNK, in);
+ if (ferror(in)) {
+ ret = Z_ERRNO;
+ goto build_index_error;
+ }
+ if (strm.avail_in == 0) {
+ ret = Z_DATA_ERROR;
+ goto build_index_error;
+ }
+ strm.next_in = input;
+
+ /* process all of that, or until end of stream */
+ do {
+ /* reset sliding window if necessary */
+ if (strm.avail_out == 0) {
+ strm.avail_out = WINSIZE;
+ strm.next_out = window;
+ }
+
+ /* inflate until out of input, output, or at end of block --
+ update the total input and output counters */
+ totin += strm.avail_in;
+ totout += strm.avail_out;
+ ret = inflate(&strm, Z_BLOCK); /* return at end of block */
+ totin -= strm.avail_in;
+ totout -= strm.avail_out;
+ if (ret == Z_NEED_DICT)
+ ret = Z_DATA_ERROR;
+ if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
+ goto build_index_error;
+ if (ret == Z_STREAM_END)
+ break;
+
+ /* if at end of block, consider adding an index entry (note that if
+ data_type indicates an end-of-block, then all of the
+ uncompressed data from that block has been delivered, and none
+ of the compressed data after that block has been consumed,
+ except for up to seven bits) -- the totout == 0 provides an
+ entry point after the zlib or gzip header, and assures that the
+ index always has at least one access point; we avoid creating an
+ access point after the last block by checking bit 6 of data_type
+ */
+ if ((strm.data_type & 128) && !(strm.data_type & 64) &&
+ (totout == 0 || totout - last > span)) {
+ index = addpoint(index, strm.data_type & 7, totin,
+ totout, strm.avail_out, window);
+ if (index == NULL) {
+ ret = Z_MEM_ERROR;
+ goto build_index_error;
+ }
+ last = totout;
+ }
+ } while (strm.avail_in != 0);
+ } while (ret != Z_STREAM_END);
+
+ /* clean up and return index (release unused entries in list) */
+ (void)inflateEnd(&strm);
+ index->list = realloc(index->list, sizeof(struct point) * index->have);
+ index->size = index->have;
+ *built = index;
+ return index->size;
+
+ /* return error */
+ build_index_error:
+ (void)inflateEnd(&strm);
+ if (index != NULL)
+ free_index(index);
+ return ret;
+}
+
+/* Use the index to read len bytes from offset into buf, return bytes read or
+ negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past
+ the end of the uncompressed data, then extract() will return a value less
+ than len, indicating how much as actually read into buf. This function
+ should not return a data error unless the file was modified since the index
+ was generated. extract() may also return Z_ERRNO if there is an error on
+ reading or seeking the input file. */
+local int extract(FILE *in, struct access *index, off_t offset,
+ unsigned char *buf, int len)
+{
+ int ret, skip;
+ z_stream strm;
+ struct point *here;
+ unsigned char input[CHUNK];
+ unsigned char discard[WINSIZE];
+
+ /* proceed only if something reasonable to do */
+ if (len < 0)
+ return 0;
+
+ /* find where in stream to start */
+ here = index->list;
+ ret = index->have;
+ while (--ret && here[1].out <= offset)
+ here++;
+
+ /* initialize file and inflate state to start there */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+ ret = inflateInit2(&strm, -15); /* raw inflate */
+ if (ret != Z_OK)
+ return ret;
+ ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
+ if (ret == -1)
+ goto extract_ret;
+ if (here->bits) {
+ ret = getc(in);
+ if (ret == -1) {
+ ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
+ goto extract_ret;
+ }
+ (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
+ }
+ (void)inflateSetDictionary(&strm, here->window, WINSIZE);
+
+ /* skip uncompressed bytes until offset reached, then satisfy request */
+ offset -= here->out;
+ strm.avail_in = 0;
+ skip = 1; /* while skipping to offset */
+ do {
+ /* define where to put uncompressed data, and how much */
+ if (offset == 0 && skip) { /* at offset now */
+ strm.avail_out = len;
+ strm.next_out = buf;
+ skip = 0; /* only do this once */
+ }
+ if (offset > WINSIZE) { /* skip WINSIZE bytes */
+ strm.avail_out = WINSIZE;
+ strm.next_out = discard;
+ offset -= WINSIZE;
+ }
+ else if (offset != 0) { /* last skip */
+ strm.avail_out = (unsigned)offset;
+ strm.next_out = discard;
+ offset = 0;
+ }
+
+ /* uncompress until avail_out filled, or end of stream */
+ do {
+ if (strm.avail_in == 0) {
+ strm.avail_in = fread(input, 1, CHUNK, in);
+ if (ferror(in)) {
+ ret = Z_ERRNO;
+ goto extract_ret;
+ }
+ if (strm.avail_in == 0) {
+ ret = Z_DATA_ERROR;
+ goto extract_ret;
+ }
+ strm.next_in = input;
+ }
+ ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */
+ if (ret == Z_NEED_DICT)
+ ret = Z_DATA_ERROR;
+ if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
+ goto extract_ret;
+ if (ret == Z_STREAM_END)
+ break;
+ } while (strm.avail_out != 0);
+
+ /* if reach end of stream, then don't keep trying to get more */
+ if (ret == Z_STREAM_END)
+ break;
+
+ /* do until offset reached and requested data read, or stream ends */
+ } while (skip);
+
+ /* compute number of uncompressed bytes read after offset */
+ ret = skip ? 0 : len - strm.avail_out;
+
+ /* clean up and return bytes read or error */
+ extract_ret:
+ (void)inflateEnd(&strm);
+ return ret;
+}
+
+/* Demonstrate the use of build_index() and extract() by processing the file
+ provided on the command line, and the extracting 16K from about 2/3rds of
+ the way through the uncompressed output, and writing that to stdout. */
+int main(int argc, char **argv)
+{
+ int len;
+ off_t offset;
+ FILE *in;
+ struct access *index = NULL;
+ unsigned char buf[CHUNK];
+
+ /* open input file */
+ if (argc != 2) {
+ fprintf(stderr, "usage: zran file.gz\n");
+ return 1;
+ }
+ in = fopen(argv[1], "rb");
+ if (in == NULL) {
+ fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
+ return 1;
+ }
+
+ /* build index */
+ len = build_index(in, SPAN, &index);
+ if (len < 0) {
+ fclose(in);
+ switch (len) {
+ case Z_MEM_ERROR:
+ fprintf(stderr, "zran: out of memory\n");
+ break;
+ case Z_DATA_ERROR:
+ fprintf(stderr, "zran: compressed data error in %s\n", argv[1]);
+ break;
+ case Z_ERRNO:
+ fprintf(stderr, "zran: read error on %s\n", argv[1]);
+ break;
+ default:
+ fprintf(stderr, "zran: error %d while building index\n", len);
+ }
+ return 1;
+ }
+ fprintf(stderr, "zran: built index with %d access points\n", len);
+
+ /* use index by reading some bytes from an arbitrary offset */
+ offset = (index->list[index->have - 1].out << 1) / 3;
+ len = extract(in, index, offset, buf, CHUNK);
+ if (len < 0)
+ fprintf(stderr, "zran: extraction failed: %s error\n",
+ len == Z_MEM_ERROR ? "out of memory" : "input corrupted");
+ else {
+ fwrite(buf, 1, len, stdout);
+ fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset);
+ }
+
+ /* clean up and exit */
+ free_index(index);
+ fclose(in);
+ return 0;
+}
diff --git a/libmariadb/external/zlib/gzclose.c b/libmariadb/external/zlib/gzclose.c
new file mode 100644
index 00000000..caeb99a3
--- /dev/null
+++ b/libmariadb/external/zlib/gzclose.c
@@ -0,0 +1,25 @@
+/* gzclose.c -- zlib gzclose() function
+ * Copyright (C) 2004, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* gzclose() is in a separate file so that it is linked in only if it is used.
+ That way the other gzclose functions can be used instead to avoid linking in
+ unneeded compression or decompression routines. */
+int ZEXPORT gzclose(file)
+ gzFile file;
+{
+#ifndef NO_GZCOMPRESS
+ gz_statep state;
+
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
+#else
+ return gzclose_r(file);
+#endif
+}
diff --git a/libmariadb/external/zlib/gzguts.h b/libmariadb/external/zlib/gzguts.h
new file mode 100644
index 00000000..57faf371
--- /dev/null
+++ b/libmariadb/external/zlib/gzguts.h
@@ -0,0 +1,219 @@
+/* gzguts.h -- zlib internal header definitions for gz* operations
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef _LARGEFILE64_SOURCE
+# ifndef _LARGEFILE_SOURCE
+# define _LARGEFILE_SOURCE 1
+# endif
+# ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+# endif
+#endif
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include <stdio.h>
+#include "zlib.h"
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+# include <limits.h>
+#endif
+
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#include <fcntl.h>
+
+#ifdef _WIN32
+# include <stddef.h>
+#endif
+
+#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
+# include <io.h>
+#endif
+
+#if defined(_WIN32)
+# define WIDECHAR
+#endif
+
+#ifdef WINAPI_FAMILY
+# define open _open
+# define read _read
+# define write _write
+# define close _close
+#endif
+
+#ifdef NO_DEFLATE /* for compatibility with old definition */
+# define NO_GZCOMPRESS
+#endif
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+# ifdef VMS
+# define NO_vsnprintf
+# endif
+# ifdef __OS400__
+# define NO_vsnprintf
+# endif
+# ifdef __MVS__
+# define NO_vsnprintf
+# endif
+#endif
+
+/* unlike snprintf (which is required in C99), _snprintf does not guarantee
+ null termination of the result -- however this is only used in gzlib.c where
+ the result is assured to fit in the space provided */
+#if defined(_MSC_VER) && _MSC_VER < 1900
+# define snprintf _snprintf
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
+
+/* gz* functions always use library allocation functions */
+#ifndef STDC
+ extern voidp malloc OF((uInt size));
+ extern void free OF((voidpf ptr));
+#endif
+
+/* get errno and strerror definition */
+#if defined UNDER_CE
+# include <windows.h>
+# define zstrerror() gz_strwinerror((DWORD)GetLastError())
+#else
+# ifndef NO_STRERROR
+# include <errno.h>
+# define zstrerror() strerror(errno)
+# else
+# define zstrerror() "stdio error (consult errno)"
+# endif
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+ ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+#endif
+
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+
+/* default i/o buffer size -- double this for output when reading (this and
+ twice this must be able to fit in an unsigned type) */
+#define GZBUFSIZE 8192
+
+/* gzip modes, also provide a little integrity check on the passed structure */
+#define GZ_NONE 0
+#define GZ_READ 7247
+#define GZ_WRITE 31153
+#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
+
+/* values for gz_state how */
+#define LOOK 0 /* look for a gzip header */
+#define COPY 1 /* copy input directly */
+#define GZIP 2 /* decompress a gzip stream */
+
+/* internal gzip file state data structure */
+typedef struct {
+ /* exposed contents for gzgetc() macro */
+ struct gzFile_s x; /* "x" for exposed */
+ /* x.have: number of bytes available at x.next */
+ /* x.next: next output data to deliver or write */
+ /* x.pos: current position in uncompressed data */
+ /* used for both reading and writing */
+ int mode; /* see gzip modes above */
+ int fd; /* file descriptor */
+ char *path; /* path or fd for error messages */
+ unsigned size; /* buffer size, zero if not allocated yet */
+ unsigned want; /* requested buffer size, default is GZBUFSIZE */
+ unsigned char *in; /* input buffer (double-sized when writing) */
+ unsigned char *out; /* output buffer (double-sized when reading) */
+ int direct; /* 0 if processing gzip, 1 if transparent */
+ /* just for reading */
+ int how; /* 0: get header, 1: copy, 2: decompress */
+ z_off64_t start; /* where the gzip data started, for rewinding */
+ int eof; /* true if end of input file reached */
+ int past; /* true if read requested past end */
+ /* just for writing */
+ int level; /* compression level */
+ int strategy; /* compression strategy */
+ int reset; /* true if a reset is pending after a Z_FINISH */
+ /* seek request */
+ z_off64_t skip; /* amount to skip (already rewound if backwards) */
+ int seek; /* true if seek request pending */
+ /* error information */
+ int err; /* error code */
+ char *msg; /* error message */
+ /* zlib inflate or deflate stream */
+ z_stream strm; /* stream structure in-place (not a pointer) */
+} gz_state;
+typedef gz_state FAR *gz_statep;
+
+/* shared functions */
+void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
+#if defined UNDER_CE
+char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
+#endif
+
+/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
+ value -- needed when comparing unsigned to z_off64_t, which is signed
+ (possible z_off64_t types off_t, off64_t, and long are all signed) */
+#ifdef INT_MAX
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
+#else
+unsigned ZLIB_INTERNAL gz_intmax OF((void));
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
+#endif
diff --git a/libmariadb/external/zlib/gzlib.c b/libmariadb/external/zlib/gzlib.c
new file mode 100644
index 00000000..55da46a4
--- /dev/null
+++ b/libmariadb/external/zlib/gzlib.c
@@ -0,0 +1,639 @@
+/* gzlib.c -- zlib functions common to reading and writing gzip files
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+#if defined(_WIN32) && !defined(__BORLANDC__)
+# define LSEEK _lseeki64
+#else
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+# define LSEEK lseek64
+#else
+# define LSEEK lseek
+#endif
+#endif
+
+/* Local functions */
+local void gz_reset OF((gz_statep));
+local gzFile gz_open OF((const void *, int, const char *));
+
+#if defined UNDER_CE
+
+/* Map the Windows error number in ERROR to a locale-dependent error message
+ string and return a pointer to it. Typically, the values for ERROR come
+ from GetLastError.
+
+ The string pointed to shall not be modified by the application, but may be
+ overwritten by a subsequent call to gz_strwinerror
+
+ The gz_strwinerror function does not change the current setting of
+ GetLastError. */
+char ZLIB_INTERNAL *gz_strwinerror(error)
+ DWORD error;
+{
+ static char buf[1024];
+
+ wchar_t *msgbuf;
+ DWORD lasterr = GetLastError();
+ DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ error,
+ 0, /* Default language */
+ (LPVOID)&msgbuf,
+ 0,
+ NULL);
+ if (chars != 0) {
+ /* If there is an \r\n appended, zap it. */
+ if (chars >= 2
+ && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > sizeof (buf) - 1) {
+ chars = sizeof (buf) - 1;
+ msgbuf[chars] = 0;
+ }
+
+ wcstombs(buf, msgbuf, chars + 1);
+ LocalFree(msgbuf);
+ }
+ else {
+ sprintf(buf, "unknown win32 error (%ld)", error);
+ }
+
+ SetLastError(lasterr);
+ return buf;
+}
+
+#endif /* UNDER_CE */
+
+/* Reset gzip file state */
+local void gz_reset(state)
+ gz_statep state;
+{
+ state->x.have = 0; /* no output data available */
+ if (state->mode == GZ_READ) { /* for reading ... */
+ state->eof = 0; /* not at end of file */
+ state->past = 0; /* have not read past end yet */
+ state->how = LOOK; /* look for gzip header */
+ }
+ else /* for writing ... */
+ state->reset = 0; /* no deflateReset pending */
+ state->seek = 0; /* no seek request pending */
+ gz_error(state, Z_OK, NULL); /* clear error */
+ state->x.pos = 0; /* no uncompressed data yet */
+ state->strm.avail_in = 0; /* no input data yet */
+}
+
+/* Open a gzip file either by name or file descriptor. */
+local gzFile gz_open(path, fd, mode)
+ const void *path;
+ int fd;
+ const char *mode;
+{
+ gz_statep state;
+ z_size_t len;
+ int oflag;
+#ifdef O_CLOEXEC
+ int cloexec = 0;
+#endif
+#ifdef O_EXCL
+ int exclusive = 0;
+#endif
+
+ /* check input */
+ if (path == NULL)
+ return NULL;
+
+ /* allocate gzFile structure to return */
+ state = (gz_statep)malloc(sizeof(gz_state));
+ if (state == NULL)
+ return NULL;
+ state->size = 0; /* no buffers allocated yet */
+ state->want = GZBUFSIZE; /* requested buffer size */
+ state->msg = NULL; /* no error message yet */
+
+ /* interpret mode */
+ state->mode = GZ_NONE;
+ state->level = Z_DEFAULT_COMPRESSION;
+ state->strategy = Z_DEFAULT_STRATEGY;
+ state->direct = 0;
+ while (*mode) {
+ if (*mode >= '0' && *mode <= '9')
+ state->level = *mode - '0';
+ else
+ switch (*mode) {
+ case 'r':
+ state->mode = GZ_READ;
+ break;
+#ifndef NO_GZCOMPRESS
+ case 'w':
+ state->mode = GZ_WRITE;
+ break;
+ case 'a':
+ state->mode = GZ_APPEND;
+ break;
+#endif
+ case '+': /* can't read and write at the same time */
+ free(state);
+ return NULL;
+ case 'b': /* ignore -- will request binary anyway */
+ break;
+#ifdef O_CLOEXEC
+ case 'e':
+ cloexec = 1;
+ break;
+#endif
+#ifdef O_EXCL
+ case 'x':
+ exclusive = 1;
+ break;
+#endif
+ case 'f':
+ state->strategy = Z_FILTERED;
+ break;
+ case 'h':
+ state->strategy = Z_HUFFMAN_ONLY;
+ break;
+ case 'R':
+ state->strategy = Z_RLE;
+ break;
+ case 'F':
+ state->strategy = Z_FIXED;
+ break;
+ case 'T':
+ state->direct = 1;
+ break;
+ default: /* could consider as an error, but just ignore */
+ ;
+ }
+ mode++;
+ }
+
+ /* must provide an "r", "w", or "a" */
+ if (state->mode == GZ_NONE) {
+ free(state);
+ return NULL;
+ }
+
+ /* can't force transparent read */
+ if (state->mode == GZ_READ) {
+ if (state->direct) {
+ free(state);
+ return NULL;
+ }
+ state->direct = 1; /* for empty file */
+ }
+
+ /* save the path name for error messages */
+#ifdef WIDECHAR
+ if (fd == -2) {
+ len = wcstombs(NULL, path, 0);
+ if (len == (z_size_t)-1)
+ len = 0;
+ }
+ else
+#endif
+ len = strlen((const char *)path);
+ state->path = (char *)malloc(len + 1);
+ if (state->path == NULL) {
+ free(state);
+ return NULL;
+ }
+#ifdef WIDECHAR
+ if (fd == -2)
+ if (len)
+ wcstombs(state->path, path, len + 1);
+ else
+ *(state->path) = 0;
+ else
+#endif
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(state->path, len + 1, "%s", (const char *)path);
+#else
+ strcpy(state->path, path);
+#endif
+
+ /* compute the flags for open() */
+ oflag =
+#ifdef O_LARGEFILE
+ O_LARGEFILE |
+#endif
+#ifdef O_BINARY
+ O_BINARY |
+#endif
+#ifdef O_CLOEXEC
+ (cloexec ? O_CLOEXEC : 0) |
+#endif
+ (state->mode == GZ_READ ?
+ O_RDONLY :
+ (O_WRONLY | O_CREAT |
+#ifdef O_EXCL
+ (exclusive ? O_EXCL : 0) |
+#endif
+ (state->mode == GZ_WRITE ?
+ O_TRUNC :
+ O_APPEND)));
+
+ /* open the file with the appropriate flags (or just use fd) */
+ state->fd = fd > -1 ? fd : (
+#ifdef WIDECHAR
+ fd == -2 ? _wopen(path, oflag, 0666) :
+#endif
+ open((const char *)path, oflag, 0666));
+ if (state->fd == -1) {
+ free(state->path);
+ free(state);
+ return NULL;
+ }
+ if (state->mode == GZ_APPEND) {
+ LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
+ state->mode = GZ_WRITE; /* simplify later checks */
+ }
+
+ /* save the current position for rewinding (only if reading) */
+ if (state->mode == GZ_READ) {
+ state->start = LSEEK(state->fd, 0, SEEK_CUR);
+ if (state->start == -1) state->start = 0;
+ }
+
+ /* initialize stream */
+ gz_reset(state);
+
+ /* return stream */
+ return (gzFile)state;
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen(path, mode)
+ const char *path;
+ const char *mode;
+{
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen64(path, mode)
+ const char *path;
+ const char *mode;
+{
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzdopen(fd, mode)
+ int fd;
+ const char *mode;
+{
+ char *path; /* identifier for error messages */
+ gzFile gz;
+
+ if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
+ return NULL;
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
+#else
+ sprintf(path, "<fd:%d>", fd); /* for debugging */
+#endif
+ gz = gz_open(path, fd, mode);
+ free(path);
+ return gz;
+}
+
+/* -- see zlib.h -- */
+#ifdef WIDECHAR
+gzFile ZEXPORT gzopen_w(path, mode)
+ const wchar_t *path;
+ const char *mode;
+{
+ return gz_open(path, -2, mode);
+}
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzbuffer(file, size)
+ gzFile file;
+ unsigned size;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* make sure we haven't already allocated memory */
+ if (state->size != 0)
+ return -1;
+
+ /* check and set requested size */
+ if ((size << 1) < size)
+ return -1; /* need to be able to double it */
+ if (size < 2)
+ size = 2; /* need two bytes to check magic header */
+ state->want = size;
+ return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzrewind(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* back up and start over */
+ if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
+ return -1;
+ gz_reset(state);
+ return 0;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzseek64(file, offset, whence)
+ gzFile file;
+ z_off64_t offset;
+ int whence;
+{
+ unsigned n;
+ z_off64_t ret;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* check that there's no error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+
+ /* can only seek from start or relative to current position */
+ if (whence != SEEK_SET && whence != SEEK_CUR)
+ return -1;
+
+ /* normalize offset to a SEEK_CUR specification */
+ if (whence == SEEK_SET)
+ offset -= state->x.pos;
+ else if (state->seek)
+ offset += state->skip;
+ state->seek = 0;
+
+ /* if within raw area while reading, just go there */
+ if (state->mode == GZ_READ && state->how == COPY &&
+ state->x.pos + offset >= 0) {
+ ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
+ if (ret == -1)
+ return -1;
+ state->x.have = 0;
+ state->eof = 0;
+ state->past = 0;
+ state->seek = 0;
+ gz_error(state, Z_OK, NULL);
+ state->strm.avail_in = 0;
+ state->x.pos += offset;
+ return state->x.pos;
+ }
+
+ /* calculate skip amount, rewinding if needed for back seek when reading */
+ if (offset < 0) {
+ if (state->mode != GZ_READ) /* writing -- can't go backwards */
+ return -1;
+ offset += state->x.pos;
+ if (offset < 0) /* before start of file! */
+ return -1;
+ if (gzrewind(file) == -1) /* rewind, then skip to offset */
+ return -1;
+ }
+
+ /* if reading, skip what's in output buffer (one less gzgetc() check) */
+ if (state->mode == GZ_READ) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
+ (unsigned)offset : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ offset -= n;
+ }
+
+ /* request skip (if not zero) */
+ if (offset) {
+ state->seek = 1;
+ state->skip = offset;
+ }
+ return state->x.pos + offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzseek(file, offset, whence)
+ gzFile file;
+ z_off_t offset;
+ int whence;
+{
+ z_off64_t ret;
+
+ ret = gzseek64(file, (z_off64_t)offset, whence);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gztell64(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* return position */
+ return state->x.pos + (state->seek ? state->skip : 0);
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gztell(file)
+ gzFile file;
+{
+ z_off64_t ret;
+
+ ret = gztell64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzoffset64(file)
+ gzFile file;
+{
+ z_off64_t offset;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* compute and return effective offset in file */
+ offset = LSEEK(state->fd, 0, SEEK_CUR);
+ if (offset == -1)
+ return -1;
+ if (state->mode == GZ_READ) /* reading */
+ offset -= state->strm.avail_in; /* don't count buffered input */
+ return offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzoffset(file)
+ gzFile file;
+{
+ z_off64_t ret;
+
+ ret = gzoffset64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzeof(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return 0;
+
+ /* return end-of-file state */
+ return state->mode == GZ_READ ? state->past : 0;
+}
+
+/* -- see zlib.h -- */
+const char * ZEXPORT gzerror(file, errnum)
+ gzFile file;
+ int *errnum;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return NULL;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return NULL;
+
+ /* return error information */
+ if (errnum != NULL)
+ *errnum = state->err;
+ return state->err == Z_MEM_ERROR ? "out of memory" :
+ (state->msg == NULL ? "" : state->msg);
+}
+
+/* -- see zlib.h -- */
+void ZEXPORT gzclearerr(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return;
+
+ /* clear error and end-of-file */
+ if (state->mode == GZ_READ) {
+ state->eof = 0;
+ state->past = 0;
+ }
+ gz_error(state, Z_OK, NULL);
+}
+
+/* Create an error message in allocated memory and set state->err and
+ state->msg accordingly. Free any previous error message already there. Do
+ not try to free or allocate space if the error is Z_MEM_ERROR (out of
+ memory). Simply save the error message as a static string. If there is an
+ allocation failure constructing the error message, then convert the error to
+ out of memory. */
+void ZLIB_INTERNAL gz_error(state, err, msg)
+ gz_statep state;
+ int err;
+ const char *msg;
+{
+ /* free previously allocated message and clear */
+ if (state->msg != NULL) {
+ if (state->err != Z_MEM_ERROR)
+ free(state->msg);
+ state->msg = NULL;
+ }
+
+ /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
+ if (err != Z_OK && err != Z_BUF_ERROR)
+ state->x.have = 0;
+
+ /* set error code, and if no message, then done */
+ state->err = err;
+ if (msg == NULL)
+ return;
+
+ /* for an out of memory error, return literal string when requested */
+ if (err == Z_MEM_ERROR)
+ return;
+
+ /* construct error message with path */
+ if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
+ NULL) {
+ state->err = Z_MEM_ERROR;
+ return;
+ }
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
+ "%s%s%s", state->path, ": ", msg);
+#else
+ strcpy(state->msg, state->path);
+ strcat(state->msg, ": ");
+ strcat(state->msg, msg);
+#endif
+}
+
+#ifndef INT_MAX
+/* portably return maximum value for an int (when limits.h presumed not
+ available) -- we need to do this to cover cases where 2's complement not
+ used, since C standard permits 1's complement and sign-bit representations,
+ otherwise we could just use ((unsigned)-1) >> 1 */
+unsigned ZLIB_INTERNAL gz_intmax()
+{
+ unsigned p, q;
+
+ p = 1;
+ do {
+ q = p;
+ p <<= 1;
+ p++;
+ } while (p > q);
+ return q >> 1;
+}
+#endif
diff --git a/libmariadb/external/zlib/gzread.c b/libmariadb/external/zlib/gzread.c
new file mode 100644
index 00000000..dd773815
--- /dev/null
+++ b/libmariadb/external/zlib/gzread.c
@@ -0,0 +1,650 @@
+/* gzread.c -- zlib functions for reading gzip files
+ * Copyright (C) 2004-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Local functions */
+local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
+local int gz_avail OF((gz_statep));
+local int gz_look OF((gz_statep));
+local int gz_decomp OF((gz_statep));
+local int gz_fetch OF((gz_statep));
+local int gz_skip OF((gz_statep, z_off64_t));
+local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
+
+/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
+ state->fd, and update state->eof, state->err, and state->msg as appropriate.
+ This function needs to loop on read(), since read() is not guaranteed to
+ read the number of bytes requested, depending on the type of descriptor. */
+local int gz_load(state, buf, len, have)
+ gz_statep state;
+ unsigned char *buf;
+ unsigned len;
+ unsigned *have;
+{
+ int ret;
+ unsigned get, max = ((unsigned)-1 >> 2) + 1;
+
+ *have = 0;
+ do {
+ get = len - *have;
+ if (get > max)
+ get = max;
+ ret = read(state->fd, buf + *have, get);
+ if (ret <= 0)
+ break;
+ *have += (unsigned)ret;
+ } while (*have < len);
+ if (ret < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ if (ret == 0)
+ state->eof = 1;
+ return 0;
+}
+
+/* Load up input buffer and set eof flag if last data loaded -- return -1 on
+ error, 0 otherwise. Note that the eof flag is set when the end of the input
+ file is reached, even though there may be unused data in the buffer. Once
+ that data has been used, no more attempts will be made to read the file.
+ If strm->avail_in != 0, then the current data is moved to the beginning of
+ the input buffer, and then the remainder of the buffer is loaded with the
+ available data from the input file. */
+local int gz_avail(state)
+ gz_statep state;
+{
+ unsigned got;
+ z_streamp strm = &(state->strm);
+
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+ if (state->eof == 0) {
+ if (strm->avail_in) { /* copy what's there to the start */
+ unsigned char *p = state->in;
+ unsigned const char *q = strm->next_in;
+ unsigned n = strm->avail_in;
+ do {
+ *p++ = *q++;
+ } while (--n);
+ }
+ if (gz_load(state, state->in + strm->avail_in,
+ state->size - strm->avail_in, &got) == -1)
+ return -1;
+ strm->avail_in += got;
+ strm->next_in = state->in;
+ }
+ return 0;
+}
+
+/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
+ If this is the first time in, allocate required memory. state->how will be
+ left unchanged if there is no more input data available, will be set to COPY
+ if there is no gzip header and direct copying will be performed, or it will
+ be set to GZIP for decompression. If direct copying, then leftover input
+ data from the input buffer will be copied to the output buffer. In that
+ case, all further file reads will be directly to either the output buffer or
+ a user buffer. If decompressing, the inflate state will be initialized.
+ gz_look() will return 0 on success or -1 on failure. */
+local int gz_look(state)
+ gz_statep state;
+{
+ z_streamp strm = &(state->strm);
+
+ /* allocate read buffers and inflate memory */
+ if (state->size == 0) {
+ /* allocate buffers */
+ state->in = (unsigned char *)malloc(state->want);
+ state->out = (unsigned char *)malloc(state->want << 1);
+ if (state->in == NULL || state->out == NULL) {
+ free(state->out);
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ state->size = state->want;
+
+ /* allocate inflate memory */
+ state->strm.zalloc = Z_NULL;
+ state->strm.zfree = Z_NULL;
+ state->strm.opaque = Z_NULL;
+ state->strm.avail_in = 0;
+ state->strm.next_in = Z_NULL;
+ if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
+ free(state->out);
+ free(state->in);
+ state->size = 0;
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ }
+
+ /* get at least the magic bytes in the input buffer */
+ if (strm->avail_in < 2) {
+ if (gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0)
+ return 0;
+ }
+
+ /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
+ a logical dilemma here when considering the case of a partially written
+ gzip file, to wit, if a single 31 byte is written, then we cannot tell
+ whether this is a single-byte file, or just a partially written gzip
+ file -- for here we assume that if a gzip file is being written, then
+ the header will be written in a single operation, so that reading a
+ single byte is sufficient indication that it is not a gzip file) */
+ if (strm->avail_in > 1 &&
+ strm->next_in[0] == 31 && strm->next_in[1] == 139) {
+ inflateReset(strm);
+ state->how = GZIP;
+ state->direct = 0;
+ return 0;
+ }
+
+ /* no gzip header -- if we were decoding gzip before, then this is trailing
+ garbage. Ignore the trailing garbage and finish. */
+ if (state->direct == 0) {
+ strm->avail_in = 0;
+ state->eof = 1;
+ state->x.have = 0;
+ return 0;
+ }
+
+ /* doing raw i/o, copy any leftover input to output -- this assumes that
+ the output buffer is larger than the input buffer, which also assures
+ space for gzungetc() */
+ state->x.next = state->out;
+ memcpy(state->x.next, strm->next_in, strm->avail_in);
+ state->x.have = strm->avail_in;
+ strm->avail_in = 0;
+ state->how = COPY;
+ state->direct = 1;
+ return 0;
+}
+
+/* Decompress from input to the provided next_out and avail_out in the state.
+ On return, state->x.have and state->x.next point to the just decompressed
+ data. If the gzip stream completes, state->how is reset to LOOK to look for
+ the next gzip stream or raw data, once state->x.have is depleted. Returns 0
+ on success, -1 on failure. */
+local int gz_decomp(state)
+ gz_statep state;
+{
+ int ret = Z_OK;
+ unsigned had;
+ z_streamp strm = &(state->strm);
+
+ /* fill output buffer up to end of deflate stream */
+ had = strm->avail_out;
+ do {
+ /* get more input for inflate() */
+ if (strm->avail_in == 0 && gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0) {
+ gz_error(state, Z_BUF_ERROR, "unexpected end of file");
+ break;
+ }
+
+ /* decompress and handle errors */
+ ret = inflate(strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: inflate stream corrupt");
+ return -1;
+ }
+ if (ret == Z_MEM_ERROR) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
+ gz_error(state, Z_DATA_ERROR,
+ strm->msg == NULL ? "compressed data error" : strm->msg);
+ return -1;
+ }
+ } while (strm->avail_out && ret != Z_STREAM_END);
+
+ /* update available output */
+ state->x.have = had - strm->avail_out;
+ state->x.next = strm->next_out - state->x.have;
+
+ /* if the gzip stream completed successfully, look for another */
+ if (ret == Z_STREAM_END)
+ state->how = LOOK;
+
+ /* good decompression */
+ return 0;
+}
+
+/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
+ Data is either copied from the input file or decompressed from the input
+ file depending on state->how. If state->how is LOOK, then a gzip header is
+ looked for to determine whether to copy or decompress. Returns -1 on error,
+ otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
+ end of the input file has been reached and all data has been processed. */
+local int gz_fetch(state)
+ gz_statep state;
+{
+ z_streamp strm = &(state->strm);
+
+ do {
+ switch(state->how) {
+ case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
+ if (gz_look(state) == -1)
+ return -1;
+ if (state->how == LOOK)
+ return 0;
+ break;
+ case COPY: /* -> COPY */
+ if (gz_load(state, state->out, state->size << 1, &(state->x.have))
+ == -1)
+ return -1;
+ state->x.next = state->out;
+ return 0;
+ case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
+ strm->avail_out = state->size << 1;
+ strm->next_out = state->out;
+ if (gz_decomp(state) == -1)
+ return -1;
+ }
+ } while (state->x.have == 0 && (!state->eof || strm->avail_in));
+ return 0;
+}
+
+/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
+local int gz_skip(state, len)
+ gz_statep state;
+ z_off64_t len;
+{
+ unsigned n;
+
+ /* skip over len bytes or reach end-of-file, whichever comes first */
+ while (len)
+ /* skip over whatever is in output buffer */
+ if (state->x.have) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
+ (unsigned)len : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ len -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && state->strm.avail_in == 0)
+ break;
+
+ /* need more data to skip -- load up output buffer */
+ else {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+/* Read len bytes into buf from file, or less than len up to the end of the
+ input. Return the number of bytes read. If zero is returned, either the
+ end of file was reached, or there was an error. state->err must be
+ consulted in that case to determine which. */
+local z_size_t gz_read(state, buf, len)
+ gz_statep state;
+ voidp buf;
+ z_size_t len;
+{
+ z_size_t got;
+ unsigned n;
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* get len bytes to buf, or less than len if at the end */
+ got = 0;
+ do {
+ /* set n to the maximum amount of len that fits in an unsigned int */
+ n = (unsigned)-1;
+ if (n > len)
+ n = (unsigned)len;
+
+ /* first just try copying data from the output buffer */
+ if (state->x.have) {
+ if (state->x.have < n)
+ n = state->x.have;
+ memcpy(buf, state->x.next, n);
+ state->x.next += n;
+ state->x.have -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && state->strm.avail_in == 0) {
+ state->past = 1; /* tried to read past end */
+ break;
+ }
+
+ /* need output data -- for small len or new stream load up our output
+ buffer */
+ else if (state->how == LOOK || n < (state->size << 1)) {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return 0;
+ continue; /* no progress yet -- go back to copy above */
+ /* the copy above assures that we will leave with space in the
+ output buffer, allowing at least one gzungetc() to succeed */
+ }
+
+ /* large len -- read directly into user buffer */
+ else if (state->how == COPY) { /* read directly */
+ if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
+ return 0;
+ }
+
+ /* large len -- decompress directly into user buffer */
+ else { /* state->how == GZIP */
+ state->strm.avail_out = n;
+ state->strm.next_out = (unsigned char *)buf;
+ if (gz_decomp(state) == -1)
+ return 0;
+ n = state->x.have;
+ state->x.have = 0;
+ }
+
+ /* update progress */
+ len -= n;
+ buf = (char *)buf + n;
+ got += n;
+ state->x.pos += n;
+ } while (len);
+
+ /* return number of bytes read into user buffer */
+ return got;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzread(file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids a flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
+ return -1;
+ }
+
+ /* read len or fewer bytes to buf */
+ len = (unsigned)gz_read(state, buf, len);
+
+ /* check for an error */
+ if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+
+ /* return the number of bytes read (this is assured to fit in an int) */
+ return (int)len;
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfread(buf, size, nitems, file)
+ voidp buf;
+ z_size_t size;
+ z_size_t nitems;
+ gzFile file;
+{
+ z_size_t len;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return 0;
+
+ /* compute bytes to read -- error on overflow */
+ len = nitems * size;
+ if (size && len / size != nitems) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+ return 0;
+ }
+
+ /* read len or fewer bytes to buf, return the number of full items read */
+ return len ? gz_read(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+#else
+# undef gzgetc
+#endif
+int ZEXPORT gzgetc(file)
+ gzFile file;
+{
+ unsigned char buf[1];
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* try output buffer (no need to check for skip request) */
+ if (state->x.have) {
+ state->x.have--;
+ state->x.pos++;
+ return *(state->x.next)++;
+ }
+
+ /* nothing there -- try gz_read() */
+ return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
+}
+
+int ZEXPORT gzgetc_(file)
+gzFile file;
+{
+ return gzgetc(file);
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzungetc(c, file)
+ int c;
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* can't push EOF */
+ if (c < 0)
+ return -1;
+
+ /* if output buffer empty, put byte at end (allows more pushing) */
+ if (state->x.have == 0) {
+ state->x.have = 1;
+ state->x.next = state->out + (state->size << 1) - 1;
+ state->x.next[0] = (unsigned char)c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+ }
+
+ /* if no room, give up (must have already done a gzungetc()) */
+ if (state->x.have == (state->size << 1)) {
+ gz_error(state, Z_DATA_ERROR, "out of room to push characters");
+ return -1;
+ }
+
+ /* slide output data if needed and insert byte before existing data */
+ if (state->x.next == state->out) {
+ unsigned char *src = state->out + state->x.have;
+ unsigned char *dest = state->out + (state->size << 1);
+ while (src > state->out)
+ *--dest = *--src;
+ state->x.next = dest;
+ }
+ state->x.have++;
+ state->x.next--;
+ state->x.next[0] = (unsigned char)c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+}
+
+/* -- see zlib.h -- */
+char * ZEXPORT gzgets(file, buf, len)
+ gzFile file;
+ char *buf;
+ int len;
+{
+ unsigned left, n;
+ char *str;
+ unsigned char *eol;
+ gz_statep state;
+
+ /* check parameters and get internal structure */
+ if (file == NULL || buf == NULL || len < 1)
+ return NULL;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return NULL;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return NULL;
+ }
+
+ /* copy output bytes up to new line or len - 1, whichever comes first --
+ append a terminating zero to the string (we don't check for a zero in
+ the contents, let the user worry about that) */
+ str = buf;
+ left = (unsigned)len - 1;
+ if (left) do {
+ /* assure that something is in the output buffer */
+ if (state->x.have == 0 && gz_fetch(state) == -1)
+ return NULL; /* error */
+ if (state->x.have == 0) { /* end of file */
+ state->past = 1; /* read past end */
+ break; /* return what we have */
+ }
+
+ /* look for end-of-line in current output buffer */
+ n = state->x.have > left ? left : state->x.have;
+ eol = (unsigned char *)memchr(state->x.next, '\n', n);
+ if (eol != NULL)
+ n = (unsigned)(eol - state->x.next) + 1;
+
+ /* copy through end-of-line, or remainder if not found */
+ memcpy(buf, state->x.next, n);
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ left -= n;
+ buf += n;
+ } while (left && eol == NULL);
+
+ /* return terminated string, or if nothing, end of file */
+ if (buf == str)
+ return NULL;
+ buf[0] = 0;
+ return str;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzdirect(file)
+ gzFile file;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* if the state is not known, but we can find out, then do so (this is
+ mainly for right after a gzopen() or gzdopen()) */
+ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+ (void)gz_look(state);
+
+ /* return 1 if transparent, 0 if processing a gzip stream */
+ return state->direct;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_r(file)
+ gzFile file;
+{
+ int ret, err;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're reading */
+ if (state->mode != GZ_READ)
+ return Z_STREAM_ERROR;
+
+ /* free memory and close file */
+ if (state->size) {
+ inflateEnd(&(state->strm));
+ free(state->out);
+ free(state->in);
+ }
+ err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ ret = close(state->fd);
+ free(state);
+ return ret ? Z_ERRNO : err;
+}
diff --git a/libmariadb/external/zlib/gzwrite.c b/libmariadb/external/zlib/gzwrite.c
new file mode 100644
index 00000000..eb8a0e58
--- /dev/null
+++ b/libmariadb/external/zlib/gzwrite.c
@@ -0,0 +1,677 @@
+/* gzwrite.c -- zlib functions for writing gzip files
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Local functions */
+local int gz_init OF((gz_statep));
+local int gz_comp OF((gz_statep, int));
+local int gz_zero OF((gz_statep, z_off64_t));
+local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
+
+/* Initialize state for writing a gzip file. Mark initialization by setting
+ state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
+ success. */
+local int gz_init(state)
+ gz_statep state;
+{
+ int ret;
+ z_streamp strm = &(state->strm);
+
+ /* allocate input buffer (double size for gzprintf) */
+ state->in = (unsigned char *)malloc(state->want << 1);
+ if (state->in == NULL) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* only need output buffer and deflate state if compressing */
+ if (!state->direct) {
+ /* allocate output buffer */
+ state->out = (unsigned char *)malloc(state->want);
+ if (state->out == NULL) {
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* allocate deflate memory, set up for gzip compression */
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ ret = deflateInit2(strm, state->level, Z_DEFLATED,
+ MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
+ if (ret != Z_OK) {
+ free(state->out);
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ strm->next_in = NULL;
+ }
+
+ /* mark state as initialized */
+ state->size = state->want;
+
+ /* initialize write buffer if compressing */
+ if (!state->direct) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ state->x.next = strm->next_out;
+ }
+ return 0;
+}
+
+/* Compress whatever is at avail_in and next_in and write to the output file.
+ Return -1 if there is an error writing to the output file or if gz_init()
+ fails to allocate memory, otherwise 0. flush is assumed to be a valid
+ deflate() flush value. If flush is Z_FINISH, then the deflate() state is
+ reset to start a new gzip stream. If gz->direct is true, then simply write
+ to the output file without compressing, and ignore flush. */
+local int gz_comp(state, flush)
+ gz_statep state;
+ int flush;
+{
+ int ret, writ;
+ unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
+ z_streamp strm = &(state->strm);
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return -1;
+
+ /* write directly if requested */
+ if (state->direct) {
+ while (strm->avail_in) {
+ put = strm->avail_in > max ? max : strm->avail_in;
+ writ = write(state->fd, strm->next_in, put);
+ if (writ < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ strm->avail_in -= (unsigned)writ;
+ strm->next_in += writ;
+ }
+ return 0;
+ }
+
+ /* check for a pending reset */
+ if (state->reset) {
+ /* don't start a new gzip member unless there is data to write */
+ if (strm->avail_in == 0)
+ return 0;
+ deflateReset(strm);
+ state->reset = 0;
+ }
+
+ /* run deflate() on provided input until it produces no more output */
+ ret = Z_OK;
+ do {
+ /* write out current buffer contents if full, or if flushing, but if
+ doing Z_FINISH then don't write until we get to Z_STREAM_END */
+ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
+ (flush != Z_FINISH || ret == Z_STREAM_END))) {
+ while (strm->next_out > state->x.next) {
+ put = strm->next_out - state->x.next > (int)max ? max :
+ (unsigned)(strm->next_out - state->x.next);
+ writ = write(state->fd, state->x.next, put);
+ if (writ < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ state->x.next += writ;
+ }
+ if (strm->avail_out == 0) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ state->x.next = state->out;
+ }
+ }
+
+ /* compress */
+ have = strm->avail_out;
+ ret = deflate(strm, flush);
+ if (ret == Z_STREAM_ERROR) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: deflate stream corrupt");
+ return -1;
+ }
+ have -= strm->avail_out;
+ } while (have);
+
+ /* if that completed a deflate stream, allow another to start */
+ if (flush == Z_FINISH)
+ state->reset = 1;
+
+ /* all done, no errors */
+ return 0;
+}
+
+/* Compress len zeros to output. Return -1 on a write error or memory
+ allocation failure by gz_comp(), or 0 on success. */
+local int gz_zero(state, len)
+ gz_statep state;
+ z_off64_t len;
+{
+ int first;
+ unsigned n;
+ z_streamp strm = &(state->strm);
+
+ /* consume whatever's left in the input buffer */
+ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+
+ /* compress len zeros (len guaranteed > 0) */
+ first = 1;
+ while (len) {
+ n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
+ (unsigned)len : state->size;
+ if (first) {
+ memset(state->in, 0, n);
+ first = 0;
+ }
+ strm->avail_in = n;
+ strm->next_in = state->in;
+ state->x.pos += n;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+ len -= n;
+ }
+ return 0;
+}
+
+/* Write len bytes from buf to file. Return the number of bytes written. If
+ the returned value is less than len, then there was an error. */
+local z_size_t gz_write(state, buf, len)
+ gz_statep state;
+ voidpc buf;
+ z_size_t len;
+{
+ z_size_t put = len;
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return 0;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* for small len, copy to input buffer, otherwise compress directly */
+ if (len < state->size) {
+ /* copy to input buffer, compress when full */
+ do {
+ unsigned have, copy;
+
+ if (state->strm.avail_in == 0)
+ state->strm.next_in = state->in;
+ have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
+ state->in);
+ copy = state->size - have;
+ if (copy > len)
+ copy = (unsigned)len;
+ memcpy(state->in + have, buf, copy);
+ state->strm.avail_in += copy;
+ state->x.pos += copy;
+ buf = (const char *)buf + copy;
+ len -= copy;
+ if (len && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ } while (len);
+ }
+ else {
+ /* consume whatever's left in the input buffer */
+ if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+
+ /* directly compress user buffer to file */
+ state->strm.next_in = (z_const Bytef *)buf;
+ do {
+ unsigned n = (unsigned)-1;
+ if (n > len)
+ n = (unsigned)len;
+ state->strm.avail_in = n;
+ state->x.pos += n;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ len -= n;
+ } while (len);
+ }
+
+ /* input was all buffered or compressed */
+ return put;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzwrite(file, buf, len)
+ gzFile file;
+ voidpc buf;
+ unsigned len;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids a flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
+ return 0;
+ }
+
+ /* write len bytes from buf (the return value will fit in an int) */
+ return (int)gz_write(state, buf, len);
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
+ voidpc buf;
+ z_size_t size;
+ z_size_t nitems;
+ gzFile file;
+{
+ z_size_t len;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* compute bytes to read -- error on overflow */
+ len = nitems * size;
+ if (size && len / size != nitems) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+ return 0;
+ }
+
+ /* write len bytes to buf, return the number of full items written */
+ return len ? gz_write(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputc(file, c)
+ gzFile file;
+ int c;
+{
+ unsigned have;
+ unsigned char buf[1];
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return -1;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* try writing to input buffer for speed (state->size == 0 if buffer not
+ initialized) */
+ if (state->size) {
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+ if (have < state->size) {
+ state->in[have] = (unsigned char)c;
+ strm->avail_in++;
+ state->x.pos++;
+ return c & 0xff;
+ }
+ }
+
+ /* no room in buffer or not initialized, use gz_write() */
+ buf[0] = (unsigned char)c;
+ if (gz_write(state, buf, 1) != 1)
+ return -1;
+ return c & 0xff;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputs(file, s)
+ gzFile file;
+ const char *s;
+{
+ z_size_t len, put;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return -1;
+
+ /* write string */
+ len = strlen(s);
+ if ((int)len < 0 || (unsigned)len != len) {
+ gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
+ return -1;
+ }
+ put = gz_write(state, s, len);
+ return put < len ? -1 : (int)len;
+}
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#include <stdarg.h>
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
+{
+ int len;
+ unsigned left;
+ char *next;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return state->err;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* do the printf() into the input buffer, put length in len -- the input
+ buffer is double-sized just for this function, so there is guaranteed to
+ be state->size bytes available after the current contents */
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
+ next[state->size - 1] = 0;
+#ifdef NO_vsnprintf
+# ifdef HAS_vsprintf_void
+ (void)vsprintf(next, format, va);
+ for (len = 0; len < state->size; len++)
+ if (next[len] == 0) break;
+# else
+ len = vsprintf(next, format, va);
+# endif
+#else
+# ifdef HAS_vsnprintf_void
+ (void)vsnprintf(next, state->size, format, va);
+ len = strlen(next);
+# else
+ len = vsnprintf(next, state->size, format, va);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, compress first half if past that */
+ strm->avail_in += (unsigned)len;
+ state->x.pos += len;
+ if (strm->avail_in >= state->size) {
+ left = strm->avail_in - state->size;
+ strm->avail_in = state->size;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return state->err;
+ memmove(state->in, state->in + state->size, left);
+ strm->next_in = state->in;
+ strm->avail_in = left;
+ }
+ return len;
+}
+
+int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
+{
+ va_list va;
+ int ret;
+
+ va_start(va, format);
+ ret = gzvprintf(file, format, va);
+ va_end(va);
+ return ret;
+}
+
+#else /* !STDC && !Z_HAVE_STDARG_H */
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+ gzFile file;
+ const char *format;
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+ unsigned len, left;
+ char *next;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that can really pass pointer in ints */
+ if (sizeof(int) != sizeof(void *))
+ return Z_STREAM_ERROR;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return state->error;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->error;
+ }
+
+ /* do the printf() into the input buffer, put length in len -- the input
+ buffer is double-sized just for this function, so there is guaranteed to
+ be state->size bytes available after the current contents */
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ next = (char *)(strm->next_in + strm->avail_in);
+ next[state->size - 1] = 0;
+#ifdef NO_snprintf
+# ifdef HAS_sprintf_void
+ sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
+ a13, a14, a15, a16, a17, a18, a19, a20);
+ for (len = 0; len < size; len++)
+ if (next[len] == 0)
+ break;
+# else
+ len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
+ a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#else
+# ifdef HAS_snprintf_void
+ snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+ len = strlen(next);
+# else
+ len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len == 0 || len >= state->size || next[state->size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, compress first half if past that */
+ strm->avail_in += len;
+ state->x.pos += len;
+ if (strm->avail_in >= state->size) {
+ left = strm->avail_in - state->size;
+ strm->avail_in = state->size;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return state->err;
+ memmove(state->in, state->in + state->size, left);
+ strm->next_in = state->in;
+ strm->avail_in = left;
+ }
+ return (int)len;
+}
+
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzflush(file, flush)
+ gzFile file;
+ int flush;
+{
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* check flush parameter */
+ if (flush < 0 || flush > Z_FINISH)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* compress remaining data with requested flush */
+ (void)gz_comp(state, flush);
+ return state->err;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzsetparams(file, level, strategy)
+ gzFile file;
+ int level;
+ int strategy;
+{
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* if no change is requested, then do nothing */
+ if (level == state->level && strategy == state->strategy)
+ return Z_OK;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* change compression parameters for subsequent input */
+ if (state->size) {
+ /* flush previous input with previous parameters before changing */
+ if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
+ return state->err;
+ deflateParams(strm, level, strategy);
+ }
+ state->level = level;
+ state->strategy = strategy;
+ return Z_OK;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_w(file)
+ gzFile file;
+{
+ int ret = Z_OK;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're writing */
+ if (state->mode != GZ_WRITE)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ ret = state->err;
+ }
+
+ /* flush, free memory, and close file */
+ if (gz_comp(state, Z_FINISH) == -1)
+ ret = state->err;
+ if (state->size) {
+ if (!state->direct) {
+ (void)deflateEnd(&(state->strm));
+ free(state->out);
+ }
+ free(state->in);
+ }
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ if (close(state->fd) == -1)
+ ret = Z_ERRNO;
+ free(state);
+ return ret;
+}
diff --git a/libmariadb/external/zlib/infback.c b/libmariadb/external/zlib/infback.c
new file mode 100644
index 00000000..babeaf18
--- /dev/null
+++ b/libmariadb/external/zlib/infback.c
@@ -0,0 +1,644 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ This code is largely copied from inflate.c. Normally either infback.o or
+ inflate.o would be linked into an application--not both. The interface
+ with inffast.c is retained so that optimized assembler-coded versions of
+ inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+ strm provides memory allocation functions in zalloc and zfree, or
+ Z_NULL to use the library memory allocation functions.
+
+ windowBits is in the range 8..15, and window is a user-supplied
+ window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
+z_streamp strm;
+int windowBits;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL || window == Z_NULL ||
+ windowBits < 8 || windowBits > 15)
+ return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+ sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = (uInt)windowBits;
+ state->wsize = 1U << windowBits;
+ state->window = window;
+ state->wnext = 0;
+ state->whave = 0;
+ state->sane = 1;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Assure that some input is available. If input is requested, but denied,
+ then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+ do { \
+ if (have == 0) { \
+ have = in(in_desc, &next); \
+ if (have == 0) { \
+ next = Z_NULL; \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+ with an error if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ PULL(); \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflateBack() with
+ an error. */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Assure that some output space is available, by writing out the window
+ if it's full. If the write fails, return from inflateBack() with a
+ Z_BUF_ERROR. */
+#define ROOM() \
+ do { \
+ if (left == 0) { \
+ put = state->window; \
+ left = state->wsize; \
+ state->whave = left; \
+ if (out(out_desc, put, left)) { \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/*
+ strm provides the memory allocation functions and window buffer on input,
+ and provides information on the unused input on return. For Z_DATA_ERROR
+ returns, strm will also provide an error message.
+
+ in() and out() are the call-back input and output functions. When
+ inflateBack() needs more input, it calls in(). When inflateBack() has
+ filled the window with output, or when it completes with data in the
+ window, it calls out() to write out the data. The application must not
+ change the provided input until in() is called again or inflateBack()
+ returns. The application must not change the window/output buffer until
+ inflateBack() returns.
+
+ in() and out() are called with a descriptor parameter provided in the
+ inflateBack() call. This parameter can be a structure that provides the
+ information required to do the read or write, as well as accumulated
+ information on the input and output such as totals and check values.
+
+ in() should return zero on failure. out() should return non-zero on
+ failure. If either in() or out() fails, than inflateBack() returns a
+ Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
+ was in() or out() that caused in the error. Otherwise, inflateBack()
+ returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+ error, or Z_MEM_ERROR if it could not allocate memory for the state.
+ inflateBack() can also return Z_STREAM_ERROR if the input parameters
+ are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
+z_streamp strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ /* Check that the strm exists and that the state was initialized */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* Reset the state */
+ strm->msg = Z_NULL;
+ state->mode = TYPE;
+ state->last = 0;
+ state->whave = 0;
+ next = strm->next_in;
+ have = next != Z_NULL ? strm->avail_in : 0;
+ hold = 0;
+ bits = 0;
+ put = state->window;
+ left = state->wsize;
+
+ /* Inflate until end of block marked as last */
+ for (;;)
+ switch (state->mode) {
+ case TYPE:
+ /* determine and dispatch block type */
+ if (state->last) {
+ BYTEBITS();
+ state->mode = DONE;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+
+ case STORED:
+ /* get and verify stored block length */
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+
+ /* copy stored block from input to output */
+ while (state->length != 0) {
+ copy = state->length;
+ PULL();
+ ROOM();
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+
+ case TABLE:
+ /* get dynamic table entries descriptor */
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+
+ /* get code length code lengths (not a typo) */
+ state->have = 0;
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+
+ /* get length and distance code code lengths */
+ state->have = 0;
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = (unsigned)(state->lens[state->have - 1]);
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ /* fallthrough */
+
+ case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
+ /* get a literal, length, or end-of-block code */
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ state->length = (unsigned)here.val;
+
+ /* process literal */
+ if (here.op == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ ROOM();
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ }
+
+ /* process end of block */
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+
+ /* invalid code */
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+
+ /* length code -- get extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+
+ /* get distance code */
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+
+ /* get distance extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+
+ /* copy match from window to output */
+ do {
+ ROOM();
+ copy = state->wsize - state->offset;
+ if (copy < left) {
+ from = put + copy;
+ copy = left - copy;
+ }
+ else {
+ from = put - state->offset;
+ copy = left;
+ }
+ if (copy > state->length) copy = state->length;
+ state->length -= copy;
+ left -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ } while (state->length != 0);
+ break;
+
+ case DONE:
+ /* inflate stream terminated properly */
+ ret = Z_STREAM_END;
+ goto inf_leave;
+
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+
+ default:
+ /* can't happen, but makes compilers happy */
+ ret = Z_STREAM_ERROR;
+ goto inf_leave;
+ }
+
+ /* Write leftover output and return unused input */
+ inf_leave:
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left) &&
+ ret == Z_STREAM_END)
+ ret = Z_BUF_ERROR;
+ }
+ strm->next_in = next;
+ strm->avail_in = have;
+ return ret;
+}
+
+int ZEXPORT inflateBackEnd(strm)
+z_streamp strm;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/libmariadb/external/zlib/inffast.c b/libmariadb/external/zlib/inffast.c
new file mode 100644
index 00000000..1fec7f36
--- /dev/null
+++ b/libmariadb/external/zlib/inffast.c
@@ -0,0 +1,323 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef ASMINF
+# pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void ZLIB_INTERNAL inflate_fast(strm, start)
+z_streamp strm;
+unsigned start; /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *in; /* local strm->next_in */
+ z_const unsigned char FAR *last; /* have enough input while in < last */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code const *here; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wnext = state->wnext;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = lcode + (hold & lmask);
+ dolen:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = dcode + (hold & dmask);
+ dodist:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state->sane) {
+ strm->msg =
+ (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ if (len <= op - whave) {
+ do {
+ *out++ = 0;
+ } while (--len);
+ continue;
+ }
+ len -= op - whave;
+ do {
+ *out++ = 0;
+ } while (--op > whave);
+ if (op == 0) {
+ from = out - dist;
+ do {
+ *out++ = *from++;
+ } while (--len);
+ continue;
+ }
+#endif
+ }
+ from = window;
+ if (wnext == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (wnext < op) { /* wrap around window */
+ from += wsize + wnext - op;
+ op -= wnext;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = window;
+ if (wnext < len) { /* some from start of window */
+ op = wnext;
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += wnext - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ }
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ here = dcode + here->val + (hold & ((1U << op) - 1));
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ here = lcode + here->val + (hold & ((1U << op) - 1));
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in;
+ strm->next_out = out;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and wnext == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/libmariadb/external/zlib/inffast.h b/libmariadb/external/zlib/inffast.h
new file mode 100644
index 00000000..e5c1aa4c
--- /dev/null
+++ b/libmariadb/external/zlib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/libmariadb/external/zlib/inffast_chunk.c b/libmariadb/external/zlib/inffast_chunk.c
new file mode 100644
index 00000000..829a8ec3
--- /dev/null
+++ b/libmariadb/external/zlib/inffast_chunk.c
@@ -0,0 +1,379 @@
+/* inffast_chunk.c -- fast decoding
+ *
+ * (C) 1995-2013 Jean-loup Gailly and Mark Adler
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Jean-loup Gailly Mark Adler
+ * jloup@gzip.org madler@alumni.caltech.edu
+ *
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast_chunk.h"
+#include "chunkcopy.h"
+
+#ifdef ASMINF
+# pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate() execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 or 8 bytes)
+ strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes)
+ start >= strm->avail_out
+ state->bits < 8
+ strm->next_out[0..strm->avail_out] does not overlap with
+ strm->next_in[0..strm->avail_in]
+ strm->state->window is allocated with an additional
+ CHUNKCOPY_CHUNK_SIZE-1 bytes of padding beyond strm->state->wsize
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ INFLATE_FAST_MIN_INPUT: 6 or 8 bytes
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The wide input data reading option reads 64 input bits at a time. Thus,
+ if strm->avail_in >= 8, then there is enough input to avoid checking for
+ available input while decoding. Reading consumes the input with:
+
+ hold |= read64le(in) << bits;
+ in += 6;
+ bits += 48;
+
+ reporting 6 bytes of new input because |bits| is 0..15 (2 bytes rounded
+ up, worst case) and 6 bytes is enough to decode as noted above. At exit,
+ hold &= (1U << bits) - 1 drops excess input to keep the invariant:
+
+ (state->hold >> state->bits) == 0
+
+ INFLATE_FAST_MIN_OUTPUT: 258 bytes
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ available output space while decoding.
+ */
+void ZLIB_INTERNAL inflate_fast_chunk_(strm, start)
+z_streamp strm;
+unsigned start; /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *in; /* local strm->next_in */
+ z_const unsigned char FAR *last; /* have enough input while in < last */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+ unsigned char FAR *limit; /* safety limit for chunky copies */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ inflate_holder_t hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code here; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in;
+ last = in + (strm->avail_in - (INFLATE_FAST_MIN_INPUT - 1));
+ out = strm->next_out;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - (INFLATE_FAST_MIN_OUTPUT - 1));
+ limit = out + strm->avail_out;
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+#ifdef INFLATE_CHUNK_READ_64LE
+ hold |= read64le(in) << bits;
+ in += 6;
+ bits += 48;
+#else
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+#endif
+ }
+ here = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(here.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ *out++ = (unsigned char)(here.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(here.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+#ifdef INFLATE_CHUNK_READ_64LE
+ hold |= read64le(in) << bits;
+ in += 6;
+ bits += 48;
+#else
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+#endif
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+#ifdef INFLATE_CHUNK_READ_64LE
+ hold |= read64le(in) << bits;
+ in += 6;
+ bits += 48;
+#else
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+#endif
+ }
+ here = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(here.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(here.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+#ifdef INFLATE_CHUNK_READ_64LE
+ hold |= read64le(in) << bits;
+ in += 6;
+ bits += 48;
+#else
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+#endif
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state->sane) {
+ strm->msg =
+ (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ if (len <= op - whave) {
+ do {
+ *out++ = 0;
+ } while (--len);
+ continue;
+ }
+ len -= op - whave;
+ do {
+ *out++ = 0;
+ } while (--op > whave);
+ if (op == 0) {
+ from = out - dist;
+ do {
+ *out++ = *from++;
+ } while (--len);
+ continue;
+ }
+#endif
+ }
+ from = window;
+ if (wnext >= op) { /* contiguous in window */
+ from += wnext - op;
+ }
+ else { /* wrap around window */
+ op -= wnext;
+ from += wsize - op;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ out = chunkcopy_safe(out, from, op, limit);
+ from = window; /* more from start of window */
+ op = wnext;
+ /* This (rare) case can create a situation where
+ the first chunkcopy below must be checked.
+ */
+ }
+ }
+ if (op < len) { /* still need some from output */
+ out = chunkcopy_safe(out, from, op, limit);
+ len -= op;
+ /* When dist is small the amount of data that can be
+ copied from the window is also small, and progress
+ towards the dangerous end of the output buffer is
+ also small. This means that for trivial memsets and
+ for chunkunroll_relaxed() a safety check is
+ unnecessary. However, these conditions may not be
+ entered at all, and in that case it's possible that
+ the main copy is near the end.
+ */
+ out = chunkunroll_relaxed(out, &dist, &len);
+ out = chunkcopy_safe_ugly(out, dist, len, limit);
+ } else {
+ /* from points to window, so there is no risk of
+ overlapping pointers requiring memset-like behaviour
+ */
+ out = chunkcopy_safe(out, from, len, limit);
+ }
+ }
+ else {
+ /* Whole reference is in range of current output. No
+ range checks are necessary because we start with room
+ for at least 258 bytes of output, so unroll and roundoff
+ operations can write beyond `out+len` so long as they
+ stay within 258 bytes of `out`.
+ */
+ out = chunkcopy_lapped_relaxed(out, dist, len);
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ here = dcode[here.val + (hold & ((1U << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ here = lcode[here.val + (hold & ((1U << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in;
+ strm->next_out = out;
+ strm->avail_in = (unsigned)(in < last ?
+ (INFLATE_FAST_MIN_INPUT - 1) + (last - in) :
+ (INFLATE_FAST_MIN_INPUT - 1) - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ (INFLATE_FAST_MIN_OUTPUT - 1) + (end - out) :
+ (INFLATE_FAST_MIN_OUTPUT - 1) - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+
+ Assert((state->hold >> state->bits) == 0, "invalid input data state");
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and wnext == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/libmariadb/external/zlib/inffast_chunk.h b/libmariadb/external/zlib/inffast_chunk.h
new file mode 100644
index 00000000..de6aa0d8
--- /dev/null
+++ b/libmariadb/external/zlib/inffast_chunk.h
@@ -0,0 +1,48 @@
+/* inffast_chunk.h -- header to use inffast_chunk.c
+ *
+ * (C) 1995-2013 Jean-loup Gailly and Mark Adler
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Jean-loup Gailly Mark Adler
+ * jloup@gzip.org madler@alumni.caltech.edu
+ *
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * Copyright (C) 2017 ARM, Inc.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#include "inffast.h"
+
+/* INFLATE_FAST_MIN_INPUT: the minimum number of input bytes needed so that
+ we can safely call inflate_fast() with only one up-front bounds check. One
+ length/distance code pair (15 bits for the length code, 5 bits for length
+ extra, 15 bits for the distance code, 13 bits for distance extra) requires
+ reading up to 48 input bits (6 bytes). The wide input data reading option
+ requires a little endian machine, and reads 64 input bits (8 bytes).
+*/
+#ifdef INFLATE_CHUNK_READ_64LE
+#undef INFLATE_FAST_MIN_INPUT
+#define INFLATE_FAST_MIN_INPUT 8
+#endif
+
+void ZLIB_INTERNAL inflate_fast_chunk_ OF((z_streamp strm, unsigned start));
diff --git a/libmariadb/external/zlib/inffixed.h b/libmariadb/external/zlib/inffixed.h
new file mode 100644
index 00000000..d6283277
--- /dev/null
+++ b/libmariadb/external/zlib/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications.
+ It is part of the implementation of this library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/libmariadb/external/zlib/inflate.c b/libmariadb/external/zlib/inflate.c
new file mode 100644
index 00000000..8acbef44
--- /dev/null
+++ b/libmariadb/external/zlib/inflate.c
@@ -0,0 +1,1595 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+/* function prototypes */
+local int inflateStateCheck OF((z_streamp strm));
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+ unsigned copy));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
+ unsigned len));
+
+local int inflateStateCheck(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+ return 1;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state == Z_NULL || state->strm != strm ||
+ state->mode < HEAD || state->mode > SYNC)
+ return 1;
+ return 0;
+}
+
+int ZEXPORT inflateResetKeep(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ if (state->wrap) /* to support ill-conceived Java test suite */
+ strm->adler = state->wrap & 1;
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->flags = -1;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ state->sane = 1;
+ state->back = -1;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ state->wsize = 0;
+ state->whave = 0;
+ state->wnext = 0;
+ return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+ int wrap;
+ struct inflate_state FAR *state;
+
+ /* get the state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* extract wrap request from windowBits parameter */
+ if (windowBits < 0) {
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ wrap = (windowBits >> 4) + 5;
+#ifdef GUNZIP
+ if (windowBits < 48)
+ windowBits &= 15;
+#endif
+ }
+
+ /* set number of window bits, free window if different */
+ if (windowBits && (windowBits < 8 || windowBits > 15))
+ return Z_STREAM_ERROR;
+ if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+ ZFREE(strm, state->window);
+ state->window = Z_NULL;
+ }
+
+ /* update state and reset the rest of it */
+ state->wrap = wrap;
+ state->wbits = (unsigned)windowBits;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+ int ret;
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->strm = strm;
+ state->window = Z_NULL;
+ state->mode = HEAD; /* to pass state test in inflateReset2() */
+ ret = inflateReset2(strm, windowBits);
+ if (ret != Z_OK) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ }
+ return ret;
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits < 0) {
+ state->hold = 0;
+ state->bits = 0;
+ return Z_OK;
+ }
+ if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += (unsigned)value << state->bits;
+ state->bits += (uInt)bits;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed()
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+ state.lencode[low].bits, state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, end, copy)
+z_streamp strm;
+const Bytef *end;
+unsigned copy;
+{
+ struct inflate_state FAR *state;
+ unsigned dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->wnext = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, end - state->wsize, state->wsize);
+ state->wnext = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->wnext;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->wnext, end - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, end - copy, copy);
+ state->wnext = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->wnext += dist;
+ if (state->wnext == state->wsize) state->wnext = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE_CHECK(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ if (state->wbits == 0)
+ state->wbits = 15;
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (state->wbits == 0)
+ state->wbits = len;
+ if (len > 15 || len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ state->flags = 0; /* indicate zlib header */
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ /* fallthrough */
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ /* fallthrough */
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ /* fallthrough */
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ /* fallthrough */
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL &&
+ (len = state->head->extra_len - state->length) <
+ state->head->extra_max) {
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ /* fallthrough */
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ /* fallthrough */
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ /* fallthrough */
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = ZSWAP32(hold);
+ INITBITS();
+ state->mode = DICT;
+ /* fallthrough */
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ /* fallthrough */
+ case TYPE:
+ if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN_; /* decode codes */
+ if (flush == Z_TREES) {
+ DROPBITS(2);
+ goto inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY_;
+ if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case COPY_:
+ state->mode = COPY;
+ /* fallthrough */
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ /* fallthrough */
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ /* fallthrough */
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (const code FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN_;
+ if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case LEN_:
+ state->mode = LEN;
+ /* fallthrough */
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ if (state->mode == TYPE)
+ state->back = -1;
+ break;
+ }
+ state->back = 0;
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ state->length = (unsigned)here.val;
+ if ((int)(here.op) == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ state->mode = LIT;
+ break;
+ }
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->back = -1;
+ state->mode = TYPE;
+ break;
+ }
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = LENEXT;
+ /* fallthrough */
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->was = state->length;
+ state->mode = DIST;
+ /* fallthrough */
+ case DIST:
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = DISTEXT;
+ /* fallthrough */
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ /* fallthrough */
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->whave) {
+ if (state->sane) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ Trace((stderr, "inflate.c too far\n"));
+ copy -= state->whave;
+ if (copy > state->length) copy = state->length;
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = 0;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+#endif
+ }
+ if (copy > state->wnext) {
+ copy -= state->wnext;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->wnext - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, put - out, out);
+ out = left;
+ if ((state->wrap & 4) && (
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ ZSWAP32(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ /* fallthrough */
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ /* fallthrough */
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ /* fallthrough */
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+ (state->mode < CHECK || flush != Z_FINISH)))
+ if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, strm->next_out - out, out);
+ strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0) +
+ (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* copy dictionary */
+ if (state->whave && dictionary != Z_NULL) {
+ zmemcpy(dictionary, state->window + state->wnext,
+ state->whave - state->wnext);
+ zmemcpy(dictionary + state->whave - state->wnext,
+ state->window, state->wnext);
+ }
+ if (dictLength != Z_NULL)
+ *dictLength = state->whave;
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ struct inflate_state FAR *state;
+ unsigned long dictid;
+ int ret;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary identifier */
+ if (state->mode == DICT) {
+ dictid = adler32(0L, Z_NULL, 0);
+ dictid = adler32(dictid, dictionary, dictLength);
+ if (dictid != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window using updatewindow(), which will amend the
+ existing dictionary if appropriate */
+ ret = updatewindow(strm, dictionary + dictLength, dictLength);
+ if (ret) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+const unsigned char FAR *buf;
+unsigned len;
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ int flags; /* temporary to save header status */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ if (state->flags == -1)
+ state->wrap = 0; /* if no header yet, treat as raw */
+ else
+ state->wrap &= ~4; /* no point in computing a check value now */
+ flags = state->flags;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->flags = flags;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (inflateStateCheck(source) || dest == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+ zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+ copy->strm = dest;
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ state->sane = !subvert;
+ return Z_OK;
+#else
+ (void)subvert;
+ state->sane = 1;
+ return Z_DATA_ERROR;
+#endif
+}
+
+int ZEXPORT inflateValidate(strm, check)
+z_streamp strm;
+int check;
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (check && state->wrap)
+ state->wrap |= 4;
+ else
+ state->wrap &= ~4;
+ return Z_OK;
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm))
+ return -(1L << 16);
+ state = (struct inflate_state FAR *)strm->state;
+ return (long)(((unsigned long)((long)state->back)) << 16) +
+ (state->mode == COPY ? state->length :
+ (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+unsigned long ZEXPORT inflateCodesUsed(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm)) return (unsigned long)-1;
+ state = (struct inflate_state FAR *)strm->state;
+ return (unsigned long)(state->next - state->codes);
+}
diff --git a/libmariadb/external/zlib/inflate.h b/libmariadb/external/zlib/inflate.h
new file mode 100644
index 00000000..f127b6b1
--- /dev/null
+++ b/libmariadb/external/zlib/inflate.h
@@ -0,0 +1,126 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD = 16180, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY_, /* i/o: same as COPY below, but only first time in */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN_, /* i: same as LEN below, but only first time in */
+ LEN, /* i: waiting for length/lit/eob code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib) or (raw)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+ HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ (raw) -> TYPEDO
+ Read deflate blocks:
+ TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+ STORED -> COPY_ -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN_
+ LEN_ -> LEN
+ Read deflate codes in fixed or dynamic block:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* State maintained between inflate() calls -- approximately 7K bytes, not
+ including the allocated sliding window, which is up to 32K bytes. */
+struct inflate_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
+ bit 2 true to validate check value */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags, 0 if zlib, or
+ -1 if raw or no header yet */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+ int sane; /* if false, allow invalid distance too far */
+ int back; /* bits back of last unprocessed length/lit */
+ unsigned was; /* initial length of match */
+};
diff --git a/libmariadb/external/zlib/inftrees.c b/libmariadb/external/zlib/inftrees.c
new file mode 100644
index 00000000..57d2793b
--- /dev/null
+++ b/libmariadb/external/zlib/inftrees.c
@@ -0,0 +1,304 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.13 Copyright 1995-2022 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code here; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ unsigned match; /* use base and extra for symbol >= match */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)1;
+ here.val = (unsigned short)0;
+ *(*table)++ = here; /* make a table to force an error */
+ *(*table)++ = here;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min < max; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked for LENS and DIST tables against
+ the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+ the initial root table size constants. See the comments in inftrees.h
+ for more information.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ match = 20;
+ break;
+ case LENS:
+ base = lbase;
+ extra = lext;
+ match = 257;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ match = 0;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ here.bits = (unsigned char)(len - drop);
+ if (work[sym] + 1U < match) {
+ here.op = (unsigned char)0;
+ here.val = work[sym];
+ }
+ else if (work[sym] >= match) {
+ here.op = (unsigned char)(extra[work[sym] - match]);
+ here.val = base[work[sym] - match];
+ }
+ else {
+ here.op = (unsigned char)(32 + 64); /* end of block */
+ here.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = here;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /* fill in remaining table entry if code is incomplete (guaranteed to have
+ at most one remaining entry, since if the code is incomplete, the
+ maximum code length that was allowed to get this far is one bit) */
+ if (huff != 0) {
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)(len - drop);
+ here.val = (unsigned short)0;
+ next[huff] = here;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/libmariadb/external/zlib/inftrees.h b/libmariadb/external/zlib/inftrees.h
new file mode 100644
index 00000000..f5366531
--- /dev/null
+++ b/libmariadb/external/zlib/inftrees.h
@@ -0,0 +1,62 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table. The maximum number of code structures is
+ 1444, which is the sum of 852 for literal/length codes and 592 for distance
+ codes. These values were found by exhaustive searches using the program
+ examples/enough.c found in the zlib distribution. The arguments to that
+ program are the number of symbols, the initial root table size, and the
+ maximum bit length of a code. "enough 286 9 15" for literal/length codes
+ returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+ The initial root table size (9 or 6) is found in the fifth argument of the
+ inflate_table() calls in inflate.c and infback.c. If the root table size is
+ changed, then these maximum sizes would be need to be recalculated and
+ updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
diff --git a/libmariadb/external/zlib/make_vms.com b/libmariadb/external/zlib/make_vms.com
new file mode 100644
index 00000000..65e9d0cb
--- /dev/null
+++ b/libmariadb/external/zlib/make_vms.com
@@ -0,0 +1,867 @@
+$! make libz under VMS written by
+$! Martin P.J. Zinser
+$!
+$! In case of problems with the install you might contact me at
+$! zinser@zinser.no-ip.info(preferred) or
+$! martin.zinser@eurexchange.com (work)
+$!
+$! Make procedure history for Zlib
+$!
+$!------------------------------------------------------------------------------
+$! Version history
+$! 0.01 20060120 First version to receive a number
+$! 0.02 20061008 Adapt to new Makefile.in
+$! 0.03 20091224 Add support for large file check
+$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite
+$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in
+$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples
+$! subdir path, update module search in makefile.in
+$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned
+$! shared image creation
+$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared
+$! image
+$! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)).
+$! "" -> automatic, preference: MMK, MMS, built-in.
+$!
+$ on error then goto err_exit
+$!
+$ true = 1
+$ false = 0
+$ tmpnam = "temp_" + f$getjpi("","pid")
+$ tt = tmpnam + ".txt"
+$ tc = tmpnam + ".c"
+$ th = tmpnam + ".h"
+$ define/nolog tconfig 'th'
+$ its_decc = false
+$ its_vaxc = false
+$ its_gnuc = false
+$ s_case = False
+$!
+$! Setup variables holding "config" information
+$!
+$ Make = "''p1'"
+$ name = "Zlib"
+$ version = "?.?.?"
+$ v_string = "ZLIB_VERSION"
+$ v_file = "zlib.h"
+$ ccopt = "/include = []"
+$ lopts = ""
+$ dnsrl = ""
+$ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in"
+$ conf_check_string = ""
+$ linkonly = false
+$ optfile = name + ".opt"
+$ mapfile = name + ".map"
+$ libdefs = ""
+$ vax = f$getsyi("HW_MODEL").lt.1024
+$ axp = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096
+$ ia64 = f$getsyi("HW_MODEL").ge.4096
+$!
+$! 2012-03-05 SMS.
+$! Why is this needed? And if it is needed, why not simply ".not. vax"?
+$!
+$!!! if axp .or. ia64 then set proc/parse=extended
+$!
+$ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL")
+$ mydef = F$parse(whoami,,,"DEVICE")
+$ mydir = f$parse(whoami,,,"DIRECTORY") - "]["
+$ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type")
+$!
+$! Check for MMK/MMS
+$!
+$ if (Make .eqs. "")
+$ then
+$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS"
+$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK"
+$ else
+$ Make = f$edit( Make, "trim")
+$ endif
+$!
+$ gosub find_version
+$!
+$ open/write topt tmp.opt
+$ open/write optf 'optfile'
+$!
+$ gosub check_opts
+$!
+$! Look for the compiler used
+$!
+$ gosub check_compiler
+$ close topt
+$ close optf
+$!
+$ if its_decc
+$ then
+$ ccopt = "/prefix=all" + ccopt
+$ if f$trnlnm("SYS") .eqs. ""
+$ then
+$ if axp
+$ then
+$ define sys sys$library:
+$ else
+$ ccopt = "/decc" + ccopt
+$ define sys decc$library_include:
+$ endif
+$ endif
+$!
+$! 2012-03-05 SMS.
+$! Why /NAMES = AS_IS? Why not simply ".not. vax"? And why not on VAX?
+$!
+$ if axp .or. ia64
+$ then
+$ ccopt = ccopt + "/name=as_is/opt=(inline=speed)"
+$ s_case = true
+$ endif
+$ endif
+$ if its_vaxc .or. its_gnuc
+$ then
+$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
+$ endif
+$!
+$! Build a fake configure input header
+$!
+$ open/write conf_hin config.hin
+$ write conf_hin "#undef _LARGEFILE64_SOURCE"
+$ close conf_hin
+$!
+$!
+$ i = 0
+$FIND_ACONF:
+$ fname = f$element(i,"#",aconf_in_file)
+$ if fname .eqs. "#" then goto AMISS_ERR
+$ if f$search(fname) .eqs. ""
+$ then
+$ i = i + 1
+$ goto find_aconf
+$ endif
+$ open/read/err=aconf_err aconf_in 'fname'
+$ open/write aconf zconf.h
+$ACONF_LOOP:
+$ read/end_of_file=aconf_exit aconf_in line
+$ work = f$edit(line, "compress,trim")
+$ if f$extract(0,6,work) .nes. "#undef"
+$ then
+$ if f$extract(0,12,work) .nes. "#cmakedefine"
+$ then
+$ write aconf line
+$ endif
+$ else
+$ cdef = f$element(1," ",work)
+$ gosub check_config
+$ endif
+$ goto aconf_loop
+$ACONF_EXIT:
+$ write aconf ""
+$ write aconf "/* VMS specifics added by make_vms.com: */"
+$ write aconf "#define VMS 1"
+$ write aconf "#include <unistd.h>"
+$ write aconf "#include <unixio.h>"
+$ write aconf "#ifdef _LARGEFILE"
+$ write aconf "# define off64_t __off64_t"
+$ write aconf "# define fopen64 fopen"
+$ write aconf "# define fseeko64 fseeko"
+$ write aconf "# define lseek64 lseek"
+$ write aconf "# define ftello64 ftell"
+$ write aconf "#endif"
+$ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)"
+$ write aconf "# define HAVE_VSNPRINTF"
+$ write aconf "#endif"
+$ close aconf_in
+$ close aconf
+$ if f$search("''th'") .nes. "" then delete 'th';*
+$! Build the thing plain or with mms
+$!
+$ write sys$output "Compiling Zlib sources ..."
+$ if make.eqs.""
+$ then
+$ if (f$search( "example.obj;*") .nes. "") then delete example.obj;*
+$ if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;*
+$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
+ adler32.c zlib.h zconf.h
+$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
+ compress.c zlib.h zconf.h
+$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
+ crc32.c zlib.h zconf.h
+$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
+ deflate.c deflate.h zutil.h zlib.h zconf.h
+$ CALL MAKE gzclose.OBJ "CC ''CCOPT' gzclose" -
+ gzclose.c zutil.h zlib.h zconf.h
+$ CALL MAKE gzlib.OBJ "CC ''CCOPT' gzlib" -
+ gzlib.c zutil.h zlib.h zconf.h
+$ CALL MAKE gzread.OBJ "CC ''CCOPT' gzread" -
+ gzread.c zutil.h zlib.h zconf.h
+$ CALL MAKE gzwrite.OBJ "CC ''CCOPT' gzwrite" -
+ gzwrite.c zutil.h zlib.h zconf.h
+$ CALL MAKE infback.OBJ "CC ''CCOPT' infback" -
+ infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
+$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
+ inffast.c zutil.h zlib.h zconf.h inffast.h
+$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
+ inflate.c zutil.h zlib.h zconf.h infblock.h
+$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
+ inftrees.c zutil.h zlib.h zconf.h inftrees.h
+$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
+ trees.c deflate.h zutil.h zlib.h zconf.h
+$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
+ uncompr.c zlib.h zconf.h
+$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
+ zutil.c zutil.h zlib.h zconf.h
+$ write sys$output "Building Zlib ..."
+$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
+$ write sys$output "Building example..."
+$ CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" -
+ [.test]example.c zlib.h zconf.h
+$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
+$ write sys$output "Building minigzip..."
+$ CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" -
+ [.test]minigzip.c zlib.h zconf.h
+$ call make minigzip.exe -
+ "LINK minigzip,libz.olb/lib" -
+ minigzip.obj libz.olb
+$ else
+$ gosub crea_mms
+$ write sys$output "Make ''name' ''version' with ''Make' "
+$ 'make'
+$ endif
+$!
+$! Create shareable image
+$!
+$ gosub crea_olist
+$ write sys$output "Creating libzshr.exe"
+$ call map_2_shopt 'mapfile' 'optfile'
+$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt
+$ write sys$output "Zlib build completed"
+$ delete/nolog tmp.opt;*
+$ exit
+$AMISS_ERR:
+$ write sys$output "No source for config.hin found."
+$ write sys$output "Tried any of ''aconf_in_file'"
+$ goto err_exit
+$CC_ERR:
+$ write sys$output "C compiler required to build ''name'"
+$ goto err_exit
+$ERR_EXIT:
+$ set message/facil/ident/sever/text
+$ close/nolog optf
+$ close/nolog topt
+$ close/nolog aconf_in
+$ close/nolog aconf
+$ close/nolog out
+$ close/nolog min
+$ close/nolog mod
+$ close/nolog h_in
+$ write sys$output "Exiting..."
+$ exit 2
+$!
+$!
+$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
+$ V = 'F$Verify(0)
+$! P1 = What we are trying to make
+$! P2 = Command to make it
+$! P3 - P8 What it depends on
+$
+$ If F$Search(P1) .Eqs. "" Then Goto Makeit
+$ Time = F$CvTime(F$File(P1,"RDT"))
+$arg=3
+$Loop:
+$ Argument = P'arg
+$ If Argument .Eqs. "" Then Goto Exit
+$ El=0
+$Loop2:
+$ File = F$Element(El," ",Argument)
+$ If File .Eqs. " " Then Goto Endl
+$ AFile = ""
+$Loop3:
+$ OFile = AFile
+$ AFile = F$Search(File)
+$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
+$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
+$ Goto Loop3
+$NextEL:
+$ El = El + 1
+$ Goto Loop2
+$EndL:
+$ arg=arg+1
+$ If arg .Le. 8 Then Goto Loop
+$ Goto Exit
+$
+$Makeit:
+$ VV=F$VERIFY(0)
+$ write sys$output P2
+$ 'P2
+$ VV='F$Verify(VV)
+$Exit:
+$ If V Then Set Verify
+$ENDSUBROUTINE
+$!------------------------------------------------------------------------------
+$!
+$! Check command line options and set symbols accordingly
+$!
+$!------------------------------------------------------------------------------
+$! Version history
+$! 0.01 20041206 First version to receive a number
+$! 0.02 20060126 Add new "HELP" target
+$ CHECK_OPTS:
+$ i = 1
+$ OPT_LOOP:
+$ if i .lt. 9
+$ then
+$ cparm = f$edit(p'i',"upcase")
+$!
+$! Check if parameter actually contains something
+$!
+$ if f$edit(cparm,"trim") .nes. ""
+$ then
+$ if cparm .eqs. "DEBUG"
+$ then
+$ ccopt = ccopt + "/noopt/deb"
+$ lopts = lopts + "/deb"
+$ endif
+$ if f$locate("CCOPT=",cparm) .lt. f$length(cparm)
+$ then
+$ start = f$locate("=",cparm) + 1
+$ len = f$length(cparm) - start
+$ ccopt = ccopt + f$extract(start,len,cparm)
+$ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) -
+ then s_case = true
+$ endif
+$ if cparm .eqs. "LINK" then linkonly = true
+$ if f$locate("LOPTS=",cparm) .lt. f$length(cparm)
+$ then
+$ start = f$locate("=",cparm) + 1
+$ len = f$length(cparm) - start
+$ lopts = lopts + f$extract(start,len,cparm)
+$ endif
+$ if f$locate("CC=",cparm) .lt. f$length(cparm)
+$ then
+$ start = f$locate("=",cparm) + 1
+$ len = f$length(cparm) - start
+$ cc_com = f$extract(start,len,cparm)
+ if (cc_com .nes. "DECC") .and. -
+ (cc_com .nes. "VAXC") .and. -
+ (cc_com .nes. "GNUC")
+$ then
+$ write sys$output "Unsupported compiler choice ''cc_com' ignored"
+$ write sys$output "Use DECC, VAXC, or GNUC instead"
+$ else
+$ if cc_com .eqs. "DECC" then its_decc = true
+$ if cc_com .eqs. "VAXC" then its_vaxc = true
+$ if cc_com .eqs. "GNUC" then its_gnuc = true
+$ endif
+$ endif
+$ if f$locate("MAKE=",cparm) .lt. f$length(cparm)
+$ then
+$ start = f$locate("=",cparm) + 1
+$ len = f$length(cparm) - start
+$ mmks = f$extract(start,len,cparm)
+$ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS")
+$ then
+$ make = mmks
+$ else
+$ write sys$output "Unsupported make choice ''mmks' ignored"
+$ write sys$output "Use MMK or MMS instead"
+$ endif
+$ endif
+$ if cparm .eqs. "HELP" then gosub bhelp
+$ endif
+$ i = i + 1
+$ goto opt_loop
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Look for the compiler used
+$!
+$! Version history
+$! 0.01 20040223 First version to receive a number
+$! 0.02 20040229 Save/set value of decc$no_rooted_search_lists
+$! 0.03 20060202 Extend handling of GNU C
+$! 0.04 20090402 Compaq -> hp
+$CHECK_COMPILER:
+$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
+$ then
+$ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "")
+$ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "")
+$ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "")
+$ endif
+$!
+$! Exit if no compiler available
+$!
+$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
+$ then goto CC_ERR
+$ else
+$ if its_decc
+$ then
+$ write sys$output "CC compiler check ... hp C"
+$ if f$trnlnm("decc$no_rooted_search_lists") .nes. ""
+$ then
+$ dnrsl = f$trnlnm("decc$no_rooted_search_lists")
+$ endif
+$ define/nolog decc$no_rooted_search_lists 1
+$ else
+$ if its_vaxc then write sys$output "CC compiler check ... VAX C"
+$ if its_gnuc
+$ then
+$ write sys$output "CC compiler check ... GNU C"
+$ if f$trnlnm(topt) then write topt "gnu_cc:[000000]gcclib.olb/lib"
+$ if f$trnlnm(optf) then write optf "gnu_cc:[000000]gcclib.olb/lib"
+$ cc = "gcc"
+$ endif
+$ if f$trnlnm(topt) then write topt "sys$share:vaxcrtl.exe/share"
+$ if f$trnlnm(optf) then write optf "sys$share:vaxcrtl.exe/share"
+$ endif
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! If MMS/MMK are available dump out the descrip.mms if required
+$!
+$CREA_MMS:
+$ write sys$output "Creating descrip.mms..."
+$ create descrip.mms
+$ open/append out descrip.mms
+$ copy sys$input: out
+$ deck
+# descrip.mms: MMS description file for building zlib on VMS
+# written by Martin P.J. Zinser
+# <zinser@zinser.no-ip.info or martin.zinser@eurexchange.com>
+
+OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\
+ gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\
+ deflate.obj, trees.obj, zutil.obj, inflate.obj, \
+ inftrees.obj, inffast.obj
+
+$ eod
+$ write out "CFLAGS=", ccopt
+$ write out "LOPTS=", lopts
+$ write out "all : example.exe minigzip.exe libz.olb"
+$ copy sys$input: out
+$ deck
+ @ write sys$output " Example applications available"
+
+libz.olb : libz.olb($(OBJS))
+ @ write sys$output " libz available"
+
+example.exe : example.obj libz.olb
+ link $(LOPTS) example,libz.olb/lib
+
+minigzip.exe : minigzip.obj libz.olb
+ link $(LOPTS) minigzip,libz.olb/lib
+
+clean :
+ delete *.obj;*,libz.olb;*,*.opt;*,*.exe;*
+
+
+# Other dependencies.
+adler32.obj : adler32.c zutil.h zlib.h zconf.h
+compress.obj : compress.c zlib.h zconf.h
+crc32.obj : crc32.c zutil.h zlib.h zconf.h
+deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h
+example.obj : [.test]example.c zlib.h zconf.h
+gzclose.obj : gzclose.c zutil.h zlib.h zconf.h
+gzlib.obj : gzlib.c zutil.h zlib.h zconf.h
+gzread.obj : gzread.c zutil.h zlib.h zconf.h
+gzwrite.obj : gzwrite.c zutil.h zlib.h zconf.h
+inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h
+inflate.obj : inflate.c zutil.h zlib.h zconf.h
+inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h
+minigzip.obj : [.test]minigzip.c zlib.h zconf.h
+trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h
+uncompr.obj : uncompr.c zlib.h zconf.h
+zutil.obj : zutil.c zutil.h zlib.h zconf.h
+infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
+$ eod
+$ close out
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Read list of core library sources from makefile.in and create options
+$! needed to build shareable image
+$!
+$CREA_OLIST:
+$ open/read min makefile.in
+$ open/write mod modules.opt
+$ src_check_list = "OBJZ =#OBJG ="
+$MRLOOP:
+$ read/end=mrdone min rec
+$ i = 0
+$SRC_CHECK_LOOP:
+$ src_check = f$element(i, "#", src_check_list)
+$ i = i+1
+$ if src_check .eqs. "#" then goto mrloop
+$ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop
+$ rec = rec - src_check
+$ gosub extra_filnam
+$ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop
+$MRSLOOP:
+$ read/end=mrdone min rec
+$ gosub extra_filnam
+$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop
+$MRDONE:
+$ close min
+$ close mod
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Take record extracted in crea_olist and split it into single filenames
+$!
+$EXTRA_FILNAM:
+$ myrec = f$edit(rec - "\", "trim,compress")
+$ i = 0
+$FELOOP:
+$ srcfil = f$element(i," ", myrec)
+$ if (srcfil .nes. " ")
+$ then
+$ write mod f$parse(srcfil,,,"NAME"), ".obj"
+$ i = i + 1
+$ goto feloop
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Find current Zlib version number
+$!
+$FIND_VERSION:
+$ open/read h_in 'v_file'
+$hloop:
+$ read/end=hdone h_in rec
+$ rec = f$edit(rec,"TRIM")
+$ if (f$extract(0,1,rec) .nes. "#") then goto hloop
+$ rec = f$edit(rec - "#", "TRIM")
+$ if f$element(0," ",rec) .nes. "define" then goto hloop
+$ if f$element(1," ",rec) .eqs. v_string
+$ then
+$ version = 'f$element(2," ",rec)'
+$ goto hdone
+$ endif
+$ goto hloop
+$hdone:
+$ close h_in
+$ return
+$!------------------------------------------------------------------------------
+$!
+$CHECK_CONFIG:
+$!
+$ in_ldef = f$locate(cdef,libdefs)
+$ if (in_ldef .lt. f$length(libdefs))
+$ then
+$ write aconf "#define ''cdef' 1"
+$ libdefs = f$extract(0,in_ldef,libdefs) + -
+ f$extract(in_ldef + f$length(cdef) + 1, -
+ f$length(libdefs) - in_ldef - f$length(cdef) - 1, -
+ libdefs)
+$ else
+$ if (f$type('cdef') .eqs. "INTEGER")
+$ then
+$ write aconf "#define ''cdef' ", 'cdef'
+$ else
+$ if (f$type('cdef') .eqs. "STRING")
+$ then
+$ write aconf "#define ''cdef' ", """", '''cdef'', """"
+$ else
+$ gosub check_cc_def
+$ endif
+$ endif
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Check if this is a define relating to the properties of the C/C++
+$! compiler
+$!
+$ CHECK_CC_DEF:
+$ if (cdef .eqs. "_LARGEFILE64_SOURCE")
+$ then
+$ copy sys$input: 'tc'
+$ deck
+#include "tconfig"
+#define _LARGEFILE
+#include <stdio.h>
+
+int main(){
+FILE *fp;
+ fp = fopen("temp.txt","r");
+ fseeko(fp,1,SEEK_SET);
+ fclose(fp);
+}
+
+$ eod
+$ test_inv = false
+$ comm_h = false
+$ gosub cc_prop_check
+$ return
+$ endif
+$ write aconf "/* ", line, " */"
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Check for properties of C/C++ compiler
+$!
+$! Version history
+$! 0.01 20031020 First version to receive a number
+$! 0.02 20031022 Added logic for defines with value
+$! 0.03 20040309 Make sure local config file gets not deleted
+$! 0.04 20041230 Also write include for configure run
+$! 0.05 20050103 Add processing of "comment defines"
+$CC_PROP_CHECK:
+$ cc_prop = true
+$ is_need = false
+$ is_need = (f$extract(0,4,cdef) .eqs. "NEED") .or. (test_inv .eq. true)
+$ if f$search(th) .eqs. "" then create 'th'
+$ set message/nofac/noident/nosever/notext
+$ on error then continue
+$ cc 'tmpnam'
+$ if .not. ($status) then cc_prop = false
+$ on error then continue
+$! The headers might lie about the capabilities of the RTL
+$ link 'tmpnam',tmp.opt/opt
+$ if .not. ($status) then cc_prop = false
+$ set message/fac/ident/sever/text
+$ on error then goto err_exit
+$ delete/nolog 'tmpnam'.*;*/exclude='th'
+$ if (cc_prop .and. .not. is_need) .or. -
+ (.not. cc_prop .and. is_need)
+$ then
+$ write sys$output "Checking for ''cdef'... yes"
+$ if f$type('cdef_val'_yes) .nes. ""
+$ then
+$ if f$type('cdef_val'_yes) .eqs. "INTEGER" -
+ then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_yes)
+$ if f$type('cdef_val'_yes) .eqs. "STRING" -
+ then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_yes)
+$ else
+$ call write_config f$fao("#define !AS 1",cdef)
+$ endif
+$ if (cdef .eqs. "HAVE_FSEEKO") .or. (cdef .eqs. "_LARGE_FILES") .or. -
+ (cdef .eqs. "_LARGEFILE64_SOURCE") then -
+ call write_config f$string("#define _LARGEFILE 1")
+$ else
+$ write sys$output "Checking for ''cdef'... no"
+$ if (comm_h)
+$ then
+ call write_config f$fao("/* !AS */",line)
+$ else
+$ if f$type('cdef_val'_no) .nes. ""
+$ then
+$ if f$type('cdef_val'_no) .eqs. "INTEGER" -
+ then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_no)
+$ if f$type('cdef_val'_no) .eqs. "STRING" -
+ then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_no)
+$ else
+$ call write_config f$fao("#undef !AS",cdef)
+$ endif
+$ endif
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Check for properties of C/C++ compiler with multiple result values
+$!
+$! Version history
+$! 0.01 20040127 First version
+$! 0.02 20050103 Reconcile changes from cc_prop up to version 0.05
+$CC_MPROP_CHECK:
+$ cc_prop = true
+$ i = 1
+$ idel = 1
+$ MT_LOOP:
+$ if f$type(result_'i') .eqs. "STRING"
+$ then
+$ set message/nofac/noident/nosever/notext
+$ on error then continue
+$ cc 'tmpnam'_'i'
+$ if .not. ($status) then cc_prop = false
+$ on error then continue
+$! The headers might lie about the capabilities of the RTL
+$ link 'tmpnam'_'i',tmp.opt/opt
+$ if .not. ($status) then cc_prop = false
+$ set message/fac/ident/sever/text
+$ on error then goto err_exit
+$ delete/nolog 'tmpnam'_'i'.*;*
+$ if (cc_prop)
+$ then
+$ write sys$output "Checking for ''cdef'... ", mdef_'i'
+$ if f$type(mdef_'i') .eqs. "INTEGER" -
+ then call write_config f$fao("#define !AS !UL",cdef,mdef_'i')
+$ if f$type('cdef_val'_yes) .eqs. "STRING" -
+ then call write_config f$fao("#define !AS !AS",cdef,mdef_'i')
+$ goto msym_clean
+$ else
+$ i = i + 1
+$ goto mt_loop
+$ endif
+$ endif
+$ write sys$output "Checking for ''cdef'... no"
+$ call write_config f$fao("#undef !AS",cdef)
+$ MSYM_CLEAN:
+$ if (idel .le. msym_max)
+$ then
+$ delete/sym mdef_'idel'
+$ idel = idel + 1
+$ goto msym_clean
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Write configuration to both permanent and temporary config file
+$!
+$! Version history
+$! 0.01 20031029 First version to receive a number
+$!
+$WRITE_CONFIG: SUBROUTINE
+$ write aconf 'p1'
+$ open/append confh 'th'
+$ write confh 'p1'
+$ close confh
+$ENDSUBROUTINE
+$!------------------------------------------------------------------------------
+$!
+$! Analyze the project map file and create the symbol vector for a shareable
+$! image from it
+$!
+$! Version history
+$! 0.01 20120128 First version
+$! 0.02 20120226 Add pre-load logic
+$!
+$ MAP_2_SHOPT: Subroutine
+$!
+$ SAY := "WRITE_ SYS$OUTPUT"
+$!
+$ IF F$SEARCH("''P1'") .EQS. ""
+$ THEN
+$ SAY "MAP_2_SHOPT-E-NOSUCHFILE: Error, inputfile ''p1' not available"
+$ goto exit_m2s
+$ ENDIF
+$ IF "''P2'" .EQS. ""
+$ THEN
+$ SAY "MAP_2_SHOPT: Error, no output file provided"
+$ goto exit_m2s
+$ ENDIF
+$!
+$ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary"
+$ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread"
+$ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary"
+$ module4 = "inflateSync#uncompress#zlibVersion#compress"
+$ open/read map 'p1
+$ if axp .or. ia64
+$ then
+$ open/write aopt a.opt
+$ open/write bopt b.opt
+$ write aopt " CASE_SENSITIVE=YES"
+$ write bopt "SYMBOL_VECTOR= (-"
+$ mod_sym_num = 1
+$ MOD_SYM_LOOP:
+$ if f$type(module'mod_sym_num') .nes. ""
+$ then
+$ mod_in = 0
+$ MOD_SYM_IN:
+$ shared_proc = f$element(mod_in, "#", module'mod_sym_num')
+$ if shared_proc .nes. "#"
+$ then
+$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",-
+ f$edit(shared_proc,"upcase"),shared_proc)
+$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc)
+$ mod_in = mod_in + 1
+$ goto mod_sym_in
+$ endif
+$ mod_sym_num = mod_sym_num + 1
+$ goto mod_sym_loop
+$ endif
+$MAP_LOOP:
+$ read/end=map_end map line
+$ if (f$locate("{",line).lt. f$length(line)) .or. -
+ (f$locate("global:", line) .lt. f$length(line))
+$ then
+$ proc = true
+$ goto map_loop
+$ endif
+$ if f$locate("}",line).lt. f$length(line) then proc = false
+$ if f$locate("local:", line) .lt. f$length(line) then proc = false
+$ if proc
+$ then
+$ shared_proc = f$edit(line,"collapse")
+$ chop_semi = f$locate(";", shared_proc)
+$ if chop_semi .lt. f$length(shared_proc) then -
+ shared_proc = f$extract(0, chop_semi, shared_proc)
+$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",-
+ f$edit(shared_proc,"upcase"),shared_proc)
+$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc)
+$ endif
+$ goto map_loop
+$MAP_END:
+$ close/nolog aopt
+$ close/nolog bopt
+$ open/append libopt 'p2'
+$ open/read aopt a.opt
+$ open/read bopt b.opt
+$ALOOP:
+$ read/end=aloop_end aopt line
+$ write libopt line
+$ goto aloop
+$ALOOP_END:
+$ close/nolog aopt
+$ sv = ""
+$BLOOP:
+$ read/end=bloop_end bopt svn
+$ if (svn.nes."")
+$ then
+$ if (sv.nes."") then write libopt sv
+$ sv = svn
+$ endif
+$ goto bloop
+$BLOOP_END:
+$ write libopt f$extract(0,f$length(sv)-2,sv), "-"
+$ write libopt ")"
+$ close/nolog bopt
+$ delete/nolog/noconf a.opt;*,b.opt;*
+$ else
+$ if vax
+$ then
+$ open/append libopt 'p2'
+$ mod_sym_num = 1
+$ VMOD_SYM_LOOP:
+$ if f$type(module'mod_sym_num') .nes. ""
+$ then
+$ mod_in = 0
+$ VMOD_SYM_IN:
+$ shared_proc = f$element(mod_in, "#", module'mod_sym_num')
+$ if shared_proc .nes. "#"
+$ then
+$ write libopt f$fao("UNIVERSAL=!AS",-
+ f$edit(shared_proc,"upcase"))
+$ mod_in = mod_in + 1
+$ goto vmod_sym_in
+$ endif
+$ mod_sym_num = mod_sym_num + 1
+$ goto vmod_sym_loop
+$ endif
+$VMAP_LOOP:
+$ read/end=vmap_end map line
+$ if (f$locate("{",line).lt. f$length(line)) .or. -
+ (f$locate("global:", line) .lt. f$length(line))
+$ then
+$ proc = true
+$ goto vmap_loop
+$ endif
+$ if f$locate("}",line).lt. f$length(line) then proc = false
+$ if f$locate("local:", line) .lt. f$length(line) then proc = false
+$ if proc
+$ then
+$ shared_proc = f$edit(line,"collapse")
+$ chop_semi = f$locate(";", shared_proc)
+$ if chop_semi .lt. f$length(shared_proc) then -
+ shared_proc = f$extract(0, chop_semi, shared_proc)
+$ write libopt f$fao("UNIVERSAL=!AS",-
+ f$edit(shared_proc,"upcase"))
+$ endif
+$ goto vmap_loop
+$VMAP_END:
+$ else
+$ write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)"
+$ write sys$output "No options file created"
+$ endif
+$ endif
+$ EXIT_M2S:
+$ close/nolog map
+$ close/nolog libopt
+$ endsubroutine
diff --git a/libmariadb/external/zlib/minigzip.c b/libmariadb/external/zlib/minigzip.c
new file mode 100644
index 00000000..9825ccc3
--- /dev/null
+++ b/libmariadb/external/zlib/minigzip.c
@@ -0,0 +1,440 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-2006, 2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+#include <stdio.h>
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifdef USE_MMAP
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+#endif
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+# include <fcntl.h>
+# include <io.h>
+# ifdef UNDER_CE
+# include <stdlib.h>
+# endif
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+# define unlink delete
+# define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+# define unlink remove
+# define GZ_SUFFIX "-gz"
+# define fileno(file) file->__file
+#endif
+#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fileno */
+#endif
+
+#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
+#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
+ extern int unlink OF((const char *));
+#endif
+#endif
+
+#if defined(UNDER_CE)
+# include <windows.h>
+# define perror(s) pwinerror(s)
+
+/* Map the Windows error number in ERROR to a locale-dependent error
+ message string and return a pointer to it. Typically, the values
+ for ERROR come from GetLastError.
+
+ The string pointed to shall not be modified by the application,
+ but may be overwritten by a subsequent call to strwinerror
+
+ The strwinerror function does not change the current setting
+ of GetLastError. */
+
+static char *strwinerror (error)
+ DWORD error;
+{
+ static char buf[1024];
+
+ wchar_t *msgbuf;
+ DWORD lasterr = GetLastError();
+ DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ error,
+ 0, /* Default language */
+ (LPVOID)&msgbuf,
+ 0,
+ NULL);
+ if (chars != 0) {
+ /* If there is an \r\n appended, zap it. */
+ if (chars >= 2
+ && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > sizeof (buf) - 1) {
+ chars = sizeof (buf) - 1;
+ msgbuf[chars] = 0;
+ }
+
+ wcstombs(buf, msgbuf, chars + 1);
+ LocalFree(msgbuf);
+ }
+ else {
+ sprintf(buf, "unknown win32 error (%ld)", error);
+ }
+
+ SetLastError(lasterr);
+ return buf;
+}
+
+static void pwinerror (s)
+ const char *s;
+{
+ if (s && *s)
+ fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
+ else
+ fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
+}
+
+#endif /* UNDER_CE */
+
+#ifndef GZ_SUFFIX
+# define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
+
+#define BUFLEN 16384
+#define MAX_NAME_LEN 1024
+
+#ifdef MAXSEG_64K
+# define local static
+ /* Needed for systems with limitation on stack size. */
+#else
+# define local
+#endif
+
+char *prog;
+
+void error OF((const char *msg));
+void gz_compress OF((FILE *in, gzFile out));
+#ifdef USE_MMAP
+int gz_compress_mmap OF((FILE *in, gzFile out));
+#endif
+void gz_uncompress OF((gzFile in, FILE *out));
+void file_compress OF((char *file, char *mode));
+void file_uncompress OF((char *file));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+ const char *msg;
+{
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+
+void gz_compress(in, out)
+ FILE *in;
+ gzFile out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+#ifdef USE_MMAP
+ /* Try first compressing with mmap. If mmap fails (minigzip used in a
+ * pipe), use the normal fread loop.
+ */
+ if (gz_compress_mmap(in, out) == Z_OK) return;
+#endif
+ for (;;) {
+ len = (int)fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+ }
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
+
+/* Try compressing the input file at once using mmap. Return Z_OK if
+ * if success, Z_ERRNO otherwise.
+ */
+int gz_compress_mmap(in, out)
+ FILE *in;
+ gzFile out;
+{
+ int len;
+ int err;
+ int ifd = fileno(in);
+ caddr_t buf; /* mmap'ed buffer for the entire input file */
+ off_t buf_len; /* length of the input file */
+ struct stat sb;
+
+ /* Determine the size of the file, needed for mmap: */
+ if (fstat(ifd, &sb) < 0) return Z_ERRNO;
+ buf_len = sb.st_size;
+ if (buf_len <= 0) return Z_ERRNO;
+
+ /* Now do the actual mmap: */
+ buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
+ if (buf == (caddr_t)(-1)) return Z_ERRNO;
+
+ /* Compress the whole file at once: */
+ len = gzwrite(out, (char *)buf, (unsigned)buf_len);
+
+ if (len != (int)buf_len) error(gzerror(out, &err));
+
+ munmap(buf, buf_len);
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+ return Z_OK;
+}
+#endif /* USE_MMAP */
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+ gzFile in;
+ FILE *out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = gzread(in, buf, sizeof(buf));
+ if (len < 0) error (gzerror(in, &err));
+ if (len == 0) break;
+
+ if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+ error("failed fwrite");
+ }
+ }
+ if (fclose(out)) error("failed fclose");
+
+ if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file, mode)
+ char *file;
+ char *mode;
+{
+ local char outfile[MAX_NAME_LEN];
+ FILE *in;
+ gzFile out;
+
+ if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
+ fprintf(stderr, "%s: filename too long\n", prog);
+ exit(1);
+ }
+
+ strcpy(outfile, file);
+ strcat(outfile, GZ_SUFFIX);
+
+ in = fopen(file, "rb");
+ if (in == NULL) {
+ perror(file);
+ exit(1);
+ }
+ out = gzopen(outfile, mode);
+ if (out == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+ exit(1);
+ }
+ gz_compress(in, out);
+
+ unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+ char *file;
+{
+ local char buf[MAX_NAME_LEN];
+ char *infile, *outfile;
+ FILE *out;
+ gzFile in;
+ size_t len = strlen(file);
+
+ if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
+ fprintf(stderr, "%s: filename too long\n", prog);
+ exit(1);
+ }
+
+ strcpy(buf, file);
+
+ if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+ infile = file;
+ outfile = buf;
+ outfile[len-3] = '\0';
+ } else {
+ outfile = file;
+ infile = buf;
+ strcat(infile, GZ_SUFFIX);
+ }
+ in = gzopen(infile, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+ exit(1);
+ }
+ out = fopen(outfile, "wb");
+ if (out == NULL) {
+ perror(file);
+ exit(1);
+ }
+
+ gz_uncompress(in, out);
+
+ unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
+ * -c : write to standard output
+ * -d : decompress
+ * -f : compress with Z_FILTERED
+ * -h : compress with Z_HUFFMAN_ONLY
+ * -r : compress with Z_RLE
+ * -1 to -9 : compression level
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int copyout = 0;
+ int uncompr = 0;
+ gzFile file;
+ char *bname, outmode[20];
+
+ strcpy(outmode, "wb6 ");
+
+ prog = argv[0];
+ bname = strrchr(argv[0], '/');
+ if (bname)
+ bname++;
+ else
+ bname = argv[0];
+ argc--, argv++;
+
+ if (!strcmp(bname, "gunzip"))
+ uncompr = 1;
+ else if (!strcmp(bname, "zcat"))
+ copyout = uncompr = 1;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "-c") == 0)
+ copyout = 1;
+ else if (strcmp(*argv, "-d") == 0)
+ uncompr = 1;
+ else if (strcmp(*argv, "-f") == 0)
+ outmode[3] = 'f';
+ else if (strcmp(*argv, "-h") == 0)
+ outmode[3] = 'h';
+ else if (strcmp(*argv, "-r") == 0)
+ outmode[3] = 'R';
+ else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
+ (*argv)[2] == 0)
+ outmode[2] = (*argv)[1];
+ else
+ break;
+ argc--, argv++;
+ }
+ if (outmode[3] == ' ')
+ outmode[3] = 0;
+ if (argc == 0) {
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+ if (uncompr) {
+ file = gzdopen(fileno(stdin), "rb");
+ if (file == NULL) error("can't gzdopen stdin");
+ gz_uncompress(file, stdout);
+ } else {
+ file = gzdopen(fileno(stdout), outmode);
+ if (file == NULL) error("can't gzdopen stdout");
+ gz_compress(stdin, file);
+ }
+ } else {
+ if (copyout) {
+ SET_BINARY_MODE(stdout);
+ }
+ do {
+ if (uncompr) {
+ if (copyout) {
+ file = gzopen(*argv, "rb");
+ if (file == NULL)
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
+ else
+ gz_uncompress(file, stdout);
+ } else {
+ file_uncompress(*argv);
+ }
+ } else {
+ if (copyout) {
+ FILE * in = fopen(*argv, "rb");
+
+ if (in == NULL) {
+ perror(*argv);
+ } else {
+ file = gzdopen(fileno(stdout), outmode);
+ if (file == NULL) error("can't gzdopen stdout");
+
+ gz_compress(in, file);
+ }
+
+ } else {
+ file_compress(*argv, outmode);
+ }
+ }
+ } while (argv++, --argc);
+ }
+ return 0;
+}
diff --git a/libmariadb/external/zlib/msdos/Makefile.bor b/libmariadb/external/zlib/msdos/Makefile.bor
new file mode 100644
index 00000000..3d12a2c2
--- /dev/null
+++ b/libmariadb/external/zlib/msdos/Makefile.bor
@@ -0,0 +1,115 @@
+# Makefile for zlib
+# Borland C++
+# Last updated: 15-Mar-2003
+
+# To use, do "make -fmakefile.bor"
+# To compile in small model, set below: MODEL=s
+
+# WARNING: the small model is supported but only for small values of
+# MAX_WBITS and MAX_MEM_LEVEL. For example:
+# -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to the LOC macro below:
+# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------ Turbo C++, Borland C++ ------------
+
+# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added
+# to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+# type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# memory model: one of s, m, c, l (small, medium, compact, large)
+MODEL=l
+
+# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version
+CC=bcc
+LD=bcc
+AR=tlib
+
+# compiler flags
+# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0
+CFLAGS=-O2 -Z -m$(MODEL) $(LOC)
+
+LDFLAGS=-m$(MODEL) -f-
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+ $(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: test/example.c zlib.h zconf.h
+
+minigzip.obj: test/minigzip.c zlib.h zconf.h
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+ -del $(ZLIB_LIB)
+ $(AR) $(ZLIB_LIB) $(OBJP1)
+ $(AR) $(ZLIB_LIB) $(OBJP2)
+
+example.exe: example.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+test: example.exe minigzip.exe
+ example
+ echo hello world | minigzip | minigzip -d
+
+clean:
+ -del *.obj
+ -del *.lib
+ -del *.exe
+ -del zlib_*.bak
+ -del foo.gz
diff --git a/libmariadb/external/zlib/msdos/Makefile.dj2 b/libmariadb/external/zlib/msdos/Makefile.dj2
new file mode 100644
index 00000000..29b03954
--- /dev/null
+++ b/libmariadb/external/zlib/msdos/Makefile.dj2
@@ -0,0 +1,104 @@
+# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96.
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type:
+#
+# make -fmakefile.dj2; make test -fmakefile.dj2
+#
+# To install libz.a, zconf.h and zlib.h in the djgpp directories, type:
+#
+# make install -fmakefile.dj2
+#
+# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as
+# in the sample below if the pattern of the DJGPP distribution is to
+# be followed. Remember that, while <sp>'es around <=> are ignored in
+# makefiles, they are *not* in batch files or in djgpp.env.
+# - - - - -
+# [make]
+# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include
+# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib
+# BUTT=-m486
+# - - - - -
+# Alternately, these variables may be defined below, overriding the values
+# in djgpp.env, as
+# INCLUDE_PATH=c:\usr\include
+# LIBRARY_PATH=c:\usr\lib
+
+CC=gcc
+
+#CFLAGS=-MMD -O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-MMD -g -DDEBUG
+CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+ -Wstrict-prototypes -Wmissing-prototypes
+
+# If cp.exe is available, replace "copy /Y" with "cp -fp" .
+CP=copy /Y
+# If gnu install.exe is available, replace $(CP) with ginstall.
+INSTALL=$(CP)
+# The default value of RM is "rm -f." If "rm.exe" is found, comment out:
+RM=del
+LDLIBS=-L. -lz
+LD=$(CC) -s -o
+LDSHARED=$(CC)
+
+INCL=zlib.h zconf.h
+LIBS=libz.a
+
+AR=ar rcs
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
+
+OBJA =
+# to use the asm code: make OBJA=match.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example.exe minigzip.exe
+
+check: test
+test: all
+ ./example
+ echo hello world | .\minigzip | .\minigzip -d
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+libz.a: $(OBJS) $(OBJA)
+ $(AR) $@ $(OBJS) $(OBJA)
+
+%.exe : %.o $(LIBS)
+ $(LD) $@ $< $(LDLIBS)
+
+# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env .
+
+.PHONY : uninstall clean
+
+install: $(INCL) $(LIBS)
+ -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH)
+ -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH)
+ $(INSTALL) zlib.h $(INCLUDE_PATH)
+ $(INSTALL) zconf.h $(INCLUDE_PATH)
+ $(INSTALL) libz.a $(LIBRARY_PATH)
+
+uninstall:
+ $(RM) $(INCLUDE_PATH)\zlib.h
+ $(RM) $(INCLUDE_PATH)\zconf.h
+ $(RM) $(LIBRARY_PATH)\libz.a
+
+clean:
+ $(RM) *.d
+ $(RM) *.o
+ $(RM) *.exe
+ $(RM) libz.a
+ $(RM) foo.gz
+
+DEPS := $(wildcard *.d)
+ifneq ($(DEPS),)
+include $(DEPS)
+endif
diff --git a/libmariadb/external/zlib/msdos/Makefile.emx b/libmariadb/external/zlib/msdos/Makefile.emx
new file mode 100644
index 00000000..9c1b57a5
--- /dev/null
+++ b/libmariadb/external/zlib/msdos/Makefile.emx
@@ -0,0 +1,69 @@
+# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98.
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type:
+#
+# make -fmakefile.emx; make test -fmakefile.emx
+#
+
+CC=gcc
+
+#CFLAGS=-MMD -O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-MMD -g -DDEBUG
+CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+ -Wstrict-prototypes -Wmissing-prototypes
+
+# If cp.exe is available, replace "copy /Y" with "cp -fp" .
+CP=copy /Y
+# If gnu install.exe is available, replace $(CP) with ginstall.
+INSTALL=$(CP)
+# The default value of RM is "rm -f." If "rm.exe" is found, comment out:
+RM=del
+LDLIBS=-L. -lzlib
+LD=$(CC) -s -o
+LDSHARED=$(CC)
+
+INCL=zlib.h zconf.h
+LIBS=zlib.a
+
+AR=ar rcs
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example.exe minigzip.exe
+
+test: all
+ ./example
+ echo hello world | .\minigzip | .\minigzip -d
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+zlib.a: $(OBJS)
+ $(AR) $@ $(OBJS)
+
+%.exe : %.o $(LIBS)
+ $(LD) $@ $< $(LDLIBS)
+
+
+.PHONY : clean
+
+clean:
+ $(RM) *.d
+ $(RM) *.o
+ $(RM) *.exe
+ $(RM) zlib.a
+ $(RM) foo.gz
+
+DEPS := $(wildcard *.d)
+ifneq ($(DEPS),)
+include $(DEPS)
+endif
diff --git a/libmariadb/external/zlib/msdos/Makefile.msc b/libmariadb/external/zlib/msdos/Makefile.msc
new file mode 100644
index 00000000..ae837861
--- /dev/null
+++ b/libmariadb/external/zlib/msdos/Makefile.msc
@@ -0,0 +1,112 @@
+# Makefile for zlib
+# Microsoft C 5.1 or later
+# Last updated: 19-Mar-2003
+
+# To use, do "make makefile.msc"
+# To compile in small model, set below: MODEL=S
+
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to the LOC macro below:
+# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------- Microsoft C 5.1 and later -------------
+
+# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added
+# to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# Memory model: one of S, M, C, L (small, medium, compact, large)
+MODEL=L
+
+CC=cl
+CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC)
+#-Ox generates bad code with MSC 5.1
+LIB_CFLAGS=-Zl $(CFLAGS)
+
+LD=link
+LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode
+# "/farcall/packcode" are only useful for `large code' memory models
+# but should be a "no-op" for small code models.
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+ $(CC) -c $(LIB_CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: test/example.c zlib.h zconf.h
+ $(CC) -c $(CFLAGS) $*.c
+
+minigzip.obj: test/minigzip.c zlib.h zconf.h
+ $(CC) -c $(CFLAGS) $*.c
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+ if exist $(ZLIB_LIB) del $(ZLIB_LIB)
+ lib $(ZLIB_LIB) $(OBJ1);
+ lib $(ZLIB_LIB) $(OBJ2);
+
+example.exe: example.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB);
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB);
+
+test: example.exe minigzip.exe
+ example
+ echo hello world | minigzip | minigzip -d
+
+clean:
+ -del *.obj
+ -del *.lib
+ -del *.exe
+ -del *.map
+ -del zlib_*.bak
+ -del foo.gz
diff --git a/libmariadb/external/zlib/msdos/Makefile.tc b/libmariadb/external/zlib/msdos/Makefile.tc
new file mode 100644
index 00000000..5aec82a9
--- /dev/null
+++ b/libmariadb/external/zlib/msdos/Makefile.tc
@@ -0,0 +1,100 @@
+# Makefile for zlib
+# Turbo C 2.01, Turbo C++ 1.01
+# Last updated: 15-Mar-2003
+
+# To use, do "make -fmakefile.tc"
+# To compile in small model, set below: MODEL=s
+
+# WARNING: the small model is supported but only for small values of
+# MAX_WBITS and MAX_MEM_LEVEL. For example:
+# -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to CFLAGS below:
+# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------ Turbo C 2.01, Turbo C++ 1.01 ------------
+MODEL=l
+CC=tcc
+LD=tcc
+AR=tlib
+# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+CFLAGS=-O2 -G -Z -m$(MODEL)
+LDFLAGS=-m$(MODEL) -f-
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+ $(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: test/example.c zlib.h zconf.h
+
+minigzip.obj: test/minigzip.c zlib.h zconf.h
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+ -del $(ZLIB_LIB)
+ $(AR) $(ZLIB_LIB) $(OBJP1)
+ $(AR) $(ZLIB_LIB) $(OBJP2)
+
+example.exe: example.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+test: example.exe minigzip.exe
+ example
+ echo hello world | minigzip | minigzip -d
+
+clean:
+ -del *.obj
+ -del *.lib
+ -del *.exe
+ -del zlib_*.bak
+ -del foo.gz
diff --git a/libmariadb/external/zlib/nintendods/README b/libmariadb/external/zlib/nintendods/README
new file mode 100644
index 00000000..ba7a37db
--- /dev/null
+++ b/libmariadb/external/zlib/nintendods/README
@@ -0,0 +1,5 @@
+This Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template.
+
+Eduardo Costa <eduardo.m.costa@gmail.com>
+January 3, 2009
+
diff --git a/libmariadb/external/zlib/old/Makefile.emx b/libmariadb/external/zlib/old/Makefile.emx
new file mode 100644
index 00000000..4d6ab0ef
--- /dev/null
+++ b/libmariadb/external/zlib/old/Makefile.emx
@@ -0,0 +1,69 @@
+# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98.
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type:
+#
+# make -fmakefile.emx; make test -fmakefile.emx
+#
+
+CC=gcc -Zwin32
+
+#CFLAGS=-MMD -O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-MMD -g -DDEBUG
+CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+ -Wstrict-prototypes -Wmissing-prototypes
+
+# If cp.exe is available, replace "copy /Y" with "cp -fp" .
+CP=copy /Y
+# If gnu install.exe is available, replace $(CP) with ginstall.
+INSTALL=$(CP)
+# The default value of RM is "rm -f." If "rm.exe" is found, comment out:
+RM=del
+LDLIBS=-L. -lzlib
+LD=$(CC) -s -o
+LDSHARED=$(CC)
+
+INCL=zlib.h zconf.h
+LIBS=zlib.a
+
+AR=ar rcs
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \
+ gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example.exe minigzip.exe
+
+test: all
+ ./example
+ echo hello world | .\minigzip | .\minigzip -d
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+zlib.a: $(OBJS)
+ $(AR) $@ $(OBJS)
+
+%.exe : %.o $(LIBS)
+ $(LD) $@ $< $(LDLIBS)
+
+
+.PHONY : clean
+
+clean:
+ $(RM) *.d
+ $(RM) *.o
+ $(RM) *.exe
+ $(RM) zlib.a
+ $(RM) foo.gz
+
+DEPS := $(wildcard *.d)
+ifneq ($(DEPS),)
+include $(DEPS)
+endif
diff --git a/libmariadb/external/zlib/old/Makefile.riscos b/libmariadb/external/zlib/old/Makefile.riscos
new file mode 100644
index 00000000..57e29d3f
--- /dev/null
+++ b/libmariadb/external/zlib/old/Makefile.riscos
@@ -0,0 +1,151 @@
+# Project: zlib_1_03
+# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430
+# test works out-of-the-box, installs `somewhere' on demand
+
+# Toolflags:
+CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah
+C++flags = -c -depend !Depend -IC: -throwback
+Linkflags = -aif -c++ -o $@
+ObjAsmflags = -throwback -NoCache -depend !Depend
+CMHGflags =
+LibFileflags = -c -l -o $@
+Squeezeflags = -o $@
+
+# change the line below to where _you_ want the library installed.
+libdest = lib:zlib
+
+# Final targets:
+@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \
+ @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \
+ @.o.uncompr @.o.zutil
+ LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \
+ @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \
+ @.o.trees @.o.uncompr @.o.zutil
+test: @.minigzip @.example @.lib
+ @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV
+ @echo running tests: hang on.
+ @/@.minigzip -f -9 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -f -1 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -h -9 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -h -1 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -9 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -1 libc
+ @/@.minigzip -d libc-gz
+ @diff @.lib @.libc
+ @echo that should have reported '@.lib and @.libc identical' if you have diff.
+ @/@.example @.fred @.fred
+ @echo that will have given lots of hello!'s.
+
+@.minigzip: @.o.minigzip @.lib C:o.Stubs
+ Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs
+@.example: @.o.example @.lib C:o.Stubs
+ Link $(Linkflags) @.o.example @.lib C:o.Stubs
+
+install: @.lib
+ cdir $(libdest)
+ cdir $(libdest).h
+ @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV
+ @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV
+ @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV
+ @echo okay, installed zlib in $(libdest)
+
+clean:; remove @.minigzip
+ remove @.example
+ remove @.libc
+ -wipe @.o.* F~r~cV
+ remove @.fred
+
+# User-editable dependencies:
+.c.o:
+ cc $(ccflags) -o $@ $<
+
+# Static dependencies:
+
+# Dynamic dependencies:
+o.example: c.example
+o.example: h.zlib
+o.example: h.zconf
+o.minigzip: c.minigzip
+o.minigzip: h.zlib
+o.minigzip: h.zconf
+o.adler32: c.adler32
+o.adler32: h.zlib
+o.adler32: h.zconf
+o.compress: c.compress
+o.compress: h.zlib
+o.compress: h.zconf
+o.crc32: c.crc32
+o.crc32: h.zlib
+o.crc32: h.zconf
+o.deflate: c.deflate
+o.deflate: h.deflate
+o.deflate: h.zutil
+o.deflate: h.zlib
+o.deflate: h.zconf
+o.gzio: c.gzio
+o.gzio: h.zutil
+o.gzio: h.zlib
+o.gzio: h.zconf
+o.infblock: c.infblock
+o.infblock: h.zutil
+o.infblock: h.zlib
+o.infblock: h.zconf
+o.infblock: h.infblock
+o.infblock: h.inftrees
+o.infblock: h.infcodes
+o.infblock: h.infutil
+o.infcodes: c.infcodes
+o.infcodes: h.zutil
+o.infcodes: h.zlib
+o.infcodes: h.zconf
+o.infcodes: h.inftrees
+o.infcodes: h.infblock
+o.infcodes: h.infcodes
+o.infcodes: h.infutil
+o.infcodes: h.inffast
+o.inffast: c.inffast
+o.inffast: h.zutil
+o.inffast: h.zlib
+o.inffast: h.zconf
+o.inffast: h.inftrees
+o.inffast: h.infblock
+o.inffast: h.infcodes
+o.inffast: h.infutil
+o.inffast: h.inffast
+o.inflate: c.inflate
+o.inflate: h.zutil
+o.inflate: h.zlib
+o.inflate: h.zconf
+o.inflate: h.infblock
+o.inftrees: c.inftrees
+o.inftrees: h.zutil
+o.inftrees: h.zlib
+o.inftrees: h.zconf
+o.inftrees: h.inftrees
+o.inftrees: h.inffixed
+o.infutil: c.infutil
+o.infutil: h.zutil
+o.infutil: h.zlib
+o.infutil: h.zconf
+o.infutil: h.infblock
+o.infutil: h.inftrees
+o.infutil: h.infcodes
+o.infutil: h.infutil
+o.trees: c.trees
+o.trees: h.deflate
+o.trees: h.zutil
+o.trees: h.zlib
+o.trees: h.zconf
+o.trees: h.trees
+o.uncompr: c.uncompr
+o.uncompr: h.zlib
+o.uncompr: h.zconf
+o.zutil: c.zutil
+o.zutil: h.zutil
+o.zutil: h.zlib
+o.zutil: h.zconf
diff --git a/libmariadb/external/zlib/old/README b/libmariadb/external/zlib/old/README
new file mode 100644
index 00000000..800bf079
--- /dev/null
+++ b/libmariadb/external/zlib/old/README
@@ -0,0 +1,3 @@
+This directory contains files that have not been updated for zlib 1.2.x
+
+(Volunteers are encouraged to help clean this up. Thanks.)
diff --git a/libmariadb/external/zlib/old/descrip.mms b/libmariadb/external/zlib/old/descrip.mms
new file mode 100644
index 00000000..7066da5b
--- /dev/null
+++ b/libmariadb/external/zlib/old/descrip.mms
@@ -0,0 +1,48 @@
+# descrip.mms: MMS description file for building zlib on VMS
+# written by Martin P.J. Zinser <m.zinser@gsi.de>
+
+cc_defs =
+c_deb =
+
+.ifdef __DECC__
+pref = /prefix=all
+.endif
+
+OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\
+ deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\
+ inftrees.obj, infcodes.obj, infutil.obj, inffast.obj
+
+CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF)
+
+all : example.exe minigzip.exe
+ @ write sys$output " Example applications available"
+libz.olb : libz.olb($(OBJS))
+ @ write sys$output " libz available"
+
+example.exe : example.obj libz.olb
+ link example,libz.olb/lib
+
+minigzip.exe : minigzip.obj libz.olb
+ link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
+
+clean :
+ delete *.obj;*,libz.olb;*
+
+
+# Other dependencies.
+adler32.obj : zutil.h zlib.h zconf.h
+compress.obj : zlib.h zconf.h
+crc32.obj : zutil.h zlib.h zconf.h
+deflate.obj : deflate.h zutil.h zlib.h zconf.h
+example.obj : zlib.h zconf.h
+gzio.obj : zutil.h zlib.h zconf.h
+infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h
+inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h
+inflate.obj : zutil.h zlib.h zconf.h infblock.h
+inftrees.obj : zutil.h zlib.h zconf.h inftrees.h
+infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h
+minigzip.obj : zlib.h zconf.h
+trees.obj : deflate.h zutil.h zlib.h zconf.h
+uncompr.obj : zlib.h zconf.h
+zutil.obj : zutil.h zlib.h zconf.h
diff --git a/libmariadb/external/zlib/old/os2/Makefile.os2 b/libmariadb/external/zlib/old/os2/Makefile.os2
new file mode 100644
index 00000000..a105aaa5
--- /dev/null
+++ b/libmariadb/external/zlib/old/os2/Makefile.os2
@@ -0,0 +1,136 @@
+# Makefile for zlib under OS/2 using GCC (PGCC)
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile and test, type:
+# cp Makefile.os2 ..
+# cd ..
+# make -f Makefile.os2 test
+
+# This makefile will build a static library z.lib, a shared library
+# z.dll and a import library zdll.lib. You can use either z.lib or
+# zdll.lib by specifying either -lz or -lzdll on gcc's command line
+
+CC=gcc -Zomf -s
+
+CFLAGS=-O6 -Wall
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DDEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+#################### BUG WARNING: #####################
+## infcodes.c hits a bug in pgcc-1.0, so you have to use either
+## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem)
+## This bug is reportedly fixed in pgcc >1.0, but this was not tested
+CFLAGS+=-fno-force-mem
+
+LDFLAGS=-s -L. -lzdll -Zcrtdll
+LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll
+
+VER=1.1.0
+ZLIB=z.lib
+SHAREDLIB=z.dll
+SHAREDLIBIMP=zdll.lib
+LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP)
+
+AR=emxomfar cr
+IMPLIB=emximp
+RANLIB=echo
+TAR=tar
+SHELL=bash
+
+prefix=/usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+ zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
+
+TEST_OBJS = example.o minigzip.o
+
+DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \
+ algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \
+ nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \
+ contrib/asm386/*.asm contrib/asm386/*.c \
+ contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \
+ contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \
+ contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32
+
+all: example.exe minigzip.exe
+
+test: all
+ @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+ echo hello world | ./minigzip | ./minigzip -d || \
+ echo ' *** minigzip test FAILED ***' ; \
+ if ./example; then \
+ echo ' *** zlib test OK ***'; \
+ else \
+ echo ' *** zlib test FAILED ***'; \
+ fi
+
+$(ZLIB): $(OBJS)
+ $(AR) $@ $(OBJS)
+ -@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+$(SHAREDLIB): $(OBJS) os2/z.def
+ $(LDSHARED) -o $@ $^
+
+$(SHAREDLIBIMP): os2/z.def
+ $(IMPLIB) -o $@ $^
+
+example.exe: example.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
+
+minigzip.exe: minigzip.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
+
+clean:
+ rm -f *.o *~ example minigzip libz.a libz.so* foo.gz
+
+distclean: clean
+
+zip:
+ mv Makefile Makefile~; cp -p Makefile.in Makefile
+ rm -f test.c ztest*.c
+ v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+ zip -ul9 zlib$$v $(DISTFILES)
+ mv Makefile~ Makefile
+
+dist:
+ mv Makefile Makefile~; cp -p Makefile.in Makefile
+ rm -f test.c ztest*.c
+ d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+ rm -f $$d.tar.gz; \
+ if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \
+ files=""; \
+ for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \
+ cd ..; \
+ GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \
+ if test ! -d $$d; then rm -f $$d; fi
+ mv Makefile~ Makefile
+
+tags:
+ etags *.[ch]
+
+depend:
+ makedepend -- $(CFLAGS) -- *.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
+infcodes.o: zutil.h zlib.h zconf.h
+infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h
+inffast.o: infblock.h infcodes.h infutil.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h infblock.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/libmariadb/external/zlib/old/os2/zlib.def b/libmariadb/external/zlib/old/os2/zlib.def
new file mode 100644
index 00000000..4c753f1a
--- /dev/null
+++ b/libmariadb/external/zlib/old/os2/zlib.def
@@ -0,0 +1,51 @@
+;
+; Slightly modified version of ../nt/zlib.dnt :-)
+;
+
+LIBRARY Z
+DESCRIPTION "Zlib compression library for OS/2"
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE MULTIPLE
+
+EXPORTS
+ adler32
+ compress
+ crc32
+ deflate
+ deflateCopy
+ deflateEnd
+ deflateInit2_
+ deflateInit_
+ deflateParams
+ deflateReset
+ deflateSetDictionary
+ gzclose
+ gzdopen
+ gzerror
+ gzflush
+ gzopen
+ gzread
+ gzwrite
+ inflate
+ inflateEnd
+ inflateInit2_
+ inflateInit_
+ inflateReset
+ inflateSetDictionary
+ inflateSync
+ uncompress
+ zlibVersion
+ gzprintf
+ gzputc
+ gzgetc
+ gzseek
+ gzrewind
+ gztell
+ gzeof
+ gzsetparams
+ zError
+ inflateSyncPoint
+ get_crc_table
+ compress2
+ gzputs
+ gzgets
diff --git a/libmariadb/external/zlib/old/visual-basic.txt b/libmariadb/external/zlib/old/visual-basic.txt
new file mode 100644
index 00000000..57efe581
--- /dev/null
+++ b/libmariadb/external/zlib/old/visual-basic.txt
@@ -0,0 +1,160 @@
+See below some functions declarations for Visual Basic.
+
+Frequently Asked Question:
+
+Q: Each time I use the compress function I get the -5 error (not enough
+ room in the output buffer).
+
+A: Make sure that the length of the compressed buffer is passed by
+ reference ("as any"), not by value ("as long"). Also check that
+ before the call of compress this length is equal to the total size of
+ the compressed buffer and not zero.
+
+
+From: "Jon Caruana" <jon-net@usa.net>
+Subject: Re: How to port zlib declares to vb?
+Date: Mon, 28 Oct 1996 18:33:03 -0600
+
+Got the answer! (I haven't had time to check this but it's what I got, and
+looks correct):
+
+He has the following routines working:
+ compress
+ uncompress
+ gzopen
+ gzwrite
+ gzread
+ gzclose
+
+Declares follow: (Quoted from Carlos Rios <c_rios@sonda.cl>, in Vb4 form)
+
+#If Win16 Then 'Use Win16 calls.
+Declare Function compress Lib "ZLIB.DLL" (ByVal compr As
+ String, comprLen As Any, ByVal buf As String, ByVal buflen
+ As Long) As Integer
+Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr
+ As String, uncomprLen As Any, ByVal compr As String, ByVal
+ lcompr As Long) As Integer
+Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As
+ String, ByVal mode As String) As Long
+Declare Function gzread Lib "ZLIB.DLL" (ByVal file As
+ Long, ByVal uncompr As String, ByVal uncomprLen As Integer)
+ As Integer
+Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As
+ Long, ByVal uncompr As String, ByVal uncomprLen As Integer)
+ As Integer
+Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As
+ Long) As Integer
+#Else
+Declare Function compress Lib "ZLIB32.DLL"
+ (ByVal compr As String, comprLen As Any, ByVal buf As
+ String, ByVal buflen As Long) As Integer
+Declare Function uncompress Lib "ZLIB32.DLL"
+ (ByVal uncompr As String, uncomprLen As Any, ByVal compr As
+ String, ByVal lcompr As Long) As Long
+Declare Function gzopen Lib "ZLIB32.DLL"
+ (ByVal file As String, ByVal mode As String) As Long
+Declare Function gzread Lib "ZLIB32.DLL"
+ (ByVal file As Long, ByVal uncompr As String, ByVal
+ uncomprLen As Long) As Long
+Declare Function gzwrite Lib "ZLIB32.DLL"
+ (ByVal file As Long, ByVal uncompr As String, ByVal
+ uncomprLen As Long) As Long
+Declare Function gzclose Lib "ZLIB32.DLL"
+ (ByVal file As Long) As Long
+#End If
+
+-Jon Caruana
+jon-net@usa.net
+Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member
+
+
+Here is another example from Michael <michael_borgsys@hotmail.com> that he
+says conforms to the VB guidelines, and that solves the problem of not
+knowing the uncompressed size by storing it at the end of the file:
+
+'Calling the functions:
+'bracket meaning: <parameter> [optional] {Range of possible values}
+'Call subCompressFile(<path with filename to compress> [, <path with
+filename to write to>, [level of compression {1..9}]])
+'Call subUncompressFile(<path with filename to compress>)
+
+Option Explicit
+Private lngpvtPcnSml As Long 'Stores value for 'lngPercentSmaller'
+Private Const SUCCESS As Long = 0
+Private Const strFilExt As String = ".cpr"
+Private Declare Function lngfncCpr Lib "zlib.dll" Alias "compress2" (ByRef
+dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long,
+ByVal level As Integer) As Long
+Private Declare Function lngfncUcp Lib "zlib.dll" Alias "uncompress" (ByRef
+dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long)
+As Long
+
+Public Sub subCompressFile(ByVal strargOriFilPth As String, Optional ByVal
+strargCprFilPth As String, Optional ByVal intLvl As Integer = 9)
+ Dim strCprPth As String
+ Dim lngOriSiz As Long
+ Dim lngCprSiz As Long
+ Dim bytaryOri() As Byte
+ Dim bytaryCpr() As Byte
+ lngOriSiz = FileLen(strargOriFilPth)
+ ReDim bytaryOri(lngOriSiz - 1)
+ Open strargOriFilPth For Binary Access Read As #1
+ Get #1, , bytaryOri()
+ Close #1
+ strCprPth = IIf(strargCprFilPth = "", strargOriFilPth, strargCprFilPth)
+'Select file path and name
+ strCprPth = strCprPth & IIf(Right(strCprPth, Len(strFilExt)) =
+strFilExt, "", strFilExt) 'Add file extension if not exists
+ lngCprSiz = (lngOriSiz * 1.01) + 12 'Compression needs temporary a bit
+more space then original file size
+ ReDim bytaryCpr(lngCprSiz - 1)
+ If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) =
+SUCCESS Then
+ lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100
+ ReDim Preserve bytaryCpr(lngCprSiz - 1)
+ Open strCprPth For Binary Access Write As #1
+ Put #1, , bytaryCpr()
+ Put #1, , lngOriSiz 'Add the the original size value to the end
+(last 4 bytes)
+ Close #1
+ Else
+ MsgBox "Compression error"
+ End If
+ Erase bytaryCpr
+ Erase bytaryOri
+End Sub
+
+Public Sub subUncompressFile(ByVal strargFilPth As String)
+ Dim bytaryCpr() As Byte
+ Dim bytaryOri() As Byte
+ Dim lngOriSiz As Long
+ Dim lngCprSiz As Long
+ Dim strOriPth As String
+ lngCprSiz = FileLen(strargFilPth)
+ ReDim bytaryCpr(lngCprSiz - 1)
+ Open strargFilPth For Binary Access Read As #1
+ Get #1, , bytaryCpr()
+ Close #1
+ 'Read the original file size value:
+ lngOriSiz = bytaryCpr(lngCprSiz - 1) * (2 ^ 24) _
+ + bytaryCpr(lngCprSiz - 2) * (2 ^ 16) _
+ + bytaryCpr(lngCprSiz - 3) * (2 ^ 8) _
+ + bytaryCpr(lngCprSiz - 4)
+ ReDim Preserve bytaryCpr(lngCprSiz - 5) 'Cut of the original size value
+ ReDim bytaryOri(lngOriSiz - 1)
+ If lngfncUcp(bytaryOri(0), lngOriSiz, bytaryCpr(0), lngCprSiz) = SUCCESS
+Then
+ strOriPth = Left(strargFilPth, Len(strargFilPth) - Len(strFilExt))
+ Open strOriPth For Binary Access Write As #1
+ Put #1, , bytaryOri()
+ Close #1
+ Else
+ MsgBox "Uncompression error"
+ End If
+ Erase bytaryCpr
+ Erase bytaryOri
+End Sub
+Public Property Get lngPercentSmaller() As Long
+ lngPercentSmaller = lngpvtPcnSml
+End Property
diff --git a/libmariadb/external/zlib/qnx/package.qpg b/libmariadb/external/zlib/qnx/package.qpg
new file mode 100644
index 00000000..aebf6e3a
--- /dev/null
+++ b/libmariadb/external/zlib/qnx/package.qpg
@@ -0,0 +1,141 @@
+<QPG:Generation>
+ <QPG:Options>
+ <QPG:User unattended="no" verbosity="2" listfiles="yes"/>
+ <QPG:Defaults type="qnx_package"/>
+ <QPG:Source></QPG:Source>
+ <QPG:Release number="+"/>
+ <QPG:Build></QPG:Build>
+ <QPG:FileSorting strip="yes"/>
+ <QPG:Package targets="combine"/>
+ <QPG:Repository generate="yes"/>
+ <QPG:FinalDir></QPG:FinalDir>
+ <QPG:Cleanup></QPG:Cleanup>
+ </QPG:Options>
+
+ <QPG:Responsible>
+ <QPG:Company></QPG:Company>
+ <QPG:Department></QPG:Department>
+ <QPG:Group></QPG:Group>
+ <QPG:Team></QPG:Team>
+ <QPG:Employee></QPG:Employee>
+ <QPG:EmailAddress></QPG:EmailAddress>
+ </QPG:Responsible>
+
+ <QPG:Values>
+ <QPG:Files>
+ <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
+ <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
+ <QPG:Add file="../libz.so.1.2.8" install="/opt/lib/" user="root:bin" permission="644"/>
+ <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.8"/>
+ <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.8"/>
+ <QPG:Add file="../libz.so.1.2.8" install="/opt/lib/" component="slib"/>
+ </QPG:Files>
+
+ <QPG:PackageFilter>
+ <QPM:PackageManifest>
+ <QPM:PackageDescription>
+ <QPM:PackageType>Library</QPM:PackageType>
+ <QPM:PackageReleaseNotes></QPM:PackageReleaseNotes>
+ <QPM:PackageReleaseUrgency>Medium</QPM:PackageReleaseUrgency>
+ <QPM:PackageRepository></QPM:PackageRepository>
+ <QPM:FileVersion>2.0</QPM:FileVersion>
+ </QPM:PackageDescription>
+
+ <QPM:ProductDescription>
+ <QPM:ProductName>zlib</QPM:ProductName>
+ <QPM:ProductIdentifier>zlib</QPM:ProductIdentifier>
+ <QPM:ProductEmail>alain.bonnefoy@icbt.com</QPM:ProductEmail>
+ <QPM:VendorName>Public</QPM:VendorName>
+ <QPM:VendorInstallName>public</QPM:VendorInstallName>
+ <QPM:VendorURL>www.gzip.org/zlib</QPM:VendorURL>
+ <QPM:VendorEmbedURL></QPM:VendorEmbedURL>
+ <QPM:VendorEmail></QPM:VendorEmail>
+ <QPM:AuthorName>Jean-Loup Gailly,Mark Adler</QPM:AuthorName>
+ <QPM:AuthorURL>www.gzip.org/zlib</QPM:AuthorURL>
+ <QPM:AuthorEmbedURL></QPM:AuthorEmbedURL>
+ <QPM:AuthorEmail>zlib@gzip.org</QPM:AuthorEmail>
+ <QPM:ProductIconSmall></QPM:ProductIconSmall>
+ <QPM:ProductIconLarge></QPM:ProductIconLarge>
+ <QPM:ProductDescriptionShort>A massively spiffy yet delicately unobtrusive compression library.</QPM:ProductDescriptionShort>
+ <QPM:ProductDescriptionLong>zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system.</QPM:ProductDescriptionLong>
+ <QPM:ProductDescriptionURL>http://www.gzip.org/zlib</QPM:ProductDescriptionURL>
+ <QPM:ProductDescriptionEmbedURL></QPM:ProductDescriptionEmbedURL>
+ </QPM:ProductDescription>
+
+ <QPM:ReleaseDescription>
+ <QPM:ReleaseVersion>1.2.8</QPM:ReleaseVersion>
+ <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
+ <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
+ <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
+ <QPM:ReleaseNoteMajor></QPM:ReleaseNoteMajor>
+ <QPM:ExcludeCountries>
+ <QPM:Country></QPM:Country>
+ </QPM:ExcludeCountries>
+
+ <QPM:ReleaseCopyright>No License</QPM:ReleaseCopyright>
+ </QPM:ReleaseDescription>
+
+ <QPM:ContentDescription>
+ <QPM:ContentTopic xmlmultiple="true">Software Development/Libraries and Extensions/C Libraries</QPM:ContentTopic>
+ <QPM:ContentKeyword>zlib,compression</QPM:ContentKeyword>
+ <QPM:TargetOS>qnx6</QPM:TargetOS>
+ <QPM:HostOS>qnx6</QPM:HostOS>
+ <QPM:DisplayEnvironment xmlmultiple="true">None</QPM:DisplayEnvironment>
+ <QPM:TargetAudience xmlmultiple="true">Developer</QPM:TargetAudience>
+ </QPM:ContentDescription>
+ </QPM:PackageManifest>
+ </QPG:PackageFilter>
+
+ <QPG:PackageFilter proc="none" target="none">
+ <QPM:PackageManifest>
+ <QPM:ProductInstallationDependencies>
+ <QPM:ProductRequirements></QPM:ProductRequirements>
+ </QPM:ProductInstallationDependencies>
+
+ <QPM:ProductInstallationProcedure>
+ <QPM:Script xmlmultiple="true">
+ <QPM:ScriptName></QPM:ScriptName>
+ <QPM:ScriptType>Install</QPM:ScriptType>
+ <QPM:ScriptTiming>Post</QPM:ScriptTiming>
+ <QPM:ScriptBlocking>No</QPM:ScriptBlocking>
+ <QPM:ScriptResult>Ignore</QPM:ScriptResult>
+ <QPM:ShortDescription></QPM:ShortDescription>
+ <QPM:UseBinaries>No</QPM:UseBinaries>
+ <QPM:Priority>Optional</QPM:Priority>
+ </QPM:Script>
+ </QPM:ProductInstallationProcedure>
+ </QPM:PackageManifest>
+
+ <QPM:Launch>
+ </QPM:Launch>
+ </QPG:PackageFilter>
+
+ <QPG:PackageFilter type="core" component="none">
+ <QPM:PackageManifest>
+ <QPM:ProductInstallationProcedure>
+ <QPM:OrderDependency xmlmultiple="true">
+ <QPM:Order>InstallOver</QPM:Order>
+ <QPM:Product>zlib</QPM:Product>
+ </QPM:OrderDependency>
+ </QPM:ProductInstallationProcedure>
+ </QPM:PackageManifest>
+
+ <QPM:Launch>
+ </QPM:Launch>
+ </QPG:PackageFilter>
+
+ <QPG:PackageFilter type="core" component="dev">
+ <QPM:PackageManifest>
+ <QPM:ProductInstallationProcedure>
+ <QPM:OrderDependency xmlmultiple="true">
+ <QPM:Order>InstallOver</QPM:Order>
+ <QPM:Product>zlib-dev</QPM:Product>
+ </QPM:OrderDependency>
+ </QPM:ProductInstallationProcedure>
+ </QPM:PackageManifest>
+
+ <QPM:Launch>
+ </QPM:Launch>
+ </QPG:PackageFilter>
+ </QPG:Values>
+</QPG:Generation>
diff --git a/libmariadb/external/zlib/treebuild.xml b/libmariadb/external/zlib/treebuild.xml
new file mode 100644
index 00000000..0017a45d
--- /dev/null
+++ b/libmariadb/external/zlib/treebuild.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" ?>
+<package name="zlib" version="1.2.13">
+ <library name="zlib" dlversion="1.2.13" dlname="z">
+ <property name="description"> zip compression library </property>
+ <property name="include-target-dir" value="$(@PACKAGE/install-includedir)" />
+
+ <!-- fixme: not implemented yet -->
+ <property name="compiler/c/inline" value="yes" />
+
+ <include-file name="zlib.h" scope="public" mode="644" />
+ <include-file name="zconf.h" scope="public" mode="644" />
+
+ <source name="adler32.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ </source>
+ <source name="compress.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ </source>
+ <source name="crc32.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="crc32.h" />
+ </source>
+ <source name="gzclose.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="gzguts.h" />
+ </source>
+ <source name="gzlib.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="gzguts.h" />
+ </source>
+ <source name="gzread.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="gzguts.h" />
+ </source>
+ <source name="gzwrite.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="gzguts.h" />
+ </source>
+ <source name="uncompr.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ </source>
+ <source name="deflate.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="zutil.h" />
+ <depend name="deflate.h" />
+ </source>
+ <source name="trees.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="zutil.h" />
+ <depend name="deflate.h" />
+ <depend name="trees.h" />
+ </source>
+ <source name="zutil.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="zutil.h" />
+ </source>
+ <source name="inflate.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="zutil.h" />
+ <depend name="inftrees.h" />
+ <depend name="inflate.h" />
+ <depend name="inffast.h" />
+ </source>
+ <source name="infback.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="zutil.h" />
+ <depend name="inftrees.h" />
+ <depend name="inflate.h" />
+ <depend name="inffast.h" />
+ </source>
+ <source name="inftrees.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="zutil.h" />
+ <depend name="inftrees.h" />
+ </source>
+ <source name="inffast.c">
+ <depend name="zlib.h" />
+ <depend name="zconf.h" />
+ <depend name="zutil.h" />
+ <depend name="inftrees.h" />
+ <depend name="inflate.h" />
+ <depend name="inffast.h" />
+ </source>
+ </library>
+</package>
+
+<!--
+CFLAGS=-O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DZLIB_DEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+# OBJA =
+# to use the asm code: make OBJA=match.o
+#
+match.o: match.S
+ $(CPP) match.S > _match.s
+ $(CC) -c _match.s
+ mv _match.o match.o
+ rm -f _match.s
+-->
diff --git a/libmariadb/external/zlib/trees.c b/libmariadb/external/zlib/trees.c
new file mode 100644
index 00000000..5f305c47
--- /dev/null
+++ b/libmariadb/external/zlib/trees.c
@@ -0,0 +1,1181 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2021 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef ZLIB_DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local const static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local const static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local const static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, const ct_data *ltree,
+ const ct_data *dtree));
+local int detect_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned code, int len));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef ZLIB_DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* !ZLIB_DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef ZLIB_DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !ZLIB_DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = (int)value;\
+ s->bi_buf |= (ush)val << s->bi_valid;\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (ush)(value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* ZLIB_DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1 << extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length - 1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1 << extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256 + dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Generate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef ZLIB_DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width) - 1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header,
+ "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->sym_next = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n - base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (unsigned)(bits + xbits);
+ if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Tracev((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length - 1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes(tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ unsigned code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ code = (code + bl_count[bits - 1]) << 1;
+ next_code[bits] = (ush)code;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree(s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code + 1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n + 1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree(s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code + 1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n + 1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except the
+ * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes - 1, 5);
+ send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int last; /* one if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */
+ bi_windup(s); /* align on byte boundary */
+ put_short(s, (ush)stored_len);
+ put_short(s, (ush)~stored_len);
+ if (stored_len)
+ zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
+ s->pending += stored_len;
+#ifdef ZLIB_DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+ s->bits_sent += 2*16;
+ s->bits_sent += stored_len << 3;
+#endif
+}
+
+/* ===========================================================================
+ * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
+ */
+void ZLIB_INTERNAL _tr_flush_bits(s)
+ deflate_state *s;
+{
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ */
+void ZLIB_INTERNAL _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and write out the encoded block.
+ */
+void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int last; /* one if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (s->strm->data_type == Z_UNKNOWN)
+ s->strm->data_type = detect_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len + 3 + 7) >> 3;
+ static_lenb = (s->static_len + 3 + 7) >> 3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->sym_next / 3));
+
+#ifndef FORCE_STATIC
+ if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)
+#endif
+ opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len + 4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, last);
+
+ } else if (static_lenb == opt_lenb) {
+ send_bits(s, (STATIC_TREES<<1) + last, 3);
+ compress_block(s, (const ct_data *)static_ltree,
+ (const ct_data *)static_dtree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1) + last, 3);
+ send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,
+ max_blindex + 1);
+ compress_block(s, (const ct_data *)s->dyn_ltree,
+ (const ct_data *)s->dyn_dtree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (last) {
+ bi_windup(s);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3,
+ s->compressed_len - 7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally(s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */
+{
+ s->sym_buf[s->sym_next++] = (uch)dist;
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
+ s->sym_buf[s->sym_next++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+ return (s->sym_next == s->sym_end);
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ const ct_data *ltree; /* literal tree */
+ const ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned sx = 0; /* running index in sym_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->sym_next != 0) do {
+ dist = s->sym_buf[sx++] & 0xff;
+ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
+ lc = s->sym_buf[sx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code + LITERALS + 1, ltree); /* send length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= (unsigned)base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and sym_buf is ok: */
+ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
+
+ } while (sx < s->sym_next);
+
+ send_code(s, END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ * a) There are no non-portable control characters belonging to the
+ * "block list" (0..6, 14..25, 28..31).
+ * b) There is at least one printable character belonging to the
+ * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(s)
+ deflate_state *s;
+{
+ /* block_mask is the bit mask of block-listed bytes
+ * set bits 0..6, 14..25, and 28..31
+ * 0xf3ffc07f = binary 11110011111111111100000001111111
+ */
+ unsigned long block_mask = 0xf3ffc07fUL;
+ int n;
+
+ /* Check for non-textual ("block-listed") bytes. */
+ for (n = 0; n <= 31; n++, block_mask >>= 1)
+ if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ return Z_BINARY;
+
+ /* Check for textual ("allow-listed") bytes. */
+ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+ || s->dyn_ltree[13].Freq != 0)
+ return Z_TEXT;
+ for (n = 32; n < LITERALS; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ return Z_TEXT;
+
+ /* There are no "block-listed" or "allow-listed" bytes:
+ * this stream either is empty or has tolerated ("gray-listed") bytes only.
+ */
+ return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+ s->bits_sent = (s->bits_sent + 7) & ~7;
+#endif
+}
diff --git a/libmariadb/external/zlib/trees.h b/libmariadb/external/zlib/trees.h
new file mode 100644
index 00000000..d35639d8
--- /dev/null
+++ b/libmariadb/external/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/libmariadb/external/zlib/ucm.cmake b/libmariadb/external/zlib/ucm.cmake
new file mode 100644
index 00000000..7eb2efb1
--- /dev/null
+++ b/libmariadb/external/zlib/ucm.cmake
@@ -0,0 +1,636 @@
+#
+# ucm.cmake - useful cmake macros
+#
+# Copyright (c) 2016 Viktor Kirilov
+#
+# Distributed under the MIT Software License
+# See accompanying file LICENSE.txt or copy at
+# https://opensource.org/licenses/MIT
+#
+# The documentation can be found at the library's page:
+# https://github.com/onqtam/ucm
+
+cmake_minimum_required(VERSION 2.8.12)
+
+include(CMakeParseArguments)
+
+# optionally include cotire - the git submodule might not be inited (or the user might have already included it)
+if(NOT COMMAND cotire)
+ include(${CMAKE_CURRENT_LIST_DIR}/../cotire/CMake/cotire.cmake OPTIONAL)
+endif()
+
+if(COMMAND cotire AND "1.7.9" VERSION_LESS "${COTIRE_CMAKE_MODULE_VERSION}")
+ set(ucm_with_cotire 1)
+else()
+ set(ucm_with_cotire 0)
+endif()
+
+# option(UCM_UNITY_BUILD "Enable unity build for targets registered with the ucm_add_target() macro" OFF)
+# option(UCM_NO_COTIRE_FOLDER "Do not use a cotire folder in the solution explorer for all unity and cotire related targets" ON)
+
+# ucm_add_flags
+# Adds compiler flags to CMAKE_<LANG>_FLAGS or to a specific config
+macro(ucm_add_flags)
+ cmake_parse_arguments(ARG "C;CXX;CLEAR_OLD" "" "CONFIG" ${ARGN})
+
+ if(NOT ARG_CONFIG)
+ set(ARG_CONFIG " ")
+ endif()
+
+ foreach(CONFIG ${ARG_CONFIG})
+ # determine to which flags to add
+ if(NOT ${CONFIG} STREQUAL " ")
+ string(TOUPPER ${CONFIG} CONFIG)
+ set(CXX_FLAGS CMAKE_CXX_FLAGS_${CONFIG})
+ set(C_FLAGS CMAKE_C_FLAGS_${CONFIG})
+ else()
+ set(CXX_FLAGS CMAKE_CXX_FLAGS)
+ set(C_FLAGS CMAKE_C_FLAGS)
+ endif()
+
+ # clear the old flags
+ if(${ARG_CLEAR_OLD})
+ if("${ARG_CXX}" OR NOT "${ARG_C}")
+ set(${CXX_FLAGS} "")
+ endif()
+ if("${ARG_C}" OR NOT "${ARG_CXX}")
+ set(${C_FLAGS} "")
+ endif()
+ endif()
+
+ # add all the passed flags
+ foreach(flag ${ARG_UNPARSED_ARGUMENTS})
+ if("${ARG_CXX}" OR NOT "${ARG_C}")
+ set(${CXX_FLAGS} "${${CXX_FLAGS}} ${flag}")
+ endif()
+ if("${ARG_C}" OR NOT "${ARG_CXX}")
+ set(${C_FLAGS} "${${C_FLAGS}} ${flag}")
+ endif()
+ endforeach()
+ endforeach()
+
+endmacro()
+
+# ucm_set_flags
+# Sets the CMAKE_<LANG>_FLAGS compiler flags or for a specific config
+macro(ucm_set_flags)
+ ucm_add_flags(CLEAR_OLD ${ARGN})
+endmacro()
+
+# ucm_add_linker_flags
+# Adds linker flags to CMAKE_<TYPE>_LINKER_FLAGS or to a specific config
+macro(ucm_add_linker_flags)
+ cmake_parse_arguments(ARG "CLEAR_OLD;EXE;MODULE;SHARED;STATIC" "" "CONFIG" ${ARGN})
+
+ if(NOT ARG_CONFIG)
+ set(ARG_CONFIG " ")
+ endif()
+
+ foreach(CONFIG ${ARG_CONFIG})
+ string(TOUPPER "${CONFIG}" CONFIG)
+
+ if(NOT ${ARG_EXE} AND NOT ${ARG_MODULE} AND NOT ${ARG_SHARED} AND NOT ${ARG_STATIC})
+ set(ARG_EXE 1)
+ set(ARG_MODULE 1)
+ set(ARG_SHARED 1)
+ set(ARG_STATIC 1)
+ endif()
+
+ set(flags_configs "")
+ if(${ARG_EXE})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_EXE_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_EXE_LINKER_FLAGS)
+ endif()
+ endif()
+ if(${ARG_MODULE})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_MODULE_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_MODULE_LINKER_FLAGS)
+ endif()
+ endif()
+ if(${ARG_SHARED})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_SHARED_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_SHARED_LINKER_FLAGS)
+ endif()
+ endif()
+ if(${ARG_STATIC})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_STATIC_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_STATIC_LINKER_FLAGS)
+ endif()
+ endif()
+
+ # clear the old flags
+ if(${ARG_CLEAR_OLD})
+ foreach(flags ${flags_configs})
+ set(${flags} "")
+ endforeach()
+ endif()
+
+ # add all the passed flags
+ foreach(flag ${ARG_UNPARSED_ARGUMENTS})
+ foreach(flags ${flags_configs})
+ set(${flags} "${${flags}} ${flag}")
+ endforeach()
+ endforeach()
+ endforeach()
+endmacro()
+
+# ucm_set_linker_flags
+# Sets the CMAKE_<TYPE>_LINKER_FLAGS linker flags or for a specific config
+macro(ucm_set_linker_flags)
+ ucm_add_linker_flags(CLEAR_OLD ${ARGN})
+endmacro()
+
+# ucm_gather_flags
+# Gathers all lists of flags for printing or manipulation
+macro(ucm_gather_flags with_linker result)
+ set(${result} "")
+ # add the main flags without a config
+ list(APPEND ${result} CMAKE_C_FLAGS)
+ list(APPEND ${result} CMAKE_CXX_FLAGS)
+ if(${with_linker})
+ list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS)
+ list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS)
+ list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS)
+ list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS)
+ endif()
+
+ if("${CMAKE_CONFIGURATION_TYPES}" STREQUAL "" AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "")
+ # handle single config generators - like makefiles/ninja - when CMAKE_BUILD_TYPE is set
+ string(TOUPPER ${CMAKE_BUILD_TYPE} config)
+ list(APPEND ${result} CMAKE_C_FLAGS_${config})
+ list(APPEND ${result} CMAKE_CXX_FLAGS_${config})
+ if(${with_linker})
+ list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS_${config})
+ endif()
+ else()
+ # handle multi config generators (like msvc, xcode)
+ foreach(config ${CMAKE_CONFIGURATION_TYPES})
+ string(TOUPPER ${config} config)
+ list(APPEND ${result} CMAKE_C_FLAGS_${config})
+ list(APPEND ${result} CMAKE_CXX_FLAGS_${config})
+ if(${with_linker})
+ list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS_${config})
+ endif()
+ endforeach()
+ endif()
+endmacro()
+
+# ucm_set_runtime
+# Sets the runtime (static/dynamic) for msvc/gcc
+macro(ucm_set_runtime)
+ cmake_parse_arguments(ARG "STATIC;DYNAMIC" "" "" ${ARGN})
+
+ if(ARG_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" STREQUAL "")
+ message(AUTHOR_WARNING "ucm_set_runtime() does not support clang yet!")
+ endif()
+
+ ucm_gather_flags(0 flags_configs)
+
+ # add/replace the flags
+ # note that if the user has messed with the flags directly this function might fail
+ # - for example if with MSVC and the user has removed the flags - here we just switch/replace them
+ if("${ARG_STATIC}")
+ foreach(flags ${flags_configs})
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "GNU")
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.4.7) # option "-static-libstdc++" available since GCC 4.5
+ if(NOT ${flags} MATCHES "-static-libstdc\\+\\+")
+ set(${flags} "${${flags}} -static-libstdc++")
+ endif()
+ endif()
+ if(NOT ${flags} MATCHES "-static-libgcc")
+ set(${flags} "${${flags}} -static-libgcc")
+ endif()
+ elseif(MSVC)
+ if(${flags} MATCHES "/MD")
+ string(REGEX REPLACE "/MD" "/MT" ${flags} "${${flags}}")
+ endif()
+ endif()
+ endforeach()
+ elseif("${ARG_DYNAMIC}")
+ foreach(flags ${flags_configs})
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "GNU")
+ if(${flags} MATCHES "-static-libstdc\\+\\+")
+ string(REGEX REPLACE "-static-libstdc\\+\\+" "" ${flags} "${${flags}}")
+ endif()
+ if(${flags} MATCHES "-static-libgcc")
+ string(REGEX REPLACE "-static-libgcc" "" ${flags} "${${flags}}")
+ endif()
+ elseif(MSVC)
+ if(${flags} MATCHES "/MT")
+ string(REGEX REPLACE "/MT" "/MD" ${flags} "${${flags}}")
+ endif()
+ endif()
+ endforeach()
+ endif()
+endmacro()
+
+# ucm_print_flags
+# Prints all compiler flags for all configurations
+macro(ucm_print_flags)
+ ucm_gather_flags(1 flags_configs)
+ message("")
+ foreach(flags ${flags_configs})
+ message("${flags}: ${${flags}}")
+ endforeach()
+ message("")
+endmacro()
+
+# ucm_count_sources
+# Counts the number of source files
+macro(ucm_count_sources)
+ cmake_parse_arguments(ARG "" "RESULT" "" ${ARGN})
+ if(${ARG_RESULT} STREQUAL "")
+ message(FATAL_ERROR "Need to pass RESULT and a variable name to ucm_count_sources()")
+ endif()
+
+ set(result 0)
+ foreach(SOURCE_FILE ${ARG_UNPARSED_ARGUMENTS})
+ if("${SOURCE_FILE}" MATCHES \\.\(c|C|cc|cp|cpp|CPP|c\\+\\+|cxx|i|ii\)$)
+ math(EXPR result "${result} + 1")
+ endif()
+ endforeach()
+ set(${ARG_RESULT} ${result})
+endmacro()
+
+# ucm_include_file_in_sources
+# Includes the file to the source with compiler flags
+macro(ucm_include_file_in_sources)
+ cmake_parse_arguments(ARG "" "HEADER" "" ${ARGN})
+ if(${ARG_HEADER} STREQUAL "")
+ message(FATAL_ERROR "Need to pass HEADER and a header file to ucm_include_file_in_sources()")
+ endif()
+
+ foreach(src ${ARG_UNPARSED_ARGUMENTS})
+ if(${src} MATCHES \\.\(c|C|cc|cp|cpp|CPP|c\\+\\+|cxx\)$)
+ # get old flags
+ get_source_file_property(old_compile_flags ${src} COMPILE_FLAGS)
+ if(old_compile_flags STREQUAL "NOTFOUND")
+ set(old_compile_flags "")
+ endif()
+
+ # update flags
+ if(MSVC)
+ set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
+ "${old_compile_flags} /FI\"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_HEADER}\"")
+ else()
+ set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
+ "${old_compile_flags} -include \"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_HEADER}\"")
+ endif()
+ endif()
+ endforeach()
+endmacro()
+
+# ucm_dir_list
+# Returns a list of subdirectories for a given directory
+macro(ucm_dir_list thedir result)
+ file(GLOB sub-dir "${thedir}/*")
+ set(list_of_dirs "")
+ foreach(dir ${sub-dir})
+ if(IS_DIRECTORY ${dir})
+ get_filename_component(DIRNAME ${dir} NAME)
+ LIST(APPEND list_of_dirs ${DIRNAME})
+ endif()
+ endforeach()
+ set(${result} ${list_of_dirs})
+endmacro()
+
+# ucm_trim_front_words
+# Trims X times the front word from a string separated with "/" and removes
+# the front "/" characters after that (used for filters for visual studio)
+macro(ucm_trim_front_words source out num_filter_trims)
+ set(result "${source}")
+ set(counter 0)
+ while(${counter} LESS ${num_filter_trims})
+ MATH(EXPR counter "${counter} + 1")
+ # removes everything at the front up to a "/" character
+ string(REGEX REPLACE "^([^/]+)" "" result "${result}")
+ # removes all consecutive "/" characters from the front
+ string(REGEX REPLACE "^(/+)" "" result "${result}")
+ endwhile()
+ set(${out} ${result})
+endmacro()
+
+# ucm_remove_files
+# Removes source files from a list of sources (path is the relative path for it to be found)
+macro(ucm_remove_files)
+ cmake_parse_arguments(ARG "" "FROM" "" ${ARGN})
+
+ if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass some relative files to ucm_remove_files()")
+ endif()
+ if(${ARG_FROM} STREQUAL "")
+ message(FATAL_ERROR "Need to pass FROM and a variable name to ucm_remove_files()")
+ endif()
+
+ foreach(cur_file ${ARG_UNPARSED_ARGUMENTS})
+ list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
+ endforeach()
+endmacro()
+
+# ucm_remove_directories
+# Removes all source files from the given directories from the sources list
+macro(ucm_remove_directories)
+ cmake_parse_arguments(ARG "" "FROM" "MATCHES" ${ARGN})
+
+ if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass some relative directories to ucm_remove_directories()")
+ endif()
+ if(${ARG_FROM} STREQUAL "")
+ message(FATAL_ERROR "Need to pass FROM and a variable name to ucm_remove_directories()")
+ endif()
+
+ foreach(cur_dir ${ARG_UNPARSED_ARGUMENTS})
+ foreach(cur_file ${${ARG_FROM}})
+ string(REGEX MATCH ${cur_dir} res ${cur_file})
+ if(NOT "${res}" STREQUAL "")
+ if("${ARG_MATCHES}" STREQUAL "")
+ list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
+ else()
+ foreach(curr_ptrn ${ARG_MATCHES})
+ string(REGEX MATCH ${curr_ptrn} res ${cur_file})
+ if(NOT "${res}" STREQUAL "")
+ list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
+ break()
+ endif()
+ endforeach()
+ endif()
+ endif()
+ endforeach()
+ endforeach()
+endmacro()
+
+# ucm_add_files_impl
+macro(ucm_add_files_impl result trim files)
+ foreach(cur_file ${files})
+ SET(${result} ${${result}} ${cur_file})
+ get_filename_component(FILEPATH ${cur_file} PATH)
+ ucm_trim_front_words("${FILEPATH}" FILEPATH "${trim}")
+ # replacing forward slashes with back slashes so filters can be generated (back slash used in parsing...)
+ STRING(REPLACE "/" "\\" FILTERS "${FILEPATH}")
+ SOURCE_GROUP("${FILTERS}" FILES ${cur_file})
+ endforeach()
+endmacro()
+
+# ucm_add_files
+# Adds files to a list of sources
+macro(ucm_add_files)
+ cmake_parse_arguments(ARG "" "TO;FILTER_POP" "" ${ARGN})
+
+ if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass some relative files to ucm_add_files()")
+ endif()
+ if(${ARG_TO} STREQUAL "")
+ message(FATAL_ERROR "Need to pass TO and a variable name to ucm_add_files()")
+ endif()
+
+ if("${ARG_FILTER_POP}" STREQUAL "")
+ set(ARG_FILTER_POP 0)
+ endif()
+
+ ucm_add_files_impl(${ARG_TO} ${ARG_FILTER_POP} "${ARG_UNPARSED_ARGUMENTS}")
+endmacro()
+
+# ucm_add_dir_impl
+macro(ucm_add_dir_impl result rec trim dirs_in additional_ext)
+ set(dirs "${dirs_in}")
+
+ # handle the "" and "." cases
+ if("${dirs}" STREQUAL "" OR "${dirs}" STREQUAL ".")
+ set(dirs "./")
+ endif()
+
+ foreach(cur_dir ${dirs})
+ # to circumvent some linux/cmake/path issues - barely made it work...
+ if(cur_dir STREQUAL "./")
+ set(cur_dir "")
+ else()
+ set(cur_dir "${cur_dir}/")
+ endif()
+
+ # since unix is case sensitive - add these valid extensions too
+ # we don't use "UNIX" but instead "CMAKE_HOST_UNIX" because we might be cross
+ # compiling (for example emscripten) under windows and UNIX may be set to 1
+ # Also OSX is case insensitive like windows...
+ set(additional_file_extensions "")
+ if(CMAKE_HOST_UNIX AND NOT APPLE)
+ set(additional_file_extensions
+ "${cur_dir}*.CPP"
+ "${cur_dir}*.C"
+ "${cur_dir}*.H"
+ "${cur_dir}*.HPP"
+ )
+ endif()
+
+ foreach(ext ${additional_ext})
+ list(APPEND additional_file_extensions "${cur_dir}*.${ext}")
+ endforeach()
+
+ # find all sources and set them as result
+ FILE(GLOB found_sources RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
+ # https://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Overall-Options.html#index-file-name-suffix-71
+ # sources
+ "${cur_dir}*.cpp"
+ "${cur_dir}*.cxx"
+ "${cur_dir}*.c++"
+ "${cur_dir}*.cc"
+ "${cur_dir}*.cp"
+ "${cur_dir}*.c"
+ "${cur_dir}*.i"
+ "${cur_dir}*.ii"
+ # headers
+ "${cur_dir}*.h"
+ "${cur_dir}*.h++"
+ "${cur_dir}*.hpp"
+ "${cur_dir}*.hxx"
+ "${cur_dir}*.hh"
+ "${cur_dir}*.inl"
+ "${cur_dir}*.inc"
+ "${cur_dir}*.ipp"
+ "${cur_dir}*.ixx"
+ "${cur_dir}*.txx"
+ "${cur_dir}*.tpp"
+ "${cur_dir}*.tcc"
+ "${cur_dir}*.tpl"
+ ${additional_file_extensions})
+ SET(${result} ${${result}} ${found_sources})
+
+ # set the proper filters
+ ucm_trim_front_words("${cur_dir}" cur_dir "${trim}")
+ # replacing forward slashes with back slashes so filters can be generated (back slash used in parsing...)
+ STRING(REPLACE "/" "\\" FILTERS "${cur_dir}")
+ SOURCE_GROUP("${FILTERS}" FILES ${found_sources})
+ endforeach()
+
+ if(${rec})
+ foreach(cur_dir ${dirs})
+ ucm_dir_list("${cur_dir}" subdirs)
+ foreach(subdir ${subdirs})
+ ucm_add_dir_impl(${result} ${rec} ${trim} "${cur_dir}/${subdir}" "${additional_ext}")
+ endforeach()
+ endforeach()
+ endif()
+endmacro()
+
+# ucm_add_dirs
+# Adds all files from directories traversing them recursively to a list of sources
+# and generates filters according to their location (accepts relative paths only).
+# Also this macro trims X times the front word from the filter string for visual studio filters.
+macro(ucm_add_dirs)
+ cmake_parse_arguments(ARG "RECURSIVE" "TO;FILTER_POP" "ADDITIONAL_EXT" ${ARGN})
+
+ if(${ARG_TO} STREQUAL "")
+ message(FATAL_ERROR "Need to pass TO and a variable name to ucm_add_dirs()")
+ endif()
+
+ if("${ARG_FILTER_POP}" STREQUAL "")
+ set(ARG_FILTER_POP 0)
+ endif()
+
+ ucm_add_dir_impl(${ARG_TO} ${ARG_RECURSIVE} ${ARG_FILTER_POP} "${ARG_UNPARSED_ARGUMENTS}" "${ARG_ADDITIONAL_EXT}")
+endmacro()
+
+# ucm_add_target
+# Adds a target eligible for cotiring - unity build and/or precompiled header
+macro(ucm_add_target)
+ cmake_parse_arguments(ARG "UNITY" "NAME;TYPE;PCH_FILE;CPP_PER_UNITY" "UNITY_EXCLUDED;SOURCES" ${ARGN})
+
+ if(NOT "${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Unrecognized options passed to ucm_add_target()")
+ endif()
+ if("${ARG_NAME}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass NAME and a name for the target to ucm_add_target()")
+ endif()
+ set(valid_types EXECUTABLE STATIC SHARED MODULE)
+ list(FIND valid_types "${ARG_TYPE}" is_type_valid)
+ if(${is_type_valid} STREQUAL "-1")
+ message(FATAL_ERROR "Need to pass TYPE and the type for the target [EXECUTABLE/STATIC/SHARED/MODULE] to ucm_add_target()")
+ endif()
+ if("${ARG_SOURCES}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass SOURCES and a list of source files to ucm_add_target()")
+ endif()
+
+ # init with the global unity flag
+ set(do_unity ${UCM_UNITY_BUILD})
+
+ # check the UNITY argument
+ if(NOT ARG_UNITY)
+ set(do_unity FALSE)
+ endif()
+
+ # if target is excluded through the exclusion list
+ list(FIND UCM_UNITY_BUILD_EXCLUDE_TARGETS ${ARG_NAME} is_target_excluded)
+ if(NOT ${is_target_excluded} STREQUAL "-1")
+ set(do_unity FALSE)
+ endif()
+
+ # unity build only for targets with > 1 source file (otherwise there will be an additional unnecessary target)
+ if(do_unity) # optimization
+ ucm_count_sources(${ARG_SOURCES} RESULT num_sources)
+ if(${num_sources} LESS 2)
+ set(do_unity FALSE)
+ endif()
+ endif()
+
+ set(wanted_cotire ${do_unity})
+
+ # if cotire cannot be used
+ if(do_unity AND NOT ucm_with_cotire)
+ set(do_unity FALSE)
+ endif()
+
+ # inform the developer that the current target might benefit from a unity build
+ if(NOT ARG_UNITY AND ${UCM_UNITY_BUILD})
+ ucm_count_sources(${ARG_SOURCES} RESULT num_sources)
+ if(${num_sources} GREATER 1)
+ message(AUTHOR_WARNING "Target '${ARG_NAME}' may benefit from a unity build.\nIt has ${num_sources} sources - enable with UNITY flag")
+ endif()
+ endif()
+
+ # prepare for the unity build
+ set(orig_target ${ARG_NAME})
+ if(do_unity)
+ # the original target will be added with a different name than the requested
+ set(orig_target ${ARG_NAME}_ORIGINAL)
+
+ # exclude requested files from unity build of the current target
+ foreach(excluded_file "${ARG_UNITY_EXCLUDED}")
+ set_source_files_properties(${excluded_file} PROPERTIES COTIRE_EXCLUDED TRUE)
+ endforeach()
+ endif()
+
+ # add the original target
+ if(${ARG_TYPE} STREQUAL "EXECUTABLE")
+ add_executable(${orig_target} ${ARG_SOURCES})
+ else()
+ add_library(${orig_target} ${ARG_TYPE} ${ARG_SOURCES})
+ endif()
+
+ if(do_unity)
+ # set the number of unity cpp files to be used for the unity target
+ if(NOT "${ARG_CPP_PER_UNITY}" STREQUAL "")
+ set_property(TARGET ${orig_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${ARG_CPP_PER_UNITY}")
+ else()
+ set_property(TARGET ${orig_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "100")
+ endif()
+
+ if(NOT "${ARG_PCH_FILE}" STREQUAL "")
+ set_target_properties(${orig_target} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${ARG_PCH_FILE}")
+ else()
+ set_target_properties(${orig_target} PROPERTIES COTIRE_ENABLE_PRECOMPILED_HEADER FALSE)
+ endif()
+ # add a unity target for the original one with the name intended for the original
+ set_target_properties(${orig_target} PROPERTIES COTIRE_UNITY_TARGET_NAME ${ARG_NAME})
+
+ # this is the library call that does the magic
+ cotire(${orig_target})
+ set_target_properties(clean_cotire PROPERTIES FOLDER "CMakePredefinedTargets")
+
+ # disable the original target and enable the unity one
+ get_target_property(unity_target_name ${orig_target} COTIRE_UNITY_TARGET_NAME)
+ set_target_properties(${orig_target} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
+ set_target_properties(${unity_target_name} PROPERTIES EXCLUDE_FROM_ALL 0 EXCLUDE_FROM_DEFAULT_BUILD 0)
+
+ # also set the name of the target output as the original one
+ set_target_properties(${unity_target_name} PROPERTIES OUTPUT_NAME ${ARG_NAME})
+ if(UCM_NO_COTIRE_FOLDER)
+ # reset the folder property so all unity targets dont end up in a single folder in the solution explorer of VS
+ set_target_properties(${unity_target_name} PROPERTIES FOLDER "")
+ endif()
+ set_target_properties(all_unity PROPERTIES FOLDER "CMakePredefinedTargets")
+ elseif(NOT "${ARG_PCH_FILE}" STREQUAL "")
+ set(wanted_cotire TRUE)
+ if(ucm_with_cotire)
+ set_target_properties(${orig_target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
+ set_target_properties(${orig_target} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${ARG_PCH_FILE}")
+ cotire(${orig_target})
+ set_target_properties(clean_cotire PROPERTIES FOLDER "CMakePredefinedTargets")
+ endif()
+ endif()
+
+ # print a message if the target was requested to be cotired but it couldn't
+ if(wanted_cotire AND NOT ucm_with_cotire)
+ if(NOT COMMAND cotire)
+ message(AUTHOR_WARNING "Target \"${ARG_NAME}\" not cotired because cotire isn't loaded")
+ else()
+ message(AUTHOR_WARNING "Target \"${ARG_NAME}\" not cotired because cotire is older than the required version")
+ endif()
+ endif()
+endmacro()
diff --git a/libmariadb/external/zlib/uncompr.c b/libmariadb/external/zlib/uncompr.c
new file mode 100644
index 00000000..f9532f46
--- /dev/null
+++ b/libmariadb/external/zlib/uncompr.c
@@ -0,0 +1,93 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. *sourceLen is
+ the byte length of the source buffer. Upon entry, *destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit,
+ *destLen is the size of the decompressed data and *sourceLen is the number
+ of source bytes consumed. Upon return, source + *sourceLen points to the
+ first unused input byte.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
+ Z_DATA_ERROR if the input data was corrupted, including if the input data is
+ an incomplete zlib stream.
+*/
+int ZEXPORT uncompress2(dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong *sourceLen;
+{
+ z_stream stream;
+ int err;
+ const uInt max = (uInt)-1;
+ uLong len, left;
+ Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
+
+ len = *sourceLen;
+ if (*destLen) {
+ left = *destLen;
+ *destLen = 0;
+ }
+ else {
+ left = 1;
+ dest = buf;
+ }
+
+ stream.next_in = (z_const Bytef *)source;
+ stream.avail_in = 0;
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ stream.next_out = dest;
+ stream.avail_out = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > (uLong)max ? max : (uInt)left;
+ left -= stream.avail_out;
+ }
+ if (stream.avail_in == 0) {
+ stream.avail_in = len > (uLong)max ? max : (uInt)len;
+ len -= stream.avail_in;
+ }
+ err = inflate(&stream, Z_NO_FLUSH);
+ } while (err == Z_OK);
+
+ *sourceLen -= len + stream.avail_in;
+ if (dest != buf)
+ *destLen = stream.total_out;
+ else if (stream.total_out && err == Z_BUF_ERROR)
+ left = 1;
+
+ inflateEnd(&stream);
+ return err == Z_STREAM_END ? Z_OK :
+ err == Z_NEED_DICT ? Z_DATA_ERROR :
+ err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
+ err;
+}
+
+int ZEXPORT uncompress(dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ return uncompress2(dest, destLen, source, &sourceLen);
+}
diff --git a/libmariadb/external/zlib/watcom/watcom_f.mak b/libmariadb/external/zlib/watcom/watcom_f.mak
new file mode 100644
index 00000000..37f4d74c
--- /dev/null
+++ b/libmariadb/external/zlib/watcom/watcom_f.mak
@@ -0,0 +1,43 @@
+# Makefile for zlib
+# OpenWatcom flat model
+# Last updated: 28-Dec-2005
+
+# To use, do "wmake -f watcom_f.mak"
+
+C_SOURCE = adler32.c compress.c crc32.c deflate.c &
+ gzclose.c gzlib.c gzread.c gzwrite.c &
+ infback.c inffast.c inflate.c inftrees.c &
+ trees.c uncompr.c zutil.c
+
+OBJS = adler32.obj compress.obj crc32.obj deflate.obj &
+ gzclose.obj gzlib.obj gzread.obj gzwrite.obj &
+ infback.obj inffast.obj inflate.obj inftrees.obj &
+ trees.obj uncompr.obj zutil.obj
+
+CC = wcc386
+LINKER = wcl386
+CFLAGS = -zq -mf -3r -fp3 -s -bt=dos -oilrtfm -fr=nul -wx
+ZLIB_LIB = zlib_f.lib
+
+.C.OBJ:
+ $(CC) $(CFLAGS) $[@
+
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+$(ZLIB_LIB): $(OBJS)
+ wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj
+ wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj
+ wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj
+ wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj
+ wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj
+
+example.exe: $(ZLIB_LIB) example.obj
+ $(LINKER) -ldos32a -fe=example.exe example.obj $(ZLIB_LIB)
+
+minigzip.exe: $(ZLIB_LIB) minigzip.obj
+ $(LINKER) -ldos32a -fe=minigzip.exe minigzip.obj $(ZLIB_LIB)
+
+clean: .SYMBOLIC
+ del *.obj
+ del $(ZLIB_LIB)
+ @echo Cleaning done
diff --git a/libmariadb/external/zlib/watcom/watcom_l.mak b/libmariadb/external/zlib/watcom/watcom_l.mak
new file mode 100644
index 00000000..193eed7b
--- /dev/null
+++ b/libmariadb/external/zlib/watcom/watcom_l.mak
@@ -0,0 +1,43 @@
+# Makefile for zlib
+# OpenWatcom large model
+# Last updated: 28-Dec-2005
+
+# To use, do "wmake -f watcom_l.mak"
+
+C_SOURCE = adler32.c compress.c crc32.c deflate.c &
+ gzclose.c gzlib.c gzread.c gzwrite.c &
+ infback.c inffast.c inflate.c inftrees.c &
+ trees.c uncompr.c zutil.c
+
+OBJS = adler32.obj compress.obj crc32.obj deflate.obj &
+ gzclose.obj gzlib.obj gzread.obj gzwrite.obj &
+ infback.obj inffast.obj inflate.obj inftrees.obj &
+ trees.obj uncompr.obj zutil.obj
+
+CC = wcc
+LINKER = wcl
+CFLAGS = -zq -ml -s -bt=dos -oilrtfm -fr=nul -wx
+ZLIB_LIB = zlib_l.lib
+
+.C.OBJ:
+ $(CC) $(CFLAGS) $[@
+
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+$(ZLIB_LIB): $(OBJS)
+ wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj
+ wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj
+ wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj
+ wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj
+ wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj
+
+example.exe: $(ZLIB_LIB) example.obj
+ $(LINKER) -fe=example.exe example.obj $(ZLIB_LIB)
+
+minigzip.exe: $(ZLIB_LIB) minigzip.obj
+ $(LINKER) -fe=minigzip.exe minigzip.obj $(ZLIB_LIB)
+
+clean: .SYMBOLIC
+ del *.obj
+ del $(ZLIB_LIB)
+ @echo Cleaning done
diff --git a/libmariadb/external/zlib/win32/DLL_FAQ.txt b/libmariadb/external/zlib/win32/DLL_FAQ.txt
new file mode 100644
index 00000000..12c00901
--- /dev/null
+++ b/libmariadb/external/zlib/win32/DLL_FAQ.txt
@@ -0,0 +1,397 @@
+
+ Frequently Asked Questions about ZLIB1.DLL
+
+
+This document describes the design, the rationale, and the usage
+of the official DLL build of zlib, named ZLIB1.DLL. If you have
+general questions about zlib, you should see the file "FAQ" found
+in the zlib distribution, or at the following location:
+ http://www.gzip.org/zlib/zlib_faq.html
+
+
+ 1. What is ZLIB1.DLL, and how can I get it?
+
+ - ZLIB1.DLL is the official build of zlib as a DLL.
+ (Please remark the character '1' in the name.)
+
+ Pointers to a precompiled ZLIB1.DLL can be found in the zlib
+ web site at:
+ http://www.zlib.net/
+
+ Applications that link to ZLIB1.DLL can rely on the following
+ specification:
+
+ * The exported symbols are exclusively defined in the source
+ files "zlib.h" and "zlib.def", found in an official zlib
+ source distribution.
+ * The symbols are exported by name, not by ordinal.
+ * The exported names are undecorated.
+ * The calling convention of functions is "C" (CDECL).
+ * The ZLIB1.DLL binary is linked to MSVCRT.DLL.
+
+ The archive in which ZLIB1.DLL is bundled contains compiled
+ test programs that must run with a valid build of ZLIB1.DLL.
+ It is recommended to download the prebuilt DLL from the zlib
+ web site, instead of building it yourself, to avoid potential
+ incompatibilities that could be introduced by your compiler
+ and build settings. If you do build the DLL yourself, please
+ make sure that it complies with all the above requirements,
+ and it runs with the precompiled test programs, bundled with
+ the original ZLIB1.DLL distribution.
+
+ If, for any reason, you need to build an incompatible DLL,
+ please use a different file name.
+
+
+ 2. Why did you change the name of the DLL to ZLIB1.DLL?
+ What happened to the old ZLIB.DLL?
+
+ - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required
+ compilation settings that were incompatible to those used by
+ a static build. The DLL settings were supposed to be enabled
+ by defining the macro ZLIB_DLL, before including "zlib.h".
+ Incorrect handling of this macro was silently accepted at
+ build time, resulting in two major problems:
+
+ * ZLIB_DLL was missing from the old makefile. When building
+ the DLL, not all people added it to the build options. In
+ consequence, incompatible incarnations of ZLIB.DLL started
+ to circulate around the net.
+
+ * When switching from using the static library to using the
+ DLL, applications had to define the ZLIB_DLL macro and
+ to recompile all the sources that contained calls to zlib
+ functions. Failure to do so resulted in creating binaries
+ that were unable to run with the official ZLIB.DLL build.
+
+ The only possible solution that we could foresee was to make
+ a binary-incompatible change in the DLL interface, in order to
+ remove the dependency on the ZLIB_DLL macro, and to release
+ the new DLL under a different name.
+
+ We chose the name ZLIB1.DLL, where '1' indicates the major
+ zlib version number. We hope that we will not have to break
+ the binary compatibility again, at least not as long as the
+ zlib-1.x series will last.
+
+ There is still a ZLIB_DLL macro, that can trigger a more
+ efficient build and use of the DLL, but compatibility no
+ longer dependents on it.
+
+
+ 3. Can I build ZLIB.DLL from the new zlib sources, and replace
+ an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier?
+
+ - In principle, you can do it by assigning calling convention
+ keywords to the macros ZEXPORT and ZEXPORTVA. In practice,
+ it depends on what you mean by "an old ZLIB.DLL", because the
+ old DLL exists in several mutually-incompatible versions.
+ You have to find out first what kind of calling convention is
+ being used in your particular ZLIB.DLL build, and to use the
+ same one in the new build. If you don't know what this is all
+ about, you might be better off if you would just leave the old
+ DLL intact.
+
+
+ 4. Can I compile my application using the new zlib interface, and
+ link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or
+ earlier?
+
+ - The official answer is "no"; the real answer depends again on
+ what kind of ZLIB.DLL you have. Even if you are lucky, this
+ course of action is unreliable.
+
+ If you rebuild your application and you intend to use a newer
+ version of zlib (post- 1.1.4), it is strongly recommended to
+ link it to the new ZLIB1.DLL.
+
+
+ 5. Why are the zlib symbols exported by name, and not by ordinal?
+
+ - Although exporting symbols by ordinal is a little faster, it
+ is risky. Any single glitch in the maintenance or use of the
+ DEF file that contains the ordinals can result in incompatible
+ builds and frustrating crashes. Simply put, the benefits of
+ exporting symbols by ordinal do not justify the risks.
+
+ Technically, it should be possible to maintain ordinals in
+ the DEF file, and still export the symbols by name. Ordinals
+ exist in every DLL, and even if the dynamic linking performed
+ at the DLL startup is searching for names, ordinals serve as
+ hints, for a faster name lookup. However, if the DEF file
+ contains ordinals, the Microsoft linker automatically builds
+ an implib that will cause the executables linked to it to use
+ those ordinals, and not the names. It is interesting to
+ notice that the GNU linker for Win32 does not suffer from this
+ problem.
+
+ It is possible to avoid the DEF file if the exported symbols
+ are accompanied by a "__declspec(dllexport)" attribute in the
+ source files. You can do this in zlib by predefining the
+ ZLIB_DLL macro.
+
+
+ 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling
+ convention. Why not use the STDCALL convention?
+ STDCALL is the standard convention in Win32, and I need it in
+ my Visual Basic project!
+
+ (For readability, we use CDECL to refer to the convention
+ triggered by the "__cdecl" keyword, STDCALL to refer to
+ the convention triggered by "__stdcall", and FASTCALL to
+ refer to the convention triggered by "__fastcall".)
+
+ - Most of the native Windows API functions (without varargs) use
+ indeed the WINAPI convention (which translates to STDCALL in
+ Win32), but the standard C functions use CDECL. If a user
+ application is intrinsically tied to the Windows API (e.g.
+ it calls native Windows API functions such as CreateFile()),
+ sometimes it makes sense to decorate its own functions with
+ WINAPI. But if ANSI C or POSIX portability is a goal (e.g.
+ it calls standard C functions such as fopen()), it is not a
+ sound decision to request the inclusion of <windows.h>, or to
+ use non-ANSI constructs, for the sole purpose to make the user
+ functions STDCALL-able.
+
+ The functionality offered by zlib is not in the category of
+ "Windows functionality", but is more like "C functionality".
+
+ Technically, STDCALL is not bad; in fact, it is slightly
+ faster than CDECL, and it works with variable-argument
+ functions, just like CDECL. It is unfortunate that, in spite
+ of using STDCALL in the Windows API, it is not the default
+ convention used by the C compilers that run under Windows.
+ The roots of the problem reside deep inside the unsafety of
+ the K&R-style function prototypes, where the argument types
+ are not specified; but that is another story for another day.
+
+ The remaining fact is that CDECL is the default convention.
+ Even if an explicit convention is hard-coded into the function
+ prototypes inside C headers, problems may appear. The
+ necessity to expose the convention in users' callbacks is one
+ of these problems.
+
+ The calling convention issues are also important when using
+ zlib in other programming languages. Some of them, like Ada
+ (GNAT) and Fortran (GNU G77), have C bindings implemented
+ initially on Unix, and relying on the C calling convention.
+ On the other hand, the pre- .NET versions of Microsoft Visual
+ Basic require STDCALL, while Borland Delphi prefers, although
+ it does not require, FASTCALL.
+
+ In fairness to all possible uses of zlib outside the C
+ programming language, we choose the default "C" convention.
+ Anyone interested in different bindings or conventions is
+ encouraged to maintain specialized projects. The "contrib/"
+ directory from the zlib distribution already holds a couple
+ of foreign bindings, such as Ada, C++, and Delphi.
+
+
+ 7. I need a DLL for my Visual Basic project. What can I do?
+
+ - Define the ZLIB_WINAPI macro before including "zlib.h", when
+ building both the DLL and the user application (except that
+ you don't need to define anything when using the DLL in Visual
+ Basic). The ZLIB_WINAPI macro will switch on the WINAPI
+ (STDCALL) convention. The name of this DLL must be different
+ than the official ZLIB1.DLL.
+
+ Gilles Vollant has contributed a build named ZLIBWAPI.DLL,
+ with the ZLIB_WINAPI macro turned on, and with the minizip
+ functionality built in. For more information, please read
+ the notes inside "contrib/vstudio/readme.txt", found in the
+ zlib distribution.
+
+
+ 8. I need to use zlib in my Microsoft .NET project. What can I
+ do?
+
+ - Henrik Ravn has contributed a .NET wrapper around zlib. Look
+ into contrib/dotzlib/, inside the zlib distribution.
+
+
+ 9. If my application uses ZLIB1.DLL, should I link it to
+ MSVCRT.DLL? Why?
+
+ - It is not required, but it is recommended to link your
+ application to MSVCRT.DLL, if it uses ZLIB1.DLL.
+
+ The executables (.EXE, .DLL, etc.) that are involved in the
+ same process and are using the C run-time library (i.e. they
+ are calling standard C functions), must link to the same
+ library. There are several libraries in the Win32 system:
+ CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc.
+ Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that
+ depend on it should also be linked to MSVCRT.DLL.
+
+
+10. Why are you saying that ZLIB1.DLL and my application should
+ be linked to the same C run-time (CRT) library? I linked my
+ application and my DLLs to different C libraries (e.g. my
+ application to a static library, and my DLLs to MSVCRT.DLL),
+ and everything works fine.
+
+ - If a user library invokes only pure Win32 API (accessible via
+ <windows.h> and the related headers), its DLL build will work
+ in any context. But if this library invokes standard C API,
+ things get more complicated.
+
+ There is a single Win32 library in a Win32 system. Every
+ function in this library resides in a single DLL module, that
+ is safe to call from anywhere. On the other hand, there are
+ multiple versions of the C library, and each of them has its
+ own separate internal state. Standalone executables and user
+ DLLs that call standard C functions must link to a C run-time
+ (CRT) library, be it static or shared (DLL). Intermixing
+ occurs when an executable (not necessarily standalone) and a
+ DLL are linked to different CRTs, and both are running in the
+ same process.
+
+ Intermixing multiple CRTs is possible, as long as their
+ internal states are kept intact. The Microsoft Knowledge Base
+ articles KB94248 "HOWTO: Use the C Run-Time" and KB140584
+ "HOWTO: Link with the Correct C Run-Time (CRT) Library"
+ mention the potential problems raised by intermixing.
+
+ If intermixing works for you, it's because your application
+ and DLLs are avoiding the corruption of each of the CRTs'
+ internal states, maybe by careful design, or maybe by fortune.
+
+ Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such
+ as those provided by Borland, raises similar problems.
+
+
+11. Why are you linking ZLIB1.DLL to MSVCRT.DLL?
+
+ - MSVCRT.DLL exists on every Windows 95 with a new service pack
+ installed, or with Microsoft Internet Explorer 4 or later, and
+ on all other Windows 4.x or later (Windows 98, Windows NT 4,
+ or later). It is freely distributable; if not present in the
+ system, it can be downloaded from Microsoft or from other
+ software provider for free.
+
+ The fact that MSVCRT.DLL does not exist on a virgin Windows 95
+ is not so problematic. Windows 95 is scarcely found nowadays,
+ Microsoft ended its support a long time ago, and many recent
+ applications from various vendors, including Microsoft, do not
+ even run on it. Furthermore, no serious user should run
+ Windows 95 without a proper update installed.
+
+
+12. Why are you not linking ZLIB1.DLL to
+ <<my favorite C run-time library>> ?
+
+ - We considered and abandoned the following alternatives:
+
+ * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or
+ LIBCMT.LIB) is not a good option. People are using the DLL
+ mainly to save disk space. If you are linking your program
+ to a static C library, you may as well consider linking zlib
+ in statically, too.
+
+ * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because
+ CRTDLL.DLL is present on every Win32 installation.
+ Unfortunately, it has a series of problems: it does not
+ work properly with Microsoft's C++ libraries, it does not
+ provide support for 64-bit file offsets, (and so on...),
+ and Microsoft discontinued its support a long time ago.
+
+ * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied
+ with the Microsoft .NET platform, and Visual C++ 7.0/7.1,
+ raises problems related to the status of ZLIB1.DLL as a
+ system component. According to the Microsoft Knowledge Base
+ article KB326922 "INFO: Redistribution of the Shared C
+ Runtime Component in Visual C++ .NET", MSVCR70.DLL and
+ MSVCR71.DLL are not supposed to function as system DLLs,
+ because they may clash with MSVCRT.DLL. Instead, the
+ application's installer is supposed to put these DLLs
+ (if needed) in the application's private directory.
+ If ZLIB1.DLL depends on a non-system runtime, it cannot
+ function as a redistributable system component.
+
+ * Linking ZLIB1.DLL to non-Microsoft runtimes, such as
+ Borland's, or Cygwin's, raises problems related to the
+ reliable presence of these runtimes on Win32 systems.
+ It's easier to let the DLL build of zlib up to the people
+ who distribute these runtimes, and who may proceed as
+ explained in the answer to Question 14.
+
+
+13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL,
+ how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0
+ (Visual Studio .NET) or newer?
+
+ - Due to the problems explained in the Microsoft Knowledge Base
+ article KB326922 (see the previous answer), the C runtime that
+ comes with the VC7 environment is no longer considered a
+ system component. That is, it should not be assumed that this
+ runtime exists, or may be installed in a system directory.
+ Since ZLIB1.DLL is supposed to be a system component, it may
+ not depend on a non-system component.
+
+ In order to link ZLIB1.DLL and your application to MSVCRT.DLL
+ in VC7, you need the library of Visual C++ 6.0 or older. If
+ you don't have this library at hand, it's probably best not to
+ use ZLIB1.DLL.
+
+ We are hoping that, in the future, Microsoft will provide a
+ way to build applications linked to a proper system runtime,
+ from the Visual C++ environment. Until then, you have a
+ couple of alternatives, such as linking zlib in statically.
+ If your application requires dynamic linking, you may proceed
+ as explained in the answer to Question 14.
+
+
+14. I need to link my own DLL build to a CRT different than
+ MSVCRT.DLL. What can I do?
+
+ - Feel free to rebuild the DLL from the zlib sources, and link
+ it the way you want. You should, however, clearly state that
+ your build is unofficial. You should give it a different file
+ name, and/or install it in a private directory that can be
+ accessed by your application only, and is not visible to the
+ others (i.e. it's neither in the PATH, nor in the SYSTEM or
+ SYSTEM32 directories). Otherwise, your build may clash with
+ applications that link to the official build.
+
+ For example, in Cygwin, zlib is linked to the Cygwin runtime
+ CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL.
+
+
+15. May I include additional pieces of code that I find useful,
+ link them in ZLIB1.DLL, and export them?
+
+ - No. A legitimate build of ZLIB1.DLL must not include code
+ that does not originate from the official zlib source code.
+ But you can make your own private DLL build, under a different
+ file name, as suggested in the previous answer.
+
+ For example, zlib is a part of the VCL library, distributed
+ with Borland Delphi and C++ Builder. The DLL build of VCL
+ is a redistributable file, named VCLxx.DLL.
+
+
+16. May I remove some functionality out of ZLIB1.DLL, by enabling
+ macros like NO_GZCOMPRESS or NO_GZIP at compile time?
+
+ - No. A legitimate build of ZLIB1.DLL must provide the complete
+ zlib functionality, as implemented in the official zlib source
+ code. But you can make your own private DLL build, under a
+ different file name, as suggested in the previous answer.
+
+
+17. I made my own ZLIB1.DLL build. Can I test it for compliance?
+
+ - We prefer that you download the official DLL from the zlib
+ web site. If you need something peculiar from this DLL, you
+ can send your suggestion to the zlib mailing list.
+
+ However, in case you do rebuild the DLL yourself, you can run
+ it with the test programs found in the DLL distribution.
+ Running these test programs is not a guarantee of compliance,
+ but a failure can imply a detected problem.
+
+**
+
+This document is written and maintained by
+Cosmin Truta <cosmint@cs.ubbcluj.ro>
diff --git a/libmariadb/external/zlib/win32/Makefile.bor b/libmariadb/external/zlib/win32/Makefile.bor
new file mode 100644
index 00000000..d152bbb7
--- /dev/null
+++ b/libmariadb/external/zlib/win32/Makefile.bor
@@ -0,0 +1,110 @@
+# Makefile for zlib
+# Borland C++ for Win32
+#
+# Usage:
+# make -f win32/Makefile.bor
+# make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj
+
+# ------------ Borland C++ ------------
+
+# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or
+# added to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+CC = bcc32
+AS = bcc32
+LD = bcc32
+AR = tlib
+CFLAGS = -a -d -k- -O2 $(LOC)
+ASFLAGS = $(LOC)
+LDFLAGS = $(LOC)
+
+
+# variables
+ZLIB_LIB = zlib.lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+#OBJA =
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+#OBJPA=
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+ $(CC) -c $(CFLAGS) $<
+
+.asm.obj:
+ $(AS) -c $(ASFLAGS) $<
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: test/example.c zlib.h zconf.h
+
+minigzip.obj: test/minigzip.c zlib.h zconf.h
+
+
+# For the sake of the old Borland make,
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA)
+ -del $(ZLIB_LIB)
+ $(AR) $(ZLIB_LIB) $(OBJP1)
+ $(AR) $(ZLIB_LIB) $(OBJP2)
+ $(AR) $(ZLIB_LIB) $(OBJPA)
+
+
+# testing
+test: example.exe minigzip.exe
+ example
+ echo hello world | minigzip | minigzip -d
+
+example.exe: example.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+ $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+
+# cleanup
+clean:
+ -del $(ZLIB_LIB)
+ -del *.obj
+ -del *.exe
+ -del *.tds
+ -del zlib.bak
+ -del foo.gz
diff --git a/libmariadb/external/zlib/win32/Makefile.gcc b/libmariadb/external/zlib/win32/Makefile.gcc
new file mode 100644
index 00000000..6d1ded62
--- /dev/null
+++ b/libmariadb/external/zlib/win32/Makefile.gcc
@@ -0,0 +1,182 @@
+# Makefile for zlib, derived from Makefile.dj2.
+# Modified for mingw32 by C. Spieler, 6/16/98.
+# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003.
+# Last updated: Mar 2012.
+# Tested under Cygwin and MinGW.
+
+# Copyright (C) 1995-2003 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile, or to compile and test, type from the top level zlib directory:
+#
+# make -fwin32/Makefile.gcc; make test testdll -fwin32/Makefile.gcc
+#
+# To use the asm code, type:
+# cp contrib/asm?86/match.S ./match.S
+# make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc
+#
+# To install libz.a, zconf.h and zlib.h in the system directories, type:
+#
+# make install -fwin32/Makefile.gcc
+#
+# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set.
+#
+# To install the shared lib, append SHARED_MODE=1 to the make command :
+#
+# make install -fwin32/Makefile.gcc SHARED_MODE=1
+
+# Note:
+# If the platform is *not* MinGW (e.g. it is Cygwin or UWIN),
+# the DLL name should be changed from "zlib1.dll".
+
+STATICLIB = libz.a
+SHAREDLIB = zlib1.dll
+IMPLIB = libz.dll.a
+
+#
+# Set to 1 if shared object needs to be installed
+#
+SHARED_MODE=0
+
+#LOC = -DASMV
+#LOC = -DDEBUG -g
+
+PREFIX =
+CC = $(PREFIX)gcc
+CFLAGS = $(LOC) -O3 -Wall
+
+AS = $(CC)
+ASFLAGS = $(LOC) -Wall
+
+LD = $(CC)
+LDFLAGS = $(LOC)
+
+AR = $(PREFIX)ar
+ARFLAGS = rcs
+
+RC = $(PREFIX)windres
+RCFLAGS = --define GCC_WINDRES
+
+STRIP = $(PREFIX)strip
+
+CP = cp -fp
+# If GNU install is available, replace $(CP) with install.
+INSTALL = $(CP)
+RM = rm -f
+
+prefix ?= /usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \
+ gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o
+OBJA =
+
+all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example.exe minigzip.exe example_d.exe minigzip_d.exe
+
+test: example.exe minigzip.exe
+ ./example
+ echo hello world | ./minigzip | ./minigzip -d
+
+testdll: example_d.exe minigzip_d.exe
+ ./example_d
+ echo hello world | ./minigzip_d | ./minigzip_d -d
+
+.c.o:
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+.S.o:
+ $(AS) $(ASFLAGS) -c -o $@ $<
+
+$(STATICLIB): $(OBJS) $(OBJA)
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(OBJA)
+
+$(IMPLIB): $(SHAREDLIB)
+
+$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o
+ $(CC) -shared -Wl,--out-implib,$(IMPLIB) $(LDFLAGS) \
+ -o $@ win32/zlib.def $(OBJS) $(OBJA) zlibrc.o
+ $(STRIP) $@
+
+example.exe: example.o $(STATICLIB)
+ $(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB)
+ $(STRIP) $@
+
+minigzip.exe: minigzip.o $(STATICLIB)
+ $(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB)
+ $(STRIP) $@
+
+example_d.exe: example.o $(IMPLIB)
+ $(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB)
+ $(STRIP) $@
+
+minigzip_d.exe: minigzip.o $(IMPLIB)
+ $(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB)
+ $(STRIP) $@
+
+example.o: test/example.c zlib.h zconf.h
+ $(CC) $(CFLAGS) -I. -c -o $@ test/example.c
+
+minigzip.o: test/minigzip.c zlib.h zconf.h
+ $(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c
+
+zlibrc.o: win32/zlib1.rc
+ $(RC) $(RCFLAGS) -o $@ win32/zlib1.rc
+
+.PHONY: install uninstall clean
+
+install: zlib.h zconf.h $(STATICLIB) $(IMPLIB)
+ @if test -z "$(DESTDIR)$(INCLUDE_PATH)" -o -z "$(DESTDIR)$(LIBRARY_PATH)" -o -z "$(DESTDIR)$(BINARY_PATH)"; then \
+ echo INCLUDE_PATH, LIBRARY_PATH, and BINARY_PATH must be specified; \
+ exit 1; \
+ fi
+ -@mkdir -p '$(DESTDIR)$(INCLUDE_PATH)'
+ -@mkdir -p '$(DESTDIR)$(LIBRARY_PATH)' '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig
+ -if [ "$(SHARED_MODE)" = "1" ]; then \
+ mkdir -p '$(DESTDIR)$(BINARY_PATH)'; \
+ $(INSTALL) $(SHAREDLIB) '$(DESTDIR)$(BINARY_PATH)'; \
+ $(INSTALL) $(IMPLIB) '$(DESTDIR)$(LIBRARY_PATH)'; \
+ fi
+ -$(INSTALL) zlib.h '$(DESTDIR)$(INCLUDE_PATH)'
+ -$(INSTALL) zconf.h '$(DESTDIR)$(INCLUDE_PATH)'
+ -$(INSTALL) $(STATICLIB) '$(DESTDIR)$(LIBRARY_PATH)'
+ sed \
+ -e 's|@prefix@|${prefix}|g' \
+ -e 's|@exec_prefix@|${exec_prefix}|g' \
+ -e 's|@libdir@|$(LIBRARY_PATH)|g' \
+ -e 's|@sharedlibdir@|$(LIBRARY_PATH)|g' \
+ -e 's|@includedir@|$(INCLUDE_PATH)|g' \
+ -e 's|@VERSION@|'`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' zlib.h`'|g' \
+ zlib.pc.in > '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc
+
+uninstall:
+ -if [ "$(SHARED_MODE)" = "1" ]; then \
+ $(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \
+ $(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \
+ fi
+ -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h
+ -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h
+ -$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB)
+
+clean:
+ -$(RM) $(STATICLIB)
+ -$(RM) $(SHAREDLIB)
+ -$(RM) $(IMPLIB)
+ -$(RM) *.o
+ -$(RM) *.exe
+ -$(RM) foo.gz
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+gzclose.o: zlib.h zconf.h gzguts.h
+gzlib.o: zlib.h zconf.h gzguts.h
+gzread.o: zlib.h zconf.h gzguts.h
+gzwrite.o: zlib.h zconf.h gzguts.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/libmariadb/external/zlib/win32/Makefile.msc b/libmariadb/external/zlib/win32/Makefile.msc
new file mode 100755
index 00000000..14575fa7
--- /dev/null
+++ b/libmariadb/external/zlib/win32/Makefile.msc
@@ -0,0 +1,163 @@
+# Makefile for zlib using Microsoft (Visual) C
+# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+#
+# Usage:
+# nmake -f win32/Makefile.msc (standard build)
+# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build)
+# nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \
+# OBJA="inffas32.obj match686.obj" (use ASM code, x86)
+# nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \
+# OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" (use ASM code, x64)
+
+# The toplevel directory of the source tree.
+#
+TOP = .
+
+# optional build flags
+LOC =
+
+# variables
+STATICLIB = zlib.lib
+SHAREDLIB = zlib1.dll
+IMPLIB = zdll.lib
+
+CC = cl
+AS = ml
+LD = link
+AR = lib
+RC = rc
+CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC)
+WFLAGS = -DHAS_PCLMUL -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
+ASFLAGS = -coff -Zi $(LOC)
+LDFLAGS = -nologo -debug -incremental:no -opt:ref
+ARFLAGS = -nologo
+RCFLAGS = /dWIN32 /r
+
+OBJS = adler32.obj compress.obj crc32_simd.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj \
+ gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj
+OBJA =
+
+
+# targets
+all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
+ example.exe minigzip.exe example_d.exe minigzip_d.exe
+
+$(STATICLIB): $(OBJS) $(OBJA)
+ $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA)
+
+$(IMPLIB): $(SHAREDLIB)
+
+$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res
+ $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \
+ -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res
+ if exist $@.manifest \
+ mt -nologo -manifest $@.manifest -outputresource:$@;2
+
+example.exe: example.obj $(STATICLIB)
+ $(LD) $(LDFLAGS) example.obj $(STATICLIB)
+ if exist $@.manifest \
+ mt -nologo -manifest $@.manifest -outputresource:$@;1
+
+minigzip.exe: minigzip.obj $(STATICLIB)
+ $(LD) $(LDFLAGS) minigzip.obj $(STATICLIB)
+ if exist $@.manifest \
+ mt -nologo -manifest $@.manifest -outputresource:$@;1
+
+example_d.exe: example.obj $(IMPLIB)
+ $(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB)
+ if exist $@.manifest \
+ mt -nologo -manifest $@.manifest -outputresource:$@;1
+
+minigzip_d.exe: minigzip.obj $(IMPLIB)
+ $(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB)
+ if exist $@.manifest \
+ mt -nologo -manifest $@.manifest -outputresource:$@;1
+
+{$(TOP)}.c.obj:
+ $(CC) -c $(WFLAGS) $(CFLAGS) $<
+
+{$(TOP)/test}.c.obj:
+ $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $<
+
+{$(TOP)/contrib/masmx64}.c.obj:
+ $(CC) -c $(WFLAGS) $(CFLAGS) $<
+
+{$(TOP)/contrib/masmx64}.asm.obj:
+ $(AS) -c $(ASFLAGS) $<
+
+{$(TOP)/contrib/masmx86}.asm.obj:
+ $(AS) -c $(ASFLAGS) $<
+
+adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h
+
+compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h
+
+crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h
+
+deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
+
+gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
+
+gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
+
+gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
+
+gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
+
+infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
+ $(TOP)/inffast.h $(TOP)/inffixed.h
+
+inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
+ $(TOP)/inffast.h
+
+inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
+ $(TOP)/inffast.h $(TOP)/inffixed.h
+
+inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h
+
+trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h
+
+uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h
+
+zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
+
+gvmat64.obj: $(TOP)/contrib\masmx64\gvmat64.asm
+
+inffasx64.obj: $(TOP)/contrib\masmx64\inffasx64.asm
+
+inffas8664.obj: $(TOP)/contrib\masmx64\inffas8664.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h \
+ $(TOP)/inftrees.h $(TOP)/inflate.h $(TOP)/inffast.h
+
+inffas32.obj: $(TOP)/contrib\masmx86\inffas32.asm
+
+match686.obj: $(TOP)/contrib\masmx86\match686.asm
+
+example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h
+
+minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h
+
+zlib1.res: $(TOP)/win32/zlib1.rc
+ $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc
+
+# testing
+test: example.exe minigzip.exe
+ example
+ echo hello world | minigzip | minigzip -d
+
+testdll: example_d.exe minigzip_d.exe
+ example_d
+ echo hello world | minigzip_d | minigzip_d -d
+
+
+# cleanup
+clean:
+ -del $(STATICLIB)
+ -del $(SHAREDLIB)
+ -del $(IMPLIB)
+ -del *.obj
+ -del *.res
+ -del *.exp
+ -del *.exe
+ -del *.pdb
+ -del *.manifest
+ -del foo.gz
diff --git a/libmariadb/external/zlib/win32/README-WIN32.txt b/libmariadb/external/zlib/win32/README-WIN32.txt
new file mode 100644
index 00000000..3d77d521
--- /dev/null
+++ b/libmariadb/external/zlib/win32/README-WIN32.txt
@@ -0,0 +1,103 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.8 is a general purpose data compression library. All the code is
+thread safe. The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
+and rfc1952.txt (gzip format).
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled
+examples are distributed in this package, example and minigzip. The example_d
+and minigzip_d flavors validate that the zlib1.dll file is working correctly.
+
+Questions about zlib should be sent to <zlib@gzip.org>. The zlib home page
+is http://zlib.net/ . Before reporting a problem, please check this site to
+verify that you have the latest version of zlib; otherwise get the latest
+version and check whether the problem still exists or not.
+
+PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html
+before asking for help.
+
+
+Manifest:
+
+The package zlib-1.2.8-win32-x86.zip will contain the following files:
+
+ README-WIN32.txt This document
+ ChangeLog Changes since previous zlib packages
+ DLL_FAQ.txt Frequently asked questions about zlib1.dll
+ zlib.3.pdf Documentation of this library in Adobe Acrobat format
+
+ example.exe A statically-bound example (using zlib.lib, not the dll)
+ example.pdb Symbolic information for debugging example.exe
+
+ example_d.exe A zlib1.dll bound example (using zdll.lib)
+ example_d.pdb Symbolic information for debugging example_d.exe
+
+ minigzip.exe A statically-bound test program (using zlib.lib, not the dll)
+ minigzip.pdb Symbolic information for debugging minigzip.exe
+
+ minigzip_d.exe A zlib1.dll bound test program (using zdll.lib)
+ minigzip_d.pdb Symbolic information for debugging minigzip_d.exe
+
+ zlib.h Install these files into the compilers' INCLUDE path to
+ zconf.h compile programs which use zlib.lib or zdll.lib
+
+ zdll.lib Install these files into the compilers' LIB path if linking
+ zdll.exp a compiled program to the zlib1.dll binary
+
+ zlib.lib Install these files into the compilers' LIB path to link zlib
+ zlib.pdb into compiled programs, without zlib1.dll runtime dependency
+ (zlib.pdb provides debugging info to the compile time linker)
+
+ zlib1.dll Install this binary shared library into the system PATH, or
+ the program's runtime directory (where the .exe resides)
+ zlib1.pdb Install in the same directory as zlib1.dll, in order to debug
+ an application crash using WinDbg or similar tools.
+
+All .pdb files above are entirely optional, but are very useful to a developer
+attempting to diagnose program misbehavior or a crash. Many additional
+important files for developers can be found in the zlib127.zip source package
+available from http://zlib.net/ - review that package's README file for details.
+
+
+Acknowledgments:
+
+The deflate format used by zlib was defined by Phil Katz. The deflate and
+zlib specifications were written by L. Peter Deutsch. Thanks to all the
+people who reported problems and suggested various improvements in zlib; they
+are too numerous to cite here.
+
+
+Copyright notice:
+
+ (C) 1995-2012 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign. The sources are provided for free but without
+warranty of any kind. The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes. Please read
+the FAQ for more information on the distribution of modified source versions.
diff --git a/libmariadb/external/zlib/win32/VisualC.txt b/libmariadb/external/zlib/win32/VisualC.txt
new file mode 100644
index 00000000..579a5fc9
--- /dev/null
+++ b/libmariadb/external/zlib/win32/VisualC.txt
@@ -0,0 +1,3 @@
+
+To build zlib using the Microsoft Visual C++ environment,
+use the appropriate project from the projects/ directory.
diff --git a/libmariadb/external/zlib/win32/zlib.def b/libmariadb/external/zlib/win32/zlib.def
new file mode 100644
index 00000000..face6551
--- /dev/null
+++ b/libmariadb/external/zlib/win32/zlib.def
@@ -0,0 +1,86 @@
+; zlib data compression library
+EXPORTS
+; basic functions
+ zlibVersion
+ deflate
+ deflateEnd
+ inflate
+ inflateEnd
+; advanced functions
+ deflateSetDictionary
+ deflateCopy
+ deflateReset
+ deflateParams
+ deflateTune
+ deflateBound
+ deflatePending
+ deflatePrime
+ deflateSetHeader
+ inflateSetDictionary
+ inflateGetDictionary
+ inflateSync
+ inflateCopy
+ inflateReset
+ inflateReset2
+ inflatePrime
+ inflateMark
+ inflateGetHeader
+ inflateBack
+ inflateBackEnd
+ zlibCompileFlags
+; utility functions
+ compress
+ compress2
+ compressBound
+ uncompress
+ gzopen
+ gzdopen
+ gzbuffer
+ gzsetparams
+ gzread
+ gzwrite
+ gzprintf
+ gzvprintf
+ gzputs
+ gzgets
+ gzputc
+ gzgetc
+ gzungetc
+ gzflush
+ gzseek
+ gzrewind
+ gztell
+ gzoffset
+ gzeof
+ gzdirect
+ gzclose
+ gzclose_r
+ gzclose_w
+ gzerror
+ gzclearerr
+; large file functions
+ gzopen64
+ gzseek64
+ gztell64
+ gzoffset64
+ adler32_combine64
+ crc32_combine64
+; checksum functions
+ adler32
+ crc32
+ adler32_combine
+ crc32_combine
+; various hacks, don't look :)
+ deflateInit_
+ deflateInit2_
+ inflateInit_
+ inflateInit2_
+ inflateBackInit_
+ gzgetc_
+ zError
+ inflateSyncPoint
+ get_crc_table
+ inflateUndermine
+ inflateResetKeep
+ deflateResetKeep
+ gzopen_w
diff --git a/libmariadb/external/zlib/win32/zlib1.rc b/libmariadb/external/zlib/win32/zlib1.rc
new file mode 100644
index 00000000..5c0feed1
--- /dev/null
+++ b/libmariadb/external/zlib/win32/zlib1.rc
@@ -0,0 +1,40 @@
+#include <winver.h>
+#include "../zlib.h"
+
+#ifdef GCC_WINDRES
+VS_VERSION_INFO VERSIONINFO
+#else
+VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
+#endif
+ FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
+ PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS 1
+#else
+ FILEFLAGS 0
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0 // not used
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ //language ID = U.S. English, char set = Windows, Multilingual
+ BEGIN
+ VALUE "FileDescription", "zlib data compression library\0"
+ VALUE "FileVersion", ZLIB_VERSION "\0"
+ VALUE "InternalName", "zlib1.dll\0"
+ VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0"
+ VALUE "OriginalFilename", "zlib1.dll\0"
+ VALUE "ProductName", "zlib\0"
+ VALUE "ProductVersion", ZLIB_VERSION "\0"
+ VALUE "Comments", "For more information visit http://www.zlib.net/\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1252
+ END
+END
diff --git a/libmariadb/external/zlib/zconf.h.cmakein b/libmariadb/external/zlib/zconf.h.cmakein
new file mode 100644
index 00000000..247ba246
--- /dev/null
+++ b/libmariadb/external/zlib/zconf.h.cmakein
@@ -0,0 +1,549 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+#cmakedefine Z_PREFIX
+#cmakedefine Z_HAVE_UNISTD_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# define adler32_z z_adler32_z
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define crc32_combine_gen z_crc32_combine_gen
+# define crc32_combine_gen64 z_crc32_combine_gen64
+# define crc32_combine_op z_crc32_combine_op
+# define crc32_z z_crc32_z
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateGetDictionary z_deflateGetDictionary
+# define deflateInit z_deflateInit
+# define deflateInit2 z_deflateInit2
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzfread z_gzfread
+# define gzfwrite z_gzfwrite
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzvprintf z_gzvprintf
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit z_inflateBackInit
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCodesUsed z_inflateCodesUsed
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit z_inflateInit
+# define inflateInit2 z_inflateInit2
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateResetKeep z_inflateResetKeep
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateValidate z_inflateValidate
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# define uncompress2 z_uncompress2
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+#ifdef Z_SOLO
+ typedef unsigned long z_size_t;
+#else
+# define z_longlong long long
+# if defined(NO_SIZE_T)
+ typedef unsigned NO_SIZE_T z_size_t;
+# elif defined(STDC)
+# include <stddef.h>
+ typedef size_t z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+# undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+# if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# define Z_ARG(args) args
+# else
+# define Z_ARG(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include <sys/types.h> /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include <stdarg.h> /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include <stddef.h> /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#ifndef Z_HAVE_UNISTD_H
+# ifdef __WATCOMC__
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_HAVE_UNISTD_H
+# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H)
+# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/libmariadb/external/zlib/zlib.3 b/libmariadb/external/zlib/zlib.3
new file mode 100644
index 00000000..0160e62b
--- /dev/null
+++ b/libmariadb/external/zlib/zlib.3
@@ -0,0 +1,151 @@
+.TH ZLIB 3 "28 Apr 2013"
+.SH NAME
+zlib \- compression/decompression library
+.SH SYNOPSIS
+[see
+.I zlib.h
+for full description]
+.SH DESCRIPTION
+The
+.I zlib
+library is a general purpose data compression library.
+The code is thread safe, assuming that the standard library functions
+used are thread safe, such as memory allocation routines.
+It provides in-memory compression and decompression functions,
+including integrity checks of the uncompressed data.
+This version of the library supports only one compression method (deflation)
+but other algorithms may be added later
+with the same stream interface.
+.LP
+Compression can be done in a single step if the buffers are large enough
+or can be done by repeated calls of the compression function.
+In the latter case,
+the application must provide more input and/or consume the output
+(providing more output space) before each call.
+.LP
+The library also supports reading and writing files in
+.IR gzip (1)
+(.gz) format
+with an interface similar to that of stdio.
+.LP
+The library does not install any signal handler.
+The decoder checks the consistency of the compressed data,
+so the library should never crash even in the case of corrupted input.
+.LP
+All functions of the compression library are documented in the file
+.IR zlib.h .
+The distribution source includes examples of use of the library
+in the files
+.I test/example.c
+and
+.IR test/minigzip.c,
+as well as other examples in the
+.IR examples/
+directory.
+.LP
+Changes to this version are documented in the file
+.I ChangeLog
+that accompanies the source.
+.LP
+.I zlib
+is available in Java using the java.util.zip package:
+.IP
+http://java.sun.com/developer/technicalArticles/Programming/compression/
+.LP
+A Perl interface to
+.IR zlib ,
+written by Paul Marquess (pmqs@cpan.org),
+is available at CPAN (Comprehensive Perl Archive Network) sites,
+including:
+.IP
+http://search.cpan.org/~pmqs/IO-Compress-Zlib/
+.LP
+A Python interface to
+.IR zlib ,
+written by A.M. Kuchling (amk@magnet.com),
+is available in Python 1.5 and later versions:
+.IP
+http://docs.python.org/library/zlib.html
+.LP
+.I zlib
+is built into
+.IR tcl:
+.IP
+http://wiki.tcl.tk/4610
+.LP
+An experimental package to read and write files in .zip format,
+written on top of
+.I zlib
+by Gilles Vollant (info@winimage.com),
+is available at:
+.IP
+http://www.winimage.com/zLibDll/minizip.html
+and also in the
+.I contrib/minizip
+directory of the main
+.I zlib
+source distribution.
+.SH "SEE ALSO"
+The
+.I zlib
+web site can be found at:
+.IP
+http://zlib.net/
+.LP
+The data format used by the zlib library is described by RFC
+(Request for Comments) 1950 to 1952 in the files:
+.IP
+http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format)
+.br
+http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format)
+.br
+http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format)
+.LP
+Mark Nelson wrote an article about
+.I zlib
+for the Jan. 1997 issue of Dr. Dobb's Journal;
+a copy of the article is available at:
+.IP
+http://marknelson.us/1997/01/01/zlib-engine/
+.SH "REPORTING PROBLEMS"
+Before reporting a problem,
+please check the
+.I zlib
+web site to verify that you have the latest version of
+.IR zlib ;
+otherwise,
+obtain the latest version and see if the problem still exists.
+Please read the
+.I zlib
+FAQ at:
+.IP
+http://zlib.net/zlib_faq.html
+.LP
+before asking for help.
+Send questions and/or comments to zlib@gzip.org,
+or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
+.SH AUTHORS
+Version 1.2.8
+Copyright (C) 1995-2013 Jean-loup Gailly (jloup@gzip.org)
+and Mark Adler (madler@alumni.caltech.edu).
+.LP
+This software is provided "as-is,"
+without any express or implied warranty.
+In no event will the authors be held liable for any damages
+arising from the use of this software.
+See the distribution directory with respect to requirements
+governing redistribution.
+The deflate format used by
+.I zlib
+was defined by Phil Katz.
+The deflate and
+.I zlib
+specifications were written by L. Peter Deutsch.
+Thanks to all the people who reported problems and suggested various
+improvements in
+.IR zlib ;
+who are too numerous to cite here.
+.LP
+UNIX manual page by R. P. C. Rodgers,
+U.S. National Library of Medicine (rodgers@nlm.nih.gov).
+.\" end of man page
diff --git a/libmariadb/external/zlib/zlib.3.pdf b/libmariadb/external/zlib/zlib.3.pdf
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/libmariadb/external/zlib/zlib.3.pdf
diff --git a/libmariadb/external/zlib/zlib.h b/libmariadb/external/zlib/zlib.h
new file mode 100644
index 00000000..953cb501
--- /dev/null
+++ b/libmariadb/external/zlib/zlib.h
@@ -0,0 +1,1935 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.13, October 13th, 2022
+
+ Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.13"
+#define ZLIB_VERNUM 0x12d0
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 13
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed data.
+ This version of the library supports only one compression method (deflation)
+ but other algorithms will be added later and will have the same stream
+ interface.
+
+ Compression can be done in a single step if the buffers are large enough,
+ or can be done by repeated calls of the compression function. In the latter
+ case, the application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip and raw deflate streams in
+ memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never crash
+ even in the case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ z_const Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total number of input bytes read so far */
+
+ Bytef *next_out; /* next output byte will go here */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total number of bytes output so far */
+
+ z_const char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text
+ for deflate, or the decoding state for inflate */
+ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has dropped
+ to zero. It must update next_out and avail_out when avail_out has dropped
+ to zero. The application must initialize zalloc, zfree and opaque before
+ calling the init function. All other fields are set by the compression
+ library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe. In that case, zlib is thread-safe. When zalloc and zfree are
+ Z_NULL on entry to the initialization function, they are set to internal
+ routines that use the standard library functions malloc() and free().
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this if
+ the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers
+ returned by zalloc for objects of exactly 65536 bytes *must* have their
+ offset normalized to zero. The default allocation function provided by this
+ library ensures this (see zutil.c). To reduce memory requirements and avoid
+ any allocation of 64K objects, at the expense of compression ratio, compile
+ the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or progress
+ reports. After compression, total_in holds the total size of the
+ uncompressed data and may be saved for use by the decompressor (particularly
+ if the decompressor wants to decompress everything in a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+#define Z_TREES 6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field for deflate() */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is not
+ compatible with the zlib.h header file used by the application. This check
+ is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+ allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at all
+ (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION
+ requests a default compromise between speed and compression (currently
+ equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if level is not a valid compression level, or
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION). msg is set to null
+ if there is no error message. deflateInit does not perform any compression:
+ this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary. Some output may be provided even if
+ flush is zero.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating avail_in or avail_out accordingly; avail_out should
+ never be zero before the call. The application can consume the compressed
+ output when it wants, for example when the output buffer is full (avail_out
+ == 0), or after each call of deflate(). If deflate returns Z_OK and with
+ zero avail_out, it must be called again after making room in the output
+ buffer because there might be more output pending. See deflatePending(),
+ which can be used if desired to determine whether or not there is more output
+ in that case.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumulate before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In
+ particular avail_in is zero after the call if enough output space has been
+ provided before the call.) Flushing may degrade compression for some
+ compression algorithms and so it should be used only when necessary. This
+ completes the current deflate block and follows it with an empty stored block
+ that is three bits plus filler bits to the next byte, followed by four bytes
+ (00 00 ff ff).
+
+ If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+ output buffer, but the output is not aligned to a byte boundary. All of the
+ input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+ This completes the current deflate block and follows it with an empty fixed
+ codes block that is 10 bits long. This assures that enough bytes are output
+ in order for the decompressor to finish the block before the empty fixed
+ codes block.
+
+ If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+ for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+ seven bits of the current block are held to be written as the next byte after
+ the next deflate block is completed. In this case, the decompressor may not
+ be provided enough bits at this point in order to complete decompression of
+ the data provided so far to the compressor. It may need to wait for the next
+ block to be emitted. This is for advanced applications that need to control
+ the emission of deflate blocks.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there was
+ enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this
+ function must be called again with Z_FINISH and more output space (updated
+ avail_out) but no more input data, until it returns with Z_STREAM_END or an
+ error. After deflate has returned Z_STREAM_END, the only possible operations
+ on the stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used in the first deflate call after deflateInit if all the
+ compression is to be done in a single step. In order to complete in one
+ call, avail_out must be at least the value returned by deflateBound (see
+ below). Then deflate is guaranteed to return Z_STREAM_END. If not enough
+ output space is provided, deflate will not return Z_STREAM_END, and it must
+ be called again as described above.
+
+ deflate() sets strm->adler to the Adler-32 checksum of all input read
+ so far (that is, total_in bytes). If a gzip stream is being generated, then
+ strm->adler will be the CRC-32 checksum of the input read so far. (See
+ deflateInit2 below.)
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is
+ considered binary. This field is only for information purposes and does not
+ affect the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was Z_NULL or the state was inadvertently written over
+ by the application), or Z_BUF_ERROR if no progress is possible (for example
+ avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and
+ deflate() can be called again with more input and more output space to
+ continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case, msg
+ may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. In the current version of inflate, the provided input is not
+ read or consumed. The allocation of a sliding window will be deferred to
+ the first call of inflate (if the decompression does not complete on the
+ first call). If zalloc and zfree are set to Z_NULL, inflateInit updates
+ them to use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit does not perform any decompression.
+ Actual decompression will be done by inflate(). So next_in, and avail_in,
+ next_out, and avail_out are unused and unchanged. The current
+ implementation of inflateInit() does not process any header information --
+ that is deferred until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), then next_in and avail_in are updated
+ accordingly, and processing will resume at this point for the next call of
+ inflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there is
+ no more input data or no more space in the output buffer (see below about
+ the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating the next_* and avail_* values accordingly. If the
+ caller of inflate() does not provide both available input and available
+ output space, it is possible that there will be no progress made. The
+ application can consume the uncompressed output when it wants, for example
+ when the output buffer is full (avail_out == 0), or after each call of
+ inflate(). If inflate returns Z_OK and with zero avail_out, it must be
+ called again after making room in the output buffer because there might be
+ more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+ Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate()
+ stop if and when it gets to the next deflate block boundary. When decoding
+ the zlib or gzip format, this will cause inflate() to return immediately
+ after the header and before the first block. When doing a raw inflate,
+ inflate() will go ahead and process the first block, and will return when it
+ gets to the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ To assist in this, on return inflate() always sets strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64 if
+ inflate() is currently decoding the last block in the deflate stream, plus
+ 128 if inflate() returned immediately after decoding an end-of-block code or
+ decoding the complete header up to just before the first byte of the deflate
+ stream. The end-of-block will not be indicated until all of the uncompressed
+ data from that block has been written to strm->next_out. The number of
+ unused bits may in general be greater than seven, except when bit 7 of
+ data_type is set, in which case the number of unused bits will be less than
+ eight. data_type is set as noted here every time inflate() returns for all
+ flush options, and so can be used to determine the amount of currently
+ consumed input in bits.
+
+ The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+ end of each deflate block header is reached, before any actual data in that
+ block is decoded. This allows the caller to determine the length of the
+ deflate block header for later use in random access within a deflate block.
+ 256 is added to the value of strm->data_type when inflate() returns
+ immediately after reaching the end of the deflate block header.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step (a
+ single call of inflate), the parameter flush should be set to Z_FINISH. In
+ this case all pending input is processed and all pending output is flushed;
+ avail_out must be large enough to hold all of the uncompressed data for the
+ operation to complete. (The size of the uncompressed data may have been
+ saved by the compressor for this purpose.) The use of Z_FINISH is not
+ required to perform an inflation in one step. However it may be used to
+ inform inflate that a faster approach can be used for the single inflate()
+ call. Z_FINISH also informs inflate to not maintain a sliding window if the
+ stream completes, which reduces inflate's memory footprint. If the stream
+ does not complete, either because not all of the stream is provided or not
+ enough output space is provided, then a sliding window will be allocated and
+ inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+ been used.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the effects of the flush parameter in this implementation are
+ on the return value of inflate() as noted below, when inflate() returns early
+ when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+ memory for a sliding window when Z_FINISH is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the Adler-32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed Adler-32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically, if requested when
+ initializing with inflateInit2(). Any information contained in the gzip
+ header is not retained unless inflateGetHeader() is used. When processing
+ gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+ produced so far. The CRC-32 is checked against the gzip trailer, as is the
+ uncompressed length, modulo 2^32.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value, in which case strm->msg points to a string with a more specific
+ error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ next_in or next_out was Z_NULL, or the state was inadvertently written over
+ by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
+ if no progress was possible or if there was not enough room in the output
+ buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may
+ then call inflateSync() to look for a good compression block if a partial
+ recovery of the data is to be attempted.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
+ was inconsistent.
+*/
+
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields zalloc, zfree and opaque must be initialized before by the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ For the current implementation of deflate(), a windowBits value of 8 (a
+ window size of 256 bytes) is not supported. As a result, a request for 8
+ will result in 9 (a 512-byte window). In that case, providing 8 to
+ inflateInit2() will result in an error when the zlib header with 9 is
+ checked against the initialization of inflate(). The remedy is to not use 8
+ with deflateInit2() with this initialization, or at least in that case use 9
+ with inflateInit2().
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute a check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero), no
+ header crc, and the operating system will be set to the appropriate value,
+ if the operating system was determined at compile time. If a gzip stream is
+ being written, strm->adler is a CRC-32 instead of an Adler-32.
+
+ For raw deflate or gzip encoding, a request for a 256-byte window is
+ rejected as invalid, since only the zlib header provides a means of
+ transmitting the window size to the decompressor.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. The default value is 8. See zconf.h for total memory usage
+ as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
+ fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
+ strategy parameter only affects the compression ratio but not the
+ correctness of the compressed output even if it is not set appropriately.
+ Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+ decoder for special applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+ method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is
+ set to null if there is no error message. deflateInit2 does not perform any
+ compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. When using the zlib format, this
+ function must be called immediately after deflateInit, deflateInit2 or
+ deflateReset, and before any call of deflate. When doing raw deflate, this
+ function must be called either before any call of deflate, or immediately
+ after the completion of a deflate block, i.e. after all input has been
+ consumed and all output has been delivered when using any of the flush
+ options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
+ compressor and decompressor must use exactly the same dictionary (see
+ inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size
+ provided in deflateInit or deflateInit2. Thus the strings most likely to be
+ useful should be put at the end of the dictionary, not at the front. In
+ addition, the current implementation of deflate will use at most the window
+ size minus 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the Adler-32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler-32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ Adler-32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if not at a block boundary for raw deflate). deflateSetDictionary does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength));
+/*
+ Returns the sliding dictionary being maintained by deflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If deflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ deflateGetDictionary() may return a length less than the window size, even
+ when more than the window size in input has been provided. It may return up
+ to 258 bytes less in that case, due to how zlib's implementation of deflate
+ manages the sliding window and lookahead for matches, where matches can be
+ up to 258 bytes long. If the application needs the last window-size bytes of
+ input, then that would need to be saved by the application outside of zlib.
+
+ deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and can
+ consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit, but
+ does not free and reallocate the internal compression state. The stream
+ will leave the compression level and any other attributes that may have been
+ set unchanged.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2(). This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different strategy.
+ If the compression approach (which is a function of the level) or the
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1..3, and 4..9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
+
+ If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
+ not have enough output space to complete, then the parameter change will not
+ take effect. In this case, deflateParams() can be called again with the
+ same parameters and more output space to try again.
+
+ In order to assure a change in the parameters on the first try, the
+ deflate stream should be flushed using deflate() with Z_BLOCK or other flush
+ request until strm.avail_out is not zero, before calling deflateParams().
+ Then no more input data should be provided before the deflateParams() call.
+ If this is done, the old level and strategy will be applied to the data
+ compressed before deflateParams(), and the new level and strategy will be
+ applied to the the data compressed after deflateParams().
+
+ deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
+ state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
+ there was not enough output space to complete the compression of the
+ available input data before a change in the strategy or approach. Note that
+ in the case of a Z_BUF_ERROR, the parameters are not changed. A return
+ value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
+ retried with more output space.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit() or
+ deflateInit2(), and after deflateSetHeader(), if used. This would be used
+ to allocate an output buffer for deflation in a single pass, and so would be
+ called before deflate(). If that first deflate() call is provided the
+ sourceLen input bytes, an output buffer allocated to the size returned by
+ deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+ to return Z_STREAM_END. Note that it is possible for the compressed size to
+ be larger than the value returned by deflateBound() if flush options other
+ than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+ unsigned *pending,
+ int *bits));
+/*
+ deflatePending() returns the number of bytes and bits of output that have
+ been generated, but not yet provided in the available output. The bytes not
+ provided would be due to the available output space having being consumed.
+ The number of bits of output not provided are between 0 and 7, where they
+ await more bits to join them in order to fill out a full byte. If pending
+ or bits are Z_NULL, then those values are not set.
+
+ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the bits
+ leftover from a previous deflate stream when appending to it. As such, this
+ function can only be used for raw deflate, and must be used before the first
+ deflate() call after a deflateInit2() or deflateReset(). bits must be less
+ than or equal to 16, and that many of the least significant bits of value
+ will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+ room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be zero to request that inflate use the window size in
+ the zlib header of the compressed stream.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an Adler-32 or a CRC-32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
+ CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit2 does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit2() does not process any header information -- that is
+ deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler-32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called at any
+ time to set the dictionary. If the provided dictionary is smaller than the
+ window and there is already data in the window, then the provided dictionary
+ will amend what's there. The application must insure that the dictionary
+ that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler-32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength));
+/*
+ Returns the sliding dictionary being maintained by inflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If inflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a possible full flush point (see above
+ for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+ All full flush points have this pattern, but not all occurrences of this
+ pattern are full flush points.
+
+ inflateSync returns Z_OK if a possible full flush point has been found,
+ Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+ has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+ In the success case, the application may save the current current value of
+ total_in which indicates where valid compressed data was found. In the
+ error case, the application may repeatedly call inflateSync, providing more
+ input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate the internal decompression state. The
+ stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+ int windowBits));
+/*
+ This function is the same as inflateReset, but it also permits changing
+ the wrap and window size requests. The windowBits parameter is interpreted
+ the same as it is for inflateInit2. If the window size is changed, then the
+ memory allocated for the window is freed, and the window will be reallocated
+ by inflate() if needed.
+
+ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+ the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ If bits is negative, then the input stream bit buffer is emptied. Then
+ inflatePrime() can be called again to put bits in the buffer. This is used
+ to clear out bits leftover after feeding inflate a block description prior
+ to feeding inflate codes.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+ This function returns two values, one in the lower 16 bits of the return
+ value, and the other in the remaining upper bits, obtained by shifting the
+ return value down 16 bits. If the upper value is -1 and the lower value is
+ zero, then inflate() is currently decoding information outside of a block.
+ If the upper value is -1 and the lower value is non-zero, then inflate is in
+ the middle of a stored block, with the lower value equaling the number of
+ bytes from the input remaining to copy. If the upper value is not -1, then
+ it is the number of bits back from the current bit position in the input of
+ the code (literal or length/distance pair) currently being processed. In
+ that case the lower value is the number of bytes already emitted for that
+ code.
+
+ A code is being processed if inflate is waiting for more input to complete
+ decoding of the code, or if it has completed decoding but is waiting for
+ more output space to write the literal or match data.
+
+ inflateMark() is used to mark locations in the input data for random
+ access, which may be at bit positions, and to note those cases where the
+ output of a code may span boundaries of random access blocks. The current
+ location in the input stream can be determined from avail_in and data_type
+ as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+ inflateMark returns the value noted above, or -65536 if the provided
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
+ used to force inflate() to return immediately after header processing is
+ complete and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When any
+ of extra, name, or comment are not Z_NULL and the respective field is not
+ present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+ allocated, or Z_VERSION_ERROR if the version of the library does not match
+ the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *,
+ z_const unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is potentially more efficient than
+ inflate() for file i/o applications, in that it avoids copying between the
+ output and the sliding window by simply making the window itself the output
+ buffer. inflate() can be faster on modern CPUs when used with large
+ buffers. inflateBack() trusts the application to not change the output
+ buffer passed by the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free the
+ allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects only
+ the raw deflate stream to decompress. This is different from the default
+ behavior of inflate(), which expects a zlib header and trailer around the
+ deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero -- buf is ignored in that
+ case -- and inflateBack() will return a buffer error. inflateBack() will
+ call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
+ out() should return zero on success, or non-zero on failure. If out()
+ returns non-zero, inflateBack() will return with an error. Neither in() nor
+ out() are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+ in the deflate stream (in which case strm->msg is set to indicate the nature
+ of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+ In the case of Z_BUF_ERROR, an input or output error can be distinguished
+ using strm->next_in which will be Z_NULL only if in() returned an error. If
+ strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+ non-zero. (in() will always be called before out(), so strm->next_in is
+ assured to be defined if out() returns non-zero.) Note that inflateBack()
+ cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: ZLIB_DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the basic
+ stream-oriented functions. To simplify the interface, some default options
+ are assumed (compression level and memory usage, standard memory allocation
+ functions). The source code of these utility functions can be modified if
+ you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data. compress() is equivalent to compress2() with a level
+ parameter of Z_DEFAULT_COMPRESSION.
+
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before a
+ compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit, destLen
+ is the actual size of the uncompressed data.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
+ the case where there is not enough room, uncompress() will fill the output
+ buffer with the uncompressed data up to that point.
+*/
+
+ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong *sourceLen));
+/*
+ Same as uncompress, except that sourceLen is a pointer, where the
+ length of the source is *sourceLen. On return, *sourceLen is the number of
+ source bytes consumed.
+*/
+
+ /* gzip file access functions */
+
+/*
+ This library supports reading and writing files in gzip (.gz) format with
+ an interface similar to that of stdio, using the functions that start with
+ "gz". The gzip format is different from the zlib format. gzip is a gzip
+ wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
+
+ "a" can be used instead of "w" to request that the gzip stream that will
+ be written be appended to the file. "+" will result in an error, since
+ reading and writing to the same gzip file is not supported. The addition of
+ "x" when writing will create the file exclusively, which fails if the file
+ already exists. On systems that support it, the addition of "e" when
+ reading or writing will set the flag to close the file on an execve() call.
+
+ These functions, as well as gzip, will read and decode a sequence of gzip
+ streams in a file. The append function of gzopen() can be used to create
+ such a file. (Also see gzflush() for another way to do this.) When
+ appending, gzopen does not test whether the file begins with a gzip stream,
+ nor does it look for the end of the gzip streams to begin appending. gzopen
+ will simply append a gzip stream to the existing file.
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression. When
+ reading, this will be detected automatically by looking for the magic two-
+ byte gzip header.
+
+ gzopen returns NULL if the file could not be opened, if there was
+ insufficient memory to allocate the gzFile state, or if an invalid mode was
+ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+ errno can be checked to determine if the reason gzopen failed was that the
+ file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
+
+ The next call of gzclose on the returned gzFile will also close the file
+ descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+ fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+ mode);. The duplicated descriptor should be saved to avoid a leak, since
+ gzdopen does not close fd if it fails. If you are using fileno() to get the
+ file descriptor from a FILE *, then you will have to use dup() to avoid
+ double-close()ing the file descriptor. Both gzclose() and fclose() will
+ close the associated file descriptor, so they need to have different file
+ descriptors.
+
+ gzdopen returns NULL if there was insufficient memory to allocate the
+ gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+ provided, or '+' was provided), or if fd is -1. The file descriptor is not
+ used until the next gz* read, write, seek, or close operation, so gzdopen
+ will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
+
+ The new buffer size also affects the maximum length for gzprintf().
+
+ gzbuffer() returns 0 on success, or -1 on failure, such as being called
+ too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
+
+ gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
+ opened for writing, Z_ERRNO if there is an error writing the flushed data,
+ or Z_MEM_ERROR if there is a memory allocation error.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Read and decompress up to len uncompressed bytes from file into buf. If
+ the input file is not in gzip format, gzread copies the given number of
+ bytes into the buffer directly from the file.
+
+ After reaching the end of a gzip stream in the input, gzread will continue
+ to read, looking for another gzip stream. Any number of gzip streams may be
+ concatenated in the input file, and will all be decompressed by gzread().
+ If something other than a gzip stream is encountered after a gzip stream,
+ that remaining trailing garbage is ignored (and no error is returned).
+
+ gzread can be used to read a gzip file that is being concurrently written.
+ Upon reaching the end of the input, gzread will return with the available
+ data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+ gzclearerr can be used to clear the end of file indicator in order to permit
+ gzread to be tried again. Z_OK indicates that a gzip stream was completed
+ on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
+ middle of a gzip stream. Note that gzread does not return -1 in the event
+ of an incomplete gzip stream. This error is deferred until gzclose(), which
+ will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+ stream. Alternatively, gzerror can be used before gzclose to detect this
+ case.
+
+ gzread returns the number of uncompressed bytes actually read, less than
+ len for end of file, or -1 for error. If len is too large to fit in an int,
+ then nothing is read, -1 is returned, and the error state is set to
+ Z_STREAM_ERROR.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
+ gzFile file));
+/*
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
+
+ gzfread() returns the number of full items read of size size, or zero if
+ the end of the file was reached and a full item could not be read, or if
+ there was an error. gzerror() must be consulted if zero is returned in
+ order to determine if there was an error. If the multiplication of size and
+ nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
+ is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
+
+ In the event that the end of file is reached and only a partial item is
+ available at the end, i.e. the remaining uncompressed data length is not a
+ multiple of size, then the final partial item is nevertheless read into buf
+ and the end-of-file flag is set. The length of the partial item read is not
+ provided, but could be inferred from the result of gztell(). This behavior
+ is the same as the behavior of fread() implementations in common libraries,
+ but it prevents the direct use of gzfread() to read a concurrently written
+ file, resetting and retrying on end-of-file, when size is not 1.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
+/*
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
+ z_size_t nitems, gzFile file));
+/*
+ Compress and write nitems items of size size from buf to file, duplicating
+ the interface of stdio's fwrite(), with size_t request and return types. If
+ the library defines size_t, then z_size_t is identical to size_t. If not,
+ then z_size_t is an unsigned integer type that can contain a pointer.
+
+ gzfwrite() returns the number of full items written of size size, or zero
+ if there was an error. If the multiplication of size and nitems overflows,
+ i.e. the product does not fit in a z_size_t, then nothing is written, zero
+ is returned, and the error state is set to Z_STREAM_ERROR.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written, or a negative zlib error code in case
+ of error. The number of uncompressed bytes written is limited to 8191, or
+ one less than the buffer size given to gzbuffer(). The caller should assure
+ that this limit is not exceeded. If it is exceeded, then gzprintf() will
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
+ because the secure snprintf() or vsnprintf() functions were not available.
+ This can be determined using zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Compress and write the given null-terminated string s to file, excluding
+ the terminating null character.
+
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
+
+ gzgets returns buf which is a null-terminated string, or it returns NULL
+ for end-of-file or in case of error. If there was an error, the contents at
+ buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Compress and write c, converted to an unsigned char, into file. gzputc
+ returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Read and decompress one byte from file. gzgetc returns this byte or -1
+ in case of end of file or error. This is implemented as a macro for speed.
+ As such, it does not do all of the checking the other functions do. I.e.
+ it does not check to see if file is NULL, nor whether the structure file
+ points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
+ gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
+ fail if c is -1, and may fail if a character has been pushed but not read
+ yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
+ output buffer size of pushed characters is allowed. (See gzbuffer above.)
+ The pushed character will be discarded if the stream is repositioned with
+ gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
+
+ If the flush parameter is Z_FINISH, the remaining data is written and the
+ gzip stream is completed in the output. If gzwrite() is called again, a new
+ gzip stream will be started in the output. gzread() is able to read such
+ concatenated gzip streams.
+
+ gzflush should be called only when strictly necessary because it will
+ degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewind file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
+
+ If gzeof() returns true, then the read functions will return no more data,
+ unless the end-of-file indicator is reset by gzclearerr() and the input file
+ has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Return true (1) if file is being copied directly while reading, or false
+ (0) if file is a gzip stream being decompressed.
+
+ If the input file is empty, gzdirect() will return true, since the input
+ does not contain a gzip stream.
+
+ If gzdirect() is used immediately after gzopen() or gzdopen() it will
+ cause buffers to be allocated to allow reading the file to determine if it
+ is a gzip file. Therefore if gzbuffer() is used, it should be called before
+ gzdirect().
+
+ When writing, gzdirect() returns true (1) if transparent writing was
+ requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
+ gzdirect() is not needed when writing. Transparent writing must be
+ explicitly requested, so the application already knows the answer. When
+ linking statically, using gzdirect() will include all of the zlib code for
+ gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
+ cannot call gzerror with file, since its structures have been deallocated.
+ gzclose must not be called more than once on the same file, just as free
+ must not be called more than once on the same allocation.
+
+ gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+ file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+ last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+ Same as gzclose(), but gzclose_r() is only for use when reading, and
+ gzclose_w() is only for use when writing or appending. The advantage to
+ using these instead of gzclose() is that they avoid linking in zlib
+ compression or decompression code that is not used when only reading or only
+ writing respectively. If gzclose() is used, then both compression and
+ decompression code will be included the application when linking to a static
+ zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
+
+ The application must not modify the returned string. Future calls to
+ this function may invalidate the previously returned string. If file is
+ closed, then the string previously returned by gzerror will no longer be
+ available.
+
+ gzerror() should be used to distinguish errors from end-of-file for those
+ functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clear the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the compression
+ library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
+ much faster.
+
+ Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,
+ z_size_t len));
+/*
+ Same as adler32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
+
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,
+ z_size_t len));
+/*
+ Same as crc32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
+
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op().
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#ifdef Z_PREFIX_SET
+# define z_deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define z_inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#else
+# define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#endif
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure. Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro. The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously. They can
+ * only be used by the gzgetc() macro. You have been warned.
+ */
+struct gzFile_s {
+ unsigned have;
+ unsigned char *next;
+ z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+# define z_gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#else
+# define gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+ ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+# ifdef Z_PREFIX_SET
+# define z_gzopen z_gzopen64
+# define z_gzseek z_gzseek64
+# define z_gztell z_gztell64
+# define z_gzoffset z_gzoffset64
+# define z_adler32_combine z_adler32_combine64
+# define z_crc32_combine z_crc32_combine64
+# define z_crc32_combine_gen z_crc32_combine_gen64
+# else
+# define gzopen gzopen64
+# define gzseek gzseek64
+# define gztell gztell64
+# define gzoffset gzoffset64
+# define adler32_combine adler32_combine64
+# define crc32_combine crc32_combine64
+# define crc32_combine_gen crc32_combine_gen64
+# endif
+# ifndef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
+# endif
+#else
+ ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* undocumented functions */
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
+ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
+ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp));
+ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
+ const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+ const char *format,
+ va_list va));
+# endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/libmariadb/external/zlib/zlib.map b/libmariadb/external/zlib/zlib.map
new file mode 100644
index 00000000..31544f2e
--- /dev/null
+++ b/libmariadb/external/zlib/zlib.map
@@ -0,0 +1,100 @@
+ZLIB_1.2.0 {
+ global:
+ compressBound;
+ deflateBound;
+ inflateBack;
+ inflateBackEnd;
+ inflateBackInit_;
+ inflateCopy;
+ local:
+ deflate_copyright;
+ inflate_copyright;
+ inflate_fast;
+ inflate_table;
+ zcalloc;
+ zcfree;
+ z_errmsg;
+ gz_error;
+ gz_intmax;
+ _*;
+};
+
+ZLIB_1.2.0.2 {
+ gzclearerr;
+ gzungetc;
+ zlibCompileFlags;
+} ZLIB_1.2.0;
+
+ZLIB_1.2.0.8 {
+ deflatePrime;
+} ZLIB_1.2.0.2;
+
+ZLIB_1.2.2 {
+ adler32_combine;
+ crc32_combine;
+ deflateSetHeader;
+ inflateGetHeader;
+} ZLIB_1.2.0.8;
+
+ZLIB_1.2.2.3 {
+ deflateTune;
+ gzdirect;
+} ZLIB_1.2.2;
+
+ZLIB_1.2.2.4 {
+ inflatePrime;
+} ZLIB_1.2.2.3;
+
+ZLIB_1.2.3.3 {
+ adler32_combine64;
+ crc32_combine64;
+ gzopen64;
+ gzseek64;
+ gztell64;
+ inflateUndermine;
+} ZLIB_1.2.2.4;
+
+ZLIB_1.2.3.4 {
+ inflateReset2;
+ inflateMark;
+} ZLIB_1.2.3.3;
+
+ZLIB_1.2.3.5 {
+ gzbuffer;
+ gzoffset;
+ gzoffset64;
+ gzclose_r;
+ gzclose_w;
+} ZLIB_1.2.3.4;
+
+ZLIB_1.2.5.1 {
+ deflatePending;
+} ZLIB_1.2.3.5;
+
+ZLIB_1.2.5.2 {
+ deflateResetKeep;
+ gzgetc_;
+ inflateResetKeep;
+} ZLIB_1.2.5.1;
+
+ZLIB_1.2.7.1 {
+ inflateGetDictionary;
+ gzvprintf;
+} ZLIB_1.2.5.2;
+
+ZLIB_1.2.9 {
+ inflateCodesUsed;
+ inflateValidate;
+ uncompress2;
+ gzfread;
+ gzfwrite;
+ deflateGetDictionary;
+ adler32_z;
+ crc32_z;
+} ZLIB_1.2.7.1;
+
+ZLIB_1.2.12 {
+ crc32_combine_gen;
+ crc32_combine_gen64;
+ crc32_combine_op;
+} ZLIB_1.2.9;
diff --git a/libmariadb/external/zlib/zlib.pc.cmakein b/libmariadb/external/zlib/zlib.pc.cmakein
new file mode 100644
index 00000000..3017c695
--- /dev/null
+++ b/libmariadb/external/zlib/zlib.pc.cmakein
@@ -0,0 +1,13 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@/bin
+libdir=@CMAKE_INSTALL_PREFIX@/lib
+sharedlibdir=@CMAKE_INSTALL_PREFIX@/lib
+includedir=@CMAKE_INSTALL_PREFIX@/include
+
+Name: zlib
+Description: zlib compression library
+Version: @ZLIB_VERSION@
+
+Requires:
+Libs: -L${libdir} -L${sharedlibdir} -lz
+Cflags: -I${includedir}
diff --git a/libmariadb/external/zlib/zlib.pc.in b/libmariadb/external/zlib/zlib.pc.in
new file mode 100644
index 00000000..7e5acf9c
--- /dev/null
+++ b/libmariadb/external/zlib/zlib.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+sharedlibdir=@sharedlibdir@
+includedir=@includedir@
+
+Name: zlib
+Description: zlib compression library
+Version: @VERSION@
+
+Requires:
+Libs: -L${libdir} -L${sharedlibdir} -lz
+Cflags: -I${includedir}
diff --git a/libmariadb/external/zlib/zlib2ansi b/libmariadb/external/zlib/zlib2ansi
new file mode 100755
index 00000000..15e3e165
--- /dev/null
+++ b/libmariadb/external/zlib/zlib2ansi
@@ -0,0 +1,152 @@
+#!/usr/bin/perl
+
+# Transform K&R C function definitions into ANSI equivalent.
+#
+# Author: Paul Marquess
+# Version: 1.0
+# Date: 3 October 2006
+
+# TODO
+#
+# Asumes no function pointer parameters. unless they are typedefed.
+# Assumes no literal strings that look like function definitions
+# Assumes functions start at the beginning of a line
+
+use strict;
+use warnings;
+
+local $/;
+$_ = <>;
+
+my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments
+
+my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ;
+my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ;
+my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ;
+
+
+while (s/^
+ ( # Start $1
+ ( # Start $2
+ .*? # Minimal eat content
+ ( ^ \w [\w\s\*]+ ) # $3 -- function name
+ \s* # optional whitespace
+ ) # $2 - Matched up to before parameter list
+
+ \( \s* # Literal "(" + optional whitespace
+ ( [^\)]+ ) # $4 - one or more anythings except ")"
+ \s* \) # optional whitespace surrounding a Literal ")"
+
+ ( (?: $dList )+ ) # $5
+
+ $sp ^ { # literal "{" at start of line
+ ) # Remember to $1
+ //xsom
+ )
+{
+ my $all = $1 ;
+ my $prefix = $2;
+ my $param_list = $4 ;
+ my $params = $5;
+
+ StripComments($params);
+ StripComments($param_list);
+ $param_list =~ s/^\s+//;
+ $param_list =~ s/\s+$//;
+
+ my $i = 0 ;
+ my %pList = map { $_ => $i++ }
+ split /\s*,\s*/, $param_list;
+ my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ;
+
+ my @params = split /\s*;\s*/, $params;
+ my @outParams = ();
+ foreach my $p (@params)
+ {
+ if ($p =~ /,/)
+ {
+ my @bits = split /\s*,\s*/, $p;
+ my $first = shift @bits;
+ $first =~ s/^\s*//;
+ push @outParams, $first;
+ $first =~ /^(\w+\s*)/;
+ my $type = $1 ;
+ push @outParams, map { $type . $_ } @bits;
+ }
+ else
+ {
+ $p =~ s/^\s+//;
+ push @outParams, $p;
+ }
+ }
+
+
+ my %tmp = map { /$pMatch/; $_ => $pList{$1} }
+ @outParams ;
+
+ @outParams = map { " $_" }
+ sort { $tmp{$a} <=> $tmp{$b} }
+ @outParams ;
+
+ print $prefix ;
+ print "(\n" . join(",\n", @outParams) . ")\n";
+ print "{" ;
+
+}
+
+# Output any trailing code.
+print ;
+exit 0;
+
+
+sub StripComments
+{
+
+ no warnings;
+
+ # Strip C & C++ coments
+ # From the perlfaq
+ $_[0] =~
+
+ s{
+ /\* ## Start of /* ... */ comment
+ [^*]*\*+ ## Non-* followed by 1-or-more *'s
+ (
+ [^/*][^*]*\*+
+ )* ## 0-or-more things which don't start with /
+ ## but do end with '*'
+ / ## End of /* ... */ comment
+
+ | ## OR C++ Comment
+ // ## Start of C++ comment //
+ [^\n]* ## followed by 0-or-more non end of line characters
+
+ | ## OR various things which aren't comments:
+
+ (
+ " ## Start of " ... " string
+ (
+ \\. ## Escaped char
+ | ## OR
+ [^"\\] ## Non "\
+ )*
+ " ## End of " ... " string
+
+ | ## OR
+
+ ' ## Start of ' ... ' string
+ (
+ \\. ## Escaped char
+ | ## OR
+ [^'\\] ## Non '\
+ )*
+ ' ## End of ' ... ' string
+
+ | ## OR
+
+ . ## Anything other char
+ [^/"'\\]* ## Chars which doesn't start a comment, string or escape
+ )
+ }{$2}gxs;
+
+}
diff --git a/libmariadb/external/zlib/zutil.c b/libmariadb/external/zlib/zutil.c
new file mode 100644
index 00000000..9543ae82
--- /dev/null
+++ b/libmariadb/external/zlib/zutil.c
@@ -0,0 +1,327 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2017 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+#ifndef Z_SOLO
+# include "gzguts.h"
+#endif
+
+z_const char * const z_errmsg[10] = {
+ (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */
+ (z_const char *)"stream end", /* Z_STREAM_END 1 */
+ (z_const char *)"", /* Z_OK 0 */
+ (z_const char *)"file error", /* Z_ERRNO (-1) */
+ (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */
+ (z_const char *)"data error", /* Z_DATA_ERROR (-3) */
+ (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */
+ (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */
+ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
+ (z_const char *)""
+};
+
+
+const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+ uLong flags;
+
+ flags = 0;
+ switch ((int)(sizeof(uInt))) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch ((int)(sizeof(uLong))) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch ((int)(sizeof(voidpf))) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch ((int)(sizeof(z_off_t))) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef ZLIB_DEBUG
+ flags += 1 << 8;
+#endif
+ /*
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+ */
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef ZLIB_DEBUG
+#include <stdlib.h>
+# ifndef verbose
+# define verbose 0
+# endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error(m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+ int err;
+{
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
+ /* The older Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifndef Z_SOLO
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf;
+ ulg bsize = (ulg)items*size;
+
+ (void)opaque;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
+{
+ int n;
+
+ (void)opaque;
+
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size)
+{
+ (void)opaque;
+ return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
+{
+ (void)opaque;
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc(opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ (void)opaque;
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree(opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ (void)opaque;
+ free(ptr);
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/libmariadb/external/zlib/zutil.h b/libmariadb/external/zlib/zutil.h
new file mode 100644
index 00000000..0bc7f4ec
--- /dev/null
+++ b/libmariadb/external/zlib/zutil.h
@@ -0,0 +1,275 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#if defined(STDC) && !defined(Z_SOLO)
+# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (ULONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long
+# elif (ULLONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long long
+# elif (UINT_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned
+# endif
+#endif
+
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# ifndef Z_SOLO
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 1
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 2
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef __370__
+# if __TARGET_LIB__ < 0x20000000
+# define OS_CODE 4
+# elif __TARGET_LIB__ < 0x40000000
+# define OS_CODE 11
+# else
+# define OS_CODE 8
+# endif
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 5
+#endif
+
+#ifdef OS2
+# define OS_CODE 6
+# if defined(M_I86) && !defined(Z_SOLO)
+# include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 7
+# ifndef Z_SOLO
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __acorn
+# define OS_CODE 13
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+# define OS_CODE 10
+#endif
+
+#ifdef _BEOS_
+# define OS_CODE 16
+#endif
+
+#ifdef __TOS_OS400__
+# define OS_CODE 18
+#endif
+
+#ifdef __APPLE__
+# define OS_CODE 19
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+#if defined(__BORLANDC__) && !defined(MSDOS)
+ #pragma warn -8004
+ #pragma warn -8008
+ #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && \
+ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 3 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(pyr) || defined(Z_SOLO)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef ZLIB_DEBUG
+# include <stdio.h>
+ extern int ZLIB_INTERNAL z_verbose;
+ extern void ZLIB_INTERNAL z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+#ifndef Z_SOLO
+ voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+ unsigned size));
+ void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
+#endif
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+#endif /* ZUTIL_H */
diff --git a/libmariadb/include/CMakeLists.txt b/libmariadb/include/CMakeLists.txt
new file mode 100644
index 00000000..b9eed535
--- /dev/null
+++ b/libmariadb/include/CMakeLists.txt
@@ -0,0 +1,41 @@
+SET(MARIADB_CLIENT_INCLUDES ${CC_SOURCE_DIR}/include/mariadb_com.h
+ ${CC_SOURCE_DIR}/include/mysql.h
+ ${CC_SOURCE_DIR}/include/mariadb_stmt.h
+ ${CC_SOURCE_DIR}/include/ma_pvio.h
+ ${CC_SOURCE_DIR}/include/ma_tls.h
+ ${CC_BINARY_DIR}/include/mariadb_version.h
+ ${CC_SOURCE_DIR}/include/ma_list.h
+ ${CC_SOURCE_DIR}/include/errmsg.h
+ ${CC_SOURCE_DIR}/include/mariadb_dyncol.h
+ ${CC_SOURCE_DIR}/include/mariadb_ctype.h
+ ${CC_SOURCE_DIR}/include/mariadb_rpl.h
+ )
+IF(NOT IS_SUBPROJECT)
+ SET(MARIADB_CLIENT_INCLUDES ${MARIADB_CLIENT_INCLUDES}
+ ${CC_SOURCE_DIR}/include/mysqld_error.h
+ )
+ENDIF()
+SET(MYSQL_ADDITIONAL_INCLUDES
+ ${CC_SOURCE_DIR}/include/mysql/client_plugin.h
+ ${CC_SOURCE_DIR}/include/mysql/plugin_auth_common.h
+ ${CC_SOURCE_DIR}/include/mysql/plugin_auth.h
+ )
+SET(MARIADB_ADDITIONAL_INCLUDES
+ ${CC_SOURCE_DIR}/include/mariadb/ma_io.h
+ )
+IF(WIN32)
+ SET(WIX_INCLUDES ${MARIADB_CLIENT_INCLUDES} ${MARIADB_ADDITIONAL_INCLUDES} ${MYSQL_ADDITIONAL_INCLUDES} PARENT_SCOPE)
+ENDIF()
+
+INSTALL(FILES
+ ${MARIADB_CLIENT_INCLUDES}
+ DESTINATION ${INSTALL_INCLUDEDIR}
+ COMPONENT Development)
+INSTALL(FILES
+ ${MYSQL_ADDITIONAL_INCLUDES}
+ DESTINATION ${INSTALL_INCLUDEDIR}/mysql
+ COMPONENT Development)
+INSTALL(FILES
+ ${MARIADB_ADDITIONAL_INCLUDES}
+ DESTINATION ${INSTALL_INCLUDEDIR}/mariadb
+ COMPONENT Development)
diff --git a/libmariadb/include/errmsg.h b/libmariadb/include/errmsg.h
new file mode 100644
index 00000000..4afe8e8a
--- /dev/null
+++ b/libmariadb/include/errmsg.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2012-2016 SkySQL AB, MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Error messages for mysql clients */
+/* error messages for the demon is in share/language/errmsg.sys */
+#ifndef _errmsg_h_
+#define _errmsg_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void init_client_errs(void);
+extern const char *client_errors[]; /* Error messages */
+extern const char *mariadb_client_errors[]; /* Error messages */
+#ifdef __cplusplus
+}
+#endif
+
+#define CR_MIN_ERROR 2000 /* For easier client code */
+#define CR_MAX_ERROR 2999
+#define CER_MIN_ERROR 5000
+#define CER_MAX_ERROR 5999
+#define CLIENT_ERRMAP 2 /* Errormap used by ma_error() */
+
+#define ER_UNKNOWN_ERROR_CODE "Unknown or undefined error code (%d)"
+
+#define CR_UNKNOWN_ERROR 2000
+#define CR_SOCKET_CREATE_ERROR 2001
+#define CR_CONNECTION_ERROR 2002
+#define CR_CONN_HOST_ERROR 2003 /* never sent to a client, message only */
+#define CR_IPSOCK_ERROR 2004
+#define CR_UNKNOWN_HOST 2005
+#define CR_SERVER_GONE_ERROR 2006 /* disappeared _between_ queries */
+#define CR_VERSION_ERROR 2007
+#define CR_OUT_OF_MEMORY 2008
+#define CR_WRONG_HOST_INFO 2009
+#define CR_LOCALHOST_CONNECTION 2010
+#define CR_TCP_CONNECTION 2011
+#define CR_SERVER_HANDSHAKE_ERR 2012
+#define CR_SERVER_LOST 2013 /* disappeared _during_ a query */
+#define CR_COMMANDS_OUT_OF_SYNC 2014
+#define CR_NAMEDPIPE_CONNECTION 2015
+#define CR_NAMEDPIPEWAIT_ERROR 2016
+#define CR_NAMEDPIPEOPEN_ERROR 2017
+#define CR_NAMEDPIPESETSTATE_ERROR 2018
+#define CR_CANT_READ_CHARSET 2019
+#define CR_NET_PACKET_TOO_LARGE 2020
+#define CR_SSL_CONNECTION_ERROR 2026
+#define CR_MALFORMED_PACKET 2027
+#define CR_NO_PREPARE_STMT 2030
+#define CR_PARAMS_NOT_BOUND 2031
+#define CR_INVALID_PARAMETER_NO 2034
+#define CR_INVALID_BUFFER_USE 2035
+#define CR_UNSUPPORTED_PARAM_TYPE 2036
+
+#define CR_SHARED_MEMORY_CONNECTION 2037
+#define CR_SHARED_MEMORY_CONNECT_ERROR 2038
+
+#define CR_CONN_UNKNOWN_PROTOCOL 2047
+#define CR_SECURE_AUTH 2049
+#define CR_NO_DATA 2051
+#define CR_NO_STMT_METADATA 2052
+#define CR_NOT_IMPLEMENTED 2054
+#define CR_SERVER_LOST_EXTENDED 2055 /* never sent to a client, message only */
+#define CR_STMT_CLOSED 2056
+#define CR_NEW_STMT_METADATA 2057
+#define CR_ALREADY_CONNECTED 2058
+#define CR_AUTH_PLUGIN_CANNOT_LOAD 2059
+#define CR_DUPLICATE_CONNECTION_ATTR 2060
+#define CR_AUTH_PLUGIN_ERR 2061
+/* Always last, if you add new error codes please update the
+ value for CR_MYSQL_LAST_ERROR */
+#define CR_MYSQL_LAST_ERROR CR_AUTH_PLUGIN_ERR
+
+/*
+ * MariaDB Connector/C errors:
+ */
+#define CR_EVENT_CREATE_FAILED 5000
+#define CR_BIND_ADDR_FAILED 5001
+#define CR_ASYNC_NOT_SUPPORTED 5002
+#define CR_FUNCTION_NOT_SUPPORTED 5003
+#define CR_FILE_NOT_FOUND 5004
+#define CR_FILE_READ 5005
+#define CR_BULK_WITHOUT_PARAMETERS 5006
+#define CR_INVALID_STMT 5007
+#define CR_VERSION_MISMATCH 5008
+#define CR_INVALID_PARAMETER 5009
+#define CR_PLUGIN_NOT_ALLOWED 5010
+#define CR_CONNSTR_PARSE_ERROR 5011
+#define CR_ERR_LOAD_PLUGIN 5012
+#define CR_ERR_NET_READ 5013
+#define CR_ERR_NET_WRITE 5014
+#define CR_ERR_NET_UNCOMPRESS 5015
+#define CR_ERR_STMT_PARAM_CALLBACK 5016
+#define CR_ERR_BINLOG_UNCOMPRESS 5017
+#define CR_ERR_CHECKSUM_VERIFICATION_ERROR 5018
+#define CR_ERR_UNSUPPORTED_BINLOG_FORMAT 5019
+#define CR_UNKNOWN_BINLOG_EVENT 5020
+#define CR_BINLOG_ERROR 5021
+#define CR_BINLOG_INVALID_FILE 5022
+#define CR_BINLOG_SEMI_SYNC_ERROR 5023
+
+/* Always last, if you add new error codes please update the
+ value for CR_MARIADB_LAST_ERROR */
+#define CR_MARIADB_LAST_ERROR CR_BINLOG_INVALID_FILE
+
+#endif
+
+#define IS_MYSQL_ERROR(code) ((code) > CR_MIN_ERROR && (code) <= CR_MYSQL_LAST_ERROR)
+#define IS_MARIADB_ERROR(code) ((code) > CER_MIN_ERROR && (code) <= CR_MARIADB_LAST_ERROR)
+
+#define ER(code) IS_MYSQL_ERROR((code)) ? client_errors[(code) - CR_MIN_ERROR] : \
+ IS_MARIADB_ERROR((code)) ? mariadb_client_errors[(code) - CER_MIN_ERROR] : \
+ "Unknown or undefined error code"
+#define CER(code) ER((code))
+
diff --git a/libmariadb/include/ma_common.h b/libmariadb/include/ma_common.h
new file mode 100644
index 00000000..1ac0cb68
--- /dev/null
+++ b/libmariadb/include/ma_common.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2013 by MontyProgram AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* defines for the libmariadb library */
+
+#ifndef _ma_common_h
+#define _ma_common_h
+
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <ma_hashtbl.h>
+
+enum enum_multi_status {
+ COM_MULTI_OFF= 0,
+ COM_MULTI_CANCEL,
+ COM_MULTI_ENABLED,
+ COM_MULTI_DISABLED,
+ COM_MULTI_END
+};
+
+
+typedef enum {
+ ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */
+ WAIT_FOR_QUERY, /* heuristics is enabled, not sending files */
+ ACCEPT_FILE_REQUEST /* heuristics is enabled, ready to send a file */
+} auto_local_infile_state;
+
+typedef struct st_mariadb_db_driver
+{
+ struct st_mariadb_client_plugin_DB *plugin;
+ char *name;
+ void *buffer;
+} MARIADB_DB_DRIVER;
+
+struct mysql_async_context;
+
+struct st_mysql_options_extension {
+ char *plugin_dir;
+ char *default_auth;
+ char *ssl_crl;
+ char *ssl_crlpath;
+ char *server_public_key_path;
+ struct mysql_async_context *async_context;
+ MA_HASHTBL connect_attrs;
+ size_t connect_attrs_len;
+ void (*report_progress)(const MYSQL *mysql,
+ unsigned int stage,
+ unsigned int max_stage,
+ double progress,
+ const char *proc_info,
+ unsigned int proc_info_length);
+ MARIADB_DB_DRIVER *db_driver;
+ char *tls_fp; /* finger print of server certificate */
+ char *tls_fp_list; /* white list of finger prints */
+ char *tls_pw; /* password for encrypted certificates */
+ my_bool multi_command; /* indicates if client wants to send multiple
+ commands in one packet */
+ char *url; /* for connection handler we need to save URL for reconnect */
+ unsigned int tls_cipher_strength;
+ char *tls_version;
+ my_bool read_only;
+ char *connection_handler;
+ my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
+ MA_HASHTBL userdata;
+ char *server_public_key;
+ char *proxy_header;
+ size_t proxy_header_len;
+ int (*io_wait)(my_socket handle, my_bool is_read, int timeout);
+ my_bool skip_read_response;
+ char *restricted_auth;
+ char *rpl_host;
+ unsigned short rpl_port;
+ void (*status_callback)(void *ptr, enum enum_mariadb_status_info type, ...);
+ void *status_data;
+ my_bool tls_verify_server_cert;
+};
+
+typedef struct st_connection_handler
+{
+ struct st_ma_connection_plugin *plugin;
+ void *data;
+ my_bool active;
+ my_bool free_data;
+} MA_CONNECTION_HANDLER;
+
+struct st_mariadb_net_extension {
+ enum enum_multi_status multi_status;
+ int extended_errno;
+ ma_compress_ctx *compression_ctx;
+ MARIADB_COMPRESSION_PLUGIN *compression_plugin;
+};
+
+struct st_mariadb_session_state
+{
+ LIST *list,
+ *current;
+};
+
+struct st_mariadb_extension {
+ MA_CONNECTION_HANDLER *conn_hdlr;
+ struct st_mariadb_session_state session_state[SESSION_TRACK_TYPES];
+ unsigned long mariadb_client_flag; /* MariaDB specific client flags */
+ unsigned long mariadb_server_capabilities; /* MariaDB specific server capabilities */
+ my_bool auto_local_infile;
+};
+
+#define OPT_EXT_VAL(a,key) \
+ (((a)->options.extension && (a)->options.extension->key) ?\
+ (a)->options.extension->key : 0)
+
+#endif
+
+
+typedef struct st_mariadb_field_extension
+{
+ MARIADB_CONST_STRING metadata[MARIADB_FIELD_ATTR_LAST+1]; /* 10.5 */
+} MA_FIELD_EXTENSION;
diff --git a/libmariadb/include/ma_compress.h b/libmariadb/include/ma_compress.h
new file mode 100644
index 00000000..a1467452
--- /dev/null
+++ b/libmariadb/include/ma_compress.h
@@ -0,0 +1,48 @@
+/************************************************************************************
+ Copyright (C) 2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+*************************************************************************************/
+#ifndef __ma_compress_h__
+
+#include <ma_sys.h>
+
+#define COMPRESSION_LEVEL_DEFAULT INT_MAX
+
+#define compression_plugin(net) (net)->extension->compression_plugin
+#define compression_ctx(net) (net)->extension->compression_ctx
+
+typedef struct {
+ void *compress_ctx;
+ void *decompress_ctx;
+ int compression_level;
+ void *extra; /* reserved */
+} ma_compress_ctx;
+
+enum enum_ma_compression_algorithm {
+ COMPRESSION_NONE= 0,
+ COMPRESSION_ZLIB,
+ COMPRESSION_ZSTD,
+ COMPRESSION_UNKNOWN
+};
+
+const char *_mariadb_compression_algorithm_str(enum enum_ma_compression_algorithm algorithm);
+my_bool _mariadb_compress(NET *net, unsigned char *, size_t *, size_t *);
+my_bool _mariadb_uncompress(NET *net, unsigned char *, size_t *, size_t *);
+unsigned char *_mariadb_compress_alloc(NET *net, const unsigned char *packet, size_t *len, size_t *complen);
+
+#endif
diff --git a/libmariadb/include/ma_config.h.in b/libmariadb/include/ma_config.h.in
new file mode 100644
index 00000000..c5c758dc
--- /dev/null
+++ b/libmariadb/include/ma_config.h.in
@@ -0,0 +1,150 @@
+
+/*
+ * Include file constants (processed in LibmysqlIncludeFiles.txt 1
+ */
+#cmakedefine HAVE_OPENSSL_APPLINK_C 1
+#cmakedefine HAVE_ALLOCA_H 1
+#cmakedefine HAVE_BIGENDIAN 1
+#cmakedefine HAVE_SETLOCALE 1
+#cmakedefine HAVE_NL_LANGINFO 1
+#cmakedefine HAVE_DLFCN_H 1
+#cmakedefine HAVE_FCNTL_H 1
+#cmakedefine HAVE_FLOAT_H 1
+#cmakedefine HAVE_LIMITS_H 1
+#cmakedefine HAVE_LINUX_LIMITS_H 1
+#cmakedefine HAVE_PWD_H 1
+#cmakedefine HAVE_SELECT_H 1
+#cmakedefine HAVE_STDDEF_H 1
+#cmakedefine HAVE_STDINT_H 1
+#cmakedefine HAVE_STDLIB_H 1
+#cmakedefine HAVE_STRING_H 1
+#cmakedefine HAVE_SYS_IOCTL_H 1
+#cmakedefine HAVE_SYS_SELECT_H 1
+#cmakedefine HAVE_SYS_SOCKET_H 1
+#cmakedefine HAVE_SYS_STREAM_H 1
+#cmakedefine HAVE_SYS_STAT_H 1
+#cmakedefine HAVE_SYS_SYSCTL_H 1
+#cmakedefine HAVE_SYS_TYPES_H 1
+#cmakedefine HAVE_SYS_UN_H 1
+#cmakedefine HAVE_UNISTD_H 1
+#cmakedefine HAVE_UCONTEXT_H 1
+
+/*
+ * function definitions - processed in LibmysqlFunctions.txt
+ */
+
+#cmakedefine HAVE_DLERROR 1
+#cmakedefine HAVE_DLOPEN 1
+#cmakedefine HAVE_GETPWUID 1
+#cmakedefine HAVE_MEMCPY 1
+#cmakedefine HAVE_POLL 1
+#cmakedefine HAVE_STRTOK_R 1
+#cmakedefine HAVE_STRTOL 1
+#cmakedefine HAVE_STRTOLL 1
+#cmakedefine HAVE_STRTOUL 1
+#cmakedefine HAVE_STRTOULL 1
+#cmakedefine HAVE_TELL 1
+#cmakedefine HAVE_THR_SETCONCURRENCY 1
+#cmakedefine HAVE_THR_YIELD 1
+#cmakedefine HAVE_VASPRINTF 1
+#cmakedefine HAVE_VSNPRINTF 1
+#cmakedefine HAVE_CUSERID 1
+
+/*
+ * types and sizes
+ */
+
+
+#cmakedefine SIZEOF_CHARP @SIZEOF_CHARP@
+#if defined(SIZEOF_CHARP)
+# define HAVE_CHARP 1
+#endif
+
+
+#cmakedefine SIZEOF_INT @SIZEOF_INT@
+#if defined(SIZEOF_INT)
+# define HAVE_INT 1
+#endif
+
+#cmakedefine SIZEOF_LONG @SIZEOF_LONG@
+#if defined(SIZEOF_LONG)
+# define HAVE_LONG 1
+#endif
+
+#cmakedefine SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@
+#if defined(SIZEOF_LONG_LONG)
+# define HAVE_LONG_LONG 1
+#endif
+
+
+#cmakedefine SIZEOF_SIZE_T @SIZEOF_SIZE_T@
+#if defined(SIZEOF_SIZE_T)
+# define HAVE_SIZE_T 1
+#endif
+
+
+#cmakedefine SIZEOF_UINT @SIZEOF_UINT@
+#if defined(SIZEOF_UINT)
+# define HAVE_UINT 1
+#endif
+
+#cmakedefine SIZEOF_USHORT @SIZEOF_USHORT@
+#if defined(SIZEOF_USHORT)
+# define HAVE_USHORT 1
+#endif
+
+#cmakedefine SIZEOF_ULONG @SIZEOF_ULONG@
+#if defined(SIZEOF_ULONG)
+# define HAVE_ULONG 1
+#endif
+
+#cmakedefine SIZEOF_INT8 @SIZEOF_INT8@
+#if defined(SIZEOF_INT8)
+# define HAVE_INT8 1
+#endif
+#cmakedefine SIZEOF_UINT8 @SIZEOF_UINT8@
+#if defined(SIZEOF_UINT8)
+# define HAVE_UINT8 1
+#endif
+
+#cmakedefine SIZEOF_INT16 @SIZEOF_INT16@
+#if defined(SIZEOF_INT16)
+# define HAVE_INT16 1
+#endif
+#cmakedefine SIZEOF_UINT16 @SIZEOF_UINT16@
+#if defined(SIZEOF_UINT16)
+# define HAVE_UINT16 1
+#endif
+
+#cmakedefine SIZEOF_INT32 @SIZEOF_INT32@
+#if defined(SIZEOF_INT32)
+# define HAVE_INT32 1
+#endif
+#cmakedefine SIZEOF_UINT32 @SIZEOF_UINT32@
+#if defined(SIZEOF_UINT32)
+# define HAVE_UINT32 1
+#endif
+
+#cmakedefine SIZEOF_INT64 @SIZEOF_INT64@
+#if defined(SIZEOF_INT64)
+# define HAVE_INT64 1
+#endif
+#cmakedefine SIZEOF_UINT64 @SIZEOF_UINT64@
+#if defined(SIZEOF_UINT64)
+# define HAVE_UINT64 1
+#endif
+
+#cmakedefine SIZEOF_SOCKLEN_T @SIZEOF_SOCKLEN_T@
+#if defined(SIZEOF_SOCKLEN_T)
+# define HAVE_SOCKLEN_T 1
+#endif
+
+#cmakedefine SOCKET_SIZE_TYPE @SOCKET_SIZE_TYPE@
+
+#define LOCAL_INFILE_MODE_OFF 0
+#define LOCAL_INFILE_MODE_ON 1
+#define LOCAL_INFILE_MODE_AUTO 2
+#define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_@ENABLED_LOCAL_INFILE@
+
+#define MARIADB_DEFAULT_CHARSET "@DEFAULT_CHARSET@"
+
diff --git a/libmariadb/include/ma_context.h b/libmariadb/include/ma_context.h
new file mode 100644
index 00000000..0ad7f68b
--- /dev/null
+++ b/libmariadb/include/ma_context.h
@@ -0,0 +1,242 @@
+/*
+ Copyright 2011 Kristian Nielsen and Monty Program Ab
+ 2015, 2022 MariaDB Corporation AB
+
+ This file is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ Simple API for spawning a co-routine, to be used for async libmysqlclient.
+
+ Idea is that by implementing this interface using whatever facilities are
+ available for given platform, we can use the same code for the generic
+ libmysqlclient-async code.
+
+ (This particular implementation uses Posix ucontext swapcontext().)
+*/
+
+#ifdef _WIN32
+#define MY_CONTEXT_USE_WIN32_FIBERS 1
+#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__x86_64__) && !defined(__ILP32__)
+#define MY_CONTEXT_USE_X86_64_GCC_ASM
+#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__)
+#define MY_CONTEXT_USE_I386_GCC_ASM
+#elif defined(HAVE_UCONTEXT_H)
+#define MY_CONTEXT_USE_UCONTEXT
+#else
+#define MY_CONTEXT_DISABLE
+#endif
+
+#ifdef MY_CONTEXT_USE_WIN32_FIBERS
+struct my_context {
+ void (*user_func)(void *);
+ void *user_arg;
+ void *app_fiber;
+ void *lib_fiber;
+ int return_value;
+#ifndef DBUG_OFF
+ void *dbug_state;
+#endif
+};
+#endif
+
+
+#ifdef MY_CONTEXT_USE_UCONTEXT
+#include <ucontext.h>
+
+struct my_context {
+ void (*user_func)(void *);
+ void *user_data;
+ void *stack;
+ size_t stack_size;
+ ucontext_t base_context;
+ ucontext_t spawned_context;
+ int active;
+#ifdef HAVE_VALGRIND
+ unsigned int valgrind_stack_id;
+#endif
+#ifndef DBUG_OFF
+ void *dbug_state;
+#endif
+};
+#endif
+
+
+#ifdef MY_CONTEXT_USE_X86_64_GCC_ASM
+#include <stdint.h>
+
+struct my_context {
+ uint64_t save[9];
+ void *stack_top;
+ void *stack_bot;
+#ifdef HAVE_VALGRIND
+ unsigned int valgrind_stack_id;
+#endif
+#ifndef DBUG_OFF
+ void *dbug_state;
+#endif
+};
+#endif
+
+
+#ifdef MY_CONTEXT_USE_I386_GCC_ASM
+#include <stdint.h>
+
+struct my_context {
+ uint64_t save[7];
+ void *stack_top;
+ void *stack_bot;
+#ifdef HAVE_VALGRIND
+ unsigned int valgrind_stack_id;
+#endif
+#ifndef DBUG_OFF
+ void *dbug_state;
+#endif
+};
+#endif
+
+
+#ifdef MY_CONTEXT_DISABLE
+struct my_context {
+ int dummy;
+};
+#endif
+
+/*
+ Initialize an asynchronous context object.
+ Returns 0 on success, non-zero on failure.
+*/
+extern int my_context_init(struct my_context *c, size_t stack_size);
+
+/* Free an asynchronous context object, deallocating any resources used. */
+extern void my_context_destroy(struct my_context *c);
+
+/*
+ Spawn an asynchronous context. The context will run the supplied user
+ function, passing the supplied user data pointer.
+
+ The context must have been initialised with my_context_init() prior to
+ this call.
+
+ The user function may call my_context_yield(), which will cause this
+ function to return 1. Then later my_context_continue() may be called, which
+ will resume the asynchronous context by returning from the previous
+ my_context_yield() call.
+
+ When the user function returns, this function returns 0.
+
+ In case of error, -1 is returned.
+*/
+extern int my_context_spawn(struct my_context *c, void (*f)(void *), void *d);
+
+/*
+ Suspend an asynchronous context started with my_context_spawn.
+
+ When my_context_yield() is called, execution immediately returns from the
+ last my_context_spawn() or my_context_continue() call. Then when later
+ my_context_continue() is called, execution resumes by returning from this
+ my_context_yield() call.
+
+ Returns 0 if ok, -1 in case of error.
+*/
+extern int my_context_yield(struct my_context *c);
+
+/*
+ Resume an asynchronous context. The context was spawned by
+ my_context_spawn(), and later suspended inside my_context_yield().
+
+ The asynchronous context may be repeatedly suspended with
+ my_context_yield() and resumed with my_context_continue().
+
+ Each time it is suspended, this function returns 1. When the originally
+ spawned user function returns, this function returns 0.
+
+ In case of error, -1 is returned.
+*/
+extern int my_context_continue(struct my_context *c);
+
+struct st_ma_pvio;
+
+struct mysql_async_context {
+ /*
+ This is set to the value that should be returned from foo_start() or
+ foo_cont() when a call is suspended.
+ */
+ unsigned int events_to_wait_for;
+ /*
+ It is also set to the event(s) that triggered when a suspended call is
+ resumed, eg. whether we woke up due to connection completed or timeout
+ in mysql_real_connect_cont().
+ */
+ unsigned int events_occurred;
+ /*
+ This is set to the result of the whole asynchronous operation when it
+ completes. It uses a union, as different calls have different return
+ types.
+ */
+ union {
+ void *r_ptr;
+ const void *r_const_ptr;
+ int r_int;
+ my_bool r_my_bool;
+ } ret_result;
+ /*
+ The timeout value (in millisecods), for suspended calls that need to wake
+ up on a timeout (eg. mysql_real_connect_start().
+ */
+ unsigned int timeout_value;
+ /*
+ This flag is set when we are executing inside some asynchronous call
+ foo_start() or foo_cont(). It is used to decide whether to use the
+ synchronous or asynchronous version of calls that may block such as
+ recv().
+
+ Note that this flag is not set when a call is suspended, eg. after
+ returning from foo_start() and before re-entering foo_cont().
+ */
+ my_bool active;
+ /*
+ This flag is set when an asynchronous operation is in progress, but
+ suspended. Ie. it is set when foo_start() or foo_cont() returns because
+ the operation needs to block, suspending the operation.
+
+ It is used to give an error (rather than crash) if the application
+ attempts to call some foo_cont() method when no suspended operation foo is
+ in progress.
+ */
+ my_bool suspended;
+ /*
+ If non-NULL, this is a pointer to a callback hook that will be invoked with
+ the user data argument just before the context is suspended, and just after
+ it is resumed.
+ */
+ struct st_ma_pvio *pvio;
+ void (*suspend_resume_hook)(my_bool suspend, void *user_data);
+ void *suspend_resume_hook_user_data;
+
+ /* If non-NULL, this is a poitner to the result of getaddrinfo() currently
+ * under traversal in pvio_socket_connect(). It gets reset to NULL when a
+ * connection has been established to a server. The main objective is to
+ * free this memory resource in mysql_close() while an initiated connection
+ * has not been established. */
+ struct addrinfo* pending_gai_res;
+
+ /*
+ This is used to save the execution contexts so that we can suspend an
+ operation and switch back to the application context, to resume the
+ suspended context later when the application re-invokes us with
+ foo_cont().
+ */
+ struct my_context async_context;
+};
diff --git a/libmariadb/include/ma_crypt.h b/libmariadb/include/ma_crypt.h
new file mode 100644
index 00000000..367488fa
--- /dev/null
+++ b/libmariadb/include/ma_crypt.h
@@ -0,0 +1,155 @@
+/*
+ Copyright (C) 2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*/
+
+#ifndef _ma_hash_h_
+#define _ma_hash_h_
+
+#include <stddef.h>
+#include <stdarg.h>
+
+/*! Hash algorithms */
+#define MA_HASH_MD5 1
+#define MA_HASH_SHA1 2
+#define MA_HASH_SHA224 3
+#define MA_HASH_SHA256 4
+#define MA_HASH_SHA384 5
+#define MA_HASH_SHA512 6
+#define MA_HASH_RIPEMD160 7
+#define MA_HASH_MAX 8
+
+/*! Hash digest sizes */
+#define MA_MD5_HASH_SIZE 16
+#define MA_SHA1_HASH_SIZE 20
+#define MA_SHA224_HASH_SIZE 28
+#define MA_SHA256_HASH_SIZE 32
+#define MA_SHA384_HASH_SIZE 48
+#define MA_SHA512_HASH_SIZE 64
+#define MA_RIPEMD160_HASH_SIZE 20
+
+#define MA_MAX_HASH_SIZE 64
+/** \typedef MRL hash context */
+
+#if defined(HAVE_WINCRYPT)
+typedef void MA_HASH_CTX;
+#elif defined(HAVE_OPENSSL)
+#include <openssl/evp.h>
+typedef EVP_MD_CTX MA_HASH_CTX;
+#elif defined(HAVE_GNUTLS)
+typedef struct {
+ void *ctx;
+ const struct nettle_hash *hash;
+} MA_HASH_CTX;
+#endif
+
+/**
+ @brief acquire and initialize new hash context
+
+ @param[in] algorithm hash algorithm
+
+ @return hash context on success, NULL on error
+*/
+MA_HASH_CTX *ma_hash_new(unsigned int algorithm);
+
+/**
+ @brief release and deinitializes a hash context
+
+ @param[in] hash context
+
+ @return void
+*/
+void ma_hash_free(MA_HASH_CTX *ctx);
+
+/**
+ @brief hashes len bytes of data into the hash context.
+ This function can be called several times on same context to
+ hash additional data.
+
+ @param[in] ctx hash context
+ @param[in] buffer data buffer
+ @param[in] len size of buffer
+
+ @return void
+*/
+void ma_hash_input(MA_HASH_CTX *ctx,
+ const unsigned char *buffer,
+ size_t len);
+
+/**
+ @brief retrieves the hash value from hash context
+
+ @param[in] ctx hash context
+ @param[out] digest digest containing hash value
+
+ @return void
+ */
+void ma_hash_result(MA_HASH_CTX *ctx, unsigned char *digest);
+
+
+/**
+ @brief returns digest size for a given hash algorithm
+
+ @param[in] hash algorithm
+
+ @returns digest size or 0 on error
+*/
+static inline size_t ma_hash_digest_size(unsigned int hash_alg)
+{
+ switch(hash_alg) {
+ case MA_HASH_MD5:
+ return MA_MD5_HASH_SIZE;
+ case MA_HASH_SHA1:
+ return MA_SHA1_HASH_SIZE;
+ case MA_HASH_SHA224:
+ return MA_SHA224_HASH_SIZE;
+ case MA_HASH_SHA256:
+ return MA_SHA256_HASH_SIZE;
+ case MA_HASH_SHA384:
+ return MA_SHA384_HASH_SIZE;
+ case MA_HASH_SHA512:
+ return MA_SHA512_HASH_SIZE;
+ case MA_HASH_RIPEMD160:
+ return MA_RIPEMD160_HASH_SIZE;
+ default:
+ return 0;
+ }
+}
+
+/**
+ @brief function to compute hash from buffer.
+
+ @param[in] hash_alg hash algorithm
+ @param[in] buffer buffer
+ @param[in] buffer_leng length of buffer
+ @param[out] digest computed hash digest
+
+ @return void
+*/
+static inline void ma_hash(unsigned int algorithm,
+ const unsigned char *buffer,
+ size_t buffer_length,
+ unsigned char *digest)
+{
+ MA_HASH_CTX *ctx= NULL;
+ ctx= ma_hash_new(algorithm);
+ ma_hash_input(ctx, buffer, buffer_length);
+ ma_hash_result(ctx, digest);
+ ma_hash_free(ctx);
+}
+
+#endif /* _ma_hash_h_ */
diff --git a/libmariadb/include/ma_decimal.h b/libmariadb/include/ma_decimal.h
new file mode 100644
index 00000000..e1f4fbf1
--- /dev/null
+++ b/libmariadb/include/ma_decimal.h
@@ -0,0 +1,64 @@
+/* Copyright (C) 2000 Sergei Golubchik
+*/
+
+#ifndef _decimal_h
+#define _decimal_h
+
+typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode;
+typedef int32 decimal_digit;
+
+typedef struct st_decimal {
+ int intg, frac, len;
+ my_bool sign;
+ decimal_digit *buf;
+} decimal;
+
+int decimal2string(decimal *from, char *to, int *to_len);
+int bin2decimal(const char *from, decimal *to, int precision, int scale);
+
+int decimal_size(int precision, int scale);
+int decimal_bin_size(int precision, int scale);
+int decimal_result_size(decimal *from1, decimal *from2, char op, int param);
+
+
+/* set a decimal to zero */
+
+#define decimal_make_zero(dec) do { \
+ (dec)->buf[0]=0; \
+ (dec)->intg=1; \
+ (dec)->frac=0; \
+ (dec)->sign=0; \
+ } while(0)
+
+/*
+ returns the length of the buffer to hold string representation
+ of the decimal (including decimal dot, possible sign and \0)
+*/
+
+#define decimal_string_size(dec) ((dec)->intg + (dec)->frac + ((dec)->frac > 0) + 2)
+
+/* negate a decimal */
+#define decimal_neg(dec) do { (dec)->sign^=1; } while(0)
+
+/*
+ conventions:
+
+ decimal_smth() == 0 -- everything's ok
+ decimal_smth() <= 1 -- result is usable, but precision loss is possible
+ decimal_smth() <= 2 -- result can be unusable, most significant digits
+ could've been lost
+ decimal_smth() > 2 -- no result was generated
+*/
+
+#define E_DEC_OK 0
+#define E_DEC_TRUNCATED 1
+#define E_DEC_OVERFLOW 2
+#define E_DEC_DIV_ZERO 4
+#define E_DEC_BAD_NUM 8
+#define E_DEC_OOM 16
+
+#define E_DEC_ERROR 31
+#define E_DEC_FATAL_ERROR 30
+
+#endif
+
diff --git a/libmariadb/include/ma_global.h b/libmariadb/include/ma_global.h
new file mode 100644
index 00000000..52f20f41
--- /dev/null
+++ b/libmariadb/include/ma_global.h
@@ -0,0 +1,1094 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* This is the main include file that should included 'first' in every
+ C file. */
+
+#ifndef _global_h
+#define _global_h
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <stdlib.h>
+#define strcasecmp _stricmp
+#define strtok_r strtok_s
+#define strdup _strdup
+#define sleep(x) Sleep(1000*(x))
+#define strerror_r(errno,buf,len) strerror_s(buf,len,errno)
+#define STDCALL __stdcall
+#endif
+
+#include <ma_config.h>
+#include <assert.h>
+#ifndef __GNUC__
+#define __attribute(A)
+#endif
+
+/* Fix problem with S_ISLNK() on Linux */
+#if defined(HAVE_LINUXTHREADS)
+#undef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+/* The client defines this to avoid all thread code */
+#if defined(UNDEF_THREADS_HACK)
+#undef THREAD
+#undef HAVE_mit_thread
+#undef HAVE_LINUXTHREADS
+#undef HAVE_UNIXWARE7_THREADS
+#endif
+
+#ifdef HAVE_THREADS_WITHOUT_SOCKETS
+/* MIT pthreads does not work with unix sockets */
+#undef HAVE_SYS_UN_H
+#endif
+
+#define __EXTENSIONS__ 1 /* We want some extension */
+#ifndef __STDC_EXT__
+#define __STDC_EXT__ 1 /* To get large file support on hpux */
+#endif
+
+#if defined(THREAD) && !defined(_WIN32)
+#ifndef _POSIX_PTHREAD_SEMANTICS
+#define _POSIX_PTHREAD_SEMANTICS /* We want posix threads */
+#endif
+/* was #if defined(HAVE_LINUXTHREADS) || defined(HAVE_DEC_THREADS) || defined(HPUX) */
+#if !defined(SCO)
+#define _REENTRANT 1 /* Some thread libraries require this */
+#endif
+#if !defined(_THREAD_SAFE) && !defined(_AIX)
+#define _THREAD_SAFE /* Required for OSF1 */
+#endif
+#ifndef HAVE_mit_thread
+#ifdef HAVE_UNIXWARE7_THREADS
+#include <thread.h>
+#else
+#include <pthread.h> /* AIX must have this included first */
+#endif /* HAVE_UNIXWARE7_THREADS */
+#endif /* HAVE_mit_thread */
+#if !defined(SCO) && !defined(_REENTRANT)
+#define _REENTRANT 1 /* Threads requires reentrant code */
+#endif
+#endif /* THREAD */
+
+/* Go around some bugs in different OS and compilers */
+#ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */
+#undef HAVE_SNPRINTF
+#endif
+#if defined(HAVE_BROKEN_INLINE) && !defined(__cplusplus)
+#undef inline
+#define inline
+#endif
+
+#ifdef UNDEF_HAVE_GETHOSTBYNAME_R /* For OSF4.x */
+#undef HAVE_GETHOSTBYNAME_R
+#endif
+#ifdef UNDEF_HAVE_INITGROUPS /* For AIX 4.3 */
+#undef HAVE_INITGROUPS
+#endif
+
+/* Fix a bug in gcc 2.8.0 on IRIX 6.2 */
+#if SIZEOF_LONG == 4 && defined(__LONG_MAX__)
+#undef __LONG_MAX__ /* Is a longlong value in gcc 2.8.0 ??? */
+#define __LONG_MAX__ 2147483647
+#endif
+
+/* Fix problem when linking c++ programs with gcc 3.x */
+#ifdef DEFINE_CXA_PURE_VIRTUAL
+#define FIX_GCC_LINKING_PROBLEM extern "C" { int __cxa_pure_virtual() {return 0;} }
+#else
+#define FIX_GCC_LINKING_PROBLEM
+#endif
+
+/* egcs 1.1.2 has a problem with memcpy on Alpha */
+#if defined(__GNUC__) && defined(__alpha__) && ! (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
+#define BAD_MEMCPY
+#endif
+
+/* In Linux-alpha we have atomic.h if we are using gcc */
+#if defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD)
+#define HAVE_ATOMIC_ADD
+#define HAVE_ATOMIC_SUB
+#endif
+
+/* In Linux-ia64 including atomic.h will give us an error */
+#if (defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && (defined(__ia64__) || defined(__powerpc64__))) || !defined(THREAD)
+#undef HAVE_ATOMIC_ADD
+#undef HAVE_ATOMIC_SUB
+#endif
+
+#if defined(_lint) && !defined(lint)
+#define lint
+#endif
+#if SIZEOF_LONG_LONG > 4 && !defined(_LONG_LONG)
+#define _LONG_LONG 1 /* For AIX string library */
+#endif
+
+#ifndef stdin
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#include <math.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if defined(TIME_WITH_SYS_TIME)
+# include <sys/time.h>
+# include <time.h>
+#else
+# if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif /* TIME_WITH_SYS_TIME */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if defined(__cplusplus) && defined(NO_CPLUSPLUS_ALLOCA)
+#undef HAVE_ALLOCA
+#undef HAVE_ALLOCA_H
+#endif
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#ifdef HAVE_ATOMIC_ADD
+#define __SMP__
+#define CONFIG_SMP
+#include <asm/atomic.h>
+#endif
+#include <errno.h> /* Recommended by debian */
+#include <assert.h>
+
+/* Go around some bugs in different OS and compilers */
+#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H)
+#include <sys/stream.h> /* HPUX 10.20 defines ulong here. UGLY !!! */
+#define HAVE_ULONG
+#endif
+#ifdef DONT_USE_FINITE /* HPUX 11.x has is_finite() */
+#undef HAVE_FINITE
+#endif
+#if defined(HPUX) && defined(_LARGEFILE64_SOURCE) && defined(THREAD)
+/* Fix bug in setrlimit */
+#undef setrlimit
+#define setrlimit cma_setrlimit64
+#endif
+
+/* We can not live without these */
+
+#define USE_MYFUNC 1 /* Must use syscall indirection */
+#define MASTER 1 /* Compile without unireg */
+#define ENGLISH 1 /* Messages in English */
+#define POSIX_MISTAKE 1 /* regexp: Fix stupid spec error */
+#define USE_REGEX 1 /* We want the use the regex library */
+/* Do not define for ultra sparcs */
+#define USE_BMOVE512 1 /* Use this unless the system bmove is faster */
+
+/* Paranoid settings. Define I_AM_PARANOID if you are paranoid */
+#ifdef I_AM_PARANOID
+#define DONT_ALLOW_USER_CHANGE 1
+#define DONT_USE_MYSQL_PWD 1
+#endif
+
+/* #define USE_some_charset 1 was deprecated by changes to configure */
+/* my_ctype my_to_upper, my_to_lower, my_sort_order gain their right value */
+/* automagically during configuration */
+
+/* Does the system remember a signal handler after a signal ? */
+#ifndef HAVE_BSD_SIGNALS
+#define DONT_REMEMBER_SIGNAL
+#endif
+
+
+#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
+#define LINT_INIT(var) do{var=0;}while(0) /* No uninitialize-warning */
+#define LINT_INIT_STRUCT(var) memset(&var, 0, sizeof(var)) /* No uninitialize-warning */
+#else
+#define LINT_INIT(var)
+#define LINT_INIT_STRUCT(var)
+#endif
+
+/* Define some useful general macros */
+#if defined(__cplusplus) && defined(__GNUC__)
+#define max(a, b) ((a) >? (b))
+#define min(a, b) ((a) <? (b))
+#elif !defined(max)
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#if defined(__EMX__) || !defined(HAVE_UINT)
+typedef unsigned int uint;
+#endif
+#if defined(__EMX__) || !defined(HAVE_USHORT)
+typedef unsigned short ushort;
+#endif
+
+#define sgn(a) (((a) < 0) ? -1 : ((a) > 0) ? 1 : 0)
+#define swap(t,a,b) do{register t dummy; dummy = a; a = b; b = dummy;}while(0)
+#define test(a) ((a) ? 1 : 0)
+#define set_if_bigger(a,b) do{ if ((a) < (b)) (a)=(b); }while(0)
+#define set_if_smaller(a,b) do{ if ((a) > (b)) (a)=(b); }while(0)
+#define test_all_bits(a,b) (((a) & (b)) == (b))
+#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1))
+#define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0])))
+#ifndef HAVE_RINT
+#define rint(A) floor((A)+0.5)
+#endif
+
+/* Define some general constants */
+#ifndef TRUE
+#define TRUE (1) /* Logical true */
+#define FALSE (0) /* Logical false */
+#endif
+
+#if defined(__GNUC__)
+#define function_volatile volatile
+#ifndef my_reinterpret_cast
+#define my_reinterpret_cast(A) reinterpret_cast<A>
+#endif
+#define my_const_cast(A) const_cast<A>
+#elif !defined(my_reinterpret_cast)
+#define my_reinterpret_cast(A) (A)
+#define my_const_cast(A) (A)
+#endif
+#if !defined(__GNUC__) && !defined(__clang__)
+#define __attribute__(A)
+#endif
+
+/* From old s-system.h */
+
+/*
+ Support macros for non ansi & other old compilers. Since such
+ things are no longer supported we do nothing. We keep then since
+ some of our code may still be needed to upgrade old customers.
+*/
+#define _VARARGS(X) X
+#define _STATIC_VARARGS(X) X
+
+#if defined(DBUG_ON) && defined(DBUG_OFF)
+#undef DBUG_OFF
+#endif
+
+#if defined(_lint) && !defined(DBUG_OFF)
+#define DBUG_OFF
+#endif
+
+#define MIN_ARRAY_SIZE 0 /* Zero or One. Gcc allows zero*/
+#define ASCII_BITS_USED 8 /* Bit char used */
+#define NEAR_F /* No near function handling */
+
+/* Some types that is different between systems */
+
+typedef int File; /* File descriptor */
+#ifndef my_socket_defined
+#define my_socket_defined
+#if defined(_WIN64)
+#define my_socket unsigned long long
+#elif defined(_WIN32)
+#define my_socket unsigned int
+#else
+typedef int my_socket;
+#endif
+#define my_socket_defined
+#endif
+#ifndef INVALID_SOCKET
+#define INVALID_SOCKET -1
+#endif
+
+#if defined(__GNUC__) && !defined(_lint)
+typedef char pchar; /* Mixed prototypes can take char */
+typedef char puchar; /* Mixed prototypes can take char */
+typedef char pbool; /* Mixed prototypes can take char */
+typedef short pshort; /* Mixed prototypes can take short int */
+typedef float pfloat; /* Mixed prototypes can take float */
+#else
+typedef int pchar; /* Mixed prototypes can't take char */
+typedef uint puchar; /* Mixed prototypes can't take char */
+typedef int pbool; /* Mixed prototypes can't take char */
+typedef int pshort; /* Mixed prototypes can't take short int */
+typedef double pfloat; /* Mixed prototypes can't take float */
+#endif
+typedef int (*qsort_cmp)(const void *,const void *);
+#ifdef HAVE_mit_thread
+#define qsort_t void
+#undef QSORT_TYPE_IS_VOID
+#define QSORT_TYPE_IS_VOID
+#else
+#define qsort_t RETQSORTTYPE /* Broken GCC can't handle typedef !!!! */
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+typedef SOCKET_SIZE_TYPE size_socket;
+
+#ifndef SOCKOPT_OPTLEN_TYPE
+#define SOCKOPT_OPTLEN_TYPE size_socket
+#endif
+
+/* file create flags */
+
+#ifndef O_SHARE
+#define O_SHARE 0 /* Flag to my_open for shared files */
+#ifndef O_BINARY
+#define O_BINARY 0 /* Flag to my_open for binary files */
+#endif
+#define FILE_BINARY 0 /* Flag to my_fopen for binary streams */
+#ifdef HAVE_FCNTL
+#define HAVE_FCNTL_LOCK
+#define F_TO_EOF 0L /* Param to lockf() to lock rest of file */
+#endif
+#endif /* O_SHARE */
+#ifndef O_TEMPORARY
+#define O_TEMPORARY 0
+#endif
+#ifndef O_SHORT_LIVED
+#define O_SHORT_LIVED 0
+#endif
+
+/* #define USE_RECORD_LOCK */
+
+ /* Unsigned types supported by the compiler */
+#define UNSINT8 /* unsigned int8 (char) */
+#define UNSINT16 /* unsigned int16 */
+#define UNSINT32 /* unsigned int32 */
+
+ /* General constants */
+#define SC_MAXWIDTH 256 /* Max width of screen (for error messages) */
+#define FN_LEN 256 /* Max file name len */
+#define FN_HEADLEN 253 /* Max length of filepart of file name */
+#define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */
+#define FN_REFLEN 512 /* Max length of full path-name */
+#define FN_EXTCHAR '.'
+#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */
+#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */
+#define FN_PARENTDIR ".." /* Parentdirectory; Must be a string */
+#define FN_DEVCHAR ':'
+
+#ifndef FN_LIBCHAR
+#ifdef _WIN32
+#define FN_LIBCHAR '\\'
+#define FN_ROOTDIR "\\"
+#else
+#define FN_LIBCHAR '/'
+#define FN_ROOTDIR "/"
+#endif
+#define MY_NFILE 1024 /* This is only used to save filenames */
+#endif
+
+/* #define EXT_IN_LIBNAME */
+/* #define FN_NO_CASE_SENCE */
+/* #define FN_UPPER_CASE TRUE */
+
+/*
+ Io buffer size; Must be a power of 2 and a multiple of 512. May be
+ smaller what the disk page size. This influences the speed of the
+ isam btree library. eg to big to slow.
+*/
+#define IO_SIZE 4096
+/*
+ How much overhead does malloc have. The code often allocates
+ something like 1024-MALLOC_OVERHEAD bytes
+*/
+#define MALLOC_OVERHEAD 8
+ /* get memory in huncs */
+#define ONCE_ALLOC_INIT ((uint) (4096-MALLOC_OVERHEAD))
+ /* Typical record cash */
+#define RECORD_CACHE_SIZE ((uint) (64*1024-MALLOC_OVERHEAD))
+ /* Typical key cash */
+#define KEY_CACHE_SIZE ((uint) (8*1024*1024-MALLOC_OVERHEAD))
+
+ /* Some things that this system doesn't have */
+
+#define ONLY_OWN_DATABASES /* We are using only databases by monty */
+#define NO_PISAM /* Not needed anymore */
+#define NO_MISAM /* Not needed anymore */
+#define NO_HASH /* Not needed anymore */
+#ifdef _WIN32
+#define NO_DIR_LIBRARY /* Not standard dir-library */
+#define USE_MY_STAT_STRUCT /* For my_lib */
+#ifdef _MSC_VER
+typedef SSIZE_T ssize_t;
+#endif
+#endif
+
+/* Some things that this system does have */
+
+#ifndef HAVE_ITOA
+#define USE_MY_ITOA /* There is no itoa */
+#endif
+
+/* Some defines of functions for portability */
+
+#ifndef HAVE_ATOD
+#define atod atof
+#endif
+#ifdef USE_MY_ATOF
+#define atof my_atof
+extern void init_my_atof(void);
+extern double my_atof(const char*);
+#endif
+#undef remove /* Crashes MySQL on SCO 5.0.0 */
+#ifndef _WIN32
+#define closesocket(A) close(A)
+#endif
+#ifndef ulonglong2double
+#define ulonglong2double(A) ((double) (A))
+#define my_off_t2double(A) ((double) (A))
+#endif
+
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+#define ulong_to_double(X) ((double) (ulong) (X))
+#define SET_STACK_SIZE(X) /* Not needed on real machines */
+
+
+#ifdef HAVE_LINUXTHREADS
+/* #define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) */
+/* #define sigset(A,B) signal((A),(B)) */
+#endif
+
+#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || \
+ defined(__cplusplus) || !defined(__GNUC__)
+#define UNINIT_VAR(x) x= 0
+#else
+/* GCC specific self-initialization which inhibits the warning. */
+#define UNINIT_VAR(x) x= x
+#endif
+
+
+/* This is from the old m-machine.h file */
+
+#if SIZEOF_LONG_LONG > 4
+#define HAVE_LONG_LONG 1
+#endif
+
+#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN)
+#define LONGLONG_MIN ((long long) 0x8000000000000000LL)
+#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL)
+#endif
+
+
+#define INT_MIN64 (~0x7FFFFFFFFFFFFFFFLL)
+#define INT_MAX64 0x7FFFFFFFFFFFFFFFLL
+#define INT_MIN32 (~0x7FFFFFFFL)
+#define INT_MAX32 0x7FFFFFFFL
+#define UINT_MAX32 0xFFFFFFFFL
+#define INT_MIN24 (~0x007FFFFF)
+#define INT_MAX24 0x007FFFFF
+#define UINT_MAX24 0x00FFFFFF
+#define INT_MIN16 (~0x7FFF)
+#define INT_MAX16 0x7FFF
+#define UINT_MAX16 0xFFFF
+#define INT_MIN8 (~0x7F)
+#define INT_MAX8 0x7F
+#define UINT_MAX8 0xFF
+
+#ifndef ULL
+#ifdef HAVE_LONG_LONG
+#define ULL(A) A ## ULL
+#else
+#define ULL(A) A ## UL
+#endif
+#endif
+
+#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)
+/* First check for ANSI C99 definition: */
+#ifdef ULLONG_MAX
+#define ULONGLONG_MAX ULLONG_MAX
+#else
+#define ULONGLONG_MAX ((unsigned long long)(~0ULL))
+#endif
+#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
+
+/* From limits.h instead */
+#ifndef DBL_MIN
+#define DBL_MIN 4.94065645841246544e-324
+#define FLT_MIN ((float)1.40129846432481707e-45)
+#endif
+#ifndef DBL_MAX
+#define DBL_MAX 1.79769313486231470e+308
+#define FLT_MAX ((float)3.40282346638528860e+38)
+#endif
+
+/*
+ Max size that must be added to a so that we know Size to make
+ addressable obj.
+*/
+typedef long my_ptrdiff_t;
+#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
+#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
+/* Size to make addressable obj. */
+#define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A),sizeof(t)))
+ /* Offset of filed f in structure t */
+#define OFFSET(t, f) ((size_t)(char *)&((t *)0)->f)
+#define ADD_TO_PTR(ptr,size,type) (type) ((unsigned char*) (ptr)+size)
+#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((unsigned char*) (A) - (unsigned char*) (B))
+
+#define NullS (char *) 0
+/* Nowadays we do not support MessyDos */
+#ifndef NEAR
+#define NEAR /* Who needs segments ? */
+#define FAR /* On a good machine */
+#ifndef HUGE_PTR
+#define HUGE_PTR
+#endif
+#endif
+#if defined(__IBMC__) || defined(__IBMCPP__)
+#define STDCALL _System _Export
+#elif !defined( STDCALL)
+#define STDCALL
+#endif
+
+/* Typedefs for easier portability */
+
+#if defined(VOIDTYPE)
+typedef void *gptr; /* Generic pointer */
+#else
+typedef char *gptr; /* Generic pointer */
+#endif
+#ifndef HAVE_INT_8_16_32
+typedef signed char int8; /* Signed integer >= 8 bits */
+typedef signed short int16; /* Signed integer >= 16 bits */
+#endif
+#ifndef HAVE_UCHAR
+typedef unsigned char uchar; /* Short for unsigned char */
+#endif
+typedef unsigned char uint8; /* Short for unsigned integer >= 8 bits */
+typedef unsigned short uint16; /* Short for unsigned integer >= 16 bits */
+
+#if SIZEOF_INT == 4
+#ifndef HAVE_INT_8_16_32
+typedef int int32;
+#endif
+typedef unsigned int uint32; /* Short for unsigned integer >= 32 bits */
+#elif SIZEOF_LONG == 4
+#ifndef HAVE_INT_8_16_32
+typedef long int32;
+#endif
+typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */
+#else
+#error "Neither int or long is of 4 bytes width"
+#endif
+
+#if !defined(HAVE_ULONG) && !defined(HAVE_LINUXTHREADS) && !defined(__USE_MISC)
+typedef unsigned long ulong; /* Short for unsigned long */
+#endif
+#ifndef longlong_defined
+#if defined(HAVE_LONG_LONG) && SIZEOF_LONG != 8
+typedef unsigned long long int ulonglong; /* ulong or unsigned long long */
+typedef long long int longlong;
+#else
+typedef unsigned long ulonglong; /* ulong or unsigned long long */
+typedef long longlong;
+#endif
+#define longlong_defined
+#endif
+
+#ifndef HAVE_INT64
+typedef longlong int64;
+#endif
+#ifndef HAVE_UINT64
+typedef ulonglong uint64;
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1)
+#ifdef USE_RAID
+/*
+ The following is done with a if to not get problems with pre-processors
+ with late define evaluation
+*/
+#if defined(SIZEOF_OFF_T) && SIZEOF_OFF_T == 4
+#define SYSTEM_SIZEOF_OFF_T 4
+#else
+#define SYSTEM_SIZEOF_OFF_T 8
+#endif
+#undef SIZEOF_OFF_T
+#define SIZEOF_OFF_T 8
+#else
+#define SYSTEM_SIZEOF_OFF_T SIZEOF_OFF_T
+#endif /* USE_RAID */
+
+#if defined(SIZEOF_OFF_T) && SIZEOF_OFF_T > 4
+typedef ulonglong my_off_t;
+#else
+typedef unsigned long my_off_t;
+#endif
+#define MY_FILEPOS_ERROR (~(my_off_t) 0)
+#ifndef _WIN32
+typedef off_t os_off_t;
+#endif
+
+#if defined(_WIN32)
+#define socket_errno WSAGetLastError()
+#define SOCKET_EINTR WSAEINTR
+#define SOCKET_EAGAIN WSAEWOULDBLOCK
+#define SOCKET_ENFILE ENFILE
+#define SOCKET_EMFILE EMFILE
+#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
+#else /* Unix */
+#define socket_errno errno
+#define closesocket(A) close(A)
+#define SOCKET_EINTR EINTR
+#define SOCKET_EAGAIN EAGAIN
+#define SOCKET_EWOULDBLOCK EWOULDBLOCK
+#define SOCKET_ENFILE ENFILE
+#define SOCKET_EMFILE EMFILE
+#endif
+
+typedef uint8 int7; /* Most effective integer 0 <= x <= 127 */
+typedef short int15; /* Most effective integer 0 <= x <= 32767 */
+typedef char *my_string; /* String of characters */
+typedef unsigned long size_s; /* Size of strings (In string-funcs) */
+typedef int myf; /* Type of MyFlags in my_funcs */
+typedef char my_bool; /* Small bool */
+typedef unsigned long long my_ulonglong;
+#if !defined(bool) && !defined(bool_defined) && (!defined(HAVE_BOOL) || !defined(__cplusplus))
+typedef char bool; /* Ordinary boolean values 0 1 */
+#endif
+ /* Macros for converting *constants* to the right type */
+#define INT8(v) (int8) (v)
+#define INT16(v) (int16) (v)
+#define INT32(v) (int32) (v)
+#define MYF(v) (myf) (v)
+
+/*
+ Defines to make it possible to prioritize register assignments. No
+ longer that important with modern compilers.
+*/
+#ifndef USING_X
+#define reg1 register
+#define reg2 register
+#define reg3 register
+#define reg4 register
+#define reg5 register
+#define reg6 register
+#define reg7 register
+#define reg8 register
+#define reg9 register
+#define reg10 register
+#define reg11 register
+#define reg12 register
+#define reg13 register
+#define reg14 register
+#define reg15 register
+#define reg16 register
+#endif
+
+/* Defines for time function */
+#define SCALE_SEC 100
+#define SCALE_USEC 10000
+#define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */
+#define MY_HOW_OFTEN_TO_WRITE 1000 /* How often we want info on screen */
+
+#define NOT_FIXED_DEC 31
+
+#if defined(_WIN32) && defined(_MSVC)
+#define MYSQLND_LLU_SPEC "%I64u"
+#define MYSQLND_LL_SPEC "%I64d"
+#ifndef L64
+#define L64(x) x##i64
+#endif
+#else
+#define MYSQLND_LLU_SPEC "%llu"
+#define MYSQLND_LL_SPEC "%lld"
+#ifndef L64
+#define L64(x) x##LL
+#endif /* L64 */
+#endif /* _WIN32 */
+/*
+** Define functions for reading and storing in machine independent format
+** (low byte first)
+*/
+
+/* Optimized store functions for Intel x86 */
+#define int1store(T,A) *((int8*) (T)) = (A)
+#define uint1korr(A) (*(((uint8*)(A))))
+#define sint1korr(A) (*(((int8*)(A))))
+#if defined(__i386__) || defined(_WIN32)
+#define sint2korr(A) (*((int16 *) (A)))
+#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
+ (((uint32) 255L << 24) | \
+ (((uint32) (uchar) (A)[2]) << 16) |\
+ (((uint32) (uchar) (A)[1]) << 8) | \
+ ((uint32) (uchar) (A)[0])) : \
+ (((uint32) (uchar) (A)[2]) << 16) |\
+ (((uint32) (uchar) (A)[1]) << 8) | \
+ ((uint32) (uchar) (A)[0])))
+#define sint4korr(A) (*((long *) (A)))
+#define uint2korr(A) (*((uint16 *) (A)))
+#if defined(HAVE_purify) && !defined(_WIN32)
+#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
+ (((uint32) ((uchar) (A)[1])) << 8) +\
+ (((uint32) ((uchar) (A)[2])) << 16))
+#else
+/*
+ ATTENTION !
+
+ Please, note, uint3korr reads 4 bytes (not 3) !
+ It means, that you have to provide enough allocated space !
+*/
+#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
+#endif /* HAVE_purify && !_WIN32 */
+#define uint4korr(A) (*((uint32 *) (A)))
+#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+ (((uint32) ((uchar) (A)[1])) << 8) +\
+ (((uint32) ((uchar) (A)[2])) << 16) +\
+ (((uint32) ((uchar) (A)[3])) << 24)) +\
+ (((ulonglong) ((uchar) (A)[4])) << 32))
+#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \
+ (((uint32) ((uchar) (A)[1])) << 8) + \
+ (((uint32) ((uchar) (A)[2])) << 16) + \
+ (((uint32) ((uchar) (A)[3])) << 24)) + \
+ (((ulonglong) ((uchar) (A)[4])) << 32) + \
+ (((ulonglong) ((uchar) (A)[5])) << 40))
+#define uint8korr(A) (*((ulonglong *) (A)))
+#define sint8korr(A) (*((longlong *) (A)))
+#define int2store(T,A) *((uint16*) (T))= (uint16) (A)
+#define int3store(T,A) do { *(T)= (uchar) ((A) & 0xff);\
+ *(T+1)=(uchar) (((uint) (A) >> 8) & 0xff);\
+ *(T+2)=(uchar) (((A) >> 16) & 0xff); } while (0)
+#define int4store(T,A) *((long *) (T))= (long) (A)
+#define int5store(T,A) do { *(T)= (uchar)((A));\
+ *((T)+1)=(uchar) (((A) >> 8));\
+ *((T)+2)=(uchar) (((A) >> 16));\
+ *((T)+3)=(uchar) (((A) >> 24)); \
+ *((T)+4)=(uchar) (((A) >> 32)); } while(0)
+#define int6store(T,A) do { *(T)= (uchar)((A)); \
+ *((T)+1)=(uchar) (((A) >> 8)); \
+ *((T)+2)=(uchar) (((A) >> 16)); \
+ *((T)+3)=(uchar) (((A) >> 24)); \
+ *((T)+4)=(uchar) (((A) >> 32)); \
+ *((T)+5)=(uchar) (((A) >> 40)); } while(0)
+#define int8store(T,A) do {*((ulonglong *) (T))= (ulonglong) (A);} while(0)
+
+typedef union {
+ double v;
+ long m[2];
+} doubleget_union;
+#define doubleget(V,M) \
+do { doubleget_union _tmp; \
+ _tmp.m[0] = *((long*)(M)); \
+ _tmp.m[1] = *(((long*) (M))+1); \
+ (V) = _tmp.v; } while(0)
+#define doublestore(T,V) do { *((long *) T) = ((doubleget_union *)&V)->m[0]; \
+ *(((long *) T)+1) = ((doubleget_union *)&V)->m[1]; \
+ } while (0)
+#define float4get(V,M) do { *((float *) &(V)) = *((float*) (M)); } while(0)
+#define float8get(V,M) doubleget((V),(M))
+#define float4store(V,M) memcpy((uchar*) V,(uchar*) (&M),sizeof(float))
+#define floatstore(T,V) memcpy((uchar*)(T), (uchar*)(&V),sizeof(float))
+#define floatget(V,M) memcpy((uchar*) &V,(uchar*) (M),sizeof(float))
+#define float8store(V,M) doublestore((V),(M))
+#else
+
+/*
+ We're here if it's not a IA-32 architecture (Win32 and UNIX IA-32 defines
+ were done before)
+*/
+#define sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) +\
+ ((int16) ((int16) (A)[1]) << 8))
+#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
+ (((uint32) 255L << 24) | \
+ (((uint32) (uchar) (A)[2]) << 16) |\
+ (((uint32) (uchar) (A)[1]) << 8) | \
+ ((uint32) (uchar) (A)[0])) : \
+ (((uint32) (uchar) (A)[2]) << 16) |\
+ (((uint32) (uchar) (A)[1]) << 8) | \
+ ((uint32) (uchar) (A)[0])))
+#define sint4korr(A) (int32) (((int32) ((uchar) (A)[0])) +\
+ (((int32) ((uchar) (A)[1]) << 8)) +\
+ (((int32) ((uchar) (A)[2]) << 16)) +\
+ (((int32) ((int16) (A)[3]) << 24)))
+#define sint8korr(A) (longlong) uint8korr(A)
+#define uint2korr(A) (uint16) (((uint16) ((uchar) (A)[0])) +\
+ ((uint16) ((uchar) (A)[1]) << 8))
+#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
+ (((uint32) ((uchar) (A)[1])) << 8) +\
+ (((uint32) ((uchar) (A)[2])) << 16))
+#define uint4korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
+ (((uint32) ((uchar) (A)[1])) << 8) +\
+ (((uint32) ((uchar) (A)[2])) << 16) +\
+ (((uint32) ((uchar) (A)[3])) << 24))
+#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+ (((uint32) ((uchar) (A)[1])) << 8) +\
+ (((uint32) ((uchar) (A)[2])) << 16) +\
+ (((uint32) ((uchar) (A)[3])) << 24)) +\
+ (((ulonglong) ((uchar) (A)[4])) << 32))
+#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \
+ (((uint32) ((uchar) (A)[1])) << 8) + \
+ (((uint32) ((uchar) (A)[2])) << 16) + \
+ (((uint32) ((uchar) (A)[3])) << 24)) + \
+ (((ulonglong) ((uchar) (A)[4])) << 32) + \
+ (((ulonglong) ((uchar) (A)[5])) << 40))
+#define uint8korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+ (((uint32) ((uchar) (A)[1])) << 8) +\
+ (((uint32) ((uchar) (A)[2])) << 16) +\
+ (((uint32) ((uchar) (A)[3])) << 24)) +\
+ (((ulonglong) (((uint32) ((uchar) (A)[4])) +\
+ (((uint32) ((uchar) (A)[5])) << 8) +\
+ (((uint32) ((uchar) (A)[6])) << 16) +\
+ (((uint32) ((uchar) (A)[7])) << 24))) <<\
+ 32))
+#define int2store(T,A) do { uint def_temp= (uint) (A) ;\
+ *((uchar*) (T))= (uchar)(def_temp); \
+ *((uchar*) (T)+1)=(uchar)((def_temp >> 8)); \
+ } while(0)
+#define int3store(T,A) do { /*lint -save -e734 */\
+ *((uchar*)(T))=(uchar) ((A));\
+ *((uchar*) (T)+1)=(uchar) (((A) >> 8));\
+ *((uchar*)(T)+2)=(uchar) (((A) >> 16)); \
+ /*lint -restore */} while(0)
+#define int4store(T,A) do { *((char *)(T))=(char) ((A));\
+ *(((char *)(T))+1)=(char) (((A) >> 8));\
+ *(((char *)(T))+2)=(char) (((A) >> 16));\
+ *(((char *)(T))+3)=(char) (((A) >> 24)); } while(0)
+#define int5store(T,A) do { *((char *)(T))= (char)((A)); \
+ *(((char *)(T))+1)= (char)(((A) >> 8)); \
+ *(((char *)(T))+2)= (char)(((A) >> 16)); \
+ *(((char *)(T))+3)= (char)(((A) >> 24)); \
+ *(((char *)(T))+4)= (char)(((A) >> 32)); \
+ } while(0)
+#define int6store(T,A) do { *((char *)(T))= (char)((A)); \
+ *(((char *)(T))+1)= (char)(((A) >> 8)); \
+ *(((char *)(T))+2)= (char)(((A) >> 16)); \
+ *(((char *)(T))+3)= (char)(((A) >> 24)); \
+ *(((char *)(T))+4)= (char)(((A) >> 32)); \
+ *(((char *)(T))+5)= (char)(((A) >> 40)); \
+ } while(0)
+#define int8store(T,A) do { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \
+ int4store((T),def_temp); \
+ int4store((T+4),def_temp2); } while(0)
+#ifdef HAVE_BIGENDIAN
+#define float4store(T,A) do { *(T)= ((uchar *) &A)[3];\
+ *((T)+1)=(char) ((uchar *) &A)[2];\
+ *((T)+2)=(char) ((uchar *) &A)[1];\
+ *((T)+3)=(char) ((uchar *) &A)[0]; } while(0)
+
+#define float4get(V,M) do { float def_temp;\
+ ((uchar*) &def_temp)[0]=(M)[3];\
+ ((uchar*) &def_temp)[1]=(M)[2];\
+ ((uchar*) &def_temp)[2]=(M)[1];\
+ ((uchar*) &def_temp)[3]=(M)[0];\
+ (V)=def_temp; } while(0)
+#define float8store(T,V) do { *(T)= ((uchar *) &V)[7];\
+ *((T)+1)=(char) ((uchar *) &V)[6];\
+ *((T)+2)=(char) ((uchar *) &V)[5];\
+ *((T)+3)=(char) ((uchar *) &V)[4];\
+ *((T)+4)=(char) ((uchar *) &V)[3];\
+ *((T)+5)=(char) ((uchar *) &V)[2];\
+ *((T)+6)=(char) ((uchar *) &V)[1];\
+ *((T)+7)=(char) ((uchar *) &V)[0]; } while(0)
+
+#define float8get(V,M) do { double def_temp;\
+ ((uchar*) &def_temp)[0]=(M)[7];\
+ ((uchar*) &def_temp)[1]=(M)[6];\
+ ((uchar*) &def_temp)[2]=(M)[5];\
+ ((uchar*) &def_temp)[3]=(M)[4];\
+ ((uchar*) &def_temp)[4]=(M)[3];\
+ ((uchar*) &def_temp)[5]=(M)[2];\
+ ((uchar*) &def_temp)[6]=(M)[1];\
+ ((uchar*) &def_temp)[7]=(M)[0];\
+ (V) = def_temp; } while(0)
+#else
+#define float4get(V,M) memcpy(&V, (M), sizeof(float))
+#define float4store(V,M) memcpy(V, (&M), sizeof(float))
+
+#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
+#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((uchar *) &V)[4];\
+ *(((char*)T)+1)=(char) ((uchar *) &V)[5];\
+ *(((char*)T)+2)=(char) ((uchar *) &V)[6];\
+ *(((char*)T)+3)=(char) ((uchar *) &V)[7];\
+ *(((char*)T)+4)=(char) ((uchar *) &V)[0];\
+ *(((char*)T)+5)=(char) ((uchar *) &V)[1];\
+ *(((char*)T)+6)=(char) ((uchar *) &V)[2];\
+ *(((char*)T)+7)=(char) ((uchar *) &V)[3]; }\
+ while(0)
+#define doubleget(V,M) do { double def_temp;\
+ ((uchar*) &def_temp)[0]=(M)[4];\
+ ((uchar*) &def_temp)[1]=(M)[5];\
+ ((uchar*) &def_temp)[2]=(M)[6];\
+ ((uchar*) &def_temp)[3]=(M)[7];\
+ ((uchar*) &def_temp)[4]=(M)[0];\
+ ((uchar*) &def_temp)[5]=(M)[1];\
+ ((uchar*) &def_temp)[6]=(M)[2];\
+ ((uchar*) &def_temp)[7]=(M)[3];\
+ (V) = def_temp; } while(0)
+#endif /* __FLOAT_WORD_ORDER */
+
+#define float8get(V,M) doubleget((V),(M))
+#define float8store(V,M) doublestore((V),(M))
+#endif /* HAVE_BIGENDIAN */
+
+#endif /* __i386__ OR _WIN32 */
+
+/*
+ Macro for reading 32-bit integer from network byte order (big-endian)
+ from unaligned memory location.
+*/
+#define int4net(A) (int32) (((uint32) ((uchar) (A)[3])) |\
+ (((uint32) ((uchar) (A)[2])) << 8) |\
+ (((uint32) ((uchar) (A)[1])) << 16) |\
+ (((uint32) ((uchar) (A)[0])) << 24))
+/*
+ Define functions for reading and storing in machine format from/to
+ short/long to/from some place in memory V should be a (not
+ register) variable, M is a pointer to byte
+*/
+
+#ifdef HAVE_BIGENDIAN
+
+#define ushortget(V,M) do { V = (uint16) (((uint16) ((uchar) (M)[1]))+\
+ ((uint16) ((uint16) (M)[0]) << 8)); } while(0)
+#define shortget(V,M) do { V = (short) (((short) ((uchar) (M)[1]))+\
+ ((short) ((short) (M)[0]) << 8)); } while(0)
+#define longget(V,M) do { int32 def_temp;\
+ ((uchar*) &def_temp)[0]=(M)[0];\
+ ((uchar*) &def_temp)[1]=(M)[1];\
+ ((uchar*) &def_temp)[2]=(M)[2];\
+ ((uchar*) &def_temp)[3]=(M)[3];\
+ (V)=def_temp; } while(0)
+#define ulongget(V,M) do { uint32 def_temp;\
+ ((uchar*) &def_temp)[0]=(M)[0];\
+ ((uchar*) &def_temp)[1]=(M)[1];\
+ ((uchar*) &def_temp)[2]=(M)[2];\
+ ((uchar*) &def_temp)[3]=(M)[3];\
+ (V)=def_temp; } while(0)
+#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
+ *(((char*)T)+1)=(char)(def_temp); \
+ *(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
+#define longstore(T,A) do { *(((char*)T)+3)=((A));\
+ *(((char*)T)+2)=(((A) >> 8));\
+ *(((char*)T)+1)=(((A) >> 16));\
+ *(((char*)T)+0)=(((A) >> 24)); } while(0)
+
+#define floatget(V,M) memcpy(&V, (M), sizeof(float))
+#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
+#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
+#define doublestore(T,V) memcpy((T), (void *) &V, sizeof(double))
+#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
+#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))
+
+#else
+
+#define ushortget(V,M) do { V = uint2korr(M); } while(0)
+#define shortget(V,M) do { V = sint2korr(M); } while(0)
+#define longget(V,M) do { V = sint4korr(M); } while(0)
+#define ulongget(V,M) do { V = uint4korr(M); } while(0)
+#define shortstore(T,V) int2store(T,V)
+#define longstore(T,V) int4store(T,V)
+#ifndef floatstore
+#define floatstore(T,V) memcpy((T), (void *) (&V), sizeof(float))
+#define floatget(V,M) memcpy(&V, (M), sizeof(float))
+#endif
+#ifndef doubleget
+#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
+#define doublestore(T,V) memcpy((T), (void *) &V, sizeof(double))
+#endif /* doubleget */
+#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
+#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))
+
+#endif /* HAVE_BIGENDIAN */
+
+#ifndef THREAD
+#define thread_safe_increment(V,L) ((V)++)
+#define thread_safe_add(V,C,L) ((V)+=(C))
+#define thread_safe_sub(V,C,L) ((V)-=(C))
+#define statistic_increment(V,L) ((V)++)
+#define statistic_add(V,C,L) ((V)+=(C))
+#endif
+
+#ifdef _WIN32
+#define SO_EXT ".dll"
+#else
+#define SO_EXT ".so"
+#endif
+
+#ifndef DBUG_OFF
+#define dbug_assert(A) assert(A)
+#define DBUG_ASSERT(A) assert(A)
+#else
+#define dbug_assert(A)
+#define DBUG_ASSERT(A)
+#endif
+
+#ifdef HAVE_DLOPEN
+#ifdef _WIN32
+#define dlsym(lib, name) GetProcAddress((HMODULE)(lib), name)
+#define dlopen(libname, unused) LoadLibraryEx(libname, NULL, 0)
+#define dlclose(lib) FreeLibrary((HMODULE)(lib))
+#elif defined(HAVE_DLFCN_H)
+#include <dlfcn.h>
+#endif
+#ifndef HAVE_DLERROR
+#define dlerror() ""
+#endif
+#endif
+
+#if SIZEOF_CHARP == SIZEOF_INT
+typedef unsigned int intptr;
+#elif SIZEOF_CHARP == SIZEOF_LONG
+typedef unsigned long intptr;
+#elif SIZEOF_CHARP == SIZEOF_LONG_LONG
+typedef unsigned long long intptr;
+#else
+#error sizeof(void *) is not sizeof(int, long or long long)
+#endif
+
+#ifdef _WIN32
+#define IF_WIN(A,B) A
+#else
+#define IF_WIN(A,B) B
+#endif
+
+#if defined(SOLARIS) || defined(__sun)
+#define IF_SOLARIS(A,B) A
+#else
+#define IF_SOLARIS(A,B) B
+#endif
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 1
+#endif
+
+#endif /* _global_h */
diff --git a/libmariadb/include/ma_hashtbl.h b/libmariadb/include/ma_hashtbl.h
new file mode 100644
index 00000000..d0954022
--- /dev/null
+++ b/libmariadb/include/ma_hashtbl.h
@@ -0,0 +1,70 @@
+/************************************************************************************
+ Copyright (C) 2000, 2012 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
+ Monty Program AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*************************************************************************************/
+
+#ifndef _ma_hashtbl_h
+#define _ma_hashtbl_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uchar *(*hash_get_key)(const uchar *,uint*,my_bool);
+typedef void (*hash_free_key)(void *);
+
+ /* flags for hash_init */
+#define MA_HASHTBL_CASE_INSENSITIVE 1
+
+typedef struct st_hash_info {
+ uint next; /* index to next key */
+ uchar *data; /* data for current entry */
+} MA_HASHTBL_LINK;
+
+typedef struct st_hash {
+ uint key_offset,key_length; /* Length of key if const length */
+ uint records,blength,current_record;
+ uint flags;
+ DYNAMIC_ARRAY array; /* Place for hash_keys */
+ hash_get_key get_key;
+ void (*free)(void *);
+ uint (*calc_hashnr)(const uchar *key,uint length);
+} MA_HASHTBL;
+
+#define ma_hashtbl_init(A,B,C,D,E,F,G) _ma_hashtbl_init(A,B,C,D,E,F,G CALLER_INFO)
+my_bool _ma_hashtbl_init(MA_HASHTBL *hash,uint default_array_elements, uint key_offset,
+ uint key_length, hash_get_key get_key,
+ void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
+void ma_hashtbl_free(MA_HASHTBL *tree);
+uchar *ma_hashtbl_element(MA_HASHTBL *hash,uint idx);
+void * ma_hashtbl_search(MA_HASHTBL *info,const uchar *key,uint length);
+void * ma_hashtbl_next(MA_HASHTBL *info,const uchar *key,uint length);
+my_bool ma_hashtbl_insert(MA_HASHTBL *info,const uchar *data);
+my_bool ma_hashtbl_delete(MA_HASHTBL *hash,uchar *record);
+my_bool ma_hashtbl_update(MA_HASHTBL *hash,uchar *record,uchar *old_key,uint old_key_length);
+my_bool ma_hashtbl_check(MA_HASHTBL *hash); /* Only in debug library */
+
+#define ma_hashtbl_clear(H) memset((char*) (H), 0,sizeof(*(H)))
+#define ma_hashtbl_inited(H) ((H)->array.buffer != 0)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libmariadb/include/ma_list.h b/libmariadb/include/ma_list.h
new file mode 100644
index 00000000..ccd2bbd8
--- /dev/null
+++ b/libmariadb/include/ma_list.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+#ifndef _list_h_
+#define _list_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct st_list {
+ struct st_list *prev,*next;
+ void *data;
+} LIST;
+
+typedef int (*list_walk_action)(void *,void *);
+
+extern LIST *list_add(LIST *root,LIST *element);
+extern LIST *list_delete(LIST *root,LIST *element);
+extern LIST *list_cons(void *data,LIST *root);
+extern LIST *list_reverse(LIST *root);
+extern void list_free(LIST *root,unsigned int free_data);
+extern unsigned int list_length(LIST *list);
+extern int list_walk(LIST *list,list_walk_action action,char * argument);
+
+#define list_rest(a) ((a)->next)
+#define list_push(a,b) (a)=list_cons((b),(a))
+#define list_pop(A) do {LIST *old=(A); (A)=list_delete(old,old) ; ma_free((char *) old,MYF(MY_FAE)); } while(0)
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libmariadb/include/ma_priv.h b/libmariadb/include/ma_priv.h
new file mode 100644
index 00000000..0fefd52e
--- /dev/null
+++ b/libmariadb/include/ma_priv.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ Copyright (C) 2020 MariaDB Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+ *****************************************************************************/
+#ifndef MA_PRIV_H
+#define MA_PRIV_H
+
+void free_rows(MYSQL_DATA *cur);
+int ma_multi_command(MYSQL *mysql, enum enum_multi_status status);
+MYSQL_FIELD * unpack_fields(const MYSQL *mysql, MYSQL_DATA *data,
+ MA_MEM_ROOT *alloc,uint fields,
+ my_bool default_value);
+
+static inline my_bool ma_has_extended_type_info(const MYSQL *mysql)
+{
+ return ((mysql->extension->mariadb_server_capabilities) &
+ (MARIADB_CLIENT_EXTENDED_METADATA >> 32)) != 0;
+}
+
+static inline uint ma_extended_type_info_rows(const MYSQL *mysql)
+{
+ return ma_has_extended_type_info(mysql) ? 1 : 0;
+}
+
+static inline my_bool ma_supports_cache_metadata(const MYSQL *mysql)
+{
+ return (mysql->extension->mariadb_server_capabilities &
+ (MARIADB_CLIENT_CACHE_METADATA >> 32)) != 0 ;
+}
+
+
+static inline uint ma_result_set_rows(const MYSQL *mysql)
+{
+ return ma_has_extended_type_info(mysql) ? 9 : 8;
+}
+
+MA_FIELD_EXTENSION *ma_field_extension_deep_dup(MA_MEM_ROOT *memroot,
+ const MA_FIELD_EXTENSION *from);
+
+MYSQL_FIELD *ma_duplicate_resultset_metadata(MYSQL_FIELD *fields, size_t count,
+ MA_MEM_ROOT *memroot);
+
+extern void ma_save_session_track_info(void *ptr, enum enum_mariadb_status_info type, ...);
+
+#define ma_status_callback(mysql, last_status)\
+ if ((mysql)->server_status != last_status && \
+ (mysql)->options.extension->status_callback != ma_save_session_track_info)\
+ {\
+ (mysql)->options.extension->status_callback((mysql)->options.extension->status_data,\
+ STATUS_TYPE, (mysql)->server_status);\
+ }
+
+#endif
diff --git a/libmariadb/include/ma_pthread.h b/libmariadb/include/ma_pthread.h
new file mode 100644
index 00000000..c01242fc
--- /dev/null
+++ b/libmariadb/include/ma_pthread.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Defines to make different thread packages compatible */
+
+#ifndef _my_pthread_h
+#define _my_pthread_h
+
+#if defined(_WIN32)
+#include <windows.h>
+typedef CRITICAL_SECTION pthread_mutex_t;
+#define pthread_mutex_init(A,B) InitializeCriticalSection(A)
+#define pthread_mutex_lock(A) (EnterCriticalSection(A),0)
+#define pthread_mutex_unlock(A) LeaveCriticalSection(A)
+#define pthread_mutex_destroy(A) DeleteCriticalSection(A)
+#define pthread_self() GetCurrentThreadId()
+#endif /* defined(_WIN32) */
+
+#endif /* _my_ptread_h */
diff --git a/libmariadb/include/ma_pvio.h b/libmariadb/include/ma_pvio.h
new file mode 100644
index 00000000..752ea034
--- /dev/null
+++ b/libmariadb/include/ma_pvio.h
@@ -0,0 +1,141 @@
+#ifndef _ma_pvio_h_
+#define _ma_pvio_h_
+#define cio_defined
+
+#ifdef HAVE_TLS
+#include <ma_tls.h>
+#else
+#define MARIADB_TLS void
+#endif
+
+/* CONC-492: Allow to build plugins outside of MariaDB Connector/C
+ source tree wnen ma_global.h was not included. */
+#if !defined(_global_h) && !defined(MY_GLOBAL_INCLUDED)
+typedef unsigned char uchar;
+#endif
+
+#define PVIO_SET_ERROR if (pvio->set_error) \
+ pvio->set_error
+
+#define PVIO_READ_AHEAD_CACHE_SIZE 16384
+#define PVIO_READ_AHEAD_CACHE_MIN_SIZE 2048
+#define PVIO_EINTR_TRIES 2
+
+struct st_ma_pvio_methods;
+typedef struct st_ma_pvio_methods PVIO_METHODS;
+
+#define IS_PVIO_ASYNC(a) \
+ ((a)->mysql && (a)->mysql->options.extension && (a)->mysql->options.extension->async_context)
+
+#define IS_PVIO_ASYNC_ACTIVE(a) \
+ (IS_PVIO_ASYNC(a)&& (a)->mysql->options.extension->async_context->active)
+
+#define IS_MYSQL_ASYNC(a) \
+ ((a)->options.extension && (a)->options.extension->async_context)
+
+#define IS_MYSQL_ASYNC_ACTIVE(a) \
+ (IS_MYSQL_ASYNC(a)&& (a)->options.extension->async_context->active)
+
+enum enum_pvio_timeout {
+ PVIO_CONNECT_TIMEOUT= 0,
+ PVIO_READ_TIMEOUT,
+ PVIO_WRITE_TIMEOUT
+};
+
+enum enum_pvio_io_event
+{
+ VIO_IO_EVENT_READ,
+ VIO_IO_EVENT_WRITE,
+ VIO_IO_EVENT_CONNECT
+};
+
+enum enum_pvio_type {
+ PVIO_TYPE_UNIXSOCKET= 0,
+ PVIO_TYPE_SOCKET,
+ PVIO_TYPE_NAMEDPIPE,
+ PVIO_TYPE_SHAREDMEM,
+};
+
+enum enum_pvio_operation {
+ PVIO_READ= 0,
+ PVIO_WRITE=1
+};
+
+#define SHM_DEFAULT_NAME "MYSQL"
+
+struct st_pvio_callback;
+
+typedef struct st_pvio_callback {
+ void (*callback)(MYSQL *mysql, uchar *buffer, size_t size);
+ struct st_pvio_callback *next;
+} PVIO_CALLBACK;
+
+struct st_ma_pvio {
+ void *data;
+ /* read ahead cache */
+ uchar *cache;
+ uchar *cache_pos;
+ size_t cache_size;
+ enum enum_pvio_type type;
+ int timeout[3];
+ int ssl_type; /* todo: change to enum (ssl plugins) */
+ MARIADB_TLS *ctls;
+ MYSQL *mysql;
+ PVIO_METHODS *methods;
+ void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...);
+ void (*callback)(MARIADB_PVIO *pvio, my_bool is_read, const uchar *buffer, size_t length);
+ size_t bytes_read;
+ size_t bytes_sent;
+};
+
+typedef struct st_ma_pvio_cinfo
+{
+ const char *host;
+ const char *unix_socket;
+ int port;
+ enum enum_pvio_type type;
+ MYSQL *mysql;
+} MA_PVIO_CINFO;
+
+struct st_ma_pvio_methods
+{
+ my_bool (*set_timeout)(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
+ int (*get_timeout)(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
+ ssize_t (*read)(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ ssize_t (*async_read)(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ ssize_t (*write)(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
+ ssize_t (*async_write)(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
+ int (*wait_io_or_timeout)(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
+ int (*blocking)(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value);
+ my_bool (*connect)(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
+ my_bool (*close)(MARIADB_PVIO *pvio);
+ int (*fast_send)(MARIADB_PVIO *pvio);
+ int (*keepalive)(MARIADB_PVIO *pvio);
+ my_bool (*get_handle)(MARIADB_PVIO *pvio, void *handle);
+ my_bool (*is_blocking)(MARIADB_PVIO *pvio);
+ my_bool (*is_alive)(MARIADB_PVIO *pvio);
+ my_bool (*has_data)(MARIADB_PVIO *pvio, ssize_t *data_len);
+ int(*shutdown)(MARIADB_PVIO *pvio);
+};
+
+/* Function prototypes */
+MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo);
+void ma_pvio_close(MARIADB_PVIO *pvio);
+ssize_t ma_pvio_cache_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ssize_t ma_pvio_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ssize_t ma_pvio_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
+int ma_pvio_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
+my_bool ma_pvio_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
+int ma_pvio_fast_send(MARIADB_PVIO *pvio);
+int ma_pvio_keepalive(MARIADB_PVIO *pvio);
+my_socket ma_pvio_get_socket(MARIADB_PVIO *pvio);
+my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio);
+my_bool ma_pvio_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode);
+my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio);
+int ma_pvio_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
+my_bool ma_pvio_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
+my_bool ma_pvio_is_alive(MARIADB_PVIO *pvio);
+my_bool ma_pvio_get_handle(MARIADB_PVIO *pvio, void *handle);
+my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *length);
+
+#endif /* _ma_pvio_h_ */
diff --git a/libmariadb/include/ma_server_error.h b/libmariadb/include/ma_server_error.h
new file mode 100644
index 00000000..6e776630
--- /dev/null
+++ b/libmariadb/include/ma_server_error.h
@@ -0,0 +1,2 @@
+/* This file exists for compatibility only */
+#include "mysqld_error.h"
diff --git a/libmariadb/include/ma_sha1.h b/libmariadb/include/ma_sha1.h
new file mode 100644
index 00000000..2748f114
--- /dev/null
+++ b/libmariadb/include/ma_sha1.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ Copyright (C) 2012 Monty Program AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*****************************************************************************/
+
+/* This code came from the PHP project, initially written by
+ Stefan Esser */
+
+#ifndef SHA1_H
+#define SHA1_H
+
+#define SHA1_MAX_LENGTH 20
+#define SCRAMBLE_LENGTH 20
+#define SCRAMBLE_LENGTH_323 8
+
+/* SHA1 context. */
+typedef struct {
+ uint32 state[5]; /* state (ABCD) */
+ uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} _MA_SHA1_CTX;
+
+void ma_SHA1Init(_MA_SHA1_CTX *);
+void ma_SHA1Update(_MA_SHA1_CTX *, const unsigned char *, size_t);
+void ma_SHA1Final(unsigned char[20], _MA_SHA1_CTX *);
+
+#endif
diff --git a/libmariadb/include/ma_string.h b/libmariadb/include/ma_string.h
new file mode 100644
index 00000000..10325387
--- /dev/null
+++ b/libmariadb/include/ma_string.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2012 by MontyProgram AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* defines for the libmariadb library */
+
+#ifndef _ma_string_h_
+#define _ma_string_h_
+
+#include <string.h>
+
+typedef enum {
+ MY_GCVT_ARG_FLOAT,
+ MY_GCVT_ARG_DOUBLE
+} my_gcvt_arg_type;
+
+size_t ma_fcvt(double x, int precision, char *to, my_bool *error);
+size_t ma_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
+ my_bool *error);
+char *ma_ll2str(long long val,char *dst, int radix);
+
+#define MAX_ENV_SIZE 1024
+
+static inline my_bool ma_check_env_str(const char *env)
+{
+ unsigned int i;
+
+ if (!env)
+ return 1;
+
+ for (i=0; i < MAX_ENV_SIZE; i++)
+ {
+ if (env[i] == 0)
+ break;
+ }
+ if (i >= MAX_ENV_SIZE)
+ return 1;
+ return 0;
+}
+
+#endif
diff --git a/libmariadb/include/ma_sys.h b/libmariadb/include/ma_sys.h
new file mode 100644
index 00000000..9b6cd007
--- /dev/null
+++ b/libmariadb/include/ma_sys.h
@@ -0,0 +1,539 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+#ifndef _my_sys_h
+#define _my_sys_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_AIOWAIT
+#include <sys/asynch.h> /* Used by record-cache */
+typedef struct my_aio_result {
+ aio_result_t result;
+ int pending;
+} my_aio_result;
+#endif
+
+#ifndef _mariadb_ctype_h
+#include <mariadb_ctype.h> /* for MARIADB_CHARSET_INFO */
+#endif
+
+#include <stdarg.h>
+
+#define MYSYS_PROGRAM_USES_CURSES() \
+do {\
+ ma_error_handler_hook = ma_message_curses;\
+ mysys_uses_curses=1;\
+} while(0)
+#define MYSYS_PROGRAM_DONT_USE_CURSES() \
+do {\
+ ma_error_handler_hook = ma_message_no_curses; \
+ mysys_uses_curses=0; \
+} while(0)
+#define MY_INIT(name) \
+do {\
+ ma_progname= name;\
+ ma_init();\
+} while(0)
+
+#define MAXMAPS (4) /* Number of error message maps */
+#define ERRMOD (1000) /* Max number of errors in a map */
+#define ERRMSGSIZE (SC_MAXWIDTH) /* Max length of a error message */
+#define NRERRBUFFS (2) /* Buffers for parameters */
+#define MY_FILE_ERROR ((uint) ~0)
+
+ /* General bitmaps for my_func's */
+#define MY_FFNF 1 /* Fatal if file not found */
+#define MY_FNABP 2 /* Fatal if not all bytes read/written */
+#define MY_NABP 4 /* Error if not all bytes read/written */
+#define MY_FAE 8 /* Fatal if any error */
+#define MY_WME 16 /* Write message on error */
+#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */
+#define MY_RAID 64 /* Support for RAID (not the "Johnson&Johnson"-s one ;) */
+#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
+#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */
+#define MY_COPYTIME 64 /* my_redel() copies time */
+#define MY_DELETE_OLD 256 /* my_create_with_symlink() */
+#define MY_RESOLVE_LINK 128 /* my_realpath(); Only resolve links */
+#define MY_HOLD_ORIGINAL_MODES 128 /* my_copy() holds to file modes */
+#define MY_REDEL_MAKE_BACKUP 256
+#define MY_SEEK_NOT_DONE 32 /* my_lock may have to do a seek */
+#define MY_DONT_WAIT 64 /* my_lock() don't wait if can't lock */
+#define MY_ZEROFILL 32 /* ma_malloc(), fill array with zero */
+#define MY_ALLOW_ZERO_PTR 64 /* ma_realloc() ; zero ptr -> malloc */
+#define MY_FREE_ON_ERROR 128 /* ma_realloc() ; Free old ptr on error */
+#define MY_HOLD_ON_ERROR 256 /* ma_realloc() ; Return old ptr on error */
+#define MY_THREADSAFE 128 /* pread/pwrite: Don't allow interrupts */
+#define MY_DONT_OVERWRITE_FILE 1024 /* my_copy; Don't overwrite file */
+
+#define MY_CHECK_ERROR 1 /* Params to ma_end; Check open-close */
+#define MY_GIVE_INFO 2 /* Give time info about process*/
+
+#define ME_HIGHBYTE 8 /* Shift for colours */
+#define ME_NOCUR 1 /* Don't use curses message */
+#define ME_OLDWIN 2 /* Use old window */
+#define ME_BELL 4 /* Ring bell then printing message */
+#define ME_HOLDTANG 8 /* Don't delete last keys */
+#define ME_WAITTOT 16 /* Wait for errtime secs of for a action */
+#define ME_WAITTANG 32 /* Wait for a user action */
+#define ME_NOREFRESH 64 /* Don't refresh screen */
+#define ME_NOINPUT 128 /* Don't use the input library */
+#define ME_COLOUR1 ((1 << ME_HIGHBYTE)) /* Possibly error-colours */
+#define ME_COLOUR2 ((2 << ME_HIGHBYTE))
+#define ME_COLOUR3 ((3 << ME_HIGHBYTE))
+
+ /* My seek flags */
+#define MY_SEEK_SET 0
+#define MY_SEEK_CUR 1
+#define MY_SEEK_END 2
+
+ /* My charsets_list flags */
+#define MY_NO_SETS 0
+#define MY_COMPILED_SETS 1 /* show compiled-in sets */
+#define MY_CONFIG_SETS 2 /* sets that have a *.conf file */
+#define MY_INDEX_SETS 4 /* all sets listed in the Index file */
+#define MY_LOADED_SETS 8 /* the sets that are currently loaded */
+
+ /* Some constants */
+#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
+#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
+#define MIN_COMPRESS_LENGTH 150 /* Don't compress small bl. */
+#define KEYCACHE_BLOCK_SIZE 1024
+
+ /* root_alloc flags */
+#define MY_KEEP_PREALLOC 1
+
+ /* defines when allocating data */
+
+#define my_checkmalloc() (0)
+#undef TERMINATE
+#define TERMINATE(A) {}
+#define QUICK_SAFEMALLOC
+#define NORMAL_SAFEMALLOC
+#define ma_malloc_ci(SZ,FLAG) ma_malloc( SZ, FLAG )
+#define CALLER_INFO_PROTO /* nothing */
+#define CALLER_INFO /* nothing */
+#define ORIG_CALLER_INFO /* nothing */
+
+#ifdef HAVE_ALLOCA
+#if defined(_AIX) && !defined(__GNUC__)
+#pragma alloca
+#endif /* _AIX */
+#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H)
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+#endif /* GNUC */
+#define my_alloca(SZ) alloca((size_t) (SZ))
+#define my_afree(PTR) {}
+#else
+#define my_alloca(SZ) ma_malloc(SZ,MYF(0))
+#define my_afree(PTR) ma_free(PTR)
+#endif /* HAVE_ALLOCA */
+
+#ifndef errno
+#ifdef HAVE_ERRNO_AS_DEFINE
+#include <errno.h> /* errno is a define */
+#else
+extern int errno; /* declare errno */
+#endif
+#endif
+extern const char ** NEAR my_errmsg[];
+extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
+/* tbr
+extern int (*ma_error_handler_hook)(uint my_err, const char *str,myf MyFlags);
+extern int (*fatal_ma_error_handler_hook)(uint my_err, const char *str,
+ myf MyFlags);
+*/
+
+/* charsets */
+/* tbr
+extern uint get_charset_number(const char *cs_name);
+extern const char *get_charset_name(uint cs_number);
+extern my_bool set_default_charset(uint cs, myf flags);
+extern my_bool set_default_charset_by_name(const char *cs_name, myf flags);
+extern void free_charsets(void);
+extern char *list_charsets(myf want_flags);
+extern char *get_charsets_dir(char *buf);
+*/
+extern MARIADB_CHARSET_INFO *get_charset(uint cs_number, myf flags);
+extern MARIADB_CHARSET_INFO *get_charset_by_name(const char *cs_name);
+extern MARIADB_CHARSET_INFO *get_charset_by_nr(uint cs_number);
+
+/* string functions */
+char *ma_strmake(register char *dst, register const char *src, size_t length);
+
+/* statistics */
+#ifdef TBR
+extern ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests,
+ _my_cache_read;
+extern ulong _my_blocks_used,_my_blocks_changed;
+extern ulong ma_file_opened,ma_stream_opened, ma_tmp_file_created;
+extern my_bool key_cache_inited;
+
+ /* Point to current ma_message() */
+extern void (*my_sigtstp_cleanup)(void),
+ /* Executed before jump to shell */
+ (*my_sigtstp_restart)(void),
+ (*my_abort_hook)(int);
+ /* Executed when coming from shell */
+extern int NEAR ma_umask, /* Default creation mask */
+ NEAR ma_umask_dir,
+ NEAR my_recived_signals, /* Signals we have got */
+ NEAR my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */
+ NEAR ma_dont_interrupt; /* call remember_intr when set */
+extern my_bool NEAR mysys_uses_curses, ma_use_symdir;
+extern size_t lCurMemory,lMaxMemory; /* from safemalloc */
+
+extern ulong ma_default_record_cache_size;
+extern my_bool NEAR ma_disable_locking,NEAR ma_disable_async_io,
+ NEAR ma_disable_flush_key_blocks, NEAR ma_disable_symlinks;
+extern char wild_many,wild_one,wild_prefix;
+extern const char *charsets_dir;
+extern char *defaults_extra_file;
+typedef struct wild_file_pack /* Struct to hold info when selecting files */
+{
+ uint wilds; /* How many wildcards */
+ uint not_pos; /* Start of not-these-files */
+ my_string *wild; /* Pointer to wildcards */
+} WF_PACK;
+
+struct my_rnd_struct {
+ unsigned long seed1,seed2,max_value;
+ double max_value_dbl;
+};
+
+#endif
+typedef struct st_typelib { /* Different types saved here */
+ uint count; /* How many types */
+ const char *name; /* Name of typelib */
+ const char **type_names;
+} TYPELIB;
+
+enum cache_type {READ_CACHE,WRITE_CACHE,READ_FIFO,READ_NET,WRITE_NET};
+enum flush_type { FLUSH_KEEP, FLUSH_RELEASE, FLUSH_IGNORE_CHANGED,
+ FLUSH_FORCE_WRITE};
+
+typedef struct st_record_cache /* Used when caching records */
+{
+ File file;
+ int rc_seek,error,inited;
+ uint rc_length,read_length,reclength;
+ my_off_t rc_record_pos,end_of_file;
+ unsigned char *rc_buff,*rc_buff2,*rc_pos,*rc_end,*rc_request_pos;
+#ifdef HAVE_AIOWAIT
+ int use_async_io;
+ my_aio_result aio_result;
+#endif
+ enum cache_type type;
+} RECORD_CACHE;
+
+
+typedef struct st_dynamic_array {
+ char *buffer;
+ uint elements,max_element;
+ uint alloc_increment;
+ uint size_of_element;
+} DYNAMIC_ARRAY;
+
+typedef struct st_dynamic_string {
+ char *str;
+ size_t length,max_length,alloc_increment;
+} DYNAMIC_STRING;
+
+
+typedef struct st_io_cache /* Used when caching files */
+{
+ my_off_t pos_in_file,end_of_file;
+ unsigned char *rc_pos,*rc_end,*buffer,*rc_request_pos;
+ int (*read_function)(struct st_io_cache *,unsigned char *,uint);
+ char *file_name; /* if used with 'open_cached_file' */
+ char *dir,*prefix;
+ File file;
+ int seek_not_done,error;
+ uint buffer_length,read_length;
+ myf myflags; /* Flags used to my_read/my_write */
+ enum cache_type type;
+#ifdef HAVE_AIOWAIT
+ uint inited;
+ my_off_t aio_read_pos;
+ my_aio_result aio_result;
+#endif
+} IO_CACHE;
+
+typedef int (*qsort2_cmp)(const void *, const void *, const void *);
+
+ /* defines for mf_iocache */
+
+ /* Test if buffer is inited */
+#define my_b_clear(info) do{(info)->buffer= 0;} while (0)
+#define my_b_inited(info) ((info)->buffer)
+#define my_b_EOF INT_MIN
+
+#define my_b_read(info,Buffer,Count) \
+ ((info)->rc_pos + (Count) <= (info)->rc_end ?\
+ (memcpy((Buffer),(info)->rc_pos,(size_t) (Count)), \
+ ((info)->rc_pos+=(Count)),0) :\
+ (*(info)->read_function)((info),(Buffer),(Count)))
+
+#define my_b_get(info) \
+ ((info)->rc_pos != (info)->rc_end ?\
+ ((info)->rc_pos++, (int) (uchar) (info)->rc_pos[-1]) :\
+ _my_b_get(info))
+
+#define my_b_write(info,Buffer,Count) \
+ ((info)->rc_pos + (Count) <= (info)->rc_end ?\
+ (memcpy((info)->rc_pos,(Buffer),(size_t) (Count)), \
+ ((info)->rc_pos+=(Count)),0) :\
+ _my_b_write((info),(Buffer),(Count)))
+
+ /* my_b_write_byte doesn't have any err-check */
+#define my_b_write_byte(info,chr) \
+ (((info)->rc_pos < (info)->rc_end) ?\
+ ((*(info)->rc_pos++)=(chr)) :\
+ (_my_b_write((info),0,0) , ((*(info)->rc_pos++)=(chr))))
+
+#define my_b_fill_cache(info) \
+ (((info)->rc_end=(info)->rc_pos),(*(info)->read_function)((info),0,0))
+
+#define my_b_tell(info) ((info)->pos_in_file + \
+ ((info)->rc_pos - (info)->rc_request_pos))
+
+#define my_b_bytes_in_cache(info) ((uint) ((info)->rc_end - (info)->rc_pos))
+
+typedef struct st_changeable_var {
+ const char *name; /* Name of variable */
+ long *varptr; /* Pointer to variable */
+ long def_value, /* Default value */
+ min_value, /* Min allowed value */
+ max_value, /* Max allowed value */
+ sub_size, /* Subtract this from given value */
+ block_size; /* Value should be a mult. of this */
+} CHANGEABLE_VAR;
+
+
+/* structs for ma_alloc_root */
+
+#ifndef ST_MA_USED_MEM_DEFINED
+#define ST_MA_USED_MEM_DEFINED
+typedef struct st_ma_used_mem { /* struct for once_alloc */
+ struct st_ma_used_mem *next; /* Next block in use */
+ size_t left; /* memory left in block */
+ size_t size; /* Size of block */
+} MA_USED_MEM;
+
+typedef struct st_ma_mem_root {
+ MA_USED_MEM *free;
+ MA_USED_MEM *used;
+ MA_USED_MEM *pre_alloc;
+ size_t min_malloc;
+ size_t block_size;
+ unsigned int block_num;
+ unsigned int first_block_usage;
+ void (*error_handler)(void);
+} MA_MEM_ROOT;
+#endif
+
+ /* Prototypes for mysys and my_func functions */
+
+extern void * _mymalloc(size_t uSize,const char *sFile,
+ uint uLine, myf MyFlag);
+extern void * _myrealloc(void * pPtr,size_t uSize,const char *sFile,
+ uint uLine, myf MyFlag);
+extern void *ma_multi_malloc(myf MyFlags, ...);
+extern void _myfree(void * pPtr,const char *sFile,uint uLine, myf MyFlag);
+extern int _sanity(const char *sFile,unsigned int uLine);
+#ifndef TERMINATE
+extern void TERMINATE(FILE *file);
+#endif
+extern void ma_init_glob_errs(void);
+extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags);
+extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags);
+extern int my_fclose(FILE *fd,myf MyFlags);
+extern int my_chsize(File fd,my_off_t newlength,myf MyFlags);
+extern int ma_error _VARARGS((int nr,myf MyFlags, ...));
+extern int ma_printf_error _VARARGS((uint my_err, const char *format,
+ myf MyFlags, ...)
+ __attribute__ ((format (printf, 2, 4))));
+extern int ma_vsnprintf( char *str, size_t n,
+ const char *format, va_list ap );
+extern int ma_snprintf(char* to, size_t n, const char* fmt, ...);
+extern int ma_message(uint my_err, const char *str,myf MyFlags);
+extern int _mariadb_stderr_out(unsigned int error, const char *errmsg, myf MyFlags);
+
+extern void ma_init(void);
+extern void ma_end(int infoflag);
+extern int my_redel(const char *from, const char *to, int MyFlags);
+extern int my_copystat(const char *from, const char *to, int MyFlags);
+extern my_string my_filename(File fd);
+
+#ifndef THREAD
+extern void dont_break(void);
+extern void allow_break(void);
+#else
+#define dont_break()
+#define allow_break()
+#endif
+
+extern void caseup(my_string str,uint length);
+extern void casedn(my_string str,uint length);
+extern void caseup_str(my_string str);
+extern void casedn_str(my_string str);
+extern void case_sort(my_string str,uint length);
+extern uint ma_dirname_part(my_string to,const char *name);
+extern uint ma_dirname_length(const char *name);
+#define base_name(A) ((A)+dirname_length(A))
+extern int test_if_hard_path(const char *dir_name);
+extern char *ma_convert_dirname(my_string name);
+extern void to_unix_path(my_string name);
+extern my_string ma_fn_ext(const char *name);
+extern my_string fn_same(my_string toname,const char *name,int flag);
+extern my_string ma_fn_format(my_string to,const char *name,const char *dsk,
+ const char *form,int flag);
+extern size_s ma_strlength(const char *str);
+extern void ma_pack_dirname(my_string to,const char *from);
+extern uint unma_pack_dirname(my_string to,const char *from);
+extern uint ma_cleanup_dirname(my_string to,const char *from);
+extern uint ma_system_filename(my_string to,const char *from);
+extern my_string ma_unpack_filename(my_string to,const char *from);
+extern my_string ma_intern_filename(my_string to,const char *from);
+extern my_string directory_file_name(my_string dst, const char *src);
+extern int pack_filename(my_string to, const char *name, size_s max_length);
+extern my_string my_path(my_string to,const char *progname,
+ const char *own_pathname_part);
+extern my_string my_load_path(my_string to, const char *path,
+ const char *own_path_prefix);
+extern int wild_compare(const char *str,const char *wildstr);
+extern my_string my_strcasestr(const char *src,const char *suffix);
+extern int my_strcasecmp(const char *s,const char *t);
+extern int my_strsortcmp(const char *s,const char *t);
+extern int my_casecmp(const char *s,const char *t,uint length);
+extern int my_sortcmp(const char *s,const char *t,uint length);
+extern int my_sortncmp(const char *s,uint s_len, const char *t,uint t_len);
+#ifdef TBR
+extern WF_PACK *wf_comp(my_string str);
+extern int wf_test(struct wild_file_pack *wf_pack,const char *name);
+extern void wf_end(struct wild_file_pack *buffer);
+extern size_s strip_sp(my_string str);
+extern void get_date(my_string to,int timeflag,time_t use_time);
+extern void soundex(my_string out_pntr, my_string in_pntr,pbool remove_garbage);
+extern int init_record_cache(RECORD_CACHE *info,uint cachesize,File file,
+ uint reclength,enum cache_type type,
+ pbool use_async_io);
+extern int read_cache_record(RECORD_CACHE *info,unsigned char *to);
+extern int end_record_cache(RECORD_CACHE *info);
+extern int write_cache_record(RECORD_CACHE *info,my_off_t filepos,
+ const unsigned char *record,uint length);
+extern int flush_write_cache(RECORD_CACHE *info);
+extern long my_clock(void);
+extern sig_handler sigtstp_handler(int signal_number);
+extern void handle_recived_signals(void);
+extern int init_key_cache(ulong use_mem,ulong leave_this_much_mem);
+extern unsigned char *key_cache_read(File file,my_off_t filepos,unsigned char* buff,uint length,
+ uint block_length,int return_buffer);
+extern int key_cache_write(File file,my_off_t filepos,unsigned char* buff,uint length,
+ uint block_length,int force_write);
+extern int flush_key_blocks(int file, enum flush_type type);
+extern void end_key_cache(void);
+extern sig_handler my_set_alarm_variable(int signo);
+extern void my_string_ptr_sort(void *base,uint items,size_s size);
+extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,
+ size_s size_of_element,uchar *buffer[]);
+extern qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size,
+ qsort2_cmp cmp, void *cmp_argument);
+extern qsort2_cmp get_ptr_compare(uint);
+extern int init_io_cache(IO_CACHE *info,File file,uint cachesize,
+ enum cache_type type,my_off_t seek_offset,
+ pbool use_async_io, myf cache_myflags);
+extern my_bool reinit_io_cache(IO_CACHE *info,enum cache_type type,
+ my_off_t seek_offset,pbool use_async_io,
+ pbool clear_cache);
+extern int _my_b_read(IO_CACHE *info,unsigned char *Buffer,uint Count);
+extern int _my_b_net_read(IO_CACHE *info,unsigned char *Buffer,uint Count);
+extern int _my_b_get(IO_CACHE *info);
+extern int _my_b_async_read(IO_CACHE *info,unsigned char *Buffer,uint Count);
+extern int _my_b_write(IO_CACHE *info,const unsigned char *Buffer,uint Count);
+extern int my_block_write(IO_CACHE *info, const unsigned char *Buffer,
+ uint Count, my_off_t pos);
+extern int flush_io_cache(IO_CACHE *info);
+extern int end_io_cache(IO_CACHE *info);
+extern uint my_b_fill(IO_CACHE *info);
+extern void my_b_seek(IO_CACHE *info,my_off_t pos);
+extern uint my_b_gets(IO_CACHE *info, char *to, uint max_length);
+extern uint my_b_printf(IO_CACHE *info, const char* fmt, ...);
+extern uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list ap);
+extern my_bool open_cached_file(IO_CACHE *cache,const char *dir,
+ const char *prefix, uint cache_size,
+ myf cache_myflags);
+extern my_bool real_open_cached_file(IO_CACHE *cache);
+extern void close_cached_file(IO_CACHE *cache);
+File create_temp_file(char *to, const char *dir, const char *pfx,
+ int mode, myf MyFlags);
+#define ma_init_dynamic_array(A,B,C,D) init_dynamic_array(A,B,C,D CALLER_INFO)
+#endif
+extern my_bool ma_init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size,
+ uint init_alloc,uint alloc_increment CALLER_INFO_PROTO);
+#define ma_init_dynamic_array_ci(A,B,C,D) ma_init_dynamic_array(A,B,C,D ORIG_CALLER_INFO)
+extern my_bool ma_insert_dynamic(DYNAMIC_ARRAY *array,void * element);
+extern unsigned char *ma_alloc_dynamic(DYNAMIC_ARRAY *array);
+extern unsigned char *ma_pop_dynamic(DYNAMIC_ARRAY*);
+extern my_bool ma_set_dynamic(DYNAMIC_ARRAY *array,void * element,uint array_index);
+extern void ma_get_dynamic(DYNAMIC_ARRAY *array,void * element,uint array_index);
+extern void ma_delete_dynamic(DYNAMIC_ARRAY *array);
+extern void ma_delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index);
+extern void ma_freeze_size(DYNAMIC_ARRAY *array);
+#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
+#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
+#define push_dynamic(A,B) ma_insert_dynamic(A,B)
+
+extern int ma_find_type(my_string x,TYPELIB *typelib,uint full_name);
+extern void ma_make_type(my_string to,uint nr,TYPELIB *typelib);
+extern const char *ma_get_type(TYPELIB *typelib,uint nr);
+extern my_bool ma_init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
+ size_t init_alloc, size_t alloc_increment);
+extern my_bool ma_dynstr_append(DYNAMIC_STRING *str, const char *append);
+extern my_bool ma_dynstr_append_quoted(DYNAMIC_STRING *str,
+ const char *append, size_t len,
+ char quote);
+my_bool ma_dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
+ size_t length);
+extern my_bool ma_dynstr_set(DYNAMIC_STRING *str, const char *init_str);
+extern my_bool ma_dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size);
+extern void ma_dynstr_free(DYNAMIC_STRING *str);
+void set_all_changeable_vars(CHANGEABLE_VAR *vars);
+my_bool set_changeable_var(my_string str,CHANGEABLE_VAR *vars);
+my_bool set_changeable_varval(const char *var, ulong val,
+ CHANGEABLE_VAR *vars);
+#define ma_alloc_root_inited(A) ((A)->min_malloc != 0)
+void ma_init_alloc_root(MA_MEM_ROOT *mem_root, size_t block_size, size_t pre_alloc_size);
+void *ma_alloc_root(MA_MEM_ROOT *mem_root, size_t Size);
+void ma_free_root(MA_MEM_ROOT *root, myf MyFLAGS);
+char *ma_strdup_root(MA_MEM_ROOT *root,const char *str);
+char *ma_memdup_root(MA_MEM_ROOT *root,const char *str, size_t len);
+void ma_free_defaults(char **argv);
+void ma_print_defaults(const char *conf_file, const char **groups);
+ulong checksum(const unsigned char *mem, uint count);
+
+#if defined(_MSC_VER) && !defined(_WIN32)
+extern void sleep(int sec);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _my_sys_h */
diff --git a/libmariadb/include/ma_tls.h b/libmariadb/include/ma_tls.h
new file mode 100644
index 00000000..ec8bc239
--- /dev/null
+++ b/libmariadb/include/ma_tls.h
@@ -0,0 +1,163 @@
+#ifndef _ma_tls_h_
+#define _ma_tls_h_
+
+enum enum_pvio_tls_type {
+ SSL_TYPE_DEFAULT=0,
+#ifdef _WIN32
+ SSL_TYPE_SCHANNEL,
+#endif
+ SSL_TYPE_OPENSSL,
+ SSL_TYPE_GNUTLS
+};
+
+#define PROTOCOL_SSLV3 0
+#define PROTOCOL_TLS_1_0 1
+#define PROTOCOL_TLS_1_1 2
+#define PROTOCOL_TLS_1_2 3
+#define PROTOCOL_TLS_1_3 4
+#define PROTOCOL_UNKNOWN 5
+#define PROTOCOL_MAX PROTOCOL_TLS_1_3
+
+#define TLS_VERSION_LENGTH 64
+extern char tls_library_version[TLS_VERSION_LENGTH];
+
+typedef struct st_ma_pvio_tls {
+ void *data;
+ MARIADB_PVIO *pvio;
+ void *ssl;
+} MARIADB_TLS;
+
+/* Function prototypes */
+
+/* ma_tls_start
+ initializes the ssl library
+ Parameter:
+ errmsg pointer to error message buffer
+ errmsg_len length of error message buffer
+ Returns:
+ 0 success
+ 1 if an error occurred
+ Notes:
+ On success the global variable ma_tls_initialized will be set to 1
+*/
+int ma_tls_start(char *errmsg, size_t errmsg_len);
+
+/* ma_tls_end
+ unloads/deinitializes ssl library and unsets global variable
+ ma_tls_initialized
+*/
+void ma_tls_end(void);
+
+/* ma_tls_init
+ creates a new SSL structure for a SSL connection and loads
+ client certificates
+
+ Parameters:
+ MYSQL a mysql structure
+ Returns:
+ void * a pointer to internal SSL structure
+*/
+void * ma_tls_init(MYSQL *mysql);
+
+/* ma_tls_connect
+ performs SSL handshake
+ Parameters:
+ MARIADB_TLS MariaDB SSL container
+ Returns:
+ 0 success
+ 1 error
+*/
+my_bool ma_tls_connect(MARIADB_TLS *ctls);
+
+/* ma_tls_read
+ reads up to length bytes from socket
+ Parameters:
+ ctls MariaDB SSL container
+ buffer read buffer
+ length buffer length
+ Returns:
+ 0-n bytes read
+ -1 if an error occurred
+*/
+ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length);
+
+/* ma_tls_write
+ write buffer to socket
+ Parameters:
+ ctls MariaDB SSL container
+ buffer write buffer
+ length buffer length
+ Returns:
+ 0-n bytes written
+ -1 if an error occurred
+*/
+ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length);
+
+/* ma_tls_close
+ closes SSL connection and frees SSL structure which was previously
+ created by ma_tls_init call
+ Parameters:
+ MARIADB_TLS MariaDB SSL container
+ Returns:
+ 0 success
+ 1 error
+*/
+my_bool ma_tls_close(MARIADB_TLS *ctls);
+
+/* ma_tls_verify_server_cert
+ validation check of server certificate
+ Parameter:
+ MARIADB_TLS MariaDB SSL container
+ Returns:
+ ß success
+ 1 error
+*/
+int ma_tls_verify_server_cert(MARIADB_TLS *ctls);
+
+/* ma_tls_get_cipher
+ returns cipher for current ssl connection
+ Parameter:
+ MARIADB_TLS MariaDB SSL container
+ Returns:
+ cipher in use or
+ NULL on error
+*/
+const char *ma_tls_get_cipher(MARIADB_TLS *ssl);
+
+/* ma_tls_get_finger_print
+ returns SHA1 finger print of server certificate
+ Parameter:
+ MARIADB_TLS MariaDB SSL container
+ fp buffer for fingerprint
+ fp_len buffer length
+ Returns:
+ actual size of finger print
+*/
+unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int fp_len);
+
+/* ma_tls_get_protocol_version
+ returns protocol version number in use
+ Parameter:
+ MARIADB_TLS MariaDB SSL container
+ Returns:
+ protocol number
+*/
+int ma_tls_get_protocol_version(MARIADB_TLS *ctls);
+const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls);
+int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls);
+void ma_tls_set_connection(MYSQL *mysql);
+
+/* Function prototypes */
+MARIADB_TLS *ma_pvio_tls_init(MYSQL *mysql);
+my_bool ma_pvio_tls_connect(MARIADB_TLS *ctls);
+ssize_t ma_pvio_tls_read(MARIADB_TLS *ctls, const uchar *buffer, size_t length);
+ssize_t ma_pvio_tls_write(MARIADB_TLS *ctls, const uchar *buffer, size_t length);
+my_bool ma_pvio_tls_close(MARIADB_TLS *ctls);
+int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls);
+const char *ma_pvio_tls_cipher(MARIADB_TLS *ctls);
+my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list);
+my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio);
+void ma_pvio_tls_set_connection(MYSQL *mysql);
+void ma_pvio_tls_end();
+
+#endif /* _ma_tls_h_ */
diff --git a/libmariadb/include/mariadb/ma_io.h b/libmariadb/include/mariadb/ma_io.h
new file mode 100644
index 00000000..d39fc06e
--- /dev/null
+++ b/libmariadb/include/mariadb/ma_io.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2015 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+#ifndef _ma_io_h_
+#define _ma_io_h_
+
+
+#ifdef HAVE_REMOTEIO
+#include <curl/curl.h>
+#endif
+
+enum enum_file_type {
+ MA_FILE_NONE=0,
+ MA_FILE_LOCAL=1,
+ MA_FILE_REMOTE=2
+};
+
+typedef struct
+{
+ enum enum_file_type type;
+ void *ptr;
+} MA_FILE;
+
+#ifdef HAVE_REMOTEIO
+struct st_rio_methods {
+ MA_FILE *(*mopen)(const char *url, const char *mode);
+ int (*mclose)(MA_FILE *ptr);
+ int (*mfeof)(MA_FILE *file);
+ size_t (*mread)(void *ptr, size_t size, size_t nmemb, MA_FILE *file);
+ char * (*mgets)(char *ptr, size_t size, MA_FILE *file);
+};
+#endif
+
+/* function prototypes */
+MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql);
+int ma_close(MA_FILE *file);
+int ma_feof(MA_FILE *file);
+size_t ma_read(void *ptr, size_t size, size_t nmemb, MA_FILE *file);
+char *ma_gets(char *ptr, size_t size, MA_FILE *file);
+
+#endif
diff --git a/libmariadb/include/mariadb_async.h b/libmariadb/include/mariadb_async.h
new file mode 100644
index 00000000..d5c13b24
--- /dev/null
+++ b/libmariadb/include/mariadb_async.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2012 MariaDB Services and Kristian Nielsen
+ 2015,2020 MariaDB Corporation AB
+
+ This file is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Common definitions for MariaDB non-blocking client library. */
+
+#ifndef MYSQL_ASYNC_H
+#define MYSQL_ASYNC_H
+
+extern int my_connect_async(MARIADB_PVIO *pvio,
+ const struct sockaddr *name, uint namelen,
+ int vio_timeout);
+extern ssize_t my_recv_async(MARIADB_PVIO *pvio,
+ unsigned char *buf, size_t size, int timeout);
+extern ssize_t my_send_async(MARIADB_PVIO *pvio,
+ const unsigned char *buf, size_t size,
+ int timeout);
+extern my_bool my_io_wait_async(struct mysql_async_context *b,
+ enum enum_pvio_io_event event, int timeout);
+#ifdef HAVE_TLS
+extern ssize_t ma_tls_read_async(MARIADB_PVIO *pvio, const uchar *buf, size_t size);
+extern ssize_t ma_tls_write_async(MARIADB_PVIO *pvio, const uchar *buf, size_t size);
+#endif
+
+#endif /* MYSQL_ASYNC_H */
diff --git a/libmariadb/include/mariadb_com.h b/libmariadb/include/mariadb_com.h
new file mode 100644
index 00000000..67461b4f
--- /dev/null
+++ b/libmariadb/include/mariadb_com.h
@@ -0,0 +1,478 @@
+/************************************************************************************
+ Copyright (C) 2000, 2012 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
+ Monty Program AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*************************************************************************************/
+
+/*
+** Common definition between mysql server & client
+*/
+
+#ifndef _mysql_com_h
+#define _mysql_com_h
+
+
+#define NAME_CHAR_LEN 64
+#define NAME_LEN 256 /* Field/table name length */
+#define HOSTNAME_LENGTH 255
+#define SYSTEM_MB_MAX_CHAR_LENGTH 4
+#define USERNAME_CHAR_LENGTH 128
+#define USERNAME_LENGTH (USERNAME_CHAR_LENGTH * SYSTEM_MB_MAX_CHAR_LENGTH)
+#define SERVER_VERSION_LENGTH 60
+#define SQLSTATE_LENGTH 5
+#define SCRAMBLE_LENGTH 20
+#define SCRAMBLE_LENGTH_323 8
+
+#define LOCAL_HOST "localhost"
+#define LOCAL_HOST_NAMEDPIPE "."
+
+#if defined(_WIN32) && !defined( _CUSTOMCONFIG_)
+#define MARIADB_NAMEDPIPE "MySQL"
+#define MYSQL_SERVICENAME "MySql"
+#endif /* _WIN32 */
+
+/* for use in mysql client tools only */
+#define MYSQL_AUTODETECT_CHARSET_NAME "auto"
+#define BINCMP_FLAG 131072
+
+enum mysql_enum_shutdown_level
+{
+ SHUTDOWN_DEFAULT = 0,
+ KILL_QUERY= 254,
+ KILL_CONNECTION= 255
+};
+
+enum enum_server_command
+{
+ COM_SLEEP = 0,
+ COM_QUIT,
+ COM_INIT_DB,
+ COM_QUERY,
+ COM_FIELD_LIST,
+ COM_CREATE_DB,
+ COM_DROP_DB,
+ COM_REFRESH,
+ COM_SHUTDOWN,
+ COM_STATISTICS,
+ COM_PROCESS_INFO,
+ COM_CONNECT,
+ COM_PROCESS_KILL,
+ COM_DEBUG,
+ COM_PING,
+ COM_TIME = 15,
+ COM_DELAYED_INSERT,
+ COM_CHANGE_USER,
+ COM_BINLOG_DUMP,
+ COM_TABLE_DUMP,
+ COM_CONNECT_OUT = 20,
+ COM_REGISTER_SLAVE,
+ COM_STMT_PREPARE = 22,
+ COM_STMT_EXECUTE = 23,
+ COM_STMT_SEND_LONG_DATA = 24,
+ COM_STMT_CLOSE = 25,
+ COM_STMT_RESET = 26,
+ COM_SET_OPTION = 27,
+ COM_STMT_FETCH = 28,
+ COM_DAEMON= 29,
+ COM_UNSUPPORTED= 30,
+ COM_RESET_CONNECTION = 31,
+ COM_STMT_BULK_EXECUTE = 250,
+ COM_RESERVED_1 = 254, /* former COM_MULTI, now removed */
+ COM_END
+};
+
+
+#define NOT_NULL_FLAG 1 /* Field can't be NULL */
+#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
+#define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */
+#define MULTIPLE_KEY_FLAG 8 /* Field is part of a key */
+#define BLOB_FLAG 16 /* Field is a blob */
+#define UNSIGNED_FLAG 32 /* Field is unsigned */
+#define ZEROFILL_FLAG 64 /* Field is zerofill */
+#define BINARY_FLAG 128
+/* The following are only sent to new clients */
+#define ENUM_FLAG 256 /* field is an enum */
+#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */
+#define TIMESTAMP_FLAG 1024 /* Field is a timestamp */
+#define SET_FLAG 2048 /* field is a set */
+/* new since 3.23.58 */
+#define NO_DEFAULT_VALUE_FLAG 4096 /* Field doesn't have default value */
+#define ON_UPDATE_NOW_FLAG 8192 /* Field is set to NOW on UPDATE */
+/* end new */
+#define NUM_FLAG 32768 /* Field is num (for clients) */
+#define PART_KEY_FLAG 16384 /* Intern; Part of some key */
+#define GROUP_FLAG 32768 /* Intern: Group field */
+#define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */
+
+#define REFRESH_GRANT 1 /* Refresh grant tables */
+#define REFRESH_LOG 2 /* Start on new log file */
+#define REFRESH_TABLES 4 /* close all tables */
+#define REFRESH_HOSTS 8 /* Flush host cache */
+#define REFRESH_STATUS 16 /* Flush status variables */
+#define REFRESH_THREADS 32 /* Flush thread cache */
+#define REFRESH_SLAVE 64 /* Reset master info and restart slave
+ thread */
+#define REFRESH_MASTER 128 /* Remove all bin logs in the index
+ and truncate the index */
+
+/* The following can't be set with mysql_refresh() */
+#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
+#define REFRESH_FAST 32768 /* Intern flag */
+
+#define CLIENT_MYSQL 1
+#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
+#define CLIENT_LONG_FLAG 4 /* Get all column flags */
+#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
+#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */
+#define CLIENT_COMPRESS 32 /* Can use compression protocol */
+#define CLIENT_ODBC 64 /* Odbc client */
+#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */
+#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */
+#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */
+#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
+#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
+#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
+/* added in 4.x */
+#define CLIENT_PROTOCOL_41 512
+#define CLIENT_RESERVED 16384
+#define CLIENT_SECURE_CONNECTION 32768
+#define CLIENT_MULTI_STATEMENTS (1UL << 16)
+#define CLIENT_MULTI_RESULTS (1UL << 17)
+#define CLIENT_PS_MULTI_RESULTS (1UL << 18)
+#define CLIENT_PLUGIN_AUTH (1UL << 19)
+#define CLIENT_CONNECT_ATTRS (1UL << 20)
+#define CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA (1UL << 21)
+#define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1UL << 22)
+#define CLIENT_SESSION_TRACKING (1UL << 23)
+#define CLIENT_ZSTD_COMPRESSION (1UL << 26)
+#define CLIENT_PROGRESS (1UL << 29) /* client supports progress indicator */
+#define CLIENT_PROGRESS_OBSOLETE CLIENT_PROGRESS
+#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
+#define CLIENT_SSL_VERIFY_SERVER_CERT_OBSOLETE CLIENT_SSL_VERIFY_SERVER_CERT
+#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
+
+/* MariaDB specific capabilities */
+#define MARIADB_CLIENT_FLAGS 0xFFFFFFFF00000000ULL
+#define MARIADB_CLIENT_PROGRESS (1ULL << 32)
+#define MARIADB_CLIENT_RESERVED_1 (1ULL << 33) /* Former COM_MULTI, don't use */
+#define MARIADB_CLIENT_STMT_BULK_OPERATIONS (1ULL << 34)
+/* support of extended data type/format information, since 10.5.0 */
+#define MARIADB_CLIENT_EXTENDED_METADATA (1ULL << 35)
+/* Do not resend metadata for prepared statements, since 10.6*/
+#define MARIADB_CLIENT_CACHE_METADATA (1ULL << 36)
+
+#define IS_MARIADB_EXTENDED_SERVER(mysql)\
+ (!(mysql->server_capabilities & CLIENT_MYSQL))
+
+#define MARIADB_CLIENT_SUPPORTED_FLAGS (MARIADB_CLIENT_PROGRESS |\
+ MARIADB_CLIENT_STMT_BULK_OPERATIONS|\
+ MARIADB_CLIENT_EXTENDED_METADATA|\
+ MARIADB_CLIENT_CACHE_METADATA)
+
+#define CLIENT_SUPPORTED_FLAGS (CLIENT_MYSQL |\
+ CLIENT_FOUND_ROWS |\
+ CLIENT_LONG_FLAG |\
+ CLIENT_CONNECT_WITH_DB |\
+ CLIENT_NO_SCHEMA |\
+ CLIENT_COMPRESS |\
+ CLIENT_ODBC |\
+ CLIENT_LOCAL_FILES |\
+ CLIENT_IGNORE_SPACE |\
+ CLIENT_INTERACTIVE |\
+ CLIENT_SSL |\
+ CLIENT_IGNORE_SIGPIPE |\
+ CLIENT_TRANSACTIONS |\
+ CLIENT_PROTOCOL_41 |\
+ CLIENT_RESERVED |\
+ CLIENT_SECURE_CONNECTION |\
+ CLIENT_MULTI_STATEMENTS |\
+ CLIENT_MULTI_RESULTS |\
+ CLIENT_PROGRESS |\
+ CLIENT_SSL_VERIFY_SERVER_CERT |\
+ CLIENT_REMEMBER_OPTIONS |\
+ CLIENT_PLUGIN_AUTH |\
+ CLIENT_SESSION_TRACKING |\
+ CLIENT_CONNECT_ATTRS)
+#define CLIENT_CAPABILITIES (CLIENT_MYSQL | \
+ CLIENT_LONG_FLAG |\
+ CLIENT_TRANSACTIONS |\
+ CLIENT_SECURE_CONNECTION |\
+ CLIENT_MULTI_RESULTS | \
+ CLIENT_PS_MULTI_RESULTS |\
+ CLIENT_PROTOCOL_41 |\
+ CLIENT_PLUGIN_AUTH |\
+ CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \
+ CLIENT_SESSION_TRACKING |\
+ CLIENT_CONNECT_ATTRS)
+
+#define CLIENT_DEFAULT_FLAGS ((CLIENT_SUPPORTED_FLAGS & ~CLIENT_COMPRESS)\
+ & ~CLIENT_SSL)
+
+#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
+#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
+#define SERVER_MORE_RESULTS_EXIST 8
+#define SERVER_QUERY_NO_GOOD_INDEX_USED 16
+#define SERVER_QUERY_NO_INDEX_USED 32
+#define SERVER_STATUS_CURSOR_EXISTS 64
+#define SERVER_STATUS_LAST_ROW_SENT 128
+#define SERVER_STATUS_DB_DROPPED 256
+#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
+#define SERVER_STATUS_METADATA_CHANGED 1024
+#define SERVER_QUERY_WAS_SLOW 2048
+#define SERVER_PS_OUT_PARAMS 4096
+#define SERVER_STATUS_IN_TRANS_READONLY 8192
+#define SERVER_SESSION_STATE_CHANGED 16384
+#define SERVER_STATUS_ANSI_QUOTES 32768
+
+#define MYSQL_ERRMSG_SIZE 512
+#define NET_READ_TIMEOUT 30 /* Timeout on read */
+#define NET_WRITE_TIMEOUT 60 /* Timeout on write */
+#define NET_WAIT_TIMEOUT (8*60*60) /* Wait for new query */
+
+/* for server integration (mysqlbinlog) */
+#define LIST_PROCESS_HOST_LEN 64
+#define MYSQL50_TABLE_NAME_PREFIX "#mysql50#"
+#define MYSQL50_TABLE_NAME_PREFIX_LENGTH (sizeof(MYSQL50_TABLE_NAME_PREFIX)-1)
+#define SAFE_NAME_LEN (NAME_LEN + MYSQL50_TABLE_NAME_PREFIX_LENGTH)
+
+struct st_ma_pvio;
+typedef struct st_ma_pvio MARIADB_PVIO;
+
+#define MAX_CHAR_WIDTH 255 /* Max length for a CHAR column */
+#define MAX_BLOB_WIDTH 8192 /* Default width for blob */
+
+/* the following defines were added for PHP's mysqli and pdo extensions:
+ see: CONC-56
+*/
+#define MAX_TINYINT_WIDTH 3
+#define MAX_SMALLINT_WIDTH 5
+#define MAX_MEDIUMINT_WIDTH 8
+#define MAX_INT_WIDTH 10
+#define MAX_BIGINT_WIDTH 20
+
+struct st_ma_connection_plugin;
+
+
+typedef struct st_net {
+ MARIADB_PVIO *pvio;
+ unsigned char *buff;
+ unsigned char *buff_end,*write_pos,*read_pos;
+ my_socket fd; /* For Perl DBI/dbd */
+ unsigned long remain_in_buf,length;
+ unsigned long buf_length, where_b;
+ unsigned long max_packet, max_packet_size;
+ unsigned int pkt_nr, compress_pkt_nr;
+ unsigned int write_timeout, read_timeout, retry_count;
+ int fcntl;
+ unsigned int *return_status;
+ unsigned char reading_or_writing;
+ char save_char;
+ char unused_1;
+ my_bool unused_2;
+ my_bool compress;
+ my_bool unused_3;
+ void *unused_4;
+ unsigned int last_errno;
+ unsigned char error;
+ my_bool unused_5;
+ my_bool unused_6;
+ char last_error[MYSQL_ERRMSG_SIZE];
+ char sqlstate[SQLSTATE_LENGTH+1];
+ struct st_mariadb_net_extension *extension;
+} NET;
+
+#define packet_error ((unsigned int) -1)
+
+/* used by mysql_set_server_option */
+enum enum_mysql_set_option
+{
+ MYSQL_OPTION_MULTI_STATEMENTS_ON,
+ MYSQL_OPTION_MULTI_STATEMENTS_OFF
+};
+
+/* for status callback function */
+enum enum_mariadb_status_info
+{
+ STATUS_TYPE= 0,
+ SESSION_TRACK_TYPE
+};
+
+enum enum_session_state_type
+{
+ SESSION_TRACK_SYSTEM_VARIABLES= 0,
+ SESSION_TRACK_SCHEMA,
+ SESSION_TRACK_STATE_CHANGE,
+ /* currently not supported by MariaDB Server */
+ SESSION_TRACK_GTIDS,
+ SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
+ SESSION_TRACK_TRANSACTION_STATE /* make sure that SESSION_TRACK_END always points
+ to last element of enum !! */
+};
+
+#define SESSION_TRACK_BEGIN 0
+#define SESSION_TRACK_END SESSION_TRACK_TRANSACTION_STATE
+#define SESSION_TRACK_TYPES (SESSION_TRACK_END + 1)
+
+/* SESSION_TRACK_TRANSACTION_TYPE was renamed to SESSION_TRACK_TRANSACTION_STATE
+ in 3e699a1738cdfb0a2c5b8eabfa8301b8d11cf711.
+ This is a workaround to prevent breaking of travis and buildbot tests.
+ TODO: Remove this after server fixes */
+#define SESSION_TRACK_TRANSACTION_TYPE SESSION_TRACK_TRANSACTION_STATE
+
+enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
+ MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
+ MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
+ MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
+ MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
+ MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ MYSQL_TYPE_BIT,
+ /*
+ the following types are not used by client,
+ only for mysqlbinlog!!
+ */
+ MYSQL_TYPE_TIMESTAMP2,
+ MYSQL_TYPE_DATETIME2,
+ MYSQL_TYPE_TIME2,
+ /* --------------------------------------------- */
+ MYSQL_TYPE_JSON=245,
+ MYSQL_TYPE_NEWDECIMAL=246,
+ MYSQL_TYPE_ENUM=247,
+ MYSQL_TYPE_SET=248,
+ MYSQL_TYPE_TINY_BLOB=249,
+ MYSQL_TYPE_MEDIUM_BLOB=250,
+ MYSQL_TYPE_LONG_BLOB=251,
+ MYSQL_TYPE_BLOB=252,
+ MYSQL_TYPE_VAR_STRING=253,
+ MYSQL_TYPE_STRING=254,
+ MYSQL_TYPE_GEOMETRY=255,
+ MAX_NO_FIELD_TYPES };
+
+#define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compatibility */
+#define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compatibility */
+#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
+#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL
+#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
+#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
+#define FIELD_TYPE_LONG MYSQL_TYPE_LONG
+#define FIELD_TYPE_FLOAT MYSQL_TYPE_FLOAT
+#define FIELD_TYPE_DOUBLE MYSQL_TYPE_DOUBLE
+#define FIELD_TYPE_NULL MYSQL_TYPE_NULL
+#define FIELD_TYPE_TIMESTAMP MYSQL_TYPE_TIMESTAMP
+#define FIELD_TYPE_LONGLONG MYSQL_TYPE_LONGLONG
+#define FIELD_TYPE_INT24 MYSQL_TYPE_INT24
+#define FIELD_TYPE_DATE MYSQL_TYPE_DATE
+#define FIELD_TYPE_TIME MYSQL_TYPE_TIME
+#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME
+#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR
+#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE
+#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM
+#define FIELD_TYPE_SET MYSQL_TYPE_SET
+#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB
+#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB
+#define FIELD_TYPE_LONG_BLOB MYSQL_TYPE_LONG_BLOB
+#define FIELD_TYPE_BLOB MYSQL_TYPE_BLOB
+#define FIELD_TYPE_VAR_STRING MYSQL_TYPE_VAR_STRING
+#define FIELD_TYPE_STRING MYSQL_TYPE_STRING
+#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
+#define FIELD_TYPE_BIT MYSQL_TYPE_BIT
+
+extern unsigned long max_allowed_packet;
+extern unsigned long net_buffer_length;
+
+#define net_new_transaction(net) ((net)->pkt_nr=0)
+
+int ma_net_init(NET *net, MARIADB_PVIO *pvio);
+void ma_net_end(NET *net);
+void ma_net_clear(NET *net);
+int ma_net_flush(NET *net);
+int ma_net_write(NET *net,const unsigned char *packet, size_t len);
+int ma_net_write_command(NET *net,unsigned char command,const char *packet,
+ size_t len, my_bool disable_flush);
+int ma_net_real_write(NET *net,const char *packet, size_t len);
+extern unsigned long ma_net_read(NET *net);
+
+struct rand_struct {
+ unsigned long seed1,seed2,max_value;
+ double max_value_dbl;
+};
+
+ /* The following is for user defined functions */
+
+enum Item_result {STRING_RESULT,REAL_RESULT,INT_RESULT,ROW_RESULT,DECIMAL_RESULT};
+
+typedef struct st_udf_args
+{
+ unsigned int arg_count; /* Number of arguments */
+ enum Item_result *arg_type; /* Pointer to item_results */
+ char **args; /* Pointer to argument */
+ unsigned long *lengths; /* Length of string arguments */
+ char *maybe_null; /* Set to 1 for all maybe_null args */
+} UDF_ARGS;
+
+ /* This holds information about the result */
+
+typedef struct st_udf_init
+{
+ my_bool maybe_null; /* 1 if function can return NULL */
+ unsigned int decimals; /* for real functions */
+ unsigned int max_length; /* For string functions */
+ char *ptr; /* free pointer for function data */
+ my_bool const_item; /* 0 if result is independent of arguments */
+} UDF_INIT;
+
+/* Connection types */
+#define MARIADB_CONNECTION_UNIXSOCKET 0
+#define MARIADB_CONNECTION_TCP 1
+#define MARIADB_CONNECTION_NAMEDPIPE 2
+#define MARIADB_CONNECTION_SHAREDMEM 3
+
+ /* Constants when using compression */
+#define NET_HEADER_SIZE 4 /* standard header size */
+#define COMP_HEADER_SIZE 3 /* compression header extra size */
+
+ /* Prototypes to password functions */
+#define native_password_plugin_name "mysql_native_password"
+#define old_password_plugin_name "mysql_old_password"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *ma_scramble_323(char *to,const char *message,const char *password);
+void ma_scramble_41(const unsigned char *buffer, const char *scramble, const char *password);
+void ma_hash_password(unsigned long *result, const char *password, size_t len);
+void ma_make_scrambled_password(char *to,const char *password);
+
+/* Some other useful functions */
+
+void mariadb_load_defaults(const char *conf_file, const char **groups,
+ int *argc, char ***argv);
+my_bool ma_thread_init(void);
+void ma_thread_end(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
+
+#endif
diff --git a/libmariadb/include/mariadb_ctype.h b/libmariadb/include/mariadb_ctype.h
new file mode 100644
index 00000000..3b218c31
--- /dev/null
+++ b/libmariadb/include/mariadb_ctype.h
@@ -0,0 +1,76 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/*
+ A better implementation of the UNIX ctype(3) library.
+ Notes: my_global.h should be included before ctype.h
+*/
+
+#ifndef _mariadb_ctype_h
+#define _mariadb_ctype_h
+
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CHARSET_DIR "charsets/"
+#define MY_CS_NAME_SIZE 32
+
+#define MADB_DEFAULT_CHARSET_NAME "latin1"
+#define MADB_DEFAULT_COLLATION_NAME "latin1_swedish_ci"
+#define MADB_AUTODETECT_CHARSET_NAME "auto"
+
+/* we use the mysqlnd implementation */
+typedef struct ma_charset_info_st
+{
+ unsigned int nr; /* so far only 1 byte for charset */
+ unsigned int state;
+ const char *csname;
+ const char *name;
+ const char *dir;
+ unsigned int codepage;
+ const char *encoding;
+ unsigned int char_minlen;
+ unsigned int char_maxlen;
+ unsigned int (*mb_charlen)(unsigned int c);
+ unsigned int (*mb_valid)(const char *start, const char *end);
+} MARIADB_CHARSET_INFO;
+
+extern const MARIADB_CHARSET_INFO mariadb_compiled_charsets[];
+extern MARIADB_CHARSET_INFO *ma_default_charset_info;
+extern MARIADB_CHARSET_INFO *ma_charset_bin;
+extern MARIADB_CHARSET_INFO *ma_charset_latin1;
+extern MARIADB_CHARSET_INFO *ma_charset_utf8_general_ci;
+extern MARIADB_CHARSET_INFO *ma_charset_utf16le_general_ci;
+
+MARIADB_CHARSET_INFO *find_compiled_charset(unsigned int cs_number);
+MARIADB_CHARSET_INFO *find_compiled_charset_by_name(const char *name);
+
+size_t mysql_cset_escape_quotes(const MARIADB_CHARSET_INFO *cset, char *newstr, const char *escapestr, size_t escapestr_len);
+size_t mysql_cset_escape_slashes(const MARIADB_CHARSET_INFO *cset, char *newstr, const char *escapestr, size_t escapestr_len);
+const char* madb_get_os_character_set(void);
+#ifdef _WIN32
+int madb_get_windows_cp(const char *charset);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmariadb/include/mariadb_dyncol.h b/libmariadb/include/mariadb_dyncol.h
new file mode 100644
index 00000000..65009079
--- /dev/null
+++ b/libmariadb/include/mariadb_dyncol.h
@@ -0,0 +1,260 @@
+/* Copyright (c) 2011, Monty Program Ab
+ Copyright (c) 2011, Oleksandr Byelkin
+ Copyright (c) 2012, 2022 MariaDB Corporation AB
+
+ 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 the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``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 <COPYRIGHT HOLDER> OR
+ CONTRIBUTORS 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.
+*/
+
+#ifndef ma_dyncol_h
+#define ma_dyncol_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LIBMARIADB
+#include <decimal.h>
+#include <my_decimal_limits.h>
+#endif
+#include <mysql.h>
+
+#ifndef longlong_defined
+#if defined(HAVE_LONG_LONG) && SIZEOF_LONG != 8
+typedef unsigned long long int ulonglong; /* ulong or unsigned long long */
+typedef long long int longlong;
+#else
+typedef unsigned long ulonglong; /* ulong or unsigned long long */
+typedef long longlong;
+#endif
+#define longlong_defined
+#endif
+
+
+#ifndef _my_sys_h
+typedef struct st_dynamic_string
+{
+ char *str;
+ size_t length,max_length,alloc_increment;
+} DYNAMIC_STRING;
+#endif
+
+struct st_mysql_lex_string
+{
+ char *str;
+ size_t length;
+};
+typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+typedef struct st_mysql_lex_string LEX_STRING;
+/*
+ Limits of implementation
+*/
+#define MAX_TOTAL_NAME_LENGTH 65535
+#define MAX_NAME_LENGTH (MAX_TOTAL_NAME_LENGTH/4)
+
+/* NO and OK is the same used just to show semantics */
+#define ER_DYNCOL_NO ER_DYNCOL_OK
+
+enum enum_dyncol_func_result
+{
+ ER_DYNCOL_OK= 0,
+ ER_DYNCOL_YES= 1, /* For functions returning 0/1 */
+ ER_DYNCOL_FORMAT= -1, /* Wrong format of the encoded string */
+ ER_DYNCOL_LIMIT= -2, /* Some limit reached */
+ ER_DYNCOL_RESOURCE= -3, /* Out of resources */
+ ER_DYNCOL_DATA= -4, /* Incorrect input data */
+ ER_DYNCOL_UNKNOWN_CHARSET= -5, /* Unknown character set */
+ ER_DYNCOL_TRUNCATED= 2 /* OK, but data was truncated */
+};
+
+typedef DYNAMIC_STRING DYNAMIC_COLUMN;
+
+enum enum_dynamic_column_type
+{
+ DYN_COL_NULL= 0,
+ DYN_COL_INT,
+ DYN_COL_UINT,
+ DYN_COL_DOUBLE,
+ DYN_COL_STRING,
+ DYN_COL_DECIMAL,
+ DYN_COL_DATETIME,
+ DYN_COL_DATE,
+ DYN_COL_TIME,
+ DYN_COL_DYNCOL
+};
+
+typedef enum enum_dynamic_column_type DYNAMIC_COLUMN_TYPE;
+
+struct st_dynamic_column_value
+{
+ DYNAMIC_COLUMN_TYPE type;
+ union
+ {
+ long long long_value;
+ unsigned long long ulong_value;
+ double double_value;
+ struct {
+ MYSQL_LEX_STRING value;
+ MARIADB_CHARSET_INFO *charset;
+ } string;
+#ifndef LIBMARIADB
+ struct {
+ decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
+ decimal_t value;
+ } decimal;
+#endif
+ MYSQL_TIME time_value;
+ } x;
+};
+
+typedef struct st_dynamic_column_value DYNAMIC_COLUMN_VALUE;
+
+#ifdef MADYNCOL_DEPRECATED
+enum enum_dyncol_func_result
+dynamic_column_create(DYNAMIC_COLUMN *str,
+ uint column_nr, DYNAMIC_COLUMN_VALUE *value);
+
+enum enum_dyncol_func_result
+dynamic_column_create_many(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values);
+enum enum_dyncol_func_result
+dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value);
+enum enum_dyncol_func_result
+dynamic_column_update_many(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values);
+
+enum enum_dyncol_func_result
+dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr);
+
+enum enum_dyncol_func_result
+dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint);
+
+enum enum_dyncol_func_result
+dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here);
+#endif
+
+/* new functions */
+enum enum_dyncol_func_result
+mariadb_dyncol_create_many_num(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_string);
+enum enum_dyncol_func_result
+mariadb_dyncol_create_many_named(DYNAMIC_COLUMN *str,
+ uint column_count,
+ MYSQL_LEX_STRING *column_keys,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_string);
+
+
+enum enum_dyncol_func_result
+mariadb_dyncol_update_many_num(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_keys,
+ DYNAMIC_COLUMN_VALUE *values);
+enum enum_dyncol_func_result
+mariadb_dyncol_update_many_named(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ MYSQL_LEX_STRING *column_keys,
+ DYNAMIC_COLUMN_VALUE *values);
+
+
+enum enum_dyncol_func_result
+mariadb_dyncol_exists_num(DYNAMIC_COLUMN *org, uint column_nr);
+enum enum_dyncol_func_result
+mariadb_dyncol_exists_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name);
+
+/* List of not NULL columns */
+enum enum_dyncol_func_result
+mariadb_dyncol_list_num(DYNAMIC_COLUMN *str, uint *count, uint **nums);
+enum enum_dyncol_func_result
+mariadb_dyncol_list_named(DYNAMIC_COLUMN *str, uint *count,
+ MYSQL_LEX_STRING **names);
+
+/*
+ if the column do not exists it is NULL
+*/
+enum enum_dyncol_func_result
+mariadb_dyncol_get_num(DYNAMIC_COLUMN *org, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here);
+enum enum_dyncol_func_result
+mariadb_dyncol_get_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name,
+ DYNAMIC_COLUMN_VALUE *store_it_here);
+
+my_bool mariadb_dyncol_has_names(DYNAMIC_COLUMN *str);
+
+enum enum_dyncol_func_result
+mariadb_dyncol_check(DYNAMIC_COLUMN *str);
+
+enum enum_dyncol_func_result
+mariadb_dyncol_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json);
+
+void mariadb_dyncol_free(DYNAMIC_COLUMN *str);
+
+#define mariadb_dyncol_init(A) memset((A), 0, sizeof(DYNAMIC_COLUMN))
+#define dynamic_column_initialize(A) mariadb_dyncol_init((A))
+#define dynamic_column_column_free(A) mariadb_dyncol_free((A))
+
+/* conversion of values to 3 base types */
+enum enum_dyncol_func_result
+mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
+ MARIADB_CHARSET_INFO *cs, char quote);
+enum enum_dyncol_func_result
+mariadb_dyncol_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val);
+enum enum_dyncol_func_result
+mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val);
+
+enum enum_dyncol_func_result
+mariadb_dyncol_unpack(DYNAMIC_COLUMN *str,
+ uint *count,
+ MYSQL_LEX_STRING **names, DYNAMIC_COLUMN_VALUE **vals);
+
+int mariadb_dyncol_column_cmp_named(const MYSQL_LEX_STRING *s1,
+ const MYSQL_LEX_STRING *s2);
+
+enum enum_dyncol_func_result
+mariadb_dyncol_column_count(DYNAMIC_COLUMN *str, uint *column_count);
+
+#define mariadb_dyncol_value_init(V) \
+do {\
+ (V)->type= DYN_COL_NULL;\
+} while(0)
+
+/*
+ Prepare value for using as decimal
+*/
+void mariadb_dyncol_prepare_decimal(DYNAMIC_COLUMN_VALUE *value);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libmariadb/include/mariadb_rpl.h b/libmariadb/include/mariadb_rpl.h
new file mode 100644
index 00000000..ea0ca4db
--- /dev/null
+++ b/libmariadb/include/mariadb_rpl.h
@@ -0,0 +1,653 @@
+/* Copyright (C) 2018-2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+#ifndef _mariadb_rpl_h_
+#define _mariadb_rpl_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <mariadb/ma_io.h>
+
+#define MARIADB_RPL_VERSION 0x0002
+#define MARIADB_RPL_REQUIRED_VERSION 0x0002
+
+#define RPL_BINLOG_MAGIC (const uchar*) "\xFE\x62\x69\x6E"
+#define RPL_BINLOG_MAGIC_SIZE 4
+
+/* Protocol flags */
+#define MARIADB_RPL_BINLOG_DUMP_NON_BLOCK 1
+#define MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS 2
+#define MARIADB_RPL_IGNORE_HEARTBEAT (1 << 17)
+
+#define EVENT_HEADER_OFS 20
+
+#define FL_STMT_END 1
+
+/* GTID flags */
+
+/* FL_STANDALONE is set in case there is no terminating COMMIT event. */
+#define FL_STANDALONE 0x01
+
+/* FL_GROUP_COMMIT_ID is set when event group is part of a group commit */
+#define FL_GROUP_COMMIT_ID 0x02
+
+/* FL_TRANSACTIONAL is set for an event group that can be safely rolled back
+ (no MyISAM, eg.).
+ */
+#define FL_TRANSACTIONAL 0x04
+ /*
+ FL_ALLOW_PARALLEL reflects the (negation of the) value of
+ @@SESSION.skip_parallel_replication at the time of commit.
+ */
+#define FL_ALLOW_PARALLEL 0x08;
+ /*
+ FL_WAITED is set if a row lock wait (or other wait) is detected during the
+ execution of the transaction.
+ */
+#define FL_WAITED 0x10
+ /* FL_DDL is set for event group containing DDL. */
+#define FL_DDL 0x20
+ /* FL_PREPARED_XA is set for XA transaction. */
+#define FL_PREPARED_XA 0x40
+ /* FL_"COMMITTED or ROLLED-BACK"_XA is set for XA transaction. */
+#define FL_COMPLETED_XA 0x80
+
+
+/* SEMI SYNCHRONOUS REPLICATION */
+#define SEMI_SYNC_INDICATOR 0xEF
+#define SEMI_SYNC_ACK_REQ 0x01
+
+/* Options */
+enum mariadb_rpl_option {
+ MARIADB_RPL_FILENAME, /* Filename and length */
+ MARIADB_RPL_START, /* Start position */
+ MARIADB_RPL_SERVER_ID, /* Server ID */
+ MARIADB_RPL_FLAGS, /* Protocol flags */
+ MARIADB_RPL_GTID_CALLBACK, /* GTID callback function */
+ MARIADB_RPL_GTID_DATA, /* GTID data */
+ MARIADB_RPL_BUFFER,
+ MARIADB_RPL_VERIFY_CHECKSUM,
+ MARIADB_RPL_UNCOMPRESS,
+ MARIADB_RPL_HOST,
+ MARIADB_RPL_PORT,
+ MARIADB_RPL_EXTRACT_VALUES,
+ MARIADB_RPL_SEMI_SYNC,
+};
+
+/* Event types: From MariaDB Server sql/log_event.h */
+enum mariadb_rpl_event {
+ UNKNOWN_EVENT= 0,
+ START_EVENT_V3= 1,
+ QUERY_EVENT= 2,
+ STOP_EVENT= 3,
+ ROTATE_EVENT= 4,
+ INTVAR_EVENT= 5,
+ LOAD_EVENT= 6,
+ SLAVE_EVENT= 7,
+ CREATE_FILE_EVENT= 8,
+ APPEND_BLOCK_EVENT= 9,
+ EXEC_LOAD_EVENT= 10,
+ DELETE_FILE_EVENT= 11,
+ NEW_LOAD_EVENT= 12,
+ RAND_EVENT= 13,
+ USER_VAR_EVENT= 14,
+ FORMAT_DESCRIPTION_EVENT= 15,
+ XID_EVENT= 16,
+ BEGIN_LOAD_QUERY_EVENT= 17,
+ EXECUTE_LOAD_QUERY_EVENT= 18,
+ TABLE_MAP_EVENT = 19,
+
+ PRE_GA_WRITE_ROWS_EVENT = 20, /* deprecated */
+ PRE_GA_UPDATE_ROWS_EVENT = 21, /* deprecated */
+ PRE_GA_DELETE_ROWS_EVENT = 22, /* deprecated */
+
+ WRITE_ROWS_EVENT_V1 = 23,
+ UPDATE_ROWS_EVENT_V1 = 24,
+ DELETE_ROWS_EVENT_V1 = 25,
+ INCIDENT_EVENT= 26,
+ HEARTBEAT_LOG_EVENT= 27,
+ IGNORABLE_LOG_EVENT= 28,
+ ROWS_QUERY_LOG_EVENT= 29,
+ WRITE_ROWS_EVENT = 30,
+ UPDATE_ROWS_EVENT = 31,
+ DELETE_ROWS_EVENT = 32,
+ GTID_LOG_EVENT= 33,
+ ANONYMOUS_GTID_LOG_EVENT= 34,
+ PREVIOUS_GTIDS_LOG_EVENT= 35,
+ TRANSACTION_CONTEXT_EVENT= 36,
+ VIEW_CHANGE_EVENT= 37,
+ XA_PREPARE_LOG_EVENT= 38,
+ PARTIAL_UPDATE_ROWS_EVENT = 39,
+
+ /*
+ Add new events here - right above this comment!
+ Existing events (except ENUM_END_EVENT) should never change their numbers
+ */
+
+ /* New MySQL events are to be added right above this comment */
+ MYSQL_EVENTS_END,
+
+ MARIA_EVENTS_BEGIN= 160,
+ ANNOTATE_ROWS_EVENT= 160,
+ BINLOG_CHECKPOINT_EVENT= 161,
+ GTID_EVENT= 162,
+ GTID_LIST_EVENT= 163,
+ START_ENCRYPTION_EVENT= 164,
+ QUERY_COMPRESSED_EVENT = 165,
+ WRITE_ROWS_COMPRESSED_EVENT_V1 = 166,
+ UPDATE_ROWS_COMPRESSED_EVENT_V1 = 167,
+ DELETE_ROWS_COMPRESSED_EVENT_V1 = 168,
+ WRITE_ROWS_COMPRESSED_EVENT = 169,
+ UPDATE_ROWS_COMPRESSED_EVENT = 170,
+ DELETE_ROWS_COMPRESSED_EVENT = 171,
+
+ /* Add new MariaDB events here - right above this comment! */
+
+ ENUM_END_EVENT /* end marker */
+};
+
+/* ROWS_EVENT flags */
+
+#define STMT_END_F 0x01
+#define NO_FOREIGN_KEY_CHECKS_F 0x02
+#define RELAXED_UNIQUE_KEY_CHECKS_F 0x04
+#define COMPLETE_ROWS_F 0x08
+#define NO_CHECK_CONSTRAINT_CHECKS_F 0x80
+
+
+enum mariadb_rpl_status_code {
+ Q_FLAGS2_CODE= 0x00,
+ Q_SQL_MODE_CODE= 0x01,
+ Q_CATALOG_CODE= 0x02,
+ Q_AUTO_INCREMENT_CODE= 0x03,
+ Q_CHARSET_CODE= 0x04,
+ Q_TIMEZONE_CODE= 0x05,
+ Q_CATALOG_NZ_CODE= 0x06,
+ Q_LC_TIME_NAMES_CODE= 0x07,
+ Q_CHARSET_DATABASE_CODE= 0x08,
+ Q_TABLE_MAP_FOR_UPDATE_CODE= 0x09,
+ Q_MASTER_DATA_WRITTEN_CODE= 0x0A,
+ Q_INVOKERS_CODE= 0x0B,
+ Q_UPDATED_DB_NAMES_CODE= 0x0C,
+ Q_MICROSECONDS_CODE= 0x0D,
+ Q_COMMIT_TS_CODE= 0x0E, /* unused */
+ Q_COMMIT_TS2_CODE= 0x0F, /* unused */
+ Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP_CODE= 0x10,
+ Q_DDL_LOGGED_WITH_XID_CODE= 0x11,
+ Q_DEFAULT_COLLATION_FOR_UTF8_CODE= 0x12,
+ Q_SQL_REQUIRE_PRIMARY_KEY_CODE= 0x13,
+ Q_DEFAULT_TABLE_ENCRYPTION_CODE= 0x14,
+ Q_HRNOW= 128, /* second part: 3 bytes */
+ Q_XID= 129 /* xid: 8 bytes */
+};
+
+#ifdef DEFAULT_CHARSET
+#undef DEFAULT_CHARSET
+#endif
+
+enum opt_metadata_field_type
+{
+ SIGNEDNESS = 1,
+ DEFAULT_CHARSET,
+ COLUMN_CHARSET,
+ COLUMN_NAME,
+ SET_STR_VALUE,
+ ENUM_STR_VALUE,
+ GEOMETRY_TYPE,
+ SIMPLE_PRIMARY_KEY,
+ PRIMARY_KEY_WITH_PREFIX,
+ ENUM_AND_SET_DEFAULT_CHARSET,
+ ENUM_AND_SET_COLUMN_CHARSET
+};
+
+/* QFLAGS2 codes */
+#define OPTION_AUTO_IS_NULL 0x00040000
+#define OPTION_NOT_AUTOCOMMIT 0x00080000
+#define OPTION_NO_FOREIGN_KEY_CHECKS 0x04000000
+#define OPTION_RELAXED_UNIQUE_CHECKS 0x08000000
+
+/* SQL modes */
+#define MODE_REAL_AS_FLOAT 0x00000001
+#define MODE_PIPES_AS_CONCAT 0x00000002
+#define MODE_ANSI_QUOTES 0x00000004
+#define MODE_IGNORE_SPACE 0x00000008
+#define MODE_NOT_USED 0x00000010
+#define MODE_ONLY_FULL_GROUP_BY 0x00000020
+#define MODE_NO_UNSIGNED_SUBTRACTION 0x00000040
+#define MODE_NO_DIR_IN_CREATE 0x00000080
+#define MODE_POSTGRESQL 0x00000100
+#define MODE_ORACLE 0x00000200
+#define MODE_MSSQL 0x00000400
+#define MODE_DB2 0x00000800
+#define MODE_MAXDB 0x00001000
+#define MODE_NO_KEY_OPTIONS 0x00002000
+#define MODE_NO_TABLE_OPTIONS 0x00004000
+#define MODE_NO_FIELD_OPTIONS 0x00008000
+#define MODE_MYSQL323 0x00010000
+#define MODE_MYSQL40 0x00020000
+#define MODE_ANSI 0x00040000
+#define MODE_NO_AUTO_VALUE_ON_ZERO 0x00080000
+#define MODE_NO_BACKSLASH_ESCAPES 0x00100000
+#define MODE_STRICT_TRANS_TABLES 0x00200000
+#define MODE_STRICT_ALL_TABLES 0x00400000
+#define MODE_NO_ZERO_IN_DATE 0x00800000
+#define MODE_NO_ZERO_DATE 0x01000000
+#define MODE_INVALID_DATES 0x02000000
+#define MODE_ERROR_FOR_DIVISION_BY_ZERO 0x04000000
+#define MODE_TRADITIONAL 0x08000000
+#define MODE_NO_AUTO_CREATE_USER 0x10000000
+#define MODE_HIGH_NOT_PRECEDENCE 0x20000000
+#define MODE_NO_ENGINE_SUBSTITUTION 0x40000000
+#define MODE_PAD_CHAR_TO_FULL_LENGTH 0x80000000
+
+/* Log Event flags */
+
+/* used in FOMRAT_DESCRIPTION_EVENT. Indicates if it
+ is the active binary log.
+ Note: When reading data via COM_BINLOG_DUMP this
+ flag is never set.
+*/
+#define LOG_EVENT_BINLOG_IN_USE_F 0x0001
+
+/* Looks like this flag is no longer in use */
+#define LOG_EVENT_FORCED_ROTATE_F 0x0002
+
+/* Log entry depends on thread, e.g. when using user variables
+ or temporary tables */
+#define LOG_EVENT_THREAD_SPECIFIC_F 0x0004
+
+/* Indicates that the USE command can be suppressed before
+ executing a statement: e.g. DRIP SCHEMA */
+#define LOG_EVENT_SUPPRESS_USE_F 0x0008
+
+/* ??? */
+#define LOG_EVENT_UPDATE_TABLE_MAP_F 0x0010
+
+/* Artifical event */
+#define LOG_EVENT_ARTIFICIAL_F 0x0020
+
+/* ??? */
+#define LOG_EVENT_RELAY_LOG_F 0x0040
+
+/* If an event is not supported, and LOG_EVENT_IGNORABLE_F was not
+ set, an error will be reported. */
+#define LOG_EVENT_IGNORABLE_F 0x0080
+
+/* ??? */
+#define LOG_EVENT_NO_FILTER_F 0x0100
+
+/* ?? */
+#define LOG_EVENT_MTS_ISOLATE_F 0x0200
+
+/* if session variable @@skip_repliation was set, this flag will be
+ reported for events which should be skipped. */
+#define LOG_EVENT_SKIP_REPLICATION_F 0x8000
+
+typedef struct {
+ char *str;
+ size_t length;
+} MARIADB_STRING;
+
+enum mariadb_row_event_type {
+ WRITE_ROWS= 0,
+ UPDATE_ROWS= 1,
+ DELETE_ROWS= 2
+};
+
+/* Global transaction id */
+typedef struct st_mariadb_gtid {
+ unsigned int domain_id;
+ unsigned int server_id;
+ unsigned long long sequence_nr;
+} MARIADB_GTID;
+
+
+/* Generic replication handle */
+typedef struct st_mariadb_rpl {
+ unsigned int version;
+ MYSQL *mysql;
+ char *filename;
+ uint32_t filename_length;
+ uint32_t server_id;
+ unsigned long start_position;
+ uint16_t flags;
+ uint8_t fd_header_len; /* header len from last format description event */
+ uint8_t use_checksum;
+ uint8_t artificial_checksum;
+ uint8_t verify_checksum;
+ uint8_t post_header_len[ENUM_END_EVENT];
+ MA_FILE *fp;
+ uint32_t error_no;
+ char error_msg[MYSQL_ERRMSG_SIZE];
+ uint8_t uncompress;
+ char *host;
+ uint32_t port;
+ uint8_t extract_values;
+ char nonce[12];
+ uint8_t encrypted;
+ uint8_t is_semi_sync;
+}MARIADB_RPL;
+
+typedef struct st_mariadb_rpl_value {
+ enum enum_field_types field_type;
+ uint8_t is_null;
+ uint8_t is_signed;
+ union {
+ int64_t ll;
+ uint64_t ull;
+ float f;
+ double d;
+ MYSQL_TIME tm;
+ MARIADB_STRING str;
+ } val;
+} MARIADB_RPL_VALUE;
+
+typedef struct st_rpl_mariadb_row {
+ uint32_t column_count;
+ MARIADB_RPL_VALUE *columns;
+ struct st_rpl_mariadb_row *next;
+} MARIADB_RPL_ROW;
+
+/* Event header */
+struct st_mariadb_rpl_rotate_event {
+ unsigned long long position;
+ MARIADB_STRING filename;
+};
+
+struct st_mariadb_rpl_query_event {
+ uint32_t thread_id;
+ uint32_t seconds;
+ MARIADB_STRING database;
+ uint32_t errornr;
+ MARIADB_STRING status;
+ MARIADB_STRING statement;
+};
+
+struct st_mariadb_rpl_previous_gtid_event {
+ MARIADB_CONST_DATA content;
+};
+
+struct st_mariadb_rpl_gtid_list_event {
+ uint32_t gtid_cnt;
+ MARIADB_GTID *gtid;
+};
+
+struct st_mariadb_rpl_format_description_event
+{
+ uint16_t format;
+ char *server_version;
+ uint32_t timestamp;
+ uint8_t header_len;
+ MARIADB_STRING post_header_lengths;
+};
+
+struct st_mariadb_rpl_checkpoint_event {
+ MARIADB_STRING filename;
+};
+
+struct st_mariadb_rpl_xid_event {
+ uint64_t transaction_nr;
+};
+
+struct st_mariadb_rpl_gtid_event {
+ uint64_t sequence_nr;
+ uint32_t domain_id;
+ uint8_t flags;
+ uint64_t commit_id;
+ uint32_t format_id;
+ uint8_t gtrid_len;
+ uint8_t bqual_len;
+ MARIADB_STRING xid;
+};
+
+struct st_mariadb_rpl_annotate_rows_event {
+ MARIADB_STRING statement;
+};
+
+struct st_mariadb_rpl_table_map_event {
+ unsigned long long table_id;
+ MARIADB_STRING database;
+ MARIADB_STRING table;
+ uint32_t column_count;
+ MARIADB_STRING column_types;
+ MARIADB_STRING metadata;
+ unsigned char *null_indicator;
+ unsigned char *signed_indicator;
+ MARIADB_CONST_DATA column_names;
+ MARIADB_CONST_DATA geometry_types;
+ uint32_t default_charset;
+ MARIADB_CONST_DATA column_charsets;
+ MARIADB_CONST_DATA simple_primary_keys;
+ MARIADB_CONST_DATA prefixed_primary_keys;
+ MARIADB_CONST_DATA set_values;
+ MARIADB_CONST_DATA enum_values;
+ uint8_t enum_set_default_charset;
+ MARIADB_CONST_DATA enum_set_column_charsets;
+};
+
+struct st_mariadb_rpl_rand_event {
+ unsigned long long first_seed;
+ unsigned long long second_seed;
+};
+
+struct st_mariadb_rpl_intvar_event {
+ unsigned long long value;
+ uint8_t type;
+};
+
+struct st_mariadb_begin_load_query_event {
+ uint32_t file_id;
+ unsigned char *data;
+};
+
+struct st_mariadb_start_encryption_event {
+ uint8_t scheme;
+ uint32_t key_version;
+ char nonce[12];
+};
+
+struct st_mariadb_execute_load_query_event {
+ uint32_t thread_id;
+ uint32_t execution_time;
+ MARIADB_STRING schema;
+ uint16_t error_code;
+ uint32_t file_id;
+ uint32_t ofs1;
+ uint32_t ofs2;
+ uint8_t duplicate_flag;
+ MARIADB_STRING status_vars;
+ MARIADB_STRING statement;
+};
+
+struct st_mariadb_rpl_uservar_event {
+ MARIADB_STRING name;
+ uint8_t is_null;
+ uint8_t type;
+ uint32_t charset_nr;
+ MARIADB_STRING value;
+ uint8_t flags;
+};
+
+struct st_mariadb_rpl_rows_event {
+ enum mariadb_row_event_type type;
+ uint64_t table_id;
+ uint16_t flags;
+ uint32_t column_count;
+ unsigned char *column_bitmap;
+ unsigned char *column_update_bitmap;
+ unsigned char *null_bitmap;
+ size_t row_data_size;
+ void *row_data;
+ size_t extra_data_size;
+ void *extra_data;
+ uint8_t compressed;
+ uint32_t row_count;
+};
+
+struct st_mariadb_rpl_heartbeat_event {
+ uint32_t timestamp;
+ uint32_t next_position;
+ uint8_t type;
+ uint16_t flags;
+};
+
+struct st_mariadb_rpl_xa_prepare_log_event {
+ uint8_t one_phase;
+ uint32_t format_id;
+ uint32_t gtrid_len;
+ uint32_t bqual_len;
+ MARIADB_STRING xid;
+};
+
+struct st_mariadb_gtid_log_event {
+ uint8_t commit_flag;
+ char source_id[16];
+ uint64_t sequence_nr;
+};
+
+typedef struct st_mariadb_rpl_event
+{
+ /* common header */
+ MA_MEM_ROOT memroot;
+ unsigned char *raw_data;
+ size_t raw_data_size;
+ size_t raw_data_ofs;
+ unsigned int checksum;
+ char ok;
+ enum mariadb_rpl_event event_type;
+ unsigned int timestamp;
+ unsigned int server_id;
+ unsigned int event_length;
+ unsigned int next_event_pos;
+ unsigned short flags;
+ /****************/
+ union {
+ struct st_mariadb_rpl_rotate_event rotate;
+ struct st_mariadb_rpl_query_event query;
+ struct st_mariadb_rpl_format_description_event format_description;
+ struct st_mariadb_rpl_gtid_list_event gtid_list;
+ struct st_mariadb_rpl_checkpoint_event checkpoint;
+ struct st_mariadb_rpl_xid_event xid;
+ struct st_mariadb_rpl_gtid_event gtid;
+ struct st_mariadb_rpl_annotate_rows_event annotate_rows;
+ struct st_mariadb_rpl_table_map_event table_map;
+ struct st_mariadb_rpl_rand_event rand;
+ struct st_mariadb_rpl_intvar_event intvar;
+ struct st_mariadb_rpl_uservar_event uservar;
+ struct st_mariadb_rpl_rows_event rows;
+ struct st_mariadb_rpl_heartbeat_event heartbeat;
+ struct st_mariadb_rpl_xa_prepare_log_event xa_prepare_log;
+ struct st_mariadb_begin_load_query_event begin_load_query;
+ struct st_mariadb_execute_load_query_event execute_load_query;
+ struct st_mariadb_gtid_log_event gtid_log;
+ struct st_mariadb_start_encryption_event start_encryption;
+ struct st_mariadb_rpl_previous_gtid_event previous_gtid;
+ } event;
+ /* Added in C/C 3.3.0 */
+ uint8_t is_semi_sync;
+ uint8_t semi_sync_flags;
+ /* Added in C/C 3.3.5 */
+ MARIADB_RPL *rpl;
+} MARIADB_RPL_EVENT;
+
+/* compression uses myisampack format */
+#define myisam_uint1korr(B) ((uint8_t)(*B))
+#define myisam_sint1korr(B) ((int8_t)(*B))
+#define myisam_uint2korr(B)\
+((uint16_t)(((uint16_t)(((const uchar*)(B))[1])) | ((uint16_t) (((const uchar*) (B))[0]) << 8)))
+#define myisam_sint2korr(B)\
+((int16_t)(((int16_t)(((const uchar*)(B))[1])) | ((int16_t) (((const uchar*) (B))[0]) << 8)))
+#define myisam_uint3korr(B)\
+((uint32_t)(((uint32_t)(((const uchar*)(B))[2])) |\
+(((uint32_t)(((const uchar*)(B))[1])) << 8) |\
+(((uint32_t)(((const uchar*)(B))[0])) << 16)))
+#define myisam_sint3korr(B)\
+((int32_t)(((int32_t)(((const uchar*)(B))[2])) |\
+(((int32_t)(((const uchar*)(B))[1])) << 8) |\
+(((int32_t)(((const uchar*)(B))[0])) << 16)))
+#define myisam_uint4korr(B)\
+((uint32_t)(((uint32_t)(((const uchar*)(B))[3])) |\
+(((uint32_t)(((const uchar*)(B))[2])) << 8) |\
+(((uint32_t)(((const uchar*) (B))[1])) << 16) |\
+(((uint32_t)(((const uchar*) (B))[0])) << 24)))
+#define myisam_sint4korr(B)\
+((int32_t)(((int32_t)(((const uchar*)(B))[3])) |\
+(((int32_t)(((const uchar*)(B))[2])) << 8) |\
+(((int32_t)(((const uchar*) (B))[1])) << 16) |\
+(((int32_t)(((const uchar*) (B))[0])) << 24)))
+#define mi_uint5korr(B)\
+((uint64_t)(((uint32_t) (((const uchar*) (B))[4])) |\
+(((uint32_t) (((const uchar*) (B))[3])) << 8) |\
+(((uint32_t) (((const uchar*) (B))[2])) << 16) |\
+(((uint32_t) (((const uchar*) (B))[1])) << 24)) |\
+(((uint64_t) (((const uchar*) (B))[0])) << 32))
+
+#define RPL_SAFEGUARD(rpl, event, condition) \
+if (!(condition))\
+{\
+ my_set_error((rpl)->mysql, CR_BINLOG_ERROR, SQLSTATE_UNKNOWN, 0,\
+ (rpl)->filename_length, (rpl)->filename,\
+ (rpl)->start_position,\
+ "Packet corrupted");\
+ mariadb_free_rpl_event((event));\
+ return 0;\
+}
+
+#define mariadb_rpl_init(a) mariadb_rpl_init_ex((a), MARIADB_RPL_VERSION)
+#define rpl_clear_error(rpl)\
+(rpl)->error_no= (rpl)->error_msg[0]= 0
+
+#define IS_ROW_VERSION2(a)\
+ ((a) == WRITE_ROWS_EVENT || (a) == UPDATE_ROWS_EVENT || \
+ (a) == DELETE_ROWS_EVENT || (a) == WRITE_ROWS_COMPRESSED_EVENT ||\
+ (a) == UPDATE_ROWS_COMPRESSED_EVENT || (a) == DELETE_ROWS_COMPRESSED_EVENT)
+
+#define IS_ROW_EVENT(a)\
+((a)->event_type == WRITE_ROWS_COMPRESSED_EVENT_V1 ||\
+(a)->event_type == UPDATE_ROWS_COMPRESSED_EVENT_V1 ||\
+(a)->event_type == DELETE_ROWS_COMPRESSED_EVENT_V1 ||\
+(a)->event_type == WRITE_ROWS_EVENT_V1 ||\
+(a)->event_type == UPDATE_ROWS_EVENT_V1 ||\
+(a)->event_type == DELETE_ROWS_EVENT_V1 ||\
+(a)->event_type == WRITE_ROWS_EVENT ||\
+(a)->event_type == UPDATE_ROWS_EVENT ||\
+(a)->event_type == DELETE_ROWS_EVENT)
+
+/* Function prototypes */
+MARIADB_RPL * STDCALL mariadb_rpl_init_ex(MYSQL *mysql, unsigned int version);
+const char * STDCALL mariadb_rpl_error(MARIADB_RPL *rpl);
+uint32_t STDCALL mariadb_rpl_errno(MARIADB_RPL *rpl);
+
+int STDCALL mariadb_rpl_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option, ...);
+int STDCALL mariadb_rpl_get_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option, ...);
+
+int STDCALL mariadb_rpl_open(MARIADB_RPL *rpl);
+void STDCALL mariadb_rpl_close(MARIADB_RPL *rpl);
+MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVENT *event);
+void STDCALL mariadb_free_rpl_event(MARIADB_RPL_EVENT *event);
+
+MARIADB_RPL_ROW * STDCALL
+mariadb_rpl_extract_rows(MARIADB_RPL *rpl,
+ MARIADB_RPL_EVENT *tm_event,
+ MARIADB_RPL_EVENT *row_event);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libmariadb/include/mariadb_stmt.h b/libmariadb/include/mariadb_stmt.h
new file mode 100644
index 00000000..531c2181
--- /dev/null
+++ b/libmariadb/include/mariadb_stmt.h
@@ -0,0 +1,255 @@
+/************************************************************************
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA
+
+ Part of this code includes code from PHP's mysqlnd extension
+ (written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
+ available from http://www.php.net/software
+
+*************************************************************************/
+
+#define MYSQL_NO_DATA 100
+#define MYSQL_DATA_TRUNCATED 101
+#define MYSQL_DEFAULT_PREFETCH_ROWS (unsigned long) 1
+
+/* Bind flags */
+#define MADB_BIND_DUMMY 1
+
+#define MARIADB_STMT_BULK_SUPPORTED(stmt)\
+ ((stmt)->mysql && \
+ (!((stmt)->mysql->server_capabilities & CLIENT_MYSQL) &&\
+ ((stmt)->mysql->extension->mariadb_server_capabilities & \
+ (MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32))))
+
+#define CLEAR_CLIENT_STMT_ERROR(a) \
+do { \
+ (a)->last_errno= 0;\
+ strcpy((a)->sqlstate, "00000");\
+ (a)->last_error[0]= 0;\
+} while (0)
+
+#define MYSQL_PS_SKIP_RESULT_W_LEN -1
+#define MYSQL_PS_SKIP_RESULT_STR -2
+#define STMT_ID_LENGTH 4
+
+
+typedef struct st_mysql_stmt MYSQL_STMT;
+
+typedef MYSQL_RES* (*mysql_stmt_use_or_store_func)(MYSQL_STMT *);
+
+enum enum_stmt_attr_type
+{
+ STMT_ATTR_UPDATE_MAX_LENGTH,
+ STMT_ATTR_CURSOR_TYPE,
+ STMT_ATTR_PREFETCH_ROWS,
+
+ /* MariaDB only */
+ STMT_ATTR_PREBIND_PARAMS=200,
+ STMT_ATTR_ARRAY_SIZE,
+ STMT_ATTR_ROW_SIZE,
+ STMT_ATTR_STATE,
+ STMT_ATTR_CB_USER_DATA,
+ STMT_ATTR_CB_PARAM,
+ STMT_ATTR_CB_RESULT
+};
+
+enum enum_cursor_type
+{
+ CURSOR_TYPE_NO_CURSOR= 0,
+ CURSOR_TYPE_READ_ONLY= 1,
+ CURSOR_TYPE_FOR_UPDATE= 2,
+ CURSOR_TYPE_SCROLLABLE= 4
+};
+
+enum enum_indicator_type
+{
+ STMT_INDICATOR_NTS=-1,
+ STMT_INDICATOR_NONE=0,
+ STMT_INDICATOR_NULL=1,
+ STMT_INDICATOR_DEFAULT=2,
+ STMT_INDICATOR_IGNORE=3,
+ STMT_INDICATOR_IGNORE_ROW=4
+};
+
+/*
+ bulk PS flags
+*/
+#define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128
+#define STMT_BULK_FLAG_INSERT_ID_REQUEST 64
+
+typedef enum mysql_stmt_state
+{
+ MYSQL_STMT_INITTED = 0,
+ MYSQL_STMT_PREPARED,
+ MYSQL_STMT_EXECUTED,
+ MYSQL_STMT_WAITING_USE_OR_STORE,
+ MYSQL_STMT_USE_OR_STORE_CALLED,
+ MYSQL_STMT_USER_FETCHING, /* fetch_row_buff or fetch_row_unbuf */
+ MYSQL_STMT_FETCH_DONE
+} enum_mysqlnd_stmt_state;
+
+typedef struct st_mysql_bind
+{
+ unsigned long *length; /* output length pointer */
+ my_bool *is_null; /* Pointer to null indicator */
+ void *buffer; /* buffer to get/put data */
+ /* set this if you want to track data truncations happened during fetch */
+ my_bool *error;
+ union {
+ unsigned char *row_ptr; /* for the current data position */
+ char *indicator; /* indicator variable */
+ } u;
+ void (*store_param_func)(NET *net, struct st_mysql_bind *param);
+ void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *,
+ unsigned char **row);
+ void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *,
+ unsigned char **row);
+ /* output buffer length, must be set when fetching str/binary */
+ unsigned long buffer_length;
+ unsigned long offset; /* offset position for char/binary fetch */
+ unsigned long length_value; /* Used if length is 0 */
+ unsigned int flags; /* special flags, e.g. for dummy bind */
+ unsigned int pack_length; /* Internal length for packed data */
+ enum enum_field_types buffer_type; /* buffer type */
+ my_bool error_value; /* used if error is 0 */
+ my_bool is_unsigned; /* set if integer type is unsigned */
+ my_bool long_data_used; /* If used with mysql_send_long_data */
+ my_bool is_null_value; /* Used if is_null is 0 */
+ void *extension;
+} MYSQL_BIND;
+
+typedef struct st_mysqlnd_upsert_result
+{
+ unsigned int warning_count;
+ unsigned int server_status;
+ unsigned long long affected_rows;
+ unsigned long long last_insert_id;
+} mysql_upsert_status;
+
+typedef struct st_mysql_cmd_buffer
+{
+ unsigned char *buffer;
+ size_t length;
+} MYSQL_CMD_BUFFER;
+
+typedef struct st_mysql_error_info
+{
+ unsigned int error_no;
+ char error[MYSQL_ERRMSG_SIZE+1];
+ char sqlstate[SQLSTATE_LENGTH + 1];
+} mysql_error_info;
+
+typedef int (*mysql_stmt_fetch_row_func)(MYSQL_STMT *stmt, unsigned char **row);
+typedef void (*ps_result_callback)(void *data, unsigned int column, unsigned char **row);
+typedef my_bool *(*ps_param_callback)(void *data, MYSQL_BIND *bind, unsigned int row_nr);
+
+struct st_mysql_stmt
+{
+ MA_MEM_ROOT mem_root;
+ MYSQL *mysql;
+ unsigned long stmt_id;
+ unsigned long flags;/* cursor is set here */
+ enum_mysqlnd_stmt_state state;
+ MYSQL_FIELD *fields;
+ unsigned int field_count;
+ unsigned int param_count;
+ unsigned char send_types_to_server;
+ MYSQL_BIND *params;
+ MYSQL_BIND *bind;
+ MYSQL_DATA result; /* we don't use mysqlnd's result set logic */
+ MYSQL_ROWS *result_cursor;
+ my_bool bind_result_done;
+ my_bool bind_param_done;
+
+ mysql_upsert_status upsert_status;
+
+ unsigned int last_errno;
+ char last_error[MYSQL_ERRMSG_SIZE+1];
+ char sqlstate[SQLSTATE_LENGTH + 1];
+
+ my_bool update_max_length;
+ unsigned long prefetch_rows;
+ LIST list;
+
+ my_bool cursor_exists;
+
+ void *extension;
+ mysql_stmt_fetch_row_func fetch_row_func;
+ unsigned int execute_count;/* count how many times the stmt was executed */
+ mysql_stmt_use_or_store_func default_rset_handler;
+ unsigned char *request_buffer;
+ unsigned int array_size;
+ size_t row_size;
+ unsigned int prebind_params;
+ void *user_data;
+ ps_result_callback result_callback;
+ ps_param_callback param_callback;
+ size_t request_length;
+};
+
+typedef void (*ps_field_fetch_func)(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row);
+typedef struct st_mysql_perm_bind {
+ ps_field_fetch_func func;
+ /* should be signed int */
+ int pack_len;
+ unsigned long max_len;
+} MYSQL_PS_CONVERSION;
+
+extern MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 1];
+unsigned long ma_net_safe_read(MYSQL *mysql);
+void mysql_init_ps_subsystem(void);
+unsigned long net_field_length(unsigned char **packet);
+int ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ size_t length, my_bool skipp_check, void *opt_arg);
+void stmt_set_error(MYSQL_STMT *stmt,
+ unsigned int error_nr,
+ const char *sqlstate,
+ const char *format,
+ ...);
+/*
+ * function prototypes
+ */
+MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
+int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length);
+int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset);
+int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
+unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *attr);
+my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *attr);
+my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt);
+my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt);
+my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int param_number, const char *data, unsigned long length);
+MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt);
+MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt);
+unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt);
+const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt);
+const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt);
+MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset);
+MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt);
+void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, unsigned long long offset);
+unsigned long long STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt);
+unsigned long long STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt);
+unsigned long long STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt);
+unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt);
+my_bool STDCALL mysql_stmt_more_results(MYSQL_STMT *stmt);
+int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, const char *stmt_str, size_t length);
+MYSQL_FIELD * STDCALL mariadb_stmt_fetch_fields(MYSQL_STMT *stmt);
diff --git a/libmariadb/include/mariadb_version.h.in b/libmariadb/include/mariadb_version.h.in
new file mode 100644
index 00000000..a82dbb71
--- /dev/null
+++ b/libmariadb/include/mariadb_version.h.in
@@ -0,0 +1,44 @@
+/* Copyright Abandoned 1996, 1999, 2001 MySQL AB
+ This file is public domain and comes with NO WARRANTY of any kind */
+
+/* Version numbers for protocol & mysqld */
+
+#ifndef _mariadb_version_h_
+#define _mariadb_version_h_
+
+#ifdef _CUSTOMCONFIG_
+#include <custom_conf.h>
+#else
+#define PROTOCOL_VERSION @PROTOCOL_VERSION@
+#define MARIADB_CLIENT_VERSION_STR "@MARIADB_CLIENT_VERSION@"
+#define MARIADB_BASE_VERSION "@MARIADB_BASE_VERSION@"
+#define MARIADB_VERSION_ID @MARIADB_VERSION_ID@
+#define MARIADB_PORT @MARIADB_PORT@
+#define MARIADB_UNIX_ADDR "@MARIADB_UNIX_ADDR@"
+#ifndef MYSQL_UNIX_ADDR
+#define MYSQL_UNIX_ADDR MARIADB_UNIX_ADDR
+#endif
+#ifndef MYSQL_PORT
+#define MYSQL_PORT MARIADB_PORT
+#endif
+
+#define MYSQL_CONFIG_NAME "my"
+#define MYSQL_VERSION_ID @MARIADB_VERSION_ID@
+#define MYSQL_SERVER_VERSION "@MARIADB_CLIENT_VERSION@-MariaDB"
+
+#define MARIADB_PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@"
+#define MARIADB_PACKAGE_VERSION_ID @MARIADB_PACKAGE_VERSION_ID@
+#define MARIADB_SYSTEM_TYPE "@CMAKE_SYSTEM_NAME@"
+#define MARIADB_MACHINE_TYPE "@CMAKE_SYSTEM_PROCESSOR@"
+#define MARIADB_PLUGINDIR "@CMAKE_INSTALL_PREFIX@/@INSTALL_PLUGINDIR@"
+
+/* mysqld compile time options */
+#ifndef MYSQL_CHARSET
+#define MYSQL_CHARSET "@default_charset@"
+#endif
+#endif
+
+/* Source information */
+#define CC_SOURCE_REVISION "@CC_SOURCE_REVISION@"
+
+#endif /* _mariadb_version_h_ */
diff --git a/libmariadb/include/mysql.h b/libmariadb/include/mysql.h
new file mode 100644
index 00000000..76b16830
--- /dev/null
+++ b/libmariadb/include/mysql.h
@@ -0,0 +1,907 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2012 by MontyProgram AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* defines for the libmariadb library */
+
+#ifndef _mysql_h
+#define _mysql_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LIBMARIADB
+#define LIBMARIADB
+#endif
+#ifndef MYSQL_CLIENT
+#define MYSQL_CLIENT
+#endif
+
+#include <stdarg.h>
+
+#if !defined (_global_h) && !defined (MY_GLOBAL_INCLUDED) /* If not standard header */
+#include <sys/types.h>
+typedef char my_bool;
+typedef unsigned long long my_ulonglong;
+
+#if !defined(_WIN32)
+#define STDCALL
+#else
+#define STDCALL __stdcall
+#endif
+
+#ifndef my_socket_defined
+#define my_socket_defined
+#if defined(_WIN64)
+#define my_socket unsigned long long
+#elif defined(_WIN32)
+#define my_socket unsigned int
+#else
+typedef int my_socket;
+#endif
+#endif
+#endif
+#include "mariadb_com.h"
+#include "mariadb_version.h"
+#include "ma_list.h"
+#include "mariadb_ctype.h"
+
+
+typedef struct st_ma_const_string
+{
+ const char *str;
+ size_t length;
+} MARIADB_CONST_STRING;
+
+typedef struct st_ma_const_data
+{
+ const unsigned char *data;
+ size_t length;
+} MARIADB_CONST_DATA;
+
+
+#ifndef ST_MA_USED_MEM_DEFINED
+#define ST_MA_USED_MEM_DEFINED
+ typedef struct st_ma_used_mem { /* struct for once_alloc */
+ struct st_ma_used_mem *next; /* Next block in use */
+ size_t left; /* memory left in block */
+ size_t size; /* Size of block */
+ } MA_USED_MEM;
+
+ typedef struct st_ma_mem_root {
+ MA_USED_MEM *free;
+ MA_USED_MEM *used;
+ MA_USED_MEM *pre_alloc;
+ size_t min_malloc;
+ size_t block_size;
+ unsigned int block_num;
+ unsigned int first_block_usage;
+ void (*error_handler)(void);
+ } MA_MEM_ROOT;
+#endif
+
+extern unsigned int mysql_port;
+extern char *mysql_unix_port;
+extern unsigned int mariadb_deinitialize_ssl;
+
+#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
+#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
+#define IS_BLOB(n) ((n) & BLOB_FLAG)
+#define IS_NUM(t) (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL)
+#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
+#define INTERNAL_NUM_FIELD(f) (((f)->type <= MYSQL_TYPE_INT24 && ((f)->type != MYSQL_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == MYSQL_TYPE_YEAR || (f)->type == MYSQL_TYPE_NEWDECIMAL || (f)->type == MYSQL_TYPE_DECIMAL)
+
+ typedef struct st_mysql_field {
+ char *name; /* Name of column */
+ char *org_name; /* Name of original column (added after 3.23.58) */
+ char *table; /* Table of column if column was a field */
+ char *org_table; /* Name of original table (added after 3.23.58 */
+ char *db; /* table schema (added after 3.23.58) */
+ char *catalog; /* table catalog (added after 3.23.58) */
+ char *def; /* Default value (set by mysql_list_fields) */
+ unsigned long length; /* Width of column */
+ unsigned long max_length; /* Max width of selected set */
+ /* added after 3.23.58 */
+ unsigned int name_length;
+ unsigned int org_name_length;
+ unsigned int table_length;
+ unsigned int org_table_length;
+ unsigned int db_length;
+ unsigned int catalog_length;
+ unsigned int def_length;
+ /***********************/
+ unsigned int flags; /* Div flags */
+ unsigned int decimals; /* Number of decimals in field */
+ unsigned int charsetnr; /* char set number (added in 4.1) */
+ enum enum_field_types type; /* Type of field. Se mysql_com.h for types */
+ void *extension; /* added in 4.1 */
+ } MYSQL_FIELD;
+
+ typedef char **MYSQL_ROW; /* return data as array of strings */
+ typedef unsigned int MYSQL_FIELD_OFFSET; /* offset to current field */
+
+#define SET_CLIENT_ERROR(a, b, c, d) \
+ do { \
+ (a)->net.last_errno= (b);\
+ strncpy((a)->net.sqlstate, (c), SQLSTATE_LENGTH);\
+ (a)->net.sqlstate[SQLSTATE_LENGTH]= 0;\
+ strncpy((a)->net.last_error, (d) ? (d) : ER((b)), MYSQL_ERRMSG_SIZE - 1);\
+ (a)->net.last_error[MYSQL_ERRMSG_SIZE - 1]= 0;\
+ } while(0)
+
+/* For mysql_async.c */
+#define set_mariadb_error(A,B,C) SET_CLIENT_ERROR((A),(B),(C),0)
+extern const char *SQLSTATE_UNKNOWN;
+#define unknown_sqlstate SQLSTATE_UNKNOWN
+
+#define CLEAR_CLIENT_ERROR(a) \
+ do { \
+ (a)->net.last_errno= 0;\
+ strcpy((a)->net.sqlstate, "00000");\
+ (a)->net.last_error[0]= '\0';\
+ if ((a)->net.extension)\
+ (a)->net.extension->extended_errno= 0;\
+ } while (0)
+
+#define MYSQL_COUNT_ERROR (~(unsigned long long) 0)
+
+
+ typedef struct st_mysql_rows {
+ struct st_mysql_rows *next; /* list of rows */
+ MYSQL_ROW data;
+ unsigned long length;
+ } MYSQL_ROWS;
+
+ typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
+
+ typedef struct st_mysql_data {
+ MYSQL_ROWS *data;
+ void *embedded_info;
+ MA_MEM_ROOT alloc;
+ unsigned long long rows;
+ unsigned int fields;
+ void *extension;
+ } MYSQL_DATA;
+
+ enum mysql_option
+ {
+ MYSQL_OPT_CONNECT_TIMEOUT,
+ MYSQL_OPT_COMPRESS,
+ MYSQL_OPT_NAMED_PIPE,
+ MYSQL_INIT_COMMAND,
+ MYSQL_READ_DEFAULT_FILE,
+ MYSQL_READ_DEFAULT_GROUP,
+ MYSQL_SET_CHARSET_DIR,
+ MYSQL_SET_CHARSET_NAME,
+ MYSQL_OPT_LOCAL_INFILE,
+ MYSQL_OPT_PROTOCOL,
+ MYSQL_SHARED_MEMORY_BASE_NAME,
+ MYSQL_OPT_READ_TIMEOUT,
+ MYSQL_OPT_WRITE_TIMEOUT,
+ MYSQL_OPT_USE_RESULT,
+ MYSQL_OPT_USE_REMOTE_CONNECTION,
+ MYSQL_OPT_USE_EMBEDDED_CONNECTION,
+ MYSQL_OPT_GUESS_CONNECTION,
+ MYSQL_SET_CLIENT_IP,
+ MYSQL_SECURE_AUTH,
+ MYSQL_REPORT_DATA_TRUNCATION,
+ MYSQL_OPT_RECONNECT,
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ MYSQL_PLUGIN_DIR,
+ MYSQL_DEFAULT_AUTH,
+ MYSQL_OPT_BIND,
+ MYSQL_OPT_SSL_KEY,
+ MYSQL_OPT_SSL_CERT,
+ MYSQL_OPT_SSL_CA,
+ MYSQL_OPT_SSL_CAPATH,
+ MYSQL_OPT_SSL_CIPHER,
+ MYSQL_OPT_SSL_CRL,
+ MYSQL_OPT_SSL_CRLPATH,
+ /* Connection attribute options */
+ MYSQL_OPT_CONNECT_ATTR_RESET,
+ MYSQL_OPT_CONNECT_ATTR_ADD,
+ MYSQL_OPT_CONNECT_ATTR_DELETE,
+ MYSQL_SERVER_PUBLIC_KEY,
+ MYSQL_ENABLE_CLEARTEXT_PLUGIN,
+ MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
+ MYSQL_OPT_SSL_ENFORCE,
+ MYSQL_OPT_MAX_ALLOWED_PACKET,
+ MYSQL_OPT_NET_BUFFER_LENGTH,
+ MYSQL_OPT_TLS_VERSION,
+
+ /* MariaDB specific */
+ MYSQL_PROGRESS_CALLBACK=5999,
+ MYSQL_OPT_NONBLOCK,
+ /* MariaDB Connector/C specific */
+ MYSQL_DATABASE_DRIVER=7000,
+ MARIADB_OPT_SSL_FP, /* deprecated, use MARIADB_OPT_TLS_PEER_FP instead */
+ MARIADB_OPT_SSL_FP_LIST, /* deprecated, use MARIADB_OPT_TLS_PEER_FP_LIST instead */
+ MARIADB_OPT_TLS_PASSPHRASE, /* passphrase for encrypted certificates */
+ MARIADB_OPT_TLS_CIPHER_STRENGTH,
+ MARIADB_OPT_TLS_VERSION,
+ MARIADB_OPT_TLS_PEER_FP, /* single finger print for server certificate verification */
+ MARIADB_OPT_TLS_PEER_FP_LIST, /* finger print white list for server certificate verification */
+ MARIADB_OPT_CONNECTION_READ_ONLY,
+ MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */
+ MARIADB_OPT_USERDATA,
+ MARIADB_OPT_CONNECTION_HANDLER,
+ MARIADB_OPT_PORT,
+ MARIADB_OPT_UNIXSOCKET,
+ MARIADB_OPT_PASSWORD,
+ MARIADB_OPT_HOST,
+ MARIADB_OPT_USER,
+ MARIADB_OPT_SCHEMA,
+ MARIADB_OPT_DEBUG,
+ MARIADB_OPT_FOUND_ROWS,
+ MARIADB_OPT_MULTI_RESULTS,
+ MARIADB_OPT_MULTI_STATEMENTS,
+ MARIADB_OPT_INTERACTIVE,
+ MARIADB_OPT_PROXY_HEADER,
+ MARIADB_OPT_IO_WAIT,
+ MARIADB_OPT_SKIP_READ_RESPONSE,
+ MARIADB_OPT_RESTRICTED_AUTH,
+ MARIADB_OPT_RPL_REGISTER_REPLICA,
+ MARIADB_OPT_STATUS_CALLBACK,
+ MARIADB_OPT_SERVER_PLUGINS
+ };
+
+ enum mariadb_value {
+ MARIADB_CHARSET_ID,
+ MARIADB_CHARSET_NAME,
+ MARIADB_CLIENT_ERRORS,
+ MARIADB_CLIENT_VERSION,
+ MARIADB_CLIENT_VERSION_ID,
+ MARIADB_CONNECTION_ASYNC_TIMEOUT,
+ MARIADB_CONNECTION_ASYNC_TIMEOUT_MS,
+ MARIADB_CONNECTION_MARIADB_CHARSET_INFO,
+ MARIADB_CONNECTION_ERROR,
+ MARIADB_CONNECTION_ERROR_ID,
+ MARIADB_CONNECTION_HOST,
+ MARIADB_CONNECTION_INFO,
+ MARIADB_CONNECTION_PORT,
+ MARIADB_CONNECTION_PROTOCOL_VERSION_ID,
+ MARIADB_CONNECTION_PVIO_TYPE,
+ MARIADB_CONNECTION_SCHEMA,
+ MARIADB_CONNECTION_SERVER_TYPE,
+ MARIADB_CONNECTION_SERVER_VERSION,
+ MARIADB_CONNECTION_SERVER_VERSION_ID,
+ MARIADB_CONNECTION_SOCKET,
+ MARIADB_CONNECTION_SQLSTATE,
+ MARIADB_CONNECTION_SSL_CIPHER,
+ MARIADB_TLS_LIBRARY,
+ MARIADB_CONNECTION_TLS_VERSION,
+ MARIADB_CONNECTION_TLS_VERSION_ID,
+ MARIADB_CONNECTION_TYPE,
+ MARIADB_CONNECTION_UNIX_SOCKET,
+ MARIADB_CONNECTION_USER,
+ MARIADB_MAX_ALLOWED_PACKET,
+ MARIADB_NET_BUFFER_LENGTH,
+ MARIADB_CONNECTION_SERVER_STATUS,
+ MARIADB_CONNECTION_SERVER_CAPABILITIES,
+ MARIADB_CONNECTION_EXTENDED_SERVER_CAPABILITIES,
+ MARIADB_CONNECTION_CLIENT_CAPABILITIES,
+ MARIADB_CONNECTION_BYTES_READ,
+ MARIADB_CONNECTION_BYTES_SENT
+ };
+
+ enum mysql_status { MYSQL_STATUS_READY,
+ MYSQL_STATUS_GET_RESULT,
+ MYSQL_STATUS_USE_RESULT,
+ MYSQL_STATUS_QUERY_SENT,
+ MYSQL_STATUS_SENDING_LOAD_DATA,
+ MYSQL_STATUS_FETCHING_DATA,
+ MYSQL_STATUS_NEXT_RESULT_PENDING,
+ MYSQL_STATUS_QUIT_SENT, /* object is "destroyed" at this stage */
+ MYSQL_STATUS_STMT_RESULT
+ };
+
+ enum mysql_protocol_type
+ {
+ MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET,
+ MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY
+ };
+
+struct st_mysql_options {
+ unsigned int connect_timeout, read_timeout, write_timeout;
+ unsigned int port, protocol;
+ unsigned long client_flag;
+ char *host,*user,*password,*unix_socket,*db;
+ struct st_dynamic_array *init_command;
+ char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
+ char *ssl_key; /* PEM key file */
+ char *ssl_cert; /* PEM cert file */
+ char *ssl_ca; /* PEM CA file */
+ char *ssl_capath; /* PEM directory of CA-s? */
+ char *ssl_cipher;
+ char *shared_memory_base_name;
+ unsigned long max_allowed_packet;
+ my_bool use_ssl; /* if to use SSL or not */
+ my_bool compress,named_pipe;
+ my_bool reconnect, unused_1, unused_2, unused_3;
+ enum mysql_option methods_to_use;
+ char *bind_address;
+ my_bool secure_auth;
+ my_bool report_data_truncation;
+ /* function pointers for local infile support */
+ int (*local_infile_init)(void **, const char *, void *);
+ int (*local_infile_read)(void *, char *, unsigned int);
+ void (*local_infile_end)(void *);
+ int (*local_infile_error)(void *, char *, unsigned int);
+ void *local_infile_userdata;
+ struct st_mysql_options_extension *extension;
+};
+
+ typedef struct st_mysql {
+ NET net; /* Communication parameters */
+ void *unused_0;
+ char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
+ char *info,*db;
+ const struct ma_charset_info_st *charset; /* character set */
+ MYSQL_FIELD *fields;
+ MA_MEM_ROOT field_alloc;
+ unsigned long long affected_rows;
+ unsigned long long insert_id; /* id if insert on table with NEXTNR */
+ unsigned long long extra_info; /* Used by mysqlshow */
+ unsigned long thread_id; /* Id for connection in server */
+ unsigned long packet_length;
+ unsigned int port;
+ unsigned long client_flag;
+ unsigned long server_capabilities;
+ unsigned int protocol_version;
+ unsigned int field_count;
+ unsigned int server_status;
+ unsigned int server_language;
+ unsigned int warning_count; /* warning count, added in 4.1 protocol */
+ struct st_mysql_options options;
+ enum mysql_status status;
+ my_bool free_me; /* If free in mysql_close */
+ my_bool unused_1;
+ char scramble_buff[20+ 1];
+ /* madded after 3.23.58 */
+ my_bool unused_2;
+ void *unused_3, *unused_4, *unused_5, *unused_6;
+ LIST *stmts;
+ const struct st_mariadb_methods *methods;
+ void *thd;
+ my_bool *unbuffered_fetch_owner;
+ char *info_buffer;
+ struct st_mariadb_extension *extension;
+} MYSQL;
+
+typedef struct st_mysql_res {
+ unsigned long long row_count;
+ unsigned int field_count, current_field;
+ MYSQL_FIELD *fields;
+ MYSQL_DATA *data;
+ MYSQL_ROWS *data_cursor;
+ MA_MEM_ROOT field_alloc;
+ MYSQL_ROW row; /* If unbuffered read */
+ MYSQL_ROW current_row; /* buffer to current row */
+ unsigned long *lengths; /* column lengths of current row */
+ MYSQL *handle; /* for unbuffered reads */
+ my_bool eof; /* Used my mysql_fetch_row */
+ my_bool is_ps;
+} MYSQL_RES;
+
+typedef struct
+{
+ unsigned long *p_max_allowed_packet;
+ unsigned long *p_net_buffer_length;
+ void *extension;
+} MYSQL_PARAMETERS;
+
+
+enum mariadb_field_attr_t
+{
+ MARIADB_FIELD_ATTR_DATA_TYPE_NAME= 0,
+ MARIADB_FIELD_ATTR_FORMAT_NAME= 1
+};
+
+#define MARIADB_FIELD_ATTR_LAST MARIADB_FIELD_ATTR_FORMAT_NAME
+
+
+int STDCALL mariadb_field_attr(MARIADB_CONST_STRING *attr,
+ const MYSQL_FIELD *field,
+ enum mariadb_field_attr_t type);
+
+#ifndef _mysql_time_h_
+enum enum_mysql_timestamp_type
+{
+ MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1,
+ MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2
+};
+
+typedef struct st_mysql_time
+{
+ unsigned int year, month, day, hour, minute, second;
+ unsigned long second_part;
+ my_bool neg;
+ enum enum_mysql_timestamp_type time_type;
+} MYSQL_TIME;
+#define AUTO_SEC_PART_DIGITS 39
+#endif
+
+#define SEC_PART_DIGITS 6
+#define MARIADB_INVALID_SOCKET -1
+
+/* Asynchronous API constants */
+#define MYSQL_WAIT_READ 1
+#define MYSQL_WAIT_WRITE 2
+#define MYSQL_WAIT_EXCEPT 4
+#define MYSQL_WAIT_TIMEOUT 8
+
+typedef struct character_set
+{
+ unsigned int number; /* character set number */
+ unsigned int state; /* character set state */
+ const char *csname; /* character set name */
+ const char *name; /* collation name */
+ const char *comment; /* comment */
+ const char *dir; /* character set directory */
+ unsigned int mbminlen; /* min. length for multibyte strings */
+ unsigned int mbmaxlen; /* max. length for multibyte strings */
+} MY_CHARSET_INFO;
+
+/* Local infile support functions */
+#define LOCAL_INFILE_ERROR_LEN 512
+
+#include "mariadb_stmt.h"
+
+#ifndef MYSQL_CLIENT_PLUGIN_HEADER
+#define MYSQL_CLIENT_PLUGIN_HEADER \
+ int type; \
+ unsigned int interface_version; \
+ const char *name; \
+ const char *author; \
+ const char *desc; \
+ unsigned int version[3]; \
+ const char *license; \
+ void *mysql_api; \
+ int (*init)(char *, size_t, int, va_list); \
+ int (*deinit)(void); \
+ int (*options)(const char *option, const void *);
+struct st_mysql_client_plugin
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+};
+
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+struct st_mysql_client_plugin * STDCALL
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+struct st_mysql_client_plugin * STDCALL
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+struct st_mysql_client_plugin * STDCALL
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
+#endif
+
+
+void STDCALL mysql_set_local_infile_handler(MYSQL *mysql,
+ int (*local_infile_init)(void **, const char *, void *),
+ int (*local_infile_read)(void *, char *, unsigned int),
+ void (*local_infile_end)(void *),
+ int (*local_infile_error)(void *, char*, unsigned int),
+ void *);
+
+void mysql_set_local_infile_default(MYSQL *mysql);
+
+void my_set_error(MYSQL *mysql, unsigned int error_nr,
+ const char *sqlstate, const char *format, ...);
+/* Functions to get information from the MYSQL and MYSQL_RES structures */
+/* Should definitely be used if one uses shared libraries */
+
+my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);
+unsigned int STDCALL mysql_num_fields(MYSQL_RES *res);
+my_bool STDCALL mysql_eof(MYSQL_RES *res);
+MYSQL_FIELD *STDCALL mysql_fetch_field_direct(MYSQL_RES *res,
+ unsigned int fieldnr);
+MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res);
+MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res);
+unsigned int STDCALL mysql_field_tell(MYSQL_RES *res);
+
+unsigned int STDCALL mysql_field_count(MYSQL *mysql);
+my_bool STDCALL mysql_more_results(MYSQL *mysql);
+int STDCALL mysql_next_result(MYSQL *mysql);
+my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
+my_bool STDCALL mysql_autocommit(MYSQL *mysql, my_bool mode);
+my_bool STDCALL mysql_commit(MYSQL *mysql);
+my_bool STDCALL mysql_rollback(MYSQL *mysql);
+my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql);
+unsigned int STDCALL mysql_errno(MYSQL *mysql);
+const char * STDCALL mysql_error(MYSQL *mysql);
+const char * STDCALL mysql_info(MYSQL *mysql);
+unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
+const char * STDCALL mysql_character_set_name(MYSQL *mysql);
+void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs);
+int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname);
+
+my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...);
+my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *arg);
+MYSQL * STDCALL mysql_init(MYSQL *mysql);
+int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
+ const char *cert, const char *ca,
+ const char *capath, const char *cipher);
+const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql);
+my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
+ const char *passwd, const char *db);
+MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
+ const char *user,
+ const char *passwd,
+ const char *db,
+ unsigned int port,
+ const char *unix_socket,
+ unsigned long clientflag);
+void STDCALL mysql_close(MYSQL *sock);
+int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
+int STDCALL mysql_query(MYSQL *mysql, const char *q);
+int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
+int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
+ unsigned long length);
+int STDCALL mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level);
+int STDCALL mysql_dump_debug_info(MYSQL *mysql);
+int STDCALL mysql_refresh(MYSQL *mysql,
+ unsigned int refresh_options);
+int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
+int STDCALL mysql_ping(MYSQL *mysql);
+char * STDCALL mysql_stat(MYSQL *mysql);
+char * STDCALL mysql_get_server_info(MYSQL *mysql);
+unsigned long STDCALL mysql_get_server_version(MYSQL *mysql);
+char * STDCALL mysql_get_host_info(MYSQL *mysql);
+unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);
+MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild);
+MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild);
+MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
+ const char *wild);
+MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql);
+MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
+MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql);
+int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
+ const void *arg);
+int STDCALL mysql_options4(MYSQL *mysql,enum mysql_option option,
+ const void *arg1, const void *arg2);
+void STDCALL mysql_free_result(MYSQL_RES *result);
+void STDCALL mysql_data_seek(MYSQL_RES *result,
+ unsigned long long offset);
+MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET);
+MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result,
+ MYSQL_FIELD_OFFSET offset);
+MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);
+unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result);
+MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result);
+unsigned long STDCALL mysql_escape_string(char *to,const char *from,
+ unsigned long from_length);
+unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
+ char *to,const char *from,
+ unsigned long length);
+unsigned int STDCALL mysql_thread_safe(void);
+unsigned int STDCALL mysql_warning_count(MYSQL *mysql);
+const char * STDCALL mysql_sqlstate(MYSQL *mysql);
+int STDCALL mysql_server_init(int argc, char **argv, char **groups);
+void STDCALL mysql_server_end(void);
+void STDCALL mysql_thread_end(void);
+my_bool STDCALL mysql_thread_init(void);
+int STDCALL mysql_set_server_option(MYSQL *mysql,
+ enum enum_mysql_set_option option);
+const char * STDCALL mysql_get_client_info(void);
+unsigned long STDCALL mysql_get_client_version(void);
+my_bool STDCALL mariadb_connection(MYSQL *mysql);
+const char * STDCALL mysql_get_server_name(MYSQL *mysql);
+MARIADB_CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname);
+MARIADB_CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr);
+size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, MARIADB_CHARSET_INFO *from_cs,
+ char *to, size_t *to_len, MARIADB_CHARSET_INFO *to_cs, int *errorcode);
+int mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...);
+int mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...);
+int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, void *arg);
+unsigned long STDCALL mysql_hex_string(char *to, const char *from, unsigned long len);
+my_socket STDCALL mysql_get_socket(MYSQL *mysql);
+unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql);
+unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql);
+my_bool STDCALL mariadb_reconnect(MYSQL *mysql);
+int STDCALL mariadb_cancel(MYSQL *mysql);
+void STDCALL mysql_debug(const char *debug);
+unsigned long STDCALL mysql_net_read_packet(MYSQL *mysql);
+unsigned long STDCALL mysql_net_field_length(unsigned char **packet);
+my_bool STDCALL mysql_embedded(void);
+MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void);
+
+/* Async API */
+int STDCALL mysql_close_start(MYSQL *sock);
+int STDCALL mysql_close_cont(MYSQL *sock, int status);
+int STDCALL mysql_commit_start(my_bool *ret, MYSQL * mysql);
+int STDCALL mysql_commit_cont(my_bool *ret, MYSQL * mysql, int status);
+int STDCALL mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, int ready_status);
+int STDCALL mysql_dump_debug_info_start(int *ret, MYSQL *mysql);
+int STDCALL mysql_rollback_start(my_bool *ret, MYSQL * mysql);
+int STDCALL mysql_rollback_cont(my_bool *ret, MYSQL * mysql, int status);
+int STDCALL mysql_autocommit_start(my_bool *ret, MYSQL * mysql,
+ my_bool auto_mode);
+int STDCALL mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status);
+int STDCALL mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, const char *table,
+ const char *wild);
+int STDCALL mysql_autocommit_cont(my_bool *ret, MYSQL * mysql, int status);
+int STDCALL mysql_next_result_start(int *ret, MYSQL *mysql);
+int STDCALL mysql_next_result_cont(int *ret, MYSQL *mysql, int status);
+int STDCALL mysql_select_db_start(int *ret, MYSQL *mysql, const char *db);
+int STDCALL mysql_select_db_cont(int *ret, MYSQL *mysql, int ready_status);
+int STDCALL mysql_stmt_warning_count(MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_next_result_start(int *ret, MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_next_result_cont(int *ret, MYSQL_STMT *stmt, int status);
+
+int STDCALL mysql_set_character_set_start(int *ret, MYSQL *mysql,
+ const char *csname);
+int STDCALL mysql_set_character_set_cont(int *ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_change_user_start(my_bool *ret, MYSQL *mysql,
+ const char *user,
+ const char *passwd,
+ const char *db);
+int STDCALL mysql_change_user_cont(my_bool *ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_real_connect_start(MYSQL **ret, MYSQL *mysql,
+ const char *host,
+ const char *user,
+ const char *passwd,
+ const char *db,
+ unsigned int port,
+ const char *unix_socket,
+ unsigned long clientflag);
+int STDCALL mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_query_start(int *ret, MYSQL *mysql,
+ const char *q);
+int STDCALL mysql_query_cont(int *ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_send_query_start(int *ret, MYSQL *mysql,
+ const char *q,
+ unsigned long length);
+int STDCALL mysql_send_query_cont(int *ret, MYSQL *mysql, int status);
+int STDCALL mysql_real_query_start(int *ret, MYSQL *mysql,
+ const char *q,
+ unsigned long length);
+int STDCALL mysql_real_query_cont(int *ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql);
+int STDCALL mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_shutdown_start(int *ret, MYSQL *mysql,
+ enum mysql_enum_shutdown_level
+ shutdown_level);
+int STDCALL mysql_shutdown_cont(int *ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_refresh_start(int *ret, MYSQL *mysql,
+ unsigned int refresh_options);
+int STDCALL mysql_refresh_cont(int *ret, MYSQL *mysql, int status);
+int STDCALL mysql_kill_start(int *ret, MYSQL *mysql,
+ unsigned long pid);
+int STDCALL mysql_kill_cont(int *ret, MYSQL *mysql, int status);
+int STDCALL mysql_set_server_option_start(int *ret, MYSQL *mysql,
+ enum enum_mysql_set_option
+ option);
+int STDCALL mysql_set_server_option_cont(int *ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_ping_start(int *ret, MYSQL *mysql);
+int STDCALL mysql_ping_cont(int *ret, MYSQL *mysql, int status);
+int STDCALL mysql_stat_start(const char **ret, MYSQL *mysql);
+int STDCALL mysql_stat_cont(const char **ret, MYSQL *mysql,
+ int status);
+int STDCALL mysql_free_result_start(MYSQL_RES *result);
+int STDCALL mysql_free_result_cont(MYSQL_RES *result, int status);
+int STDCALL mysql_fetch_row_start(MYSQL_ROW *ret,
+ MYSQL_RES *result);
+int STDCALL mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result,
+ int status);
+int STDCALL mysql_read_query_result_start(my_bool *ret,
+ MYSQL *mysql);
+int STDCALL mysql_read_query_result_cont(my_bool *ret,
+ MYSQL *mysql, int status);
+int STDCALL mysql_reset_connection_start(int *ret, MYSQL *mysql);
+int STDCALL mysql_reset_connection_cont(int *ret, MYSQL *mysql, int status);
+int STDCALL mysql_session_track_get_next(MYSQL *mysql, enum enum_session_state_type type, const char **data, size_t *length);
+int STDCALL mysql_session_track_get_first(MYSQL *mysql, enum enum_session_state_type type, const char **data, size_t *length);
+int STDCALL mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt,const char *query, unsigned long length);
+int STDCALL mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int status);
+int STDCALL mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int status);
+int STDCALL mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int status);
+int STDCALL mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt,int status);
+int STDCALL mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT * stmt, int status);
+int STDCALL mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT * stmt);
+int STDCALL mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int status);
+int STDCALL mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt);
+int STDCALL mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt,
+ int status);
+int STDCALL mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt,
+ unsigned int param_number,
+ const char *data,
+ unsigned long len);
+int STDCALL mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt,
+ int status);
+int STDCALL mysql_reset_connection(MYSQL *mysql);
+
+/* API function calls (used by dynamic plugins) */
+struct st_mariadb_api {
+ unsigned long long (STDCALL *mysql_num_rows)(MYSQL_RES *res);
+ unsigned int (STDCALL *mysql_num_fields)(MYSQL_RES *res);
+ my_bool (STDCALL *mysql_eof)(MYSQL_RES *res);
+ MYSQL_FIELD *(STDCALL *mysql_fetch_field_direct)(MYSQL_RES *res, unsigned int fieldnr);
+ MYSQL_FIELD * (STDCALL *mysql_fetch_fields)(MYSQL_RES *res);
+ MYSQL_ROWS * (STDCALL *mysql_row_tell)(MYSQL_RES *res);
+ unsigned int (STDCALL *mysql_field_tell)(MYSQL_RES *res);
+ unsigned int (STDCALL *mysql_field_count)(MYSQL *mysql);
+ my_bool (STDCALL *mysql_more_results)(MYSQL *mysql);
+ int (STDCALL *mysql_next_result)(MYSQL *mysql);
+ unsigned long long (STDCALL *mysql_affected_rows)(MYSQL *mysql);
+ my_bool (STDCALL *mysql_autocommit)(MYSQL *mysql, my_bool mode);
+ my_bool (STDCALL *mysql_commit)(MYSQL *mysql);
+ my_bool (STDCALL *mysql_rollback)(MYSQL *mysql);
+ unsigned long long (STDCALL *mysql_insert_id)(MYSQL *mysql);
+ unsigned int (STDCALL *mysql_errno)(MYSQL *mysql);
+ const char * (STDCALL *mysql_error)(MYSQL *mysql);
+ const char * (STDCALL *mysql_info)(MYSQL *mysql);
+ unsigned long (STDCALL *mysql_thread_id)(MYSQL *mysql);
+ const char * (STDCALL *mysql_character_set_name)(MYSQL *mysql);
+ void (STDCALL *mysql_get_character_set_info)(MYSQL *mysql, MY_CHARSET_INFO *cs);
+ int (STDCALL *mysql_set_character_set)(MYSQL *mysql, const char *csname);
+ my_bool (*mariadb_get_infov)(MYSQL *mysql, enum mariadb_value value, void *arg, ...);
+ my_bool (STDCALL *mariadb_get_info)(MYSQL *mysql, enum mariadb_value value, void *arg);
+ MYSQL * (STDCALL *mysql_init)(MYSQL *mysql);
+ int (STDCALL *mysql_ssl_set)(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher);
+ const char * (STDCALL *mysql_get_ssl_cipher)(MYSQL *mysql);
+ my_bool (STDCALL *mysql_change_user)(MYSQL *mysql, const char *user, const char *passwd, const char *db);
+ MYSQL * (STDCALL *mysql_real_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
+ void (STDCALL *mysql_close)(MYSQL *sock);
+ int (STDCALL *mysql_select_db)(MYSQL *mysql, const char *db);
+ int (STDCALL *mysql_query)(MYSQL *mysql, const char *q);
+ int (STDCALL *mysql_send_query)(MYSQL *mysql, const char *q, unsigned long length);
+ my_bool (STDCALL *mysql_read_query_result)(MYSQL *mysql);
+ int (STDCALL *mysql_real_query)(MYSQL *mysql, const char *q, unsigned long length);
+ int (STDCALL *mysql_shutdown)(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level);
+ int (STDCALL *mysql_dump_debug_info)(MYSQL *mysql);
+ int (STDCALL *mysql_refresh)(MYSQL *mysql, unsigned int refresh_options);
+ int (STDCALL *mysql_kill)(MYSQL *mysql,unsigned long pid);
+ int (STDCALL *mysql_ping)(MYSQL *mysql);
+ char * (STDCALL *mysql_stat)(MYSQL *mysql);
+ char * (STDCALL *mysql_get_server_info)(MYSQL *mysql);
+ unsigned long (STDCALL *mysql_get_server_version)(MYSQL *mysql);
+ char * (STDCALL *mysql_get_host_info)(MYSQL *mysql);
+ unsigned int (STDCALL *mysql_get_proto_info)(MYSQL *mysql);
+ MYSQL_RES * (STDCALL *mysql_list_dbs)(MYSQL *mysql,const char *wild);
+ MYSQL_RES * (STDCALL *mysql_list_tables)(MYSQL *mysql,const char *wild);
+ MYSQL_RES * (STDCALL *mysql_list_fields)(MYSQL *mysql, const char *table, const char *wild);
+ MYSQL_RES * (STDCALL *mysql_list_processes)(MYSQL *mysql);
+ MYSQL_RES * (STDCALL *mysql_store_result)(MYSQL *mysql);
+ MYSQL_RES * (STDCALL *mysql_use_result)(MYSQL *mysql);
+ int (STDCALL *mysql_options)(MYSQL *mysql,enum mysql_option option, const void *arg);
+ void (STDCALL *mysql_free_result)(MYSQL_RES *result);
+ void (STDCALL *mysql_data_seek)(MYSQL_RES *result, unsigned long long offset);
+ MYSQL_ROW_OFFSET (STDCALL *mysql_row_seek)(MYSQL_RES *result, MYSQL_ROW_OFFSET);
+ MYSQL_FIELD_OFFSET (STDCALL *mysql_field_seek)(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset);
+ MYSQL_ROW (STDCALL *mysql_fetch_row)(MYSQL_RES *result);
+ unsigned long * (STDCALL *mysql_fetch_lengths)(MYSQL_RES *result);
+ MYSQL_FIELD * (STDCALL *mysql_fetch_field)(MYSQL_RES *result);
+ unsigned long (STDCALL *mysql_escape_string)(char *to,const char *from, unsigned long from_length);
+ unsigned long (STDCALL *mysql_real_escape_string)(MYSQL *mysql, char *to,const char *from, unsigned long length);
+ unsigned int (STDCALL *mysql_thread_safe)(void);
+ unsigned int (STDCALL *mysql_warning_count)(MYSQL *mysql);
+ const char * (STDCALL *mysql_sqlstate)(MYSQL *mysql);
+ int (STDCALL *mysql_server_init)(int argc, char **argv, char **groups);
+ void (STDCALL *mysql_server_end)(void);
+ void (STDCALL *mysql_thread_end)(void);
+ my_bool (STDCALL *mysql_thread_init)(void);
+ int (STDCALL *mysql_set_server_option)(MYSQL *mysql, enum enum_mysql_set_option option);
+ const char * (STDCALL *mysql_get_client_info)(void);
+ unsigned long (STDCALL *mysql_get_client_version)(void);
+ my_bool (STDCALL *mariadb_connection)(MYSQL *mysql);
+ const char * (STDCALL *mysql_get_server_name)(MYSQL *mysql);
+ MARIADB_CHARSET_INFO * (STDCALL *mariadb_get_charset_by_name)(const char *csname);
+ MARIADB_CHARSET_INFO * (STDCALL *mariadb_get_charset_by_nr)(unsigned int csnr);
+ size_t (STDCALL *mariadb_convert_string)(const char *from, size_t *from_len, MARIADB_CHARSET_INFO *from_cs, char *to, size_t *to_len, MARIADB_CHARSET_INFO *to_cs, int *errorcode);
+ int (*mysql_optionsv)(MYSQL *mysql,enum mysql_option option, ...);
+ int (*mysql_get_optionv)(MYSQL *mysql, enum mysql_option option, void *arg, ...);
+ int (STDCALL *mysql_get_option)(MYSQL *mysql, enum mysql_option option, void *arg);
+ unsigned long (STDCALL *mysql_hex_string)(char *to, const char *from, unsigned long len);
+ my_socket (STDCALL *mysql_get_socket)(MYSQL *mysql);
+ unsigned int (STDCALL *mysql_get_timeout_value)(const MYSQL *mysql);
+ unsigned int (STDCALL *mysql_get_timeout_value_ms)(const MYSQL *mysql);
+ my_bool (STDCALL *mariadb_reconnect)(MYSQL *mysql);
+ MYSQL_STMT * (STDCALL *mysql_stmt_init)(MYSQL *mysql);
+ int (STDCALL *mysql_stmt_prepare)(MYSQL_STMT *stmt, const char *query, unsigned long length);
+ int (STDCALL *mysql_stmt_execute)(MYSQL_STMT *stmt);
+ int (STDCALL *mysql_stmt_fetch)(MYSQL_STMT *stmt);
+ int (STDCALL *mysql_stmt_fetch_column)(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset);
+ int (STDCALL *mysql_stmt_store_result)(MYSQL_STMT *stmt);
+ unsigned long (STDCALL *mysql_stmt_param_count)(MYSQL_STMT * stmt);
+ my_bool (STDCALL *mysql_stmt_attr_set)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *attr);
+ my_bool (STDCALL *mysql_stmt_attr_get)(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *attr);
+ my_bool (STDCALL *mysql_stmt_bind_param)(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+ my_bool (STDCALL *mysql_stmt_bind_result)(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+ my_bool (STDCALL *mysql_stmt_close)(MYSQL_STMT * stmt);
+ my_bool (STDCALL *mysql_stmt_reset)(MYSQL_STMT * stmt);
+ my_bool (STDCALL *mysql_stmt_free_result)(MYSQL_STMT *stmt);
+ my_bool (STDCALL *mysql_stmt_send_long_data)(MYSQL_STMT *stmt, unsigned int param_number, const char *data, unsigned long length);
+ MYSQL_RES *(STDCALL *mysql_stmt_result_metadata)(MYSQL_STMT *stmt);
+ MYSQL_RES *(STDCALL *mysql_stmt_param_metadata)(MYSQL_STMT *stmt);
+ unsigned int (STDCALL *mysql_stmt_errno)(MYSQL_STMT * stmt);
+ const char *(STDCALL *mysql_stmt_error)(MYSQL_STMT * stmt);
+ const char *(STDCALL *mysql_stmt_sqlstate)(MYSQL_STMT * stmt);
+ MYSQL_ROW_OFFSET (STDCALL *mysql_stmt_row_seek)(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset);
+ MYSQL_ROW_OFFSET (STDCALL *mysql_stmt_row_tell)(MYSQL_STMT *stmt);
+ void (STDCALL *mysql_stmt_data_seek)(MYSQL_STMT *stmt, unsigned long long offset);
+ unsigned long long (STDCALL *mysql_stmt_num_rows)(MYSQL_STMT *stmt);
+ unsigned long long (STDCALL *mysql_stmt_affected_rows)(MYSQL_STMT *stmt);
+ unsigned long long (STDCALL *mysql_stmt_insert_id)(MYSQL_STMT *stmt);
+ unsigned int (STDCALL *mysql_stmt_field_count)(MYSQL_STMT *stmt);
+ int (STDCALL *mysql_stmt_next_result)(MYSQL_STMT *stmt);
+ my_bool (STDCALL *mysql_stmt_more_results)(MYSQL_STMT *stmt);
+ int (STDCALL *mariadb_stmt_execute_direct)(MYSQL_STMT *stmt, const char *stmtstr, size_t length);
+ int (STDCALL *mysql_reset_connection)(MYSQL *mysql);
+};
+
+/* these methods can be overwritten by db plugins */
+struct st_mariadb_methods {
+ MYSQL *(*db_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd,
+ const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
+ void (*db_close)(MYSQL *mysql);
+ int (*db_command)(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ size_t length, my_bool skip_check, void *opt_arg);
+ void (*db_skip_result)(MYSQL *mysql);
+ int (*db_read_query_result)(MYSQL *mysql);
+ MYSQL_DATA *(*db_read_rows)(MYSQL *mysql,MYSQL_FIELD *fields, unsigned int field_count);
+ int (*db_read_one_row)(MYSQL *mysql,unsigned int fields,MYSQL_ROW row, unsigned long *lengths);
+ /* prepared statements */
+ my_bool (*db_supported_buffer_type)(enum enum_field_types type);
+ my_bool (*db_read_prepare_response)(MYSQL_STMT *stmt);
+ int (*db_read_stmt_result)(MYSQL *mysql);
+ my_bool (*db_stmt_get_result_metadata)(MYSQL_STMT *stmt);
+ my_bool (*db_stmt_get_param_metadata)(MYSQL_STMT *stmt);
+ int (*db_stmt_read_all_rows)(MYSQL_STMT *stmt);
+ int (*db_stmt_fetch)(MYSQL_STMT *stmt, unsigned char **row);
+ int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row);
+ void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt);
+ void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...);
+ void (*invalidate_stmts)(MYSQL *mysql, const char *function_name);
+ struct st_mariadb_api *api;
+ int (*db_read_execute_response)(MYSQL_STMT *stmt);
+ unsigned char* (*db_execute_generate_request)(MYSQL_STMT *stmt, size_t *request_len, my_bool internal);
+};
+
+/* synonyms/aliases functions */
+#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
+#define mysql_library_init mysql_server_init
+#define mysql_library_end mysql_server_end
+#define mariadb_connect(hdl, conn_str) mysql_real_connect((hdl),(conn_str), NULL, NULL, NULL, 0, NULL, 0)
+
+/* new api functions */
+
+#define HAVE_MYSQL_REAL_CONNECT
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmariadb/include/mysql/client_plugin.h b/libmariadb/include/mysql/client_plugin.h
new file mode 100644
index 00000000..262fd4a0
--- /dev/null
+++ b/libmariadb/include/mysql/client_plugin.h
@@ -0,0 +1,258 @@
+/* Copyright (C) 2010 - 2012 Sergei Golubchik and Monty Program Ab
+ 2014, 2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA */
+
+/**
+ @file
+
+ MySQL Client Plugin API
+
+ This file defines the API for plugins that work on the client side
+*/
+#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED
+#define MYSQL_CLIENT_PLUGIN_INCLUDED
+
+#ifndef MYSQL_ABI_CHECK
+#include <stdarg.h>
+#include <stdlib.h>
+#endif
+
+
+#ifndef PLUGINDIR
+#define PLUGINDIR "lib/plugin"
+#endif
+
+#define plugin_declarations_sym "_mysql_client_plugin_declaration_"
+
+/* known plugin types */
+#define MYSQL_CLIENT_PLUGIN_RESERVED 0
+#define MYSQL_CLIENT_PLUGIN_RESERVED2 1
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 /* authentication */
+
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
+#define MYSQL_CLIENT_MAX_PLUGINS 3
+
+/* Connector/C specific plugin types */
+#define MARIADB_CLIENT_REMOTEIO_PLUGIN 100 /* communication IO */
+#define MARIADB_CLIENT_PVIO_PLUGIN 101
+#define MARIADB_CLIENT_TRACE_PLUGIN 102
+#define MARIADB_CLIENT_CONNECTION_PLUGIN 103
+#define MARIADB_CLIENT_COMPRESSION_PLUGIN 104
+
+#define MARIADB_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION 0x0100
+#define MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION 0x0100
+#define MARIADB_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION 0x0100
+#define MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION 0x0100
+#define MARIADB_CLIENT_COMPRESSION_PLUGIN_INTERFACE_VERSION 0x0100
+
+#define MARIADB_CLIENT_MAX_PLUGINS 5
+
+#define mysql_declare_client_plugin(X) \
+ struct st_mysql_client_plugin_ ## X \
+ _mysql_client_plugin_declaration_ = { \
+ MYSQL_CLIENT_ ## X ## _PLUGIN, \
+ MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION,
+#define mysql_end_client_plugin }
+
+/* generic plugin header structure */
+#ifndef MYSQL_CLIENT_PLUGIN_HEADER
+#define MYSQL_CLIENT_PLUGIN_HEADER \
+ int type; \
+ unsigned int interface_version; \
+ const char *name; \
+ const char *author; \
+ const char *desc; \
+ unsigned int version[3]; \
+ const char *license; \
+ void *mysql_api; \
+ int (*init)(char *, size_t, int, va_list); \
+ int (*deinit)(void); \
+ int (*options)(const char *option, const void *);
+
+struct st_mysql_client_plugin
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+};
+#endif
+
+struct st_mysql;
+
+/********* connection handler plugin specific declarations **********/
+
+typedef struct st_ma_connection_plugin
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ /* functions */
+ MYSQL *(*connect)(MYSQL *mysql, const char *host,
+ const char *user, const char *passwd,
+ const char *db, unsigned int port,
+ const char *unix_socket, unsigned long clientflag);
+ void (*close)(MYSQL *mysql);
+ int (*set_optionsv)(MYSQL *mysql, unsigned int option, ...);
+ int (*set_connection)(MYSQL *mysql,enum enum_server_command command,
+ const char *arg,
+ size_t length, my_bool skipp_check, void *opt_arg);
+ my_bool (*reconnect)(MYSQL *mysql);
+ int (*reset)(MYSQL *mysql);
+} MARIADB_CONNECTION_PLUGIN;
+
+#define MARIADB_DB_DRIVER(a) ((a)->ext_db)
+
+/******************* Communication IO plugin *****************/
+#include <ma_pvio.h>
+
+typedef struct st_mariadb_client_plugin_PVIO
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ struct st_ma_pvio_methods *methods;
+} MARIADB_PVIO_PLUGIN;
+
+/******** authentication plugin specific declarations *********/
+#include <mysql/plugin_auth_common.h>
+
+struct st_mysql_client_plugin_AUTHENTICATION
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+};
+
+/******** trace plugin *******/
+struct st_mysql_client_plugin_TRACE
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+};
+
+#include <ma_compress.h>
+
+typedef struct st_mariadb_client_plugin_COMPRESS
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ ma_compress_ctx *(*init_ctx)(int compression_level);
+ void (*free_ctx)(ma_compress_ctx *ctx);
+ my_bool (*compress)(ma_compress_ctx *ctx, void *dst, size_t *dst_len, void *source, size_t source_len);
+ my_bool (*decompress)(ma_compress_ctx *ctx, void *dst, size_t *dst_len, void *source, size_t *source_len);
+} MARIADB_COMPRESSION_PLUGIN;
+
+/**
+ type of the mysql_authentication_dialog_ask function
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - ordinary string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
+ int type, const char *prompt, char *buf, int buf_len);
+
+/********************** remote IO plugin **********************/
+#ifdef HAVE_REMOTEIO
+#include <mariadb/ma_io.h>
+
+/* Remote IO plugin */
+typedef struct st_mysql_client_plugin_REMOTEIO
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ struct st_rio_methods *methods;
+} MARIADB_REMOTEIO_PLUGIN;
+#endif
+
+/******** using plugins ************/
+
+/**
+ loads a plugin and initializes it
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param ... arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+
+/**
+ loads a plugin and initializes it, taking va_list as an argument
+
+ This is the same as mysql_load_plugin, but take va_list instead of
+ a list of arguments.
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param args arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin * STDCALL
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+
+/**
+ finds an already loaded plugin by name, or loads it, if necessary
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin * STDCALL
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+
+/**
+ adds a plugin structure to the list of loaded plugins
+
+ This is useful if an application has the necessary functionality
+ (for example, a special load data handler) statically linked into
+ the application binary. It can use this function to register the plugin
+ directly, avoiding the need to factor it out into a shared object.
+
+ @param mysql MYSQL structure. It is only used for error reporting
+ @param plugin an st_mysql_client_plugin structure to register
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin * STDCALL
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
+
+extern struct st_mysql_client_plugin *mysql_client_builtins[];
+
+#endif
+
+
diff --git a/libmariadb/include/mysql/plugin_auth.h b/libmariadb/include/mysql/plugin_auth.h
new file mode 100644
index 00000000..2be64a6b
--- /dev/null
+++ b/libmariadb/include/mysql/plugin_auth.h
@@ -0,0 +1,107 @@
+#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/**
+ @file
+
+ This file defines constants and data structures that are the same for
+ both client- and server-side authentication plugins.
+*/
+#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+
+/** the max allowed length for a user name */
+#define MYSQL_USERNAME_LENGTH 512
+
+/**
+ return values of the plugin authenticate_user() method.
+*/
+
+/**
+ Authentication failed. Additionally, all other CR_xxx values
+ (libmariadb error code) can be used too.
+
+ The client plugin may set the error code and the error message directly
+ in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error
+ code was returned, an error message in the MYSQL structure will be
+ overwritten. If CR_ERROR is returned without setting the error in MYSQL,
+ CR_UNKNOWN_ERROR will be user.
+*/
+#define CR_ERROR 0
+/**
+ Authentication (client part) was successful. It does not mean that the
+ authentication as a whole was successful, usually it only means
+ that the client was able to send the user name and the password to the
+ server. If CR_OK is returned, the libmariadb reads the next packet expecting
+ it to be one of OK, ERROR, or CHANGE_PLUGIN packets.
+*/
+#define CR_OK -1
+/**
+ Authentication was successful.
+ It means that the client has done its part successfully and also that
+ a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN).
+ In this case, libmariadb will not read a packet from the server,
+ but it will use the data at mysql->net.read_pos.
+
+ A plugin may return this value if the number of roundtrips in the
+ authentication protocol is not known in advance, and the client plugin
+ needs to read one packet more to determine if the authentication is finished
+ or not.
+*/
+#define CR_OK_HANDSHAKE_COMPLETE -2
+
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket; /**< it's set, if the protocol is SOCKET or TCP */
+#ifdef _WIN32
+ HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
+#endif
+} MYSQL_PLUGIN_VIO_INFO;
+
+/**
+ Provides plugin access to communication channel
+*/
+typedef struct st_plugin_vio
+{
+ /**
+ Plugin provides a pointer reference and this function sets it to the
+ contents of any incoming packet. Returns the packet length, or -1 if
+ the plugin should terminate.
+ */
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+
+ /**
+ Plugin provides a buffer with data and the length and this
+ function sends it as a packet. Returns 0 on success, 1 on failure.
+ */
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+
+ /**
+ Fills in a st_plugin_vio_info structure, providing the information
+ about the connection.
+ */
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+
+} MYSQL_PLUGIN_VIO;
+
+#endif
+
diff --git a/libmariadb/include/mysql/plugin_auth_common.h b/libmariadb/include/mysql/plugin_auth_common.h
new file mode 100644
index 00000000..ee4b8b9c
--- /dev/null
+++ b/libmariadb/include/mysql/plugin_auth_common.h
@@ -0,0 +1,110 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+
+#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+/**
+ @file
+
+ This file defines constants and data structures that are the same for
+ both client- and server-side authentication plugins.
+*/
+#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+
+/** the max allowed length for a user name */
+#define MYSQL_USERNAME_LENGTH 512
+
+/**
+ return values of the plugin authenticate_user() method.
+*/
+
+/**
+ Authentication failed. Additionally, all other CR_xxx values
+ (libmariadb error code) can be used too.
+
+ The client plugin may set the error code and the error message directly
+ in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error
+ code was returned, an error message in the MYSQL structure will be
+ overwritten. If CR_ERROR is returned without setting the error in MYSQL,
+ CR_UNKNOWN_ERROR will be user.
+*/
+#define CR_ERROR 0
+/**
+ Authentication (client part) was successful. It does not mean that the
+ authentication as a whole was successful, usually it only means
+ that the client was able to send the user name and the password to the
+ server. If CR_OK is returned, the libmariadb reads the next packet expecting
+ it to be one of OK, ERROR, or CHANGE_PLUGIN packets.
+*/
+#define CR_OK -1
+/**
+ Authentication was successful.
+ It means that the client has done its part successfully and also that
+ a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN).
+ In this case, libmariadb will not read a packet from the server,
+ but it will use the data at mysql->net.read_pos.
+
+ A plugin may return this value if the number of roundtrips in the
+ authentication protocol is not known in advance, and the client plugin
+ needs to read one packet more to determine if the authentication is finished
+ or not.
+*/
+#define CR_OK_HANDSHAKE_COMPLETE -2
+
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+#ifndef _WIN32
+ int socket; /**< it's set, if the protocol is SOCKET or TCP */
+#else
+ SOCKET socket; /**< it's set, if the protocol is SOCKET or TCP */
+ HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
+#endif
+} MYSQL_PLUGIN_VIO_INFO;
+
+/**
+ Provides plugin access to communication channel
+*/
+typedef struct st_plugin_vio
+{
+ /**
+ Plugin provides a pointer reference and this function sets it to the
+ contents of any incoming packet. Returns the packet length, or -1 if
+ the plugin should terminate.
+ */
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+
+ /**
+ Plugin provides a buffer with data and the length and this
+ function sends it as a packet. Returns 0 on success, 1 on failure.
+ */
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+
+ /**
+ Fills in a st_plugin_vio_info structure, providing the information
+ about the connection.
+ */
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+
+} MYSQL_PLUGIN_VIO;
+
+#endif
+
diff --git a/libmariadb/include/mysqld_error.h b/libmariadb/include/mysqld_error.h
new file mode 100644
index 00000000..13365437
--- /dev/null
+++ b/libmariadb/include/mysqld_error.h
@@ -0,0 +1,1240 @@
+/* Autogenerated file, please don't edit */
+
+#ifndef ER_ERROR_FIRST
+#define ER_ERROR_FIRST 1000
+#define ER_HASHCHK 1000
+#define ER_NISAMCHK 1001
+#define ER_NO 1002
+#define ER_YES 1003
+#define ER_CANT_CREATE_FILE 1004
+#define ER_CANT_CREATE_TABLE 1005
+#define ER_CANT_CREATE_DB 1006
+#define ER_DB_CREATE_EXISTS 1007
+#define ER_DB_DROP_EXISTS 1008
+#define ER_DB_DROP_DELETE 1009
+#define ER_DB_DROP_RMDIR 1010
+#define ER_CANT_DELETE_FILE 1011
+#define ER_CANT_FIND_SYSTEM_REC 1012
+#define ER_CANT_GET_STAT 1013
+#define ER_CANT_GET_WD 1014
+#define ER_CANT_LOCK 1015
+#define ER_CANT_OPEN_FILE 1016
+#define ER_FILE_NOT_FOUND 1017
+#define ER_CANT_READ_DIR 1018
+#define ER_CANT_SET_WD 1019
+#define ER_CHECKREAD 1020
+#define ER_DISK_FULL 1021
+#define ER_DUP_KEY 1022
+#define ER_ERROR_ON_CLOSE 1023
+#define ER_ERROR_ON_READ 1024
+#define ER_ERROR_ON_RENAME 1025
+#define ER_ERROR_ON_WRITE 1026
+#define ER_FILE_USED 1027
+#define ER_FILSORT_ABORT 1028
+#define ER_FORM_NOT_FOUND 1029
+#define ER_GET_ERRNO 1030
+#define ER_ILLEGAL_HA 1031
+#define ER_KEY_NOT_FOUND 1032
+#define ER_NOT_FORM_FILE 1033
+#define ER_NOT_KEYFILE 1034
+#define ER_OLD_KEYFILE 1035
+#define ER_OPEN_AS_READONLY 1036
+#define ER_OUTOFMEMORY 1037
+#define ER_OUT_OF_SORTMEMORY 1038
+#define ER_UNEXPECTED_EOF 1039
+#define ER_CON_COUNT_ERROR 1040
+#define ER_OUT_OF_RESOURCES 1041
+#define ER_BAD_HOST_ERROR 1042
+#define ER_HANDSHAKE_ERROR 1043
+#define ER_DBACCESS_DENIED_ERROR 1044
+#define ER_ACCESS_DENIED_ERROR 1045
+#define ER_NO_DB_ERROR 1046
+#define ER_UNKNOWN_COM_ERROR 1047
+#define ER_BAD_NULL_ERROR 1048
+#define ER_BAD_DB_ERROR 1049
+#define ER_TABLE_EXISTS_ERROR 1050
+#define ER_BAD_TABLE_ERROR 1051
+#define ER_NON_UNIQ_ERROR 1052
+#define ER_SERVER_SHUTDOWN 1053
+#define ER_BAD_FIELD_ERROR 1054
+#define ER_WRONG_FIELD_WITH_GROUP 1055
+#define ER_WRONG_GROUP_FIELD 1056
+#define ER_WRONG_SUM_SELECT 1057
+#define ER_WRONG_VALUE_COUNT 1058
+#define ER_TOO_LONG_IDENT 1059
+#define ER_DUP_FIELDNAME 1060
+#define ER_DUP_KEYNAME 1061
+#define ER_DUP_ENTRY 1062
+#define ER_WRONG_FIELD_SPEC 1063
+#define ER_PARSE_ERROR 1064
+#define ER_EMPTY_QUERY 1065
+#define ER_NONUNIQ_TABLE 1066
+#define ER_INVALID_DEFAULT 1067
+#define ER_MULTIPLE_PRI_KEY 1068
+#define ER_TOO_MANY_KEYS 1069
+#define ER_TOO_MANY_KEY_PARTS 1070
+#define ER_TOO_LONG_KEY 1071
+#define ER_KEY_COLUMN_DOES_NOT_EXIST 1072
+#define ER_BLOB_USED_AS_KEY 1073
+#define ER_TOO_BIG_FIELDLENGTH 1074
+#define ER_WRONG_AUTO_KEY 1075
+#define ER_BINLOG_CANT_DELETE_GTID_DOMAIN 1076
+#define ER_NORMAL_SHUTDOWN 1077
+#define ER_GOT_SIGNAL 1078
+#define ER_SHUTDOWN_COMPLETE 1079
+#define ER_FORCING_CLOSE 1080
+#define ER_IPSOCK_ERROR 1081
+#define ER_NO_SUCH_INDEX 1082
+#define ER_WRONG_FIELD_TERMINATORS 1083
+#define ER_BLOBS_AND_NO_TERMINATED 1084
+#define ER_TEXTFILE_NOT_READABLE 1085
+#define ER_FILE_EXISTS_ERROR 1086
+#define ER_LOAD_INFO 1087
+#define ER_ALTER_INFO 1088
+#define ER_WRONG_SUB_KEY 1089
+#define ER_CANT_REMOVE_ALL_FIELDS 1090
+#define ER_CANT_DROP_FIELD_OR_KEY 1091
+#define ER_INSERT_INFO 1092
+#define ER_UPDATE_TABLE_USED 1093
+#define ER_NO_SUCH_THREAD 1094
+#define ER_KILL_DENIED_ERROR 1095
+#define ER_NO_TABLES_USED 1096
+#define ER_TOO_BIG_SET 1097
+#define ER_NO_UNIQUE_LOGFILE 1098
+#define ER_TABLE_NOT_LOCKED_FOR_WRITE 1099
+#define ER_TABLE_NOT_LOCKED 1100
+#define ER_UNUSED_17 1101
+#define ER_WRONG_DB_NAME 1102
+#define ER_WRONG_TABLE_NAME 1103
+#define ER_TOO_BIG_SELECT 1104
+#define ER_UNKNOWN_ERROR 1105
+#define ER_UNKNOWN_PROCEDURE 1106
+#define ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107
+#define ER_WRONG_PARAMETERS_TO_PROCEDURE 1108
+#define ER_UNKNOWN_TABLE 1109
+#define ER_FIELD_SPECIFIED_TWICE 1110
+#define ER_INVALID_GROUP_FUNC_USE 1111
+#define ER_UNSUPPORTED_EXTENSION 1112
+#define ER_TABLE_MUST_HAVE_COLUMNS 1113
+#define ER_RECORD_FILE_FULL 1114
+#define ER_UNKNOWN_CHARACTER_SET 1115
+#define ER_TOO_MANY_TABLES 1116
+#define ER_TOO_MANY_FIELDS 1117
+#define ER_TOO_BIG_ROWSIZE 1118
+#define ER_STACK_OVERRUN 1119
+#define ER_WRONG_OUTER_JOIN 1120
+#define ER_NULL_COLUMN_IN_INDEX 1121
+#define ER_CANT_FIND_UDF 1122
+#define ER_CANT_INITIALIZE_UDF 1123
+#define ER_UDF_NO_PATHS 1124
+#define ER_UDF_EXISTS 1125
+#define ER_CANT_OPEN_LIBRARY 1126
+#define ER_CANT_FIND_DL_ENTRY 1127
+#define ER_FUNCTION_NOT_DEFINED 1128
+#define ER_HOST_IS_BLOCKED 1129
+#define ER_HOST_NOT_PRIVILEGED 1130
+#define ER_PASSWORD_ANONYMOUS_USER 1131
+#define ER_PASSWORD_NOT_ALLOWED 1132
+#define ER_PASSWORD_NO_MATCH 1133
+#define ER_UPDATE_INFO 1134
+#define ER_CANT_CREATE_THREAD 1135
+#define ER_WRONG_VALUE_COUNT_ON_ROW 1136
+#define ER_CANT_REOPEN_TABLE 1137
+#define ER_INVALID_USE_OF_NULL 1138
+#define ER_REGEXP_ERROR 1139
+#define ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140
+#define ER_NONEXISTING_GRANT 1141
+#define ER_TABLEACCESS_DENIED_ERROR 1142
+#define ER_COLUMNACCESS_DENIED_ERROR 1143
+#define ER_ILLEGAL_GRANT_FOR_TABLE 1144
+#define ER_GRANT_WRONG_HOST_OR_USER 1145
+#define ER_NO_SUCH_TABLE 1146
+#define ER_NONEXISTING_TABLE_GRANT 1147
+#define ER_NOT_ALLOWED_COMMAND 1148
+#define ER_SYNTAX_ERROR 1149
+#define ER_DELAYED_CANT_CHANGE_LOCK 1150
+#define ER_TOO_MANY_DELAYED_THREADS 1151
+#define ER_ABORTING_CONNECTION 1152
+#define ER_NET_PACKET_TOO_LARGE 1153
+#define ER_NET_READ_ERROR_FROM_PIPE 1154
+#define ER_NET_FCNTL_ERROR 1155
+#define ER_NET_PACKETS_OUT_OF_ORDER 1156
+#define ER_NET_UNCOMPRESS_ERROR 1157
+#define ER_NET_READ_ERROR 1158
+#define ER_NET_READ_INTERRUPTED 1159
+#define ER_NET_ERROR_ON_WRITE 1160
+#define ER_NET_WRITE_INTERRUPTED 1161
+#define ER_TOO_LONG_STRING 1162
+#define ER_TABLE_CANT_HANDLE_BLOB 1163
+#define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164
+#define ER_DELAYED_INSERT_TABLE_LOCKED 1165
+#define ER_WRONG_COLUMN_NAME 1166
+#define ER_WRONG_KEY_COLUMN 1167
+#define ER_WRONG_MRG_TABLE 1168
+#define ER_DUP_UNIQUE 1169
+#define ER_BLOB_KEY_WITHOUT_LENGTH 1170
+#define ER_PRIMARY_CANT_HAVE_NULL 1171
+#define ER_TOO_MANY_ROWS 1172
+#define ER_REQUIRES_PRIMARY_KEY 1173
+#define ER_NO_RAID_COMPILED 1174
+#define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175
+#define ER_KEY_DOES_NOT_EXISTS 1176
+#define ER_CHECK_NO_SUCH_TABLE 1177
+#define ER_CHECK_NOT_IMPLEMENTED 1178
+#define ER_CANT_DO_THIS_DURING_AN_TRANSACTION 1179
+#define ER_ERROR_DURING_COMMIT 1180
+#define ER_ERROR_DURING_ROLLBACK 1181
+#define ER_ERROR_DURING_FLUSH_LOGS 1182
+#define ER_ERROR_DURING_CHECKPOINT 1183
+#define ER_NEW_ABORTING_CONNECTION 1184
+#define ER_UNUSED_10 1185
+#define ER_FLUSH_MASTER_BINLOG_CLOSED 1186
+#define ER_INDEX_REBUILD 1187
+#define ER_MASTER 1188
+#define ER_MASTER_NET_READ 1189
+#define ER_MASTER_NET_WRITE 1190
+#define ER_FT_MATCHING_KEY_NOT_FOUND 1191
+#define ER_LOCK_OR_ACTIVE_TRANSACTION 1192
+#define ER_UNKNOWN_SYSTEM_VARIABLE 1193
+#define ER_CRASHED_ON_USAGE 1194
+#define ER_CRASHED_ON_REPAIR 1195
+#define ER_WARNING_NOT_COMPLETE_ROLLBACK 1196
+#define ER_TRANS_CACHE_FULL 1197
+#define ER_SLAVE_MUST_STOP 1198
+#define ER_SLAVE_NOT_RUNNING 1199
+#define ER_BAD_SLAVE 1200
+#define ER_MASTER_INFO 1201
+#define ER_SLAVE_THREAD 1202
+#define ER_TOO_MANY_USER_CONNECTIONS 1203
+#define ER_SET_CONSTANTS_ONLY 1204
+#define ER_LOCK_WAIT_TIMEOUT 1205
+#define ER_LOCK_TABLE_FULL 1206
+#define ER_READ_ONLY_TRANSACTION 1207
+#define ER_DROP_DB_WITH_READ_LOCK 1208
+#define ER_CREATE_DB_WITH_READ_LOCK 1209
+#define ER_WRONG_ARGUMENTS 1210
+#define ER_NO_PERMISSION_TO_CREATE_USER 1211
+#define ER_UNION_TABLES_IN_DIFFERENT_DIR 1212
+#define ER_LOCK_DEADLOCK 1213
+#define ER_TABLE_CANT_HANDLE_FT 1214
+#define ER_CANNOT_ADD_FOREIGN 1215
+#define ER_NO_REFERENCED_ROW 1216
+#define ER_ROW_IS_REFERENCED 1217
+#define ER_CONNECT_TO_MASTER 1218
+#define ER_QUERY_ON_MASTER 1219
+#define ER_ERROR_WHEN_EXECUTING_COMMAND 1220
+#define ER_WRONG_USAGE 1221
+#define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222
+#define ER_CANT_UPDATE_WITH_READLOCK 1223
+#define ER_MIXING_NOT_ALLOWED 1224
+#define ER_DUP_ARGUMENT 1225
+#define ER_USER_LIMIT_REACHED 1226
+#define ER_SPECIFIC_ACCESS_DENIED_ERROR 1227
+#define ER_LOCAL_VARIABLE 1228
+#define ER_GLOBAL_VARIABLE 1229
+#define ER_NO_DEFAULT 1230
+#define ER_WRONG_VALUE_FOR_VAR 1231
+#define ER_WRONG_TYPE_FOR_VAR 1232
+#define ER_VAR_CANT_BE_READ 1233
+#define ER_CANT_USE_OPTION_HERE 1234
+#define ER_NOT_SUPPORTED_YET 1235
+#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
+#define ER_SLAVE_IGNORED_TABLE 1237
+#define ER_INCORRECT_GLOBAL_LOCAL_VAR 1238
+#define ER_WRONG_FK_DEF 1239
+#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1240
+#define ER_OPERAND_COLUMNS 1241
+#define ER_SUBQUERY_NO_1_ROW 1242
+#define ER_UNKNOWN_STMT_HANDLER 1243
+#define ER_CORRUPT_HELP_DB 1244
+#define ER_CYCLIC_REFERENCE 1245
+#define ER_AUTO_CONVERT 1246
+#define ER_ILLEGAL_REFERENCE 1247
+#define ER_DERIVED_MUST_HAVE_ALIAS 1248
+#define ER_SELECT_REDUCED 1249
+#define ER_TABLENAME_NOT_ALLOWED_HERE 1250
+#define ER_NOT_SUPPORTED_AUTH_MODE 1251
+#define ER_SPATIAL_CANT_HAVE_NULL 1252
+#define ER_COLLATION_CHARSET_MISMATCH 1253
+#define ER_SLAVE_WAS_RUNNING 1254
+#define ER_SLAVE_WAS_NOT_RUNNING 1255
+#define ER_TOO_BIG_FOR_UNCOMPRESS 1256
+#define ER_ZLIB_Z_MEM_ERROR 1257
+#define ER_ZLIB_Z_BUF_ERROR 1258
+#define ER_ZLIB_Z_DATA_ERROR 1259
+#define ER_CUT_VALUE_GROUP_CONCAT 1260
+#define ER_WARN_TOO_FEW_RECORDS 1261
+#define ER_WARN_TOO_MANY_RECORDS 1262
+#define ER_WARN_NULL_TO_NOTNULL 1263
+#define ER_WARN_DATA_OUT_OF_RANGE 1264
+#define WARN_DATA_TRUNCATED 1265
+#define ER_WARN_USING_OTHER_HANDLER 1266
+#define ER_CANT_AGGREGATE_2COLLATIONS 1267
+#define ER_DROP_USER 1268
+#define ER_REVOKE_GRANTS 1269
+#define ER_CANT_AGGREGATE_3COLLATIONS 1270
+#define ER_CANT_AGGREGATE_NCOLLATIONS 1271
+#define ER_VARIABLE_IS_NOT_STRUCT 1272
+#define ER_UNKNOWN_COLLATION 1273
+#define ER_SLAVE_IGNORED_SSL_PARAMS 1274
+#define ER_SERVER_IS_IN_SECURE_AUTH_MODE 1275
+#define ER_WARN_FIELD_RESOLVED 1276
+#define ER_BAD_SLAVE_UNTIL_COND 1277
+#define ER_MISSING_SKIP_SLAVE 1278
+#define ER_UNTIL_COND_IGNORED 1279
+#define ER_WRONG_NAME_FOR_INDEX 1280
+#define ER_WRONG_NAME_FOR_CATALOG 1281
+#define ER_WARN_QC_RESIZE 1282
+#define ER_BAD_FT_COLUMN 1283
+#define ER_UNKNOWN_KEY_CACHE 1284
+#define ER_WARN_HOSTNAME_WONT_WORK 1285
+#define ER_UNKNOWN_STORAGE_ENGINE 1286
+#define ER_WARN_DEPRECATED_SYNTAX 1287
+#define ER_NON_UPDATABLE_TABLE 1288
+#define ER_FEATURE_DISABLED 1289
+#define ER_OPTION_PREVENTS_STATEMENT 1290
+#define ER_DUPLICATED_VALUE_IN_TYPE 1291
+#define ER_TRUNCATED_WRONG_VALUE 1292
+#define ER_TOO_MUCH_AUTO_TIMESTAMP_COLS 1293
+#define ER_INVALID_ON_UPDATE 1294
+#define ER_UNSUPPORTED_PS 1295
+#define ER_GET_ERRMSG 1296
+#define ER_GET_TEMPORARY_ERRMSG 1297
+#define ER_UNKNOWN_TIME_ZONE 1298
+#define ER_WARN_INVALID_TIMESTAMP 1299
+#define ER_INVALID_CHARACTER_STRING 1300
+#define ER_WARN_ALLOWED_PACKET_OVERFLOWED 1301
+#define ER_CONFLICTING_DECLARATIONS 1302
+#define ER_SP_NO_RECURSIVE_CREATE 1303
+#define ER_SP_ALREADY_EXISTS 1304
+#define ER_SP_DOES_NOT_EXIST 1305
+#define ER_SP_DROP_FAILED 1306
+#define ER_SP_STORE_FAILED 1307
+#define ER_SP_LILABEL_MISMATCH 1308
+#define ER_SP_LABEL_REDEFINE 1309
+#define ER_SP_LABEL_MISMATCH 1310
+#define ER_SP_UNINIT_VAR 1311
+#define ER_SP_BADSELECT 1312
+#define ER_SP_BADRETURN 1313
+#define ER_SP_BADSTATEMENT 1314
+#define ER_UPDATE_LOG_DEPRECATED_IGNORED 1315
+#define ER_UPDATE_LOG_DEPRECATED_TRANSLATED 1316
+#define ER_QUERY_INTERRUPTED 1317
+#define ER_SP_WRONG_NO_OF_ARGS 1318
+#define ER_SP_COND_MISMATCH 1319
+#define ER_SP_NORETURN 1320
+#define ER_SP_NORETURNEND 1321
+#define ER_SP_BAD_CURSOR_QUERY 1322
+#define ER_SP_BAD_CURSOR_SELECT 1323
+#define ER_SP_CURSOR_MISMATCH 1324
+#define ER_SP_CURSOR_ALREADY_OPEN 1325
+#define ER_SP_CURSOR_NOT_OPEN 1326
+#define ER_SP_UNDECLARED_VAR 1327
+#define ER_SP_WRONG_NO_OF_FETCH_ARGS 1328
+#define ER_SP_FETCH_NO_DATA 1329
+#define ER_SP_DUP_PARAM 1330
+#define ER_SP_DUP_VAR 1331
+#define ER_SP_DUP_COND 1332
+#define ER_SP_DUP_CURS 1333
+#define ER_SP_CANT_ALTER 1334
+#define ER_SP_SUBSELECT_NYI 1335
+#define ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG 1336
+#define ER_SP_VARCOND_AFTER_CURSHNDLR 1337
+#define ER_SP_CURSOR_AFTER_HANDLER 1338
+#define ER_SP_CASE_NOT_FOUND 1339
+#define ER_FPARSER_TOO_BIG_FILE 1340
+#define ER_FPARSER_BAD_HEADER 1341
+#define ER_FPARSER_EOF_IN_COMMENT 1342
+#define ER_FPARSER_ERROR_IN_PARAMETER 1343
+#define ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER 1344
+#define ER_VIEW_NO_EXPLAIN 1345
+#define ER_FRM_UNKNOWN_TYPE 1346
+#define ER_WRONG_OBJECT 1347
+#define ER_NONUPDATEABLE_COLUMN 1348
+#define ER_VIEW_SELECT_DERIVED 1349
+#define ER_VIEW_SELECT_CLAUSE 1350
+#define ER_VIEW_SELECT_VARIABLE 1351
+#define ER_VIEW_SELECT_TMPTABLE 1352
+#define ER_VIEW_WRONG_LIST 1353
+#define ER_WARN_VIEW_MERGE 1354
+#define ER_WARN_VIEW_WITHOUT_KEY 1355
+#define ER_VIEW_INVALID 1356
+#define ER_SP_NO_DROP_SP 1357
+#define ER_SP_GOTO_IN_HNDLR 1358
+#define ER_TRG_ALREADY_EXISTS 1359
+#define ER_TRG_DOES_NOT_EXIST 1360
+#define ER_TRG_ON_VIEW_OR_TEMP_TABLE 1361
+#define ER_TRG_CANT_CHANGE_ROW 1362
+#define ER_TRG_NO_SUCH_ROW_IN_TRG 1363
+#define ER_NO_DEFAULT_FOR_FIELD 1364
+#define ER_DIVISION_BY_ZERO 1365
+#define ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 1366
+#define ER_ILLEGAL_VALUE_FOR_TYPE 1367
+#define ER_VIEW_NONUPD_CHECK 1368
+#define ER_VIEW_CHECK_FAILED 1369
+#define ER_PROCACCESS_DENIED_ERROR 1370
+#define ER_RELAY_LOG_FAIL 1371
+#define ER_PASSWD_LENGTH 1372
+#define ER_UNKNOWN_TARGET_BINLOG 1373
+#define ER_IO_ERR_LOG_INDEX_READ 1374
+#define ER_BINLOG_PURGE_PROHIBITED 1375
+#define ER_FSEEK_FAIL 1376
+#define ER_BINLOG_PURGE_FATAL_ERR 1377
+#define ER_LOG_IN_USE 1378
+#define ER_LOG_PURGE_UNKNOWN_ERR 1379
+#define ER_RELAY_LOG_INIT 1380
+#define ER_NO_BINARY_LOGGING 1381
+#define ER_RESERVED_SYNTAX 1382
+#define ER_WSAS_FAILED 1383
+#define ER_DIFF_GROUPS_PROC 1384
+#define ER_NO_GROUP_FOR_PROC 1385
+#define ER_ORDER_WITH_PROC 1386
+#define ER_LOGGING_PROHIBIT_CHANGING_OF 1387
+#define ER_NO_FILE_MAPPING 1388
+#define ER_WRONG_MAGIC 1389
+#define ER_PS_MANY_PARAM 1390
+#define ER_KEY_PART_0 1391
+#define ER_VIEW_CHECKSUM 1392
+#define ER_VIEW_MULTIUPDATE 1393
+#define ER_VIEW_NO_INSERT_FIELD_LIST 1394
+#define ER_VIEW_DELETE_MERGE_VIEW 1395
+#define ER_CANNOT_USER 1396
+#define ER_XAER_NOTA 1397
+#define ER_XAER_INVAL 1398
+#define ER_XAER_RMFAIL 1399
+#define ER_XAER_OUTSIDE 1400
+#define ER_XAER_RMERR 1401
+#define ER_XA_RBROLLBACK 1402
+#define ER_NONEXISTING_PROC_GRANT 1403
+#define ER_PROC_AUTO_GRANT_FAIL 1404
+#define ER_PROC_AUTO_REVOKE_FAIL 1405
+#define ER_DATA_TOO_LONG 1406
+#define ER_SP_BAD_SQLSTATE 1407
+#define ER_STARTUP 1408
+#define ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR 1409
+#define ER_CANT_CREATE_USER_WITH_GRANT 1410
+#define ER_WRONG_VALUE_FOR_TYPE 1411
+#define ER_TABLE_DEF_CHANGED 1412
+#define ER_SP_DUP_HANDLER 1413
+#define ER_SP_NOT_VAR_ARG 1414
+#define ER_SP_NO_RETSET 1415
+#define ER_CANT_CREATE_GEOMETRY_OBJECT 1416
+#define ER_FAILED_ROUTINE_BREAK_BINLOG 1417
+#define ER_BINLOG_UNSAFE_ROUTINE 1418
+#define ER_BINLOG_CREATE_ROUTINE_NEED_SUPER 1419
+#define ER_EXEC_STMT_WITH_OPEN_CURSOR 1420
+#define ER_STMT_HAS_NO_OPEN_CURSOR 1421
+#define ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG 1422
+#define ER_NO_DEFAULT_FOR_VIEW_FIELD 1423
+#define ER_SP_NO_RECURSION 1424
+#define ER_TOO_BIG_SCALE 1425
+#define ER_TOO_BIG_PRECISION 1426
+#define ER_M_BIGGER_THAN_D 1427
+#define ER_WRONG_LOCK_OF_SYSTEM_TABLE 1428
+#define ER_CONNECT_TO_FOREIGN_DATA_SOURCE 1429
+#define ER_QUERY_ON_FOREIGN_DATA_SOURCE 1430
+#define ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST 1431
+#define ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE 1432
+#define ER_FOREIGN_DATA_STRING_INVALID 1433
+#define ER_CANT_CREATE_FEDERATED_TABLE 1434
+#define ER_TRG_IN_WRONG_SCHEMA 1435
+#define ER_STACK_OVERRUN_NEED_MORE 1436
+#define ER_TOO_LONG_BODY 1437
+#define ER_WARN_CANT_DROP_DEFAULT_KEYCACHE 1438
+#define ER_TOO_BIG_DISPLAYWIDTH 1439
+#define ER_XAER_DUPID 1440
+#define ER_DATETIME_FUNCTION_OVERFLOW 1441
+#define ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG 1442
+#define ER_VIEW_PREVENT_UPDATE 1443
+#define ER_PS_NO_RECURSION 1444
+#define ER_SP_CANT_SET_AUTOCOMMIT 1445
+#define ER_MALFORMED_DEFINER 1446
+#define ER_VIEW_FRM_NO_USER 1447
+#define ER_VIEW_OTHER_USER 1448
+#define ER_NO_SUCH_USER 1449
+#define ER_FORBID_SCHEMA_CHANGE 1450
+#define ER_ROW_IS_REFERENCED_2 1451
+#define ER_NO_REFERENCED_ROW_2 1452
+#define ER_SP_BAD_VAR_SHADOW 1453
+#define ER_TRG_NO_DEFINER 1454
+#define ER_OLD_FILE_FORMAT 1455
+#define ER_SP_RECURSION_LIMIT 1456
+#define ER_SP_PROC_TABLE_CORRUPT 1457
+#define ER_SP_WRONG_NAME 1458
+#define ER_TABLE_NEEDS_UPGRADE 1459
+#define ER_SP_NO_AGGREGATE 1460
+#define ER_MAX_PREPARED_STMT_COUNT_REACHED 1461
+#define ER_VIEW_RECURSIVE 1462
+#define ER_NON_GROUPING_FIELD_USED 1463
+#define ER_TABLE_CANT_HANDLE_SPKEYS 1464
+#define ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA 1465
+#define ER_REMOVED_SPACES 1466
+#define ER_AUTOINC_READ_FAILED 1467
+#define ER_USERNAME 1468
+#define ER_HOSTNAME 1469
+#define ER_WRONG_STRING_LENGTH 1470
+#define ER_NON_INSERTABLE_TABLE 1471
+#define ER_ADMIN_WRONG_MRG_TABLE 1472
+#define ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT 1473
+#define ER_NAME_BECOMES_EMPTY 1474
+#define ER_AMBIGUOUS_FIELD_TERM 1475
+#define ER_FOREIGN_SERVER_EXISTS 1476
+#define ER_FOREIGN_SERVER_DOESNT_EXIST 1477
+#define ER_ILLEGAL_HA_CREATE_OPTION 1478
+#define ER_PARTITION_REQUIRES_VALUES_ERROR 1479
+#define ER_PARTITION_WRONG_VALUES_ERROR 1480
+#define ER_PARTITION_MAXVALUE_ERROR 1481
+#define ER_PARTITION_SUBPARTITION_ERROR 1482
+#define ER_PARTITION_SUBPART_MIX_ERROR 1483
+#define ER_PARTITION_WRONG_NO_PART_ERROR 1484
+#define ER_PARTITION_WRONG_NO_SUBPART_ERROR 1485
+#define ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR 1486
+#define ER_NOT_CONSTANT_EXPRESSION 1487
+#define ER_FIELD_NOT_FOUND_PART_ERROR 1488
+#define ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR 1489
+#define ER_INCONSISTENT_PARTITION_INFO_ERROR 1490
+#define ER_PARTITION_FUNC_NOT_ALLOWED_ERROR 1491
+#define ER_PARTITIONS_MUST_BE_DEFINED_ERROR 1492
+#define ER_RANGE_NOT_INCREASING_ERROR 1493
+#define ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR 1494
+#define ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR 1495
+#define ER_PARTITION_ENTRY_ERROR 1496
+#define ER_MIX_HANDLER_ERROR 1497
+#define ER_PARTITION_NOT_DEFINED_ERROR 1498
+#define ER_TOO_MANY_PARTITIONS_ERROR 1499
+#define ER_SUBPARTITION_ERROR 1500
+#define ER_CANT_CREATE_HANDLER_FILE 1501
+#define ER_BLOB_FIELD_IN_PART_FUNC_ERROR 1502
+#define ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF 1503
+#define ER_NO_PARTS_ERROR 1504
+#define ER_PARTITION_MGMT_ON_NONPARTITIONED 1505
+#define ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING 1506
+#define ER_PARTITION_DOES_NOT_EXIST 1507
+#define ER_DROP_LAST_PARTITION 1508
+#define ER_COALESCE_ONLY_ON_HASH_PARTITION 1509
+#define ER_REORG_HASH_ONLY_ON_SAME_NO 1510
+#define ER_REORG_NO_PARAM_ERROR 1511
+#define ER_ONLY_ON_RANGE_LIST_PARTITION 1512
+#define ER_ADD_PARTITION_SUBPART_ERROR 1513
+#define ER_ADD_PARTITION_NO_NEW_PARTITION 1514
+#define ER_COALESCE_PARTITION_NO_PARTITION 1515
+#define ER_REORG_PARTITION_NOT_EXIST 1516
+#define ER_SAME_NAME_PARTITION 1517
+#define ER_NO_BINLOG_ERROR 1518
+#define ER_CONSECUTIVE_REORG_PARTITIONS 1519
+#define ER_REORG_OUTSIDE_RANGE 1520
+#define ER_PARTITION_FUNCTION_FAILURE 1521
+#define ER_PART_STATE_ERROR 1522
+#define ER_LIMITED_PART_RANGE 1523
+#define ER_PLUGIN_IS_NOT_LOADED 1524
+#define ER_WRONG_VALUE 1525
+#define ER_NO_PARTITION_FOR_GIVEN_VALUE 1526
+#define ER_FILEGROUP_OPTION_ONLY_ONCE 1527
+#define ER_CREATE_FILEGROUP_FAILED 1528
+#define ER_DROP_FILEGROUP_FAILED 1529
+#define ER_TABLESPACE_AUTO_EXTEND_ERROR 1530
+#define ER_WRONG_SIZE_NUMBER 1531
+#define ER_SIZE_OVERFLOW_ERROR 1532
+#define ER_ALTER_FILEGROUP_FAILED 1533
+#define ER_BINLOG_ROW_LOGGING_FAILED 1534
+#define ER_BINLOG_ROW_WRONG_TABLE_DEF 1535
+#define ER_BINLOG_ROW_RBR_TO_SBR 1536
+#define ER_EVENT_ALREADY_EXISTS 1537
+#define ER_EVENT_STORE_FAILED 1538
+#define ER_EVENT_DOES_NOT_EXIST 1539
+#define ER_EVENT_CANT_ALTER 1540
+#define ER_EVENT_DROP_FAILED 1541
+#define ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG 1542
+#define ER_EVENT_ENDS_BEFORE_STARTS 1543
+#define ER_EVENT_EXEC_TIME_IN_THE_PAST 1544
+#define ER_EVENT_OPEN_TABLE_FAILED 1545
+#define ER_EVENT_NEITHER_M_EXPR_NOR_M_AT 1546
+#define ER_UNUSED_2 1547
+#define ER_UNUSED_3 1548
+#define ER_EVENT_CANNOT_DELETE 1549
+#define ER_EVENT_COMPILE_ERROR 1550
+#define ER_EVENT_SAME_NAME 1551
+#define ER_EVENT_DATA_TOO_LONG 1552
+#define ER_DROP_INDEX_FK 1553
+#define ER_WARN_DEPRECATED_SYNTAX_WITH_VER 1554
+#define ER_CANT_WRITE_LOCK_LOG_TABLE 1555
+#define ER_CANT_LOCK_LOG_TABLE 1556
+#define ER_UNUSED_4 1557
+#define ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE 1558
+#define ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR 1559
+#define ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT 1560
+#define ER_UNUSED_13 1561
+#define ER_PARTITION_NO_TEMPORARY 1562
+#define ER_PARTITION_CONST_DOMAIN_ERROR 1563
+#define ER_PARTITION_FUNCTION_IS_NOT_ALLOWED 1564
+#define ER_DDL_LOG_ERROR 1565
+#define ER_NULL_IN_VALUES_LESS_THAN 1566
+#define ER_WRONG_PARTITION_NAME 1567
+#define ER_CANT_CHANGE_TX_CHARACTERISTICS 1568
+#define ER_DUP_ENTRY_AUTOINCREMENT_CASE 1569
+#define ER_EVENT_MODIFY_QUEUE_ERROR 1570
+#define ER_EVENT_SET_VAR_ERROR 1571
+#define ER_PARTITION_MERGE_ERROR 1572
+#define ER_CANT_ACTIVATE_LOG 1573
+#define ER_RBR_NOT_AVAILABLE 1574
+#define ER_BASE64_DECODE_ERROR 1575
+#define ER_EVENT_RECURSION_FORBIDDEN 1576
+#define ER_EVENTS_DB_ERROR 1577
+#define ER_ONLY_INTEGERS_ALLOWED 1578
+#define ER_UNSUPORTED_LOG_ENGINE 1579
+#define ER_BAD_LOG_STATEMENT 1580
+#define ER_CANT_RENAME_LOG_TABLE 1581
+#define ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT 1582
+#define ER_WRONG_PARAMETERS_TO_NATIVE_FCT 1583
+#define ER_WRONG_PARAMETERS_TO_STORED_FCT 1584
+#define ER_NATIVE_FCT_NAME_COLLISION 1585
+#define ER_DUP_ENTRY_WITH_KEY_NAME 1586
+#define ER_BINLOG_PURGE_EMFILE 1587
+#define ER_EVENT_CANNOT_CREATE_IN_THE_PAST 1588
+#define ER_EVENT_CANNOT_ALTER_IN_THE_PAST 1589
+#define ER_SLAVE_INCIDENT 1590
+#define ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT 1591
+#define ER_BINLOG_UNSAFE_STATEMENT 1592
+#define ER_SLAVE_FATAL_ERROR 1593
+#define ER_SLAVE_RELAY_LOG_READ_FAILURE 1594
+#define ER_SLAVE_RELAY_LOG_WRITE_FAILURE 1595
+#define ER_SLAVE_CREATE_EVENT_FAILURE 1596
+#define ER_SLAVE_MASTER_COM_FAILURE 1597
+#define ER_BINLOG_LOGGING_IMPOSSIBLE 1598
+#define ER_VIEW_NO_CREATION_CTX 1599
+#define ER_VIEW_INVALID_CREATION_CTX 1600
+#define ER_SR_INVALID_CREATION_CTX 1601
+#define ER_TRG_CORRUPTED_FILE 1602
+#define ER_TRG_NO_CREATION_CTX 1603
+#define ER_TRG_INVALID_CREATION_CTX 1604
+#define ER_EVENT_INVALID_CREATION_CTX 1605
+#define ER_TRG_CANT_OPEN_TABLE 1606
+#define ER_CANT_CREATE_SROUTINE 1607
+#define ER_UNUSED_11 1608
+#define ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT 1609
+#define ER_SLAVE_CORRUPT_EVENT 1610
+#define ER_LOAD_DATA_INVALID_COLUMN 1611
+#define ER_LOG_PURGE_NO_FILE 1612
+#define ER_XA_RBTIMEOUT 1613
+#define ER_XA_RBDEADLOCK 1614
+#define ER_NEED_REPREPARE 1615
+#define ER_DELAYED_NOT_SUPPORTED 1616
+#define WARN_NO_MASTER_INFO 1617
+#define WARN_OPTION_IGNORED 1618
+#define ER_PLUGIN_DELETE_BUILTIN 1619
+#define WARN_PLUGIN_BUSY 1620
+#define ER_VARIABLE_IS_READONLY 1621
+#define ER_WARN_ENGINE_TRANSACTION_ROLLBACK 1622
+#define ER_SLAVE_HEARTBEAT_FAILURE 1623
+#define ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE 1624
+#define ER_UNUSED_14 1625
+#define ER_CONFLICT_FN_PARSE_ERROR 1626
+#define ER_EXCEPTIONS_WRITE_ERROR 1627
+#define ER_TOO_LONG_TABLE_COMMENT 1628
+#define ER_TOO_LONG_FIELD_COMMENT 1629
+#define ER_FUNC_INEXISTENT_NAME_COLLISION 1630
+#define ER_DATABASE_NAME 1631
+#define ER_TABLE_NAME 1632
+#define ER_PARTITION_NAME 1633
+#define ER_SUBPARTITION_NAME 1634
+#define ER_TEMPORARY_NAME 1635
+#define ER_RENAMED_NAME 1636
+#define ER_TOO_MANY_CONCURRENT_TRXS 1637
+#define WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED 1638
+#define ER_DEBUG_SYNC_TIMEOUT 1639
+#define ER_DEBUG_SYNC_HIT_LIMIT 1640
+#define ER_DUP_SIGNAL_SET 1641
+#define ER_SIGNAL_WARN 1642
+#define ER_SIGNAL_NOT_FOUND 1643
+#define ER_SIGNAL_EXCEPTION 1644
+#define ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER 1645
+#define ER_SIGNAL_BAD_CONDITION_TYPE 1646
+#define WARN_COND_ITEM_TRUNCATED 1647
+#define ER_COND_ITEM_TOO_LONG 1648
+#define ER_UNKNOWN_LOCALE 1649
+#define ER_SLAVE_IGNORE_SERVER_IDS 1650
+#define ER_QUERY_CACHE_DISABLED 1651
+#define ER_SAME_NAME_PARTITION_FIELD 1652
+#define ER_PARTITION_COLUMN_LIST_ERROR 1653
+#define ER_WRONG_TYPE_COLUMN_VALUE_ERROR 1654
+#define ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR 1655
+#define ER_MAXVALUE_IN_VALUES_IN 1656
+#define ER_TOO_MANY_VALUES_ERROR 1657
+#define ER_ROW_SINGLE_PARTITION_FIELD_ERROR 1658
+#define ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD 1659
+#define ER_PARTITION_FIELDS_TOO_LONG 1660
+#define ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE 1661
+#define ER_BINLOG_ROW_MODE_AND_STMT_ENGINE 1662
+#define ER_BINLOG_UNSAFE_AND_STMT_ENGINE 1663
+#define ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE 1664
+#define ER_BINLOG_STMT_MODE_AND_ROW_ENGINE 1665
+#define ER_BINLOG_ROW_INJECTION_AND_STMT_MODE 1666
+#define ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE 1667
+#define ER_BINLOG_UNSAFE_LIMIT 1668
+#define ER_BINLOG_UNSAFE_INSERT_DELAYED 1669
+#define ER_BINLOG_UNSAFE_SYSTEM_TABLE 1670
+#define ER_BINLOG_UNSAFE_AUTOINC_COLUMNS 1671
+#define ER_BINLOG_UNSAFE_UDF 1672
+#define ER_BINLOG_UNSAFE_SYSTEM_VARIABLE 1673
+#define ER_BINLOG_UNSAFE_SYSTEM_FUNCTION 1674
+#define ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS 1675
+#define ER_MESSAGE_AND_STATEMENT 1676
+#define ER_SLAVE_CONVERSION_FAILED 1677
+#define ER_SLAVE_CANT_CREATE_CONVERSION 1678
+#define ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT 1679
+#define ER_PATH_LENGTH 1680
+#define ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT 1681
+#define ER_WRONG_NATIVE_TABLE_STRUCTURE 1682
+#define ER_WRONG_PERFSCHEMA_USAGE 1683
+#define ER_WARN_I_S_SKIPPED_TABLE 1684
+#define ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT 1685
+#define ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT 1686
+#define ER_SPATIAL_MUST_HAVE_GEOM_COL 1687
+#define ER_TOO_LONG_INDEX_COMMENT 1688
+#define ER_LOCK_ABORTED 1689
+#define ER_DATA_OUT_OF_RANGE 1690
+#define ER_WRONG_SPVAR_TYPE_IN_LIMIT 1691
+#define ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE 1692
+#define ER_BINLOG_UNSAFE_MIXED_STATEMENT 1693
+#define ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN 1694
+#define ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN 1695
+#define ER_FAILED_READ_FROM_PAR_FILE 1696
+#define ER_VALUES_IS_NOT_INT_TYPE_ERROR 1697
+#define ER_ACCESS_DENIED_NO_PASSWORD_ERROR 1698
+#define ER_SET_PASSWORD_AUTH_PLUGIN 1699
+#define ER_GRANT_PLUGIN_USER_EXISTS 1700
+#define ER_TRUNCATE_ILLEGAL_FK 1701
+#define ER_PLUGIN_IS_PERMANENT 1702
+#define ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN 1703
+#define ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX 1704
+#define ER_STMT_CACHE_FULL 1705
+#define ER_MULTI_UPDATE_KEY_CONFLICT 1706
+#define ER_TABLE_NEEDS_REBUILD 1707
+#define WARN_OPTION_BELOW_LIMIT 1708
+#define ER_INDEX_COLUMN_TOO_LONG 1709
+#define ER_ERROR_IN_TRIGGER_BODY 1710
+#define ER_ERROR_IN_UNKNOWN_TRIGGER_BODY 1711
+#define ER_INDEX_CORRUPT 1712
+#define ER_UNDO_RECORD_TOO_BIG 1713
+#define ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT 1714
+#define ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE 1715
+#define ER_BINLOG_UNSAFE_REPLACE_SELECT 1716
+#define ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT 1717
+#define ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT 1718
+#define ER_BINLOG_UNSAFE_UPDATE_IGNORE 1719
+#define ER_UNUSED_15 1720
+#define ER_UNUSED_16 1721
+#define ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT 1722
+#define ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC 1723
+#define ER_BINLOG_UNSAFE_INSERT_TWO_KEYS 1724
+#define ER_UNUSED_28 1725
+#define ER_VERS_NOT_ALLOWED 1726
+#define ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST 1727
+#define ER_CANNOT_LOAD_FROM_TABLE_V2 1728
+#define ER_MASTER_DELAY_VALUE_OUT_OF_RANGE 1729
+#define ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT 1730
+#define ER_PARTITION_EXCHANGE_DIFFERENT_OPTION 1731
+#define ER_PARTITION_EXCHANGE_PART_TABLE 1732
+#define ER_PARTITION_EXCHANGE_TEMP_TABLE 1733
+#define ER_PARTITION_INSTEAD_OF_SUBPARTITION 1734
+#define ER_UNKNOWN_PARTITION 1735
+#define ER_TABLES_DIFFERENT_METADATA 1736
+#define ER_ROW_DOES_NOT_MATCH_PARTITION 1737
+#define ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX 1738
+#define ER_WARN_INDEX_NOT_APPLICABLE 1739
+#define ER_PARTITION_EXCHANGE_FOREIGN_KEY 1740
+#define ER_NO_SUCH_KEY_VALUE 1741
+#define ER_VALUE_TOO_LONG 1742
+#define ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE 1743
+#define ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE 1744
+#define ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX 1745
+#define ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT 1746
+#define ER_PARTITION_CLAUSE_ON_NONPARTITIONED 1747
+#define ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET 1748
+#define ER_UNUSED_5 1749
+#define ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE 1750
+#define ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE 1751
+#define ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE 1752
+#define ER_MTS_FEATURE_IS_NOT_SUPPORTED 1753
+#define ER_MTS_UPDATED_DBS_GREATER_MAX 1754
+#define ER_MTS_CANT_PARALLEL 1755
+#define ER_MTS_INCONSISTENT_DATA 1756
+#define ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING 1757
+#define ER_DA_INVALID_CONDITION_NUMBER 1758
+#define ER_INSECURE_PLAIN_TEXT 1759
+#define ER_INSECURE_CHANGE_MASTER 1760
+#define ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO 1761
+#define ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO 1762
+#define ER_SQLTHREAD_WITH_SECURE_SLAVE 1763
+#define ER_TABLE_HAS_NO_FT 1764
+#define ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER 1765
+#define ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION 1766
+#define ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST 1767
+#define ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION_WHEN_GTID_NEXT_LIST_IS_NULL 1768
+#define ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION 1769
+#define ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL 1770
+#define ER_SKIPPING_LOGGED_TRANSACTION 1771
+#define ER_MALFORMED_GTID_SET_SPECIFICATION 1772
+#define ER_MALFORMED_GTID_SET_ENCODING 1773
+#define ER_MALFORMED_GTID_SPECIFICATION 1774
+#define ER_GNO_EXHAUSTED 1775
+#define ER_BAD_SLAVE_AUTO_POSITION 1776
+#define ER_AUTO_POSITION_REQUIRES_GTID_MODE_ON 1777
+#define ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET 1778
+#define ER_GTID_MODE_2_OR_3_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON 1779
+#define ER_GTID_MODE_REQUIRES_BINLOG 1780
+#define ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF 1781
+#define ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON 1782
+#define ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF 1783
+#define ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF 1784
+#define ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE 1785
+#define ER_GTID_UNSAFE_CREATE_SELECT 1786
+#define ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION 1787
+#define ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME 1788
+#define ER_MASTER_HAS_PURGED_REQUIRED_GTIDS 1789
+#define ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID 1790
+#define ER_UNKNOWN_EXPLAIN_FORMAT 1791
+#define ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION 1792
+#define ER_TOO_LONG_TABLE_PARTITION_COMMENT 1793
+#define ER_SLAVE_CONFIGURATION 1794
+#define ER_INNODB_FT_LIMIT 1795
+#define ER_INNODB_NO_FT_TEMP_TABLE 1796
+#define ER_INNODB_FT_WRONG_DOCID_COLUMN 1797
+#define ER_INNODB_FT_WRONG_DOCID_INDEX 1798
+#define ER_INNODB_ONLINE_LOG_TOO_BIG 1799
+#define ER_UNKNOWN_ALTER_ALGORITHM 1800
+#define ER_UNKNOWN_ALTER_LOCK 1801
+#define ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS 1802
+#define ER_MTS_RECOVERY_FAILURE 1803
+#define ER_MTS_RESET_WORKERS 1804
+#define ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2 1805
+#define ER_SLAVE_SILENT_RETRY_TRANSACTION 1806
+#define ER_UNUSED_22 1807
+#define ER_TABLE_SCHEMA_MISMATCH 1808
+#define ER_TABLE_IN_SYSTEM_TABLESPACE 1809
+#define ER_IO_READ_ERROR 1810
+#define ER_IO_WRITE_ERROR 1811
+#define ER_TABLESPACE_MISSING 1812
+#define ER_TABLESPACE_EXISTS 1813
+#define ER_TABLESPACE_DISCARDED 1814
+#define ER_INTERNAL_ERROR 1815
+#define ER_INNODB_IMPORT_ERROR 1816
+#define ER_INNODB_INDEX_CORRUPT 1817
+#define ER_INVALID_YEAR_COLUMN_LENGTH 1818
+#define ER_NOT_VALID_PASSWORD 1819
+#define ER_MUST_CHANGE_PASSWORD 1820
+#define ER_FK_NO_INDEX_CHILD 1821
+#define ER_FK_NO_INDEX_PARENT 1822
+#define ER_FK_FAIL_ADD_SYSTEM 1823
+#define ER_FK_CANNOT_OPEN_PARENT 1824
+#define ER_FK_INCORRECT_OPTION 1825
+#define ER_DUP_CONSTRAINT_NAME 1826
+#define ER_PASSWORD_FORMAT 1827
+#define ER_FK_COLUMN_CANNOT_DROP 1828
+#define ER_FK_COLUMN_CANNOT_DROP_CHILD 1829
+#define ER_FK_COLUMN_NOT_NULL 1830
+#define ER_DUP_INDEX 1831
+#define ER_FK_COLUMN_CANNOT_CHANGE 1832
+#define ER_FK_COLUMN_CANNOT_CHANGE_CHILD 1833
+#define ER_FK_CANNOT_DELETE_PARENT 1834
+#define ER_MALFORMED_PACKET 1835
+#define ER_READ_ONLY_MODE 1836
+#define ER_GTID_NEXT_TYPE_UNDEFINED_GROUP 1837
+#define ER_VARIABLE_NOT_SETTABLE_IN_SP 1838
+#define ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF 1839
+#define ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY 1840
+#define ER_CANT_SET_GTID_PURGED_WHEN_OWNED_GTIDS_IS_NOT_EMPTY 1841
+#define ER_GTID_PURGED_WAS_CHANGED 1842
+#define ER_GTID_EXECUTED_WAS_CHANGED 1843
+#define ER_BINLOG_STMT_MODE_AND_NO_REPL_TABLES 1844
+#define ER_ALTER_OPERATION_NOT_SUPPORTED 1845
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON 1846
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY 1847
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION 1848
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME 1849
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE 1850
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK 1851
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_IGNORE 1852
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK 1853
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC 1854
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS 1855
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS 1856
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS 1857
+#define ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE 1858
+#define ER_DUP_UNKNOWN_IN_INDEX 1859
+#define ER_IDENT_CAUSES_TOO_LONG_PATH 1860
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL 1861
+#define ER_MUST_CHANGE_PASSWORD_LOGIN 1862
+#define ER_ROW_IN_WRONG_PARTITION 1863
+#define ER_MTS_EVENT_BIGGER_PENDING_JOBS_SIZE_MAX 1864
+#define ER_INNODB_NO_FT_USES_PARSER 1865
+#define ER_BINLOG_LOGICAL_CORRUPTION 1866
+#define ER_WARN_PURGE_LOG_IN_USE 1867
+#define ER_WARN_PURGE_LOG_IS_ACTIVE 1868
+#define ER_AUTO_INCREMENT_CONFLICT 1869
+#define WARN_ON_BLOCKHOLE_IN_RBR 1870
+#define ER_SLAVE_MI_INIT_REPOSITORY 1871
+#define ER_SLAVE_RLI_INIT_REPOSITORY 1872
+#define ER_ACCESS_DENIED_CHANGE_USER_ERROR 1873
+#define ER_INNODB_READ_ONLY 1874
+#define ER_STOP_SLAVE_SQL_THREAD_TIMEOUT 1875
+#define ER_STOP_SLAVE_IO_THREAD_TIMEOUT 1876
+#define ER_TABLE_CORRUPT 1877
+#define ER_TEMP_FILE_WRITE_FAILURE 1878
+#define ER_INNODB_FT_AUX_NOT_HEX_ID 1879
+#define ER_LAST_MYSQL_ERROR_MESSAGE 1880
+#define ER_ERROR_LAST_SECTION_1 1880
+
+/* New section */
+
+#define ER_ERROR_FIRST_SECTION_2 1900
+#define ER_UNUSED_18 1900
+#define ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED 1901
+#define ER_UNUSED_19 1902
+#define ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN 1903
+#define ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN 1904
+#define ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN 1905
+#define ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN 1906
+#define ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN 1907
+#define ER_UNUSED_20 1908
+#define ER_UNUSED_21 1909
+#define ER_UNSUPPORTED_ENGINE_FOR_GENERATED_COLUMNS 1910
+#define ER_UNKNOWN_OPTION 1911
+#define ER_BAD_OPTION_VALUE 1912
+#define ER_UNUSED_6 1913
+#define ER_UNUSED_7 1914
+#define ER_UNUSED_8 1915
+#define ER_DATA_OVERFLOW 1916
+#define ER_DATA_TRUNCATED 1917
+#define ER_BAD_DATA 1918
+#define ER_DYN_COL_WRONG_FORMAT 1919
+#define ER_DYN_COL_IMPLEMENTATION_LIMIT 1920
+#define ER_DYN_COL_DATA 1921
+#define ER_DYN_COL_WRONG_CHARSET 1922
+#define ER_ILLEGAL_SUBQUERY_OPTIMIZER_SWITCHES 1923
+#define ER_QUERY_CACHE_IS_DISABLED 1924
+#define ER_QUERY_CACHE_IS_GLOBALY_DISABLED 1925
+#define ER_VIEW_ORDERBY_IGNORED 1926
+#define ER_CONNECTION_KILLED 1927
+#define ER_UNUSED_12 1928
+#define ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SKIP_REPLICATION 1929
+#define ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION 1930
+#define ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT 1931
+#define ER_NO_SUCH_TABLE_IN_ENGINE 1932
+#define ER_TARGET_NOT_EXPLAINABLE 1933
+#define ER_CONNECTION_ALREADY_EXISTS 1934
+#define ER_MASTER_LOG_PREFIX 1935
+#define ER_CANT_START_STOP_SLAVE 1936
+#define ER_SLAVE_STARTED 1937
+#define ER_SLAVE_STOPPED 1938
+#define ER_SQL_DISCOVER_ERROR 1939
+#define ER_FAILED_GTID_STATE_INIT 1940
+#define ER_INCORRECT_GTID_STATE 1941
+#define ER_CANNOT_UPDATE_GTID_STATE 1942
+#define ER_DUPLICATE_GTID_DOMAIN 1943
+#define ER_GTID_OPEN_TABLE_FAILED 1944
+#define ER_GTID_POSITION_NOT_FOUND_IN_BINLOG 1945
+#define ER_CANNOT_LOAD_SLAVE_GTID_STATE 1946
+#define ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG 1947
+#define ER_MASTER_GTID_POS_MISSING_DOMAIN 1948
+#define ER_UNTIL_REQUIRES_USING_GTID 1949
+#define ER_GTID_STRICT_OUT_OF_ORDER 1950
+#define ER_GTID_START_FROM_BINLOG_HOLE 1951
+#define ER_SLAVE_UNEXPECTED_MASTER_SWITCH 1952
+#define ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO 1953
+#define ER_STORED_FUNCTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO 1954
+#define ER_GTID_POSITION_NOT_FOUND_IN_BINLOG2 1955
+#define ER_BINLOG_MUST_BE_EMPTY 1956
+#define ER_NO_SUCH_QUERY 1957
+#define ER_BAD_BASE64_DATA 1958
+#define ER_INVALID_ROLE 1959
+#define ER_INVALID_CURRENT_USER 1960
+#define ER_CANNOT_GRANT_ROLE 1961
+#define ER_CANNOT_REVOKE_ROLE 1962
+#define ER_CHANGE_SLAVE_PARALLEL_THREADS_ACTIVE 1963
+#define ER_PRIOR_COMMIT_FAILED 1964
+#define ER_IT_IS_A_VIEW 1965
+#define ER_SLAVE_SKIP_NOT_IN_GTID 1966
+#define ER_TABLE_DEFINITION_TOO_BIG 1967
+#define ER_PLUGIN_INSTALLED 1968
+#define ER_STATEMENT_TIMEOUT 1969
+#define ER_SUBQUERIES_NOT_SUPPORTED 1970
+#define ER_SET_STATEMENT_NOT_SUPPORTED 1971
+#define ER_UNUSED_9 1972
+#define ER_USER_CREATE_EXISTS 1973
+#define ER_USER_DROP_EXISTS 1974
+#define ER_ROLE_CREATE_EXISTS 1975
+#define ER_ROLE_DROP_EXISTS 1976
+#define ER_CANNOT_CONVERT_CHARACTER 1977
+#define ER_INVALID_DEFAULT_VALUE_FOR_FIELD 1978
+#define ER_KILL_QUERY_DENIED_ERROR 1979
+#define ER_NO_EIS_FOR_FIELD 1980
+#define ER_WARN_AGGFUNC_DEPENDENCE 1981
+#define WARN_INNODB_PARTITION_OPTION_IGNORED 1982
+#define ER_ERROR_LAST_SECTION_2 1982
+
+/* New section */
+
+#define ER_ERROR_FIRST_SECTION_3 2000
+#define ER_ERROR_LAST_SECTION_3 2000
+
+/* New section */
+
+#define ER_ERROR_FIRST_SECTION_4 3000
+#define ER_FILE_CORRUPT 3000
+#define ER_ERROR_ON_MASTER 3001
+#define ER_INCONSISTENT_ERROR 3002
+#define ER_STORAGE_ENGINE_NOT_LOADED 3003
+#define ER_GET_STACKED_DA_WITHOUT_ACTIVE_HANDLER 3004
+#define ER_WARN_LEGACY_SYNTAX_CONVERTED 3005
+#define ER_BINLOG_UNSAFE_FULLTEXT_PLUGIN 3006
+#define ER_CANNOT_DISCARD_TEMPORARY_TABLE 3007
+#define ER_FK_DEPTH_EXCEEDED 3008
+#define ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE_V2 3009
+#define ER_WARN_TRIGGER_DOESNT_HAVE_CREATED 3010
+#define ER_REFERENCED_TRG_DOES_NOT_EXIST_MYSQL 3011
+#define ER_EXPLAIN_NOT_SUPPORTED 3012
+#define ER_INVALID_FIELD_SIZE 3013
+#define ER_MISSING_HA_CREATE_OPTION 3014
+#define ER_ENGINE_OUT_OF_MEMORY 3015
+#define ER_PASSWORD_EXPIRE_ANONYMOUS_USER 3016
+#define ER_SLAVE_SQL_THREAD_MUST_STOP 3017
+#define ER_NO_FT_MATERIALIZED_SUBQUERY 3018
+#define ER_INNODB_UNDO_LOG_FULL 3019
+#define ER_INVALID_ARGUMENT_FOR_LOGARITHM 3020
+#define ER_SLAVE_CHANNEL_IO_THREAD_MUST_STOP 3021
+#define ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO 3022
+#define ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS 3023
+#define ER_QUERY_TIMEOUT 3024
+#define ER_NON_RO_SELECT_DISABLE_TIMER 3025
+#define ER_DUP_LIST_ENTRY 3026
+#define ER_SQL_MODE_NO_EFFECT 3027
+#define ER_AGGREGATE_ORDER_FOR_UNION 3028
+#define ER_AGGREGATE_ORDER_NON_AGG_QUERY 3029
+#define ER_SLAVE_WORKER_STOPPED_PREVIOUS_THD_ERROR 3030
+#define ER_DONT_SUPPORT_SLAVE_PRESERVE_COMMIT_ORDER 3031
+#define ER_SERVER_OFFLINE_MODE 3032
+#define ER_GIS_DIFFERENT_SRIDS 3033
+#define ER_GIS_UNSUPPORTED_ARGUMENT 3034
+#define ER_GIS_UNKNOWN_ERROR 3035
+#define ER_GIS_UNKNOWN_EXCEPTION 3036
+#define ER_GIS_INVALID_DATA 3037
+#define ER_BOOST_GEOMETRY_EMPTY_INPUT_EXCEPTION 3038
+#define ER_BOOST_GEOMETRY_CENTROID_EXCEPTION 3039
+#define ER_BOOST_GEOMETRY_OVERLAY_INVALID_INPUT_EXCEPTION 3040
+#define ER_BOOST_GEOMETRY_TURN_INFO_EXCEPTION 3041
+#define ER_BOOST_GEOMETRY_SELF_INTERSECTION_POINT_EXCEPTION 3042
+#define ER_BOOST_GEOMETRY_UNKNOWN_EXCEPTION 3043
+#define ER_STD_BAD_ALLOC_ERROR 3044
+#define ER_STD_DOMAIN_ERROR 3045
+#define ER_STD_LENGTH_ERROR 3046
+#define ER_STD_INVALID_ARGUMENT 3047
+#define ER_STD_OUT_OF_RANGE_ERROR 3048
+#define ER_STD_OVERFLOW_ERROR 3049
+#define ER_STD_RANGE_ERROR 3050
+#define ER_STD_UNDERFLOW_ERROR 3051
+#define ER_STD_LOGIC_ERROR 3052
+#define ER_STD_RUNTIME_ERROR 3053
+#define ER_STD_UNKNOWN_EXCEPTION 3054
+#define ER_GIS_DATA_WRONG_ENDIANESS 3055
+#define ER_CHANGE_MASTER_PASSWORD_LENGTH 3056
+#define ER_USER_LOCK_WRONG_NAME 3057
+#define ER_USER_LOCK_DEADLOCK 3058
+#define ER_REPLACE_INACCESSIBLE_ROWS 3059
+#define ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS 3060
+#define ER_ERROR_LAST_SECTION_4 3060
+
+/* New section */
+
+#define ER_ERROR_FIRST_SECTION_5 4000
+#define ER_UNUSED_26 4000
+#define ER_UNUSED_27 4001
+#define ER_WITH_COL_WRONG_LIST 4002
+#define ER_TOO_MANY_DEFINITIONS_IN_WITH_CLAUSE 4003
+#define ER_DUP_QUERY_NAME 4004
+#define ER_RECURSIVE_WITHOUT_ANCHORS 4005
+#define ER_UNACCEPTABLE_MUTUAL_RECURSION 4006
+#define ER_REF_TO_RECURSIVE_WITH_TABLE_IN_DERIVED 4007
+#define ER_NOT_STANDARD_COMPLIANT_RECURSIVE 4008
+#define ER_WRONG_WINDOW_SPEC_NAME 4009
+#define ER_DUP_WINDOW_NAME 4010
+#define ER_PARTITION_LIST_IN_REFERENCING_WINDOW_SPEC 4011
+#define ER_ORDER_LIST_IN_REFERENCING_WINDOW_SPEC 4012
+#define ER_WINDOW_FRAME_IN_REFERENCED_WINDOW_SPEC 4013
+#define ER_BAD_COMBINATION_OF_WINDOW_FRAME_BOUND_SPECS 4014
+#define ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION 4015
+#define ER_WINDOW_FUNCTION_IN_WINDOW_SPEC 4016
+#define ER_NOT_ALLOWED_WINDOW_FRAME 4017
+#define ER_NO_ORDER_LIST_IN_WINDOW_SPEC 4018
+#define ER_RANGE_FRAME_NEEDS_SIMPLE_ORDERBY 4019
+#define ER_WRONG_TYPE_FOR_ROWS_FRAME 4020
+#define ER_WRONG_TYPE_FOR_RANGE_FRAME 4021
+#define ER_FRAME_EXCLUSION_NOT_SUPPORTED 4022
+#define ER_WINDOW_FUNCTION_DONT_HAVE_FRAME 4023
+#define ER_INVALID_NTILE_ARGUMENT 4024
+#define ER_CONSTRAINT_FAILED 4025
+#define ER_EXPRESSION_IS_TOO_BIG 4026
+#define ER_ERROR_EVALUATING_EXPRESSION 4027
+#define ER_CALCULATING_DEFAULT_VALUE 4028
+#define ER_EXPRESSION_REFERS_TO_UNINIT_FIELD 4029
+#define ER_PARTITION_DEFAULT_ERROR 4030
+#define ER_REFERENCED_TRG_DOES_NOT_EXIST 4031
+#define ER_INVALID_DEFAULT_PARAM 4032
+#define ER_BINLOG_NON_SUPPORTED_BULK 4033
+#define ER_BINLOG_UNCOMPRESS_ERROR 4034
+#define ER_JSON_BAD_CHR 4035
+#define ER_JSON_NOT_JSON_CHR 4036
+#define ER_JSON_EOS 4037
+#define ER_JSON_SYNTAX 4038
+#define ER_JSON_ESCAPING 4039
+#define ER_JSON_DEPTH 4040
+#define ER_JSON_PATH_EOS 4041
+#define ER_JSON_PATH_SYNTAX 4042
+#define ER_JSON_PATH_DEPTH 4043
+#define ER_JSON_PATH_NO_WILDCARD 4044
+#define ER_JSON_PATH_ARRAY 4045
+#define ER_JSON_ONE_OR_ALL 4046
+#define ER_UNSUPPORTED_COMPRESSED_TABLE 4047
+#define ER_GEOJSON_INCORRECT 4048
+#define ER_GEOJSON_TOO_FEW_POINTS 4049
+#define ER_GEOJSON_NOT_CLOSED 4050
+#define ER_JSON_PATH_EMPTY 4051
+#define ER_SLAVE_SAME_ID 4052
+#define ER_FLASHBACK_NOT_SUPPORTED 4053
+#define ER_KEYS_OUT_OF_ORDER 4054
+#define ER_OVERLAPPING_KEYS 4055
+#define ER_REQUIRE_ROW_BINLOG_FORMAT 4056
+#define ER_ISOLATION_MODE_NOT_SUPPORTED 4057
+#define ER_ON_DUPLICATE_DISABLED 4058
+#define ER_UPDATES_WITH_CONSISTENT_SNAPSHOT 4059
+#define ER_ROLLBACK_ONLY 4060
+#define ER_ROLLBACK_TO_SAVEPOINT 4061
+#define ER_ISOLATION_LEVEL_WITH_CONSISTENT_SNAPSHOT 4062
+#define ER_UNSUPPORTED_COLLATION 4063
+#define ER_METADATA_INCONSISTENCY 4064
+#define ER_CF_DIFFERENT 4065
+#define ER_RDB_TTL_DURATION_FORMAT 4066
+#define ER_RDB_STATUS_GENERAL 4067
+#define ER_RDB_STATUS_MSG 4068
+#define ER_RDB_TTL_UNSUPPORTED 4069
+#define ER_RDB_TTL_COL_FORMAT 4070
+#define ER_PER_INDEX_CF_DEPRECATED 4071
+#define ER_KEY_CREATE_DURING_ALTER 4072
+#define ER_SK_POPULATE_DURING_ALTER 4073
+#define ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG 4074
+#define ER_NET_OK_PACKET_TOO_LARGE 4075
+#define ER_GEOJSON_EMPTY_COORDINATES 4076
+#define ER_MYROCKS_CANT_NOPAD_COLLATION 4077
+#define ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION 4078
+#define ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION 4079
+#define ER_WRONG_PARAMCOUNT_TO_CURSOR 4080
+#define ER_UNKNOWN_STRUCTURED_VARIABLE 4081
+#define ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD 4082
+#define ER_END_IDENTIFIER_DOES_NOT_MATCH 4083
+#define ER_SEQUENCE_RUN_OUT 4084
+#define ER_SEQUENCE_INVALID_DATA 4085
+#define ER_SEQUENCE_INVALID_TABLE_STRUCTURE 4086
+#define ER_SEQUENCE_ACCESS_ERROR 4087
+#define ER_SEQUENCE_BINLOG_FORMAT 4088
+#define ER_NOT_SEQUENCE 4089
+#define ER_NOT_SEQUENCE2 4090
+#define ER_UNKNOWN_SEQUENCES 4091
+#define ER_UNKNOWN_VIEW 4092
+#define ER_WRONG_INSERT_INTO_SEQUENCE 4093
+#define ER_SP_STACK_TRACE 4094
+#define ER_PACKAGE_ROUTINE_IN_SPEC_NOT_DEFINED_IN_BODY 4095
+#define ER_PACKAGE_ROUTINE_FORWARD_DECLARATION_NOT_DEFINED 4096
+#define ER_COMPRESSED_COLUMN_USED_AS_KEY 4097
+#define ER_UNKNOWN_COMPRESSION_METHOD 4098
+#define ER_WRONG_NUMBER_OF_VALUES_IN_TVC 4099
+#define ER_FIELD_REFERENCE_IN_TVC 4100
+#define ER_WRONG_TYPE_FOR_PERCENTILE_FUNC 4101
+#define ER_ARGUMENT_NOT_CONSTANT 4102
+#define ER_ARGUMENT_OUT_OF_RANGE 4103
+#define ER_WRONG_TYPE_OF_ARGUMENT 4104
+#define ER_NOT_AGGREGATE_FUNCTION 4105
+#define ER_INVALID_AGGREGATE_FUNCTION 4106
+#define ER_INVALID_VALUE_TO_LIMIT 4107
+#define ER_INVISIBLE_NOT_NULL_WITHOUT_DEFAULT 4108
+#define ER_UPDATE_INFO_WITH_SYSTEM_VERSIONING 4109
+#define ER_VERS_FIELD_WRONG_TYPE 4110
+#define ER_VERS_ENGINE_UNSUPPORTED 4111
+#define ER_UNUSED_23 4112
+#define ER_PARTITION_WRONG_TYPE 4113
+#define WARN_VERS_PART_FULL 4114
+#define WARN_VERS_PARAMETERS 4115
+#define ER_VERS_DROP_PARTITION_INTERVAL 4116
+#define ER_UNUSED_25 4117
+#define WARN_VERS_PART_NON_HISTORICAL 4118
+#define ER_VERS_ALTER_NOT_ALLOWED 4119
+#define ER_VERS_ALTER_ENGINE_PROHIBITED 4120
+#define ER_VERS_RANGE_PROHIBITED 4121
+#define ER_CONFLICTING_FOR_SYSTEM_TIME 4122
+#define ER_VERS_TABLE_MUST_HAVE_COLUMNS 4123
+#define ER_VERS_NOT_VERSIONED 4124
+#define ER_MISSING 4125
+#define ER_VERS_PERIOD_COLUMNS 4126
+#define ER_PART_WRONG_VALUE 4127
+#define ER_VERS_WRONG_PARTS 4128
+#define ER_VERS_NO_TRX_ID 4129
+#define ER_VERS_ALTER_SYSTEM_FIELD 4130
+#define ER_DROP_VERSIONING_SYSTEM_TIME_PARTITION 4131
+#define ER_VERS_DB_NOT_SUPPORTED 4132
+#define ER_VERS_TRT_IS_DISABLED 4133
+#define ER_VERS_DUPLICATE_ROW_START_END 4134
+#define ER_VERS_ALREADY_VERSIONED 4135
+#define ER_UNUSED_24 4136
+#define ER_VERS_NOT_SUPPORTED 4137
+#define ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED 4138
+#define ER_INDEX_FILE_FULL 4139
+#define ER_UPDATED_COLUMN_ONLY_ONCE 4140
+#define ER_EMPTY_ROW_IN_TVC 4141
+#define ER_VERS_QUERY_IN_PARTITION 4142
+#define ER_KEY_DOESNT_SUPPORT 4143
+#define ER_ALTER_OPERATION_TABLE_OPTIONS_NEED_REBUILD 4144
+#define ER_BACKUP_LOCK_IS_ACTIVE 4145
+#define ER_BACKUP_NOT_RUNNING 4146
+#define ER_BACKUP_WRONG_STAGE 4147
+#define ER_BACKUP_STAGE_FAILED 4148
+#define ER_BACKUP_UNKNOWN_STAGE 4149
+#define ER_USER_IS_BLOCKED 4150
+#define ER_ACCOUNT_HAS_BEEN_LOCKED 4151
+#define ER_PERIOD_TEMPORARY_NOT_ALLOWED 4152
+#define ER_PERIOD_TYPES_MISMATCH 4153
+#define ER_MORE_THAN_ONE_PERIOD 4154
+#define ER_PERIOD_FIELD_WRONG_ATTRIBUTES 4155
+#define ER_PERIOD_NOT_FOUND 4156
+#define ER_PERIOD_COLUMNS_UPDATED 4157
+#define ER_PERIOD_CONSTRAINT_DROP 4158
+#define ER_TOO_LONG_KEYPART 4159
+#define ER_TOO_LONG_DATABASE_COMMENT 4160
+#define ER_UNKNOWN_DATA_TYPE 4161
+#define ER_UNKNOWN_OPERATOR 4162
+#define ER_WARN_HISTORY_ROW_START_TIME 4163
+#define ER_PART_STARTS_BEYOND_INTERVAL 4164
+#define ER_GALERA_REPLICATION_NOT_SUPPORTED 4165
+#define ER_LOAD_INFILE_CAPABILITY_DISABLED 4166
+#define ER_NO_SECURE_TRANSPORTS_CONFIGURED 4167
+#define ER_SLAVE_IGNORED_SHARED_TABLE 4168
+#define ER_NO_AUTOINCREMENT_WITH_UNIQUE 4169
+#define ER_KEY_CONTAINS_PERIOD_FIELDS 4170
+#define ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS 4171
+#define ER_NOT_ALLOWED_IN_THIS_CONTEXT 4172
+#define ER_DATA_WAS_COMMITED_UNDER_ROLLBACK 4173
+#define ER_PK_INDEX_CANT_BE_IGNORED 4174
+#define ER_BINLOG_UNSAFE_SKIP_LOCKED 4175
+#define ER_JSON_TABLE_ERROR_ON_FIELD 4176
+#define ER_JSON_TABLE_ALIAS_REQUIRED 4177
+#define ER_JSON_TABLE_SCALAR_EXPECTED 4178
+#define ER_JSON_TABLE_MULTIPLE_MATCHES 4179
+#define ER_WITH_TIES_NEEDS_ORDER 4180
+#define ER_REMOVED_ORPHAN_TRIGGER 4181
+#define ER_STORAGE_ENGINE_DISABLED 4182
+#define WARN_SFORMAT_ERROR 4183
+#define ER_PARTITION_CONVERT_SUBPARTITIONED 4184
+#define ER_PROVIDER_NOT_LOADED 4185
+#define ER_JSON_HISTOGRAM_PARSE_FAILED 4186
+#define ER_SF_OUT_INOUT_ARG_NOT_ALLOWED 4187
+#define ER_INCONSISTENT_SLAVE_TEMP_TABLE 4188
+#define ER_ERROR_LAST 4188
+#endif /* ER_ERROR_FIRST */
diff --git a/libmariadb/libmariadb/CMakeLists.txt b/libmariadb/libmariadb/CMakeLists.txt
new file mode 100644
index 00000000..43ed67b4
--- /dev/null
+++ b/libmariadb/libmariadb/CMakeLists.txt
@@ -0,0 +1,526 @@
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
+ ${CC_SOURCE_DIR}/libmariadb)
+
+ADD_DEFINITIONS(-D HAVE_COMPRESS)
+ADD_DEFINITIONS(-D LIBMARIADB)
+ADD_DEFINITIONS(-D THREAD)
+
+IF(APPLE)
+ ADD_DEFINITIONS(-D _XOPEN_SOURCE)
+ENDIF()
+
+INCLUDE(${CC_SOURCE_DIR}/cmake/sign.cmake)
+
+SET(MARIADB_LIB_SYMBOLS
+ mariadb_cancel
+ mariadb_connection
+ mariadb_convert_string
+ ma_pvio_register_callback
+ mariadb_get_charset_by_name
+ mariadb_stmt_execute_direct
+ mariadb_get_charset_by_nr
+ mariadb_get_info
+ mariadb_get_infov
+ mysql_get_timeout_value
+ mysql_get_timeout_value_ms
+ mysql_optionsv
+ mysql_ps_fetch_functions
+ mariadb_reconnect
+ mysql_stmt_warning_count
+ mariadb_stmt_fetch_fields
+ mariadb_rpl_open
+ mariadb_rpl_close
+ mariadb_rpl_fetch
+ mariadb_rpl_optionsv
+ mariadb_rpl_get_optionsv
+ mariadb_rpl_init_ex
+ mariadb_free_rpl_event
+ mariadb_field_attr
+)
+
+SET(MARIADB_LIB_3_3_5_SYMBOLS
+ mariadb_rpl_extract_rows
+ mariadb_rpl_error
+ mariadb_rpl_errno)
+IF(WITH_SSL)
+ SET(MARIADB_LIB_SYMBOLS ${MARIADB_LIB_SYMBOLS} mariadb_deinitialize_ssl)
+ENDIF()
+
+SET(MYSQL_LIB_SYMBOLS
+ mysql_affected_rows
+ mysql_autocommit
+ mysql_change_user
+ mysql_character_set_name
+ mysql_client_find_plugin
+ mysql_client_register_plugin
+ mysql_close
+ mysql_commit
+ mysql_data_seek
+ mysql_debug
+ mysql_dump_debug_info
+ mysql_embedded
+ mysql_eof
+ mysql_errno
+ mysql_error
+ mysql_escape_string
+ mysql_fetch_field
+ mysql_fetch_field_direct
+ mysql_fetch_fields
+ mysql_fetch_lengths
+ mysql_fetch_row
+ mysql_field_count
+ mysql_field_seek
+ mysql_field_tell
+ mysql_free_result
+ mysql_get_character_set_info
+ mysql_get_charset_by_name
+ mysql_get_charset_by_nr
+ mysql_get_client_info
+ mysql_get_client_version
+ mysql_get_host_info
+ mysql_get_option
+ mysql_get_optionv
+ mysql_get_parameters
+ mysql_get_proto_info
+ mysql_get_server_info
+ mysql_get_server_name
+ mysql_get_server_version
+ mysql_get_socket
+ mysql_get_ssl_cipher
+ mysql_hex_string
+ mysql_info
+ mysql_init
+ mysql_insert_id
+ mysql_kill
+ mysql_list_dbs
+ mysql_list_fields
+ mysql_list_processes
+ mysql_list_tables
+ mysql_load_plugin
+ mysql_load_plugin_v
+ mysql_more_results
+ mysql_net_field_length
+ mysql_net_read_packet
+ mysql_next_result
+ mysql_num_fields
+ mysql_num_rows
+ mysql_options
+ mysql_options4
+ mysql_ping
+ mysql_query
+ mysql_read_query_result
+ mysql_real_connect
+ mysql_real_escape_string
+ mysql_real_query
+ mysql_refresh
+ mysql_reset_connection
+ mysql_rollback
+ mysql_row_seek
+ mysql_row_tell
+ mysql_select_db
+ mysql_send_query
+ mysql_server_end
+ mysql_server_init
+ mysql_session_track_get_next
+ mysql_session_track_get_first
+ mysql_set_character_set
+ mysql_set_local_infile_default
+ mysql_set_local_infile_handler
+ mysql_set_server_option
+ mysql_shutdown
+ mysql_sqlstate
+ mysql_ssl_set
+ mysql_stat
+ mysql_stmt_affected_rows
+ mysql_stmt_attr_get
+ mysql_stmt_attr_set
+ mysql_stmt_bind_param
+ mysql_stmt_bind_result
+ mysql_stmt_close
+ mysql_stmt_data_seek
+ mysql_stmt_errno
+ mysql_stmt_error
+ mysql_stmt_execute
+ mysql_stmt_fetch
+ mysql_stmt_fetch_column
+ mysql_stmt_field_count
+ mysql_stmt_free_result
+ mysql_stmt_init
+ mysql_stmt_insert_id
+ mysql_stmt_more_results
+ mysql_stmt_next_result
+ mysql_stmt_num_rows
+ mysql_stmt_param_count
+ mysql_stmt_param_metadata
+ mysql_stmt_prepare
+ mysql_stmt_reset
+ mysql_stmt_result_metadata
+ mysql_stmt_row_seek
+ mysql_stmt_row_tell
+ mysql_stmt_send_long_data
+ mysql_stmt_sqlstate
+ mysql_stmt_store_result
+ mysql_store_result
+ mysql_thread_end
+ mysql_thread_id
+ mysql_thread_init
+ mysql_thread_safe
+ mysql_use_result
+ mysql_warning_count)
+
+# some gcc versions fail to compile asm parts of my_context.c,
+# if build type is "Release" (see CONC-133), so we need to add -g flag
+IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_BUILD_TYPE MATCHES "Release")
+ SET_SOURCE_FILES_PROPERTIES(my_context.c PROPERTIES COMPILE_FLAGS -g)
+ENDIF()
+
+IF(ZLIB_FOUND AND WITH_EXTERNAL_ZLIB)
+ INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
+ELSE()
+ SET(ZLIB_SOURCES
+ ${CC_SOURCE_DIR}/external/zlib/adler32.c
+ ${CC_SOURCE_DIR}/external/zlib/compress.c
+ ${CC_SOURCE_DIR}/external/zlib/crc32.c
+ ${CC_SOURCE_DIR}/external/zlib/deflate.c
+ ${CC_SOURCE_DIR}/external/zlib/gzclose.c
+ ${CC_SOURCE_DIR}/external/zlib/gzlib.c
+ ${CC_SOURCE_DIR}/external/zlib/gzread.c
+ ${CC_SOURCE_DIR}/external/zlib/gzwrite.c
+ ${CC_SOURCE_DIR}/external/zlib/infback.c
+ ${CC_SOURCE_DIR}/external/zlib/inffast.c
+ ${CC_SOURCE_DIR}/external/zlib/inflate.c
+ ${CC_SOURCE_DIR}/external/zlib/inftrees.c
+ ${CC_SOURCE_DIR}/external/zlib/trees.c
+ ${CC_SOURCE_DIR}/external/zlib/uncompr.c
+ ${CC_SOURCE_DIR}/external/zlib/zutil.c
+ )
+ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/external/zlib ${CC_BINARY_DIR}/external/zlib)
+ENDIF()
+
+
+SET(MARIADB_DYNCOL_SYMBOLS
+ mariadb_dyncol_check
+ mariadb_dyncol_column_cmp_named
+ mariadb_dyncol_column_count
+ mariadb_dyncol_create_many_named
+ mariadb_dyncol_create_many_num
+ mariadb_dyncol_exists_named
+ mariadb_dyncol_exists_num
+ mariadb_dyncol_free
+ mariadb_dyncol_get_named
+ mariadb_dyncol_get_num
+ mariadb_dyncol_has_names
+ mariadb_dyncol_json
+ mariadb_dyncol_list_named
+ mariadb_dyncol_list_num
+ mariadb_dyncol_unpack
+ mariadb_dyncol_update_many_named
+ mariadb_dyncol_update_many_num
+ mariadb_dyncol_val_double
+ mariadb_dyncol_val_long
+ mariadb_dyncol_val_str)
+
+SET(MARIADB_NONBLOCK_SYMBOLS
+ mysql_autocommit_cont
+ mysql_autocommit_start
+ mysql_change_user_cont
+ mysql_change_user_start
+ mysql_close_cont
+ mysql_close_start
+ mysql_commit_cont
+ mysql_commit_start
+ mysql_dump_debug_info_cont
+ mysql_dump_debug_info_start
+ mysql_fetch_row_cont
+ mysql_fetch_row_start
+ mysql_free_result_cont
+ mysql_free_result_start
+ mysql_kill_cont
+ mysql_kill_start
+ mysql_list_fields_cont
+ mysql_list_fields_start
+ mysql_next_result_cont
+ mysql_next_result_start
+ mysql_ping_cont
+ mysql_ping_start
+ mysql_reset_connection_start
+ mysql_reset_connection_cont
+ mysql_query_cont
+ mysql_query_start
+ mysql_read_query_result_cont
+ mysql_read_query_result_start
+ mysql_real_connect_cont
+ mysql_real_connect_start
+ mysql_real_query_cont
+ mysql_real_query_start
+ mysql_refresh_cont
+ mysql_refresh_start
+ mysql_rollback_cont
+ mysql_rollback_start
+ mysql_select_db_cont
+ mysql_select_db_start
+ mysql_send_query_cont
+ mysql_send_query_start
+ mysql_set_character_set_cont
+ mysql_set_character_set_start
+ mysql_set_server_option_cont
+ mysql_set_server_option_start
+ mysql_shutdown_cont
+ mysql_shutdown_start
+ mysql_stat_cont
+ mysql_stat_start
+ mysql_stmt_close_cont
+ mysql_stmt_close_start
+ mysql_stmt_execute_cont
+ mysql_stmt_execute_start
+ mysql_stmt_fetch_cont
+ mysql_stmt_fetch_start
+ mysql_stmt_free_result_cont
+ mysql_stmt_free_result_start
+ mysql_stmt_next_result_cont
+ mysql_stmt_next_result_start
+ mysql_stmt_prepare_cont
+ mysql_stmt_prepare_start
+ mysql_stmt_reset_cont
+ mysql_stmt_reset_start
+ mysql_stmt_send_long_data_cont
+ mysql_stmt_send_long_data_start
+ mysql_stmt_store_result_cont
+ mysql_stmt_store_result_start
+ mysql_store_result_cont
+ mysql_store_result_start
+)
+
+# handle static plugins
+SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} ${LIBMARIADB_PLUGIN_SOURCES})
+SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBMARIADB_PLUGIN_LIBS} ${ZSTD_LIBRARY} ${ZLIB_LIBRARY})
+MESSAGE(STATUS "SYSTEM_LIBS: ${SYSTEM_LIBS}")
+INCLUDE_DIRECTORIES(${LIBMARIADB_PLUGIN_INCLUDES})
+ADD_DEFINITIONS(${LIBMARIADB_PLUGIN_DEFS})
+FOREACH(plugin ${PLUGINS_STATIC})
+ SET(EXTERNAL_PLUGINS "${EXTERNAL_PLUGINS} extern struct st_mysql_client_plugin ${plugin}_client_plugin;\n")
+ SET(BUILTIN_PLUGINS "${BUILTIN_PLUGINS} (struct st_mysql_client_plugin *)&${plugin}_client_plugin,\n")
+ENDFOREACH()
+CONFIGURE_FILE(${CC_SOURCE_DIR}/libmariadb/ma_client_plugin.c.in
+ ${CC_BINARY_DIR}/libmariadb/ma_client_plugin.c)
+
+SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES}
+${CC_SOURCE_DIR}/plugins/auth/my_auth.c
+ma_array.c
+ma_charset.c
+ma_decimal.c
+ma_hashtbl.c
+ma_net.c
+mariadb_charset.c
+ma_time.c
+ma_default.c
+ma_errmsg.c
+mariadb_lib.c
+ma_list.c
+ma_pvio.c
+ma_tls.c
+ma_alloc.c
+ma_compress.c
+ma_init.c
+ma_password.c
+ma_ll2str.c
+ma_sha1.c
+mariadb_stmt.c
+ma_loaddata.c
+ma_stmt_codec.c
+ma_string.c
+ma_dtoa.c
+mariadb_rpl.c
+${CC_BINARY_DIR}/libmariadb/ma_client_plugin.c
+ma_io.c
+${SSL_SOURCES}
+)
+
+IF(WIN32)
+ ADD_DEFINITIONS(-DSIZEOF_CHARP=${CMAKE_SIZEOF_VOID_P})
+ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/win-iconv)
+ SET(LIBMARIADB_SOURCES
+ ${LIBMARIADB_SOURCES}
+ ${CC_SOURCE_DIR}/win-iconv/win_iconv.c
+ win32_errmsg.c
+ win32_errmsg.h)
+ELSE()
+ IF(ICONV_INCLUDE_DIR)
+ INCLUDE_DIRECTORIES(BEFORE ${ICONV_INCLUDE_DIR})
+ ENDIF()
+ IF(NOT CMAKE_SYSTEM_NAME MATCHES AIX)
+ ADD_DEFINITIONS(-DLIBICONV_PLUG)
+ ENDIF()
+ IF(APPLE)
+ ADD_DEFINITIONS(-Wno-deprecated-declarations)
+ ENDIF()
+ENDIF()
+
+IF(ZLIB_FOUND AND WITH_EXTERNAL_ZLIB)
+ INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
+ELSE()
+ SET(ZLIB_SOURCES
+ ${CC_SOURCE_DIR}/external/zlib/adler32.c
+ ${CC_SOURCE_DIR}/external/zlib/compress.c
+ ${CC_SOURCE_DIR}/external/zlib/crc32.c
+ ${CC_SOURCE_DIR}/external/zlib/deflate.c
+ ${CC_SOURCE_DIR}/external/zlib/gzclose.c
+ ${CC_SOURCE_DIR}/external/zlib/gzlib.c
+ ${CC_SOURCE_DIR}/external/zlib/gzread.c
+ ${CC_SOURCE_DIR}/external/zlib/gzwrite.c
+ ${CC_SOURCE_DIR}/external/zlib/infback.c
+ ${CC_SOURCE_DIR}/external/zlib/inffast.c
+ ${CC_SOURCE_DIR}/external/zlib/inflate.c
+ ${CC_SOURCE_DIR}/external/zlib/inftrees.c
+ ${CC_SOURCE_DIR}/external/zlib/trees.c
+ ${CC_SOURCE_DIR}/external/zlib/uncompr.c
+ ${CC_SOURCE_DIR}/external/zlib/zutil.c
+ )
+ IF(MSVC)
+ SET_SOURCE_FILES_PROPERTIES(${ZLIB_SOURCES} PROPERTIES COMPILE_FLAGS -W0)
+ ENDIF()
+ SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} ${ZLIB_SOURCES})
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/external/zlib)
+ENDIF()
+
+IF(WITH_DYNCOL)
+ MESSAGE1(WITH_DYNCOL "Dynamic column API support: ON")
+ SET(MARIADB_LIB_SYMBOLS ${MARIADB_LIB_SYMBOLS} ${MARIADB_DYNCOL_SYMBOLS})
+ SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} mariadb_dyncol.c)
+ENDIF()
+
+SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} mariadb_async.c ma_context.c)
+SET(MARIADB_LIB_SYMBOLS ${MARIADB_LIB_SYMBOLS} ${MARIADB_NONBLOCK_SYMBOLS})
+
+INCLUDE(${CC_SOURCE_DIR}/cmake/export.cmake)
+IF(NOT WIN32)
+ CREATE_EXPORT_FILE(WRITE mariadbclient.def
+ "libmysqlclient_18"
+ "${MYSQL_LIB_SYMBOLS}"
+ "libmariadbclient_18")
+ CREATE_EXPORT_FILE(APPEND mariadbclient.def
+ "libmariadb_3"
+ "${MARIADB_LIB_SYMBOLS}"
+ "")
+ CREATE_EXPORT_FILE(APPEND mariadbclient.def
+ "libmariadb_3_3_5"
+ "${MARIADB_LIB_3_3_5_SYMBOLS}"
+ "")
+ELSE()
+ CREATE_EXPORT_FILE(WRITE mariadbclient.def
+ "libmariadb_3"
+ "${MARIADB_LIB_SYMBOLS};${MYSQL_LIB_SYMBOLS};${MARIADB_LIB_3_3_5_SYMBOLS}"
+ "")
+ENDIF()
+
+
+IF(CMAKE_VERSION VERSION_GREATER 2.8.7)
+ # CREATE OBJECT LIBRARY
+ ADD_LIBRARY(mariadb_obj OBJECT ${LIBMARIADB_SOURCES})
+ IF(UNIX)
+ SET_TARGET_PROPERTIES(mariadb_obj PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
+ ENDIF()
+ SET (MARIADB_OBJECTS $<TARGET_OBJECTS:mariadb_obj>)
+ELSE()
+ SET (MARIADB_OBJECTS ${LIBMARIADB_SOURCES})
+ENDIF()
+
+# Xcode doesn't support targets that have only object files,
+# so let's add an empty file to keep Xcode happy
+IF(CMAKE_GENERATOR MATCHES Xcode)
+ FILE(WRITE ${CC_BINARY_DIR}/libmariadb/empty.c "")
+ SET(EMPTY_FILE ${CC_BINARY_DIR}/libmariadb/empty.c)
+ENDIF()
+
+#* create file with list of functions */
+FILE(WRITE ${CC_BINARY_DIR}/manpages.list "${MARIADB_LIB_SYMBOLS};${MYSQL_LIB_SYMBOLS}")
+
+IF(WIN32)
+ SET_VERSION_INFO("TARGET:libmariadb"
+ "FILE_TYPE:VFT_DLL"
+ "SOURCE_FILE:libmariadb/libmariadb.c"
+ "ORIGINAL_FILE_NAME:libmariadb.dll"
+ "FILE_DESCRIPTION:Dynamic lib for client/server communication")
+ENDIF()
+
+ADD_LIBRARY(mariadbclient STATIC ${MARIADB_OBJECTS} ${EMPTY_FILE})
+TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS} ${CRYPTO_LIBS})
+
+IF(UNIX)
+ ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} ${MARIADB_OBJECTS} ${EMPTY_FILE})
+ SET_TARGET_PROPERTIES(libmariadb PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
+ELSE()
+ ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} ${MARIADB_OBJECTS} mariadbclient.def)
+ SET_TARGET_PROPERTIES(libmariadb PROPERTIES LINKER_LANGUAGE C)
+ENDIF()
+
+TARGET_LINK_LIBRARIES(libmariadb LINK_PRIVATE ${SYSTEM_LIBS} ${CRYPTO_LIBS})
+
+SIGN_TARGET(libmariadb)
+
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux" OR
+ CMAKE_SYSTEM_NAME MATCHES "kFreeBSD" OR
+ CMAKE_SYSTEM_NAME MATCHES "GNU")
+ IF (NOT WITH_ASAN AND NOT WITH_TSAN AND NOT WITH_UBSAN AND NOT WITH_MSAN)
+ TARGET_LINK_LIBRARIES (libmariadb LINK_PRIVATE "-Wl,--no-undefined")
+ ENDIF()
+ SET_TARGET_PROPERTIES(libmariadb PROPERTIES LINK_FLAGS "${CC_BINARY_DIR}/libmariadb/mariadbclient.def")
+ENDIF()
+
+SET_TARGET_PROPERTIES(mariadbclient PROPERTIES IMPORTED_INTERFACE_LINK_LIBRARIES "${SYSTEM_LIBS}")
+SET_TARGET_PROPERTIES(libmariadb PROPERTIES IMPORTED_INTERFACE_LINK_LIBRARIES "${SYSTEM_LIBS}")
+
+SET_TARGET_PROPERTIES(libmariadb PROPERTIES PREFIX "")
+
+#
+# Installation
+#
+INCLUDE(${CC_SOURCE_DIR}/cmake/symlink.cmake)
+
+# There are still several projects which don't make use
+# of the config program. To make sure these programs can
+# use mariadb client library we provide libmysql symlinks
+
+IF(WITH_MYSQLCOMPAT)
+ create_symlink(libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX} libmariadb ${INSTALL_LIBDIR})
+ create_symlink(libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX} libmariadb ${INSTALL_LIBDIR})
+ IF(NOT CMAKE_SYSTEM_NAME MATCHES AIX)
+ create_symlink(libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX} mariadbclient ${INSTALL_LIBDIR})
+ create_symlink(libmysqlclient_r${CMAKE_STATIC_LIBRARY_SUFFIX} mariadbclient ${INSTALL_LIBDIR})
+ ENDIF()
+ENDIF()
+
+create_symlink(libmariadb${CMAKE_STATIC_LIBRARY_SUFFIX} mariadbclient ${INSTALL_LIBDIR})
+
+SET_TARGET_PROPERTIES(libmariadb PROPERTIES VERSION
+ ${CPACK_PACKAGE_VERSION_MAJOR}
+ SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
+
+IF(NOT WIN32)
+ SET_TARGET_PROPERTIES(mariadbclient PROPERTIES OUTPUT_NAME "${LIBMARIADB_STATIC_NAME}")
+ENDIF()
+
+INSTALL(TARGETS mariadbclient
+ COMPONENT Development
+ DESTINATION ${INSTALL_LIBDIR})
+IF(WIN32)
+INSTALL(TARGETS libmariadb
+ COMPONENT SharedLibraries
+ DESTINATION ${INSTALL_LIBDIR})
+ELSE()
+# in cmake 3.12+ we can use
+#INSTALL(TARGETS libmariadb LIBRARY DESTINATION ${INSTALL_LIBDIR}
+# COMPONENT SharedLibraries NAMELINK_COMPONENT Development)
+# but as long as we build on CentOS 7 with its cmake 2.8.12.2 we have to use
+INSTALL(TARGETS libmariadb LIBRARY DESTINATION ${INSTALL_LIBDIR}
+ COMPONENT SharedLibraries NAMELINK_SKIP)
+INSTALL(TARGETS libmariadb LIBRARY DESTINATION ${INSTALL_LIBDIR}
+ COMPONENT Development NAMELINK_ONLY)
+ENDIF()
+
+IF(MSVC)
+ # On Windows, install PDB
+ INSTALL(FILES $<TARGET_PDB_FILE:libmariadb> DESTINATION "${INSTALL_LIBDIR}"
+ CONFIGURATIONS Debug RelWithDebInfo
+ COMPONENT Development)
+ENDIF()
diff --git a/libmariadb/libmariadb/bmove_upp.c b/libmariadb/libmariadb/bmove_upp.c
new file mode 100644
index 00000000..599b38be
--- /dev/null
+++ b/libmariadb/libmariadb/bmove_upp.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* File : bmove.c
+ Author : Michael widenius
+ Updated: 1987-03-20
+ Defines: bmove_upp()
+
+ bmove_upp(dst, src, len) moves exactly "len" bytes from the source
+ "src-len" to the destination "dst-len" counting downwards.
+*/
+
+#include <ma_global.h>
+#include "ma_string.h"
+
+void ma_bmove_upp(register char *dst, register const char *src, register size_t len)
+{
+ while (len-- != 0) *--dst = *--src;
+}
diff --git a/libmariadb/libmariadb/get_password.c b/libmariadb/libmariadb/get_password.c
new file mode 100644
index 00000000..4a93a738
--- /dev/null
+++ b/libmariadb/libmariadb/get_password.c
@@ -0,0 +1,172 @@
+/************************************************************************************
+ Copyright (C) 2014 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+#include <ma_global.h>
+#include <ma_sys.h>
+#include "mysql.h"
+#include <ma_string.h>
+#include <mariadb_ctype.h>
+#include <stdio.h>
+#include <memory.h>
+
+#ifndef _WIN32
+#include <termios.h>
+#else
+#include <conio.h>
+#endif /* _WIN32 */
+
+/* {{{ static char *get_password() */
+/*
+ read password from device
+
+ SYNOPSIS
+ get_password
+ Hdl/file file handle
+ buffer input buffer
+ length buffer length
+
+ RETURN
+ buffer zero terminated input buffer
+*/
+#ifdef _WIN32
+static char *get_password(HANDLE Hdl, char *buffer, DWORD length)
+#else
+static char *get_password(FILE *file, char *buffer, int length)
+#endif
+{
+ char inChar;
+ int CharsProcessed= 1;
+#ifdef _WIN32
+ DWORD Offset= 0;
+#else
+ int Offset= 0;
+#endif
+ memset(buffer, 0, length);
+
+ do
+ {
+#ifdef _WIN32
+ if (!ReadConsole(Hdl, &inChar, 1, (DWORD *)&CharsProcessed, NULL) ||
+ !CharsProcessed)
+ break;
+#else
+ inChar= (char)fgetc(file);
+#endif
+
+ switch(inChar) {
+ case '\b': /* backslash */
+ if (Offset)
+ {
+ /* cursor is always at the end */
+ Offset--;
+ buffer[Offset]= 0;
+#ifdef _WIN32
+ _cputs("\b \b");
+#endif
+ }
+ break;
+ case '\n':
+ case '\r':
+ break;
+ default:
+ buffer[Offset]= inChar;
+ if (Offset < length - 2)
+ Offset++;
+#ifdef _WIN32
+ _cputs("*");
+#endif
+ break;
+ }
+ } while (CharsProcessed && inChar != '\n' && inChar != '\r');
+ return buffer;
+}
+/* }}} */
+
+/* {{{ static char* get_tty_password */
+/*
+ reads password from tty/console
+
+ SYNOPSIS
+ get_tty_password()
+ buffer input buffer
+ length length of input buffer
+
+ DESCRIPTION
+ reads a password from console (Windows) or tty without echoing
+ it's characters. Input buffer must be allocated by calling function.
+
+ RETURNS
+ buffer pointer to input buffer
+*/
+char* get_tty_password(char *prompt, char *buffer, int length)
+{
+#ifdef _WIN32
+ DWORD SaveState;
+ HANDLE Hdl;
+
+ if (prompt)
+ fprintf(stderr, "%s", prompt);
+
+ if (!(Hdl= CreateFile("CONIN$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING, 0, NULL)))
+ {
+ /* todo: provide a graphical dialog */
+ return buffer;
+ }
+ /* Save ConsoleMode and set ENABLE_PROCESSED_INPUT:
+ CTRL+C is processed by the system and is not placed in the input buffer */
+ GetConsoleMode(Hdl, &SaveState);
+ SetConsoleMode(Hdl, ENABLE_PROCESSED_INPUT);
+
+ buffer= get_password(Hdl, buffer, length);
+ SetConsoleMode(Hdl, SaveState);
+ CloseHandle(Hdl);
+ return buffer;
+#else
+ struct termios term_old,
+ term_new;
+ FILE *readfrom;
+
+ if (prompt && isatty(fileno(stderr)))
+ fputs(prompt, stderr);
+
+ if (!(readfrom= fopen("/dev/tty", "r")))
+ readfrom= stdin;
+
+ /* try to disable echo */
+ tcgetattr(fileno(readfrom), &term_old);
+ term_new= term_old;
+ term_new.c_cc[VMIN] = 1;
+ term_new.c_cc[VTIME]= 0;
+ term_new.c_lflag&= ~(ECHO | ISIG | ICANON | ECHONL);
+ tcsetattr(fileno(readfrom), TCSADRAIN, &term_new);
+
+ buffer= get_password(readfrom, buffer, length);
+
+ if (isatty(fileno(readfrom)))
+ tcsetattr(fileno(readfrom), TCSADRAIN, &term_old);
+
+ fclose(readfrom);
+
+ return buffer;
+#endif
+}
+/* }}} */
diff --git a/libmariadb/libmariadb/ma_alloc.c b/libmariadb/libmariadb/ma_alloc.c
new file mode 100644
index 00000000..d6db279e
--- /dev/null
+++ b/libmariadb/libmariadb/ma_alloc.c
@@ -0,0 +1,196 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Routines to handle mallocing of results which will be freed the same time */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_string.h>
+
+#define INIT_BLOCK_NUM 4
+void ma_init_alloc_root(MA_MEM_ROOT *mem_root, size_t block_size, size_t pre_alloc_size)
+{
+ mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
+ mem_root->min_malloc=32;
+ mem_root->block_size= (block_size-MALLOC_OVERHEAD-sizeof(MA_USED_MEM)+8);
+ mem_root->error_handler=0;
+ mem_root->block_num= INIT_BLOCK_NUM;
+ mem_root->first_block_usage= 0;
+#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
+ if (pre_alloc_size)
+ {
+ if ((mem_root->free = mem_root->pre_alloc=
+ (MA_USED_MEM*) malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(MA_USED_MEM)))))
+ {
+ mem_root->free->size=pre_alloc_size+ALIGN_SIZE(sizeof(MA_USED_MEM));
+ mem_root->free->left=pre_alloc_size;
+ mem_root->free->next=0;
+ }
+ }
+#endif
+}
+
+void * ma_alloc_root(MA_MEM_ROOT *mem_root, size_t Size)
+{
+#if defined(HAVE_purify) && defined(EXTRA_DEBUG)
+ reg1 MA_USED_MEM *next;
+ Size+=ALIGN_SIZE(sizeof(MA_USED_MEM));
+
+ if (!(next = (MA_USED_MEM*) malloc(Size)))
+ {
+ if (mem_root->error_handler)
+ (*mem_root->error_handler)();
+ return((void *) 0); /* purecov: inspected */
+ }
+ next->next=mem_root->used;
+ mem_root->used=next;
+ return (void *) (((char*) next)+ALIGN_SIZE(sizeof(MA_USED_MEM)));
+#else
+ size_t get_size;
+ void * point;
+ reg1 MA_USED_MEM *next= 0;
+ reg2 MA_USED_MEM **prev;
+
+ Size= ALIGN_SIZE(Size);
+
+ if ((*(prev= &mem_root->free)))
+ {
+ if ((*prev)->left < Size &&
+ mem_root->first_block_usage++ >= 16 &&
+ (*prev)->left < 4096)
+ {
+ next= *prev;
+ *prev= next->next;
+ next->next= mem_root->used;
+ mem_root->used= next;
+ mem_root->first_block_usage= 0;
+ }
+ for (next= *prev; next && next->left < Size; next= next->next)
+ prev= &next->next;
+ }
+
+ if (! next)
+ { /* Time to alloc new block */
+ get_size= MAX(Size+ALIGN_SIZE(sizeof(MA_USED_MEM)),
+ (mem_root->block_size & ~1) * (mem_root->block_num >> 2));
+
+ if (!(next = (MA_USED_MEM*) malloc(get_size)))
+ {
+ if (mem_root->error_handler)
+ (*mem_root->error_handler)();
+ return((void *) 0); /* purecov: inspected */
+ }
+ mem_root->block_num++;
+ next->next= *prev;
+ next->size= get_size;
+ next->left= get_size-ALIGN_SIZE(sizeof(MA_USED_MEM));
+ *prev=next;
+ }
+ point= (void *) ((char*) next+ (next->size-next->left));
+ if ((next->left-= Size) < mem_root->min_malloc)
+ { /* Full block */
+ *prev=next->next; /* Remove block from list */
+ next->next=mem_root->used;
+ mem_root->used=next;
+ mem_root->first_block_usage= 0;
+ }
+ return(point);
+#endif
+}
+
+ /* deallocate everything used by alloc_root */
+
+void ma_free_root(MA_MEM_ROOT *root, myf MyFlags)
+{
+ reg1 MA_USED_MEM *next,*old;
+
+ if (!root)
+ return; /* purecov: inspected */
+ if (!(MyFlags & MY_KEEP_PREALLOC))
+ root->pre_alloc=0;
+
+ for ( next=root->used; next ;)
+ {
+ old=next; next= next->next ;
+ if (old != root->pre_alloc)
+ free(old);
+ }
+ for (next= root->free ; next ; )
+ {
+ old=next; next= next->next ;
+ if (old != root->pre_alloc)
+ free(old);
+ }
+ root->used=root->free=0;
+ if (root->pre_alloc)
+ {
+ root->free=root->pre_alloc;
+ root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(MA_USED_MEM));
+ root->free->next=0;
+ }
+ root->block_num= INIT_BLOCK_NUM;
+ root->first_block_usage= 0;
+}
+
+
+char *ma_strdup_root(MA_MEM_ROOT *root,const char *str)
+{
+ size_t len= strlen(str)+1;
+ char *pos;
+ if ((pos=ma_alloc_root(root,len)))
+ memcpy(pos,str,len);
+ return pos;
+}
+
+
+char *ma_memdup_root(MA_MEM_ROOT *root, const char *str, size_t len)
+{
+ char *pos;
+ if ((pos= ma_alloc_root(root,len)))
+ memcpy(pos,str,len);
+ return pos;
+}
+
+void *ma_multi_malloc(myf myFlags, ...)
+{
+ va_list args;
+ char **ptr,*start,*res;
+ size_t tot_length,length;
+
+ va_start(args,myFlags);
+ tot_length=0;
+ while ((ptr=va_arg(args, char **)))
+ {
+ length=va_arg(args, size_t);
+ tot_length+=ALIGN_SIZE(length);
+ }
+ va_end(args);
+
+ if (!(start=(char *)malloc(tot_length)))
+ return 0;
+
+ va_start(args,myFlags);
+ res=start;
+ while ((ptr=va_arg(args, char **)))
+ {
+ *ptr=res;
+ length=va_arg(args,size_t);
+ res+=ALIGN_SIZE(length);
+ }
+ va_end(args);
+ return start;
+}
diff --git a/libmariadb/libmariadb/ma_array.c b/libmariadb/libmariadb/ma_array.c
new file mode 100644
index 00000000..d067aa4a
--- /dev/null
+++ b/libmariadb/libmariadb/ma_array.c
@@ -0,0 +1,172 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Handling of arrays that can grow dynamically. */
+
+#undef SAFEMALLOC /* Problems with threads */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include "ma_string.h"
+#include <memory.h>
+
+/*
+ Initiate array and alloc space for init_alloc elements. Array is usable
+ even if space allocation failed
+*/
+
+my_bool ma_init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
+ uint init_alloc, uint alloc_increment CALLER_INFO_PROTO)
+{
+ if (!alloc_increment)
+ {
+ alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16);
+ if (init_alloc > 8 && alloc_increment > init_alloc * 2)
+ alloc_increment=init_alloc*2;
+ }
+
+ if (!init_alloc)
+ init_alloc=alloc_increment;
+ array->elements=0;
+ array->max_element=init_alloc;
+ array->alloc_increment=alloc_increment;
+ array->size_of_element=element_size;
+ if (!(array->buffer=(char*) malloc(element_size*init_alloc)))
+ {
+ array->max_element=0;
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+
+my_bool ma_insert_dynamic(DYNAMIC_ARRAY *array, void *element)
+{
+ void *buffer;
+ if (array->elements == array->max_element)
+ { /* Call only when necessary */
+ if (!(buffer=ma_alloc_dynamic(array)))
+ return TRUE;
+ }
+ else
+ {
+ buffer=array->buffer+(array->elements * array->size_of_element);
+ array->elements++;
+ }
+ memcpy(buffer,element,(size_t) array->size_of_element);
+ return FALSE;
+}
+
+
+ /* Alloc room for one element */
+
+unsigned char *ma_alloc_dynamic(DYNAMIC_ARRAY *array)
+{
+ if (array->elements == array->max_element)
+ {
+ char *new_ptr;
+ if (!(new_ptr=(char*) realloc(array->buffer,(array->max_element+
+ array->alloc_increment)*
+ array->size_of_element)))
+ return 0;
+ array->buffer=new_ptr;
+ array->max_element+=array->alloc_increment;
+ }
+ return (unsigned char *)array->buffer+(array->elements++ * array->size_of_element);
+}
+
+
+ /* remove last element from array and return it */
+
+unsigned char *ma_pop_dynamic(DYNAMIC_ARRAY *array)
+{
+ if (array->elements)
+ return (unsigned char *)array->buffer+(--array->elements * array->size_of_element);
+ return 0;
+}
+
+
+my_bool ma_set_dynamic(DYNAMIC_ARRAY *array, void * element, uint idx)
+{
+ if (idx >= array->elements)
+ {
+ if (idx >= array->max_element)
+ {
+ uint size;
+ char *new_ptr;
+ size=(idx+array->alloc_increment)/array->alloc_increment;
+ size*= array->alloc_increment;
+ if (!(new_ptr=(char*) realloc(array->buffer,size*
+ array->size_of_element)))
+ return TRUE;
+ array->buffer=new_ptr;
+ array->max_element=size;
+ }
+ memset((array->buffer+array->elements*array->size_of_element), 0,
+ (idx - array->elements)*array->size_of_element);
+ array->elements=idx+1;
+ }
+ memcpy(array->buffer+(idx * array->size_of_element),element,
+ (size_t) array->size_of_element);
+ return FALSE;
+}
+
+
+void ma_get_dynamic(DYNAMIC_ARRAY *array, void * element, uint idx)
+{
+ if (idx >= array->elements)
+ {
+ memset(element, 0, array->size_of_element);
+ return;
+ }
+ memcpy(element,array->buffer+idx*array->size_of_element,
+ (size_t) array->size_of_element);
+}
+
+
+void ma_delete_dynamic(DYNAMIC_ARRAY *array)
+{
+ if (array->buffer)
+ {
+ free(array->buffer);
+ array->buffer=0;
+ array->elements=array->max_element=0;
+ }
+}
+
+
+void ma_delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx)
+{
+ char *ptr=array->buffer+array->size_of_element*idx;
+ array->elements--;
+ memmove(ptr,ptr+array->size_of_element,
+ (array->elements-idx)*array->size_of_element);
+}
+
+
+void ma_freeze_size(DYNAMIC_ARRAY *array)
+{
+ uint elements=max(array->elements,1);
+
+ if (array->buffer && array->max_element != elements)
+ {
+ array->buffer=(char*) realloc(array->buffer,
+ elements*array->size_of_element);
+ array->max_element=elements;
+ }
+}
diff --git a/libmariadb/libmariadb/ma_charset.c b/libmariadb/libmariadb/ma_charset.c
new file mode 100644
index 00000000..f6ed6f80
--- /dev/null
+++ b/libmariadb/libmariadb/ma_charset.c
@@ -0,0 +1,1603 @@
+/****************************************************************************
+ Copyright (C) 2012, 2022, MariaDB Corporation.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*****************************************************************************/
+
+/* The implementation for character set support was ported from PHP's mysqlnd
+ extension, written by Andrey Hristov, Georg Richter and Ulf Wendel
+
+ Original file header:
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef _WIN32
+#include <strings.h>
+#include <string.h>
+#else
+#include <string.h>
+#endif
+#include <ma_global.h>
+#include <mariadb_ctype.h>
+#include <ma_string.h>
+
+#ifdef HAVE_ICONV
+#ifdef _WIN32
+#include "../win-iconv/iconv.h"
+#else
+#include <iconv.h>
+#endif
+#endif
+
+
+#if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE)
+#include <locale.h>
+#include <langinfo.h>
+#endif
+
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* {{{ utf8 functions */
+static unsigned int check_mb_utf8mb3_sequence(const char *start, const char *end)
+{
+ uchar c;
+
+ if (start >= end) {
+ return 0;
+ }
+
+ c = (uchar) start[0];
+
+ if (c < 0x80) {
+ return 1; /* single byte character */
+ }
+ if (c < 0xC2) {
+ return 0; /* invalid mb character */
+ }
+ if (c < 0xE0) {
+ if (start + 2 > end) {
+ return 0; /* too small */
+ }
+ if (!(((uchar)start[1] ^ 0x80) < 0x40)) {
+ return 0;
+ }
+ return 2;
+ }
+ if (c < 0xF0) {
+ if (start + 3 > end) {
+ return 0; /* too small */
+ }
+ if (!(((uchar)start[1] ^ 0x80) < 0x40 && ((uchar)start[2] ^ 0x80) < 0x40 &&
+ (c >= 0xE1 || (uchar)start[1] >= 0xA0))) {
+ return 0; /* invalid utf8 character */
+ }
+ return 3;
+ }
+ return 0;
+}
+
+
+static unsigned int check_mb_utf8_sequence(const char *start, const char *end)
+{
+ uchar c;
+
+ if (start >= end) {
+ return 0;
+ }
+
+ c = (uchar) start[0];
+
+ if (c < 0x80) {
+ return 1; /* single byte character */
+ }
+ if (c < 0xC2) {
+ return 0; /* invalid mb character */
+ }
+ if (c < 0xE0) {
+ if (start + 2 > end) {
+ return 0; /* too small */
+ }
+ if (!(((uchar)start[1] ^ 0x80) < 0x40)) {
+ return 0;
+ }
+ return 2;
+ }
+ if (c < 0xF0) {
+ if (start + 3 > end) {
+ return 0; /* too small */
+ }
+ if (!(((uchar)start[1] ^ 0x80) < 0x40 && ((uchar)start[2] ^ 0x80) < 0x40 &&
+ (c >= 0xE1 || (uchar)start[1] >= 0xA0))) {
+ return 0; /* invalid utf8 character */
+ }
+ return 3;
+ }
+ if (c < 0xF5) {
+ if (start + 4 > end) { /* We need 4 characters */
+ return 0; /* too small */
+ }
+
+ /*
+ UTF-8 quick four-byte mask:
+ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ Encoding allows to encode U+00010000..U+001FFFFF
+
+ The maximum character defined in the Unicode standard is U+0010FFFF.
+ Higher characters U+00110000..U+001FFFFF are not used.
+
+ 11110000.10010000.10xxxxxx.10xxxxxx == F0.90.80.80 == U+00010000 (min)
+ 11110100.10001111.10111111.10111111 == F4.8F.BF.BF == U+0010FFFF (max)
+
+ Valid codes:
+ [F0][90..BF][80..BF][80..BF]
+ [F1][80..BF][80..BF][80..BF]
+ [F2][80..BF][80..BF][80..BF]
+ [F3][80..BF][80..BF][80..BF]
+ [F4][80..8F][80..BF][80..BF]
+ */
+
+ if (!(((uchar)start[1] ^ 0x80) < 0x40 &&
+ ((uchar)start[2] ^ 0x80) < 0x40 &&
+ ((uchar)start[3] ^ 0x80) < 0x40 &&
+ (c >= 0xf1 || (uchar)start[1] >= 0x90) &&
+ (c <= 0xf3 || (uchar)start[1] <= 0x8F)))
+ {
+ return 0; /* invalid utf8 character */
+ }
+ return 4;
+ }
+ return 0;
+}
+
+static unsigned int check_mb_utf8mb3_valid(const char *start, const char *end)
+{
+ unsigned int len = check_mb_utf8mb3_sequence(start, end);
+ return (len > 1)? len:0;
+}
+
+static unsigned int check_mb_utf8_valid(const char *start, const char *end)
+{
+ unsigned int len = check_mb_utf8_sequence(start, end);
+ return (len > 1)? len:0;
+}
+
+
+static unsigned int mysql_mbcharlen_utf8mb3(unsigned int utf8)
+{
+ if (utf8 < 0x80) {
+ return 1; /* single byte character */
+ }
+ if (utf8 < 0xC2) {
+ return 0; /* invalid multibyte header */
+ }
+ if (utf8 < 0xE0) {
+ return 2; /* double byte character */
+ }
+ if (utf8 < 0xF0) {
+ return 3; /* triple byte character */
+ }
+ return 0;
+}
+
+
+static unsigned int mysql_mbcharlen_utf8(unsigned int utf8)
+{
+ if (utf8 < 0x80) {
+ return 1; /* single byte character */
+ }
+ if (utf8 < 0xC2) {
+ return 0; /* invalid multibyte header */
+ }
+ if (utf8 < 0xE0) {
+ return 2; /* double byte character */
+ }
+ if (utf8 < 0xF0) {
+ return 3; /* triple byte character */
+ }
+ if (utf8 < 0xF8) {
+ return 4; /* four byte character */
+ }
+ return 0;
+}
+/* }}} */
+
+
+/* {{{ big5 functions */
+#define valid_big5head(c) (0xA1 <= (unsigned int)(c) && (unsigned int)(c) <= 0xF9)
+#define valid_big5tail(c) ((0x40 <= (unsigned int)(c) && (unsigned int)(c) <= 0x7E) || \
+ (0xA1 <= (unsigned int)(c) && (unsigned int)(c) <= 0xFE))
+
+#define isbig5code(c,d) (isbig5head(c) && isbig5tail(d))
+
+static unsigned int check_mb_big5(const char *start, const char *end)
+{
+ return (valid_big5head(*((const uchar*) start)) && (end - start) > 1 && valid_big5tail(*((const uchar*) start + 1)) ? 2 : 0);
+}
+
+
+static unsigned int mysql_mbcharlen_big5(unsigned int big5)
+{
+ return (valid_big5head(big5)) ? 2 : 1;
+}
+/* }}} */
+
+
+/* {{{ cp932 functions */
+#define valid_cp932head(c) ((0x81 <= (c) && (c) <= 0x9F) || (0xE0 <= (c) && c <= 0xFC))
+#define valid_cp932tail(c) ((0x40 <= (c) && (c) <= 0x7E) || (0x80 <= (c) && c <= 0xFC))
+
+
+static unsigned int check_mb_cp932(const char *start, const char *end)
+{
+ return (valid_cp932head((uchar)start[0]) && (end - start > 1) &&
+ valid_cp932tail((uchar)start[1])) ? 2 : 0;
+}
+
+
+static unsigned int mysql_mbcharlen_cp932(unsigned int cp932)
+{
+ return (valid_cp932head((uchar)cp932)) ? 2 : 1;
+}
+/* }}} */
+
+
+/* {{{ euckr functions */
+#define valid_euckr(c) ((0xA1 <= (uchar)(c) && (uchar)(c) <= 0xFE))
+
+static unsigned int check_mb_euckr(const char *start, const char *end)
+{
+ if (end - start <= 1) {
+ return 0; /* invalid length */
+ }
+ if (*(uchar *)start < 0x80) {
+ return 0; /* invalid euckr character */
+ }
+ if (valid_euckr(start[1])) {
+ return 2;
+ }
+ return 0;
+}
+
+
+static unsigned int mysql_mbcharlen_euckr(unsigned int kr)
+{
+ return (valid_euckr(kr)) ? 2 : 1;
+}
+/* }}} */
+
+
+/* {{{ eucjpms functions */
+#define valid_eucjpms(c) (((c) & 0xFF) >= 0xA1 && ((c) & 0xFF) <= 0xFE)
+#define valid_eucjpms_kata(c) (((c) & 0xFF) >= 0xA1 && ((c) & 0xFF) <= 0xDF)
+#define valid_eucjpms_ss2(c) (((c) & 0xFF) == 0x8E)
+#define valid_eucjpms_ss3(c) (((c) & 0xFF) == 0x8F)
+
+static unsigned int check_mb_eucjpms(const char *start, const char *end)
+{
+ if (*((uchar *)start) < 0x80) {
+ return 0; /* invalid eucjpms character */
+ }
+ if (valid_eucjpms(start[0]) && (end - start) > 1 && valid_eucjpms(start[1])) {
+ return 2;
+ }
+ if (valid_eucjpms_ss2(start[0]) && (end - start) > 1 && valid_eucjpms_kata(start[1])) {
+ return 2;
+ }
+ if (valid_eucjpms_ss3(start[0]) && (end - start) > 2 && valid_eucjpms(start[1]) &&
+ valid_eucjpms(start[2])) {
+ return 2;
+ }
+ return 0;
+}
+
+
+static unsigned int mysql_mbcharlen_eucjpms(unsigned int jpms)
+{
+ if (valid_eucjpms(jpms) || valid_eucjpms_ss2(jpms)) {
+ return 2;
+ }
+ if (valid_eucjpms_ss3(jpms)) {
+ return 3;
+ }
+ return 1;
+}
+/* }}} */
+
+
+/* {{{ gb2312 functions */
+#define valid_gb2312_head(c) (0xA1 <= (uchar)(c) && (uchar)(c) <= 0xF7)
+#define valid_gb2312_tail(c) (0xA1 <= (uchar)(c) && (uchar)(c) <= 0xFE)
+
+
+static unsigned int check_mb_gb2312(const char *start, const char *end)
+{
+ return (valid_gb2312_head((unsigned int)start[0]) && end - start > 1 &&
+ valid_gb2312_tail((unsigned int)start[1])) ? 2 : 0;
+}
+
+
+static unsigned int mysql_mbcharlen_gb2312(unsigned int gb)
+{
+ return (valid_gb2312_head(gb)) ? 2 : 1;
+}
+/* }}} */
+
+
+/* {{{ gbk functions */
+#define valid_gbk_head(c) (0x81<=(uchar)(c) && (uchar)(c)<=0xFE)
+#define valid_gbk_tail(c) ((0x40<=(uchar)(c) && (uchar)(c)<=0x7E) || (0x80<=(uchar)(c) && (uchar)(c)<=0xFE))
+
+static unsigned int check_mb_gbk(const char *start, const char *end)
+{
+ return (valid_gbk_head(start[0]) && (end) - (start) > 1 && valid_gbk_tail(start[1])) ? 2 : 0;
+}
+
+static unsigned int mysql_mbcharlen_gbk(unsigned int gbk)
+{
+ return (valid_gbk_head(gbk) ? 2 : 1);
+}
+/* }}} */
+
+
+/* {{{ sjis functions */
+#define valid_sjis_head(c) ((0x81 <= (c) && (c) <= 0x9F) || (0xE0 <= (c) && (c) <= 0xFC))
+#define valid_sjis_tail(c) ((0x40 <= (c) && (c) <= 0x7E) || (0x80 <= (c) && (c) <= 0xFC))
+
+
+static unsigned int check_mb_sjis(const char *start, const char *end)
+{
+ return (valid_sjis_head((uchar)start[0]) && (end - start) > 1 && valid_sjis_tail((uchar)start[1])) ? 2 : 0;
+}
+
+
+static unsigned int mysql_mbcharlen_sjis(unsigned int sjis)
+{
+ return (valid_sjis_head((uchar)sjis)) ? 2 : 1;
+}
+/* }}} */
+
+
+/* {{{ ucs2 functions */
+static unsigned int check_mb_ucs2(const char *start __attribute((unused)), const char *end __attribute((unused)))
+{
+ return 2; /* always 2 */
+}
+
+static unsigned int mysql_mbcharlen_ucs2(unsigned int ucs2 __attribute((unused)))
+{
+ return 2; /* always 2 */
+}
+/* }}} */
+
+
+/* {{{ ujis functions */
+#define valid_ujis(c) ((0xA1 <= ((c)&0xFF) && ((c)&0xFF) <= 0xFE))
+#define valid_ujis_kata(c) ((0xA1 <= ((c)&0xFF) && ((c)&0xFF) <= 0xDF))
+#define valid_ujis_ss2(c) (((c)&0xFF) == 0x8E)
+#define valid_ujis_ss3(c) (((c)&0xFF) == 0x8F)
+
+static unsigned int check_mb_ujis(const char *start, const char *end)
+{
+ if (*(uchar*)start < 0x80) {
+ return 0; /* invalid ujis character */
+ }
+ if (valid_ujis(*(start)) && valid_ujis(*((start)+1))) {
+ return 2;
+ }
+ if (valid_ujis_ss2(*(start)) && valid_ujis_kata(*((start)+1))) {
+ return 2;
+ }
+ if (valid_ujis_ss3(*(start)) && (end-start) > 2 && valid_ujis(*((start)+1)) && valid_ujis(*((start)+2))) {
+ return 3;
+ }
+ return 0;
+}
+
+
+static unsigned int mysql_mbcharlen_ujis(unsigned int ujis)
+{
+ return (valid_ujis(ujis)? 2: valid_ujis_ss2(ujis)? 2: valid_ujis_ss3(ujis)? 3: 1);
+}
+/* }}} */
+
+
+
+/* {{{ utf16 functions */
+#define UTF16_HIGH_HEAD(x) ((((uchar) (x)) & 0xFC) == 0xD8)
+#define UTF16_LOW_HEAD(x) ((((uchar) (x)) & 0xFC) == 0xDC)
+
+static unsigned int check_mb_utf16(const char *start, const char *end)
+{
+ if (start + 2 > end) {
+ return 0;
+ }
+
+ if (UTF16_HIGH_HEAD(*start)) {
+ return (start + 4 <= end) && UTF16_LOW_HEAD(start[2]) ? 4 : 0;
+ }
+
+ if (UTF16_LOW_HEAD(*start)) {
+ return 0;
+ }
+ return 2;
+}
+
+
+static uint mysql_mbcharlen_utf16(unsigned int utf16)
+{
+ return UTF16_HIGH_HEAD(utf16) ? 4 : 2;
+}
+/* }}} */
+
+
+/* {{{ utf32 functions */
+static uint
+check_mb_utf32(const char *start __attribute((unused)), const char *end __attribute((unused)))
+{
+ return 4;
+}
+
+
+static uint
+mysql_mbcharlen_utf32(unsigned int utf32 __attribute((unused)))
+{
+ return 4;
+}
+/* }}} */
+
+/* {{{ gb18030 functions */
+#define is_gb18030_odd(c) (0x81 <= (unsigned char) (c) && (unsigned char) (c) <= 0xFE)
+#define is_gb18030_even_2(c) ((0x40 <= (unsigned char) (c) && (unsigned char) (c) <= 0x7E) || (0x80 <= (unsigned char) (c) && (unsigned char) (c) <= 0xFE))
+#define is_gb18030_even_4(c) (0x30 <= (unsigned char) (c) && (unsigned char) (c) <= 0x39)
+
+
+static unsigned int mysql_mbcharlen_gb18030(unsigned int c)
+{
+ if (c <= 0xFF) {
+ return !is_gb18030_odd(c);
+ }
+ if (c > 0xFFFF || !is_gb18030_odd((c >> 8) & 0xFF)) {
+ return 0;
+ }
+ if (is_gb18030_even_2((c & 0xFF))) {
+ return 2;
+ }
+ if (is_gb18030_even_4((c & 0xFF))) {
+ return 4;
+ }
+
+ return 0;
+}
+
+static unsigned int check_mb_gb18030_valid(const char * start, const char * end)
+{
+ if (end - start <= 1 || !is_gb18030_odd(start[0])) {
+ return 0;
+ }
+
+ if (is_gb18030_even_2(start[1])) {
+ return 2;
+ } else if (end - start > 3 && is_gb18030_even_4(start[1]) && is_gb18030_odd(start[2]) && is_gb18030_even_4(start[3])) {
+ return 4;
+ }
+
+ return 0;
+}
+/* }}} */
+
+/*
+ The server compiles sometimes the full utf-8 (the mb4) as utf8mb4, and the old as utf8,
+ for BC reasons. Sometimes, utf8mb4 is just utf8 but the old charsets are utf8mb3.
+ Change easily now, with a macro, could be made compilation dependable.
+*/
+
+#define UTF8_MB4 "utf8mb4"
+#define UTF8_MB3 "utf8mb3"
+
+/* {{{ mysql_charsets */
+const MARIADB_CHARSET_INFO mariadb_compiled_charsets[] =
+{
+ { 1, 1, "big5","big5_chinese_ci", "", 950, "BIG5", 1, 2, mysql_mbcharlen_big5, check_mb_big5},
+ { 3, 1, "dec8", "dec8_swedish_ci", "", 0, "DEC", 1, 1, NULL, NULL},
+ { 4, 1, "cp850", "cp850_general_ci", "", 850, "CP850", 1, 1, NULL, NULL},
+ { 6, 1, "hp8", "hp8_english_ci", "", 0, "HP-ROMAN8", 1, 1, NULL, NULL},
+ { 7, 1, "koi8r", "koi8r_general_ci", "", 20866, "KOI8R", 1, 1, NULL, NULL},
+ { 8, 1, "latin1", "latin1_swedish_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
+ { 9, 1, "latin2", "latin2_general_ci", "", 852, "LATIN2", 1, 1, NULL, NULL},
+ { 10, 1, "swe7", "swe7_swedish_ci", "", 20107, "", 1, 1, NULL, NULL},
+ { 11, 1, "ascii", "ascii_general_ci", "", 1252, "ASCII", 1, 1, NULL, NULL},
+ { 12, 1, "ujis", "ujis_japanese_ci", "", 20932, "UJIS", 1, 3, mysql_mbcharlen_ujis, check_mb_ujis},
+ { 13, 1, "sjis", "sjis_japanese_ci", "", 932, "SJIS", 1, 2, mysql_mbcharlen_sjis, check_mb_sjis},
+ { 16, 1, "hebrew", "hebrew_general_ci", "", 1255, "HEBREW", 1, 1, NULL, NULL},
+ { 18, 1, "tis620", "tis620_thai_ci", "", 874, "TIS620", 1, 1, NULL, NULL},
+ { 19, 1, "euckr", "euckr_korean_ci", "", 51949, "EUCKR", 1, 2, mysql_mbcharlen_euckr, check_mb_euckr},
+ { 22, 1, "koi8u", "koi8u_general_ci", "", 21866, "KOI8U", 1, 1, NULL, NULL},
+ { 24, 1, "gb2312", "gb2312_chinese_ci", "", 936, "GB2312", 1, 2, mysql_mbcharlen_gb2312, check_mb_gb2312},
+ { 25, 1, "greek", "greek_general_ci", "", 28597, "GREEK", 1, 1, NULL, NULL},
+ { 26, 1, "cp1250", "cp1250_general_ci", "", 1250, "CP1250", 1, 1, NULL, NULL},
+ { 28, 1, "gbk", "gbk_chinese_ci", "", 936, "GBK", 1, 2, mysql_mbcharlen_gbk, check_mb_gbk},
+ { 30, 1, "latin5", "latin5_turkish_ci", "", 1254, "LATIN5", 1, 1, NULL, NULL},
+ { 32, 1, "armscii8", "armscii8_general_ci", "", 0, "ARMSCII-8", 1, 1, NULL, NULL},
+ { 33, 1, UTF8_MB3, UTF8_MB3"_general_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 35, 1, "ucs2", "ucs2_general_ci", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 36, 1, "cp866", "cp866_general_ci", "", 866, "CP866", 1, 1, NULL, NULL},
+ { 37, 1, "keybcs2", "keybcs2_general_ci", "", 0, "", 1, 1, NULL, NULL},
+ { 38, 1, "macce", "macce_general_ci", "", 10029, "CP1282", 1, 1, NULL, NULL},
+ { 39, 1, "macroman", "macroman_general_ci", "", 10000, "MACINTOSH", 1, 1, NULL, NULL},
+ { 40, 1, "cp852", "cp852_general_ci", "", 852, "CP852", 1, 1, NULL, NULL},
+ { 41, 1, "latin7", "latin7_general_ci", "", 28603, "LATIN7", 1, 1, NULL, NULL},
+ { 51, 1, "cp1251", "cp1251_general_ci", "", 1251, "CP1251", 1, 1, NULL, NULL},
+ { 57, 1, "cp1256", "cp1256_general_ci", "", 1256, "CP1256", 1, 1, NULL, NULL},
+ { 59, 1, "cp1257", "cp1257_general_ci", "", 1257, "CP1257", 1, 1, NULL, NULL},
+ { 63, 1, "binary", "binary", "", 0, "ASCII", 1, 1, NULL, NULL},
+ { 64, 1, "armscii8", "armscii8_bin", "", 0, "ARMSCII-8", 1, 1, NULL, NULL},
+ { 92, 1, "geostd8", "geostd8_general_ci", "", 0, "GEORGIAN-PS", 1, 1, NULL, NULL},
+ { 95, 1, "cp932", "cp932_japanese_ci", "", 932, "CP932", 1, 2, mysql_mbcharlen_cp932, check_mb_cp932},
+ { 97, 1, "eucjpms", "eucjpms_japanese_ci", "", 932, "EUC-JP-MS", 1, 3, mysql_mbcharlen_eucjpms, check_mb_eucjpms},
+ { 2, 1, "latin2", "latin2_czech_cs", "", 852, "LATIN2", 1, 1, NULL, NULL},
+ { 5, 1, "latin1", "latin1_german1_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
+ { 14, 1, "cp1251", "cp1251_bulgarian_ci", "", 1251, "CP1251", 1, 1, NULL, NULL},
+ { 15, 1, "latin1", "latin1_danish_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
+ { 17, 1, "filename", "filename", "", 0, "", 1, 5, NULL, NULL},
+ { 20, 1, "latin7", "latin7_estonian_cs", "", 28603, "LATIN7", 1, 1, NULL, NULL},
+ { 21, 1, "latin2", "latin2_hungarian_ci", "", 852, "LATIN2", 1, 1, NULL, NULL},
+ { 23, 1, "cp1251", "cp1251_ukrainian_ci", "", 1251, "CP1251", 1, 1, NULL, NULL},
+ { 27, 1, "latin2", "latin2_croatian_ci", "", 852, "LATIN2", 1, 1, NULL, NULL},
+ { 29, 1, "cp1257", "cp1257_lithuanian_ci", "", 1257, "CP1257", 1, 1, NULL, NULL},
+ { 31, 1, "latin1", "latin1_german2_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
+ { 34, 1, "cp1250", "cp1250_czech_cs", "", 1250, "CP1250", 1, 1, NULL, NULL},
+ { 42, 1, "latin7", "latin7_general_cs", "", 28603, "LATIN7", 1, 1, NULL, NULL},
+ { 43, 1, "macce", "macce_bin", "", 10029, "CP1282", 1, 1, NULL, NULL},
+ { 44, 1, "cp1250", "cp1250_croatian_ci", "", 1250, "CP1250", 1, 1, NULL, NULL},
+ { 45, 1, UTF8_MB4, UTF8_MB4"_general_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 46, 1, UTF8_MB4, UTF8_MB4"_bin", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 47, 1, "latin1", "latin1_bin", "", 1250, "LATIN1", 1, 1, NULL, NULL},
+ { 48, 1, "latin1", "latin1_general_ci", "", 1250, "LATIN1", 1, 1, NULL, NULL},
+ { 49, 1, "latin1", "latin1_general_cs", "", 1250, "LATIN1", 1, 1, NULL, NULL},
+ { 50, 1, "cp1251", "cp1251_bin", "", 1251, "CP1251", 1, 1, NULL, NULL},
+ { 52, 1, "cp1251", "cp1251_general_cs", "", 1251, "CP1251", 1, 1, NULL, NULL},
+ { 53, 1, "macroman", "macroman_bin", "", 10000, "MACINTOSH", 1, 1, NULL, NULL},
+ { 54, 1, "utf16", "utf16_general_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 55, 1, "utf16", "utf16_bin", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 56, 1, "utf16le", "utf16_general_ci", "", 1200, "UTF16LE", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 58, 1, "cp1257", "cp1257_bin", "", 1257, "CP1257", 1, 1, NULL, NULL},
+#ifdef USED_TO_BE_SO_BEFORE_MYSQL_5_5
+ { 60, 1, "armascii8", "armascii8_bin", "", 0, "ARMSCII-8", 1, 1, NULL, NULL},
+#endif
+ { 60, 1, "utf32", "utf32_general_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 61, 1, "utf32", "utf32_bin", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 62, 1, "utf16le", "utf16_bin", "", 1200, "UTF16LE", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 65, 1, "ascii", "ascii_bin", "", 1252, "ASCII", 1, 1, NULL, NULL},
+ { 66, 1, "cp1250", "cp1250_bin", "", 1250, "CP1250", 1, 1, NULL, NULL},
+ { 67, 1, "cp1256", "cp1256_bin", "", 1256, "CP1256", 1, 1, NULL, NULL},
+ { 68, 1, "cp866", "cp866_bin", "", 866, "CP866", 1, 1, NULL, NULL},
+ { 69, 1, "dec8", "dec8_bin", "", 0, "DEC", 1, 1, NULL, NULL},
+ { 70, 1, "greek", "greek_bin", "", 28597, "GREEK", 1, 1, NULL, NULL},
+ { 71, 1, "hebrew", "hebrew_bin", "", 1255, "hebrew", 1, 1, NULL, NULL},
+ { 72, 1, "hp8", "hp8_bin", "", 0, "HPROMAN-8", 1, 1, NULL, NULL},
+ { 73, 1, "keybcs2", "keybcs2_bin", "", 0, "", 1, 1, NULL, NULL},
+ { 74, 1, "koi8r", "koi8r_bin", "", 20866, "KOI8R", 1, 1, NULL, NULL},
+ { 75, 1, "koi8u", "koi8u_bin", "", 21866, "KOI8U", 1, 1, NULL, NULL},
+ { 76, 1, UTF8_MB3, UTF8_MB3"_tolower_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 77, 1, "latin2", "latin2_bin", "", 28592, "LATIN2", 1, 1, NULL, NULL},
+ { 78, 1, "latin5", "latin5_bin", "", 1254, "LATIN5", 1, 1, NULL, NULL},
+ { 79, 1, "latin7", "latin7_bin", "", 28603, "LATIN7", 1, 1, NULL, NULL},
+ { 80, 1, "cp850", "cp850_bin", "", 850, "CP850", 1, 1, NULL, NULL},
+ { 81, 1, "cp852", "cp852_bin", "", 852, "CP852", 1, 1, NULL, NULL},
+ { 82, 1, "swe7", "swe7_bin", "", 0, "", 1, 1, NULL, NULL},
+ { 93, 1, "geostd8", "geostd8_bin", "", 0, "GEORGIAN-PS", 1, 1, NULL, NULL},
+ { 83, 1, UTF8_MB3, UTF8_MB3"_bin", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 84, 1, "big5", "big5_bin", "", 65000, "BIG5", 1, 2, mysql_mbcharlen_big5, check_mb_big5},
+ { 85, 1, "euckr", "euckr_bin", "", 51949, "EUCKR", 1, 2, mysql_mbcharlen_euckr, check_mb_euckr},
+ { 86, 1, "gb2312", "gb2312_bin", "", 936, "GB2312", 1, 2, mysql_mbcharlen_gb2312, check_mb_gb2312},
+ { 87, 1, "gbk", "gbk_bin", "", 936, "GBK", 1, 2, mysql_mbcharlen_gbk, check_mb_gbk},
+ { 88, 1, "sjis", "sjis_bin", "", 932, "SJIS", 1, 2, mysql_mbcharlen_sjis, check_mb_sjis},
+ { 89, 1, "tis620", "tis620_bin", "", 874, "TIS620", 1, 1, NULL, NULL},
+ { 90, 1, "ucs2", "ucs2_bin", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 91, 1, "ujis", "ujis_bin", "", 20932, "UJIS", 1, 3, mysql_mbcharlen_ujis, check_mb_ujis},
+ { 94, 1, "latin1", "latin1_spanish_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
+ { 96, 1, "cp932", "cp932_bin", "", 932, "CP932", 1, 2, mysql_mbcharlen_cp932, check_mb_cp932},
+ { 99, 1, "cp1250", "cp1250_polish_ci", "", 1250, "CP1250", 1, 1, NULL, NULL},
+ { 98, 1, "eucjpms", "eucjpms_bin", "", 932, "EUCJP-MS", 1, 3, mysql_mbcharlen_eucjpms, check_mb_eucjpms},
+ { 101, 1, "utf16", "utf16_unicode_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 102, 1, "utf16", "utf16_icelandic_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 103, 1, "utf16", "utf16_latvian_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 104, 1, "utf16", "utf16_romanian_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 105, 1, "utf16", "utf16_slovenian_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 106, 1, "utf16", "utf16_polish_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 107, 1, "utf16", "utf16_estonian_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 108, 1, "utf16", "utf16_spanish_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 109, 1, "utf16", "utf16_swedish_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 110, 1, "utf16", "utf16_turkish_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 111, 1, "utf16", "utf16_czech_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 112, 1, "utf16", "utf16_danish_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 113, 1, "utf16", "utf16_lithunian_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 114, 1, "utf16", "utf16_slovak_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 115, 1, "utf16", "utf16_spanish2_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 116, 1, "utf16", "utf16_roman_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 117, 1, "utf16", "utf16_persian_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 118, 1, "utf16", "utf16_esperanto_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 120, 1, "utf16", "utf16_sinhala_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 121, 1, "utf16", "utf16_german2_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 122, 1, "utf16", "utf16_croatian_mysql561_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 123, 1, "utf16", "utf16_unicode_520_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 124, 1, "utf16", "utf16_vietnamese_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 128, 1, "ucs2", "ucs2_unicode_ci", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 129, 1, "ucs2", "ucs2_icelandic_ci", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 130, 1, "ucs2", "ucs2_latvian_ci", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 131, 1, "ucs2", "ucs2_romanian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 132, 1, "ucs2", "ucs2_slovenian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 133, 1, "ucs2", "ucs2_polish_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 134, 1, "ucs2", "ucs2_estonian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 135, 1, "ucs2", "ucs2_spanish_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 136, 1, "ucs2", "ucs2_swedish_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 137, 1, "ucs2", "ucs2_turkish_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 138, 1, "ucs2", "ucs2_czech_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 139, 1, "ucs2", "ucs2_danish_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 140, 1, "ucs2", "ucs2_lithuanian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 141, 1, "ucs2", "ucs2_slovak_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 142, 1, "ucs2", "ucs2_spanish2_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 143, 1, "ucs2", "ucs2_roman_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 144, 1, "ucs2", "ucs2_persian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 145, 1, "ucs2", "ucs2_esperanto_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 146, 1, "ucs2", "ucs2_hungarian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 147, 1, "ucs2", "ucs2_sinhala_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 148, 1, "ucs2", "ucs2_german2_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 149, 1, "ucs2", "ucs2_croatian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2}, /* MDB */
+ { 150, 1, "ucs2", "ucs2_unicode_520_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2}, /* MDB */
+ { 151, 1, "ucs2", "ucs2_vietnamese_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2}, /* MDB */
+ { 159, 1, "ucs2", "ucs2_general_mysql500_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2}, /* MDB */
+ { 160, 1, "utf32", "utf32_unicode_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 161, 1, "utf32", "utf32_icelandic_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 162, 1, "utf32", "utf32_latvian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 163, 1, "utf32", "utf32_romanian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 164, 1, "utf32", "utf32_slovenian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 165, 1, "utf32", "utf32_polish_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 166, 1, "utf32", "utf32_estonian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 167, 1, "utf32", "utf32_spanish_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 168, 1, "utf32", "utf32_swedish_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 169, 1, "utf32", "utf32_turkish_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 170, 1, "utf32", "utf32_czech_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 171, 1, "utf32", "utf32_danish_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 172, 1, "utf32", "utf32_lithuanian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 173, 1, "utf32", "utf32_slovak_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 174, 1, "utf32", "utf32_spanish_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 175, 1, "utf32", "utf32_roman_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 176, 1, "utf32", "utf32_persian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 177, 1, "utf32", "utf32_esperanto_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 178, 1, "utf32", "utf32_hungarian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 179, 1, "utf32", "utf32_sinhala_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 180, 1, "utf32", "utf32_german2_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 181, 1, "utf32", "utf32_croatian_mysql561_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 182, 1, "utf32", "utf32_unicode_520_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 183, 1, "utf32", "utf32_vietnamese_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+
+ { 192, 1, UTF8_MB3, UTF8_MB3"_general_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 193, 1, UTF8_MB3, UTF8_MB3"_icelandic_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 194, 1, UTF8_MB3, UTF8_MB3"_latvian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 195, 1, UTF8_MB3, UTF8_MB3"_romanian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 196, 1, UTF8_MB3, UTF8_MB3"_slovenian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 197, 1, UTF8_MB3, UTF8_MB3"_polish_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 198, 1, UTF8_MB3, UTF8_MB3"_estonian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 199, 1, UTF8_MB3, UTF8_MB3"_spanish_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 119, 1, UTF8_MB3, UTF8_MB3"_spanish_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 200, 1, UTF8_MB3, UTF8_MB3"_swedish_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 201, 1, UTF8_MB3, UTF8_MB3"_turkish_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 202, 1, UTF8_MB3, UTF8_MB3"_czech_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 203, 1, UTF8_MB3, UTF8_MB3"_danish_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
+ { 204, 1, UTF8_MB3, UTF8_MB3"_lithuanian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid },
+ { 205, 1, UTF8_MB3, UTF8_MB3"_slovak_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 206, 1, UTF8_MB3, UTF8_MB3"_spanish2_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 207, 1, UTF8_MB3, UTF8_MB3"_roman_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 208, 1, UTF8_MB3, UTF8_MB3"_persian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 209, 1, UTF8_MB3, UTF8_MB3"_esperanto_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 210, 1, UTF8_MB3, UTF8_MB3"_hungarian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 211, 1, UTF8_MB3, UTF8_MB3"_sinhala_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 212, 1, UTF8_MB3, UTF8_MB3"_german2_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 214, 1, UTF8_MB3, UTF8_MB3"_unicode_520_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 215, 1, UTF8_MB3, UTF8_MB3"_vietnamese_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ { 213, 1, UTF8_MB3, UTF8_MB3"_croatian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
+ { 223, 1, UTF8_MB3, UTF8_MB3"_general_mysql500_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
+
+ { 224, 1, UTF8_MB4, UTF8_MB4"_unicode_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 225, 1, UTF8_MB4, UTF8_MB4"_icelandic_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 226, 1, UTF8_MB4, UTF8_MB4"_latvian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 227, 1, UTF8_MB4, UTF8_MB4"_romanian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 228, 1, UTF8_MB4, UTF8_MB4"_slovenian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 229, 1, UTF8_MB4, UTF8_MB4"_polish_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 230, 1, UTF8_MB4, UTF8_MB4"_estonian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 231, 1, UTF8_MB4, UTF8_MB4"_spanish_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 232, 1, UTF8_MB4, UTF8_MB4"_swedish_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 233, 1, UTF8_MB4, UTF8_MB4"_turkish_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 234, 1, UTF8_MB4, UTF8_MB4"_czech_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 235, 1, UTF8_MB4, UTF8_MB4"_danish_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 236, 1, UTF8_MB4, UTF8_MB4"_lithuanian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 237, 1, UTF8_MB4, UTF8_MB4"_slovak_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 238, 1, UTF8_MB4, UTF8_MB4"_spanish2_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 239, 1, UTF8_MB4, UTF8_MB4"_roman_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 240, 1, UTF8_MB4, UTF8_MB4"_persian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 241, 1, UTF8_MB4, UTF8_MB4"_esperanto_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 242, 1, UTF8_MB4, UTF8_MB4"_hungarian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 243, 1, UTF8_MB4, UTF8_MB4"_sinhala_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 244, 1, UTF8_MB4, UTF8_MB4"_german2_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 245, 1, UTF8_MB4, UTF8_MB4"_croatian_mysql561_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 246, 1, UTF8_MB4, UTF8_MB4"_unicode_520_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 247, 1, UTF8_MB4, UTF8_MB4"_vietnamese_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 248, 1, "gb18030", "gb18030_chinese_ci", "", 54936, "GB18030", 1, 4, mysql_mbcharlen_gb18030, check_mb_gb18030_valid},
+ { 249, 1, "gb18030", "gb18030_bin", "", 54936, "GB18030", 1, 4, mysql_mbcharlen_gb18030, check_mb_gb18030_valid},
+ { 250, 1, "gb18030", "gb18030_unicode_520_ci", "", 54936, "GB18030", 1, 4, mysql_mbcharlen_gb18030, check_mb_gb18030_valid},
+
+
+ { 254, 1, UTF8_MB3, UTF8_MB3"_general_cs", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+
+ { 255, 1, UTF8_MB4, UTF8_MB4"_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 256, 1, UTF8_MB4, UTF8_MB4"_de_pb_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 257, 1, UTF8_MB4, UTF8_MB4"_is_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 258, 1, UTF8_MB4, UTF8_MB4"_lv_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 259, 1, UTF8_MB4, UTF8_MB4"_ro_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 260, 1, UTF8_MB4, UTF8_MB4"_sl_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 261, 1, UTF8_MB4, UTF8_MB4"_pl_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 262, 1, UTF8_MB4, UTF8_MB4"_et_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 263, 1, UTF8_MB4, UTF8_MB4"_es_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 264, 1, UTF8_MB4, UTF8_MB4"_sv_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 265, 1, UTF8_MB4, UTF8_MB4"_tr_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 266, 1, UTF8_MB4, UTF8_MB4"_cs_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 267, 1, UTF8_MB4, UTF8_MB4"_da_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 268, 1, UTF8_MB4, UTF8_MB4"_lt_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 269, 1, UTF8_MB4, UTF8_MB4"_sk_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 270, 1, UTF8_MB4, UTF8_MB4"_es_trad_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 271, 1, UTF8_MB4, UTF8_MB4"_la_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 273, 1, UTF8_MB4, UTF8_MB4"_eo_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 274, 1, UTF8_MB4, UTF8_MB4"_hu_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 275, 1, UTF8_MB4, UTF8_MB4"_hr_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 277, 1, UTF8_MB4, UTF8_MB4"_vi_0900_ai_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 278, 1, UTF8_MB4, UTF8_MB4"_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 279, 1, UTF8_MB4, UTF8_MB4"_de_pb__0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 280, 1, UTF8_MB4, UTF8_MB4"_is_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 281, 1, UTF8_MB4, UTF8_MB4"_lv_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 282, 1, UTF8_MB4, UTF8_MB4"_ro_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 283, 1, UTF8_MB4, UTF8_MB4"_sl_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 284, 1, UTF8_MB4, UTF8_MB4"_pl_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 285, 1, UTF8_MB4, UTF8_MB4"_et_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 286, 1, UTF8_MB4, UTF8_MB4"_es_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 287, 1, UTF8_MB4, UTF8_MB4"_sv_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 288, 1, UTF8_MB4, UTF8_MB4"_tr_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 289, 1, UTF8_MB4, UTF8_MB4"_cs_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 290, 1, UTF8_MB4, UTF8_MB4"_da_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 291, 1, UTF8_MB4, UTF8_MB4"_lt_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 292, 1, UTF8_MB4, UTF8_MB4"_sk_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 293, 1, UTF8_MB4, UTF8_MB4"_es_trad_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 294, 1, UTF8_MB4, UTF8_MB4"_la_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 296, 1, UTF8_MB4, UTF8_MB4"_eo_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 297, 1, UTF8_MB4, UTF8_MB4"_hu_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 298, 1, UTF8_MB4, UTF8_MB4"_hr_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 300, 1, UTF8_MB4, UTF8_MB4"_vi_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 303, 1, UTF8_MB4, UTF8_MB4"_ja_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 304, 1, UTF8_MB4, UTF8_MB4"_ja_0900_as_cs_ks", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 305, 1, UTF8_MB4, UTF8_MB4"_0900_as_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 306, 1, UTF8_MB4, UTF8_MB4"_ru_0900_as_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 307, 1, UTF8_MB4, UTF8_MB4"_ru_0900_as_cs", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 576, 1, UTF8_MB3, UTF8_MB3"_croatian_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
+ { 577, 1, UTF8_MB3, UTF8_MB3"_myanmar_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
+ { 578, 1, UTF8_MB3, UTF8_MB3"_thai_520_w2", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid}, /*MDB*/
+ { 608, 1, UTF8_MB4, UTF8_MB4"_croatian_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 609, 1, UTF8_MB4, UTF8_MB4"_myanmar_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 610, 1, UTF8_MB4, UTF8_MB4"_thai_520_w2", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 640, 1, "ucs2", "ucs2_croatian_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 641, 1, "ucs2", "ucs2_myanmar_ci", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 642, 1, "ucs2", "ucs2_thai_520_w2", "", 1200, "UCS2-BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ { 672, 1, "utf16", "utf16_croatian_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 673, 1, "utf16", "utf16_myanmar_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 674, 1, "utf16", "utf16_thai_520_w2", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ { 736, 1, "utf32", "utf32_croatian_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 737, 1, "utf32", "utf32_myanmar_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ { 738, 1, "utf32", "utf32_thai_520_w2", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ {1025, 1, "big5","big5_chinese_nopad_ci", "", 950, "BIG5", 1, 2, mysql_mbcharlen_big5, check_mb_big5},
+ {1027, 1, "dec8", "dec8_swedisch_nopad_ci", "", 0, "DEC", 1, 1, NULL, NULL},
+ {1028, 1, "cp850", "cp850_general_nopad_ci", "", 850, "CP850", 1, 1, NULL, NULL},
+ {1030, 1, "hp8", "hp8_english_nopad_ci", "", 0, "HP-ROMAN8", 1, 1, NULL, NULL},
+ {1031, 1, "koi8r", "koi8r_general_nopad_ci", "", 878, "KOI8R", 1, 1, NULL, NULL},
+ {1032, 1, "latin1", "latin1_swedish_nopad_ci", "", 850, "LATIN1", 1, 1, NULL, NULL},
+ {1033, 1, "latin2", "latin2_general_nopad_ci", "", 852, "LATIN2", 1, 1, NULL, NULL},
+ {1034, 1, "swe7", "swe7_swedish_nopad_ci", "", 20107, "", 1, 1, NULL, NULL},
+ {1035, 1, "ascii", "ascii_general_nopad_ci", "", 1252, "ASCII", 1, 1, NULL, NULL},
+ {1036, 1, "ujis", "ujis_japanese_nopad_ci", "", 20932, "UJIS", 1, 3, mysql_mbcharlen_ujis, check_mb_ujis},
+ {1037, 1, "sjis", "sjis_japanese_nopad_ci", "", 932, "SJIS", 1, 2, mysql_mbcharlen_sjis, check_mb_sjis},
+ {1040, 1, "hebrew", "hebrew_general_nopad_ci", "", 1255, "HEBREW", 1, 1, NULL, NULL},
+ {1042, 1, "tis620", "tis620_thai_nopad_ci", "", 874, "TIS620", 1, 1, NULL, NULL},
+ {1043, 1, "euckr", "euckr_korean_nopad_ci", "", 51949, "EUCKR", 1, 2, mysql_mbcharlen_euckr, check_mb_euckr},
+ {1046, 1, "koi8u", "koi8u_general_nopad_ci", "", 20866, "KOI8U", 1, 1, NULL, NULL},
+ {1048, 1, "gb2312", "gb2312_chinese_nopad_ci", "", 936, "GB2312", 1, 2, mysql_mbcharlen_gb2312, check_mb_gb2312},
+ {1049, 1, "greek", "greek_general_nopad_ci", "", 28597, "GREEK", 1, 1, NULL, NULL},
+ {1050, 1, "cp1250", "cp1250_general_nopad_ci", "", 1250, "CP1250", 1, 1, NULL, NULL},
+ {1052, 1, "gbk", "gbk_chinese_nopad_ci", "", 936, "GBK", 1, 2, mysql_mbcharlen_gbk, check_mb_gbk},
+ {1054, 1, "latin5", "latin5_turkish_nopad_ci", "", 1254, "LATIN5", 1, 1, NULL, NULL},
+ {1056, 1, "armscii8", "armscii8_general_nopad_ci", "", 0, "ARMSCII-8", 1, 1, NULL, NULL},
+ {1057, 1, UTF8_MB3, UTF8_MB3"_general_nopad_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ {1059, 1, "ucs2", "ucs2_general_nopad_ci", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ {1060, 1, "cp866", "cp866_general_nopad_ci", "", 866, "CP866", 1, 1, NULL, NULL},
+ {1061, 1, "keybcs2", "keybcs2_general_nopad_ci", "", 0, "", 1, 1, NULL, NULL},
+ {1062, 1, "macce", "macce_general_nopad_ci", "", 10029, "CP1282", 1, 1, NULL, NULL},
+ {1063, 1, "macroman", "macroman_general_nopad_ci", "", 10000, "MACINTOSH", 1, 1, NULL, NULL},
+ {1064, 1, "cp852", "cp852_general_nopad_ci", "", 852, "CP852", 1, 1, NULL, NULL},
+ {1065, 1, "latin7", "latin7_general_nopad_ci", "", 28603, "LATIN7", 1, 1, NULL, NULL},
+ {1067, 1, "macce", "macce_nopad_bin", "", 10029, "CP1282", 1, 1, NULL, NULL},
+ {1069, 1, UTF8_MB4, UTF8_MB4"_general_nopad_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ {1070, 1, UTF8_MB4, UTF8_MB4"_general_nopad_bin", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ {1071, 1, "latin1", "latin1_nopad_bin", "", 850, "LATIN1", 1, 1, NULL, NULL},
+ {1074, 1, "cp1251", "cp1251_nopad_bin", "", 1251, "CP1251", 1, 1, NULL, NULL},
+ {1075, 1, "cp1251", "cp1251_general_nopad_ci", "", 1251, "CP1251", 1, 1, NULL, NULL},
+ {1077, 1, "macroman", "macroman_nopad_bin", "", 10000, "MACINTOSH", 1, 1, NULL, NULL},
+ {1078, 1, "utf16", "utf16_general_nopad_ci", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ {1079, 1, "utf16", "utf16_nopad_bin", "", 0, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ {1080, 1, "utf16le", "utf16le_general_nopad_ci", "", 1200, "UTF16LE", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ {1081, 1, "cp1256", "cp1256_general_nopad_ci", "", 1256, "CP1256", 1, 1, NULL, NULL},
+ {1082, 1, "cp1257", "cp1257_nopad_bin", "", 1257, "CP1257", 1, 1, NULL, NULL},
+ {1083, 1, "cp1257", "cp1257_general_nopad_ci", "", 1257, "CP1257", 1, 1, NULL, NULL},
+ {1084, 1, "utf32", "utf32_general_nopad_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ {1085, 1, "utf32", "utf32_nopad_bin", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ {1086, 1, "utf16le", "utf16le_nopad_bin", "", 1200, "UTF16LE", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ {1088, 1, "armscii8", "armscii8_nopad_bin", "", 0, "ARMSCII-8", 1, 1, NULL, NULL},
+ {1089, 1, "ascii", "ascii_nopad_bin", "", 1252, "ASCII", 1, 1, NULL, NULL},
+ {1090, 1, "cp1250", "cp1250_nopad_bin", "", 1250, "CP1250", 1, 1, NULL, NULL},
+ {1091, 1, "cp1256", "cp1256_nopad_bin", "", 1256, "CP1256", 1, 1, NULL, NULL},
+ {1092, 1, "cp866", "cp866_nopad_bin", "", 866, "CP866", 1, 1, NULL, NULL},
+ {1093, 1, "dec8", "dec8_nopad_bin", "", 0, "DEC", 1, 1, NULL, NULL},
+ {1094, 1, "greek", "greek_nopad_bin", "", 28597, "GREEK", 1, 1, NULL, NULL},
+ {1095, 1, "hebrew", "hebrew_nopad_bin", "", 1255, "HEBREW", 1, 1, NULL, NULL},
+ {1096, 1, "hp8", "hp8_nopad_bin", "", 0, "HP-ROMAN8", 1, 1, NULL, NULL},
+ {1097, 1, "keybcs2", "keybcs2_nopad_bin", "", 0, "", 1, 1, NULL, NULL},
+ {1098, 1, "koi8r", "koi8r_nopad_bin", "", 878, "KOI8R", 1, 1, NULL, NULL},
+ {1099, 1, "koi8u", "koi8u_nopad_bin", "", 20866, "KOI8U", 1, 1, NULL, NULL},
+ {1101, 1, "latin2", "latin2_nopad_bin", "", 852, "LATIN2", 1, 1, NULL, NULL},
+ {1102, 1, "latin5", "latin5_nopad_bin", "", 1254, "LATIN5", 1, 1, NULL, NULL},
+ {1103, 1, "latin7", "latin7_nopad_bin", "", 28603, "LATIN7", 1, 1, NULL, NULL},
+ {1104, 1, "cp850", "cp850_nopad_bin", "", 850, "CP850", 1, 1, NULL, NULL},
+ {1105, 1, "cp852", "cp852_nopad_bin", "", 852, "CP852", 1, 1, NULL, NULL},
+ {1106, 1, "swe7", "swe7_nopad_bin", "", 20107, "", 1, 1, NULL, NULL},
+ {1107, 1, UTF8_MB3, UTF8_MB3"_nopad_bin", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ {1108, 1, "big5","big5_nopad_bin", "", 950, "BIG5", 1, 2, mysql_mbcharlen_big5, check_mb_big5},
+ {1109, 1, "euckr", "euckr_nopad_bin", "", 51949, "EUCKR", 1, 2, mysql_mbcharlen_euckr, check_mb_euckr},
+ {1110, 1, "gb2312", "gb2312_nopad_bin", "", 936, "GB2312", 1, 2, mysql_mbcharlen_gb2312, check_mb_gb2312},
+ {1111, 1, "gbk", "gbk_nopad_bin", "", 936, "GBK", 1, 2, mysql_mbcharlen_gbk, check_mb_gbk},
+ {1112, 1, "sjis", "sjis_nopad_bin", "", 932, "SJIS", 1, 2, mysql_mbcharlen_sjis, check_mb_sjis},
+ {1113, 1, "tis620", "tis620_nopad_bin", "", 874, "TIS620", 1, 1, NULL, NULL},
+ {1114, 1, "ucs2", "ucs2_nopad_bin", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ {1115, 1, "ujis", "ujis_nopad_bin", "", 20932, "UJIS", 1, 3, mysql_mbcharlen_ujis, check_mb_ujis},
+ {1116, 1, "geostd8", "geostd8_general_nopad_ci", "", 0, "GEORGIAN-PS", 1, 1, NULL, NULL},
+ {1117, 1, "geostd8", "geostd8_nopad_bin", "", 0, "GEORGIAN-PS", 1, 1, NULL, NULL},
+ {1119, 1, "cp932", "cp932_japanese_nopad_ci", "", 932, "CP932", 1, 2, mysql_mbcharlen_cp932, check_mb_cp932},
+ {1120, 1, "cp932", "cp932_nopad_bin", "", 932, "CP932", 1, 2, mysql_mbcharlen_cp932, check_mb_cp932},
+ {1121, 1, "eucjpms", "eucjpms_japanese_nopad_ci", "", 932, "EUCJP-MS", 1, 3, mysql_mbcharlen_eucjpms, check_mb_eucjpms},
+ {1122, 1, "eucjpms", "eucjpms_nopad_bin", "", 932, "EUCJP-MS", 1, 3, mysql_mbcharlen_eucjpms, check_mb_eucjpms},
+ {1125, 1, "utf16", "utf16_unicode_nopad_ci", "", 1200, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ {1147, 1, "utf16", "utf16_unicode_520_nopad_ci", "", 1200, "UTF16", 2, 4, mysql_mbcharlen_utf16, check_mb_utf16},
+ {1152, 1, "ucs2", "ucs2_unicode_nopad_ci", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ {1174, 1, "ucs2", "ucs2_unicode_520_nopad_ci", "", 1200, "UCS-2BE", 2, 2, mysql_mbcharlen_ucs2, check_mb_ucs2},
+ {1184, 1, "utf32", "utf32_unicode_nopad_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ {1206, 1, "utf32", "utf32_unicode_520_nopad_ci", "", 0, "UTF32", 4, 4, mysql_mbcharlen_utf32, check_mb_utf32},
+ {1216, 1, UTF8_MB3, UTF8_MB3"_unicode_nopad_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ {1238, 1, UTF8_MB3, UTF8_MB3"_unicode_520_nopad_ci", "", 65001, "UTF-8", 1, 3, mysql_mbcharlen_utf8mb3, check_mb_utf8mb3_valid},
+ {1248, 1, UTF8_MB4, UTF8_MB4"_unicode_nopad_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ {1270, 1, UTF8_MB4, UTF8_MB4"_unicode_520_nopad_ci", "", 65001, "UTF-8", 1, 4, mysql_mbcharlen_utf8, check_mb_utf8_valid},
+ { 0, 0, NULL, NULL, NULL, 0, NULL, 0, 0, NULL, NULL}
+};
+/* }}} */
+
+
+typedef enum my_cs_encoding_enum
+{
+ MY_CS_ENCODING_UTF8MB3= 0,
+ MY_CS_ENCODING_UTF8MB4= 1,
+ MY_CS_ENCODING_UCS2= 2,
+ MY_CS_ENCODING_UTF16= 3,
+ MY_CS_ENCODING_UTF32= 4,
+} my_cs_encoding_t;
+
+#define MY_CS_ENCODING_LAST MY_CS_ENCODING_UTF32
+
+
+typedef struct my_uca1400_collation_definition_st
+{
+ const char * tailoring;
+ const char * name;
+ uint16 id_utf8mb3;
+ uint16 id_utf8mb4;
+ uint16 id_ucs2;
+ uint16 id_utf16;
+ uint16 id_utf32;
+} MY_UCA1400_COLLATION_DEFINITION;
+
+
+#define MY_UCA1400_COLLATION_DEFINITION_COUNT 26
+/*
+ UCA1400 collation definitions in the order of their UCA400 counterparts,
+ with IDs of their closest UCA1400 counterparts, for character sets
+ utf8mb3, utf8mb4, ucs2, utf16, utf32.
+*/
+static MY_UCA1400_COLLATION_DEFINITION
+my_uca1400_collation_definitions[MY_UCA1400_COLLATION_DEFINITION_COUNT]=
+{
+#define COLDEF(tl,name,id_utf8mb3,id_utf8mb4,id_ucs2,id_utf16,id_utf32) \
+ {(""), (name), (id_utf8mb3), (id_utf8mb4), (id_ucs2), (id_utf16), (id_utf32)}
+ /* Block N1 */
+ COLDEF("", "", 192, 224, 128, 101, 160),
+ COLDEF(icelandic, "icelandic", 193, 225, 129, 102, 161),
+ COLDEF(latvian, "latvian", 194, 226, 130, 103, 162),
+ COLDEF(romanian, "romanian", 195, 227, 131, 104, 163),
+ COLDEF(slovenian, "slovenian", 196, 228, 132, 105, 164),
+ COLDEF(polish, "polish", 197, 229, 133, 106, 165),
+ COLDEF(estonian, "estonian", 198, 230, 134, 107, 166),
+ COLDEF(spanish, "spanish", 199, 231, 135, 108, 167),
+ COLDEF(swedish, "swedish", 200, 232, 136, 109, 168),
+ COLDEF(turkish, "turkish", 201, 233, 137, 110, 169),
+ COLDEF(czech, "czech", 202, 234, 138, 111, 170),
+ COLDEF(danish, "danish", 203, 235, 139, 112, 171),
+ COLDEF(lithuanian, "lithuanian", 204, 236, 140, 113, 172),
+ COLDEF(slovak, "slovak", 205, 237, 141, 114, 173),
+ COLDEF(spanish2, "spanish2", 206, 238, 142, 115, 174),
+ COLDEF(roman, "roman", 207, 239, 143, 116, 175),
+ COLDEF(persian, "persian", 208, 240, 144, 117, 176),
+ COLDEF(esperanto, "esperanto", 209, 241, 145, 118, 177),
+ COLDEF(hungarian, "hungarian", 210, 242, 146, 119, 178),
+ COLDEF(sinhala, "sinhala", 211, 243, 147, 120, 179),
+ COLDEF(german2, "german2", 212, 244, 148, 121, 180),
+ /*
+ Don't add "croatian_mysql561", as its UCA-4.0.0 version was added for
+ compatibility only, to open MySQL tables.
+ The "croatian" version is closer to CLDR. Checked with CLDR-40.
+ */
+ COLDEF(NULL,/*croatian_mysql561*/ NULL, 213, 245, 149, 122, 181),
+ COLDEF(NULL,/*unicode_520_ci*/ NULL, 214, 246, 150, 123, 182),
+ COLDEF(vietnamese, "vietnamese", 215, 247, 151, 124, 183),
+ /* Block N2 */
+ COLDEF(croatian_mariadb, "croatian", 576, 608, 640, 672, 736),
+ /* Don't add myanmar yet. It causes too long weights on the tertiary level.*/
+ COLDEF(NULL,/*myanmar*/ NULL, 577, 609, 641, 673, 737)
+
+#undef COLDEF
+};
+
+
+#define MY_UCA1400_COLLATION_ID_POSSIBLE_MIN 2048
+#define MY_UCA1400_COLLATION_ID_POSSIBLE_MAX 4095
+
+static inline my_bool
+my_collation_id_is_uca1400(uint id)
+{
+ return (my_bool) (id >= MY_UCA1400_COLLATION_ID_POSSIBLE_MIN &&
+ id <= MY_UCA1400_COLLATION_ID_POSSIBLE_MAX);
+}
+
+
+static inline uint
+my_uca1400_collation_id_to_tailoring_id(uint id)
+{
+ return (id >> 3) & 0x1F;
+}
+
+
+static inline my_cs_encoding_t
+my_uca1400_collation_id_to_charset_id(uint id)
+{
+ return (my_cs_encoding_t) ((id >> 8) & 0x07);
+}
+
+
+static uint my_uca1400_collation_id_uca400_compat(uint id)
+{
+ uint tlid= my_uca1400_collation_id_to_tailoring_id(id);
+ my_cs_encoding_t csid= my_uca1400_collation_id_to_charset_id(id);
+ MY_UCA1400_COLLATION_DEFINITION *def;
+ DBUG_ASSERT(my_collation_id_is_uca1400(id));
+ if (!(def= &my_uca1400_collation_definitions[tlid])->name)
+ return id;
+ switch (csid) {
+ case MY_CS_ENCODING_UTF8MB3: return def->id_utf8mb3;
+ case MY_CS_ENCODING_UTF8MB4: return def->id_utf8mb4;
+ case MY_CS_ENCODING_UCS2: return def->id_ucs2;
+ case MY_CS_ENCODING_UTF16: return def->id_utf16;
+ case MY_CS_ENCODING_UTF32: return def->id_utf32;
+ }
+ return id;
+}
+
+
+/* {{{ mysql_find_charset_nr */
+const MARIADB_CHARSET_INFO * mysql_find_charset_nr(unsigned int charsetnr)
+{
+ const MARIADB_CHARSET_INFO * c = mariadb_compiled_charsets;
+
+ if (my_collation_id_is_uca1400(charsetnr))
+ charsetnr= my_uca1400_collation_id_uca400_compat(charsetnr);
+
+ do {
+ if (c->nr == charsetnr) {
+ return(c);
+ }
+ ++c;
+ } while (c[0].nr != 0);
+ return(NULL);
+}
+/* }}} */
+
+
+/* {{{ mysql_find_charset_name */
+MARIADB_CHARSET_INFO * mysql_find_charset_name(const char *name)
+{
+ MARIADB_CHARSET_INFO *c = (MARIADB_CHARSET_INFO *)mariadb_compiled_charsets;
+ const char *csname;
+
+ if (!strcasecmp(name, MADB_AUTODETECT_CHARSET_NAME))
+ csname= madb_get_os_character_set();
+ else
+ csname= (char *)name;
+
+ if (!strcasecmp("utf8",csname))
+ csname= "utf8mb3";
+
+ do {
+ if (!strcasecmp(c->csname, csname)) {
+ return(c);
+ }
+ ++c;
+ } while (c[0].nr != 0);
+ return(NULL);
+}
+/* }}} */
+
+
+/* {{{ mysql_cset_escape_quotes */
+size_t mysql_cset_escape_quotes(const MARIADB_CHARSET_INFO *cset, char *newstr,
+ const char * escapestr, size_t escapestr_len )
+{
+ const char *newstr_s = newstr;
+ const char *newstr_e = newstr + 2 * escapestr_len;
+ const char *end = escapestr + escapestr_len;
+ my_bool escape_overflow = FALSE;
+
+ for (;escapestr < end; escapestr++) {
+ unsigned int len = 0;
+ /* check unicode characters */
+
+ if (cset->char_maxlen > 1 && (len = cset->mb_valid(escapestr, end))) {
+
+ /* check possible overflow */
+ if ((newstr + len) > newstr_e) {
+ escape_overflow = TRUE;
+ break;
+ }
+ /* copy mb char without escaping it */
+ while (len--) {
+ *newstr++ = *escapestr++;
+ }
+ escapestr--;
+ continue;
+ }
+ if (*escapestr == '\'') {
+ if (newstr + 2 > newstr_e) {
+ escape_overflow = TRUE;
+ break;
+ }
+ *newstr++ = '\'';
+ *newstr++ = '\'';
+ } else {
+ if (newstr + 1 > newstr_e) {
+ escape_overflow = TRUE;
+ break;
+ }
+ *newstr++ = *escapestr;
+ }
+ }
+ *newstr = '\0';
+
+ if (escape_overflow) {
+ return((size_t)~0);
+ }
+ return((size_t)(newstr - newstr_s));
+}
+/* }}} */
+
+
+/* {{{ mysql_cset_escape_slashes */
+size_t mysql_cset_escape_slashes(const MARIADB_CHARSET_INFO * cset, char *newstr,
+ const char * escapestr, size_t escapestr_len )
+{
+ const char *newstr_s = newstr;
+ const char *newstr_e = newstr + 2 * escapestr_len;
+ const char *end = escapestr + escapestr_len;
+ my_bool escape_overflow = FALSE;
+
+ for (;escapestr < end; escapestr++) {
+ char esc = '\0';
+ unsigned int len = 0;
+
+ /* check unicode characters */
+ if (cset->char_maxlen > 1 && (len = cset->mb_valid(escapestr, end))) {
+ /* check possible overflow */
+ if ((newstr + len) > newstr_e) {
+ escape_overflow = TRUE;
+ break;
+ }
+ /* copy mb char without escaping it */
+ while (len--) {
+ *newstr++ = *escapestr++;
+ }
+ escapestr--;
+ continue;
+ }
+ if (cset->char_maxlen > 1 && cset->mb_charlen(*escapestr) > 1) {
+ esc = *escapestr;
+ } else {
+ switch (*escapestr) {
+ case 0:
+ esc = '0';
+ break;
+ case '\n':
+ esc = 'n';
+ break;
+ case '\r':
+ esc = 'r';
+ break;
+ case '\\':
+ case '\'':
+ case '"':
+ esc = *escapestr;
+ break;
+ case '\032':
+ esc = 'Z';
+ break;
+ }
+ }
+ if (esc) {
+ if (newstr + 2 > newstr_e) {
+ escape_overflow = TRUE;
+ break;
+ }
+ /* copy escaped character */
+ *newstr++ = '\\';
+ *newstr++ = esc;
+ } else {
+ if (newstr + 1 > newstr_e) {
+ escape_overflow = TRUE;
+ break;
+ }
+ /* copy non escaped character */
+ *newstr++ = *escapestr;
+ }
+ }
+ *newstr = '\0';
+
+ if (escape_overflow) {
+ return((size_t)~0);
+ }
+ return((size_t)(newstr - newstr_s));
+}
+/* }}} */
+
+/* {{{ MADB_OS_CHARSET */
+struct st_madb_os_charset {
+ const char *identifier;
+ const char *description;
+ const char *charset;
+ const char *iconv_cs;
+ unsigned char supported;
+};
+
+#define MADB_CS_UNSUPPORTED 0
+#define MADB_CS_APPROX 1
+#define MADB_CS_EXACT 2
+
+/* Please add new character sets at the end. */
+struct st_madb_os_charset MADB_OS_CHARSET[]=
+{
+#ifdef _WIN32
+ /* Windows code pages */
+ {"037", "IBM EBCDIC US-Canada", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"437", "OEM United States", "cp850", NULL, MADB_CS_APPROX},
+ {"500", "IBM EBCDIC International", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"708", "Arabic (ASMO 708)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"709", "Arabic (ASMO-449+, BCON V4)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"710", "Transparent Arabic", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"720", "Arabic (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"737", "Greek (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"775", "Baltic (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"850", "Western European (DOS)", "cp850", NULL, MADB_CS_EXACT},
+ {"852", "Central European (DOS)", "cp852", NULL, MADB_CS_EXACT},
+ {"855", "Cyrillic (primarily Russian)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"857", "Turkish (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"858", "OEM Multilingual Latin 1 + Euro symbol", "cp850", NULL, MADB_CS_EXACT},
+ {"860", "Portuguese (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"861", "Icelandic (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"862", "Hebrew (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"863", "French Canadian (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"864", "Arabic (864)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"865", "Nordic (DOS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"866", "Cyrillic (DOS)", "cp866", NULL, MADB_CS_EXACT},
+ {"869", "Greek, Modern (DOS)", "greek", NULL, MADB_CS_EXACT},
+ {"870", "IBM EBCDIC Multilingual Latin 2", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"874", "Thai (Windows)", "tis620", NULL, MADB_CS_UNSUPPORTED},
+ {"875", "Greek Modern", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"932", "Japanese (Shift-JIS)", "cp932", NULL, MADB_CS_EXACT},
+ {"936", "Chinese Simplified (GB2312)", "gbk", NULL, MADB_CS_EXACT},
+ {"949", "ANSI/OEM Korean (Unified Hangul Code)", "euckr", NULL, MADB_CS_EXACT},
+ {"950", "Chinese Traditional (Big5)", "big5", NULL, MADB_CS_EXACT},
+ {"1026", "EBCDIC Turkish (Latin 5)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1047", "EBCDIC Latin 1/Open System", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1140", "IBM EBCDIC (US-Canada-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1141", "IBM EBCDIC (Germany-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1142", "IBM EBCDIC (Denmark-Norway-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1143", "IBM EBCDIC (Finland-Sweden-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1144", "IBM EBCDIC (Italy-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1145", "IBM EBCDIC (Spain-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1146", "IBM EBCDIC (UK-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1147", "IBM EBCDIC (France-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1148", "IBM EBCDIC (International-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1149", "IBM EBCDIC (Icelandic-Euro)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1200", "UTF-16, little endian byte order", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1201", "UTF-16, big endian byte order", "utf16", NULL, MADB_CS_UNSUPPORTED},
+ {"1250", "Central European (Windows)", "cp1250", NULL, MADB_CS_EXACT},
+ {"1251", "Cyrillic (Windows)", "cp1251", NULL, MADB_CS_EXACT},
+ {"1252", "Western European (Windows)", "latin1", NULL, MADB_CS_EXACT},
+ {"1253", "Greek (Windows)", "greek", NULL, MADB_CS_EXACT},
+ {"1254", "Turkish (Windows)", "latin5", NULL, MADB_CS_EXACT},
+ {"1255", "Hebrew (Windows)", "hebrew", NULL, MADB_CS_EXACT},
+ {"1256", "Arabic (Windows)", "cp1256", NULL, MADB_CS_EXACT},
+ {"1257", "Baltic (Windows)","cp1257", NULL, MADB_CS_EXACT},
+ {"1258", "Vietnamese (Windows)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"1361", "Korean (Johab)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10000", "Western European (Mac)", "macroman", NULL, MADB_CS_EXACT},
+ {"10001", "Japanese (Mac)", "sjis", NULL, MADB_CS_EXACT},
+ {"10002", "Chinese Traditional (Mac)", "big5", NULL, MADB_CS_EXACT},
+ {"10003", "Korean (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10004", "Arabic (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10005", "Hebrew (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10006", "Greek (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10007", "Cyrillic (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10008", "Chinese Simplified (Mac)", "gb2312", NULL, MADB_CS_EXACT},
+ {"10010", "Romanian (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10017", "Ukrainian (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10021", "Thai (Mac)", "tis620", NULL, MADB_CS_EXACT},
+ {"10029", "Central European (Mac)", "macce", NULL, MADB_CS_EXACT},
+ {"10079", "Icelandic (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10081", "Turkish (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"10082", "Croatian (Mac)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"12000", "Unicode UTF-32, little endian byte order", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"12001", "Unicode UTF-32, big endian byte order", "utf32", NULL, MADB_CS_UNSUPPORTED},
+ {"20000", "Chinese Traditional (CNS)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20001", "TCA Taiwan", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20002", "Chinese Traditional (Eten)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20003", "IBM5550 Taiwan", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20004", "TeleText Taiwan", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20005", "Wang Taiwan", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20105", "Western European (IA5)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20106", "IA5 German (7-bit)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20107", "Swedish (7-bit)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20108", "Norwegian (7-bit)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20127", "US-ASCII (7-bit)", "ascii", NULL, MADB_CS_EXACT},
+ {"20261", "T.61", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20269", "Non-Spacing Accent", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20273", "EBCDIC Germany", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20277", "EBCDIC Denmark-Norway", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20278", "EBCDIC Finland-Sweden", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20280", "EBCDIC Italy", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20284", "EBCDIC Latin America-Spain", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20285", "EBCDIC United Kingdom", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20290", "EBCDIC Japanese Katakana Extended", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20297", "EBCDIC France", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20420", "EBCDIC Arabic", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20423", "EBCDIC Greek", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20424", "EBCDIC Hebrew", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20833", "EBCDIC Korean Extended", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20838", "EBCDIC Thai", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20866", "Cyrillic (KOI8-R)", "koi8r", NULL, MADB_CS_EXACT},
+ {"20871", "EBCDIC Icelandic", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20880", "EBCDIC Cyrillic Russian", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20905", "EBCDIC Turkish", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20924", "EBCDIC Latin 1/Open System (1047 + Euro symbol)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"20932", "Japanese (JIS 0208-1990 and 0121-1990)", "ujis", NULL, MADB_CS_EXACT},
+ {"20936", "Chinese Simplified (GB2312-80)", "gb2312", NULL, MADB_CS_APPROX},
+ {"20949", "Korean Wansung", "euckr", NULL, MADB_CS_APPROX},
+ {"21025", "EBCDIC Cyrillic Serbian-Bulgarian", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"21866", "Cyrillic (KOI8-U)", "koi8u", NULL, MADB_CS_EXACT},
+ {"28591", "Western European (ISO)", "latin1", NULL, MADB_CS_APPROX},
+ {"28592", "Central European (ISO)", "latin2", NULL, MADB_CS_EXACT},
+ {"28593", "Latin 3", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"28594", "Baltic", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"28595", "ISO 8859-5 Cyrillic", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"28596", "ISO 8859-6 Arabic", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"28597", "ISO 8859-7 Greek", "greek", NULL, MADB_CS_EXACT},
+ {"28598", "Hebrew (ISO-Visual)", "hebrew", NULL, MADB_CS_EXACT},
+ {"28599", "ISO 8859-9 Turkish", "latin5", NULL, MADB_CS_EXACT},
+ {"28603", "ISO 8859-13 Estonian", "latin7", NULL, MADB_CS_EXACT},
+ {"28605", "8859-15 Latin 9", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"29001", "Europa 3", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"38598", "ISO 8859-8 Hebrew; Hebrew (ISO-Logical)", "hebrew", NULL, MADB_CS_EXACT},
+ {"50220", "ISO 2022 Japanese with no halfwidth Katakana", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50221", "ISO 2022 Japanese with halfwidth Katakana", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50222", "ISO 2022 Japanese JIS X 0201-1989", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50225", "ISO 2022 Korean", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50227", "ISO 2022 Simplified Chinese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50229", "ISO 2022 Traditional Chinese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50930", "EBCDIC Japanese (Katakana) Extended", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50931", "EBCDIC US-Canada and Japanese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50933", "EBCDIC Korean Extended and Korean", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50935", "EBCDIC Simplified Chinese Extended and Simplified Chinese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50936", "EBCDIC Simplified Chinese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50937", "EBCDIC US-Canada and Traditional Chinese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"50939", "EBCDIC Japanese (Latin) Extended and Japanese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"51932", "EUC Japanese", "ujis", NULL, MADB_CS_EXACT},
+ {"51936", "EUC Simplified Chinese; Chinese Simplified (EUC)", "gb2312", NULL, MADB_CS_EXACT},
+ {"51949", "EUC Korean", "euckr", NULL, MADB_CS_EXACT},
+ {"51950", "EUC Traditional Chinese", "big5", NULL, MADB_CS_EXACT},
+ {"52936", "Chinese Simplified (HZ)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"54936", "Chinese Simplified (GB18030)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57002", "ISCII Devanagari", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57003", "ISCII Bengali", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57004", "ISCII Tamil", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57005", "ISCII Telugu", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57006", "ISCII Assamese", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57007", "ISCII Oriya", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57008", "ISCII Kannada", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57009", "ISCII Malayalam", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57010", "ISCII Gujarati", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"57011", "ISCII Punjabi", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"65000", "utf-7 Unicode (UTF-7)", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"65001", "utf-8 Unicode (UTF-8)", "utf8", NULL, MADB_CS_EXACT},
+ /* non Windows */
+#else
+ /* iconv encodings */
+ {"ASCII", "US-ASCII", "ascii", "ASCII", MADB_CS_APPROX},
+ {"US-ASCII", "US-ASCII", "ascii", "ASCII", MADB_CS_APPROX},
+ {"Big5", "Chinese for Taiwan Multi-byte set", "big5", "BIG5", MADB_CS_EXACT},
+ {"CP866", "IBM 866", "cp866", "CP866", MADB_CS_EXACT},
+ {"IBM-1252", "Catalan Spain", "cp1252", "CP1252", MADB_CS_EXACT},
+ {"ISCII-DEV", "Hindi", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"ISO-8859-1", "ISO-8859-1", "latin1", "ISO_8859-1", MADB_CS_APPROX},
+ {"ISO8859-1", "ISO-8859-1", "latin1", "ISO_8859-1", MADB_CS_APPROX},
+ {"ISO_8859-1", "ISO-8859-1", "latin1", "ISO_8859-1", MADB_CS_APPROX},
+ {"ISO88591", "ISO-8859-1", "latin1", "ISO_8859-1", MADB_CS_APPROX},
+ {"ISO-8859-13", "ISO-8859-13", "latin7", "ISO_8859-13", MADB_CS_EXACT},
+ {"ISO8859-13", "ISO-8859-13", "latin7", "ISO_8859-13", MADB_CS_EXACT},
+ {"ISO_8859-13", "ISO-8859-13", "latin7", "ISO_8859-13", MADB_CS_EXACT},
+ {"ISO885913", "ISO-8859-13", "latin7", "ISO_8859-13", MADB_CS_EXACT},
+ {"ISO-8859-15", "ISO-8859-15", "latin9", "ISO_8859-15", MADB_CS_UNSUPPORTED},
+ {"ISO8859-15", "ISO-8859-15", "latin9", "ISO_8859-15", MADB_CS_UNSUPPORTED},
+ {"ISO_8859-15", "ISO-8859-15", "latin9", "ISO_8859-15", MADB_CS_UNSUPPORTED},
+ {"ISO885915", "ISO-8859-15", "latin9", "ISO_8859-15", MADB_CS_UNSUPPORTED},
+ {"ISO-8859-2", "ISO-8859-2", "latin2", "ISO_8859-2", MADB_CS_EXACT},
+ {"ISO8859-2", "ISO-8859-2", "latin2", "ISO_8859-2", MADB_CS_EXACT},
+ {"ISO_8859-2", "ISO-8859-2", "latin2", "ISO_8859-2", MADB_CS_EXACT},
+ {"ISO88592", "ISO-8859-2", "latin2", "ISO_8859-2", MADB_CS_EXACT},
+ {"ISO-8859-7", "ISO-8859-7", "greek", "ISO_8859-7", MADB_CS_EXACT},
+ {"ISO8859-7", "ISO-8859-7", "greek", "ISO_8859-7", MADB_CS_EXACT},
+ {"ISO_8859-7", "ISO-8859-7", "greek", "ISO_8859-7", MADB_CS_EXACT},
+ {"ISO88597", "ISO-8859-7", "greek", "ISO_8859-7", MADB_CS_EXACT},
+ {"ISO-8859-8", "ISO-8859-8", "hebrew", "ISO_8859-8", MADB_CS_EXACT},
+ {"ISO8859-8", "ISO-8859-8", "hebrew", "ISO_8859-8", MADB_CS_EXACT},
+ {"ISO_8859-8", "ISO-8859-8", "hebrew", "ISO_8859-8", MADB_CS_EXACT},
+ {"ISO88598", "ISO-8859-8", "hebrew", "ISO_8859-8", MADB_CS_EXACT},
+ {"ISO-8859-9", "ISO-8859-9", "latin5", "ISO_8859-9", MADB_CS_EXACT},
+ {"ISO8859-9", "ISO-8859-9", "latin5", "ISO_8859-9", MADB_CS_EXACT},
+ {"ISO_8859-9", "ISO-8859-9", "latin5", "ISO_8859-9", MADB_CS_EXACT},
+ {"ISO88599", "ISO-8859-9", "latin5", "ISO_8859-9", MADB_CS_EXACT},
+ {"ISO-8859-4", "ISO-8859-4", NULL, "ISO_8859-4", MADB_CS_UNSUPPORTED},
+ {"ISO8859-4", "ISO-8859-4", NULL, "ISO_8859-4", MADB_CS_UNSUPPORTED},
+ {"ISO_8859-4", "ISO-8859-4", NULL, "ISO_8859-4", MADB_CS_UNSUPPORTED},
+ {"ISO88594", "ISO-8859-4", NULL, "ISO_8859-4", MADB_CS_UNSUPPORTED},
+ {"ISO-8859-5", "ISO-8859-5", NULL, "ISO_8859-5", MADB_CS_UNSUPPORTED},
+ {"ISO8859-5", "ISO-8859-5", NULL, "ISO_8859-5", MADB_CS_UNSUPPORTED},
+ {"ISO_8859-5", "ISO-8859-5", NULL, "ISO_8859-5", MADB_CS_UNSUPPORTED},
+ {"ISO88595", "ISO-8859-5", NULL, "ISO_8859-5", MADB_CS_UNSUPPORTED},
+ {"KOI8-R", "KOI8-R", "koi8r", "KOI8R", MADB_CS_EXACT},
+ {"koi8r", "KOI8-R", "koi8r", "KOI8R", MADB_CS_EXACT},
+ {"KOI8-U", "KOI8-U", "koi8u", "KOI8U", MADB_CS_EXACT},
+ {"koi8u", "KOI8-U", "koi8u", "KOI8U", MADB_CS_EXACT},
+ {"koi8t", "KOI8-T", NULL, "KOI8-T", MADB_CS_UNSUPPORTED},
+ {"KOI8-T", "KOI8-T", NULL, "KOI8-T", MADB_CS_UNSUPPORTED},
+ {"SJIS", "SHIFT_JIS", "sjis", "SJIS", MADB_CS_EXACT},
+ {"Shift-JIS", "SHIFT_JIS", "sjis", "SJIS", MADB_CS_EXACT},
+ {"ansi1251", "Cyrillic", "cp1251", "CP1251", MADB_CS_EXACT},
+ {"cp1251", "Cyrillic", "cp1251", "CP1251", MADB_CS_EXACT},
+ {"armscii8", "Armenian", "armscii8", "ASMSCII-8", MADB_CS_EXACT},
+ {"armscii-8", "Armenian", "armscii8", "ASMSCII-8", MADB_CS_EXACT},
+ {"big5hkscs", "Big5-HKSCS", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"cp1255", "Hebrew", "cp1255", "CP1255", MADB_CS_EXACT},
+ {"eucCN", "GB-2312", "gb2312", "GB2312", MADB_CS_EXACT},
+ {"eucJP", "UJIS", "ujis", "UJIS", MADB_CS_EXACT},
+ {"eucKR", "EUC-KR", "euckr", "EUCKR", MADB_CS_EXACT},
+ {"euctw", "EUC-TW", NULL, NULL, MADB_CS_UNSUPPORTED},
+ {"gb18030", "GB 18030-2000", "gb18030", "GB18030", MADB_CS_UNSUPPORTED},
+ {"gb2312", "GB2312", "gb2312", "GB2312", MADB_CS_EXACT},
+ {"gbk", "GBK", "gbk", "GBK", MADB_CS_EXACT},
+ {"georgianps", "Georgian", "geostd8", "GEORGIAN-PS", MADB_CS_EXACT},
+ {"utf8", "UTF8", "utf8", "UTF-8", MADB_CS_EXACT},
+ {"utf-8", "UTF8", "utf8", "UTF-8", MADB_CS_EXACT},
+#endif
+ {NULL, NULL, NULL, NULL, 0}
+};
+/* }}} */
+
+/* {{{ madb_get_os_character_set */
+const char *madb_get_os_character_set()
+{
+ unsigned int i= 0;
+ char *p= NULL;
+#ifdef _WIN32
+ char codepage[FN_REFLEN];
+ snprintf(codepage, FN_REFLEN, "%u", GetConsoleCP() ? GetConsoleCP() : GetACP());
+ p= codepage;
+#elif defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE)
+ if (setlocale(LC_CTYPE, ""))
+ p= nl_langinfo(CODESET);
+#endif
+ if (!p)
+ return MADB_DEFAULT_CHARSET_NAME;
+ while (MADB_OS_CHARSET[i].identifier)
+ {
+ if (MADB_OS_CHARSET[i].supported > MADB_CS_UNSUPPORTED &&
+ strcasecmp(MADB_OS_CHARSET[i].identifier, p) == 0)
+ return MADB_OS_CHARSET[i].charset;
+ i++;
+ }
+ return MADB_DEFAULT_CHARSET_NAME;
+}
+/* }}} */
+
+/* {{{ madb_get_code_page */
+#ifdef _WIN32
+int madb_get_windows_cp(const char *charset)
+{
+ unsigned int i= 0;
+ while (MADB_OS_CHARSET[i].identifier)
+ {
+ if (MADB_OS_CHARSET[i].supported > MADB_CS_UNSUPPORTED &&
+ strcmp(MADB_OS_CHARSET[i].charset, charset) == 0)
+ return atoi(MADB_OS_CHARSET[i].identifier);
+ i++;
+ }
+ return -1;
+}
+#endif
+/* }}} */
+
+#ifdef HAVE_ICONV
+/* {{{ map_charset_name
+ Changing charset name into something iconv understands, if necessary.
+ Another purpose it to avoid BOMs in result string, adding BE if necessary
+ e.g.UTF16 does not work form iconv, while UTF-16 does.
+ */
+static void map_charset_name(const char *cs_name, my_bool target_cs, char *buffer, size_t buff_len)
+{
+ char digits[3], endianness[3]= "BE";
+
+ if (sscanf(cs_name, "UTF%2[0-9]%2[LBE]", digits, endianness))
+ {
+ /* We should have at least digits. Endianness we write either default(BE), or what we found in the string */
+ snprintf(buffer, buff_len, "UTF-%s%s", digits, endianness);
+ }
+ else
+ {
+ /* Not our client - copy as is*/
+ strncpy(buffer, cs_name, buff_len - 1);
+ buffer[buff_len - 1]= '\0';
+ }
+
+ if (target_cs)
+ {
+ strncat(buffer, "//TRANSLIT", buff_len - strlen(buffer));
+ }
+}
+/* }}} */
+#endif
+
+/* {{{ mariadb_convert_string
+ Converts string from one charset to another, and writes converted string to given buffer
+ @param[in] from
+ @param[in/out] from_len
+ @param[in] from_cs
+ @param[out] to
+ @param[in/out] to_len
+ @param[in] to_cs
+ @param[out] errorcode
+
+ @return -1 in case of error, bytes used in the "to" buffer, otherwise
+ */
+size_t STDCALL mariadb_convert_string(const char *from __attribute__((unused)),
+ size_t *from_len __attribute__((unused)),
+ MARIADB_CHARSET_INFO *from_cs __attribute__((unused)),
+ char *to __attribute__((unused)),
+ size_t *to_len __attribute__((unused)),
+ MARIADB_CHARSET_INFO *to_cs __attribute__((unused)), int *errorcode)
+{
+#ifndef HAVE_ICONV
+ *errorcode= ENOTSUP;
+ return -1;
+#else
+ iconv_t conv= 0;
+ size_t rc= -1;
+ size_t save_len= *to_len;
+ char to_encoding[128], from_encoding[128];
+
+ *errorcode= 0;
+
+ /* check if conversion is supported */
+ if (!from_cs || !from_cs->encoding || !from_cs->encoding[0] ||
+ !to_cs || !to_cs->encoding || !to_cs->encoding[0])
+ {
+ *errorcode= EINVAL;
+ return rc;
+ }
+
+ map_charset_name(to_cs->encoding, 1, to_encoding, sizeof(to_encoding));
+ map_charset_name(from_cs->encoding, 0, from_encoding, sizeof(from_encoding));
+
+ if ((conv= iconv_open(to_encoding, from_encoding)) == (iconv_t)-1)
+ {
+ *errorcode= errno;
+ goto error;
+ }
+ if ((rc= iconv(conv, IF_WIN(,IF_SOLARIS(,(char **)))&from, from_len, &to, to_len)) == (size_t)-1)
+ {
+ *errorcode= errno;
+ goto error;
+ }
+ rc= save_len - *to_len;
+error:
+ if (conv != (iconv_t)-1)
+ iconv_close(conv);
+ return rc;
+#endif
+}
+/* }}} */
+
diff --git a/libmariadb/libmariadb/ma_client_plugin.c.in b/libmariadb/libmariadb/ma_client_plugin.c.in
new file mode 100644
index 00000000..6e0433b3
--- /dev/null
+++ b/libmariadb/libmariadb/ma_client_plugin.c.in
@@ -0,0 +1,503 @@
+/* Copyright (C) 2010 - 2012 Sergei Golubchik and Monty Program Ab
+ 2015-2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA */
+
+/**
+ @file
+
+ Support code for the client side (libmariadb) plugins
+
+ Client plugins are somewhat different from server plugins, they are simpler.
+
+ They do not need to be installed or in any way explicitly loaded on the
+ client, they are loaded automatically on demand.
+ One client plugin per shared object, soname *must* match the plugin name.
+
+ There is no reference counting and no unloading either.
+*/
+
+/* Silence warnings about variable 'unused' being used. */
+#define FORCE_INIT_OF_VARS 1
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+#include <ma_string.h>
+#include <ma_pthread.h>
+
+#include "errmsg.h"
+#include <mysql/client_plugin.h>
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+struct st_client_plugin_int {
+ struct st_client_plugin_int *next;
+ void *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+};
+
+static my_bool initialized= 0;
+static MA_MEM_ROOT mem_root;
+
+static uint valid_plugins[][2]= {
+ {MYSQL_CLIENT_AUTHENTICATION_PLUGIN, MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION},
+ {MARIADB_CLIENT_PVIO_PLUGIN, MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION},
+ {MARIADB_CLIENT_TRACE_PLUGIN, MARIADB_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION},
+ {MARIADB_CLIENT_REMOTEIO_PLUGIN, MARIADB_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION},
+ {MARIADB_CLIENT_CONNECTION_PLUGIN, MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION},
+ {MARIADB_CLIENT_COMPRESSION_PLUGIN, MARIADB_CLIENT_COMPRESSION_PLUGIN_INTERFACE_VERSION},
+ {0, 0}
+};
+
+/*
+ Loaded plugins are stored in a linked list.
+ The list is append-only, the elements are added to the head (like in a stack).
+ The elements are added under a mutex, but the list can be read and traversed
+ without any mutex because once an element is added to the list, it stays
+ there. The main purpose of a mutex is to prevent two threads from
+ loading the same plugin twice in parallel.
+*/
+
+
+struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS + MARIADB_CLIENT_MAX_PLUGINS];
+#ifdef THREAD
+static pthread_mutex_t LOCK_load_client_plugin;
+#endif
+
+@EXTERNAL_PLUGINS@
+
+struct st_mysql_client_plugin *mysql_client_builtins[]=
+{
+ @BUILTIN_PLUGINS@
+ 0
+};
+
+
+static int is_not_initialized(MYSQL *mysql, const char *name)
+{
+ if (initialized)
+ return 0;
+
+ my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ SQLSTATE_UNKNOWN, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ name, "not initialized");
+ return 1;
+}
+
+static int get_plugin_nr(uint type)
+{
+ uint i= 0;
+ for(; valid_plugins[i][1]; i++)
+ if (valid_plugins[i][0] == type)
+ return i;
+ return -1;
+}
+
+static const char *check_plugin_version(struct st_mysql_client_plugin *plugin, unsigned int version)
+{
+ if (plugin->interface_version < version ||
+ (plugin->interface_version >> 8) > (version >> 8))
+ return "Incompatible client plugin interface";
+ return 0;
+}
+
+/**
+ finds a plugin in the list
+
+ @param name plugin name to search for
+ @param type plugin type
+
+ @note this does NOT necessarily need a mutex, take care!
+
+ @retval a pointer to a found plugin or 0
+*/
+static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
+{
+ struct st_client_plugin_int *p;
+ int plugin_nr= get_plugin_nr(type);
+
+ DBUG_ASSERT(initialized);
+ if (plugin_nr == -1)
+ return 0;
+
+ if (!name)
+ return plugin_list[plugin_nr]->plugin;
+
+ for (p= plugin_list[plugin_nr]; p; p= p->next)
+ {
+ if (strcmp(p->plugin->name, name) == 0)
+ return p->plugin;
+ }
+ return NULL;
+}
+
+
+/**
+ verifies the plugin and adds it to the list
+
+ @param mysql MYSQL structure (for error reporting)
+ @param plugin plugin to install
+ @param dlhandle a handle to the shared object (returned by dlopen)
+ or 0 if the plugin was not dynamically loaded
+ @param argc number of arguments in the 'va_list args'
+ @param args arguments passed to the plugin initialization function
+
+ @retval a pointer to an installed plugin or 0
+*/
+
+static struct st_mysql_client_plugin *
+add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
+ int argc, va_list args)
+{
+ const char *errmsg;
+ struct st_client_plugin_int plugin_int, *p;
+ char errbuf[1024];
+ int plugin_nr;
+
+ DBUG_ASSERT(initialized);
+
+ plugin_int.plugin= plugin;
+ plugin_int.dlhandle= dlhandle;
+
+ if ((plugin_nr= get_plugin_nr(plugin->type)) == -1)
+ {
+ errmsg= "Unknown client plugin type";
+ goto err1;
+ }
+ if ((errmsg= check_plugin_version(plugin, valid_plugins[plugin_nr][1])))
+ goto err1;
+
+ /* Call the plugin initialization function, if any */
+ if (plugin->init && plugin->init(errbuf, sizeof(errbuf), argc, args))
+ {
+ errmsg= errbuf;
+ goto err1;
+ }
+
+ p= (struct st_client_plugin_int *)
+ ma_memdup_root(&mem_root, (char *)&plugin_int, sizeof(plugin_int));
+
+ if (!p)
+ {
+ errmsg= "Out of memory";
+ goto err2;
+ }
+
+
+ p->next= plugin_list[plugin_nr];
+ plugin_list[plugin_nr]= p;
+
+ return plugin;
+
+err2:
+ if (plugin->deinit)
+ plugin->deinit();
+err1:
+ my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name, errmsg);
+ if (dlhandle)
+ (void)dlclose(dlhandle);
+ return NULL;
+}
+
+
+/**
+ Loads plugins which are specified in the environment variable
+ LIBMYSQL_PLUGINS.
+
+ Multiple plugins must be separated by semicolon. This function doesn't
+ return or log an error.
+
+ The function is be called by mysql_client_plugin_init
+
+ @todo
+ Support extended syntax, passing parameters to plugins, for example
+ LIBMYSQL_PLUGINS="plugin1(param1,param2);plugin2;..."
+ or
+ LIBMYSQL_PLUGINS="plugin1=int:param1,str:param2;plugin2;..."
+*/
+
+static void load_env_plugins(MYSQL *mysql)
+{
+ char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS");
+
+ if (ma_check_env_str(s))
+ return;
+
+ free_env= strdup(s);
+ plugs= s= free_env;
+
+ do {
+ if ((s= strchr(plugs, ';')))
+ *s= '\0';
+ mysql_load_plugin(mysql, plugs, -1, 0);
+ plugs= s + 1;
+ } while (s);
+
+ free(free_env);
+}
+
+/********** extern functions to be used by libmariadb *********************/
+
+/**
+ Initializes the client plugin layer.
+
+ This function must be called before any other client plugin function.
+
+ @retval 0 successful
+ @retval != 0 error occurred
+*/
+
+int mysql_client_plugin_init()
+{
+ MYSQL mysql;
+ struct st_mysql_client_plugin **builtin;
+ va_list unused;
+ LINT_INIT_STRUCT(unused);
+
+ if (initialized)
+ return 0;
+
+ memset(&mysql, 0, sizeof(mysql)); /* dummy mysql for set_mysql_extended_error */
+
+ pthread_mutex_init(&LOCK_load_client_plugin, NULL);
+ ma_init_alloc_root(&mem_root, 128, 128);
+
+ memset(&plugin_list, 0, sizeof(plugin_list));
+
+ initialized= 1;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+ for (builtin= mysql_client_builtins; *builtin; builtin++)
+ add_plugin(&mysql, *builtin, 0, 0, unused);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ load_env_plugins(&mysql);
+
+ return 0;
+}
+
+
+/**
+ Deinitializes the client plugin layer.
+
+ Unloades all client plugins and frees any associated resources.
+*/
+
+void mysql_client_plugin_deinit()
+{
+ int i;
+ struct st_client_plugin_int *p;
+
+ if (!initialized)
+ return;
+
+ for (i=0; i < MYSQL_CLIENT_MAX_PLUGINS; i++)
+ for (p= plugin_list[i]; p; p= p->next)
+ {
+ if (p->plugin->deinit)
+ p->plugin->deinit();
+ if (p->dlhandle)
+ (void)dlclose(p->dlhandle);
+ }
+
+ memset(&plugin_list, 0, sizeof(plugin_list));
+ initialized= 0;
+ ma_free_root(&mem_root, MYF(0));
+ pthread_mutex_destroy(&LOCK_load_client_plugin);
+}
+
+/************* public facing functions, for client consumption *********/
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin * STDCALL
+mysql_client_register_plugin(MYSQL *mysql,
+ struct st_mysql_client_plugin *plugin)
+{
+ struct st_mysql_client_plugin *found_plugin= NULL;
+ va_list unused;
+ LINT_INIT_STRUCT(unused);
+
+ if (is_not_initialized(mysql, plugin->name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (!(found_plugin= find_plugin(plugin->name, plugin->type)))
+ found_plugin= add_plugin(mysql, plugin, 0, 0, unused);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ return found_plugin;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin * STDCALL
+mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
+ int argc, va_list args)
+{
+ const char *errmsg;
+#ifdef _WIN32
+ char errbuf[1024];
+#endif
+ char dlpath[FN_REFLEN+1];
+ void *sym, *dlhandle = NULL;
+ struct st_mysql_client_plugin *plugin;
+ char *env_plugin_dir= getenv("MARIADB_PLUGIN_DIR");
+
+ CLEAR_CLIENT_ERROR(mysql);
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (type >= 0 && find_plugin(name, type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ /* Compile dll path */
+#ifndef WIN32
+ snprintf(dlpath, sizeof(dlpath) - 1, "%s/%s%s",
+ mysql->options.extension && mysql->options.extension->plugin_dir ?
+ mysql->options.extension->plugin_dir : (env_plugin_dir) ? env_plugin_dir :
+ MARIADB_PLUGINDIR, name, SO_EXT);
+#else
+ {
+ char *p= (mysql->options.extension && mysql->options.extension->plugin_dir) ?
+ mysql->options.extension->plugin_dir : env_plugin_dir;
+ snprintf(dlpath, sizeof(dlpath), "%s%s%s%s", p ? p : "", p ? "\\" : "", name, SO_EXT);
+ }
+#endif
+
+ if (strpbrk(name, "()[]!@#$%^&/*;.,'?\\"))
+ {
+ errmsg= "invalid plugin name";
+ goto err;
+ }
+
+
+ /* Open new dll handle */
+ if (!(dlhandle= dlopen((const char *)dlpath, RTLD_NOW)))
+ {
+#ifdef _WIN32
+ char winmsg[255];
+ size_t len;
+ winmsg[0] = 0;
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ winmsg, 255, NULL);
+ len= strlen(winmsg);
+ while (len > 0 && (winmsg[len - 1] == '\n' || winmsg[len - 1] == '\r'))
+ len--;
+ if (len)
+ winmsg[len] = 0;
+ snprintf(errbuf, sizeof(errbuf), "%s Library path is '%s'", winmsg, dlpath);
+ errmsg= errbuf;
+#else
+ errmsg= dlerror();
+#endif
+ goto err;
+ }
+
+
+ if (!(sym= dlsym(dlhandle, plugin_declarations_sym)))
+ {
+ errmsg= "not a plugin";
+ (void)dlclose(dlhandle);
+ goto err;
+ }
+
+ plugin= (struct st_mysql_client_plugin*)sym;
+
+ if (type >=0 && type != plugin->type)
+ {
+ errmsg= "type mismatch";
+ goto err;
+ }
+
+ if (strcmp(name, plugin->name))
+ {
+ errmsg= "name mismatch";
+ goto err;
+ }
+
+ if (type < 0 && find_plugin(name, plugin->type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ plugin= add_plugin(mysql, plugin, dlhandle, argc, args);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ return plugin;
+
+err:
+ if (dlhandle)
+ dlclose(dlhandle);
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, errmsg);
+ return NULL;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin * STDCALL
+mysql_load_plugin(MYSQL *mysql, const char *name, int type, int argc, ...)
+{
+ struct st_mysql_client_plugin *p;
+ va_list args;
+ va_start(args, argc);
+ p= mysql_load_plugin_v(mysql, name, type, argc, args);
+ va_end(args);
+ return p;
+}
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin * STDCALL
+mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
+{
+ struct st_mysql_client_plugin *p;
+ int plugin_nr= get_plugin_nr(type);
+
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ if (plugin_nr == -1)
+ {
+ my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, "invalid type");
+ }
+
+ if ((p= find_plugin(name, type)))
+ return p;
+
+ /* not found, load it */
+ return mysql_load_plugin(mysql, name, type, 0);
+}
+
diff --git a/libmariadb/libmariadb/ma_compress.c b/libmariadb/libmariadb/ma_compress.c
new file mode 100644
index 00000000..002246e9
--- /dev/null
+++ b/libmariadb/libmariadb/ma_compress.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016, 2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Initially Written by Sinisa Milivojevic <sinisa@coresinc.com> */
+
+#include <ma_global.h>
+#ifdef HAVE_COMPRESS
+#include <mysql.h>
+#include <ma_common.h>
+#include <ma_sys.h>
+#include <ma_string.h>
+
+const char *compression_algorithms[] =
+{
+ "none",
+ "zlib",
+ "zstd",
+ "unknown"
+};
+
+const char *_mariadb_compression_algorithm_str(enum enum_ma_compression_algorithm algorithm)
+{
+ switch(algorithm) {
+ case COMPRESSION_NONE:
+ case COMPRESSION_ZLIB:
+ case COMPRESSION_ZSTD:
+ return compression_algorithms[algorithm] ;
+ default:
+ return compression_algorithms[COMPRESSION_UNKNOWN];
+ }
+}
+/*
+** This replaces the packet with a compressed packet
+** Returns 1 on error
+** *complen is 0 if the packet wasn't compressed
+*/
+
+my_bool _mariadb_compress(NET *net, unsigned char *packet, size_t *len, size_t *complen)
+{
+ if (*len < MIN_COMPRESS_LENGTH ||
+ !compression_plugin(net))
+ *complen=0;
+ else
+ {
+ unsigned char *compbuf=_mariadb_compress_alloc(net,packet,len,complen);
+ if (!compbuf)
+ return *complen ? 0 : 1;
+ memcpy(packet,compbuf,*len);
+ free(compbuf);
+ }
+ return 0;
+}
+
+unsigned char *_mariadb_compress_alloc(NET *net, const unsigned char *packet, size_t *len, size_t *complen)
+{
+ unsigned char *compbuf;
+ *complen = *len * 120 / 100 + 12;
+
+ if (!(compbuf = (unsigned char *) malloc(*complen)))
+ return 0; /* Not enough memory */
+
+ if (compression_plugin(net)->compress(compression_ctx(net), (void *)compbuf, complen, (void *)packet, *len))
+ {
+ free(compbuf);
+ return 0;
+ }
+
+ if (*complen >= *len)
+ {
+ *complen=0;
+ free(compbuf);
+ return 0;
+ }
+
+ swap(size_t,*len,*complen); /* *len is now packet length */
+ return compbuf;
+}
+
+my_bool _mariadb_uncompress (NET *net, unsigned char *packet, size_t *len, size_t *complen)
+{
+ if (*complen) /* If compressed */
+ {
+ unsigned char *compbuf = (unsigned char *) malloc (*complen);
+ if (!compbuf)
+ return 1; /* Not enough memory */
+ if (compression_plugin(net)->decompress(compression_ctx(net), compbuf, complen, packet, len))
+ { /* Probably wrong packet */
+ free(compbuf);
+ return 1;
+ }
+ *len = *complen;
+ memcpy(packet,compbuf,*len);
+ free(compbuf);
+ }
+ else *complen= *len;
+ return 0;
+}
+#endif /* HAVE_COMPRESS */
diff --git a/libmariadb/libmariadb/ma_context.c b/libmariadb/libmariadb/ma_context.c
new file mode 100644
index 00000000..222dbe28
--- /dev/null
+++ b/libmariadb/libmariadb/ma_context.c
@@ -0,0 +1,728 @@
+/*
+ Copyright 2011, 2012 Kristian Nielsen and Monty Program Ab
+ 2016 MariaDB Corporation AB
+
+ This file is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ Implementation of async context spawning using Posix ucontext and
+ swapcontext().
+*/
+
+#include "ma_global.h"
+#include "ma_string.h"
+#include "ma_context.h"
+
+#ifdef HAVE_VALGRIND
+#include <valgrind/valgrind.h>
+#endif
+
+#ifdef MY_CONTEXT_USE_UCONTEXT
+
+typedef void (*uc_func_t)(void);
+
+/*
+ The makecontext() only allows to pass integers into the created context :-(
+ We want to pass pointers, so we do it this kinda hackish way.
+ Anyway, it should work everywhere, and at least it does not break strict
+ aliasing.
+*/
+union pass_void_ptr_as_2_int {
+ int a[2];
+ void *p;
+};
+
+/*
+ We use old-style function definition here, as this is passed to
+ makecontext(). And the type of the makecontext() argument does not match
+ the actual type (as the actual type can differ from call to call).
+*/
+static void
+my_context_spawn_internal(int i0, int i1)
+{
+ int err;
+ struct my_context *c;
+ union pass_void_ptr_as_2_int u;
+
+ u.a[0]= i0;
+ u.a[1]= i1;
+ c= (struct my_context *)u.p;
+
+ (*c->user_func)(c->user_data);
+ c->active= 0;
+ err= setcontext(&c->base_context);
+ fprintf(stderr, "Aieie, setcontext() failed: %d (errno=%d)\n", err, errno);
+}
+
+
+int
+my_context_continue(struct my_context *c)
+{
+ int err;
+
+ if (!c->active)
+ return 0;
+
+ err= swapcontext(&c->base_context, &c->spawned_context);
+ if (err)
+ {
+ fprintf(stderr, "Aieie, swapcontext() failed: %d (errno=%d)\n",
+ err, errno);
+ return -1;
+ }
+
+ return c->active;
+}
+
+
+int
+my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
+{
+ int err;
+ union pass_void_ptr_as_2_int u;
+
+ err= getcontext(&c->spawned_context);
+ if (err)
+ return -1;
+ c->spawned_context.uc_stack.ss_sp= c->stack;
+ c->spawned_context.uc_stack.ss_size= c->stack_size;
+ c->spawned_context.uc_link= NULL;
+ c->user_func= f;
+ c->user_data= d;
+ c->active= 1;
+ u.p= c;
+ makecontext(&c->spawned_context, (uc_func_t)my_context_spawn_internal, 2,
+ u.a[0], u.a[1]);
+
+ return my_context_continue(c);
+}
+
+
+int
+my_context_yield(struct my_context *c)
+{
+ int err;
+
+ if (!c->active)
+ return -1;
+
+ err= swapcontext(&c->spawned_context, &c->base_context);
+ if (err)
+ return -1;
+ return 0;
+}
+
+int
+my_context_init(struct my_context *c, size_t stack_size)
+{
+#if SIZEOF_CHARP > SIZEOF_INT*2
+#error Error: Unable to store pointer in 2 ints on this architecture
+#endif
+
+ memset(c, 0, sizeof(*c));
+ if (!(c->stack= malloc(stack_size)))
+ return -1; /* Out of memory */
+ c->stack_size= stack_size;
+#ifdef HAVE_VALGRIND
+ c->valgrind_stack_id=
+ VALGRIND_STACK_REGISTER(c->stack, ((unsigned char *)(c->stack))+stack_size);
+#endif
+ return 0;
+}
+
+void
+my_context_destroy(struct my_context *c)
+{
+ if (c->stack)
+ {
+#ifdef HAVE_VALGRIND
+ VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id);
+#endif
+ free(c->stack);
+ }
+}
+
+#endif /* MY_CONTEXT_USE_UCONTEXT */
+
+
+#ifdef MY_CONTEXT_USE_X86_64_GCC_ASM
+/*
+ GCC-amd64 implementation of my_context.
+
+ This is slightly optimized in the common case where we never yield
+ (eg. fetch next row and it is already fully received in buffer). In this
+ case we do not need to restore registers at return (though we still need to
+ save them as we cannot know if we will yield or not in advance).
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ Layout of saved registers etc.
+ Since this is accessed through gcc inline assembler, it is simpler to just
+ use numbers than to try to define nice constants or structs.
+
+ 0 0 %rsp
+ 1 8 %rbp
+ 2 16 %rbx
+ 3 24 %r12
+ 4 32 %r13
+ 5 40 %r14
+ 6 48 %r15
+ 7 56 %rip for done
+ 8 64 %rip for yield/continue
+*/
+
+int
+my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
+{
+ int ret;
+
+ /*
+ There are 6 callee-save registers we need to save and restore when
+ suspending and continuing, plus stack pointer %rsp and instruction pointer
+ %rip.
+
+ However, if we never suspend, the user-supplied function will in any case
+ restore the 6 callee-save registers, so we can avoid restoring them in
+ this case.
+ */
+ __asm__ __volatile__
+ (
+ "movq %%rsp, (%[save])\n\t"
+ "movq %[stack], %%rsp\n\t"
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 && !defined(__INTEL_COMPILER)
+ /*
+ This emits a DWARF DW_CFA_undefined directive to make the return address
+ undefined. This indicates that this is the top of the stack frame, and
+ helps tools that use DWARF stack unwinding to obtain stack traces.
+ (I use numeric constant to avoid a dependency on libdwarf includes).
+ */
+ ".cfi_escape 0x07, 16\n\t"
+#endif
+ "movq %%rbp, 8(%[save])\n\t"
+ "movq %%rbx, 16(%[save])\n\t"
+ "movq %%r12, 24(%[save])\n\t"
+ "movq %%r13, 32(%[save])\n\t"
+ "movq %%r14, 40(%[save])\n\t"
+ "movq %%r15, 48(%[save])\n\t"
+ "leaq 1f(%%rip), %%rax\n\t"
+ "leaq 2f(%%rip), %%rcx\n\t"
+ "movq %%rax, 56(%[save])\n\t"
+ "movq %%rcx, 64(%[save])\n\t"
+ /*
+ Constraint below puts the argument to the user function into %rdi, as
+ needed for the calling convention.
+ */
+ "callq *%[f]\n\t"
+ "jmpq *56(%[save])\n"
+ /*
+ Come here when operation is done.
+ We do not need to restore callee-save registers, as the called function
+ will do this for us if needed.
+ */
+ "1:\n\t"
+ "movq (%[save]), %%rsp\n\t"
+ "xorl %[ret], %[ret]\n\t"
+ "jmp 3f\n"
+ /* Come here when operation was suspended. */
+ "2:\n\t"
+ "movl $1, %[ret]\n"
+ "3:\n"
+ : [ret] "=a" (ret),
+ [f] "+S" (f),
+ /* Need this in %rdi to follow calling convention. */
+ [d] "+D" (d)
+ : [stack] "a" (c->stack_top),
+ /* Need this in callee-save register to preserve in function call. */
+ [save] "b" (&c->save[0])
+ : "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc"
+ );
+
+ return ret;
+}
+
+int
+my_context_continue(struct my_context *c)
+{
+ int ret;
+
+ __asm__ __volatile__
+ (
+ "movq (%[save]), %%rax\n\t"
+ "movq %%rsp, (%[save])\n\t"
+ "movq %%rax, %%rsp\n\t"
+ "movq 8(%[save]), %%rax\n\t"
+ "movq %%rbp, 8(%[save])\n\t"
+ "movq %%rax, %%rbp\n\t"
+ "movq 24(%[save]), %%rax\n\t"
+ "movq %%r12, 24(%[save])\n\t"
+ "movq %%rax, %%r12\n\t"
+ "movq 32(%[save]), %%rax\n\t"
+ "movq %%r13, 32(%[save])\n\t"
+ "movq %%rax, %%r13\n\t"
+ "movq 40(%[save]), %%rax\n\t"
+ "movq %%r14, 40(%[save])\n\t"
+ "movq %%rax, %%r14\n\t"
+ "movq 48(%[save]), %%rax\n\t"
+ "movq %%r15, 48(%[save])\n\t"
+ "movq %%rax, %%r15\n\t"
+
+ "leaq 1f(%%rip), %%rax\n\t"
+ "leaq 2f(%%rip), %%rcx\n\t"
+ "movq %%rax, 56(%[save])\n\t"
+ "movq 64(%[save]), %%rax\n\t"
+ "movq %%rcx, 64(%[save])\n\t"
+
+ "movq 16(%[save]), %%rcx\n\t"
+ "movq %%rbx, 16(%[save])\n\t"
+ "movq %%rcx, %%rbx\n\t"
+
+ "jmpq *%%rax\n"
+ /*
+ Come here when operation is done.
+ Be sure to use the same callee-save register for %[save] here and in
+ my_context_spawn(), so we preserve the value correctly at this point.
+ */
+ "1:\n\t"
+ "movq (%[save]), %%rsp\n\t"
+ "movq 8(%[save]), %%rbp\n\t"
+ /* %rbx is preserved from my_context_spawn() in this case. */
+ "movq 24(%[save]), %%r12\n\t"
+ "movq 32(%[save]), %%r13\n\t"
+ "movq 40(%[save]), %%r14\n\t"
+ "movq 48(%[save]), %%r15\n\t"
+ "xorl %[ret], %[ret]\n\t"
+ "jmp 3f\n"
+ /* Come here when operation is suspended. */
+ "2:\n\t"
+ "movl $1, %[ret]\n"
+ "3:\n"
+ : [ret] "=a" (ret)
+ : /* Need this in callee-save register to preserve in function call. */
+ [save] "b" (&c->save[0])
+ : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "memory", "cc"
+ );
+
+ return ret;
+}
+
+int
+my_context_yield(struct my_context *c)
+{
+ uint64_t *save= &c->save[0];
+ __asm__ __volatile__
+ (
+ "movq (%[save]), %%rax\n\t"
+ "movq %%rsp, (%[save])\n\t"
+ "movq %%rax, %%rsp\n\t"
+ "movq 8(%[save]), %%rax\n\t"
+ "movq %%rbp, 8(%[save])\n\t"
+ "movq %%rax, %%rbp\n\t"
+ "movq 16(%[save]), %%rax\n\t"
+ "movq %%rbx, 16(%[save])\n\t"
+ "movq %%rax, %%rbx\n\t"
+ "movq 24(%[save]), %%rax\n\t"
+ "movq %%r12, 24(%[save])\n\t"
+ "movq %%rax, %%r12\n\t"
+ "movq 32(%[save]), %%rax\n\t"
+ "movq %%r13, 32(%[save])\n\t"
+ "movq %%rax, %%r13\n\t"
+ "movq 40(%[save]), %%rax\n\t"
+ "movq %%r14, 40(%[save])\n\t"
+ "movq %%rax, %%r14\n\t"
+ "movq 48(%[save]), %%rax\n\t"
+ "movq %%r15, 48(%[save])\n\t"
+ "movq %%rax, %%r15\n\t"
+ "movq 64(%[save]), %%rax\n\t"
+ "leaq 1f(%%rip), %%rcx\n\t"
+ "movq %%rcx, 64(%[save])\n\t"
+
+ "jmpq *%%rax\n"
+
+ "1:\n"
+ : [save] "+D" (save)
+ :
+ : "rax", "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc"
+ );
+ return 0;
+}
+
+int
+my_context_init(struct my_context *c, size_t stack_size)
+{
+ memset(c, 0, sizeof(*c));
+
+ if (!(c->stack_bot= malloc(stack_size)))
+ return -1; /* Out of memory */
+ /*
+ The x86_64 ABI specifies 16-byte stack alignment.
+ Also put two zero words at the top of the stack.
+ */
+ c->stack_top= (void *)
+ (( ((intptr)c->stack_bot + stack_size) & ~(intptr)0xf) - 16);
+ memset(c->stack_top, 0, 16);
+
+#ifdef HAVE_VALGRIND
+ c->valgrind_stack_id=
+ VALGRIND_STACK_REGISTER(c->stack_bot, c->stack_top);
+#endif
+ return 0;
+}
+
+void
+my_context_destroy(struct my_context *c)
+{
+ if (c->stack_bot)
+ {
+ free(c->stack_bot);
+#ifdef HAVE_VALGRIND
+ VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id);
+#endif
+ }
+}
+
+#endif /* MY_CONTEXT_USE_X86_64_GCC_ASM */
+
+
+#ifdef MY_CONTEXT_USE_I386_GCC_ASM
+/*
+ GCC-i386 implementation of my_context.
+
+ This is slightly optimized in the common case where we never yield
+ (eg. fetch next row and it is already fully received in buffer). In this
+ case we do not need to restore registers at return (though we still need to
+ save them as we cannot know if we will yield or not in advance).
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ Layout of saved registers etc.
+ Since this is accessed through gcc inline assembler, it is simpler to just
+ use numbers than to try to define nice constants or structs.
+
+ 0 0 %esp
+ 1 4 %ebp
+ 2 8 %ebx
+ 3 12 %esi
+ 4 16 %edi
+ 5 20 %eip for done
+ 6 24 %eip for yield/continue
+*/
+
+int
+my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
+{
+ int ret;
+
+ /*
+ There are 4 callee-save registers we need to save and restore when
+ suspending and continuing, plus stack pointer %esp and instruction pointer
+ %eip.
+
+ However, if we never suspend, the user-supplied function will in any case
+ restore the 4 callee-save registers, so we can avoid restoring them in
+ this case.
+ */
+ __asm__ __volatile__
+ (
+ "movl %%esp, (%[save])\n\t"
+ "movl %[stack], %%esp\n\t"
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 && !defined(__INTEL_COMPILER)
+ /*
+ This emits a DWARF DW_CFA_undefined directive to make the return address
+ undefined. This indicates that this is the top of the stack frame, and
+ helps tools that use DWARF stack unwinding to obtain stack traces.
+ (I use numeric constant to avoid a dependency on libdwarf includes).
+ */
+ ".cfi_escape 0x07, 8\n\t"
+#endif
+ /* Push the parameter on the stack. */
+ "pushl %[d]\n\t"
+ "movl %%ebp, 4(%[save])\n\t"
+ "movl %%ebx, 8(%[save])\n\t"
+ "movl %%esi, 12(%[save])\n\t"
+ "movl %%edi, 16(%[save])\n\t"
+ /* Get label addresses in -fPIC-compatible way (no pc-relative on 32bit) */
+ "call 1f\n"
+ "1:\n\t"
+ "popl %%eax\n\t"
+ "addl $(2f-1b), %%eax\n\t"
+ "movl %%eax, 20(%[save])\n\t"
+ "addl $(3f-2f), %%eax\n\t"
+ "movl %%eax, 24(%[save])\n\t"
+ "call *%[f]\n\t"
+ "jmp *20(%[save])\n"
+ /*
+ Come here when operation is done.
+ We do not need to restore callee-save registers, as the called function
+ will do this for us if needed.
+ */
+ "2:\n\t"
+ "movl (%[save]), %%esp\n\t"
+ "xorl %[ret], %[ret]\n\t"
+ "jmp 4f\n"
+ /* Come here when operation was suspended. */
+ "3:\n\t"
+ "movl $1, %[ret]\n"
+ "4:\n"
+ : [ret] "=a" (ret),
+ [f] "+c" (f),
+ [d] "+d" (d)
+ : [stack] "a" (c->stack_top),
+ /* Need this in callee-save register to preserve across function call. */
+ [save] "D" (&c->save[0])
+ : "memory", "cc"
+ );
+
+ return ret;
+}
+
+int
+my_context_continue(struct my_context *c)
+{
+ int ret;
+
+ __asm__ __volatile__
+ (
+ "movl (%[save]), %%eax\n\t"
+ "movl %%esp, (%[save])\n\t"
+ "movl %%eax, %%esp\n\t"
+ "movl 4(%[save]), %%eax\n\t"
+ "movl %%ebp, 4(%[save])\n\t"
+ "movl %%eax, %%ebp\n\t"
+ "movl 8(%[save]), %%eax\n\t"
+ "movl %%ebx, 8(%[save])\n\t"
+ "movl %%eax, %%ebx\n\t"
+ "movl 12(%[save]), %%eax\n\t"
+ "movl %%esi, 12(%[save])\n\t"
+ "movl %%eax, %%esi\n\t"
+
+ "movl 24(%[save]), %%eax\n\t"
+ "call 1f\n"
+ "1:\n\t"
+ "popl %%ecx\n\t"
+ "addl $(2f-1b), %%ecx\n\t"
+ "movl %%ecx, 20(%[save])\n\t"
+ "addl $(3f-2f), %%ecx\n\t"
+ "movl %%ecx, 24(%[save])\n\t"
+
+ /* Must restore %edi last as it is also our %[save] register. */
+ "movl 16(%[save]), %%ecx\n\t"
+ "movl %%edi, 16(%[save])\n\t"
+ "movl %%ecx, %%edi\n\t"
+
+ "jmp *%%eax\n"
+ /*
+ Come here when operation is done.
+ Be sure to use the same callee-save register for %[save] here and in
+ my_context_spawn(), so we preserve the value correctly at this point.
+ */
+ "2:\n\t"
+ "movl (%[save]), %%esp\n\t"
+ "movl 4(%[save]), %%ebp\n\t"
+ "movl 8(%[save]), %%ebx\n\t"
+ "movl 12(%[save]), %%esi\n\t"
+ "movl 16(%[save]), %%edi\n\t"
+ "xorl %[ret], %[ret]\n\t"
+ "jmp 4f\n"
+ /* Come here when operation is suspended. */
+ "3:\n\t"
+ "movl $1, %[ret]\n"
+ "4:\n"
+ : [ret] "=a" (ret)
+ : /* Need this in callee-save register to preserve in function call. */
+ [save] "D" (&c->save[0])
+ : "ecx", "edx", "memory", "cc"
+ );
+
+ return ret;
+}
+
+int
+my_context_yield(struct my_context *c)
+{
+ uint64_t *save= &c->save[0];
+ __asm__ __volatile__
+ (
+ "movl (%[save]), %%eax\n\t"
+ "movl %%esp, (%[save])\n\t"
+ "movl %%eax, %%esp\n\t"
+ "movl 4(%[save]), %%eax\n\t"
+ "movl %%ebp, 4(%[save])\n\t"
+ "movl %%eax, %%ebp\n\t"
+ "movl 8(%[save]), %%eax\n\t"
+ "movl %%ebx, 8(%[save])\n\t"
+ "movl %%eax, %%ebx\n\t"
+ "movl 12(%[save]), %%eax\n\t"
+ "movl %%esi, 12(%[save])\n\t"
+ "movl %%eax, %%esi\n\t"
+ "movl 16(%[save]), %%eax\n\t"
+ "movl %%edi, 16(%[save])\n\t"
+ "movl %%eax, %%edi\n\t"
+
+ "movl 24(%[save]), %%eax\n\t"
+ "call 1f\n"
+ "1:\n\t"
+ "popl %%ecx\n\t"
+ "addl $(2f-1b), %%ecx\n\t"
+ "movl %%ecx, 24(%[save])\n\t"
+
+ "jmp *%%eax\n"
+
+ "2:\n"
+ : [save] "+d" (save)
+ :
+ : "eax", "ecx", "memory", "cc"
+ );
+ return 0;
+}
+
+int
+my_context_init(struct my_context *c, size_t stack_size)
+{
+ memset(c, 0, sizeof(*c));
+ if (!(c->stack_bot= malloc(stack_size)))
+ return -1; /* Out of memory */
+ c->stack_top= (void *)
+ (( ((intptr)c->stack_bot + stack_size) & ~(intptr)0xf) - 16);
+ memset(c->stack_top, 0, 16);
+
+#ifdef HAVE_VALGRIND
+ c->valgrind_stack_id=
+ VALGRIND_STACK_REGISTER(c->stack_bot, c->stack_top);
+#endif
+ return 0;
+}
+
+void
+my_context_destroy(struct my_context *c)
+{
+ if (c->stack_bot)
+ {
+ free(c->stack_bot);
+#ifdef HAVE_VALGRIND
+ VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id);
+#endif
+ }
+}
+
+#endif /* MY_CONTEXT_USE_I386_GCC_ASM */
+
+
+#ifdef MY_CONTEXT_USE_WIN32_FIBERS
+int
+my_context_yield(struct my_context *c)
+{
+ c->return_value= 1;
+ SwitchToFiber(c->app_fiber);
+ return 0;
+}
+
+
+static void WINAPI
+my_context_trampoline(void *p)
+{
+ struct my_context *c= (struct my_context *)p;
+ /*
+ Reuse the Fiber by looping infinitely, each time we are scheduled we
+ spawn the appropriate function and switch back when it is done.
+
+ This way we avoid the overhead of CreateFiber() for every asynchronous
+ operation.
+ */
+ for(;;)
+ {
+ (*(c->user_func))(c->user_arg);
+ c->return_value= 0;
+ SwitchToFiber(c->app_fiber);
+ }
+}
+
+int
+my_context_init(struct my_context *c, size_t stack_size)
+{
+ memset(c, 0, sizeof(*c));
+ c->lib_fiber= CreateFiber(stack_size, my_context_trampoline, c);
+ if (c->lib_fiber)
+ return 0;
+ return -1;
+}
+
+void
+my_context_destroy(struct my_context *c)
+{
+ if (c->lib_fiber)
+ {
+ DeleteFiber(c->lib_fiber);
+ c->lib_fiber= NULL;
+ }
+}
+
+int
+my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
+{
+ c->user_func= f;
+ c->user_arg= d;
+ return my_context_continue(c);
+}
+
+int
+my_context_continue(struct my_context *c)
+{
+ void *current_fiber= IsThreadAFiber() ? GetCurrentFiber() : ConvertThreadToFiber(c);
+ c->app_fiber= current_fiber;
+ SwitchToFiber(c->lib_fiber);
+ return c->return_value;
+}
+
+#endif /* MY_CONTEXT_USE_WIN32_FIBERS */
+
+#ifdef MY_CONTEXT_DISABLE
+int
+my_context_continue(struct my_context *c)
+{
+ return -1;
+}
+
+
+int
+my_context_spawn(struct my_context *c, void (*f)(void *), void *d)
+{
+ return -1;
+}
+
+
+int
+my_context_yield(struct my_context *c)
+{
+ return -1;
+}
+
+int
+my_context_init(struct my_context *c, size_t stack_size)
+{
+ return -1; /* Out of memory */
+}
+
+void
+my_context_destroy(struct my_context *c)
+{
+}
+
+#endif
diff --git a/libmariadb/libmariadb/ma_decimal.c b/libmariadb/libmariadb/ma_decimal.c
new file mode 100644
index 00000000..de6062df
--- /dev/null
+++ b/libmariadb/libmariadb/ma_decimal.c
@@ -0,0 +1,479 @@
+/* Copyright (C) 2004 Sergei Golubchik
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*/
+
+/*
+=======================================================================
+ NOTE: this library implements SQL standard "exact numeric" type
+ and is not at all generic, but rather intentinally crippled to
+ follow the standard :)
+=======================================================================
+ Quoting the standard
+ (SQL:2003, Part 2 Foundations, aka ISO/IEC 9075-2:2003)
+
+4.4.2 Characteristics of numbers, page 27:
+
+ An exact numeric type has a precision P and a scale S. P is a positive
+ integer that determines the number of significant digits in a
+ particular radix R, where R is either 2 or 10. S is a non-negative
+ integer. Every value of an exact numeric type of scale S is of the
+ form n*10^{-S}, where n is an integer such that ?-R^P <= n <= R^P.
+
+ [...]
+
+ If an assignment of some number would result in a loss of its most
+ significant digit, an exception condition is raised. If least
+ significant digits are lost, implementation-defined rounding or
+ truncating occurs, with no exception condition being raised.
+
+ [...]
+
+ Whenever an exact or approximate numeric value is assigned to an exact
+ numeric value site, an approximation of its value that preserves
+ leading significant digits after rounding or truncating is represented
+ in the declared type of the target. The value is converted to have the
+ precision and scale of the target. The choice of whether to truncate
+ or round is implementation-defined.
+
+ [...]
+
+ All numeric values between the smallest and the largest value,
+ inclusive, in a given exact numeric type have an approximation
+ obtained by rounding or truncation for that type; it is
+ implementation-defined which other numeric values have such
+ approximations.
+
+5.3 <literal>, page 143
+
+ <exact numeric literal> ::=
+ <unsigned integer> [ <period> [ <unsigned integer> ] ]
+ | <period> <unsigned integer>
+
+6.1 <data type>, page 165:
+
+ 19) The <scale> of an <exact numeric type> shall not be greater than
+ the <precision> of the <exact numeric type>.
+
+ 20) For the <exact numeric type>s DECIMAL and NUMERIC:
+
+ a) The maximum value of <precision> is implementation-defined.
+ <precision> shall not be greater than this value.
+ b) The maximum value of <scale> is implementation-defined. <scale>
+ shall not be greater than this maximum value.
+
+ 21) NUMERIC specifies the data type exact numeric, with the decimal
+ precision and scale specified by the <precision> and <scale>.
+
+ 22) DECIMAL specifies the data type exact numeric, with the decimal
+ scale specified by the <scale> and the implementation-defined
+ decimal precision equal to or greater than the value of the
+ specified <precision>.
+
+6.26 <numeric value expression>, page 241:
+
+ 1) If the declared type of both operands of a dyadic arithmetic
+ operator is exact numeric, then the declared type of the result is
+ an implementation-defined exact numeric type, with precision and
+ scale determined as follows:
+
+ a) Let S1 and S2 be the scale of the first and second operands
+ respectively.
+ b) The precision of the result of addition and subtraction is
+ implementation-defined, and the scale is the maximum of S1 and S2.
+ c) The precision of the result of multiplication is
+ implementation-defined, and the scale is S1 + S2.
+ d) The precision and scale of the result of division are
+ implementation-defined.
+*/
+
+#include <ma_global.h>
+#include <ma_sys.h> /* for my_alloca */
+#include <ma_decimal.h>
+#include <mysql.h>
+#include <mariadb_rpl.h>
+#include <string.h>
+
+#ifdef WIN32
+#include <malloc.h>
+#endif
+
+typedef decimal_digit dec1;
+typedef longlong dec2;
+
+#define unlikely(A) (A)
+#define DIG_PER_DEC1 9
+#define DIG_MASK 100000000
+#define DIG_BASE 1000000000
+#define DIG_BASE2 LL(1000000000000000000)
+#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
+static const dec1 powers10[DIG_PER_DEC1+1]={
+ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
+static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
+
+#define sanity(d) DBUG_ASSERT((d)->len >0 && ((d)->buf[0] | \
+ (d)->buf[(d)->len-1] | 1))
+
+#define FIX_INTG_FRAC_ERROR(len, intg1, frac1, error) \
+ do \
+ { \
+ if (unlikely(intg1+frac1 > (len))) \
+ { \
+ if (unlikely(intg1 > (len))) \
+ { \
+ intg1=(len); \
+ frac1=0; \
+ error=E_DEC_OVERFLOW; \
+ } \
+ else \
+ { \
+ frac1=(len)-intg1; \
+ error=E_DEC_TRUNCATED; \
+ } \
+ } \
+ else \
+ error=E_DEC_OK; \
+ } while(0)
+
+#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
+ do \
+ { \
+ dec1 a=(from1)+(from2)+(carry); \
+ if (((carry)= a >= DIG_BASE)) /* no division here! */ \
+ a-=DIG_BASE; \
+ (to)=a; \
+ } while(0)
+
+#define ADD2(to, from1, from2, carry) \
+ do \
+ { \
+ dec1 a=(from1)+(from2)+(carry); \
+ if (((carry)= a >= DIG_BASE)) \
+ a-=DIG_BASE; \
+ if (unlikely(a >= DIG_BASE)) \
+ { \
+ a-=DIG_BASE; \
+ carry++; \
+ } \
+ (to)=a; \
+ } while(0)
+
+#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
+ do \
+ { \
+ dec1 a=(from1)-(from2)-(carry); \
+ if (((carry)= a < 0)) \
+ a+=DIG_BASE; \
+ (to)=a; \
+ } while(0)
+
+#define SUB2(to, from1, from2, carry) /* to=from1-from2 */ \
+ do \
+ { \
+ dec1 a=(from1)-(from2)-(carry); \
+ if (((carry)= a < 0)) \
+ a+=DIG_BASE; \
+ if (unlikely(a < 0)) \
+ { \
+ a+=DIG_BASE; \
+ carry++; \
+ } \
+ (to)=a; \
+ } while(0)
+
+/*
+ Convert decimal to its printable string representation
+
+ SYNOPSIS
+ decimal2string()
+ from - value to convert
+ to - points to buffer where string representation should be stored
+ *to_len - in: size of to buffer
+ out: length of the actually written string
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
+*/
+
+int decimal2string(decimal *from, char *to, int *to_len)
+{
+ int len, intg=from->intg, frac=from->frac, i;
+ int error=E_DEC_OK;
+ char *s=to;
+ dec1 *buf, *buf0=from->buf, tmp;
+
+ DBUG_ASSERT(*to_len >= 2+from->sign);
+
+ /* removing leading zeroes */
+ i=((intg-1) % DIG_PER_DEC1)+1;
+ while (intg > 0 && *buf0 == 0)
+ {
+ intg-=i;
+ i=DIG_PER_DEC1;
+ buf0++;
+ }
+ if (intg > 0)
+ {
+ for (i=(intg-1) % DIG_PER_DEC1; *buf0 < powers10[i--]; intg--) {}
+ DBUG_ASSERT(intg > 0);
+ }
+ else
+ intg=0;
+ if (unlikely(intg+frac==0))
+ {
+ intg=1;
+ tmp=0;
+ buf0=&tmp;
+ }
+
+ len= from->sign + intg + test(frac) + frac;
+ if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
+ {
+ int i=len-*to_len;
+ error= (frac && i <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
+ if (frac && i >= frac + 1) i--;
+ if (i > frac)
+ {
+ intg-= i-frac;
+ frac= 0;
+ }
+ else
+ frac-=i;
+ len= from->sign + intg + test(frac) + frac;
+ }
+ *to_len=len;
+ s[len]=0;
+
+ if (from->sign)
+ *s++='-';
+
+ if (frac)
+ {
+ char *s1=s+intg;
+ buf=buf0+ROUND_UP(intg);
+ *s1++='.';
+ for (; frac>0; frac-=DIG_PER_DEC1)
+ {
+ dec1 x=*buf++;
+ for (i=min(frac, DIG_PER_DEC1); i; i--)
+ {
+ dec1 y=x/DIG_MASK;
+ *s1++='0'+(uchar)y;
+ x-=y*DIG_MASK;
+ x*=10;
+ }
+ }
+ }
+
+ s+=intg;
+ for (buf=buf0+ROUND_UP(intg); intg>0; intg-=DIG_PER_DEC1)
+ {
+ dec1 x=*--buf;
+ for (i=min(intg, DIG_PER_DEC1); i; i--)
+ {
+ dec1 y=x/10;
+ *--s='0'+(uchar)(x-y*10);
+ x=y;
+ }
+ }
+ return error;
+}
+
+/*
+ Convert string to decimal
+
+ SYNOPSIS
+ str2decl()
+ from - value to convert
+ to - decimal where where the result will be stored
+ to->buf and to->len must be set.
+ end - if not NULL, *end will be set to the char where
+ conversion ended
+ fixed - use to->intg, to->frac as limits for input number
+
+ NOTE
+ to->intg and to->frac can be modified even when fixed=1
+ (but only decreased, in this case)
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
+*/
+
+/*
+ Convert decimal to its binary fixed-length representation
+ two representations of the same length can be compared with memcmp
+ with the correct -1/0/+1 result
+
+ SYNOPSIS
+ decimal2bin()
+ from - value to convert
+ to - points to buffer where string representation should be stored
+ precision/scale - see decimal_bin_size() below
+
+ NOTE
+ the buffer is assumed to be of the size decimal_bin_size(precision, scale)
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
+*/
+
+/*
+ Restores decimal from its binary fixed-length representation
+
+ SYNOPSIS
+ bin2decimal()
+ from - value to convert
+ to - result
+ precision/scale - see decimal_bin_size() below
+
+ NOTE
+ see decimal2bin()
+ the buffer is assumed to be of the size decimal_bin_size(precision, scale)
+
+ RETURN VALUE
+ E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
+*/
+
+int bin2decimal(const char *from, decimal *to, int precision, int scale)
+{
+ int error=E_DEC_OK,
+ intg= precision - scale,
+ intg0= intg / DIG_PER_DEC1,
+ frac0= scale / DIG_PER_DEC1,
+ intg0x= intg - intg0 * DIG_PER_DEC1,
+ frac0x= scale - frac0*DIG_PER_DEC1,
+ intg1= intg0 + (intg0x > 0),
+ frac1= frac0 + (frac0x > 0),
+ tmp_size= decimal_bin_size(precision, scale);
+ char *tmp;
+ dec1 *buf= to->buf,
+ mask=(*from & 0x80) ? 0 : -1;
+ char *stop;
+
+ /* Initial implementation from Sergei modified "from" buffer, (which errored
+ in binlog api when verifying checksum), so we declare from as read only and use
+ a stack buffer instead */
+ tmp= (char *)alloca(tmp_size);
+ memcpy(tmp, from, tmp_size);
+ *tmp^= 0x80; /* remove sign bit */
+ from= tmp;
+
+ sanity(to);
+
+ FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error);
+ if (unlikely(error))
+ {
+ if (intg1 < intg0+(intg0x>0))
+ {
+ from+= dig2bytes[intg0x] + sizeof(dec1)*(intg0 - intg1);
+ frac0= frac0x= intg0x= 0;
+ intg0= intg1;
+ }
+ else
+ {
+ frac0x= 0;
+ frac0= frac1;
+ }
+ }
+
+ to->sign= (mask != 0);
+ to->intg= intg0 * DIG_PER_DEC1 + intg0x;
+ to->frac= frac0 * DIG_PER_DEC1 + frac0x;
+
+ if (intg0x)
+ {
+ int i= dig2bytes[intg0x];
+ dec1 x= 0;
+ switch (i)
+ {
+ case 1: x=myisam_sint1korr(from); break;
+ case 2: x=myisam_sint2korr(from); break;
+ case 3: x=myisam_sint3korr(from); break;
+ case 4: x=myisam_sint4korr(from); break;
+ default: DBUG_ASSERT(0); x= 0;
+ }
+ from+=i;
+ *buf=x ^ mask;
+ if (buf > to->buf || *buf != 0)
+ buf++;
+ else
+ to->intg-=intg0x;
+ }
+ for (stop=(char *)from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1))
+ {
+ DBUG_ASSERT(sizeof(dec1) == 4);
+ *buf=myisam_sint4korr(from) ^ mask;
+ if (buf > to->buf || *buf != 0)
+ buf++;
+ else
+ to->intg-=DIG_PER_DEC1;
+ }
+ DBUG_ASSERT(to->intg >=0);
+ for (stop=(char *)from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1))
+ {
+ DBUG_ASSERT(sizeof(dec1) == 4);
+ *buf=myisam_sint4korr(from) ^ mask;
+ buf++;
+ }
+ if (frac0x)
+ {
+ int i=dig2bytes[frac0x];
+ dec1 x= 0;
+ switch (i)
+ {
+ case 1: x=myisam_sint1korr(from); break;
+ case 2: x=myisam_sint2korr(from); break;
+ case 3: x=myisam_sint3korr(from); break;
+ case 4: x=myisam_sint4korr(from); break;
+ default: DBUG_ASSERT(0); x= 0;
+ }
+ *buf= (x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
+ buf++;
+ }
+ return error;
+}
+
+/*
+ Returns the size of array to hold a decimal with given precision and scale
+
+ RETURN VALUE
+ size in dec1
+ (multiply by sizeof(dec1) to get the size if bytes)
+*/
+
+int decimal_size(int precision, int scale)
+{
+ DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
+ return ROUND_UP(precision-scale)+ROUND_UP(scale);
+}
+
+/*
+ Returns the size of array to hold a binary representation of a decimal
+
+ RETURN VALUE
+ size in bytes
+*/
+
+int decimal_bin_size(int precision, int scale)
+{
+ int intg=precision-scale,
+ intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1,
+ intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1;
+
+ DBUG_ASSERT(scale >= 0 && precision > 0 && scale <= precision);
+ return intg0*sizeof(dec1)+dig2bytes[intg0x]+
+ frac0*sizeof(dec1)+dig2bytes[frac0x];
+}
diff --git a/libmariadb/libmariadb/ma_default.c b/libmariadb/libmariadb/ma_default.c
new file mode 100644
index 00000000..0f6921c1
--- /dev/null
+++ b/libmariadb/libmariadb/ma_default.c
@@ -0,0 +1,370 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include "ma_string.h"
+#include <ctype.h>
+#include "mariadb_ctype.h"
+#include <mysql.h>
+#include <ma_common.h>
+#include <mariadb/ma_io.h>
+
+#ifdef _WIN32
+#include <io.h>
+#include "shlwapi.h"
+
+#define access _access
+
+static const char *ini_exts[]= {"ini", "cnf", 0};
+#define R_OK 4
+#else
+#include <unistd.h>
+static const char *ini_exts[]= {"cnf", 0};
+#endif
+
+char **configuration_dirs= NULL;
+#define MAX_CONFIG_DIRS 6
+
+my_bool _mariadb_read_options(MYSQL *mysql,
+ const char *config_dir,
+ const char *config_file,
+ const char *group,
+ unsigned int recursion);
+
+static int add_cfg_dir(char **cfg_dirs, const char *directory)
+{
+ int i;
+
+ for (i = 0; i < MAX_CONFIG_DIRS && cfg_dirs[i]; i++)
+ if (!strcmp(cfg_dirs[i], directory)) /* already present */
+ return 0;
+
+ if (i < MAX_CONFIG_DIRS) {
+ cfg_dirs[i]= strdup(directory);
+ return 0;
+ }
+ return 1;
+}
+
+void release_configuration_dirs()
+{
+ if (configuration_dirs)
+ {
+ int i= 0;
+ while (configuration_dirs[i])
+ free(configuration_dirs[i++]);
+ free(configuration_dirs);
+ }
+}
+
+char **get_default_configuration_dirs()
+{
+#ifdef _WIN32
+ char dirname[FN_REFLEN];
+#endif
+ char *env;
+
+ configuration_dirs= (char **)calloc(1, (MAX_CONFIG_DIRS + 1) * sizeof(char *));
+ if (!configuration_dirs)
+ goto end;
+
+#ifdef _WIN32
+ /* On Windows operating systems configuration files are stored in
+ 1. System Windows directory
+ 2. System directory
+ 3. Windows directory
+ 4. C:\
+ */
+
+ if (!GetSystemWindowsDirectory(dirname, FN_REFLEN) ||
+ add_cfg_dir(configuration_dirs, dirname))
+ goto error;
+
+ if (!GetWindowsDirectory(dirname, FN_REFLEN) ||
+ add_cfg_dir(configuration_dirs, dirname))
+ goto error;
+
+ if (add_cfg_dir(configuration_dirs, "C:"))
+ goto error;
+
+ if (GetModuleFileName(NULL, dirname, FN_REFLEN))
+ {
+ PathRemoveFileSpec(dirname);
+ if (add_cfg_dir(configuration_dirs, dirname))
+ goto error;
+ }
+#else
+ /* on *nix platforms configuration files are stored in
+ 1. SYSCONFDIR (if build happens inside server package, or
+ -DDEFAULT_SYSCONFDIR was specified
+ 2. /etc
+ 3. /etc/mysql
+ */
+#ifdef DEFAULT_SYSCONFDIR
+ if (add_cfg_dir(configuration_dirs, DEFAULT_SYSCONFDIR))
+ goto error;
+#else
+ if (add_cfg_dir(configuration_dirs, "/etc"))
+ goto error;
+ if (add_cfg_dir(configuration_dirs, "/etc/mysql"))
+ goto error;
+#endif
+#endif
+ /* CONC-537: Read configuration files from MYSQL_HOME directory only if
+ MARIADB_HOME was not set */
+ if (!(env= getenv("MARIADB_HOME")))
+ env= getenv("MYSQL_HOME");
+ if (env && add_cfg_dir(configuration_dirs, env))
+ goto error;
+end:
+ return configuration_dirs;
+error:
+ return NULL;
+}
+
+extern my_bool _mariadb_set_conf_option(MYSQL *mysql, const char *config_option, const char *config_value);
+
+static my_bool is_group(char *ptr, const char **groups)
+{
+ while (*groups)
+ {
+ if (!strcmp(ptr, *groups))
+ return 1;
+ groups++;
+ }
+ return 0;
+}
+
+static my_bool _mariadb_read_options_from_file(MYSQL *mysql,
+ const char *config_file,
+ const char *group,
+ unsigned int recursion)
+{
+ my_bool read_values= 0, found_group= 0, is_escaped= 0, is_quoted= 0;
+ char buff[4096],*ptr,*end,*value, *key= 0, *optval;
+ MA_FILE *file= NULL;
+ my_bool rc= 1;
+ const char *groups[5]= {"client",
+ "client-server",
+ "client-mariadb",
+ group,
+ NULL};
+ my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
+
+
+ /* if a plugin registered a hook we will call this hook, otherwise
+ * default (_mariadb_set_conf_option) will be called */
+ if (mysql->options.extension && mysql->options.extension->set_option)
+ set_option= mysql->options.extension->set_option;
+ else
+ set_option= _mariadb_set_conf_option;
+
+ if (!(file = ma_open(config_file, "r", NULL)))
+ goto err;
+
+ while (ma_gets(buff,sizeof(buff)-1,file))
+ {
+ key= 0;
+ /* Ignore comment and empty lines */
+ for (ptr=buff ; isspace(*ptr) ; ptr++ );
+ if (!is_escaped && (*ptr == '\"' || *ptr== '\''))
+ {
+ is_quoted= !is_quoted;
+ continue;
+ }
+ /* CONC- 327: !includedir and !include */
+ if (*ptr == '!')
+ {
+ char *val;
+ ptr++;
+ if (!(val= strchr(ptr, ' ')))
+ continue;
+ *val++= 0;
+ end= strchr(val, 0);
+ for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
+ *end= 0;
+ if (!strcmp(ptr, "includedir"))
+ _mariadb_read_options(mysql, (const char *)val, NULL, group, recursion + 1);
+ else if (!strcmp(ptr, "include"))
+ _mariadb_read_options(mysql, NULL, (const char *)val, group, recursion + 1);
+ continue;
+ }
+ if (*ptr == '#' || *ptr == ';' || !*ptr)
+ continue;
+ is_escaped= (*ptr == '\\');
+ if (*ptr == '[') /* Group name */
+ {
+ found_group=1;
+ if (!(end=(char *) strchr(++ptr,']')))
+ {
+ /* todo: set error */
+ goto err;
+ }
+ for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
+ end[0]=0;
+ read_values= is_group(ptr, groups);
+ continue;
+ }
+ if (!found_group)
+ {
+ /* todo: set error */
+ goto err;
+ }
+ if (!read_values)
+ continue;
+ if (!(end=value=strchr(ptr,'=')))
+ {
+ end=strchr(ptr, '\0'); /* Option without argument */
+ set_option(mysql, ptr, NULL);
+ }
+ if (!key)
+ key= ptr;
+ for ( ; isspace(end[-1]) ; end--) ;
+ *end= 0;
+ if (value)
+ {
+ /* Remove pre- and end space */
+ char *value_end;
+ *value= 0;
+ value++;
+ ptr= value;
+ for ( ; isspace(*value); value++) ;
+ value_end=strchr(value, '\0');
+ *value_end= 0;
+ optval= ptr;
+ for ( ; isspace(value_end[-1]) ; value_end--) ;
+ /* remove possible quotes */
+ if (*value == '\'' || *value == '\"')
+ {
+ value++;
+ if (value_end[-1] == '\'' || value_end[-1] == '\"')
+ value_end--;
+ }
+ if (value_end < value) /* Empty string */
+ value_end=value;
+ for ( ; value != value_end; value++)
+ {
+ if (*value == '\\' && value != value_end-1)
+ {
+ switch(*++value) {
+ case 'n':
+ *ptr++='\n';
+ break;
+ case 't':
+ *ptr++= '\t';
+ break;
+ case 'r':
+ *ptr++ = '\r';
+ break;
+ case 'b':
+ *ptr++ = '\b';
+ break;
+ case 's':
+ *ptr++= ' '; /* space */
+ break;
+ case '\"':
+ *ptr++= '\"';
+ break;
+ case '\'':
+ *ptr++= '\'';
+ break;
+ case '\\':
+ *ptr++= '\\';
+ break;
+ default: /* Unknown; Keep '\' */
+ *ptr++= '\\';
+ *ptr++= *value;
+ break;
+ }
+ }
+ else
+ *ptr++= *value;
+ }
+ *ptr=0;
+ set_option(mysql, key, optval);
+ key= optval= 0;
+ }
+ }
+ rc= 0;
+
+err:
+ if (file)
+ ma_close(file);
+ return rc;
+}
+
+
+my_bool _mariadb_read_options(MYSQL *mysql,
+ const char *config_dir,
+ const char *config_file,
+ const char *group,
+ unsigned int recursion)
+{
+ int i= 0,
+ exts,
+ errors= 0;
+ char filename[FN_REFLEN + 1];
+ unsigned int recursion_stop= 64;
+#ifndef _WIN32
+ char *env;
+#endif
+
+ if (recursion >= recursion_stop)
+ return 1;
+
+ if (config_file && config_file[0])
+ return _mariadb_read_options_from_file(mysql, config_file, group, recursion);
+
+ if (config_dir && config_dir[0])
+ {
+ for (exts= 0; ini_exts[exts]; exts++)
+ {
+ snprintf(filename, FN_REFLEN,
+ "%s%cmy.%s", config_dir, FN_LIBCHAR, ini_exts[exts]);
+ if (!access(filename, R_OK))
+ errors+= _mariadb_read_options_from_file(mysql, filename, group, recursion);
+ }
+ return errors;
+ }
+
+ for (i=0; i < MAX_CONFIG_DIRS && configuration_dirs[i]; i++)
+ {
+ for (exts= 0; ini_exts[exts]; exts++)
+ {
+ snprintf(filename, FN_REFLEN,
+ "%s%cmy.%s", configuration_dirs[i], FN_LIBCHAR, ini_exts[exts]);
+ if (!access(filename, R_OK))
+ errors+= _mariadb_read_options_from_file(mysql, filename, group, recursion);
+ }
+ }
+#ifndef _WIN32
+ /* special case: .my.cnf in Home directory */
+ if ((env= getenv("HOME")))
+ {
+ for (exts= 0; ini_exts[exts]; exts++)
+ {
+ snprintf(filename, FN_REFLEN,
+ "%s%c.my.%s", env, FN_LIBCHAR, ini_exts[exts]);
+ if (!access(filename, R_OK))
+ errors+= _mariadb_read_options_from_file(mysql, filename, group, recursion);
+ }
+ }
+#endif
+ return errors;
+}
diff --git a/libmariadb/libmariadb/ma_dtoa.c b/libmariadb/libmariadb/ma_dtoa.c
new file mode 100644
index 00000000..05ab0f0b
--- /dev/null
+++ b/libmariadb/libmariadb/ma_dtoa.c
@@ -0,0 +1,1924 @@
+/* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ 2016,2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; version 2
+ of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/****************************************************************
+
+ This file incorporates work covered by the following copyright and
+ permission notice:
+
+ The author of this software is David M. Gay.
+
+ Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose without fee is hereby granted, provided that this entire notice
+ is included in all copies of any software which is or includes a copy
+ or modification of this software and in all copies of the supporting
+ documentation for such software.
+
+ THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+
+ ***************************************************************/
+
+//#include "strings_def.h"
+//#include <my_base.h> /* for EOVERFLOW on Windows */
+#include <ma_global.h>
+#include <memory.h>
+#include "ma_string.h"
+
+/**
+ Appears to suffice to not call malloc() in most cases.
+ @todo
+ see if it is possible to get rid of malloc().
+ this constant is sufficient to avoid malloc() on all inputs I have tried.
+*/
+#define DTOA_BUFF_SIZE (460 * sizeof(void *))
+
+/* Magic value returned by dtoa() to indicate overflow */
+#define DTOA_OVERFLOW 9999
+
+static char *dtoa(double, int, int, int *, int *, char **, char *, size_t);
+static void dtoa_free(char *, char *, size_t);
+
+/**
+ @brief
+ Converts a given floating point number to a zero-terminated string
+ representation using the 'f' format.
+
+ @details
+ This function is a wrapper around dtoa() to do the same as
+ sprintf(to, "%-.*f", precision, x), though the conversion is usually more
+ precise. The only difference is in handling [-,+]infinity and nan values,
+ in which case we print '0\0' to the output string and indicate an overflow.
+
+ @param x the input floating point number.
+ @param precision the number of digits after the decimal point.
+ All properties of sprintf() apply:
+ - if the number of significant digits after the decimal
+ point is less than precision, the resulting string is
+ right-padded with zeros
+ - if the precision is 0, no decimal point appears
+ - if a decimal point appears, at least one digit appears
+ before it
+ @param to pointer to the output buffer. The longest string which
+ my_fcvt() can return is FLOATING_POINT_BUFFER bytes
+ (including the terminating '\0').
+ @param error if not NULL, points to a location where the status of
+ conversion is stored upon return.
+ FALSE successful conversion
+ TRUE the input number is [-,+]infinity or nan.
+ The output string in this case is always '0'.
+ @return number of written characters (excluding terminating '\0')
+*/
+
+size_t ma_fcvt(double x, int precision, char *to, my_bool *error)
+{
+ int decpt, sign, len, i;
+ char *res, *src, *end, *dst= to;
+ char buf[DTOA_BUFF_SIZE];
+ DBUG_ASSERT(precision >= 0 && precision < NOT_FIXED_DEC && to != NULL);
+
+ res= dtoa(x, 5, precision, &decpt, &sign, &end, buf, sizeof(buf));
+
+ if (decpt == DTOA_OVERFLOW)
+ {
+ dtoa_free(res, buf, sizeof(buf));
+ *to++= '0';
+ *to= '\0';
+ if (error != NULL)
+ *error= TRUE;
+ return 1;
+ }
+
+ src= res;
+ len= (int)(end - src);
+
+ if (sign)
+ *dst++= '-';
+
+ if (decpt <= 0)
+ {
+ *dst++= '0';
+ *dst++= '.';
+ for (i= decpt; i < 0; i++)
+ *dst++= '0';
+ }
+
+ for (i= 1; i <= len; i++)
+ {
+ *dst++= *src++;
+ if (i == decpt && i < len)
+ *dst++= '.';
+ }
+ while (i++ <= decpt)
+ *dst++= '0';
+
+ if (precision > 0)
+ {
+ if (len <= decpt)
+ *dst++= '.';
+
+ for (i= precision - MAX(0, (len - decpt)); i > 0; i--)
+ *dst++= '0';
+ }
+
+ *dst= '\0';
+ if (error != NULL)
+ *error= FALSE;
+
+ dtoa_free(res, buf, sizeof(buf));
+
+ return dst - to;
+}
+
+/**
+ @brief
+ Converts a given floating point number to a zero-terminated string
+ representation with a given field width using the 'e' format
+ (aka scientific notation) or the 'f' one.
+
+ @details
+ The format is chosen automatically to provide the most number of significant
+ digits (and thus, precision) with a given field width. In many cases, the
+ result is similar to that of sprintf(to, "%g", x) with a few notable
+ differences:
+ - the conversion is usually more precise than C library functions.
+ - there is no 'precision' argument. instead, we specify the number of
+ characters available for conversion (i.e. a field width).
+ - the result never exceeds the specified field width. If the field is too
+ short to contain even a rounded decimal representation, ma_gcvt()
+ indicates overflow and truncates the output string to the specified width.
+ - float-type arguments are handled differently than double ones. For a
+ float input number (i.e. when the 'type' argument is MY_GCVT_ARG_FLOAT)
+ we deliberately limit the precision of conversion by FLT_DIG digits to
+ avoid garbage past the significant digits.
+ - unlike sprintf(), in cases where the 'e' format is preferred, we don't
+ zero-pad the exponent to save space for significant digits. The '+' sign
+ for a positive exponent does not appear for the same reason.
+
+ @param x the input floating point number.
+ @param type is either MY_GCVT_ARG_FLOAT or MY_GCVT_ARG_DOUBLE.
+ Specifies the type of the input number (see notes above).
+ @param width field width in characters. The minimal field width to
+ hold any number representation (albeit rounded) is 7
+ characters ("-Ne-NNN").
+ @param to pointer to the output buffer. The result is always
+ zero-terminated, and the longest returned string is thus
+ 'width + 1' bytes.
+ @param error if not NULL, points to a location where the status of
+ conversion is stored upon return.
+ FALSE successful conversion
+ TRUE the input number is [-,+]infinity or nan.
+ The output string in this case is always '0'.
+ @return number of written characters (excluding terminating '\0')
+
+ @todo
+ Check if it is possible and makes sense to do our own rounding on top of
+ dtoa() instead of calling dtoa() twice in (rare) cases when the resulting
+ string representation does not fit in the specified field width and we want
+ to re-round the input number with fewer significant digits. Examples:
+
+ ma_gcvt(-9e-3, ..., 4, ...);
+ ma_gcvt(-9e-3, ..., 2, ...);
+ ma_gcvt(1.87e-3, ..., 4, ...);
+ ma_gcvt(55, ..., 1, ...);
+
+ We do our best to minimize such cases by:
+
+ - passing to dtoa() the field width as the number of significant digits
+
+ - removing the sign of the number early (and decreasing the width before
+ passing it to dtoa())
+
+ - choosing the proper format to preserve the most number of significant
+ digits.
+*/
+
+size_t ma_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
+ my_bool *error)
+{
+ int decpt, sign, len, exp_len;
+ char *res, *src, *end, *dst= to, *dend= dst + width;
+ char buf[DTOA_BUFF_SIZE];
+ my_bool have_space, force_e_format;
+ DBUG_ASSERT(width > 0 && to != NULL);
+
+ /* We want to remove '-' from equations early */
+ if (x < 0.)
+ width--;
+
+ res= dtoa(x, 4, type == MY_GCVT_ARG_DOUBLE ? width : MIN(width, FLT_DIG),
+ &decpt, &sign, &end, buf, sizeof(buf));
+ if (decpt == DTOA_OVERFLOW)
+ {
+ dtoa_free(res, buf, sizeof(buf));
+ *to++= '0';
+ *to= '\0';
+ if (error != NULL)
+ *error= TRUE;
+ return 1;
+ }
+
+ if (error != NULL)
+ *error= FALSE;
+
+ src= res;
+ len= (int)(end - res);
+
+ /*
+ Number of digits in the exponent from the 'e' conversion.
+ The sign of the exponent is taken into account separately, we don't need
+ to count it here.
+ */
+ exp_len= 1 + (decpt >= 101 || decpt <= -99) + (decpt >= 11 || decpt <= -9);
+
+ /*
+ Do we have enough space for all digits in the 'f' format?
+ Let 'len' be the number of significant digits returned by dtoa,
+ and F be the length of the resulting decimal representation.
+ Consider the following cases:
+ 1. decpt <= 0, i.e. we have "0.NNN" => F = len - decpt + 2
+ 2. 0 < decpt < len, i.e. we have "NNN.NNN" => F = len + 1
+ 3. len <= decpt, i.e. we have "NNN00" => F = decpt
+ */
+ have_space= (decpt <= 0 ? len - decpt + 2 :
+ decpt > 0 && decpt < len ? len + 1 :
+ decpt) <= width;
+ /*
+ The following is true when no significant digits can be placed with the
+ specified field width using the 'f' format, and the 'e' format
+ will not be truncated.
+ */
+ force_e_format= (decpt <= 0 && width <= 2 - decpt && width >= 3 + exp_len);
+ /*
+ Assume that we don't have enough space to place all significant digits in
+ the 'f' format. We have to choose between the 'e' format and the 'f' one
+ to keep as many significant digits as possible.
+ Let E and F be the lengths of decimal representation in the 'e' and 'f'
+ formats, respectively. We want to use the 'f' format if, and only if F <= E.
+ Consider the following cases:
+ 1. decpt <= 0.
+ F = len - decpt + 2 (see above)
+ E = len + (len > 1) + 1 + 1 (decpt <= -99) + (decpt <= -9) + 1
+ ("N.NNe-MMM")
+ (F <= E) <=> (len == 1 && decpt >= -1) || (len > 1 && decpt >= -2)
+ We also need to ensure that if the 'f' format is chosen,
+ the field width allows us to place at least one significant digit
+ (i.e. width > 2 - decpt). If not, we prefer the 'e' format.
+ 2. 0 < decpt < len
+ F = len + 1 (see above)
+ E = len + 1 + 1 + ... ("N.NNeMMM")
+ F is always less than E.
+ 3. len <= decpt <= width
+ In this case we have enough space to represent the number in the 'f'
+ format, so we prefer it with some exceptions.
+ 4. width < decpt
+ The number cannot be represented in the 'f' format at all, always use
+ the 'e' 'one.
+ */
+ if ((have_space ||
+ /*
+ Not enough space, let's see if the 'f' format provides the most number
+ of significant digits.
+ */
+ ((decpt <= width && (decpt >= -1 || (decpt == -2 &&
+ (len > 1 || !force_e_format)))) &&
+ !force_e_format)) &&
+
+ /*
+ Use the 'e' format in some cases even if we have enough space for the
+ 'f' one. See comment for DBL_DIG.
+ */
+ (!have_space || (decpt >= -DBL_DIG + 1 &&
+ (decpt <= DBL_DIG || len > decpt))))
+ {
+ /* 'f' format */
+ int i;
+
+ width-= (decpt < len) + (decpt <= 0 ? 1 - decpt : 0);
+
+ /* Do we have to truncate any digits? */
+ if (width < len)
+ {
+ if (width < decpt)
+ {
+ if (error != NULL)
+ *error= TRUE;
+ width= decpt;
+ }
+
+ /*
+ We want to truncate (len - width) least significant digits after the
+ decimal point. For this we are calling dtoa with mode=5, passing the
+ number of significant digits = (len-decpt) - (len-width) = width-decpt
+ */
+ dtoa_free(res, buf, sizeof(buf));
+ res= dtoa(x, 5, width - decpt, &decpt, &sign, &end, buf, sizeof(buf));
+ src= res;
+ len= (int)(end - res);
+ }
+
+ if (len == 0)
+ {
+ /* Underflow. Just print '0' and exit */
+ *dst++= '0';
+ goto end;
+ }
+
+ /*
+ At this point we are sure we have enough space to put all digits
+ returned by dtoa
+ */
+ if (sign && dst < dend)
+ *dst++= '-';
+ if (decpt <= 0)
+ {
+ if (dst < dend)
+ *dst++= '0';
+ if (len > 0 && dst < dend)
+ *dst++= '.';
+ for (; decpt < 0 && dst < dend; decpt++)
+ *dst++= '0';
+ }
+
+ for (i= 1; i <= len && dst < dend; i++)
+ {
+ *dst++= *src++;
+ if (i == decpt && i < len && dst < dend)
+ *dst++= '.';
+ }
+ while (i++ <= decpt && dst < dend)
+ *dst++= '0';
+ }
+ else
+ {
+ /* 'e' format */
+ int decpt_sign= 0;
+
+ if (--decpt < 0)
+ {
+ decpt= -decpt;
+ width--;
+ decpt_sign= 1;
+ }
+ width-= 1 + exp_len; /* eNNN */
+
+ if (len > 1)
+ width--;
+
+ if (width <= 0)
+ {
+ /* Overflow */
+ if (error != NULL)
+ *error= TRUE;
+ width= 0;
+ }
+
+ /* Do we have to truncate any digits? */
+ if (width < len)
+ {
+ /* Yes, re-convert with a smaller width */
+ dtoa_free(res, buf, sizeof(buf));
+ res= dtoa(x, 4, width, &decpt, &sign, &end, buf, sizeof(buf));
+ src= res;
+ len= (int)(end - res);
+ if (--decpt < 0)
+ decpt= -decpt;
+ }
+ /*
+ At this point we are sure we have enough space to put all digits
+ returned by dtoa
+ */
+ if (sign && dst < dend)
+ *dst++= '-';
+ if (dst < dend)
+ *dst++= *src++;
+ if (len > 1 && dst < dend)
+ {
+ *dst++= '.';
+ while (src < end && dst < dend)
+ *dst++= *src++;
+ }
+ if (dst < dend)
+ *dst++= 'e';
+ if (decpt_sign && dst < dend)
+ *dst++= '-';
+
+ if (decpt >= 100 && dst < dend)
+ {
+ *dst++= decpt / 100 + '0';
+ decpt%= 100;
+ if (dst < dend)
+ *dst++= decpt / 10 + '0';
+ }
+ else if (decpt >= 10 && dst < dend)
+ *dst++= decpt / 10 + '0';
+ if (dst < dend)
+ *dst++= decpt % 10 + '0';
+
+ }
+
+end:
+ dtoa_free(res, buf, sizeof(buf));
+ *dst= '\0';
+
+ return dst - to;
+}
+
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+/*
+ Original copy of the software is located at http://www.netlib.org/fp/dtoa.c
+ It was adjusted to serve MySQL server needs:
+ * strtod() was modified to not expect a zero-terminated string.
+ It now honors 'se' (end of string) argument as the input parameter,
+ not just as the output one.
+ * in dtoa(), in case of overflow/underflow/NaN result string now contains "0";
+ decpt is set to DTOA_OVERFLOW to indicate overflow.
+ * support for VAX, IBM mainframe and 16-bit hardware removed
+ * we always assume that 64-bit integer type is available
+ * support for Kernigan-Ritchie style headers (pre-ANSI compilers)
+ removed
+ * all gcc warnings ironed out
+ * we always assume multithreaded environment, so we had to change
+ memory allocation procedures to use stack in most cases;
+ malloc is used as the last resort.
+ * pow5mult rewritten to use pre-calculated pow5 list instead of
+ the one generated on the fly.
+*/
+
+
+/*
+ On a machine with IEEE extended-precision registers, it is
+ necessary to specify double-precision (53-bit) rounding precision
+ before invoking strtod or dtoa. If the machine uses (the equivalent
+ of) Intel 80x87 arithmetic, the call
+ _control87(PC_53, MCW_PC);
+ does this with many compilers. Whether this or another call is
+ appropriate depends on the compiler; for this to work, it may be
+ necessary to #include "float.h" or another system-dependent header
+ file.
+*/
+
+/*
+ #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ and dtoa should round accordingly.
+ #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ and Honor_FLT_ROUNDS is not #defined.
+
+ TODO: check if we can get rid of the above two
+*/
+
+typedef int32 Long;
+typedef uint32 ULong;
+typedef int64 LLong;
+typedef uint64 ULLong;
+
+typedef union { double d; ULong L[2]; } U;
+
+#if defined(HAVE_BIGENDIAN) || \
+ (defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN))
+#define word0(x) ((x)->L[0])
+#define word1(x) ((x)->L[1])
+#else
+#define word0(x) ((x)->L[1])
+#define word1(x) ((x)->L[0])
+#endif
+
+#define dval(x) ((x)->d)
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax= floor(P*log(2)/log(5)) */
+/* Bletch= (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max= floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max= floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+
+#ifndef Flt_Rounds
+#ifdef FLT_ROUNDS
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+#ifdef Honor_FLT_ROUNDS
+#define Rounding rounding
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+#define rounded_product(a,b) ((a)*= (b))
+#define rounded_quotient(a,b) ((a)/= (b))
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 0xffffffff
+#define FFFFFFFF 0xffffffffUL
+
+/* This is tested to be enough for dtoa */
+
+#define Kmax 15
+
+#define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \
+ 2*sizeof(int) + (y)->wds*sizeof(ULong))
+
+/* Arbitrary-length integer */
+
+typedef struct Bigint
+{
+ union {
+ ULong *x; /* points right after this Bigint object */
+ struct Bigint *next; /* to maintain free lists */
+ } p;
+ int k; /* 2^k = maxwds */
+ int maxwds; /* maximum length in 32-bit words */
+ int sign; /* not zero if number is negative */
+ int wds; /* current length in 32-bit words */
+} Bigint;
+
+
+/* A simple stack-memory based allocator for Bigints */
+
+typedef struct Stack_alloc
+{
+ char *begin;
+ char *free;
+ char *end;
+ /*
+ Having list of free blocks lets us reduce maximum required amount
+ of memory from ~4000 bytes to < 1680 (tested on x86).
+ */
+ Bigint *freelist[Kmax+1];
+} Stack_alloc;
+
+
+/*
+ Try to allocate object on stack, and resort to malloc if all
+ stack memory is used. Ensure allocated objects to be aligned by the pointer
+ size in order to not break the alignment rules when storing a pointer to a
+ Bigint.
+*/
+
+static Bigint *Balloc(int k, Stack_alloc *alloc)
+{
+ Bigint *rv;
+ DBUG_ASSERT(k <= Kmax);
+ if (k <= Kmax && alloc->freelist[k])
+ {
+ rv= alloc->freelist[k];
+ alloc->freelist[k]= rv->p.next;
+ }
+ else
+ {
+ int x, len;
+
+ x= 1 << k;
+ len= MY_ALIGN(sizeof(Bigint) + x * sizeof(ULong), SIZEOF_CHARP);
+
+ if (alloc->free + len <= alloc->end)
+ {
+ rv= (Bigint*) alloc->free;
+ alloc->free+= len;
+ }
+ else
+ rv= (Bigint*) malloc(len);
+
+ rv->k= k;
+ rv->maxwds= x;
+ }
+ rv->sign= rv->wds= 0;
+ rv->p.x= (ULong*) (rv + 1);
+ return rv;
+}
+
+
+/*
+ If object was allocated on stack, try putting it to the free
+ list. Otherwise call free().
+*/
+
+static void Bfree(Bigint *v, Stack_alloc *alloc)
+{
+ char *gptr= (char*) v; /* generic pointer */
+ if (gptr < alloc->begin || gptr >= alloc->end)
+ free(gptr);
+ else if (v->k <= Kmax)
+ {
+ /*
+ Maintain free lists only for stack objects: this way we don't
+ have to bother with freeing lists in the end of dtoa;
+ heap should not be used normally anyway.
+ */
+ v->p.next= alloc->freelist[v->k];
+ alloc->freelist[v->k]= v;
+ }
+}
+
+
+/*
+ This is to place return value of dtoa in: tries to use stack
+ as well, but passes by free lists management and just aligns len by
+ the pointer size in order to not break the alignment rules when storing a
+ pointer to a Bigint.
+*/
+
+static char *dtoa_alloc(int i, Stack_alloc *alloc)
+{
+ char *rv;
+ int aligned_size= MY_ALIGN(i, SIZEOF_CHARP);
+ if (alloc->free + aligned_size <= alloc->end)
+ {
+ rv= alloc->free;
+ alloc->free+= aligned_size;
+ }
+ else
+ rv= malloc(i);
+ return rv;
+}
+
+
+/*
+ dtoa_free() must be used to free values s returned by dtoa()
+ This is the counterpart of dtoa_alloc()
+*/
+
+static void dtoa_free(char *gptr, char *buf, size_t buf_size)
+{
+ if (gptr < buf || gptr >= buf + buf_size)
+ free(gptr);
+}
+
+
+/* Bigint arithmetic functions */
+
+/* Multiply by m and add a */
+
+static Bigint *multadd(Bigint *b, int m, int a, Stack_alloc *alloc)
+{
+ int i, wds;
+ ULong *x;
+ ULLong carry, y;
+ Bigint *b1;
+
+ wds= b->wds;
+ x= b->p.x;
+ i= 0;
+ carry= a;
+ do
+ {
+ y= *x * (ULLong)m + carry;
+ carry= y >> 32;
+ *x++= (ULong)(y & FFFFFFFF);
+ }
+ while (++i < wds);
+ if (carry)
+ {
+ if (wds >= b->maxwds)
+ {
+ b1= Balloc(b->k+1, alloc);
+ Bcopy(b1, b);
+ Bfree(b, alloc);
+ b= b1;
+ }
+ b->p.x[wds++]= (ULong) carry;
+ b->wds= wds;
+ }
+ return b;
+}
+
+
+static int hi0bits(register ULong x)
+{
+ register int k= 0;
+
+ if (!(x & 0xffff0000))
+ {
+ k= 16;
+ x<<= 16;
+ }
+ if (!(x & 0xff000000))
+ {
+ k+= 8;
+ x<<= 8;
+ }
+ if (!(x & 0xf0000000))
+ {
+ k+= 4;
+ x<<= 4;
+ }
+ if (!(x & 0xc0000000))
+ {
+ k+= 2;
+ x<<= 2;
+ }
+ if (!(x & 0x80000000))
+ {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+}
+
+
+static int lo0bits(ULong *y)
+{
+ register int k;
+ register ULong x= *y;
+
+ if (x & 7)
+ {
+ if (x & 1)
+ return 0;
+ if (x & 2)
+ {
+ *y= x >> 1;
+ return 1;
+ }
+ *y= x >> 2;
+ return 2;
+ }
+ k= 0;
+ if (!(x & 0xffff))
+ {
+ k= 16;
+ x>>= 16;
+ }
+ if (!(x & 0xff))
+ {
+ k+= 8;
+ x>>= 8;
+ }
+ if (!(x & 0xf))
+ {
+ k+= 4;
+ x>>= 4;
+ }
+ if (!(x & 0x3))
+ {
+ k+= 2;
+ x>>= 2;
+ }
+ if (!(x & 1))
+ {
+ k++;
+ x>>= 1;
+ if (!x)
+ return 32;
+ }
+ *y= x;
+ return k;
+}
+
+
+/* Convert integer to Bigint number */
+
+static Bigint *i2b(int i, Stack_alloc *alloc)
+{
+ Bigint *b;
+
+ b= Balloc(1, alloc);
+ b->p.x[0]= i;
+ b->wds= 1;
+ return b;
+}
+
+
+/* Multiply two Bigint numbers */
+
+static Bigint *mult(Bigint *a, Bigint *b, Stack_alloc *alloc)
+{
+ Bigint *c;
+ int k, wa, wb, wc;
+ ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ ULong y;
+ ULLong carry, z;
+
+ if (a->wds < b->wds)
+ {
+ c= a;
+ a= b;
+ b= c;
+ }
+ k= a->k;
+ wa= a->wds;
+ wb= b->wds;
+ wc= wa + wb;
+ if (wc > a->maxwds)
+ k++;
+ c= Balloc(k, alloc);
+ for (x= c->p.x, xa= x + wc; x < xa; x++)
+ *x= 0;
+ xa= a->p.x;
+ xae= xa + wa;
+ xb= b->p.x;
+ xbe= xb + wb;
+ xc0= c->p.x;
+ for (; xb < xbe; xc0++)
+ {
+ if ((y= *xb++))
+ {
+ x= xa;
+ xc= xc0;
+ carry= 0;
+ do
+ {
+ z= *x++ * (ULLong)y + *xc + carry;
+ carry= z >> 32;
+ *xc++= (ULong) (z & FFFFFFFF);
+ }
+ while (x < xae);
+ *xc= (ULong) carry;
+ }
+ }
+ for (xc0= c->p.x, xc= xc0 + wc; wc > 0 && !*--xc; --wc) ;
+ c->wds= wc;
+ return c;
+}
+
+
+/*
+ Precalculated array of powers of 5: tested to be enough for
+ vasting majority of dtoa_r cases.
+*/
+
+static ULong powers5[]=
+{
+ 625UL,
+
+ 390625UL,
+
+ 2264035265UL, 35UL,
+
+ 2242703233UL, 762134875UL, 1262UL,
+
+ 3211403009UL, 1849224548UL, 3668416493UL, 3913284084UL, 1593091UL,
+
+ 781532673UL, 64985353UL, 253049085UL, 594863151UL, 3553621484UL,
+ 3288652808UL, 3167596762UL, 2788392729UL, 3911132675UL, 590UL,
+
+ 2553183233UL, 3201533787UL, 3638140786UL, 303378311UL, 1809731782UL,
+ 3477761648UL, 3583367183UL, 649228654UL, 2915460784UL, 487929380UL,
+ 1011012442UL, 1677677582UL, 3428152256UL, 1710878487UL, 1438394610UL,
+ 2161952759UL, 4100910556UL, 1608314830UL, 349175UL
+};
+
+
+static Bigint p5_a[]=
+{
+ /* { x } - k - maxwds - sign - wds */
+ { { powers5 }, 1, 1, 0, 1 },
+ { { powers5 + 1 }, 1, 1, 0, 1 },
+ { { powers5 + 2 }, 1, 2, 0, 2 },
+ { { powers5 + 4 }, 2, 3, 0, 3 },
+ { { powers5 + 7 }, 3, 5, 0, 5 },
+ { { powers5 + 12 }, 4, 10, 0, 10 },
+ { { powers5 + 22 }, 5, 19, 0, 19 }
+};
+
+#define P5A_MAX (sizeof(p5_a)/sizeof(*p5_a) - 1)
+
+static Bigint *pow5mult(Bigint *b, int k, Stack_alloc *alloc)
+{
+ Bigint *b1, *p5, *p51=NULL;
+ int i;
+ static int p05[3]= { 5, 25, 125 };
+ my_bool overflow= FALSE;
+
+ if ((i= k & 3))
+ b= multadd(b, p05[i-1], 0, alloc);
+
+ if (!(k>>= 2))
+ return b;
+ p5= p5_a;
+ for (;;)
+ {
+ if (k & 1)
+ {
+ b1= mult(b, p5, alloc);
+ Bfree(b, alloc);
+ b= b1;
+ }
+ if (!(k>>= 1))
+ break;
+ /* Calculate next power of 5 */
+ if (overflow)
+ {
+ p51= mult(p5, p5, alloc);
+ Bfree(p5, alloc);
+ p5= p51;
+ }
+ else if (p5 < p5_a + P5A_MAX)
+ ++p5;
+ else if (p5 == p5_a + P5A_MAX)
+ {
+ p5= mult(p5, p5, alloc);
+ overflow= TRUE;
+ }
+ }
+ if (p51)
+ Bfree(p51, alloc);
+ return b;
+}
+
+
+static Bigint *lshift(Bigint *b, int k, Stack_alloc *alloc)
+{
+ int i, k1, n, n1;
+ Bigint *b1;
+ ULong *x, *x1, *xe, z;
+
+ n= k >> 5;
+ k1= b->k;
+ n1= n + b->wds + 1;
+ for (i= b->maxwds; n1 > i; i<<= 1)
+ k1++;
+ b1= Balloc(k1, alloc);
+ x1= b1->p.x;
+ for (i= 0; i < n; i++)
+ *x1++= 0;
+ x= b->p.x;
+ xe= x + b->wds;
+ if (k&= 0x1f)
+ {
+ k1= 32 - k;
+ z= 0;
+ do
+ {
+ *x1++= *x << k | z;
+ z= *x++ >> k1;
+ }
+ while (x < xe);
+ if ((*x1= z))
+ ++n1;
+ }
+ else
+ do
+ *x1++= *x++;
+ while (x < xe);
+ b1->wds= n1 - 1;
+ Bfree(b, alloc);
+ return b1;
+}
+
+
+static int cmp(Bigint *a, Bigint *b)
+{
+ ULong *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i= a->wds;
+ j= b->wds;
+ if (i-= j)
+ return i;
+ xa0= a->p.x;
+ xa= xa0 + j;
+ xb0= b->p.x;
+ xb= xb0 + j;
+ for (;;)
+ {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+}
+
+
+static Bigint *diff(Bigint *a, Bigint *b, Stack_alloc *alloc)
+{
+ Bigint *c;
+ int i, wa, wb;
+ ULong *xa, *xae, *xb, *xbe, *xc;
+ ULLong borrow, y;
+
+ i= cmp(a,b);
+ if (!i)
+ {
+ c= Balloc(0, alloc);
+ c->wds= 1;
+ c->p.x[0]= 0;
+ return c;
+ }
+ if (i < 0)
+ {
+ c= a;
+ a= b;
+ b= c;
+ i= 1;
+ }
+ else
+ i= 0;
+ c= Balloc(a->k, alloc);
+ c->sign= i;
+ wa= a->wds;
+ xa= a->p.x;
+ xae= xa + wa;
+ wb= b->wds;
+ xb= b->p.x;
+ xbe= xb + wb;
+ xc= c->p.x;
+ borrow= 0;
+ do
+ {
+ y= (ULLong)*xa++ - *xb++ - borrow;
+ borrow= y >> 32 & (ULong)1;
+ *xc++= (ULong) (y & FFFFFFFF);
+ }
+ while (xb < xbe);
+ while (xa < xae)
+ {
+ y= *xa++ - borrow;
+ borrow= y >> 32 & (ULong)1;
+ *xc++= (ULong) (y & FFFFFFFF);
+ }
+ while (!*--xc)
+ wa--;
+ c->wds= wa;
+ return c;
+}
+
+
+static Bigint *d2b(U *d, int *e, int *bits, Stack_alloc *alloc)
+{
+ Bigint *b;
+ int de, k;
+ ULong *x, y, z;
+ int i;
+#define d0 word0(d)
+#define d1 word1(d)
+
+ b= Balloc(1, alloc);
+ x= b->p.x;
+
+ z= d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+ if ((de= (int)(d0 >> Exp_shift)))
+ z|= Exp_msk1;
+ if ((y= d1))
+ {
+ if ((k= lo0bits(&y)))
+ {
+ x[0]= y | z << (32 - k);
+ z>>= (k == 32) ? (--k) : k;
+ }
+ else
+ x[0]= y;
+ i= b->wds= (x[1]= z) ? 2 : 1;
+ }
+ else
+ {
+ k= lo0bits(&z);
+ x[0]= z;
+ i= b->wds= 1;
+ k+= 32;
+ }
+ if (de)
+ {
+ *e= de - Bias - (P-1) + k;
+ *bits= P - k;
+ }
+ else
+ {
+ *e= de - Bias - (P-1) + 1 + k;
+ *bits= 32*i - hi0bits(x[i-1]);
+ }
+ return b;
+#undef d0
+#undef d1
+}
+
+
+static const double tens[] =
+{
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+};
+
+static const double bigtens[]= { 1e16, 1e32, 1e64, 1e128, 1e256 };
+/*
+ The factor of 2^53 in tinytens[4] helps us avoid setting the underflow
+ flag unnecessarily. It leads to a song and dance at the end of strtod.
+*/
+#define Scale_Bit 0x10
+#define n_bigtens 5
+
+
+static int quorem(Bigint *b, Bigint *S)
+{
+ int n;
+ ULong *bx, *bxe, q, *sx, *sxe;
+ ULLong borrow, carry, y, ys;
+
+ n= S->wds;
+ if (b->wds < n)
+ return 0;
+ sx= S->p.x;
+ sxe= sx + --n;
+ bx= b->p.x;
+ bxe= bx + n;
+ q= *bxe / (*sxe + 1); /* ensure q <= true quotient */
+ if (q)
+ {
+ borrow= 0;
+ carry= 0;
+ do
+ {
+ ys= *sx++ * (ULLong)q + carry;
+ carry= ys >> 32;
+ y= *bx - (ys & FFFFFFFF) - borrow;
+ borrow= y >> 32 & (ULong)1;
+ *bx++= (ULong) (y & FFFFFFFF);
+ }
+ while (sx <= sxe);
+ if (!*bxe)
+ {
+ bx= b->p.x;
+ while (--bxe > bx && !*bxe)
+ --n;
+ b->wds= n;
+ }
+ }
+ if (cmp(b, S) >= 0)
+ {
+ q++;
+ borrow= 0;
+ carry= 0;
+ bx= b->p.x;
+ sx= S->p.x;
+ do
+ {
+ ys= *sx++ + carry;
+ carry= ys >> 32;
+ y= *bx - (ys & FFFFFFFF) - borrow;
+ borrow= y >> 32 & (ULong)1;
+ *bx++= (ULong) (y & FFFFFFFF);
+ }
+ while (sx <= sxe);
+ bx= b->p.x;
+ bxe= bx + n;
+ if (!*bxe)
+ {
+ while (--bxe > bx && !*bxe)
+ --n;
+ b->wds= n;
+ }
+ }
+ return q;
+}
+
+
+/*
+ dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+
+ Inspired by "How to Print Floating-Point Numbers Accurately" by
+ Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
+
+ Modifications:
+ 1. Rather than iterating, we use a simple numeric overestimate
+ to determine k= floor(log10(d)). We scale relevant
+ quantities using O(log2(k)) rather than O(k) multiplications.
+ 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ try to generate digits strictly left to right. Instead, we
+ compute with fewer bits and propagate the carry if necessary
+ when rounding the final digit up. This is often faster.
+ 3. Under the assumption that input will be rounded nearest,
+ mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ That is, we allow equality in stopping tests when the
+ round-nearest rule will give the same floating-point value
+ as would satisfaction of the stopping test with strict
+ inequality.
+ 4. We remove common factors of powers of 2 from relevant
+ quantities.
+ 5. When converting floating-point integers less than 1e16,
+ we use floating-point arithmetic rather than resorting
+ to multiple-precision integers.
+ 6. When asked to produce fewer than 15 digits, we first try
+ to get by with floating-point arithmetic; we resort to
+ multiple-precision integer arithmetic only if we cannot
+ guarantee that the floating-point calculation has given
+ the correctly rounded result. For k requested digits and
+ "uniformly" distributed input, the probability is
+ something like 10^(k-15) that we must resort to the Long
+ calculation.
+ */
+
+static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign,
+ char **rve, char *buf, size_t buf_size)
+{
+ /*
+ Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to DTOA_OVERFLOW.
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> MAX(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4,5 ==> similar to 2 and 3, respectively, but (in
+ round-nearest mode) with the tests of mode 0 to
+ possibly return a shorter string that rounds to d.
+ With IEEE arithmetic and compilation with
+ -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
+ as modes 2 and 3 when FLT_ROUNDS != 1.
+ 6-9 ==> Debugging modes similar to mode - 4: don't try
+ fast floating-point estimate (if applicable).
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, UNINIT_VAR(ilim), ilim0,
+ UNINIT_VAR(ilim1), j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ spec_case, try_quick;
+ Long L;
+ int denorm;
+ ULong x;
+ Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+ U d2, eps, u;
+ double ds;
+ char *s, *s0;
+#ifdef Honor_FLT_ROUNDS
+ int rounding;
+#endif
+ Stack_alloc alloc;
+
+ alloc.begin= alloc.free= buf;
+ alloc.end= buf + buf_size;
+ memset(alloc.freelist, 0, sizeof(alloc.freelist));
+
+ u.d= dd;
+ if (word0(&u) & Sign_bit)
+ {
+ /* set sign for everything, including 0's and NaNs */
+ *sign= 1;
+ word0(&u) &= ~Sign_bit; /* clear sign bit */
+ }
+ else
+ *sign= 0;
+
+ /* If infinity, set decpt to DTOA_OVERFLOW, if 0 set it to 1 */
+ /* coverity[assign_where_compare_meant] */
+ if (((word0(&u) & Exp_mask) == Exp_mask && (*decpt= DTOA_OVERFLOW)) ||
+ /* coverity[assign_where_compare_meant] */
+ (!dval(&u) && (*decpt= 1)))
+ {
+ /* Infinity, NaN, 0 */
+ char *res= (char*) dtoa_alloc(2, &alloc);
+ res[0]= '0';
+ res[1]= '\0';
+ if (rve)
+ *rve= res + 1;
+ return res;
+ }
+
+#ifdef Honor_FLT_ROUNDS
+ if ((rounding= Flt_Rounds) >= 2)
+ {
+ if (*sign)
+ rounding= rounding == 2 ? 0 : 2;
+ else
+ if (rounding != 2)
+ rounding= 0;
+ }
+#endif
+
+ b= d2b(&u, &be, &bbits, &alloc);
+ if ((i= (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1))))
+ {
+ dval(&d2)= dval(&u);
+ word0(&d2) &= Frac_mask1;
+ word0(&d2) |= Exp_11;
+
+ /*
+ log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ log10(x) = log(x) / log(10)
+ ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ log10(d)= (i-Bias)*log(2)/log(10) + log10(d2)
+
+ This suggests computing an approximation k to log10(d) by
+
+ k= (i - Bias)*0.301029995663981
+ + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+
+ We want k to be too large rather than too small.
+ The error in the first-order Taylor series approximation
+ is in our favor, so we just round up the constant enough
+ to compensate for any error in the multiplication of
+ (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ adding 1e-13 to the constant term more than suffices.
+ Hence we adjust the constant term to 0.1760912590558.
+ (We could get a more accurate k by invoking log10,
+ but this is probably not worthwhile.)
+ */
+
+ i-= Bias;
+ denorm= 0;
+ }
+ else
+ {
+ /* d is denormalized */
+
+ i= bbits + be + (Bias + (P-1) - 1);
+ x= i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32)
+ : word1(&u) << (32 - i);
+ dval(&d2)= x;
+ word0(&d2)-= 31*Exp_msk1; /* adjust exponent */
+ i-= (Bias + (P-1) - 1) + 1;
+ denorm= 1;
+ }
+ ds= (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ k= (int)ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k= floor(ds) */
+ k_check= 1;
+ if (k >= 0 && k <= Ten_pmax)
+ {
+ if (dval(&u) < tens[k])
+ k--;
+ k_check= 0;
+ }
+ j= bbits - i - 1;
+ if (j >= 0)
+ {
+ b2= 0;
+ s2= j;
+ }
+ else
+ {
+ b2= -j;
+ s2= 0;
+ }
+ if (k >= 0)
+ {
+ b5= 0;
+ s5= k;
+ s2+= k;
+ }
+ else
+ {
+ b2-= k;
+ b5= -k;
+ s5= 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode= 0;
+
+#ifdef Check_FLT_ROUNDS
+ try_quick= Rounding == 1;
+#else
+ try_quick= 1;
+#endif
+
+ if (mode > 5)
+ {
+ mode-= 4;
+ try_quick= 0;
+ }
+ leftright= 1;
+ switch (mode) {
+ case 0:
+ case 1:
+ ilim= ilim1= -1;
+ i= 18;
+ ndigits= 0;
+ break;
+ case 2:
+ leftright= 0;
+ /* fall through */
+ case 4:
+ if (ndigits <= 0)
+ ndigits= 1;
+ ilim= ilim1= i= ndigits;
+ break;
+ case 3:
+ leftright= 0;
+ /* fall through */
+ case 5:
+ i= ndigits + k + 1;
+ ilim= i;
+ ilim1= i - 1;
+ if (i <= 0)
+ i= 1;
+ }
+ s= s0= dtoa_alloc(i, &alloc);
+
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1 && rounding != 1)
+ leftright= 0;
+#endif
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick)
+ {
+ /* Try to get by with floating-point arithmetic. */
+ i= 0;
+ dval(&d2)= dval(&u);
+ k0= k;
+ ilim0= ilim;
+ ieps= 2; /* conservative */
+ if (k > 0)
+ {
+ ds= tens[k&0xf];
+ j= k >> 4;
+ if (j & Bletch)
+ {
+ /* prevent overflows */
+ j&= Bletch - 1;
+ dval(&u)/= bigtens[n_bigtens-1];
+ ieps++;
+ }
+ for (; j; j>>= 1, i++)
+ {
+ if (j & 1)
+ {
+ ieps++;
+ ds*= bigtens[i];
+ }
+ }
+ dval(&u)/= ds;
+ }
+ else if ((j1= -k))
+ {
+ dval(&u)*= tens[j1 & 0xf];
+ for (j= j1 >> 4; j; j>>= 1, i++)
+ {
+ if (j & 1)
+ {
+ ieps++;
+ dval(&u)*= bigtens[i];
+ }
+ }
+ }
+ if (k_check && dval(&u) < 1. && ilim > 0)
+ {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim= ilim1;
+ k--;
+ dval(&u)*= 10.;
+ ieps++;
+ }
+ dval(&eps)= ieps*dval(&u) + 7.;
+ word0(&eps)-= (P-1)*Exp_msk1;
+ if (ilim == 0)
+ {
+ S= mhi= 0;
+ dval(&u)-= 5.;
+ if (dval(&u) > dval(&eps))
+ goto one_digit;
+ if (dval(&u) < -dval(&eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+ if (leftright)
+ {
+ /* Use Steele & White method of only generating digits needed. */
+ dval(&eps)= 0.5/tens[ilim-1] - dval(&eps);
+ for (i= 0;;)
+ {
+ L= (Long) dval(&u);
+ dval(&u)-= L;
+ *s++= '0' + (int)L;
+ if (dval(&u) < dval(&eps))
+ goto ret1;
+ if (1. - dval(&u) < dval(&eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(&eps)*= 10.;
+ dval(&u)*= 10.;
+ }
+ }
+ else
+ {
+ /* Generate ilim digits, then fix them up. */
+ dval(&eps)*= tens[ilim-1];
+ for (i= 1;; i++, dval(&u)*= 10.)
+ {
+ L= (Long)(dval(&u));
+ if (!(dval(&u)-= L))
+ ilim= i;
+ *s++= '0' + (int)L;
+ if (i == ilim)
+ {
+ if (dval(&u) > 0.5 + dval(&eps))
+ goto bump_up;
+ else if (dval(&u) < 0.5 - dval(&eps))
+ {
+ while (*--s == '0');
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+ }
+ fast_failed:
+ s= s0;
+ dval(&u)= dval(&d2);
+ k= k0;
+ ilim= ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max)
+ {
+ /* Yes. */
+ ds= tens[k];
+ if (ndigits < 0 && ilim <= 0)
+ {
+ S= mhi= 0;
+ if (ilim < 0 || dval(&u) <= 5*ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for (i= 1;; i++, dval(&u)*= 10.)
+ {
+ L= (Long)(dval(&u) / ds);
+ dval(&u)-= L*ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(&u) < 0)
+ {
+ L--;
+ dval(&u)+= ds;
+ }
+#endif
+ *s++= '0' + (int)L;
+ if (!dval(&u))
+ {
+ break;
+ }
+ if (i == ilim)
+ {
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ {
+ switch (rounding) {
+ case 0: goto ret1;
+ case 2: goto bump_up;
+ }
+ }
+#endif
+ dval(&u)+= dval(&u);
+ if (dval(&u) > ds || (dval(&u) == ds && L & 1))
+ {
+bump_up:
+ while (*--s == '9')
+ if (s == s0)
+ {
+ k++;
+ *s= '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2= b2;
+ m5= b5;
+ mhi= mlo= 0;
+ if (leftright)
+ {
+ i = denorm ? be + (Bias + (P-1) - 1 + 1) : 1 + P - bbits;
+ b2+= i;
+ s2+= i;
+ mhi= i2b(1, &alloc);
+ }
+ if (m2 > 0 && s2 > 0)
+ {
+ i= m2 < s2 ? m2 : s2;
+ b2-= i;
+ m2-= i;
+ s2-= i;
+ }
+ if (b5 > 0)
+ {
+ if (leftright)
+ {
+ if (m5 > 0)
+ {
+ mhi= pow5mult(mhi, m5, &alloc);
+ b1= mult(mhi, b, &alloc);
+ Bfree(b, &alloc);
+ b= b1;
+ }
+ if ((j= b5 - m5))
+ b= pow5mult(b, j, &alloc);
+ }
+ else
+ b= pow5mult(b, b5, &alloc);
+ }
+ S= i2b(1, &alloc);
+ if (s5 > 0)
+ S= pow5mult(S, s5, &alloc);
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ spec_case= 0;
+ if ((mode < 2 || leftright)
+#ifdef Honor_FLT_ROUNDS
+ && rounding == 1
+#endif
+ )
+ {
+ if (!word1(&u) && !(word0(&u) & Bndry_mask) &&
+ word0(&u) & (Exp_mask & ~Exp_msk1)
+ )
+ {
+ /* The special case */
+ b2+= Log2P;
+ s2+= Log2P;
+ spec_case= 1;
+ }
+ }
+
+ /*
+ Arrange for convenient computation of quotients:
+ shift left if necessary so divisor has 4 leading 0 bits.
+
+ Perhaps we should just compute leading 28 bits of S once
+ a nd for all and pass them and a shift to quorem, so it
+ can do shifts and ors to compute the numerator for q.
+ */
+ if ((i= ((s5 ? 32 - hi0bits(S->p.x[S->wds-1]) : 1) + s2) & 0x1f))
+ i= 32 - i;
+ if (i > 4)
+ {
+ i-= 4;
+ b2+= i;
+ m2+= i;
+ s2+= i;
+ }
+ else if (i < 4)
+ {
+ i+= 28;
+ b2+= i;
+ m2+= i;
+ s2+= i;
+ }
+ if (b2 > 0)
+ b= lshift(b, b2, &alloc);
+ if (s2 > 0)
+ S= lshift(S, s2, &alloc);
+ if (k_check)
+ {
+ if (cmp(b,S) < 0)
+ {
+ k--;
+ /* we botched the k estimate */
+ b= multadd(b, 10, 0, &alloc);
+ if (leftright)
+ mhi= multadd(mhi, 10, 0, &alloc);
+ ilim= ilim1;
+ }
+ }
+ if (ilim <= 0 && (mode == 3 || mode == 5))
+ {
+ if (ilim < 0 || cmp(b,S= multadd(S,5,0, &alloc)) <= 0)
+ {
+ /* no digits, fcvt style */
+no_digits:
+ k= -1 - ndigits;
+ goto ret;
+ }
+one_digit:
+ *s++= '1';
+ k++;
+ goto ret;
+ }
+ if (leftright)
+ {
+ if (m2 > 0)
+ mhi= lshift(mhi, m2, &alloc);
+
+ /*
+ Compute mlo -- check for special case that d is a normalized power of 2.
+ */
+
+ mlo= mhi;
+ if (spec_case)
+ {
+ mhi= Balloc(mhi->k, &alloc);
+ Bcopy(mhi, mlo);
+ mhi= lshift(mhi, Log2P, &alloc);
+ }
+
+ for (i= 1;;i++)
+ {
+ dig= quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string that will round to d? */
+ j= cmp(b, mlo);
+ delta= diff(S, mhi, &alloc);
+ j1= delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta, &alloc);
+ if (j1 == 0 && mode != 1 && !(word1(&u) & 1)
+#ifdef Honor_FLT_ROUNDS
+ && rounding >= 1
+#endif
+ )
+ {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+ *s++= dig;
+ goto ret;
+ }
+ if (j < 0 || (j == 0 && mode != 1 && !(word1(&u) & 1)))
+ {
+ if (!b->p.x[0] && b->wds <= 1)
+ {
+ goto accept_dig;
+ }
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch (rounding) {
+ case 0: goto accept_dig;
+ case 2: goto keep_dig;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+ if (j1 > 0)
+ {
+ b= lshift(b, 1, &alloc);
+ j1= cmp(b, S);
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+ && dig++ == '9')
+ goto round_9_up;
+ }
+accept_dig:
+ *s++= dig;
+ goto ret;
+ }
+ if (j1 > 0)
+ {
+#ifdef Honor_FLT_ROUNDS
+ if (!rounding)
+ goto accept_dig;
+#endif
+ if (dig == '9')
+ { /* possible if i == 1 */
+round_9_up:
+ *s++= '9';
+ goto roundoff;
+ }
+ *s++= dig + 1;
+ goto ret;
+ }
+#ifdef Honor_FLT_ROUNDS
+keep_dig:
+#endif
+ *s++= dig;
+ if (i == ilim)
+ break;
+ b= multadd(b, 10, 0, &alloc);
+ if (mlo == mhi)
+ mlo= mhi= multadd(mhi, 10, 0, &alloc);
+ else
+ {
+ mlo= multadd(mlo, 10, 0, &alloc);
+ mhi= multadd(mhi, 10, 0, &alloc);
+ }
+ }
+ }
+ else
+ for (i= 1;; i++)
+ {
+ *s++= dig= quorem(b,S) + '0';
+ if (!b->p.x[0] && b->wds <= 1)
+ {
+ goto ret;
+ }
+ if (i >= ilim)
+ break;
+ b= multadd(b, 10, 0, &alloc);
+ }
+
+ /* Round off last digit */
+
+#ifdef Honor_FLT_ROUNDS
+ switch (rounding) {
+ case 0: goto trimzeros;
+ case 2: goto roundoff;
+ }
+#endif
+ b= lshift(b, 1, &alloc);
+ j= cmp(b, S);
+ if (j > 0 || (j == 0 && dig & 1))
+ {
+roundoff:
+ while (*--s == '9')
+ if (s == s0)
+ {
+ k++;
+ *s++= '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else
+ {
+#ifdef Honor_FLT_ROUNDS
+trimzeros:
+#endif
+ while (*--s == '0');
+ s++;
+ }
+ret:
+ if (S != NULL)
+ Bfree(S, &alloc);
+ if (mhi)
+ {
+ if (mlo && mlo != mhi)
+ Bfree(mlo, &alloc);
+ Bfree(mhi, &alloc);
+ }
+ret1:
+ Bfree(b, &alloc);
+ *s= 0;
+ *decpt= k + 1;
+ if (rve)
+ *rve= s;
+ return s0;
+}
diff --git a/libmariadb/libmariadb/ma_errmsg.c b/libmariadb/libmariadb/ma_errmsg.c
new file mode 100644
index 00000000..888a41e3
--- /dev/null
+++ b/libmariadb/libmariadb/ma_errmsg.c
@@ -0,0 +1,131 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Error messages for clients */
+/* error messages for the demon is in share/language/errmsg.sys */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include "errmsg.h"
+#include <stdarg.h>
+
+const char *SQLSTATE_UNKNOWN= "HY000";
+
+const char *client_errors[]=
+{
+/* 2000 */ "Unknown error",
+/* 2001 */ "Can't create UNIX socket (%d)",
+/* 2002 */ "Can't connect to local server through socket '%-.64s' (%d)",
+/* 2003 */ "Can't connect to server on '%-.64s' (%d)",
+/* 2004 */ "Can't create TCP/IP socket (%d)",
+/* 2005 */ "Unknown server host '%-.100s' (%d)",
+/* 2006 */ "Server has gone away",
+/* 2007 */ "Protocol mismatch. Server Version = %d Client Version = %d",
+/* 2008 */ "Client run out of memory",
+/* 2009 */ "Wrong host info",
+/* 2010 */ "Localhost via UNIX socket",
+/* 2011 */ "%-.64s via TCP/IP",
+/* 2012 */ "Error in server handshake",
+/* 2013 */ "Lost connection to server during query",
+/* 2014 */ "Commands out of sync; you can't run this command now",
+/* 2015 */ "%-.64s via named pipe",
+/* 2016 */ "Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
+/* 2017 */ "Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
+/* 2018 */ "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
+/* 2019 */ "Can't initialize character set %-.64s (path: %-.64s)",
+/* 2020 */ "Got packet bigger than 'max_allowed_packet'",
+/* 2021 */ "",
+/* 2022 */ "",
+/* 2023 */ "",
+/* 2024 */ "",
+/* 2025 */ "",
+/* 2026 */ "TLS/SSL error: %-.100s",
+/* 2027 */ "Received malformed packet",
+/* 2028 */ "",
+/* 2029 */ "",
+/* 2030 */ "Statement is not prepared",
+/* 2031 */ "No data supplied for parameters in prepared statement",
+/* 2032 */ "Data truncated",
+/* 2033 */ "",
+/* 2034 */ "Invalid parameter number",
+/* 2035 */ "Invalid buffer type: %d (parameter: %d)",
+/* 2036 */ "Buffer type is not supported",
+/* 2037 */ "Shared memory: %-.64s",
+/* 2038 */ "Shared memory connection failed during %s. (%lu)",
+/* 2039 */ "",
+/* 2040 */ "",
+/* 2041 */ "",
+/* 2042 */ "",
+/* 2043 */ "",
+/* 2044 */ "",
+/* 2045 */ "",
+/* 2046 */ "",
+/* 2047 */ "Wrong or unknown protocol",
+/* 2048 */ "",
+/* 2049 */ "Connection with old authentication protocol refused.",
+/* 2050 */ "",
+/* 2051 */ "",
+/* 2052 */ "Prepared statement contains no metadata",
+/* 2053 */ "",
+/* 2054 */ "This feature is not implemented or disabled",
+/* 2055 */ "Lost connection to server at '%s', system error: %d",
+/* 2056 */ "Server closed statement due to a prior %s function call",
+/* 2057 */ "The number of parameters in bound buffers differs from number of columns in resultset",
+/* 2058 */ "Can't connect twice. Already connected",
+/* 2059 */ "Plugin %s could not be loaded: %s",
+/* 2060 */ "An attribute with same name already exists",
+/* 2061 */ "Plugin doesn't support this function",
+ ""
+};
+
+const char *mariadb_client_errors[] =
+{
+ /* 5000 */ "Creating an event failed (Errorcode: %d)",
+ /* 5001 */ "Bind to local interface '-.%64s' failed (Errorcode: %d)",
+ /* 5002 */ "Connection type doesn't support asynchronous IO operations",
+ /* 5003 */ "Server doesn't support function '%s'",
+ /* 5004 */ "File '%s' not found (Errcode: %d)",
+ /* 5005 */ "Error reading file '%s' (Errcode: %d)",
+ /* 5006 */ "Bulk operation without parameters is not supported",
+ /* 5007 */ "Invalid statement handle",
+ /* 5008 */ "Unsupported version %d. Supported versions are in the range %d - %d",
+ /* 5009 */ "Invalid or missing parameter '%s'.",
+ /* 5010 */ "Authentication plugin '%s' couldn't be found in restricted_auth plugin list.",
+ /* 5011 */ "Parse error in connection string (offset %d)",
+ /* 5012 */ "Error while loading plugin '%s'",
+ /* 5013 */ "Read error: %s (%d)",
+ /* 5014 */ "Write error: %s (%d)",
+ /* 5015 */ "Error while uncompressing packet",
+ /* 5016 */ "Error while retrieving parameter from callback function",
+ /* 5017 */ "Error while uncompressing packet (File: %.*s start_pos=%ld).",
+ /* 5018 */ "Checksum verification failed (File: %.*s start_pos=%ld). Reported checksum is %x, while calculated checksum is %x.",
+ /* 5019 */ "Binary log protocol error (File: %.*s start_pos=%ld): Log format %d not supported.",
+ /* 5020 */ "Binary log error (File: %.*s start_pos=%ld): Unknown event type (%d) with flag 'not_ignorable'.",
+ /* 5021 */ "Binary log error (File: %.*s start_pos=%ld): %s.",
+ /* 5022 */ "File '%s' is not a binary log file",
+ /* 5023 */ "Semi sync request error: %s",
+ ""
+};
+
+const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
+char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
+
+void init_client_errs(void)
+{
+ my_errmsg[CLIENT_ERRMAP] = &client_errors[0];
+}
+
diff --git a/libmariadb/libmariadb/ma_hashtbl.c b/libmariadb/libmariadb/ma_hashtbl.c
new file mode 100644
index 00000000..4805dee0
--- /dev/null
+++ b/libmariadb/libmariadb/ma_hashtbl.c
@@ -0,0 +1,580 @@
+/************************************************************************************
+ Copyright (C) 2000, 2012 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
+ Monty Program AB, 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*************************************************************************************/
+
+/* The hash functions used for saving keys */
+/* One of key_length or key_length_offset must be given */
+/* Key length of 0 isn't allowed */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_string.h>
+#include <mariadb_ctype.h>
+#include "ma_hashtbl.h"
+
+#define NO_RECORD ((uint) -1)
+#define LOWFIND 1
+#define LOWUSED 2
+#define HIGHFIND 4
+#define HIGHUSED 8
+
+static uint hash_mask(uint hashnr,uint buffmax,uint maxlength);
+static void movelink(MA_HASHTBL_LINK *array,uint pos,uint next_link,uint newlink);
+static uint calc_hashnr(const uchar *key,uint length);
+static uint calc_hashnr_caseup(const uchar *key,uint length);
+static int hashcmp(MA_HASHTBL *hash,MA_HASHTBL_LINK *pos,const uchar *key,uint length);
+
+
+my_bool _ma_hashtbl_init(MA_HASHTBL *hash,uint size,uint key_offset,uint key_length,
+ hash_get_key get_key,
+ void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
+{
+ hash->records=0;
+ if (ma_init_dynamic_array_ci(&hash->array,sizeof(MA_HASHTBL_LINK),size,0))
+ {
+ hash->free=0; /* Allow call to hash_free */
+ return(TRUE);
+ }
+ hash->key_offset=key_offset;
+ hash->key_length=key_length;
+ hash->blength=1;
+ hash->current_record= NO_RECORD; /* For the future */
+ hash->get_key=get_key;
+ hash->free=free_element;
+ hash->flags=flags;
+ if (flags & MA_HASHTBL_CASE_INSENSITIVE)
+ hash->calc_hashnr=calc_hashnr_caseup;
+ else
+ hash->calc_hashnr=calc_hashnr;
+ return(0);
+}
+
+
+void ma_hashtbl_free(MA_HASHTBL *hash)
+{
+ if (hash->free)
+ {
+ uint i,records;
+ MA_HASHTBL_LINK *data=dynamic_element(&hash->array,0,MA_HASHTBL_LINK*);
+ for (i=0,records=hash->records ; i < records ; i++)
+ (*hash->free)(data[i].data);
+ hash->free=0;
+ }
+ ma_delete_dynamic(&hash->array);
+ hash->records=0;
+ return;
+}
+
+ /* some helper functions */
+
+/*
+ This function is char* instead of uchar* as HPUX11 compiler can't
+ handle inline functions that are not defined as native types
+*/
+
+static inline char*
+hash_key(MA_HASHTBL *hash,const uchar *record,uint *length,my_bool first)
+{
+ if (hash->get_key)
+ return (char *)(*hash->get_key)(record,(uint *)length,first);
+ *length=hash->key_length;
+ return (char*) record+hash->key_offset;
+}
+
+ /* Calculate pos according to keys */
+
+static uint hash_mask(uint hashnr,uint buffmax,uint maxlength)
+{
+ if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
+ return (hashnr & ((buffmax >> 1) -1));
+}
+
+static uint hash_rec_mask(MA_HASHTBL *hash,MA_HASHTBL_LINK *pos,uint buffmax,
+ uint maxlength)
+{
+ uint length;
+ uchar *key= (uchar*) hash_key(hash,pos->data,&length,0);
+ return hash_mask((*hash->calc_hashnr)(key,length),buffmax,maxlength);
+}
+
+#ifndef NEW_MA_HASHTBL_FUNCTION
+
+ /* Calc hashvalue for a key */
+
+static uint calc_hashnr(const uchar *key,uint length)
+{
+ register uint nr=1, nr2=4;
+ while (length--)
+ {
+ nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8);
+ nr2+=3;
+ }
+ return((uint) nr);
+}
+
+ /* Calc hashvalue for a key, case independently */
+
+static uint calc_hashnr_caseup(const uchar *key,uint length)
+{
+ register uint nr=1, nr2=4;
+ while (length--)
+ {
+ nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8);
+ nr2+=3;
+ }
+ return((uint) nr);
+}
+
+#else
+
+/*
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of the hash algorithm was taken from an idea sent by email to the
+ * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
+ * Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com)
+ * later improved on their algorithm.
+ *
+ * The magic is in the interesting relationship between the special prime
+ * 16777619 (2^24 + 403) and 2^32 and 2^8.
+ *
+ * This hash produces the fewest collisions of any function that we've seen so
+ * far, and works well on both numbers and strings.
+ */
+
+uint calc_hashnr(const uchar *key, uint len)
+{
+ const uchar *end=key+len;
+ uint hash;
+ for (hash = 0; key < end; key++)
+ {
+ hash *= 16777619;
+ hash ^= (uint) *(uchar*) key;
+ }
+ return (hash);
+}
+
+uint calc_hashnr_caseup(const uchar *key, uint len)
+{
+ const uchar *end=key+len;
+ uint hash;
+ for (hash = 0; key < end; key++)
+ {
+ hash *= 16777619;
+ hash ^= (uint) (uchar) toupper(*key);
+ }
+ return (hash);
+}
+
+#endif
+
+
+#ifndef __SUNPRO_C /* SUNPRO can't handle this */
+static inline
+#endif
+unsigned int rec_hashnr(MA_HASHTBL *hash,const uchar *record)
+{
+ uint length;
+ uchar *key= (uchar*) hash_key(hash,record,&length,0);
+ return (*hash->calc_hashnr)(key,length);
+}
+
+
+ /* Search after a record based on a key */
+ /* Sets info->current_ptr to found record */
+
+void* ma_hashtbl_search(MA_HASHTBL *hash,const uchar *key,uint length)
+{
+ MA_HASHTBL_LINK *pos;
+ uint flag,idx;
+
+ flag=1;
+ if (hash->records)
+ {
+ idx=hash_mask((*hash->calc_hashnr)(key,length ? length :
+ hash->key_length),
+ hash->blength,hash->records);
+ do
+ {
+ pos= dynamic_element(&hash->array,idx,MA_HASHTBL_LINK*);
+ if (!hashcmp(hash,pos,key,length))
+ {
+ hash->current_record= idx;
+ return (pos->data);
+ }
+ if (flag)
+ {
+ flag=0; /* Reset flag */
+ if (hash_rec_mask(hash,pos,hash->blength,hash->records) != idx)
+ break; /* Wrong link */
+ }
+ }
+ while ((idx=pos->next) != NO_RECORD);
+ }
+ hash->current_record= NO_RECORD;
+ return(0);
+}
+
+ /* Get next record with identical key */
+ /* Can only be called if previous calls was hash_search */
+
+void *ma_hashtbl_next(MA_HASHTBL *hash,const uchar *key,uint length)
+{
+ MA_HASHTBL_LINK *pos;
+ uint idx;
+
+ if (hash->current_record != NO_RECORD)
+ {
+ MA_HASHTBL_LINK *data=dynamic_element(&hash->array,0,MA_HASHTBL_LINK*);
+ for (idx=data[hash->current_record].next; idx != NO_RECORD ; idx=pos->next)
+ {
+ pos=data+idx;
+ if (!hashcmp(hash,pos,key,length))
+ {
+ hash->current_record= idx;
+ return pos->data;
+ }
+ }
+ hash->current_record=NO_RECORD;
+ }
+ return 0;
+}
+
+
+ /* Change link from pos to new_link */
+
+static void movelink(MA_HASHTBL_LINK *array,uint find,uint next_link,uint newlink)
+{
+ MA_HASHTBL_LINK *old_link;
+ do
+ {
+ old_link=array+next_link;
+ }
+ while ((next_link=old_link->next) != find);
+ old_link->next= newlink;
+ return;
+}
+
+ /* Compare a key in a record to a whole key. Return 0 if identical */
+
+static int hashcmp(MA_HASHTBL *hash,MA_HASHTBL_LINK *pos,const uchar *key,uint length)
+{
+ uint rec_keylength;
+ uchar *rec_key= (uchar*) hash_key(hash,pos->data,&rec_keylength,1);
+ return (length && length != rec_keylength) ||
+ memcmp(rec_key,key,rec_keylength);
+}
+
+
+ /* Write a hash-key to the hash-index */
+
+my_bool ma_hashtbl_insert(MA_HASHTBL *info,const uchar *record)
+{
+ int flag;
+ uint halfbuff,hash_nr,first_index,idx;
+ uchar *ptr_to_rec= NULL,*ptr_to_rec2= NULL;
+ MA_HASHTBL_LINK *data,*empty,*gpos= NULL,*gpos2 = NULL,*pos;
+
+ LINT_INIT(gpos); LINT_INIT(gpos2);
+ LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
+
+ flag=0;
+ if (!(empty=(MA_HASHTBL_LINK*) ma_alloc_dynamic(&info->array)))
+ return(TRUE); /* No more memory */
+
+ info->current_record= NO_RECORD;
+ data=dynamic_element(&info->array,0,MA_HASHTBL_LINK*);
+ halfbuff= info->blength >> 1;
+
+ idx=first_index=info->records-halfbuff;
+ if (idx != info->records) /* If some records */
+ {
+ do
+ {
+ pos=data+idx;
+ hash_nr=rec_hashnr(info,pos->data);
+ if (flag == 0) /* First loop; Check if ok */
+ if (hash_mask(hash_nr,info->blength,info->records) != first_index)
+ break;
+ if (!(hash_nr & halfbuff))
+ { /* Key will not move */
+ if (!(flag & LOWFIND))
+ {
+ if (flag & HIGHFIND)
+ {
+ flag=LOWFIND | HIGHFIND;
+ /* key shall be moved to the current empty position */
+ gpos=empty;
+ ptr_to_rec=pos->data;
+ empty=pos; /* This place is now free */
+ }
+ else
+ {
+ flag=LOWFIND | LOWUSED; /* key isn't changed */
+ gpos=pos;
+ ptr_to_rec=pos->data;
+ }
+ }
+ else
+ {
+ if (!(flag & LOWUSED))
+ {
+ /* Change link of previous LOW-key */
+ gpos->data=ptr_to_rec;
+ gpos->next=(uint) (pos-data);
+ flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED);
+ }
+ gpos=pos;
+ ptr_to_rec=pos->data;
+ }
+ }
+ else
+ { /* key will be moved */
+ if (!(flag & HIGHFIND))
+ {
+ flag= (flag & LOWFIND) | HIGHFIND;
+ /* key shall be moved to the last (empty) position */
+ gpos2 = empty; empty=pos;
+ ptr_to_rec2=pos->data;
+ }
+ else
+ {
+ if (!(flag & HIGHUSED))
+ {
+ /* Change link of previous hash-key and save */
+ gpos2->data=ptr_to_rec2;
+ gpos2->next=(uint) (pos-data);
+ flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED);
+ }
+ gpos2=pos;
+ ptr_to_rec2=pos->data;
+ }
+ }
+ }
+ while ((idx=pos->next) != NO_RECORD);
+
+ if ((flag & (LOWFIND | LOWUSED)) == LOWFIND)
+ {
+ gpos->data=ptr_to_rec;
+ gpos->next=NO_RECORD;
+ }
+ if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND)
+ {
+ gpos2->data=ptr_to_rec2;
+ gpos2->next=NO_RECORD;
+ }
+ }
+ /* Check if we are at the empty position */
+
+ idx=hash_mask(rec_hashnr(info,record),info->blength,info->records+1);
+ pos=data+idx;
+ if (pos == empty)
+ {
+ pos->data=(uchar*) record;
+ pos->next=NO_RECORD;
+ }
+ else
+ {
+ /* Check if more records in same hash-nr family */
+ empty[0]=pos[0];
+ gpos=data+hash_rec_mask(info,pos,info->blength,info->records+1);
+ if (pos == gpos)
+ {
+ pos->data=(uchar*) record;
+ pos->next=(uint) (empty - data);
+ }
+ else
+ {
+ pos->data=(uchar*) record;
+ pos->next=NO_RECORD;
+ movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data));
+ }
+ }
+ if (++info->records == info->blength)
+ info->blength+= info->blength;
+ return(0);
+}
+
+
+/******************************************************************************
+** Remove one record from hash-table. The record with the same record
+** ptr is removed.
+** if there is a free-function it's called for record if found
+******************************************************************************/
+
+my_bool ma_hashtbl_delete(MA_HASHTBL *hash,uchar *record)
+{
+ uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index;
+ MA_HASHTBL_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty;
+ if (!hash->records)
+ return(1);
+
+ blength=hash->blength;
+ data=dynamic_element(&hash->array,0,MA_HASHTBL_LINK*);
+ /* Search after record with key */
+ pos=data+ hash_mask(rec_hashnr(hash,record),blength,hash->records);
+ gpos = 0;
+
+ while (pos->data != record)
+ {
+ gpos=pos;
+ if (pos->next == NO_RECORD)
+ return(1); /* Key not found */
+ pos=data+pos->next;
+ }
+
+ if ( --(hash->records) < hash->blength >> 1) hash->blength>>=1;
+ hash->current_record= NO_RECORD;
+ lastpos=data+hash->records;
+
+ /* Remove link to record */
+ empty=pos; empty_index=(uint) (empty-data);
+ if (gpos)
+ gpos->next=pos->next; /* unlink current ptr */
+ else if (pos->next != NO_RECORD)
+ {
+ empty=data+(empty_index=pos->next);
+ pos->data=empty->data;
+ pos->next=empty->next;
+ }
+
+ if (empty == lastpos) /* last key at wrong pos or no next link */
+ goto exit;
+
+ /* Move the last key (lastpos) */
+ lastpos_hashnr=rec_hashnr(hash,lastpos->data);
+ /* pos is where lastpos should be */
+ pos=data+hash_mask(lastpos_hashnr,hash->blength,hash->records);
+ if (pos == empty) /* Move to empty position. */
+ {
+ empty[0]=lastpos[0];
+ goto exit;
+ }
+ pos_hashnr=rec_hashnr(hash,pos->data);
+ /* pos3 is where the pos should be */
+ pos3= data+hash_mask(pos_hashnr,hash->blength,hash->records);
+ if (pos != pos3)
+ { /* pos is on wrong posit */
+ empty[0]=pos[0]; /* Save it here */
+ pos[0]=lastpos[0]; /* This should be here */
+ movelink(data,(uint) (pos-data),(uint) (pos3-data),empty_index);
+ goto exit;
+ }
+ pos2= hash_mask(lastpos_hashnr,blength,hash->records+1);
+ if (pos2 == hash_mask(pos_hashnr,blength,hash->records+1))
+ { /* Identical key-positions */
+ if (pos2 != hash->records)
+ {
+ empty[0]=lastpos[0];
+ movelink(data,(uint) (lastpos-data),(uint) (pos-data),empty_index);
+ goto exit;
+ }
+ idx= (uint) (pos-data); /* Link pos->next after lastpos */
+ }
+ else idx= NO_RECORD; /* Different positions merge */
+
+ empty[0]=lastpos[0];
+ movelink(data,idx,empty_index,pos->next);
+ pos->next=empty_index;
+
+exit:
+ ma_pop_dynamic(&hash->array);
+ if (hash->free)
+ (*hash->free)((uchar*) record);
+ return(0);
+}
+
+ /*
+ Update keys when record has changed.
+ This is much more efficient than using a delete & insert.
+ */
+
+my_bool ma_hashtbl_update(MA_HASHTBL *hash,uchar *record,uchar *old_key,uint old_key_length)
+{
+ uint idx,new_index,new_pos_index,blength,records,empty;
+ MA_HASHTBL_LINK org_link,*data,*previous,*pos;
+
+ data=dynamic_element(&hash->array,0,MA_HASHTBL_LINK*);
+ blength=hash->blength; records=hash->records;
+
+ /* Search after record with key */
+
+ idx=hash_mask((*hash->calc_hashnr)(old_key,(old_key_length ?
+ old_key_length :
+ hash->key_length)),
+ blength,records);
+ new_index=hash_mask(rec_hashnr(hash,record),blength,records);
+ if (idx == new_index)
+ return(0); /* Nothing to do (No record check) */
+ previous=0;
+ for (;;)
+ {
+
+ if ((pos= data+idx)->data == record)
+ break;
+ previous=pos;
+ if ((idx=pos->next) == NO_RECORD)
+ return(1); /* Not found in links */
+ }
+ hash->current_record= NO_RECORD;
+ org_link= *pos;
+ empty=idx;
+
+ /* Relink record from current chain */
+
+ if (!previous)
+ {
+ if (pos->next != NO_RECORD)
+ {
+ empty=pos->next;
+ *pos= data[pos->next];
+ }
+ }
+ else
+ previous->next=pos->next; /* unlink pos */
+
+ /* Move data to correct position */
+ pos=data+new_index;
+ new_pos_index=hash_rec_mask(hash,pos,blength,records);
+ if (new_index != new_pos_index)
+ { /* Other record in wrong position */
+ data[empty] = *pos;
+ movelink(data,new_index,new_pos_index,empty);
+ org_link.next=NO_RECORD;
+ data[new_index]= org_link;
+ }
+ else
+ { /* Link in chain at right position */
+ org_link.next=data[new_index].next;
+ data[empty]=org_link;
+ data[new_index].next=empty;
+ }
+ return(0);
+}
+
+
+uchar *ma_hashtbl_element(MA_HASHTBL *hash,uint idx)
+{
+ if (idx < hash->records)
+ return dynamic_element(&hash->array,idx,MA_HASHTBL_LINK*)->data;
+ return 0;
+}
diff --git a/libmariadb/libmariadb/ma_init.c b/libmariadb/libmariadb/ma_init.c
new file mode 100644
index 00000000..008aec54
--- /dev/null
+++ b/libmariadb/libmariadb/ma_init.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include "mariadb_ctype.h"
+#include <ma_string.h>
+#include <mariadb_ctype.h>
+#include <signal.h>
+#ifdef _WIN32
+#ifdef _MSC_VER
+#include <locale.h>
+#include <crtdbg.h>
+#endif
+static my_bool my_win_init(void);
+#else
+#define my_win_init()
+#endif
+
+my_bool ma_init_done=0;
+
+
+
+/* Init ma_sys functions and ma_sys variabels */
+
+void ma_init(void)
+{
+ if (ma_init_done)
+ return;
+ ma_init_done=1;
+ {
+#ifdef _WIN32
+ my_win_init();
+#endif
+ return;
+ }
+} /* ma_init */
+
+
+
+void ma_end(int infoflag __attribute__((unused)))
+{
+#ifdef _WIN32
+ WSACleanup( );
+#endif /* _WIN32 */
+ ma_init_done=0;
+} /* ma_end */
+
+#ifdef _WIN32
+static my_bool my_win_init()
+{
+ WORD VersionRequested;
+ int err;
+ WSADATA WsaData;
+ const unsigned int MajorVersion=2,
+ MinorVersion=2;
+ VersionRequested= MAKEWORD(MajorVersion, MinorVersion);
+ /* Load WinSock library */
+ if ((err= WSAStartup(VersionRequested, &WsaData)))
+ {
+ return 0;
+ }
+ /* make sure 2.2 or higher is supported */
+ if ((LOBYTE(WsaData.wVersion) * 10 + HIBYTE(WsaData.wVersion)) < 22)
+ {
+ WSACleanup();
+ return 1;
+ }
+ return 0;
+}
+#endif
+
diff --git a/libmariadb/libmariadb/ma_io.c b/libmariadb/libmariadb/ma_io.c
new file mode 100644
index 00000000..178ffe9f
--- /dev/null
+++ b/libmariadb/libmariadb/ma_io.c
@@ -0,0 +1,224 @@
+/*
+ Copyright (C) 2015 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA
+*/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <errmsg.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <mariadb/ma_io.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_REMOTEIO
+struct st_mysql_client_plugin_REMOTEIO *rio_plugin= NULL;
+#endif
+
+/* {{{ ma_open */
+MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql)
+{
+ int CodePage= -1;
+ FILE *fp= NULL;
+ MA_FILE *ma_file= NULL;
+
+ if (!location || !location[0])
+ return NULL;
+#ifdef HAVE_REMOTEIO
+ if (strstr(location, "://"))
+ goto remote;
+#endif
+
+#ifdef _WIN32
+ if (mysql && mysql->charset)
+ CodePage= madb_get_windows_cp(mysql->charset->csname);
+#endif
+ if (CodePage == -1)
+ {
+ if (!(fp= fopen(location, mode)))
+ {
+ return NULL;
+ }
+ }
+#ifdef _WIN32
+ /* See CONC-44: we need to support non ascii filenames too, so we convert
+ current character set to wchar_t and try to open the file via _wsopen */
+ else
+ {
+ wchar_t *w_filename= NULL;
+ wchar_t *w_mode= NULL;
+ int len;
+ DWORD Length;
+
+ len= MultiByteToWideChar(CodePage, 0, location, (int)strlen(location), NULL, 0);
+ if (!len)
+ return NULL;
+ if (!(w_filename= (wchar_t *)calloc(1, (len + 1) * sizeof(wchar_t))))
+ {
+ my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return NULL;
+ }
+ Length= len;
+ len= MultiByteToWideChar(CodePage, 0, location, (int)strlen(location), w_filename, (int)Length);
+ if (!len)
+ {
+ /* todo: error handling */
+ free(w_filename);
+ return NULL;
+ }
+ len= (int)strlen(mode);
+ if (!(w_mode= (wchar_t *)calloc(1, (len + 1) * sizeof(wchar_t))))
+ {
+ my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ free(w_filename);
+ return NULL;
+ }
+ Length= len;
+ len= MultiByteToWideChar(CodePage, 0, mode, (int)strlen(mode), w_mode, (int)Length);
+ if (!len)
+ {
+ /* todo: error handling */
+ free(w_filename);
+ free(w_mode);
+ return NULL;
+ }
+ fp= _wfopen(w_filename, w_mode);
+ free(w_filename);
+ free(w_mode);
+ }
+
+#endif
+ if (fp)
+ {
+ ma_file= (MA_FILE *)malloc(sizeof(MA_FILE));
+ if (!ma_file)
+ {
+ fclose(fp);
+ my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return NULL;
+ }
+ ma_file->type= MA_FILE_LOCAL;
+ ma_file->ptr= (void *)fp;
+ }
+ return ma_file;
+#ifdef HAVE_REMOTEIO
+remote:
+ /* check if plugin for remote io is available and try
+ * to open location */
+ {
+ MYSQL mysql;
+ if (rio_plugin ||(rio_plugin= (struct st_mysql_client_plugin_REMOTEIO *)
+ mysql_client_find_plugin(&mysql, NULL, MARIADB_CLIENT_REMOTEIO_PLUGIN)))
+ return rio_plugin->methods->mopen(location, mode);
+ return NULL;
+ }
+#endif
+}
+/* }}} */
+
+/* {{{ ma_close */
+int ma_close(MA_FILE *file)
+{
+ int rc;
+ if (!file)
+ return -1;
+
+ switch (file->type) {
+ case MA_FILE_LOCAL:
+ rc= fclose((FILE *)file->ptr);
+ free(file);
+ break;
+#ifdef HAVE_REMOTEIO
+ case MA_FILE_REMOTE:
+ rc= rio_plugin->methods->mclose(file);
+ break;
+#endif
+ default:
+ return -1;
+ }
+ return rc;
+}
+/* }}} */
+
+
+/* {{{ ma_feof */
+int ma_feof(MA_FILE *file)
+{
+ if (!file)
+ return -1;
+
+ switch (file->type) {
+ case MA_FILE_LOCAL:
+ return feof((FILE *)file->ptr);
+ break;
+#ifdef HAVE_REMOTEIO
+ case MA_FILE_REMOTE:
+ return rio_plugin->methods->mfeof(file);
+ break;
+#endif
+ default:
+ return -1;
+ }
+}
+/* }}} */
+
+/* {{{ ma_read */
+size_t ma_read(void *ptr, size_t size, size_t nmemb, MA_FILE *file)
+{
+ size_t s= 0;
+ if (!file)
+ return -1;
+
+ switch (file->type) {
+ case MA_FILE_LOCAL:
+ s= fread(ptr, size, nmemb, (FILE *)file->ptr);
+ return s;
+ break;
+#ifdef HAVE_REMOTEIO
+ case MA_FILE_REMOTE:
+ return rio_plugin->methods->mread(ptr, size, nmemb, file);
+ break;
+#endif
+ default:
+ return -1;
+ }
+}
+/* }}} */
+
+/* {{{ ma_gets */
+char *ma_gets(char *ptr, size_t size, MA_FILE *file)
+{
+ if (!file)
+ return NULL;
+
+ switch (file->type) {
+ case MA_FILE_LOCAL:
+ return fgets(ptr, (int)size, (FILE *)file->ptr);
+ break;
+#ifdef HAVE_REMOTEIO
+ case MA_FILE_REMOTE:
+ return rio_plugin->methods->mgets(ptr, size, file);
+ break;
+#endif
+ default:
+ return NULL;
+ }
+}
+/* }}} */
+
+
diff --git a/libmariadb/libmariadb/ma_list.c b/libmariadb/libmariadb/ma_list.c
new file mode 100644
index 00000000..63c526f1
--- /dev/null
+++ b/libmariadb/libmariadb/ma_list.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/*
+ Code for handling dubble-linked lists in C
+*/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_list.h>
+
+ /* Add a element to start of list */
+
+LIST *list_add(LIST *root, LIST *element)
+{
+ if (root)
+ {
+ if (root->prev) /* If add in mid of list */
+ root->prev->next= element;
+ element->prev=root->prev;
+ root->prev=element;
+ }
+ else
+ element->prev=0;
+ element->next=root;
+ return(element); /* New root */
+}
+
+
+LIST *list_delete(LIST *root, LIST *element)
+{
+ if (element->prev)
+ element->prev->next=element->next;
+ else
+ root=element->next;
+ if (element->next)
+ element->next->prev=element->prev;
+ return root;
+}
+
+
+void list_free(LIST *root, unsigned int free_data)
+{
+ LIST *next;
+ while (root)
+ {
+ next=root->next;
+ if (free_data)
+ free(root->data);
+ free(root);
+ root=next;
+ }
+}
+
+
+LIST *list_cons(void *data, LIST *list)
+{
+ LIST *new_charset=(LIST*) malloc(sizeof(LIST));
+ if (!new_charset)
+ return 0;
+ new_charset->data=data;
+ return list_add(list,new_charset);
+}
+
+
+LIST *list_reverse(LIST *root)
+{
+ LIST *last;
+
+ last=root;
+ while (root)
+ {
+ last=root;
+ root=root->next;
+ last->next=last->prev;
+ last->prev=root;
+ }
+ return last;
+}
+
+uint list_length(LIST *list)
+{
+ uint count;
+ for (count=0 ; list ; list=list->next, count++) ;
+ return count;
+}
+
+
+int list_walk(LIST *list, list_walk_action action, gptr argument)
+{
+ int error=0;
+ while (list)
+ {
+ if ((error = (*action)(list->data,argument)))
+ return error;
+ list= list_rest(list);
+ }
+ return 0;
+}
diff --git a/libmariadb/libmariadb/ma_ll2str.c b/libmariadb/libmariadb/ma_ll2str.c
new file mode 100644
index 00000000..6938d37f
--- /dev/null
+++ b/libmariadb/libmariadb/ma_ll2str.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016,2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+#include <ma_global.h>
+#include "ma_string.h"
+#include <ctype.h>
+
+static char NEAR _dig_vec[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+char *ma_ll2str(long long val,char *dst,int radix)
+{
+ char buffer[65];
+ register char *p;
+ long long_val;
+
+ if (radix < 0)
+ {
+ if (radix < -36 || radix > -2) return (char*) 0;
+ if (val < 0) {
+ *dst++ = '-';
+ val = 0ULL - val;
+ }
+ radix = -radix;
+ }
+ else
+ {
+ if (radix > 36 || radix < 2) return (char*) 0;
+ }
+ if (val == 0)
+ {
+ *dst++='0';
+ *dst='\0';
+ return dst;
+ }
+ p = &buffer[sizeof(buffer)-1];
+ *p = '\0';
+
+ while ((ulonglong) val > (ulonglong) LONG_MAX)
+ {
+ ulonglong quo=(ulonglong) val/(uint) radix;
+ uint rem= (uint) (val- quo* (uint) radix);
+ *--p = _dig_vec[rem];
+ val= quo;
+ }
+ long_val= (long) val;
+ while (long_val != 0)
+ {
+ long quo= long_val/radix;
+ *--p = _dig_vec[(uchar) (long_val - quo*radix)];
+ long_val= quo;
+ }
+ while ((*dst++ = *p++) != 0) ;
+ return dst-1;
+}
diff --git a/libmariadb/libmariadb/ma_loaddata.c b/libmariadb/libmariadb/ma_loaddata.c
new file mode 100644
index 00000000..c59285ec
--- /dev/null
+++ b/libmariadb/libmariadb/ma_loaddata.c
@@ -0,0 +1,265 @@
+/************************************************************************************
+ Copyright (C) 2000, 2011 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
+ Monty Program AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*************************************************************************************/
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "ma_global.h"
+#include <ma_sys.h>
+#include <ma_string.h>
+#include "errmsg.h"
+#include "mysql.h"
+#include <mariadb/ma_io.h>
+#include <string.h>
+#ifdef _WIN32
+#include <share.h>
+#endif
+#include <ma_common.h>
+
+typedef struct st_mysql_infile_info
+{
+ MA_FILE *fp;
+ int error_no;
+ char error_msg[MYSQL_ERRMSG_SIZE + 1];
+ const char *filename;
+} MYSQL_INFILE_INFO;
+
+/* {{{ mysql_local_infile_init */
+static
+int mysql_local_infile_init(void **ptr, const char *filename, void *userdata)
+{
+ MYSQL_INFILE_INFO *info;
+ MYSQL *mysql= (MYSQL *)userdata;
+
+ info = (MYSQL_INFILE_INFO *)malloc(sizeof(MYSQL_INFILE_INFO));
+ if (!info) {
+ return(1);
+ }
+ memset(info, 0, sizeof(MYSQL_INFILE_INFO));
+ *ptr = info;
+
+ info->filename = filename;
+
+ info->fp= ma_open(filename, "rb", mysql);
+
+ if (!info->fp)
+ {
+ /* error handling is done via mysql_local_infile_error function, so we
+ need to copy error to info */
+ if (mysql_errno(mysql) && !info->error_no)
+ {
+ info->error_no= mysql_errno(mysql);
+ ma_strmake(info->error_msg, mysql_error(mysql), MYSQL_ERRMSG_SIZE);
+ }
+ else
+ {
+ info->error_no = errno;
+ snprintf((char *)info->error_msg, sizeof(info->error_msg),
+ CER(CR_FILE_NOT_FOUND), filename, info->error_no);
+ }
+ return(1);
+ }
+
+ return(0);
+}
+/* }}} */
+
+
+/* {{{ mysql_local_infile_read */
+static
+int mysql_local_infile_read(void *ptr, char * buf, unsigned int buf_len)
+{
+ MYSQL_INFILE_INFO *info = (MYSQL_INFILE_INFO *)ptr;
+ size_t count;
+
+ count= ma_read((void *)buf, 1, (size_t)buf_len, info->fp);
+
+ if (count == (size_t)-1)
+ {
+ info->error_no = errno;
+ snprintf((char *)info->error_msg, sizeof(info->error_msg),
+ CER(CR_FILE_READ), info->filename, info->error_no);
+ }
+ return((int)count);
+}
+/* }}} */
+
+
+/* {{{ mysql_local_infile_error */
+static
+int mysql_local_infile_error(void *ptr, char *error_buf, unsigned int error_buf_len)
+{
+ MYSQL_INFILE_INFO *info = (MYSQL_INFILE_INFO *)ptr;
+
+ if (info) {
+ ma_strmake(error_buf, info->error_msg, error_buf_len);
+ return(info->error_no);
+ }
+
+ ma_strmake(error_buf, "Unknown error", error_buf_len);
+ return(CR_UNKNOWN_ERROR);
+}
+/* }}} */
+
+
+/* {{{ mysql_local_infile_end */
+static
+void mysql_local_infile_end(void *ptr)
+{
+ MYSQL_INFILE_INFO *info = (MYSQL_INFILE_INFO *)ptr;
+
+ if (info)
+ {
+ if (info->fp)
+ ma_close(info->fp);
+ free(ptr);
+ }
+ return;
+}
+/* }}} */
+
+
+/* {{{ mysql_local_infile_default */
+void mysql_set_local_infile_default(MYSQL *conn)
+{
+ conn->options.local_infile_init = mysql_local_infile_init;
+ conn->options.local_infile_read = mysql_local_infile_read;
+ conn->options.local_infile_error = mysql_local_infile_error;
+ conn->options.local_infile_end = mysql_local_infile_end;
+ return;
+}
+/* }}} */
+
+/* {{{ mysql_set_local_infile_handler */
+void STDCALL mysql_set_local_infile_handler(MYSQL *conn,
+ int (*local_infile_init)(void **, const char *, void *),
+ int (*local_infile_read)(void *, char *, uint),
+ void (*local_infile_end)(void *),
+ int (*local_infile_error)(void *, char *, uint),
+ void *userdata)
+{
+ conn->options.local_infile_init= local_infile_init;
+ conn->options.local_infile_read= local_infile_read;
+ conn->options.local_infile_end= local_infile_end;
+ conn->options.local_infile_error= local_infile_error;
+ conn->options.local_infile_userdata = userdata;
+ return;
+}
+/* }}} */
+
+/* {{{ mysql_handle_local_infile */
+my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename, my_bool can_local_infile)
+{
+ unsigned int buflen= 4096;
+ int bufread;
+ unsigned char *buf= NULL;
+ void *info= NULL;
+ my_bool result= 1;
+
+ /* check if all callback functions exist */
+ if (!conn->options.local_infile_init || !conn->options.local_infile_end ||
+ !conn->options.local_infile_read || !conn->options.local_infile_error)
+ {
+ conn->options.local_infile_userdata= conn;
+ mysql_set_local_infile_default(conn);
+ }
+
+ if (!(conn->options.client_flag & CLIENT_LOCAL_FILES) ||
+ !can_local_infile)
+ {
+ my_set_error(conn, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "Load data local infile forbidden");
+ /* write empty packet to server */
+ ma_net_write(&conn->net, (unsigned char *)"", 0);
+ ma_net_flush(&conn->net);
+ goto infile_error;
+ }
+
+ /* allocate buffer for reading data */
+ buf = (uchar *)malloc(buflen);
+
+ /* init handler: allocate read buffer and open file */
+ if (conn->options.local_infile_init(&info, filename,
+ conn->options.local_infile_userdata))
+ {
+ char tmp_buf[MYSQL_ERRMSG_SIZE];
+ int tmp_errno;
+
+ tmp_errno= conn->options.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
+ my_set_error(conn, tmp_errno, SQLSTATE_UNKNOWN, tmp_buf);
+ ma_net_write(&conn->net, (unsigned char *)"", 0);
+ ma_net_flush(&conn->net);
+ goto infile_error;
+ }
+
+ /* read data */
+ while ((bufread= conn->options.local_infile_read(info, (char *)buf, buflen)) > 0)
+ {
+ if (ma_net_write(&conn->net, (unsigned char *)buf, bufread))
+ {
+ my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
+ goto infile_error;
+ }
+ }
+
+ /* send empty packet for eof */
+ if (ma_net_write(&conn->net, (unsigned char *)"", 0) ||
+ ma_net_flush(&conn->net))
+ {
+ my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
+ goto infile_error;
+ }
+
+ /* error during read occurred */
+ if (bufread < 0)
+ {
+ char tmp_buf[MYSQL_ERRMSG_SIZE];
+ int tmp_errno= conn->options.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
+ my_set_error(conn, tmp_errno, SQLSTATE_UNKNOWN, tmp_buf);
+ goto infile_error;
+ }
+
+ result = 0;
+
+infile_error:
+ conn->options.local_infile_end(info);
+ free(buf);
+ return(result);
+}
+/* }}} */
+
diff --git a/libmariadb/libmariadb/ma_net.c b/libmariadb/libmariadb/ma_net.c
new file mode 100644
index 00000000..2e932b17
--- /dev/null
+++ b/libmariadb/libmariadb/ma_net.c
@@ -0,0 +1,595 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2012-2016 SkySQL AB, MariaDB Corporation AB
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Write and read of logical packets to/from socket
+ ** Writes are cached into net_buffer_length big packets.
+ ** Read packets are reallocated dynamically when reading big packets.
+ ** Each logical packet has the following pre-info:
+ ** 3 byte length & 1 byte package-number.
+ */
+
+
+#include <ma_global.h>
+#include <mysql.h>
+#include <ma_pvio.h>
+#include <ma_sys.h>
+#include <ma_string.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <ma_pvio.h>
+#include <ma_common.h>
+#ifndef _WIN32
+#include <poll.h>
+#endif
+
+#define MAX_PACKET_LENGTH (256L*256L*256L-1)
+
+/* net_buffer_length and max_allowed_packet are defined in mysql.h
+ See bug conc-57
+ */
+#undef net_buffer_length
+
+#undef max_allowed_packet
+ulong max_allowed_packet=1024L * 1024L * 1024L;
+ulong net_read_timeout= NET_READ_TIMEOUT;
+ulong net_write_timeout= NET_WRITE_TIMEOUT;
+ulong net_buffer_length= 8192; /* Default length. Enlarged if necessary */
+
+#if !defined(_WIN32)
+#include <sys/socket.h>
+#else
+#undef MYSQL_SERVER /* Win32 can't handle interrupts */
+#endif
+#if !defined(_WIN32) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__)
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#if !defined(alpha_linux_port)
+#include <netinet/tcp.h>
+#endif
+#endif
+
+
+/*
+ ** Give error if a too big packet is found
+ ** The server can change this with the -O switch, but because the client
+ ** can't normally do this the client should have a bigger max-buffer.
+ */
+
+static int ma_net_write_buff(NET *net,const char *packet, size_t len);
+
+
+/* Init with packet info */
+
+int ma_net_init(NET *net, MARIADB_PVIO* pvio)
+{
+ if (!(net->buff=(uchar*) malloc(net_buffer_length)))
+ return 1;
+ if (!net->extension)
+ return 1;
+
+ memset(net->buff, 0, net_buffer_length);
+
+ net->max_packet_size= MAX(net_buffer_length, max_allowed_packet);
+ net->buff_end=net->buff+(net->max_packet=net_buffer_length);
+ net->pvio = pvio;
+ net->error=0; net->return_status=0;
+ net->read_timeout=(uint) net_read_timeout; /* Timeout for read */
+ net->compress_pkt_nr= net->pkt_nr= 0;
+ net->write_pos=net->read_pos = net->buff;
+ net->last_error[0]= net->sqlstate[0] =0;
+
+ net->compress=0; net->reading_or_writing=0;
+ net->where_b = net->remain_in_buf=0;
+ net->last_errno=0;
+
+ if (pvio != 0) /* If real connection */
+ {
+ ma_pvio_get_handle(pvio, &net->fd);
+ ma_pvio_blocking(pvio, 1, 0);
+ ma_pvio_fast_send(pvio);
+ }
+ return 0;
+}
+
+void ma_net_end(NET *net)
+{
+ free(net->buff);
+ net->buff=0;
+}
+
+/* Realloc the packet buffer */
+
+static my_bool net_realloc(NET *net, size_t length)
+{
+ uchar *buff;
+ size_t pkt_length;
+
+ if (length >= net->max_packet_size)
+ {
+ net->error=1;
+ net->pvio->set_error(net->pvio->mysql, CR_NET_PACKET_TOO_LARGE, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
+ /* reallocate buffer:
+ size= pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE */
+ if (!(buff=(uchar*) realloc(net->buff,
+ pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE)))
+ {
+ net->error=1;
+ return(1);
+ }
+ net->buff=net->write_pos=buff;
+ net->buff_end=buff+(net->max_packet=(unsigned long)pkt_length);
+ return(0);
+}
+
+/* Remove unwanted characters from connection */
+void ma_net_clear(NET *net)
+{
+ if (net->extension->multi_status > COM_MULTI_OFF)
+ return;
+ net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */
+ net->write_pos=net->buff;
+ return;
+}
+
+/* Flush write_buffer if not empty. */
+int ma_net_flush(NET *net)
+{
+ int error=0;
+
+ /* don't flush if pipelined query is in progress */
+ if (net->extension->multi_status > COM_MULTI_OFF)
+ return 0;
+
+ if (net->buff != net->write_pos)
+ {
+ error=ma_net_real_write(net,(char*) net->buff,
+ (size_t) (net->write_pos - net->buff));
+ net->write_pos=net->buff;
+ }
+ if (net->compress)
+ net->pkt_nr= net->compress_pkt_nr;
+ return(error);
+}
+
+/*****************************************************************************
+ ** Write something to server/client buffer
+ *****************************************************************************/
+
+/*
+ ** Write a logical packet with packet header
+ ** Format: Packet length (3 bytes), packet number(1 byte)
+ ** When compression is used a 3 byte compression length is added
+ ** NOTE: If compression is used the original package is destroyed!
+ */
+
+int ma_net_write(NET *net, const uchar *packet, size_t len)
+{
+ uchar buff[NET_HEADER_SIZE];
+ while (len >= MAX_PACKET_LENGTH)
+ {
+ const ulong max_len= MAX_PACKET_LENGTH;
+ int3store(buff,max_len);
+ buff[3]= (uchar)net->pkt_nr++;
+ if (ma_net_write_buff(net,(char*) buff,NET_HEADER_SIZE) ||
+ ma_net_write_buff(net, (char *)packet, max_len))
+ return 1;
+ packet+= max_len;
+ len-= max_len;
+ }
+ /* write last remaining packet, size can be zero */
+ int3store(buff, len);
+ buff[3]= (uchar)net->pkt_nr++;
+ if (ma_net_write_buff(net,(char*) buff,NET_HEADER_SIZE) ||
+ ma_net_write_buff(net, (char *)packet, len))
+ return 1;
+ return 0;
+}
+
+int ma_net_write_command(NET *net, uchar command,
+ const char *packet, size_t len,
+ my_bool disable_flush)
+{
+ uchar buff[NET_HEADER_SIZE+1];
+ size_t buff_size= NET_HEADER_SIZE + 1;
+ size_t length= 1 + len; /* 1 extra byte for command */
+ int rc;
+
+ buff[NET_HEADER_SIZE]= 0;
+ buff[4]=command;
+
+ if (length >= MAX_PACKET_LENGTH)
+ {
+ len= MAX_PACKET_LENGTH - 1;
+ do
+ {
+ int3store(buff, MAX_PACKET_LENGTH);
+ buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
+
+ if (ma_net_write_buff(net, (char *)buff, buff_size) ||
+ ma_net_write_buff(net, packet, len))
+ return(1);
+ packet+= len;
+ length-= MAX_PACKET_LENGTH;
+ len= MAX_PACKET_LENGTH;
+ buff_size= NET_HEADER_SIZE; /* don't send command for further packets */
+ } while (length >= MAX_PACKET_LENGTH);
+ len= length;
+ }
+ int3store(buff,length);
+ buff[3]= (net->compress) ? 0 :(uchar) (net->pkt_nr++);
+ rc= test (ma_net_write_buff(net,(char *)buff, buff_size) ||
+ ma_net_write_buff(net,packet,len));
+ if (!rc && !disable_flush)
+ return test(ma_net_flush(net));
+ return rc;
+}
+
+
+static int ma_net_write_buff(NET *net,const char *packet, size_t len)
+{
+ size_t left_length;
+
+ if (!len)
+ return 0;
+
+ if (net->max_packet > MAX_PACKET_LENGTH &&
+ net->compress)
+ left_length= (size_t)(MAX_PACKET_LENGTH - (net->write_pos - net->buff));
+ else
+ left_length=(size_t) (net->buff_end - net->write_pos);
+
+ if (len > left_length)
+ {
+ if (net->write_pos != net->buff)
+ {
+ memcpy((char*) net->write_pos,packet,left_length);
+ if (ma_net_real_write(net,(char*) net->buff,
+ (size_t)(net->write_pos - net->buff) + left_length))
+ return 1;
+ packet+=left_length;
+ len-=left_length;
+ net->write_pos= net->buff;
+ }
+ if (net->compress)
+ {
+ /* uncompressed length is stored in 3 bytes,so
+ packet can't be > 0xFFFFFF */
+ left_length= MAX_PACKET_LENGTH;
+ while (len > left_length)
+ {
+ if (ma_net_real_write(net, packet, left_length))
+ return 1;
+ packet+= left_length;
+ len-= left_length;
+ }
+ }
+ if (len > net->max_packet)
+ return(test(ma_net_real_write(net, packet, len)));
+ }
+ memcpy((char*) net->write_pos,packet,len);
+ net->write_pos+=len;
+ return 0;
+}
+
+unsigned char *mysql_net_store_length(unsigned char *packet, ulonglong length);
+
+/* Read and write using timeouts */
+
+int ma_net_real_write(NET *net, const char *packet, size_t len)
+{
+ ssize_t length;
+ char *pos,*end;
+
+ if (net->error == 2)
+ return(-1); /* socket can't be used */
+
+ net->reading_or_writing=2;
+#ifdef HAVE_COMPRESS
+ if (net->compress)
+ {
+ size_t complen;
+ uchar *b;
+ uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
+ if (!(b=(uchar*) malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1)))
+ {
+ net->pvio->set_error(net->pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ net->error=2;
+ net->reading_or_writing=0;
+ return(1);
+ }
+ memcpy(b+header_length,packet,len);
+
+ if (_mariadb_compress(net, (unsigned char*) b+header_length,&len,&complen))
+ {
+ complen=0;
+ }
+ int3store(&b[NET_HEADER_SIZE],complen);
+ int3store(b,len);
+ b[3]=(uchar) (net->compress_pkt_nr++);
+ len+= header_length;
+ packet= (char*) b;
+ }
+#endif /* HAVE_COMPRESS */
+
+ pos=(char*) packet; end=pos+len;
+ while (pos != end)
+ {
+ if ((length=ma_pvio_write(net->pvio,(uchar *)pos,(size_t) (end-pos))) <= 0)
+ {
+ int save_errno= errno;
+ char errmsg[100];
+
+ net->error=2; /* Close socket */
+ strerror_r(save_errno, errmsg, 100);
+ net->pvio->set_error(net->pvio->mysql, CR_ERR_NET_WRITE, SQLSTATE_UNKNOWN, 0,
+ errmsg, save_errno);
+ net->reading_or_writing=0;
+#ifdef HAVE_COMPRESS
+ if (net->compress)
+ free((char*) packet);
+#endif
+ return(1);
+ }
+ pos+=length;
+ }
+#ifdef HAVE_COMPRESS
+ if (net->compress)
+ free((char*) packet);
+#endif
+ net->reading_or_writing=0;
+ return(((int) (pos != end)));
+}
+
+/*****************************************************************************
+ ** Read something from server/clinet
+ *****************************************************************************/
+static ulong ma_real_read(NET *net, size_t *complen)
+{
+ uchar *pos;
+ ssize_t length;
+ uint i;
+ ulong len=packet_error;
+ size_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
+ NET_HEADER_SIZE);
+ *complen = 0;
+
+ net->reading_or_writing=1;
+
+ pos = net->buff + net->where_b; /* net->packet -4 */
+ for (i=0 ; i < 2 ; i++)
+ {
+ while (remain > 0)
+ {
+ /* First read is done with non blocking mode */
+ if ((length=ma_pvio_cache_read(net->pvio, pos,remain)) <= 0L)
+ {
+ len= packet_error;
+ net->error=2; /* Close socket */
+ goto end;
+ }
+ remain -= (ulong) length;
+ pos+= (ulong) length;
+ }
+
+ if (i == 0)
+ { /* First parts is packet length */
+ ulong helping;
+ net->pkt_nr= net->buff[net->where_b + 3];
+ net->compress_pkt_nr= ++net->pkt_nr;
+#ifdef HAVE_COMPRESS
+ if (net->compress)
+ {
+ /* complen is > 0 if package is really compressed */
+ *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
+ }
+#endif
+
+ len=uint3korr(net->buff+net->where_b);
+ if (!len)
+ goto end;
+ helping = max(len,(ulong)*complen) + net->where_b;
+ /* The necessary size of net->buff */
+ if (helping >= net->max_packet)
+ {
+ if (net_realloc(net, helping))
+ {
+ len= packet_error; /* Return error */
+ goto end;
+ }
+ }
+ pos=net->buff + net->where_b;
+ remain = len;
+ }
+ }
+
+end:
+ net->reading_or_writing=0;
+ return(len);
+}
+
+ulong ma_net_read(NET *net)
+{
+ size_t len,complen;
+
+#ifdef HAVE_COMPRESS
+ if (!net->compress)
+ {
+#endif
+ len = ma_real_read (net,(size_t *)&complen);
+ if (len == MAX_PACKET_LENGTH)
+ {
+ /* multi packet read */
+ size_t length= 0;
+ ulong last_pos= net->where_b;
+
+ do
+ {
+ length+= len;
+ net->where_b+= (unsigned long)len;
+ len= ma_real_read(net, &complen);
+ } while (len == MAX_PACKET_LENGTH);
+ net->where_b= last_pos;
+ if (len != packet_error)
+ len+= length;
+ }
+ net->read_pos = net->buff + net->where_b;
+ if (len != packet_error)
+ net->read_pos[len]=0; /* Safeguard for mysql_use_result */
+ return (ulong)len;
+#ifdef HAVE_COMPRESS
+ }
+ else
+ {
+ /*
+ compressed protocol:
+
+ --------------------------------------
+ packet_length 3
+ sequence_id 1
+ uncompressed_length 3
+ --------------------------------------
+ compressed data packet_length - 7
+ --------------------------------------
+
+ Another packet will follow if:
+ packet_length == MAX_PACKET_LENGTH
+
+ Last package will be identified by
+ - packet_length is zero (special case)
+ - packet_length < MAX_PACKET_LENGTH
+ */
+
+ size_t packet_length,
+ buffer_length;
+ size_t current= 0, start= 0;
+ my_bool is_multi_packet= 0;
+
+ /* check if buffer is empty */
+ if (!net->remain_in_buf)
+ {
+ buffer_length= 0;
+ }
+ else
+ {
+ /* save position and restore \0 character */
+ buffer_length= net->buf_length;
+ current= net->buf_length - net->remain_in_buf;
+ start= current;
+ net->buff[net->buf_length - net->remain_in_buf]=net->save_char;
+ }
+ for (;;)
+ {
+ if (buffer_length - current >= 4)
+ {
+ uchar *pos= net->buff + current;
+ packet_length= uint3korr(pos);
+
+ /* check if we have last package (special case: zero length) */
+ if (!packet_length)
+ {
+ current+= 4; /* length + sequence_id,
+ no more data will follow */
+ break;
+ }
+ if (packet_length + 4 <= buffer_length - current)
+ {
+ if (!is_multi_packet)
+ {
+ current= current + packet_length + 4;
+ }
+ else
+ {
+ /* remove packet_header */
+ memmove(net->buff + current,
+ net->buff + current + 4,
+ buffer_length - current);
+ buffer_length-= 4;
+ current+= packet_length;
+ }
+ /* do we have last packet ? */
+ if (packet_length != MAX_PACKET_LENGTH)
+ {
+ is_multi_packet= 0;
+ break;
+ }
+ else
+ is_multi_packet= 1;
+ if (start)
+ {
+ memmove(net->buff, net->buff + start,
+ buffer_length - start);
+ /* decrease buflen*/
+ buffer_length-= start;
+ start= 0;
+ }
+ continue;
+ }
+ }
+ if (start)
+ {
+ memmove(net->buff, net->buff + start, buffer_length - start);
+ /* decrease buflen and current */
+ current -= start;
+ buffer_length-= start;
+ start= 0;
+ }
+
+ net->where_b=(unsigned long)buffer_length;
+
+ if ((packet_length = ma_real_read(net,(size_t *)&complen)) == packet_error)
+ return packet_error;
+ if (_mariadb_uncompress(net, (unsigned char*) net->buff + net->where_b, &packet_length, &complen))
+ {
+ net->error=2; /* caller will close socket */
+ net->pvio->set_error(net->pvio->mysql, CR_ERR_NET_UNCOMPRESS, SQLSTATE_UNKNOWN, 0);
+ return packet_error;
+ }
+ buffer_length+= complen;
+ }
+ /* set values */
+ net->buf_length= (unsigned long)buffer_length;
+ net->remain_in_buf= (unsigned long)(buffer_length - current);
+ net->read_pos= net->buff + start + 4;
+ len= current - start - 4;
+ if (is_multi_packet)
+ len-= 4;
+ net->save_char= net->read_pos[len]; /* Must be saved */
+ net->read_pos[len]=0; /* Safeguard for mysql_use_result */
+ }
+#endif
+ return (ulong)len;
+}
+
+int net_add_multi_command(NET *net, uchar command, const uchar *packet,
+ size_t length)
+{
+ if (net->extension->multi_status == COM_MULTI_OFF)
+ {
+ return(1);
+ }
+ /* don't increase packet number */
+ net->compress_pkt_nr= net->pkt_nr= 0;
+ return ma_net_write_command(net, command, (const char *)packet, length, 1);
+}
+
diff --git a/libmariadb/libmariadb/ma_password.c b/libmariadb/libmariadb/ma_password.c
new file mode 100644
index 00000000..eb6fe6a8
--- /dev/null
+++ b/libmariadb/libmariadb/ma_password.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016,2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* password checking routines */
+/*****************************************************************************
+ The main idea is that no password are sent between client & server on
+ connection and that no password are saved in mysql in a decodable form.
+
+ On connection a random string is generated and sent to the client.
+ The client generates a new string with a random generator inited with
+ the hash values from the password and the sent string.
+ This 'check' string is sent to the server where it is compared with
+ a string generated from the stored hash_value of the password and the
+ random string.
+
+ The password is saved (in user.password) by using the PASSWORD() function in
+ mysql.
+
+ Example:
+ update user set password=PASSWORD("hello") where user="test"
+ This saves a hashed number as a string in the password field.
+*****************************************************************************/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_string.h>
+#include <ma_sha1.h>
+#include "mysql.h"
+
+
+void ma_randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
+{ /* For mysql 3.21.# */
+#ifdef HAVE_purify
+ memset((char*) rand_st, 0m sizeof(*rand_st)); /* Avoid UMC warnings */
+#endif
+ rand_st->max_value= 0x3FFFFFFFL;
+ rand_st->max_value_dbl=(double) rand_st->max_value;
+ rand_st->seed1=seed1%rand_st->max_value ;
+ rand_st->seed2=seed2%rand_st->max_value;
+}
+
+double rnd(struct rand_struct *rand_st)
+{
+ rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
+ rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
+ return (((double) rand_st->seed1)/rand_st->max_value_dbl);
+}
+
+void ma_hash_password(ulong *result, const char *password, size_t len)
+{
+ register ulong nr=1345345333L, add=7, nr2=0x12345671L;
+ ulong tmp;
+ const char *password_end= password + len;
+ for (; password < password_end; password++)
+ {
+ if (*password == ' ' || *password == '\t')
+ continue; /* skip space in password */
+ tmp= (ulong) (uchar) *password;
+ nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
+ nr2+=(nr2 << 8) ^ nr;
+ add+=tmp;
+ }
+ result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
+ result[1]=nr2 & (((ulong) 1L << 31) -1L);
+ return;
+}
+
+/*
+ * Generate a new message based on message and password
+ * The same thing is done in client and server and the results are checked.
+ */
+
+/* scramble for 4.1 servers
+ * Code based on php_nysqlnd_scramble function from PHP's mysqlnd extension,
+ * written by Andrey Hristov (andrey@php.net)
+ * License: PHP License 3.0
+ */
+void my_crypt(unsigned char *buffer, const unsigned char *s1, const unsigned char *s2, size_t len)
+{
+ const unsigned char *s1_end= s1 + len;
+ while (s1 < s1_end) {
+ *buffer++= *s1++ ^ *s2++;
+ }
+}
+
+void ma_scramble_41(const unsigned char *buffer, const char *scramble, const char *password)
+{
+ _MA_SHA1_CTX context;
+ unsigned char sha1[SHA1_MAX_LENGTH];
+ unsigned char sha2[SHA1_MAX_LENGTH];
+
+
+ /* Phase 1: hash password */
+ ma_SHA1Init(&context);
+ ma_SHA1Update(&context, (unsigned char *)password, strlen((char *)password));
+ ma_SHA1Final(sha1, &context);
+
+ /* Phase 2: hash sha1 */
+ ma_SHA1Init(&context);
+ ma_SHA1Update(&context, (unsigned char*)sha1, SHA1_MAX_LENGTH);
+ ma_SHA1Final(sha2, &context);
+
+ /* Phase 3: hash scramble + sha2 */
+ ma_SHA1Init(&context);
+ ma_SHA1Update(&context, (unsigned char *)scramble, SCRAMBLE_LENGTH);
+ ma_SHA1Update(&context, (unsigned char*)sha2, SHA1_MAX_LENGTH);
+ ma_SHA1Final((unsigned char *)buffer, &context);
+
+ /* let's crypt buffer now */
+ my_crypt((uchar *)buffer, (const unsigned char *)buffer, (const unsigned char *)sha1, SHA1_MAX_LENGTH);
+}
+/* }}} */
+
+void ma_make_scrambled_password(char *to,const char *password)
+{
+ ulong hash_res[2];
+ ma_hash_password(hash_res,password, strlen(password));
+ sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
+}
+
+/*
+ * Generate a new message based on message and password
+ * The same thing is done in client and server and the results are checked.
+ */
+char *ma_scramble_323(char *to, const char *message, const char *password)
+{
+ struct rand_struct rand_st;
+ ulong hash_pass[2], hash_message[2];
+
+ if (password && password[0])
+ {
+ char extra, *to_start=to;
+ const char *end_scramble323= message + SCRAMBLE_LENGTH_323;
+ ma_hash_password(hash_pass,password, (uint) strlen(password));
+ /* Don't use strlen, could be > SCRAMBLE_LENGTH_323 ! */
+ ma_hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
+ ma_randominit(&rand_st, hash_pass[0] ^ hash_message[0],
+ hash_pass[1] ^ hash_message[1]);
+ for (; message < end_scramble323; message++)
+ *to++= (char) (floor(rnd(&rand_st) * 31) + 64);
+ extra=(char) (floor(rnd(&rand_st) * 31));
+ while (to_start != to)
+ *(to_start++)^= extra;
+ }
+ *to= 0;
+ return to;
+}
diff --git a/libmariadb/libmariadb/ma_pvio.c b/libmariadb/libmariadb/ma_pvio.c
new file mode 100644
index 00000000..a8a653b6
--- /dev/null
+++ b/libmariadb/libmariadb/ma_pvio.c
@@ -0,0 +1,598 @@
+/************************************************************************************
+ Copyright (C) 2015, 2022 MariaDB Corporation AB,
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+
+/* MariaDB Communication IO (PVIO) interface
+
+ PVIO is the interface for client server communication and replaces former vio
+ component of the client library.
+
+ PVIO support various protocols like sockets, pipes and shared memory, which are
+ implemented as plugins and can be extended therefore easily.
+
+ Interface function description:
+
+ ma_pvio_init allocates a new PVIO object which will be used
+ for the current connection
+
+ ma_pvio_close frees all resources of previously allocated PVIO object
+ and closes open connections
+
+ ma_pvio_read reads data from server
+
+ ma_pvio_write sends data to server
+
+ ma_pvio_set_timeout sets timeout for connection, read and write
+
+ ma_pvio_register_callback
+ register callback functions for read and write
+ */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <mysql.h>
+#include <errmsg.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <ma_common.h>
+#include <ma_pvio.h>
+#include <mariadb_async.h>
+#include <ma_context.h>
+
+/* callback functions for read/write */
+LIST *pvio_callback= NULL;
+
+#define IS_BLOCKING_ERROR() \
+ IF_WIN(WSAGetLastError() != WSAEWOULDBLOCK, \
+ (errno != EAGAIN && errno != EINTR))
+
+/* {{{ MARIADB_PVIO *ma_pvio_init */
+MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo)
+{
+ /* check connection type and load the required plugin.
+ * Currently we support the following pvio types:
+ * pvio_socket
+ * pvio_namedpipe
+ * pvio_sharedmed
+ */
+ const char *pvio_plugins[] = {"pvio_socket", "pvio_npipe", "pvio_shmem"};
+ int type;
+ MARIADB_PVIO_PLUGIN *pvio_plugin;
+ MARIADB_PVIO *pvio= NULL;
+
+ switch (cinfo->type)
+ {
+ case PVIO_TYPE_UNIXSOCKET:
+ case PVIO_TYPE_SOCKET:
+ type= 0;
+ break;
+#ifdef _WIN32
+ case PVIO_TYPE_NAMEDPIPE:
+ type= 1;
+ break;
+ case PVIO_TYPE_SHAREDMEM:
+ type= 2;
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ if (!(pvio_plugin= (MARIADB_PVIO_PLUGIN *)
+ mysql_client_find_plugin(cinfo->mysql,
+ pvio_plugins[type],
+ MARIADB_CLIENT_PVIO_PLUGIN)))
+ {
+ /* error already set in mysql_client_find_plugin */
+ return NULL;
+ }
+
+/* coverity[var_deref_op] */
+ if (!(pvio= (MARIADB_PVIO *)calloc(1, sizeof(MARIADB_PVIO))))
+ {
+ my_set_error(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
+ return NULL;
+ }
+
+ /* register error routine and methods */
+ pvio->methods= pvio_plugin->methods;
+ pvio->set_error= my_set_error;
+ pvio->type= cinfo->type;
+
+ /* set timeout to connect timeout - after successful connect we will set
+ * correct values for read and write */
+ if (pvio->methods->set_timeout)
+ {
+ pvio->methods->set_timeout(pvio, PVIO_CONNECT_TIMEOUT, cinfo->mysql->options.connect_timeout);
+ pvio->methods->set_timeout(pvio, PVIO_READ_TIMEOUT, cinfo->mysql->options.connect_timeout);
+ pvio->methods->set_timeout(pvio, PVIO_WRITE_TIMEOUT, cinfo->mysql->options.connect_timeout);
+ }
+
+ if (!(pvio->cache= calloc(1, PVIO_READ_AHEAD_CACHE_SIZE)))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
+ free(pvio);
+ return NULL;
+ }
+ pvio->cache_size= 0;
+ pvio->cache_pos= pvio->cache;
+
+ return pvio;
+}
+/* }}} */
+
+/* {{{ my_bool ma_pvio_is_alive */
+my_bool ma_pvio_is_alive(MARIADB_PVIO *pvio)
+{
+ if (!pvio)
+ return FALSE;
+ if (pvio->methods->is_alive)
+ return pvio->methods->is_alive(pvio);
+ return TRUE;
+}
+/* }}} */
+
+/* {{{ int ma_pvio_fast_send */
+int ma_pvio_fast_send(MARIADB_PVIO *pvio)
+{
+ if (!pvio || !pvio->methods->fast_send)
+ return 1;
+ return pvio->methods->fast_send(pvio);
+}
+/* }}} */
+
+/* {{{ int ma_pvio_keepalive */
+int ma_pvio_keepalive(MARIADB_PVIO *pvio)
+{
+ if (!pvio || !pvio->methods->keepalive)
+ return 1;
+ return pvio->methods->keepalive(pvio);
+}
+/* }}} */
+
+/* {{{ my_bool ma_pvio_set_timeout */
+my_bool ma_pvio_set_timeout(MARIADB_PVIO *pvio,
+ enum enum_pvio_timeout type,
+ int timeout)
+{
+ if (!pvio)
+ return 1;
+
+ if (pvio->methods->set_timeout)
+ return pvio->methods->set_timeout(pvio, type, timeout);
+ return 1;
+}
+/* }}} */
+
+/* {{{ size_t ma_pvio_read_async */
+static size_t ma_pvio_read_async(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
+{
+ ssize_t res= 0;
+ struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
+ int timeout= pvio->timeout[PVIO_READ_TIMEOUT];
+
+ if (!pvio->methods->async_read)
+ {
+ PVIO_SET_ERROR(pvio->mysql, CR_ASYNC_NOT_SUPPORTED, unknown_sqlstate, 0);
+ return -1;
+ }
+
+ for (;;)
+ {
+ if (pvio->methods->async_read)
+ res= pvio->methods->async_read(pvio, buffer, length);
+ if (res >= 0 || IS_BLOCKING_ERROR())
+ return res;
+ b->events_to_wait_for= MYSQL_WAIT_READ;
+ if (timeout >= 0)
+ {
+ b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
+ b->timeout_value= timeout;
+ }
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ if (b->events_occurred & MYSQL_WAIT_TIMEOUT)
+ return -1;
+ }
+}
+/* }}} */
+
+/* {{{ size_t ma_pvio_read */
+ssize_t ma_pvio_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
+{
+ ssize_t r= -1;
+ if (!pvio)
+ return -1;
+ if (IS_PVIO_ASYNC_ACTIVE(pvio))
+ {
+ r=
+#if defined(HAVE_TLS) && !defined(HAVE_SCHANNEL)
+ (pvio->ctls) ? ma_tls_read_async(pvio, buffer, length) :
+#endif
+ (ssize_t)ma_pvio_read_async(pvio, buffer, length);
+ goto end;
+ }
+ else
+ {
+ if (IS_PVIO_ASYNC(pvio))
+ {
+ /*
+ If switching from non-blocking to blocking API usage, set the socket
+ back to blocking mode.
+ */
+ my_bool old_mode;
+ ma_pvio_blocking(pvio, TRUE, &old_mode);
+ }
+ }
+
+ /* secure connection */
+#ifdef HAVE_TLS
+ if (pvio->ctls)
+ {
+ r= ma_pvio_tls_read(pvio->ctls, buffer, length);
+ goto end;
+ }
+#endif
+ if (pvio->methods->read)
+ r= pvio->methods->read(pvio, buffer, length);
+end:
+ if (pvio_callback)
+ {
+ void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
+ LIST *p= pvio_callback;
+ while (p)
+ {
+ callback= p->data;
+ callback(0, pvio->mysql, buffer, r);
+ p= p->next;
+ }
+ }
+ if (r > 0)
+ pvio->bytes_read+= r;
+ return r;
+}
+/* }}} */
+
+/* {{{ size_t ma_pvio_cache_read */
+ssize_t ma_pvio_cache_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
+{
+ ssize_t r;
+
+ if (!pvio)
+ return -1;
+
+ if (!pvio->cache)
+ return ma_pvio_read(pvio, buffer, length);
+
+ if (pvio->cache + pvio->cache_size > pvio->cache_pos)
+ {
+ ssize_t remaining = pvio->cache + pvio->cache_size - pvio->cache_pos;
+ assert(remaining > 0);
+ r= MIN((ssize_t)length, remaining);
+ memcpy(buffer, pvio->cache_pos, r);
+ pvio->cache_pos+= r;
+ }
+ else if (length >= PVIO_READ_AHEAD_CACHE_MIN_SIZE)
+ {
+ r= ma_pvio_read(pvio, buffer, length);
+ }
+ else
+ {
+ r= ma_pvio_read(pvio, pvio->cache, PVIO_READ_AHEAD_CACHE_SIZE);
+ if (r > 0)
+ {
+ if (length < (size_t)r)
+ {
+ pvio->cache_size= r;
+ pvio->cache_pos= pvio->cache + length;
+ r= length;
+ }
+ memcpy(buffer, pvio->cache, r);
+ }
+ }
+ return r;
+}
+/* }}} */
+
+/* {{{ size_t ma_pvio_write_async */
+static ssize_t ma_pvio_write_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ ssize_t res;
+ struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
+ int timeout= pvio->timeout[PVIO_WRITE_TIMEOUT];
+
+ for (;;)
+ {
+ res= pvio->methods->async_write(pvio, buffer, length);
+ if (res >= 0 || IS_BLOCKING_ERROR())
+ return res;
+ b->events_to_wait_for= MYSQL_WAIT_WRITE;
+ if (timeout >= 0)
+ {
+ b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
+ b->timeout_value= timeout;
+ }
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ if (b->events_occurred & MYSQL_WAIT_TIMEOUT)
+ return -1;
+ }
+}
+/* }}} */
+
+/* {{{ size_t ma_pvio_write */
+ssize_t ma_pvio_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ ssize_t r= 0;
+
+ if (!pvio)
+ return -1;
+
+ if (IS_PVIO_ASYNC_ACTIVE(pvio))
+ {
+ r=
+#if defined(HAVE_TLS) && !defined(HAVE_SCHANNEL)
+ (pvio->ctls) ? ma_tls_write_async(pvio, buffer, length) :
+#endif
+ ma_pvio_write_async(pvio, buffer, length);
+ goto end;
+ }
+ else
+ {
+ if (IS_PVIO_ASYNC(pvio))
+ {
+ /*
+ If switching from non-blocking to blocking API usage, set the socket
+ back to blocking mode.
+ */
+ my_bool old_mode;
+ ma_pvio_blocking(pvio, TRUE, &old_mode);
+ }
+ }
+ /* secure connection */
+#ifdef HAVE_TLS
+ if (pvio->ctls)
+ {
+ r= ma_pvio_tls_write(pvio->ctls, buffer, length);
+ goto end;
+ }
+#endif
+
+ if (pvio->methods->write)
+ r= pvio->methods->write(pvio, buffer, length);
+end:
+ if (pvio_callback)
+ {
+ void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
+ LIST *p= pvio_callback;
+ while (p)
+ {
+ callback= p->data;
+ callback(1, pvio->mysql, buffer, r);
+ p= p->next;
+ }
+ }
+ if (r > 0)
+ pvio->bytes_sent+= r;
+ return r;
+}
+/* }}} */
+
+/* {{{ void ma_pvio_close */
+void ma_pvio_close(MARIADB_PVIO *pvio)
+{
+ /* free internal structures and close connection */
+ if (pvio)
+ {
+#ifdef HAVE_TLS
+ if (pvio->ctls)
+ {
+ ma_pvio_tls_close(pvio->ctls);
+ free(pvio->ctls);
+ }
+#endif
+ if (pvio && pvio->methods->close)
+ pvio->methods->close(pvio);
+
+ if (pvio->cache)
+ free(pvio->cache);
+
+ free(pvio);
+ }
+}
+/* }}} */
+
+/* {{{ my_bool ma_pvio_get_handle */
+my_bool ma_pvio_get_handle(MARIADB_PVIO *pvio, void *handle)
+{
+ if (pvio && pvio->methods->get_handle)
+ return pvio->methods->get_handle(pvio, handle);
+ return 1;
+}
+/* }}} */
+
+/* {{{ ma_pvio_wait_async */
+static my_bool
+ma_pvio_wait_async(struct mysql_async_context *b, enum enum_pvio_io_event event,
+ int timeout)
+{
+ switch (event)
+ {
+ case VIO_IO_EVENT_READ:
+ b->events_to_wait_for = MYSQL_WAIT_READ;
+ break;
+ case VIO_IO_EVENT_WRITE:
+ b->events_to_wait_for = MYSQL_WAIT_WRITE;
+ break;
+ case VIO_IO_EVENT_CONNECT:
+ b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT);
+ break;
+ }
+
+ if (timeout >= 0)
+ {
+ b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT;
+ b->timeout_value= timeout;
+ }
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ return (b->events_occurred & MYSQL_WAIT_TIMEOUT) ? 0 : 1;
+}
+/* }}} */
+
+/* {{{ ma_pvio_wait_io_or_timeout */
+int ma_pvio_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
+{
+ if (pvio)
+ {
+ if (IS_PVIO_ASYNC_ACTIVE(pvio))
+ return ma_pvio_wait_async(pvio->mysql->options.extension->async_context,
+ (is_read) ? VIO_IO_EVENT_READ : VIO_IO_EVENT_WRITE,
+ timeout);
+
+ if (pvio && pvio->methods->wait_io_or_timeout)
+ return pvio->methods->wait_io_or_timeout(pvio, is_read, timeout);
+ }
+ return 1;
+}
+/* }}} */
+
+/* {{{ my_bool ma_pvio_connect */
+my_bool ma_pvio_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
+{
+ if (pvio && pvio->methods->connect)
+ return pvio->methods->connect(pvio, cinfo);
+ return 1;
+}
+/* }}} */
+
+/* {{{ my_bool ma_pvio_blocking */
+my_bool ma_pvio_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
+{
+ if (pvio && pvio->methods->blocking)
+ return pvio->methods->blocking(pvio, block, previous_mode) != 0;
+ return 1;
+}
+/* }}} */
+
+/* {{{ my_bool ma_pvio_is_blocking */
+my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio)
+{
+ if (pvio && pvio->methods->is_blocking)
+ return pvio->methods->is_blocking(pvio);
+ return 1;
+}
+/* }}} */
+
+/* {{{ ma_pvio_has_data */
+my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
+{
+ /* check if we still have unread data in cache */
+ if (pvio && pvio->cache)
+ if (pvio->cache_pos > pvio->cache)
+ return test(pvio->cache_pos - pvio->cache);
+ if (pvio && pvio->methods->has_data)
+ return pvio->methods->has_data(pvio, data_len);
+ return 1;
+}
+/* }}} */
+
+#ifdef HAVE_TLS
+/* {{{ my_bool ma_pvio_start_ssl */
+my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
+{
+ if (!pvio || !pvio->mysql)
+ return 1;
+ CLEAR_CLIENT_ERROR(pvio->mysql);
+ if (!(pvio->ctls= ma_pvio_tls_init(pvio->mysql)))
+ {
+ return 1;
+ }
+ if (ma_pvio_tls_connect(pvio->ctls))
+ {
+ free(pvio->ctls);
+ pvio->ctls= NULL;
+ return 1;
+ }
+
+ /* default behaviour:
+ 1. peer certificate verification
+ 2. verify CN (requires option ssl_verify_check)
+ 3. verrify finger print
+ */
+ if (pvio->mysql->options.extension->tls_verify_server_cert &&
+ ma_pvio_tls_verify_server_cert(pvio->ctls))
+ return 1;
+
+ if (pvio->mysql->options.extension &&
+ ((pvio->mysql->options.extension->tls_fp && pvio->mysql->options.extension->tls_fp[0]) ||
+ (pvio->mysql->options.extension->tls_fp_list && pvio->mysql->options.extension->tls_fp_list[0])))
+ {
+ if (ma_pvio_tls_check_fp(pvio->ctls,
+ pvio->mysql->options.extension->tls_fp,
+ pvio->mysql->options.extension->tls_fp_list))
+ return 1;
+ }
+
+ return 0;
+}
+/* }}} */
+#endif
+
+/* {{{ ma_pvio_register_callback */
+int ma_pvio_register_callback(my_bool register_callback,
+ void (*callback_function)(int mode, MYSQL *mysql, const uchar *buffer, size_t length))
+{
+ LIST *list;
+
+ if (!callback_function)
+ return 1;
+
+ /* plugin will unregister in it's deinit function */
+ if (register_callback)
+ {
+ list= (LIST *)malloc(sizeof(LIST));
+
+ list->data= (void *)callback_function;
+ pvio_callback= list_add(pvio_callback, list);
+ }
+ else /* unregister callback function */
+ {
+ LIST *p= pvio_callback;
+ while (p)
+ {
+ if (p->data == callback_function)
+ {
+ list_delete(pvio_callback, p);
+ break;
+ }
+ p= p->next;
+ }
+ }
+ return 0;
+}
+/* }}} */
diff --git a/libmariadb/libmariadb/ma_sha1.c b/libmariadb/libmariadb/ma_sha1.c
new file mode 100644
index 00000000..04c5760e
--- /dev/null
+++ b/libmariadb/libmariadb/ma_sha1.c
@@ -0,0 +1,326 @@
+/****************************************************************************
+ Copyright (C) 2012 Monty Program AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+ *****************************************************************************/
+
+/* This code came from the PHP project, initially written by
+ Stefan Esser */
+
+
+#include "ma_global.h"
+#include "string.h"
+
+/* This code is heavily based on the PHP md5 implementation */
+
+#include "ma_sha1.h"
+
+
+static void ma_SHA1Transform(uint32[5], const unsigned char[64]);
+static void ma_SHA1Encode(unsigned char *, uint32 *, unsigned int);
+static void ma_SHA1Decode(uint32 *, const unsigned char *, unsigned int);
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic SHA1 functions.
+*/
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) ((x) ^ (y) ^ (z))
+#define H(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
+#define I(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+*/
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* W[i]
+*/
+#define W(i) ( tmp=x[(i-3)&15]^x[(i-8)&15]^x[(i-14)&15]^x[i&15], \
+ (x[i&15]=ROTATE_LEFT(tmp, 1)) )
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+*/
+#define FF(a, b, c, d, e, w) { \
+ (e) += F ((b), (c), (d)) + (w) + (uint32)(0x5A827999); \
+ (e) += ROTATE_LEFT ((a), 5); \
+ (b) = ROTATE_LEFT((b), 30); \
+}
+#define GG(a, b, c, d, e, w) { \
+ (e) += G ((b), (c), (d)) + (w) + (uint32)(0x6ED9EBA1); \
+ (e) += ROTATE_LEFT ((a), 5); \
+ (b) = ROTATE_LEFT((b), 30); \
+}
+#define HH(a, b, c, d, e, w) { \
+ (e) += H ((b), (c), (d)) + (w) + (uint32)(0x8F1BBCDC); \
+ (e) += ROTATE_LEFT ((a), 5); \
+ (b) = ROTATE_LEFT((b), 30); \
+}
+#define II(a, b, c, d, e, w) { \
+ (e) += I ((b), (c), (d)) + (w) + (uint32)(0xCA62C1D6); \
+ (e) += ROTATE_LEFT ((a), 5); \
+ (b) = ROTATE_LEFT((b), 30); \
+}
+
+
+/* {{{ ma_SHA1Init
+ * SHA1 initialization. Begins an SHA1 operation, writing a new context.
+ */
+void ma_SHA1Init(_MA_SHA1_CTX * context)
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants.
+ */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xc3d2e1f0;
+}
+/* }}} */
+
+/* {{{ ma_SHA1Update
+ SHA1 block update operation. Continues an SHA1 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void ma_SHA1Update(_MA_SHA1_CTX * context, const unsigned char *input,
+ size_t inputLen)
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((uint32) inputLen << 3))
+ < ((uint32) inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((uint32) inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ memcpy
+ ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
+ ma_SHA1Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ ma_SHA1Transform(context->state, &input[i]);
+
+ index = 0;
+ } else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy
+ ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
+ inputLen - i);
+}
+/* }}} */
+
+/* {{{ ma_SHA1Final
+ SHA1 finalization. Ends an SHA1 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+void ma_SHA1Final(unsigned char digest[20], _MA_SHA1_CTX * context)
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ bits[7] = context->count[0] & 0xFF;
+ bits[6] = (context->count[0] >> 8) & 0xFF;
+ bits[5] = (context->count[0] >> 16) & 0xFF;
+ bits[4] = (context->count[0] >> 24) & 0xFF;
+ bits[3] = context->count[1] & 0xFF;
+ bits[2] = (context->count[1] >> 8) & 0xFF;
+ bits[1] = (context->count[1] >> 16) & 0xFF;
+ bits[0] = (context->count[1] >> 24) & 0xFF;
+
+ /* Pad out to 56 mod 64.
+ */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ ma_SHA1Update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ ma_SHA1Update(context, bits, 8);
+
+ /* Store state in digest */
+ ma_SHA1Encode(digest, context->state, 20);
+
+ /* Zeroize sensitive information.
+ */
+ memset((unsigned char*) context, 0, sizeof(*context));
+}
+/* }}} */
+
+/* {{{ ma_SHA1Transform
+ * SHA1 basic transformation. Transforms state based on block.
+ */
+static void ma_SHA1Transform(uint32 state[5], const unsigned char block[64])
+{
+ uint32 a = state[0], b = state[1], c = state[2];
+ uint32 d = state[3], e = state[4], x[16], tmp;
+
+ ma_SHA1Decode(x, block, 64);
+
+ /* Round 1 */
+ FF(a, b, c, d, e, x[0]); /* 1 */
+ FF(e, a, b, c, d, x[1]); /* 2 */
+ FF(d, e, a, b, c, x[2]); /* 3 */
+ FF(c, d, e, a, b, x[3]); /* 4 */
+ FF(b, c, d, e, a, x[4]); /* 5 */
+ FF(a, b, c, d, e, x[5]); /* 6 */
+ FF(e, a, b, c, d, x[6]); /* 7 */
+ FF(d, e, a, b, c, x[7]); /* 8 */
+ FF(c, d, e, a, b, x[8]); /* 9 */
+ FF(b, c, d, e, a, x[9]); /* 10 */
+ FF(a, b, c, d, e, x[10]); /* 11 */
+ FF(e, a, b, c, d, x[11]); /* 12 */
+ FF(d, e, a, b, c, x[12]); /* 13 */
+ FF(c, d, e, a, b, x[13]); /* 14 */
+ FF(b, c, d, e, a, x[14]); /* 15 */
+ FF(a, b, c, d, e, x[15]); /* 16 */
+ FF(e, a, b, c, d, W(16)); /* 17 */
+ FF(d, e, a, b, c, W(17)); /* 18 */
+ FF(c, d, e, a, b, W(18)); /* 19 */
+ FF(b, c, d, e, a, W(19)); /* 20 */
+
+ /* Round 2 */
+ GG(a, b, c, d, e, W(20)); /* 21 */
+ GG(e, a, b, c, d, W(21)); /* 22 */
+ GG(d, e, a, b, c, W(22)); /* 23 */
+ GG(c, d, e, a, b, W(23)); /* 24 */
+ GG(b, c, d, e, a, W(24)); /* 25 */
+ GG(a, b, c, d, e, W(25)); /* 26 */
+ GG(e, a, b, c, d, W(26)); /* 27 */
+ GG(d, e, a, b, c, W(27)); /* 28 */
+ GG(c, d, e, a, b, W(28)); /* 29 */
+ GG(b, c, d, e, a, W(29)); /* 30 */
+ GG(a, b, c, d, e, W(30)); /* 31 */
+ GG(e, a, b, c, d, W(31)); /* 32 */
+ GG(d, e, a, b, c, W(32)); /* 33 */
+ GG(c, d, e, a, b, W(33)); /* 34 */
+ GG(b, c, d, e, a, W(34)); /* 35 */
+ GG(a, b, c, d, e, W(35)); /* 36 */
+ GG(e, a, b, c, d, W(36)); /* 37 */
+ GG(d, e, a, b, c, W(37)); /* 38 */
+ GG(c, d, e, a, b, W(38)); /* 39 */
+ GG(b, c, d, e, a, W(39)); /* 40 */
+
+ /* Round 3 */
+ HH(a, b, c, d, e, W(40)); /* 41 */
+ HH(e, a, b, c, d, W(41)); /* 42 */
+ HH(d, e, a, b, c, W(42)); /* 43 */
+ HH(c, d, e, a, b, W(43)); /* 44 */
+ HH(b, c, d, e, a, W(44)); /* 45 */
+ HH(a, b, c, d, e, W(45)); /* 46 */
+ HH(e, a, b, c, d, W(46)); /* 47 */
+ HH(d, e, a, b, c, W(47)); /* 48 */
+ HH(c, d, e, a, b, W(48)); /* 49 */
+ HH(b, c, d, e, a, W(49)); /* 50 */
+ HH(a, b, c, d, e, W(50)); /* 51 */
+ HH(e, a, b, c, d, W(51)); /* 52 */
+ HH(d, e, a, b, c, W(52)); /* 53 */
+ HH(c, d, e, a, b, W(53)); /* 54 */
+ HH(b, c, d, e, a, W(54)); /* 55 */
+ HH(a, b, c, d, e, W(55)); /* 56 */
+ HH(e, a, b, c, d, W(56)); /* 57 */
+ HH(d, e, a, b, c, W(57)); /* 58 */
+ HH(c, d, e, a, b, W(58)); /* 59 */
+ HH(b, c, d, e, a, W(59)); /* 60 */
+
+ /* Round 4 */
+ II(a, b, c, d, e, W(60)); /* 61 */
+ II(e, a, b, c, d, W(61)); /* 62 */
+ II(d, e, a, b, c, W(62)); /* 63 */
+ II(c, d, e, a, b, W(63)); /* 64 */
+ II(b, c, d, e, a, W(64)); /* 65 */
+ II(a, b, c, d, e, W(65)); /* 66 */
+ II(e, a, b, c, d, W(66)); /* 67 */
+ II(d, e, a, b, c, W(67)); /* 68 */
+ II(c, d, e, a, b, W(68)); /* 69 */
+ II(b, c, d, e, a, W(69)); /* 70 */
+ II(a, b, c, d, e, W(70)); /* 71 */
+ II(e, a, b, c, d, W(71)); /* 72 */
+ II(d, e, a, b, c, W(72)); /* 73 */
+ II(c, d, e, a, b, W(73)); /* 74 */
+ II(b, c, d, e, a, W(74)); /* 75 */
+ II(a, b, c, d, e, W(75)); /* 76 */
+ II(e, a, b, c, d, W(76)); /* 77 */
+ II(d, e, a, b, c, W(77)); /* 78 */
+ II(c, d, e, a, b, W(78)); /* 79 */
+ II(b, c, d, e, a, W(79)); /* 80 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Zeroize sensitive information. */
+ memset((unsigned char*) x, 0, sizeof(x));
+}
+/* }}} */
+
+/* {{{ ma_SHA1Encode
+ Encodes input (uint32) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void ma_SHA1Encode(unsigned char *output, uint32 *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
+ output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
+ output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
+ output[j + 3] = (unsigned char) (input[i] & 0xff);
+ }
+}
+/* }}} */
+
+/* {{{ ma_SHA1Decode
+ Decodes input (unsigned char) into output (uint32). Assumes len is
+ a multiple of 4.
+ */
+static void ma_SHA1Decode(uint32 *output, const unsigned char * input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((uint32) input[j + 3]) | (((uint32) input[j + 2]) << 8) |
+ (((uint32) input[j + 1]) << 16) | (((uint32) input[j]) << 24);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/libmariadb/libmariadb/ma_stmt_codec.c b/libmariadb/libmariadb/ma_stmt_codec.c
new file mode 100644
index 00000000..afb46b25
--- /dev/null
+++ b/libmariadb/libmariadb/ma_stmt_codec.c
@@ -0,0 +1,1362 @@
+/****************************************************************************
+ Copyright (C) 2012 Monty Program AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*****************************************************************************/
+
+/* The implementation for prepared statements was ported from PHP's mysqlnd
+ extension, written by Andrey Hristov, Georg Richter and Ulf Wendel
+
+ Original file header:
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "ma_global.h"
+#include <ma_sys.h>
+#include <ma_string.h>
+#include <mariadb_ctype.h>
+#include "mysql.h"
+#include <math.h> /* ceil() */
+#include <limits.h>
+
+#ifdef WIN32
+#include <malloc.h>
+#endif
+
+#define MYSQL_SILENT
+
+/* ranges for C-binding */
+#define UINT_MAX32 0xFFFFFFFFL
+#define UINT_MAX24 0x00FFFFFF
+#define UINT_MAX16 0xFFFF
+#ifndef INT_MIN8
+#define INT_MIN8 (~0x7F)
+#define INT_MAX8 0x7F
+#endif
+#define UINT_MAX8 0xFF
+
+ #define MAX_DOUBLE_STRING_REP_LENGTH 300
+#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN)
+#define LONGLONG_MIN ((long long) 0x8000000000000000LL)
+#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL)
+#endif
+
+#define MAX_DBL_STR (3 + DBL_MANT_DIG - DBL_MIN_EXP)
+
+#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)
+/* First check for ANSI C99 definition: */
+#ifdef ULLONG_MAX
+#define ULONGLONG_MAX ULLONG_MAX
+#else
+#define ULONGLONG_MAX ((unsigned long long)(~0ULL))
+#endif
+#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
+
+#define YY_PART_YEAR 70
+
+MYSQL_PS_CONVERSION mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY + 1];
+my_bool mysql_ps_subsystem_initialized= 0;
+
+
+#define NUMERIC_TRUNCATION(val,min_range, max_range)\
+ ((((val) > (max_range)) || ((val) < (min_range)) ? 1 : 0))
+
+
+void ma_bmove_upp(register char *dst, register const char *src, register size_t len)
+{
+ while (len-- != 0) *--dst = *--src;
+}
+
+/* {{{ ps_fetch_from_1_to_8_bytes */
+void ps_fetch_from_1_to_8_bytes(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
+ unsigned char **row, unsigned int byte_count)
+{
+ my_bool is_unsigned= test(field->flags & UNSIGNED_FLAG);
+ r_param->buffer_length= byte_count;
+ switch (byte_count) {
+ case 1:
+ *(uchar *)r_param->buffer= **row;
+ *r_param->error= is_unsigned != r_param->is_unsigned && *(uchar *)r_param->buffer > INT_MAX8;
+ break;
+ case 2:
+ shortstore(r_param->buffer, ((ushort) sint2korr(*row)));
+ *r_param->error= is_unsigned != r_param->is_unsigned && *(ushort *)r_param->buffer > INT_MAX16;
+ break;
+ case 4:
+ {
+ longstore(r_param->buffer, ((uint32)sint4korr(*row)));
+ *r_param->error= is_unsigned != r_param->is_unsigned && *(uint32 *)r_param->buffer > INT_MAX32;
+ }
+ break;
+ case 8:
+ {
+ ulonglong val= (ulonglong)sint8korr(*row);
+ longlongstore(r_param->buffer, val);
+ *r_param->error= is_unsigned != r_param->is_unsigned && val > LONGLONG_MAX ;
+ }
+ break;
+ default:
+ r_param->buffer_length= 0;
+ break;
+ }
+ (*row)+= byte_count;
+}
+/* }}} */
+
+static unsigned long long my_strtoull(const char *str, size_t len, const char **end, int *err)
+{
+ unsigned long long val = 0;
+ const char *p = str;
+ const char *end_str = p + len;
+
+ for (; p < end_str; p++)
+ {
+ if (*p < '0' || *p > '9')
+ break;
+
+ if (val > ULONGLONG_MAX /10 || val*10 > ULONGLONG_MAX - (*p - '0'))
+ {
+ *err = ERANGE;
+ break;
+ }
+ val = val * 10 + *p -'0';
+ }
+
+ if (p == str)
+ /* Did not parse anything.*/
+ *err = ERANGE;
+
+ *end = p;
+ return val;
+}
+
+static long long my_strtoll(const char *str, size_t len, const char **end, int *err)
+{
+ unsigned long long uval = 0;
+ const char *p = str;
+ const char *end_str = p + len;
+ int neg;
+
+ while (p < end_str && isspace(*p))
+ p++;
+
+ if (p == end_str)
+ {
+ *end = p;
+ *err = ERANGE;
+ return 0;
+ }
+
+ neg = *p == '-';
+ if (neg)
+ p++;
+
+ uval = my_strtoull(p, (end_str - p), &p, err);
+ *end = p;
+ if (*err)
+ return uval;
+
+ if (!neg)
+ {
+ /* Overflow of the long long range. */
+ if (uval > LONGLONG_MAX)
+ {
+ *end = p - 1;
+ uval = LONGLONG_MAX;
+ *err = ERANGE;
+ }
+ return uval;
+ }
+
+ if (uval == (unsigned long long) LONGLONG_MIN)
+ return LONGLONG_MIN;
+
+ if (uval > LONGLONG_MAX)
+ {
+ *end = p - 1;
+ uval = LONGLONG_MIN;
+ *err = ERANGE;
+ }
+
+ return -1LL * uval;
+}
+
+
+static long long my_atoll(const char *str, const char *end_str, int *error)
+{
+ const char *p=str;
+ const char *end;
+ long long ret;
+ while (p < end_str && isspace(*p))
+ p++;
+
+ ret = my_strtoll(p, end_str - p, &end, error);
+
+ while(end < end_str && isspace(*end))
+ end++;
+
+ if(end != end_str)
+ *error= 1;
+
+ return ret;
+}
+
+
+static unsigned long long my_atoull(const char *str, const char *end_str, int *error)
+{
+ const char *p = str;
+ const char *end;
+ unsigned long long ret;
+
+ while (p < end_str && isspace(*p))
+ p++;
+
+ ret = my_strtoull(p, end_str - p, &end, error);
+
+ while(end < end_str && isspace(*end))
+ end++;
+
+ if(end != end_str)
+ *error= 1;
+
+ return ret;
+}
+
+double my_atod(const char *number, const char *end, int *error)
+{
+ double val= 0.0;
+ char buffer[MAX_DBL_STR + 1];
+ int len= (int)(end - number);
+
+ *error= errno= 0;
+
+ if (len > MAX_DBL_STR)
+ {
+ *error= 1;
+ len= MAX_DBL_STR;
+ }
+
+ memcpy(buffer, number, len);
+ buffer[len]= '\0';
+
+ val= strtod(buffer, NULL);
+
+ if (errno)
+ *error= errno;
+
+ return val;
+}
+
+
+/*
+ strtoui() version, that works for non-null terminated strings
+*/
+static unsigned int my_strtoui(const char *str, size_t len, const char **end, int *err)
+{
+ unsigned long long ull = my_strtoull(str, len, end, err);
+ if (ull > UINT_MAX)
+ *err = ERANGE;
+ return (unsigned int)ull;
+}
+
+/*
+ Parse time, in MySQL format.
+
+ the input string needs is in form "hour:minute:second[.fraction]"
+ hour, minute and second can have leading zeroes or not,
+ they are not necessarily 2 chars.
+
+ Hour must be < 838, minute < 60, second < 60
+ Only 6 places of fraction are considered, the value is truncated after 6 places.
+*/
+static const unsigned int frac_mul[] = { 1000000,100000,10000,1000,100,10 };
+
+static int parse_time(const char *str, size_t length, const char **end_ptr, MYSQL_TIME *tm)
+{
+ int err= 0;
+ const char *p = str;
+ const char *end = str + length;
+ size_t frac_len;
+ int ret=1;
+
+ tm->hour = my_strtoui(p, end-p, &p, &err);
+ if (err || tm->hour > 838 || p == end || *p != ':' )
+ goto end;
+
+ p++;
+ tm->minute = my_strtoui(p, end-p, &p, &err);
+ if (err || tm->minute > 59 || p == end || *p != ':')
+ goto end;
+
+ p++;
+ tm->second = my_strtoui(p, end-p, &p, &err);
+ if (err || tm->second > 59)
+ goto end;
+
+ ret = 0;
+ tm->second_part = 0;
+
+ if (p == end)
+ goto end;
+
+ /* Check for fractional part*/
+ if (*p != '.')
+ goto end;
+
+ p++;
+ frac_len = MIN(6,end-p);
+
+ tm->second_part = my_strtoui(p, frac_len, &p, &err);
+ if (err)
+ goto end;
+
+ if (frac_len < 6)
+ tm->second_part *= frac_mul[frac_len];
+
+ ret = 0;
+
+ /* Consume whole fractional part, even after 6 digits.*/
+ p += frac_len;
+ while(p < *end_ptr)
+ {
+ if (*p < '0' || *p > '9')
+ break;
+ p++;
+ }
+end:
+ *end_ptr = p;
+ return ret;
+}
+
+
+/*
+ Parse date, in MySQL format.
+
+ The input string needs is in form "year-month-day"
+ year, month and day can have leading zeroes or not,
+ they do not have fixed length.
+
+ Year must be < 10000, month < 12, day < 32
+
+ Years with 2 digits, are converted to values 1970-2069 according to
+ usual rules:
+
+ 00-69 is converted to 2000-2069.
+ 70-99 is converted to 1970-1999.
+*/
+static int parse_date(const char *str, size_t length, const char **end_ptr, MYSQL_TIME *tm)
+{
+ int err = 0;
+ const char *p = str;
+ const char *end = str + length;
+ int ret = 1;
+
+ tm->year = my_strtoui(p, end - p, &p, &err);
+ if (err || tm->year > 9999 || p == end || *p != '-')
+ goto end;
+
+ if (p - str == 2) // 2-digit year
+ tm->year += (tm->year >= 70) ? 1900 : 2000;
+
+ p++;
+ tm->month = my_strtoui(p,end -p, &p, &err);
+ if (err || tm->month > 12 || p == end || *p != '-')
+ goto end;
+
+ p++;
+ tm->day = my_strtoui(p, end -p , &p, &err);
+ if (err || tm->day > 31)
+ goto end;
+
+ ret = 0;
+
+end:
+ *end_ptr = p;
+ return ret;
+}
+
+/*
+ Parse (not null terminated) string representing
+ TIME, DATE, or DATETIME into MYSQL_TIME structure
+
+ The supported formats by this functions are
+ - TIME : [-]hours:minutes:seconds[.fraction]
+ - DATE : year-month-day
+ - DATETIME : year-month-day<space>hours:minutes:seconds[.fraction]
+
+ cf https://dev.mysql.com/doc/refman/8.0/en/datetime.html
+
+ Whitespaces are trimmed from the start and end of the string.
+ The function ignores junk at the end of the string.
+
+ Parts of date of time do not have fixed length, so that parsing is compatible with server.
+ However server supports additional formats, e.g YYYYMMDD, HHMMSS, which this function does
+ not support.
+
+*/
+int str_to_TIME(const char *str, size_t length, MYSQL_TIME *tm)
+{
+ const char *p = str;
+ const char *end = str + length;
+ int is_time = 0;
+
+ if (!p)
+ goto error;
+
+ while (p < end && isspace(*p))
+ p++;
+ while (p < end && isspace(end[-1]))
+ end--;
+
+ if (end -p < 5)
+ goto error;
+
+ if (*p == '-')
+ {
+ tm->neg = 1;
+ /* Only TIME can't be negative.*/
+ is_time = 1;
+ p++;
+ }
+ else
+ {
+ int i;
+ tm->neg = 0;
+ /*
+ Date parsing (in server) accepts leading zeroes, thus position of the delimiters
+ is not fixed. Scan the string to find out what we need to parse.
+ */
+ for (i = 1; p + i < end; i++)
+ {
+ if(p[i] == '-' || p [i] == ':')
+ {
+ is_time = p[i] == ':';
+ break;
+ }
+ }
+ }
+
+ if (is_time)
+ {
+ if (parse_time(p, end - p, &p, tm))
+ goto error;
+
+ tm->year = tm->month = tm->day = 0;
+ tm->time_type = MYSQL_TIMESTAMP_TIME;
+ return 0;
+ }
+
+ if (parse_date(p, end - p, &p, tm))
+ goto error;
+
+ if (p == end || p[0] != ' ')
+ {
+ tm->hour = tm->minute = tm->second = tm->second_part = 0;
+ tm->time_type = MYSQL_TIMESTAMP_DATE;
+ return 0;
+ }
+
+ /* Skip space. */
+ p++;
+ if (parse_time(p, end - p, &p, tm))
+ goto error;
+
+ /* In DATETIME, hours must be < 24.*/
+ if (tm->hour > 23)
+ goto error;
+
+ tm->time_type = MYSQL_TIMESTAMP_DATETIME;
+ return 0;
+
+error:
+ memset(tm, 0, sizeof(*tm));
+ tm->time_type = MYSQL_TIMESTAMP_ERROR;
+ return 1;
+}
+
+
+static void convert_froma_string(MYSQL_BIND *r_param, char *buffer, size_t len)
+{
+ int error= 0;
+ switch (r_param->buffer_type)
+ {
+ case MYSQL_TYPE_TINY:
+ {
+ longlong val= my_atoll(buffer, buffer + len, &error);
+ *r_param->error= error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX8) : NUMERIC_TRUNCATION(val, INT_MIN8, INT_MAX8) || error > 0;
+ int1store(r_param->buffer, (uchar) val);
+ r_param->buffer_length= sizeof(uchar);
+ }
+ break;
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_SHORT:
+ {
+ longlong val= my_atoll(buffer, buffer + len, &error);
+ *r_param->error= error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX16) : NUMERIC_TRUNCATION(val, INT_MIN16, INT_MAX16) || error > 0;
+ shortstore(r_param->buffer, (short)val);
+ r_param->buffer_length= sizeof(short);
+ }
+ break;
+ case MYSQL_TYPE_LONG:
+ {
+ longlong val= my_atoll(buffer, buffer + len, &error);
+ *r_param->error=error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32) || error > 0;
+ longstore(r_param->buffer, (int32)val);
+ r_param->buffer_length= sizeof(uint32);
+ }
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong val= r_param->is_unsigned ? (longlong)my_atoull(buffer, buffer + len, &error) : my_atoll(buffer, buffer + len, &error);
+ *r_param->error= error > 0; /* no need to check for truncation */
+ longlongstore(r_param->buffer, val);
+ r_param->buffer_length= sizeof(longlong);
+ }
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double val= my_atod(buffer, buffer + len, &error);
+ *r_param->error= error > 0; /* no need to check for truncation */
+ doublestore((uchar *)r_param->buffer, val);
+ r_param->buffer_length= sizeof(double);
+ }
+ break;
+ case MYSQL_TYPE_FLOAT:
+ {
+ float val= (float)my_atod(buffer, buffer + len, &error);
+ *r_param->error= error > 0; /* no need to check for truncation */
+ floatstore((uchar *)r_param->buffer, val);
+ r_param->buffer_length= sizeof(float);
+ }
+ break;
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ MYSQL_TIME *tm= (MYSQL_TIME *)r_param->buffer;
+ str_to_TIME(buffer, len, tm);
+ break;
+ }
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ default:
+ {
+ if (len >= r_param->offset)
+ {
+ char *start= buffer + r_param->offset; /* stmt_fetch_column sets offset */
+ char *end= buffer + len;
+ size_t copylen= 0;
+
+ if (start < end)
+ {
+ copylen= end - start;
+ if (r_param->buffer_length)
+ memcpy(r_param->buffer, start, MIN(copylen, r_param->buffer_length));
+ }
+ if (copylen < r_param->buffer_length)
+ ((char *)r_param->buffer)[copylen]= 0;
+ *r_param->error= (copylen > r_param->buffer_length);
+
+ }
+ *r_param->length= (ulong)len;
+ }
+ break;
+ }
+}
+
+static void convert_from_long(MYSQL_BIND *r_param, const MYSQL_FIELD *field, longlong val, my_bool is_unsigned)
+{
+ switch (r_param->buffer_type) {
+ case MYSQL_TYPE_TINY:
+ *(uchar *)r_param->buffer= (uchar)(val & 0xff);
+ *r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX8) : NUMERIC_TRUNCATION(val, INT_MIN8, INT_MAX8);
+ r_param->buffer_length= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ shortstore(r_param->buffer, (short)(val & 0xffff));
+ *r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX16) : NUMERIC_TRUNCATION(val, INT_MIN16, INT_MAX16);
+ r_param->buffer_length= 2;
+ break;
+ case MYSQL_TYPE_LONG:
+ longstore(r_param->buffer, (int32)(val & 0xffffffff));
+ *r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32);
+ r_param->buffer_length= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ *r_param->error= (val < 0 && r_param->is_unsigned != is_unsigned);
+ longlongstore(r_param->buffer, val);
+ r_param->buffer_length= 8;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ {
+ volatile double dbl;
+
+ dbl= (is_unsigned) ? ulonglong2double((ulonglong)val) : (double)val;
+ doublestore(r_param->buffer, dbl);
+
+ *r_param->error = (dbl != ceil(dbl)) ||
+ (is_unsigned ? (ulonglong )dbl != (ulonglong)val :
+ (longlong)dbl != (longlong)val);
+
+ r_param->buffer_length= 8;
+ break;
+ }
+ case MYSQL_TYPE_FLOAT:
+ {
+ volatile float fval;
+ fval= is_unsigned ? (float)(ulonglong)(val) : (float)val;
+ floatstore((uchar *)r_param->buffer, fval);
+ *r_param->error= (fval != ceilf(fval)) ||
+ (is_unsigned ? (ulonglong)fval != (ulonglong)val :
+ (longlong)fval != val);
+ r_param->buffer_length= 4;
+ }
+ break;
+ default:
+ {
+ char *buffer;
+ char *endptr;
+ uint len;
+ my_bool zf_truncated= 0;
+
+ buffer= alloca(MAX(field->length, 22));
+ endptr= ma_ll2str(val, buffer, is_unsigned ? 10 : -10);
+ len= (uint)(endptr - buffer);
+
+ /* check if field flag is zerofill */
+ if (field->flags & ZEROFILL_FLAG)
+ {
+ uint display_width= MAX(field->length, len);
+ if (display_width < r_param->buffer_length)
+ {
+ ma_bmove_upp(buffer + display_width, buffer + len, len);
+ /* coverity[bad_memset] */
+ memset((void*) buffer, (int) '0', display_width - len);
+ len= display_width;
+ }
+ else
+ zf_truncated= 1;
+ }
+ convert_froma_string(r_param, buffer, len);
+ *r_param->error+= zf_truncated;
+ }
+ break;
+ }
+}
+
+
+/* {{{ ps_fetch_null */
+static
+void ps_fetch_null(MYSQL_BIND *r_param __attribute__((unused)),
+ const MYSQL_FIELD * field __attribute__((unused)),
+ unsigned char **row __attribute__((unused)))
+{
+ /* do nothing */
+}
+/* }}} */
+
+#define GET_LVALUE_FROM_ROW(is_unsigned, data, ucast, scast)\
+ (is_unsigned) ? (longlong)(ucast) *(longlong *)(data) : (longlong)(scast) *(longlong *)(data)
+/* {{{ ps_fetch_int8 */
+static
+void ps_fetch_int8(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
+ unsigned char **row)
+{
+ switch(r_param->buffer_type) {
+ case MYSQL_TYPE_TINY:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 1);
+ break;
+ default:
+ {
+ uchar val= **row;
+ longlong lval= field->flags & UNSIGNED_FLAG ? (longlong) val : (longlong)(signed char)val;
+ convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
+ (*row) += 1;
+ }
+ break;
+ }
+}
+/* }}} */
+
+
+/* {{{ ps_fetch_int16 */
+static
+void ps_fetch_int16(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
+ unsigned char **row)
+{
+ switch (r_param->buffer_type) {
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_SHORT:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 2);
+ break;
+ default:
+ {
+ short sval= sint2korr(*row);
+ longlong lval= field->flags & UNSIGNED_FLAG ? (longlong)(ushort) sval : (longlong)sval;
+ convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
+ (*row) += 2;
+ }
+ break;
+ }
+}
+/* }}} */
+
+
+/* {{{ ps_fetch_int32 */
+static
+void ps_fetch_int32(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
+ unsigned char **row)
+{
+ switch (r_param->buffer_type) {
+/* case MYSQL_TYPE_TINY:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 1);
+ break;
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_SHORT:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 2);
+ break; */
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 4);
+ break;
+ default:
+ {
+ int32 sval= sint4korr(*row);
+ longlong lval= field->flags & UNSIGNED_FLAG ? (longlong)(uint32) sval : (longlong)sval;
+ convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
+ (*row) += 4;
+ }
+ break;
+ }
+}
+/* }}} */
+
+
+/* {{{ ps_fetch_int64 */
+static
+void ps_fetch_int64(MYSQL_BIND *r_param, const MYSQL_FIELD * const field,
+ unsigned char **row)
+{
+ switch(r_param->buffer_type)
+ {
+/* case MYSQL_TYPE_TINY:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 1);
+ break;
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_SHORT:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 2);
+ break;
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 4);
+ break; */
+ case MYSQL_TYPE_LONGLONG:
+ ps_fetch_from_1_to_8_bytes(r_param, field, row, 8);
+ break;
+ default:
+ {
+ longlong sval= (longlong)sint8korr(*row);
+ longlong lval= field->flags & UNSIGNED_FLAG ? (longlong)(ulonglong) sval : (longlong)sval;
+ convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG);
+ (*row) += 8;
+ }
+ break;
+ }
+}
+/* }}} */
+
+static void convert_from_float(MYSQL_BIND *r_param, const MYSQL_FIELD *field, float val, int size __attribute__((unused)))
+{
+ double check_trunc_val= (val > 0) ? floor(val) : -floor(-val);
+ char *buf= (char *)r_param->buffer;
+ switch (r_param->buffer_type)
+ {
+ case MYSQL_TYPE_TINY:
+ *buf= (r_param->is_unsigned) ? (uint8)val : (int8)val;
+ *r_param->error= check_trunc_val != (r_param->is_unsigned ? (double)((uint8)*buf) :
+ (double)((int8)*buf));
+ r_param->buffer_length= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ {
+ if (r_param->is_unsigned)
+ {
+ ushort sval= (ushort)val;
+ shortstore(buf, sval);
+ *r_param->error= check_trunc_val != (double)sval;
+ } else {
+ short sval= (short)val;
+ shortstore(buf, sval);
+ *r_param->error= check_trunc_val != (double)sval;
+ }
+ r_param->buffer_length= 2;
+ }
+ break;
+ case MYSQL_TYPE_LONG:
+ {
+ if (r_param->is_unsigned)
+ {
+ uint32 lval= (uint32)val;
+ longstore(buf, lval);
+ *r_param->error= (check_trunc_val != (double)lval);
+ } else {
+ int32 lval= (int32)val;
+ longstore(buf, lval);
+ *r_param->error= (check_trunc_val != (double)lval);
+ }
+ r_param->buffer_length= 4;
+ }
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ {
+ if (r_param->is_unsigned)
+ {
+ ulonglong llval= (ulonglong)val;
+ longlongstore(buf, llval);
+ *r_param->error= (check_trunc_val != (double)llval);
+ } else {
+ longlong llval= (longlong)val;
+ longlongstore(buf, llval);
+ *r_param->error= (check_trunc_val != (double)llval);
+ }
+ r_param->buffer_length= 8;
+ }
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double dval= (double)val;
+ memcpy(buf, &dval, sizeof(double));
+ r_param->buffer_length= 8;
+ }
+ break;
+ default:
+ {
+ char buff[MAX_DOUBLE_STRING_REP_LENGTH];
+ size_t length;
+
+ length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length);
+
+ if (field->decimals >= NOT_FIXED_DEC)
+ {
+ length= ma_gcvt(val, MY_GCVT_ARG_FLOAT, (int)length, buff, NULL);
+ }
+ else
+ {
+ length= ma_fcvt(val, field->decimals, buff, NULL);
+ }
+
+ /* check if ZEROFILL flag is active */
+ if (field->flags & ZEROFILL_FLAG)
+ {
+ /* enough space available ? */
+ if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1)
+ break;
+ ma_bmove_upp(buff + field->length, buff + length, length);
+ /* coverity[bad_memset] */
+ memset((void*) buff, (int) '0', field->length - length);
+ length= field->length;
+ }
+
+ convert_froma_string(r_param, buff, length);
+ }
+ break;
+ }
+}
+
+static void convert_from_double(MYSQL_BIND *r_param, const MYSQL_FIELD *field, double val, int size __attribute__((unused)))
+{
+ double check_trunc_val= (val > 0) ? floor(val) : -floor(-val);
+ char *buf= (char *)r_param->buffer;
+ switch (r_param->buffer_type)
+ {
+ case MYSQL_TYPE_TINY:
+ *buf= (r_param->is_unsigned) ? (uint8)val : (int8)val;
+ *r_param->error= check_trunc_val != (r_param->is_unsigned ? (double)((uint8)*buf) :
+ (double)((int8)*buf));
+ r_param->buffer_length= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ {
+ if (r_param->is_unsigned)
+ {
+ ushort sval= (ushort)val;
+ shortstore(buf, sval);
+ *r_param->error= check_trunc_val != (double)sval;
+ } else {
+ short sval= (short)val;
+ shortstore(buf, sval);
+ *r_param->error= check_trunc_val != (double)sval;
+ }
+ r_param->buffer_length= 2;
+ }
+ break;
+ case MYSQL_TYPE_LONG:
+ {
+ if (r_param->is_unsigned)
+ {
+ uint32 lval= (uint32)val;
+ longstore(buf, lval);
+ *r_param->error= (check_trunc_val != (double)lval);
+ } else {
+ int32 lval= (int32)val;
+ longstore(buf, lval);
+ *r_param->error= (check_trunc_val != (double)lval);
+ }
+ r_param->buffer_length= 4;
+ }
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ {
+ if (r_param->is_unsigned)
+ {
+ ulonglong llval= (ulonglong)val;
+ longlongstore(buf, llval);
+ *r_param->error= (check_trunc_val != (double)llval);
+ } else {
+ longlong llval= (longlong)val;
+ longlongstore(buf, llval);
+ *r_param->error= (check_trunc_val != (double)llval);
+ }
+ r_param->buffer_length= 8;
+ }
+ break;
+ case MYSQL_TYPE_FLOAT:
+ {
+ float fval= (float)val;
+ memcpy(buf, &fval, sizeof(float));
+ *r_param->error= (*(float*)buf != fval);
+ r_param->buffer_length= 4;
+ }
+ break;
+ default:
+ {
+ char buff[MAX_DOUBLE_STRING_REP_LENGTH];
+ size_t length;
+
+ length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length);
+
+ if (field->decimals >= NOT_FIXED_DEC)
+ {
+ length= ma_gcvt(val, MY_GCVT_ARG_DOUBLE, (int)length, buff, NULL);
+ }
+ else
+ {
+ length= ma_fcvt(val, field->decimals, buff, NULL);
+ }
+
+ /* check if ZEROFILL flag is active */
+ if (field->flags & ZEROFILL_FLAG)
+ {
+ /* enough space available ? */
+ if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1)
+ break;
+ ma_bmove_upp(buff + field->length, buff + length, length);
+ /* coverity [bad_memset] */
+ memset((void*) buff, (int) '0', field->length - length);
+ length= field->length;
+ }
+ convert_froma_string(r_param, buff, length);
+ }
+ break;
+ }
+}
+
+
+/* {{{ ps_fetch_double */
+static
+void ps_fetch_double(MYSQL_BIND *r_param, const MYSQL_FIELD * field , unsigned char **row)
+{
+ switch (r_param->buffer_type)
+ {
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double *value= (double *)r_param->buffer;
+ float8get(*value, *row);
+ r_param->buffer_length= 8;
+ }
+ break;
+ default:
+ {
+ double value;
+ float8get(value, *row);
+ convert_from_double(r_param, field, value, sizeof(double));
+ }
+ break;
+ }
+ (*row)+= 8;
+}
+/* }}} */
+
+/* {{{ ps_fetch_float */
+static
+void ps_fetch_float(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row)
+{
+ switch(r_param->buffer_type)
+ {
+ case MYSQL_TYPE_FLOAT:
+ {
+ float *value= (float *)r_param->buffer;
+ float4get(*value, *row);
+ r_param->buffer_length= 4;
+ *r_param->error= 0;
+ }
+ break;
+ default:
+ {
+ float value;
+ memcpy(&value, *row, sizeof(float));
+ float4get(value, (char *)*row);
+ convert_from_float(r_param, field, value, sizeof(float));
+ }
+ break;
+ }
+ (*row)+= 4;
+}
+/* }}} */
+
+static void convert_to_datetime(MYSQL_TIME *t, unsigned char **row, uint len, enum enum_field_types type)
+{
+ memset(t, 0, sizeof(MYSQL_TIME));
+
+ /* binary protocol for datetime:
+ 4-bytes: DATE
+ 7-bytes: DATE + TIME
+ >7 bytes: DATE + TIME with second_part
+ */
+ if (len)
+ {
+ unsigned char *to= *row;
+ int has_date= 0;
+ uint offset= 7;
+
+ if (type == MYSQL_TYPE_TIME)
+ {
+ t->neg= to[0];
+ t->day= (ulong) sint4korr(to + 1);
+ t->time_type= MYSQL_TIMESTAMP_TIME;
+ offset= 8;
+ to++;
+ } else
+ {
+ t->year= (uint) sint2korr(to);
+ t->month= (uint) to[2];
+ t->day= (uint) to[3];
+ t->time_type= MYSQL_TIMESTAMP_DATE;
+ if (type == MYSQL_TYPE_DATE)
+ return;
+ has_date= 1;
+ }
+
+ if (len > 4)
+ {
+ t->hour= (uint) to[4];
+ if (type == MYSQL_TYPE_TIME)
+ t->hour+= t->day * 24;
+ t->minute= (uint) to[5];
+ t->second= (uint) to[6];
+ if (has_date)
+ t->time_type= MYSQL_TIMESTAMP_DATETIME;
+ }
+ if (len > offset)
+ {
+ t->second_part= (ulong)sint4korr(to+7);
+ }
+ }
+}
+
+
+/* {{{ ps_fetch_datetime */
+static
+void ps_fetch_datetime(MYSQL_BIND *r_param, const MYSQL_FIELD * field,
+ unsigned char **row)
+{
+ MYSQL_TIME *t= (MYSQL_TIME *)r_param->buffer;
+ unsigned int len= net_field_length(row);
+
+ switch (r_param->buffer_type) {
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ convert_to_datetime(t, row, len, field->type);
+ break;
+ case MYSQL_TYPE_DATE:
+ convert_to_datetime(t, row, len, field->type);
+ break;
+ case MYSQL_TYPE_TIME:
+ convert_to_datetime(t, row, len, field->type);
+ t->year= t->day= t->month= 0;
+ break;
+ case MYSQL_TYPE_YEAR:
+ {
+ MYSQL_TIME tm;
+ convert_to_datetime(&tm, row, len, field->type);
+ shortstore(r_param->buffer, tm.year);
+ break;
+ }
+ default:
+ {
+ char dtbuffer[60];
+ MYSQL_TIME tm;
+ size_t length;
+ convert_to_datetime(&tm, row, len, field->type);
+
+ switch(field->type) {
+ case MYSQL_TYPE_DATE:
+ length= sprintf(dtbuffer, "%04u-%02u-%02u", tm.year, tm.month, tm.day);
+ break;
+ case MYSQL_TYPE_TIME:
+ length= sprintf(dtbuffer, "%s%02u:%02u:%02u", (tm.neg ? "-" : ""), tm.hour, tm.minute, tm.second);
+ if (field->decimals && field->decimals <= 6)
+ {
+ char ms[8];
+ sprintf(ms, ".%06lu", tm.second_part);
+ if (field->decimals < 6)
+ ms[field->decimals + 1]= 0;
+ length+= strlen(ms);
+ strcat(dtbuffer, ms);
+ }
+ break;
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ length= sprintf(dtbuffer, "%04u-%02u-%02u %02u:%02u:%02u", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
+ if (field->decimals && field->decimals <= 6)
+ {
+ char ms[8];
+ sprintf(ms, ".%06lu", tm.second_part);
+ if (field->decimals < 6)
+ ms[field->decimals + 1]= 0;
+ length+= strlen(ms);
+ strcat(dtbuffer, ms);
+ }
+ break;
+ default:
+ dtbuffer[0]= 0;
+ length= 0;
+ break;
+ }
+ convert_froma_string(r_param, dtbuffer, length);
+ break;
+ }
+ }
+ (*row) += len;
+}
+/* }}} */
+
+/* {{{ ps_fetch_string */
+static
+void ps_fetch_string(MYSQL_BIND *r_param,
+ const MYSQL_FIELD *field __attribute__((unused)),
+ unsigned char **row)
+{
+ /* C-API differs from PHP. While PHP just converts string to string,
+ C-API needs to convert the string to the defined type with in
+ the result bind buffer.
+ */
+ ulong field_length= net_field_length(row);
+
+ convert_froma_string(r_param, (char *)*row, field_length);
+ (*row) += field_length;
+}
+/* }}} */
+
+/* {{{ ps_fetch_bin */
+static
+void ps_fetch_bin(MYSQL_BIND *r_param,
+ const MYSQL_FIELD *field,
+ unsigned char **row)
+{
+ if (field->charsetnr == 63)
+ {
+ ulong field_length= *r_param->length= net_field_length(row);
+ uchar *current_pos= (*row) + r_param->offset,
+ *end= (*row) + field_length;
+ size_t copylen= 0;
+
+ if (current_pos < end)
+ {
+ copylen= end - current_pos;
+ if (r_param->buffer_length)
+ memcpy(r_param->buffer, current_pos, MIN(copylen, r_param->buffer_length));
+ }
+ if (copylen < r_param->buffer_length &&
+ (r_param->buffer_type == MYSQL_TYPE_STRING ||
+ r_param->buffer_type == MYSQL_TYPE_JSON))
+ ((char *)r_param->buffer)[copylen]= 0;
+ *r_param->error= copylen > r_param->buffer_length;
+ (*row)+= field_length;
+ }
+ else
+ ps_fetch_string(r_param, field, row);
+}
+/* }}} */
+
+/* {{{ _mysqlnd_init_ps_subsystem */
+void mysql_init_ps_subsystem(void)
+{
+ memset(mysql_ps_fetch_functions, 0, sizeof(mysql_ps_fetch_functions));
+ mysql_ps_fetch_functions[MYSQL_TYPE_NULL].func= ps_fetch_null;
+ mysql_ps_fetch_functions[MYSQL_TYPE_NULL].pack_len = 0;
+ mysql_ps_fetch_functions[MYSQL_TYPE_NULL].max_len = 0;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_TINY].func = ps_fetch_int8;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len = 1;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TINY].max_len = 4;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_SHORT].func = ps_fetch_int16;
+ mysql_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len = 2;
+ mysql_ps_fetch_functions[MYSQL_TYPE_SHORT].max_len = 6;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_YEAR].func = ps_fetch_int16;
+ mysql_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len = 2;
+ mysql_ps_fetch_functions[MYSQL_TYPE_YEAR].max_len = 4;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_INT24].func = ps_fetch_int32;
+ mysql_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len = 4;
+ mysql_ps_fetch_functions[MYSQL_TYPE_INT24].max_len = 8;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONG].func = ps_fetch_int32;
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len = 4;
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONG].max_len = 11;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func = ps_fetch_int64;
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8;
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONGLONG].max_len = 20;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_FLOAT].func = ps_fetch_float;
+ mysql_ps_fetch_functions[MYSQL_TYPE_FLOAT].pack_len = 4;
+ mysql_ps_fetch_functions[MYSQL_TYPE_FLOAT].max_len = MAX_DOUBLE_STRING_REP_LENGTH;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_DOUBLE].func = ps_fetch_double;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DOUBLE].pack_len = 8;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DOUBLE].max_len = MAX_DOUBLE_STRING_REP_LENGTH;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_TIME].func = ps_fetch_datetime;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TIME].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TIME].max_len = 17;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_DATE].func = ps_fetch_datetime;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DATE].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DATE].max_len = 10;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].pack_len = MYSQL_PS_SKIP_RESULT_W_LEN;
+ mysql_ps_fetch_functions[MYSQL_TYPE_NEWDATE].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_DATETIME].func = ps_fetch_datetime;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DATETIME].pack_len= MYSQL_PS_SKIP_RESULT_W_LEN;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DATETIME].max_len = 30;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].func = ps_fetch_datetime;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQL_PS_SKIP_RESULT_W_LEN;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].max_len = 30;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func = ps_fetch_bin;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].pack_len= MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].func = ps_fetch_bin;
+ mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_BLOB].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func = ps_fetch_bin;
+ mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].pack_len= MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func = ps_fetch_bin;
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_BIT].func = ps_fetch_bin;
+ mysql_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_BIT].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_VARCHAR].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_VARCHAR].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_VARCHAR].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_STRING].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_STRING].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_STRING].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_JSON].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_JSON].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_JSON].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_DECIMAL].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DECIMAL].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_DECIMAL].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_ENUM].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_SET].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_SET].pack_len = MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_SET].max_len = -1;
+
+ mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].func = ps_fetch_string;
+ mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].pack_len= MYSQL_PS_SKIP_RESULT_STR;
+ mysql_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].max_len = -1;
+
+ mysql_ps_subsystem_initialized= 1;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
diff --git a/libmariadb/libmariadb/ma_string.c b/libmariadb/libmariadb/ma_string.c
new file mode 100644
index 00000000..9a62e06e
--- /dev/null
+++ b/libmariadb/libmariadb/ma_string.c
@@ -0,0 +1,163 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/*
+ Code for handling strings which can grow dynamically.
+ Copyright Monty Program KB.
+ By monty.
+*/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_string.h>
+
+my_bool ma_init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
+ size_t init_alloc, size_t alloc_increment)
+{
+ uint length;
+
+ if (!alloc_increment)
+ alloc_increment=128;
+ length=1;
+ if (init_str && (length= (uint) strlen(init_str)+1) < init_alloc)
+ init_alloc=((length+alloc_increment-1)/alloc_increment)*alloc_increment;
+ if (!init_alloc)
+ init_alloc=alloc_increment;
+
+ if (!(str->str=(char*) malloc(init_alloc)))
+ return(TRUE);
+ str->length=length-1;
+ if (init_str)
+ memcpy(str->str,init_str,length);
+ str->max_length=init_alloc;
+ str->alloc_increment=alloc_increment;
+ return(FALSE);
+}
+
+my_bool ma_dynstr_set(DYNAMIC_STRING *str, const char *init_str)
+{
+ uint length;
+
+ if (init_str && (length= (uint) strlen(init_str)+1) > str->max_length)
+ {
+ str->max_length=((length+str->alloc_increment-1)/str->alloc_increment)*
+ str->alloc_increment;
+ if (!str->max_length)
+ str->max_length=str->alloc_increment;
+ if (!(str->str=(char*) realloc(str->str,str->max_length)))
+ return(TRUE);
+ }
+ if (init_str)
+ {
+ str->length=length-1;
+ memcpy(str->str,init_str,length);
+ }
+ else
+ str->length=0;
+ return(FALSE);
+}
+
+
+my_bool ma_dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size)
+{
+ if (!additional_size) return(FALSE);
+ if (str->length + additional_size > str->max_length)
+ {
+ str->max_length=((str->length + additional_size+str->alloc_increment-1)/
+ str->alloc_increment)*str->alloc_increment;
+ if (!(str->str=(char*) realloc(str->str,str->max_length)))
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+
+my_bool ma_dynstr_append(DYNAMIC_STRING *str, const char *append)
+{
+ return ma_dynstr_append_mem(str,append,strlen(append));
+}
+
+my_bool ma_dynstr_append_quoted(DYNAMIC_STRING *str,
+ const char *append, size_t len,
+ char quote)
+{
+ size_t additional= str->alloc_increment;
+ size_t lim= additional;
+ uint i;
+
+ if (ma_dynstr_realloc(str, len + additional + 2))
+ return TRUE;
+ str->str[str->length++]= quote;
+ for (i= 0; i < len; i++)
+ {
+ register char c= append[i];
+ if (c == quote || c == '\\')
+ {
+ if (!lim)
+ {
+ if (ma_dynstr_realloc(str, additional))
+ return TRUE;
+ lim= additional;
+ }
+ lim--;
+ str->str[str->length++]= '\\';
+ }
+ str->str[str->length++]= c;
+ }
+ str->str[str->length++]= quote;
+ return FALSE;
+}
+
+my_bool ma_dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
+ size_t length)
+{
+ char *new_ptr;
+ if (str->length+length >= str->max_length)
+ {
+ size_t new_length=(str->length+length+str->alloc_increment)/
+ str->alloc_increment;
+ new_length*=str->alloc_increment;
+ if (!(new_ptr=(char*) realloc(str->str,new_length)))
+ return TRUE;
+ str->str=new_ptr;
+ str->max_length=new_length;
+ }
+ memcpy(str->str + str->length,append,length);
+ str->length+=length;
+ str->str[str->length]=0; /* Safety for C programs */
+ return FALSE;
+}
+
+
+void ma_dynstr_free(DYNAMIC_STRING *str)
+{
+ if (str->str)
+ {
+ free(str->str);
+ str->str=0;
+ }
+}
+
+char *ma_strmake(register char *dst, register const char *src, size_t length)
+{
+ while (length--)
+ if (! (*dst++ = *src++))
+ return dst-1;
+ *dst=0;
+ return dst;
+}
diff --git a/libmariadb/libmariadb/ma_time.c b/libmariadb/libmariadb/ma_time.c
new file mode 100644
index 00000000..460c32d4
--- /dev/null
+++ b/libmariadb/libmariadb/ma_time.c
@@ -0,0 +1,65 @@
+/****************************************************************************
+ Copyright (C) 2013 Monty Program AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*****************************************************************************/
+#include <ma_global.h>
+#include <mysql.h>
+#include <stdio.h>
+
+
+size_t mariadb_time_to_string(const MYSQL_TIME *tm, char *time_str, size_t len,
+ unsigned int digits)
+{
+ size_t length;
+
+ if (!time_str || !len)
+ return 0;
+
+ if (digits == AUTO_SEC_PART_DIGITS)
+ digits= (tm->second_part) ? SEC_PART_DIGITS : 0;
+
+ switch(tm->time_type) {
+ case MYSQL_TIMESTAMP_DATE:
+ length= snprintf(time_str, len, "%04u-%02u-%02u", tm->year, tm->month, tm->day);
+ digits= 0;
+ break;
+ case MYSQL_TIMESTAMP_DATETIME:
+ length= snprintf(time_str, len, "%04u-%02u-%02u %02u:%02u:%02u",
+ tm->year, tm->month, tm->day, tm->hour, tm->minute, tm->second);
+ break;
+ case MYSQL_TIMESTAMP_TIME:
+ length= snprintf(time_str, len, "%s%02u:%02u:%02u",
+ (tm->neg ? "-" : ""), tm->hour, tm->minute, tm->second);
+ break;
+ default:
+ time_str[0]= '\0';
+ return 0;
+ break;
+ }
+ if (digits && (len < length))
+ {
+ char helper[16];
+ snprintf(helper, 16, ".%%0%du", digits);
+ length+= snprintf(time_str + length, len - length, helper, digits);
+ }
+ return length;
+}
+
diff --git a/libmariadb/libmariadb/ma_tls.c b/libmariadb/libmariadb/ma_tls.c
new file mode 100644
index 00000000..3f48ad8b
--- /dev/null
+++ b/libmariadb/libmariadb/ma_tls.c
@@ -0,0 +1,237 @@
+/************************************************************************************
+ Copyright (C) 2014 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ *************************************************************************************/
+
+/*
+ * this is the abstraction layer for communication via SSL.
+ * The following SSL libraries/variants are currently supported:
+ * - openssl
+ * - gnutls
+ * - schannel (windows only)
+ *
+ * Different SSL variants are implemented as plugins
+ * On Windows schannel is implemented as (standard)
+ * built-in plugin.
+ */
+
+#ifdef HAVE_TLS
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+#include <string.h>
+#include <errmsg.h>
+#include <ma_pvio.h>
+#include <ma_tls.h>
+#include <mysql/client_plugin.h>
+#include <mariadb/ma_io.h>
+
+#ifdef HAVE_NONBLOCK
+#include <mariadb_async.h>
+#include <ma_context.h>
+#endif
+
+/* Errors should be handled via pvio callback function */
+my_bool ma_tls_initialized= FALSE;
+unsigned int mariadb_deinitialize_ssl= 1;
+
+const char *tls_protocol_version[]=
+ {"SSLv3", "TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3", "Unknown"};
+
+MARIADB_TLS *ma_pvio_tls_init(MYSQL *mysql)
+{
+ MARIADB_TLS *ctls= NULL;
+
+ if (!ma_tls_initialized)
+ ma_tls_start(mysql->net.last_error, MYSQL_ERRMSG_SIZE);
+
+ if (!(ctls= (MARIADB_TLS *)calloc(1, sizeof(MARIADB_TLS))))
+ {
+ return NULL;
+ }
+
+ /* register error routine and methods */
+ ctls->pvio= mysql->net.pvio;
+ if (!(ctls->ssl= ma_tls_init(mysql)))
+ {
+ free(ctls);
+ ctls= NULL;
+ }
+ return ctls;
+}
+
+my_bool ma_pvio_tls_connect(MARIADB_TLS *ctls)
+{
+ my_bool rc;
+
+ if ((rc= ma_tls_connect(ctls)))
+ ma_tls_close(ctls);
+ return rc;
+}
+
+ssize_t ma_pvio_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ return ma_tls_read(ctls, buffer, length);
+}
+
+ssize_t ma_pvio_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ return ma_tls_write(ctls, buffer, length);
+}
+
+my_bool ma_pvio_tls_close(MARIADB_TLS *ctls)
+{
+ return ma_tls_close(ctls);
+}
+
+int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls)
+{
+ return ma_tls_verify_server_cert(ctls);
+}
+
+const char *ma_pvio_tls_cipher(MARIADB_TLS *ctls)
+{
+ return ma_tls_get_cipher(ctls);
+}
+
+void ma_pvio_tls_end()
+{
+ ma_tls_end();
+}
+
+int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls)
+{
+ return ma_tls_get_protocol_version(ctls);
+}
+
+const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls)
+{
+ int version;
+
+ version= ma_tls_get_protocol_version(ctls);
+ if (version < 0 || version > PROTOCOL_MAX)
+ return tls_protocol_version[PROTOCOL_UNKNOWN];
+ return tls_protocol_version[version];
+}
+
+static signed char ma_hex2int(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'A' && c <= 'F')
+ return 10 + c - 'A';
+ if (c >= 'a' && c <= 'f')
+ return 10 + c - 'a';
+ return -1;
+}
+
+static my_bool ma_pvio_tls_compare_fp(const char *cert_fp,
+ unsigned int cert_fp_len,
+ const char *fp, unsigned int fp_len)
+{
+ char *p= (char *)fp,
+ *c;
+
+ /* check length */
+ if (cert_fp_len != 20)
+ return 1;
+
+ /* We support two formats:
+ 2 digits hex numbers, separated by colons (length=59)
+ 20 * 2 digits hex numbers without separators (length = 40)
+ */
+ if (fp_len != (strchr(fp, ':') ? 59 : 40))
+ return 1;
+
+ for(c= (char *)cert_fp; c < cert_fp + cert_fp_len; c++)
+ {
+ signed char d1, d2;
+ if (*p == ':')
+ p++;
+ if (p - fp > (int)fp_len -1)
+ return 1;
+ if ((d1 = ma_hex2int(*p)) == - 1 ||
+ (d2 = ma_hex2int(*(p+1))) == -1 ||
+ (char)(d1 * 16 + d2) != *c)
+ return 1;
+ p+= 2;
+ }
+ return 0;
+}
+
+my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list)
+{
+ unsigned int cert_fp_len= 64;
+ char *cert_fp= NULL;
+ my_bool rc=1;
+ MYSQL *mysql= ctls->pvio->mysql;
+
+ cert_fp= (char *)malloc(cert_fp_len);
+
+ if ((cert_fp_len= ma_tls_get_finger_print(ctls, cert_fp, cert_fp_len)) < 1)
+ goto end;
+ if (fp)
+ rc= ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, fp, (unsigned int)strlen(fp));
+ else if (fp_list)
+ {
+ MA_FILE *fp;
+ char buff[255];
+
+ if (!(fp = ma_open(fp_list, "r", mysql)))
+ goto end;
+
+ while (ma_gets(buff, sizeof(buff)-1, fp))
+ {
+ /* remove trailing new line character */
+ char *pos= strchr(buff, '\r');
+ if (!pos)
+ pos= strchr(buff, '\n');
+ if (pos)
+ *pos= '\0';
+
+ if (!ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, buff, (unsigned int)strlen(buff)))
+ {
+ /* finger print is valid: close file and exit */
+ ma_close(fp);
+ rc= 0;
+ goto end;
+ }
+ }
+
+ /* No finger print matched - close file and return error */
+ ma_close(fp);
+ }
+
+end:
+ if (cert_fp)
+ free(cert_fp);
+ if (rc)
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Fingerprint verification of server certificate failed");
+ }
+ return rc;
+}
+
+void ma_pvio_tls_set_connection(MYSQL *mysql)
+{
+ ma_tls_set_connection(mysql);
+}
+#endif /* HAVE_TLS */
diff --git a/libmariadb/libmariadb/mariadb_async.c b/libmariadb/libmariadb/mariadb_async.c
new file mode 100644
index 00000000..feb73329
--- /dev/null
+++ b/libmariadb/libmariadb/mariadb_async.c
@@ -0,0 +1,1946 @@
+/* Copyright (C) 2012 MariaDB Services and Kristian Nielsen
+ 2015 MariaDB Corporation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+*/
+
+/*
+ MySQL non-blocking client library functions.
+*/
+
+#include "ma_global.h"
+#include "ma_sys.h"
+#include "mysql.h"
+#include "errmsg.h"
+#ifndef LIBMARIADB
+#include "sql_common.h"
+#else
+#include "ma_common.h"
+#endif
+#include "ma_context.h"
+#include "ma_pvio.h"
+#include "mariadb_async.h"
+#include <string.h>
+
+
+#ifdef _WIN32
+/*
+ Windows does not support MSG_DONTWAIT for send()/recv(). So we need to ensure
+ that the socket is non-blocking at the start of every operation.
+*/
+#define WIN_SET_NONBLOCKING(mysql) do { \
+ my_bool old_mode; \
+ if ((mysql)->net.pvio) ma_pvio_blocking((mysql)->net.pvio, FALSE, &old_mode); \
+ } while(0);
+#else
+#define WIN_SET_NONBLOCKING(mysql)
+#endif
+
+extern void mysql_close_slow_part(MYSQL *mysql);
+
+
+void
+my_context_install_suspend_resume_hook(struct mysql_async_context *b,
+ void (*hook)(my_bool, void *),
+ void *user_data)
+{
+ b->suspend_resume_hook= hook;
+ b->suspend_resume_hook_user_data= user_data;
+}
+
+
+/* Asynchronous connect(); socket must already be set non-blocking. */
+int
+my_connect_async(MARIADB_PVIO *pvio,
+ const struct sockaddr *name, uint namelen, int vio_timeout)
+{
+ int res;
+ size_socket s_err_size;
+ struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
+ my_socket sock;
+
+ ma_pvio_get_handle(pvio, &sock);
+
+ /* Make the socket non-blocking. */
+ ma_pvio_blocking(pvio, 0, 0);
+
+ b->events_to_wait_for= 0;
+ /*
+ Start to connect asynchronously.
+ If this will block, we suspend the call and return control to the
+ application context. The application will then resume us when the socket
+ polls ready for write, indicating that the connection attempt completed.
+ */
+ res= connect(sock, name, namelen);
+ if (res != 0)
+ {
+#ifdef _WIN32
+ int wsa_err= WSAGetLastError();
+ if (wsa_err != WSAEWOULDBLOCK)
+ return res;
+ b->events_to_wait_for|= MYSQL_WAIT_EXCEPT;
+#else
+ int err= errno;
+ if (err != EINPROGRESS && err != EALREADY && err != EAGAIN)
+ return res;
+#endif
+ b->events_to_wait_for|= MYSQL_WAIT_WRITE;
+ if (vio_timeout >= 0)
+ {
+ b->timeout_value= vio_timeout;
+ b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
+ }
+ else
+ b->timeout_value= 0;
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ if (b->events_occurred & MYSQL_WAIT_TIMEOUT)
+ return -1;
+
+ s_err_size= sizeof(res);
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0)
+ return -1;
+ if (res)
+ {
+ errno= res;
+ return -1;
+ }
+ }
+ return res;
+}
+
+#define IS_BLOCKING_ERROR() \
+ IF_WIN(WSAGetLastError() != WSAEWOULDBLOCK, \
+ (errno != EAGAIN && errno != EINTR))
+
+#ifdef _AIX
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+#endif
+
+#ifdef HAVE_TLS_FIXME
+static my_bool
+my_ssl_async_check_result(int res, struct mysql_async_context *b, MARIADB_SSL *cssl)
+{
+ int ssl_err;
+ b->events_to_wait_for= 0;
+ if (res >= 0)
+ return 1;
+ ssl_err= SSL_get_error(ssl, res);
+ if (ssl_err == SSL_ERROR_WANT_READ)
+ b->events_to_wait_for|= MYSQL_WAIT_READ;
+ else if (ssl_err == SSL_ERROR_WANT_WRITE)
+ b->events_to_wait_for|= MYSQL_WAIT_WRITE;
+ else
+ return 1;
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ return 0;
+}
+
+int
+my_ssl_read_async(struct mysql_async_context *b, SSL *ssl,
+ void *buf, int size)
+{
+ int res;
+
+ for (;;)
+ {
+ res= SSL_read(ssl, buf, size);
+ if (my_ssl_async_check_result(res, b, ssl))
+ return res;
+ }
+}
+
+int
+my_ssl_write_async(struct mysql_async_context *b, SSL *ssl,
+ const void *buf, int size)
+{
+ int res;
+
+ for (;;)
+ {
+ res= SSL_write(ssl, buf, size);
+ if (my_ssl_async_check_result(res, b, ssl))
+ return res;
+ }
+}
+#endif /* HAVE_OPENSSL */
+
+
+
+
+/*
+ Now create non-blocking definitions for all the calls that may block.
+
+ Each call FOO gives rise to FOO_start() that prepares the MYSQL object for
+ doing non-blocking calls that can suspend operation mid-way, and then starts
+ the call itself. And a FOO_start_internal trampoline to assist with running
+ the real call in a co-routine that can be suspended. And a FOO_cont() that
+ can continue a suspended operation.
+*/
+
+#define MK_ASYNC_INTERNAL_BODY(call, invoke_args, mysql_val, ret_type, ok_val)\
+ struct call ## _params *parms= (struct call ## _params *)d; \
+ ret_type ret; \
+ struct mysql_async_context *b= \
+ (mysql_val)->options.extension->async_context; \
+ \
+ ret= call invoke_args; \
+ b->ret_result. ok_val = ret; \
+ b->events_to_wait_for= 0;
+
+#define MK_ASYNC_START_BODY(call, mysql_val, parms_assign, err_val, ok_val, extra1) \
+ int res; \
+ struct mysql_async_context *b; \
+ struct call ## _params parms; \
+ \
+ extra1 \
+ b= mysql_val->options.extension->async_context; \
+ parms_assign \
+ \
+ b->active= 1; \
+ res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \
+ b->active= b->suspended= 0; \
+ if (res > 0) \
+ { \
+ /* Suspended. */ \
+ b->suspended= 1; \
+ return b->events_to_wait_for; \
+ } \
+ if (res < 0) \
+ { \
+ set_mariadb_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
+ *ret= err_val; \
+ } \
+ else \
+ *ret= b->ret_result. ok_val; \
+ return 0;
+
+#define MK_ASYNC_CONT_BODY(mysql_val, err_val, ok_val) \
+ int res; \
+ struct mysql_async_context *b= \
+ (mysql_val)->options.extension->async_context; \
+ if (!b->suspended) \
+ { \
+ set_mariadb_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \
+ *ret= err_val; \
+ return 0; \
+ } \
+ \
+ b->active= 1; \
+ b->events_occurred= ready_status; \
+ res= my_context_continue(&b->async_context); \
+ b->active= 0; \
+ if (res > 0) \
+ return b->events_to_wait_for; /* (Still) suspended */ \
+ b->suspended= 0; \
+ if (res < 0) \
+ { \
+ set_mariadb_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
+ *ret= err_val; \
+ } \
+ else \
+ *ret= b->ret_result. ok_val; /* Finished. */ \
+ return 0;
+
+#define MK_ASYNC_INTERNAL_BODY_VOID_RETURN(call, invoke_args, mysql_val) \
+ struct call ## _params *parms= (struct call ## _params *)d; \
+ struct mysql_async_context *b= \
+ (mysql_val)->options.extension->async_context; \
+ \
+ call invoke_args; \
+ b->events_to_wait_for= 0;
+
+#define MK_ASYNC_START_BODY_VOID_RETURN(call, mysql_val, parms_assign, extra1)\
+ int res; \
+ struct mysql_async_context *b; \
+ struct call ## _params parms; \
+ \
+ extra1 \
+ b= mysql_val->options.extension->async_context; \
+ parms_assign \
+ \
+ b->active= 1; \
+ res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \
+ b->active= b->suspended= 0; \
+ if (res > 0) \
+ { \
+ /* Suspended. */ \
+ b->suspended= 1; \
+ return b->events_to_wait_for; \
+ } \
+ if (res < 0) \
+ set_mariadb_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
+ return 0;
+
+#define MK_ASYNC_CONT_BODY_VOID_RETURN(mysql_val) \
+ int res; \
+ struct mysql_async_context *b= \
+ (mysql_val)->options.extension->async_context; \
+ if (!b->suspended) \
+ { \
+ set_mariadb_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \
+ return 0; \
+ } \
+ \
+ b->active= 1; \
+ b->events_occurred= ready_status; \
+ res= my_context_continue(&b->async_context); \
+ b->active= 0; \
+ if (res > 0) \
+ return b->events_to_wait_for; /* (Still) suspended */ \
+ b->suspended= 0; \
+ if (res < 0) \
+ set_mariadb_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
+ return 0;
+
+
+/* Structure used to pass parameters from mysql_real_connect_start(). */
+struct mysql_real_connect_params {
+ MYSQL *mysql;
+ const char *host;
+ const char *user;
+ const char *passwd;
+ const char *db;
+ unsigned int port;
+ const char *unix_socket;
+ unsigned long client_flags;
+};
+static void
+mysql_real_connect_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_real_connect,
+ (parms->mysql, parms->host, parms->user, parms->passwd, parms->db,
+ parms->port, parms->unix_socket, parms->client_flags),
+ parms->mysql,
+ MYSQL *,
+ r_ptr)
+}
+int STDCALL
+mysql_real_connect_start(MYSQL **ret, MYSQL *mysql, const char *host,
+ const char *user, const char *passwd, const char *db,
+ unsigned int port, const char *unix_socket,
+ unsigned long client_flags)
+{
+MK_ASYNC_START_BODY(
+ mysql_real_connect,
+ mysql,
+ {
+ parms.mysql= mysql;
+ parms.host= host;
+ parms.user= user;
+ parms.passwd= passwd;
+ parms.db= db;
+ parms.port= port;
+ parms.unix_socket= unix_socket;
+ parms.client_flags= client_flags | CLIENT_REMEMBER_OPTIONS;
+ },
+ NULL,
+ r_ptr,
+ /* Nothing */)
+}
+int STDCALL
+mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ NULL,
+ r_ptr)
+}
+
+/* Structure used to pass parameters from mysql_real_query_start(). */
+struct mysql_real_query_params {
+ MYSQL *mysql;
+ const char *stmt_str;
+ unsigned long length;
+};
+static void
+mysql_real_query_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_real_query,
+ (parms->mysql, parms->stmt_str, parms->length),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length)
+{
+ int res;
+ struct mysql_async_context *b;
+ struct mysql_real_query_params parms;
+
+ b= mysql->options.extension->async_context;
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.stmt_str= stmt_str;
+ parms.length= length;
+ }
+
+ b->active= 1;
+ res= my_context_spawn(&b->async_context, mysql_real_query_start_internal, &parms);
+ b->active= b->suspended= 0;
+ if (res > 0)
+ {
+ /* Suspended. */
+ b->suspended= 1;
+ return b->events_to_wait_for;
+ }
+ if (res < 0)
+ {
+ set_mariadb_error((mysql), CR_OUT_OF_MEMORY, unknown_sqlstate);
+ *ret= 1;
+ }
+ else
+ *ret= b->ret_result.r_int;
+ return 0;
+
+}
+int STDCALL
+mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_fetch_row_start(). */
+struct mysql_fetch_row_params {
+ MYSQL_RES *result;
+};
+static void
+mysql_fetch_row_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_fetch_row,
+ (parms->result),
+ parms->result->handle,
+ MYSQL_ROW,
+ r_ptr)
+}
+int STDCALL
+mysql_fetch_row_start(MYSQL_ROW *ret, MYSQL_RES *result)
+{
+MK_ASYNC_START_BODY(
+ mysql_fetch_row,
+ result->handle,
+ {
+ WIN_SET_NONBLOCKING(result->handle)
+ parms.result= result;
+ },
+ NULL,
+ r_ptr,
+ /*
+ If we already fetched all rows from server (eg. mysql_store_result()),
+ then result->handle will be NULL and we cannot suspend. But that is fine,
+ since in this case mysql_fetch_row cannot block anyway. Just return
+ directly.
+ */
+ if (!result->handle)
+ {
+ *ret= mysql_fetch_row(result);
+ return 0;
+ })
+}
+int STDCALL
+mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ result->handle,
+ NULL,
+ r_ptr)
+}
+
+/* Structure used to pass parameters from mysql_set_character_set_start(). */
+struct mysql_set_character_set_params {
+ MYSQL *mysql;
+ const char *csname;
+};
+static void
+mysql_set_character_set_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_set_character_set,
+ (parms->mysql, parms->csname),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_set_character_set_start(int *ret, MYSQL *mysql, const char *csname)
+{
+MK_ASYNC_START_BODY(
+ mysql_set_character_set,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.csname= csname;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_set_character_set_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_sekect_db_start(). */
+struct mysql_select_db_params {
+ MYSQL *mysql;
+ const char *db;
+};
+static void
+mysql_select_db_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_select_db,
+ (parms->mysql, parms->db),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_select_db_start(int *ret, MYSQL *mysql, const char *db)
+{
+MK_ASYNC_START_BODY(
+ mysql_select_db,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.db= db;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_select_db_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_send_query_start(). */
+struct mysql_send_query_params {
+ MYSQL *mysql;
+ const char *q;
+ unsigned long length;
+};
+static void
+mysql_send_query_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_send_query,
+ (parms->mysql, parms->q, parms->length),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_send_query_start(int *ret, MYSQL *mysql, const char *q, unsigned long length)
+{
+MK_ASYNC_START_BODY(
+ mysql_send_query,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.q= q;
+ parms.length= length;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_send_query_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_store_result_start(). */
+struct mysql_store_result_params {
+ MYSQL *mysql;
+};
+static void
+mysql_store_result_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_store_result,
+ (parms->mysql),
+ parms->mysql,
+ MYSQL_RES *,
+ r_ptr)
+}
+int STDCALL
+mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_store_result,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ NULL,
+ r_ptr,
+ /* Nothing */)
+}
+int STDCALL
+mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ NULL,
+ r_ptr)
+}
+
+/* Structure used to pass parameters from mysql_free_result_start(). */
+struct mysql_free_result_params {
+ MYSQL_RES *result;
+};
+static void
+mysql_free_result_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
+ mysql_free_result,
+ (parms->result),
+ parms->result->handle)
+}
+int STDCALL
+mysql_free_result_start(MYSQL_RES *result)
+{
+MK_ASYNC_START_BODY_VOID_RETURN(
+ mysql_free_result,
+ result->handle,
+ {
+ WIN_SET_NONBLOCKING(result->handle)
+ parms.result= result;
+ },
+ /*
+ mysql_free_result() can have NULL in result->handle (this happens when all
+ rows have been fetched and mysql_fetch_row() returned NULL.)
+ So we cannot suspend, but it does not matter, as in this case
+ mysql_free_result() cannot block.
+ It is also legitimate to have NULL result, which will do nothing.
+ */
+ if (!result || !result->handle)
+ {
+ mysql_free_result(result);
+ return 0;
+ })
+}
+int STDCALL
+mysql_free_result_cont(MYSQL_RES *result, int ready_status)
+{
+MK_ASYNC_CONT_BODY_VOID_RETURN(result->handle)
+}
+
+/* Structure used to pass parameters from mysql_close_slow_part_start(). */
+struct mysql_close_slow_part_params {
+ MYSQL *sock;
+};
+/*
+ We need special handling for mysql_close(), as the first part may block,
+ while the last part needs to free our extra library context stack.
+
+ So we do the first part (mysql_close_slow_part()) non-blocking, but the last
+ part blocking.
+*/
+static void
+mysql_close_slow_part_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
+ mysql_close_slow_part,
+ (parms->sock),
+ parms->sock)
+}
+
+int STDCALL
+mysql_close_slow_part_start(MYSQL *sock)
+{
+MK_ASYNC_START_BODY_VOID_RETURN(
+ mysql_close_slow_part,
+ sock,
+ {
+ WIN_SET_NONBLOCKING(sock)
+ parms.sock= sock;
+ },
+ /* Nothing */)
+}
+int STDCALL
+mysql_close_slow_part_cont(MYSQL *sock, int ready_status)
+{
+MK_ASYNC_CONT_BODY_VOID_RETURN(sock)
+}
+int STDCALL
+mysql_close_start(MYSQL *sock)
+{
+ int res;
+
+ /* It is legitimate to have NULL sock argument, which will do nothing. */
+ if (sock && sock->net.pvio)
+ {
+ res= mysql_close_slow_part_start(sock);
+ /* If we need to block, return now and do the rest in mysql_close_cont(). */
+ if (res)
+ return res;
+ }
+ mysql_close(sock);
+ return 0;
+}
+int STDCALL
+mysql_close_cont(MYSQL *sock, int ready_status)
+{
+ int res;
+
+ res= mysql_close_slow_part_cont(sock, ready_status);
+ if (res)
+ return res;
+ mysql_close(sock);
+ return 0;
+}
+
+/*
+ These following are not available inside the server (neither blocking or
+ non-blocking).
+*/
+#ifndef MYSQL_SERVER
+/* Structure used to pass parameters from mysql_change_user_start(). */
+struct mysql_change_user_params {
+ MYSQL *mysql;
+ const char *user;
+ const char *passwd;
+ const char *db;
+};
+static void
+mysql_change_user_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_change_user,
+ (parms->mysql, parms->user, parms->passwd, parms->db),
+ parms->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_change_user_start(my_bool *ret, MYSQL *mysql, const char *user, const char *passwd, const char *db)
+{
+MK_ASYNC_START_BODY(
+ mysql_change_user,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.user= user;
+ parms.passwd= passwd;
+ parms.db= db;
+ },
+ TRUE,
+ r_my_bool,
+ /* Nothing */)
+}
+int STDCALL
+mysql_change_user_cont(my_bool *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_query_start(). */
+struct mysql_query_params {
+ MYSQL *mysql;
+ const char *q;
+};
+static void
+mysql_query_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_query,
+ (parms->mysql, parms->q),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_query_start(int *ret, MYSQL *mysql, const char *q)
+{
+MK_ASYNC_START_BODY(
+ mysql_query,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.q= q;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_query_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_shutdown_start(). */
+struct mysql_shutdown_params {
+ MYSQL *mysql;
+ enum mysql_enum_shutdown_level shutdown_level;
+};
+static void
+mysql_shutdown_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_shutdown,
+ (parms->mysql, parms->shutdown_level),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_shutdown_start(int *ret, MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
+{
+MK_ASYNC_START_BODY(
+ mysql_shutdown,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.shutdown_level= shutdown_level;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_shutdown_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_dump_debug_info_start(). */
+struct mysql_dump_debug_info_params {
+ MYSQL *mysql;
+};
+static void
+mysql_dump_debug_info_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_dump_debug_info,
+ (parms->mysql),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_dump_debug_info_start(int *ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_dump_debug_info,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_refresh_start(). */
+struct mysql_refresh_params {
+ MYSQL *mysql;
+ unsigned int refresh_options;
+};
+static void
+mysql_refresh_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_refresh,
+ (parms->mysql, parms->refresh_options),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_refresh_start(int *ret, MYSQL *mysql, unsigned int refresh_options)
+{
+MK_ASYNC_START_BODY(
+ mysql_refresh,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.refresh_options= refresh_options;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_refresh_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_kill_start(). */
+struct mysql_kill_params {
+ MYSQL *mysql;
+ unsigned long pid;
+};
+static void
+mysql_kill_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_kill,
+ (parms->mysql, parms->pid),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_kill_start(int *ret, MYSQL *mysql, unsigned long pid)
+{
+MK_ASYNC_START_BODY(
+ mysql_kill,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.pid= pid;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_kill_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_set_server_option_start(). */
+struct mysql_set_server_option_params {
+ MYSQL *mysql;
+ enum enum_mysql_set_option option;
+};
+static void
+mysql_set_server_option_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_set_server_option,
+ (parms->mysql, parms->option),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_set_server_option_start(int *ret, MYSQL *mysql,
+ enum enum_mysql_set_option option)
+{
+MK_ASYNC_START_BODY(
+ mysql_set_server_option,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.option= option;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_set_server_option_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_ping_start(). */
+struct mysql_ping_params {
+ MYSQL *mysql;
+};
+static void
+mysql_ping_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_ping,
+ (parms->mysql),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_ping_start(int *ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_ping,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_ping_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_reset_connection_start(). */
+struct mysql_reset_connection_params {
+ MYSQL *mysql;
+};
+static void
+mysql_reset_connection_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_reset_connection,
+ (parms->mysql),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_reset_connection_start(int *ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_reset_connection,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_reset_connection_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_stat_start(). */
+struct mysql_stat_params {
+ MYSQL *mysql;
+};
+static void
+mysql_stat_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stat,
+ (parms->mysql),
+ parms->mysql,
+ const char *,
+ r_const_ptr)
+}
+int STDCALL
+mysql_stat_start(const char **ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_stat,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ NULL,
+ r_const_ptr,
+ /* Nothing */)
+}
+int STDCALL
+mysql_stat_cont(const char **ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ NULL,
+ r_const_ptr)
+}
+
+/* Structure used to pass parameters from mysql_list_dbs_start(). */
+struct mysql_list_dbs_params {
+ MYSQL *mysql;
+ const char *wild;
+};
+static void
+mysql_list_dbs_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_list_dbs,
+ (parms->mysql, parms->wild),
+ parms->mysql,
+ MYSQL_RES *,
+ r_ptr)
+}
+int STDCALL
+mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
+{
+MK_ASYNC_START_BODY(
+ mysql_list_dbs,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.wild= wild;
+ },
+ NULL,
+ r_ptr,
+ /* Nothing */)
+}
+int STDCALL
+mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ NULL,
+ r_ptr)
+}
+
+/* Structure used to pass parameters from mysql_list_tables_start(). */
+struct mysql_list_tables_params {
+ MYSQL *mysql;
+ const char *wild;
+};
+static void
+mysql_list_tables_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_list_tables,
+ (parms->mysql, parms->wild),
+ parms->mysql,
+ MYSQL_RES *,
+ r_ptr)
+}
+int STDCALL
+mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
+{
+MK_ASYNC_START_BODY(
+ mysql_list_tables,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.wild= wild;
+ },
+ NULL,
+ r_ptr,
+ /* Nothing */)
+}
+int STDCALL
+mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ NULL,
+ r_ptr)
+}
+
+/* Structure used to pass parameters from mysql_list_processes_start(). */
+struct mysql_list_processes_params {
+ MYSQL *mysql;
+};
+static void
+mysql_list_processes_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_list_processes,
+ (parms->mysql),
+ parms->mysql,
+ MYSQL_RES *,
+ r_ptr)
+}
+int STDCALL
+mysql_list_processes_start(MYSQL_RES **ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_list_processes,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ NULL,
+ r_ptr,
+ /* Nothing */)
+}
+int STDCALL
+mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ NULL,
+ r_ptr)
+}
+
+/* Structure used to pass parameters from mysql_list_fields_start(). */
+struct mysql_list_fields_params {
+ MYSQL *mysql;
+ const char *table;
+ const char *wild;
+};
+static void
+mysql_list_fields_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_list_fields,
+ (parms->mysql, parms->table, parms->wild),
+ parms->mysql,
+ MYSQL_RES *,
+ r_ptr)
+}
+int STDCALL
+mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, const char *table,
+ const char *wild)
+{
+MK_ASYNC_START_BODY(
+ mysql_list_fields,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.table= table;
+ parms.wild= wild;
+ },
+ NULL,
+ r_ptr,
+ /* Nothing */)
+}
+int STDCALL
+mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ NULL,
+ r_ptr)
+}
+
+/* Structure used to pass parameters from mysql_read_query_result_start(). */
+struct mysql_read_query_result_params {
+ MYSQL *mysql;
+};
+static void
+mysql_read_query_result_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_read_query_result,
+ (parms->mysql),
+ parms->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_read_query_result_start(my_bool *ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_read_query_result,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ TRUE,
+ r_my_bool,
+ /* Nothing */)
+}
+int STDCALL
+mysql_read_query_result_cont(my_bool *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_stmt_prepare_start(). */
+struct mysql_stmt_prepare_params {
+ MYSQL_STMT *stmt;
+ const char *query;
+ unsigned long length;
+};
+static void
+mysql_stmt_prepare_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_prepare,
+ (parms->stmt, parms->query, parms->length),
+ parms->stmt->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt, const char *query,
+ unsigned long length)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_prepare,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ parms.query= query;
+ parms.length= length;
+ },
+ 1,
+ r_int,
+ /* If stmt->mysql==NULL then we will not block so can call directly. */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_prepare(stmt, query, length);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_stmt_execute_start(). */
+struct mysql_stmt_execute_params {
+ MYSQL_STMT *stmt;
+};
+static void
+mysql_stmt_execute_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_execute,
+ (parms->stmt),
+ parms->stmt->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_execute,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ },
+ 1,
+ r_int,
+ /*
+ If eg. mysql_change_user(), stmt->mysql will be NULL.
+ In this case, we cannot block.
+ */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_execute(stmt);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_stmt_fetch_start(). */
+struct mysql_stmt_fetch_params {
+ MYSQL_STMT *stmt;
+};
+static void
+mysql_stmt_fetch_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_fetch,
+ (parms->stmt),
+ parms->stmt->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_fetch,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ },
+ 1,
+ r_int,
+ /* If stmt->mysql==NULL then we will not block so can call directly. */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_fetch(stmt);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_stmt_store_result_start(). */
+struct mysql_stmt_store_result_params {
+ MYSQL_STMT *stmt;
+};
+static void
+mysql_stmt_store_result_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_store_result,
+ (parms->stmt),
+ parms->stmt->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_store_result,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ },
+ 1,
+ r_int,
+ /* If stmt->mysql==NULL then we will not block so can call directly. */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_store_result(stmt);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_stmt_close_start(). */
+struct mysql_stmt_close_params {
+ MYSQL_STMT *stmt;
+};
+static void
+mysql_stmt_close_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_close,
+ (parms->stmt),
+ parms->stmt->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_close,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ },
+ TRUE,
+ r_my_bool,
+ /* If stmt->mysql==NULL then we will not block so can call directly. */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_close(stmt);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_stmt_reset_start(). */
+struct mysql_stmt_reset_params {
+ MYSQL_STMT *stmt;
+};
+static void
+mysql_stmt_reset_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_reset,
+ (parms->stmt),
+ parms->stmt->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT *stmt)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_reset,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ },
+ TRUE,
+ r_my_bool,
+ /* If stmt->mysql==NULL then we will not block so can call directly. */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_reset(stmt);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_stmt_free_result_start(). */
+struct mysql_stmt_free_result_params {
+ MYSQL_STMT *stmt;
+};
+static void
+mysql_stmt_free_result_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_free_result,
+ (parms->stmt),
+ parms->stmt->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_free_result,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ },
+ TRUE,
+ r_my_bool,
+ /* If stmt->mysql==NULL then we will not block so can call directly. */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_free_result(stmt);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_stmt_send_long_data_start(). */
+struct mysql_stmt_send_long_data_params {
+ MYSQL_STMT *stmt;
+ unsigned int param_number;
+ const char *data;
+ unsigned long length;
+};
+static void
+mysql_stmt_send_long_data_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_send_long_data,
+ (parms->stmt, parms->param_number, parms->data, parms->length),
+ parms->stmt->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt,
+ unsigned int param_number,
+ const char *data, unsigned long length)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_send_long_data,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ parms.param_number= param_number;
+ parms.data= data;
+ parms.length= length;
+ },
+ TRUE,
+ r_my_bool,
+ /* If stmt->mysql==NULL then we will not block so can call directly. */
+ if (!stmt->mysql)
+ {
+ *ret= mysql_stmt_send_long_data(stmt, param_number, data, length);
+ return 0;
+ })
+}
+int STDCALL
+mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_commit_start(). */
+struct mysql_commit_params {
+ MYSQL *mysql;
+};
+static void
+mysql_commit_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_commit,
+ (parms->mysql),
+ parms->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_commit_start(my_bool *ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_commit,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ TRUE,
+ r_my_bool,
+ /* Nothing */)
+}
+int STDCALL
+mysql_commit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_rollback_start(). */
+struct mysql_rollback_params {
+ MYSQL *mysql;
+};
+static void
+mysql_rollback_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_rollback,
+ (parms->mysql),
+ parms->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_rollback_start(my_bool *ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_rollback,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ TRUE,
+ r_my_bool,
+ /* Nothing */)
+}
+int STDCALL
+mysql_rollback_cont(my_bool *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_autocommit_start(). */
+struct mysql_autocommit_params {
+ MYSQL *mysql;
+ my_bool auto_mode;
+};
+static void
+mysql_autocommit_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_autocommit,
+ (parms->mysql, parms->auto_mode),
+ parms->mysql,
+ my_bool,
+ r_my_bool)
+}
+int STDCALL
+mysql_autocommit_start(my_bool *ret, MYSQL *mysql, my_bool auto_mode)
+{
+MK_ASYNC_START_BODY(
+ mysql_autocommit,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ parms.auto_mode= auto_mode;
+ },
+ TRUE,
+ r_my_bool,
+ /* Nothing */)
+}
+int STDCALL
+mysql_autocommit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ TRUE,
+ r_my_bool)
+}
+
+/* Structure used to pass parameters from mysql_next_result_start(). */
+struct mysql_next_result_params {
+ MYSQL *mysql;
+};
+static void
+mysql_next_result_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_next_result,
+ (parms->mysql),
+ parms->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_next_result_start(int *ret, MYSQL *mysql)
+{
+MK_ASYNC_START_BODY(
+ mysql_next_result,
+ mysql,
+ {
+ WIN_SET_NONBLOCKING(mysql)
+ parms.mysql= mysql;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_next_result_cont(int *ret, MYSQL *mysql, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ mysql,
+ 1,
+ r_int)
+}
+
+/* Structure used to pass parameters from mysql_stmt_next_result_start(). */
+struct mysql_stmt_next_result_params {
+ MYSQL_STMT *stmt;
+};
+static void
+mysql_stmt_next_result_start_internal(void *d)
+{
+MK_ASYNC_INTERNAL_BODY(
+ mysql_stmt_next_result,
+ (parms->stmt),
+ parms->stmt->mysql,
+ int,
+ r_int)
+}
+int STDCALL
+mysql_stmt_next_result_start(int *ret, MYSQL_STMT *stmt)
+{
+MK_ASYNC_START_BODY(
+ mysql_stmt_next_result,
+ stmt->mysql,
+ {
+ WIN_SET_NONBLOCKING(stmt->mysql)
+ parms.stmt= stmt;
+ },
+ 1,
+ r_int,
+ /* Nothing */)
+}
+int STDCALL
+mysql_stmt_next_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
+{
+MK_ASYNC_CONT_BODY(
+ stmt->mysql,
+ 1,
+ r_int)
+}
+#endif
+
+
+/*
+ The following functions are deprecated, and so have no non-blocking version:
+
+ mysql_connect
+ mysql_create_db
+ mysql_drop_db
+*/
+
+/*
+ The following functions can newer block, and so do not have special
+ non-blocking versions:
+
+ mysql_num_rows()
+ mysql_num_fields()
+ mysql_eof()
+ mysql_fetch_field_direct()
+ mysql_fetch_fields()
+ mysql_row_tell()
+ mysql_field_tell()
+ mysql_field_count()
+ mysql_affected_rows()
+ mysql_insert_id()
+ mysql_errno()
+ mysql_error()
+ mysql_sqlstate()
+ mysql_warning_count()
+ mysql_info()
+ mysql_thread_id()
+ mysql_character_set_name()
+ mysql_init()
+ mysql_ssl_set()
+ mysql_get_ssl_cipher()
+ mysql_use_result()
+ mysql_get_character_set_info()
+ mysql_set_local_infile_handler()
+ mysql_set_local_infile_default()
+ mysql_get_server_info()
+ mysql_get_server_name()
+ mysql_get_client_info()
+ mysql_get_client_version()
+ mysql_get_host_info()
+ mysql_get_server_version()
+ mysql_get_proto_info()
+ mysql_options()
+ mysql_data_seek()
+ mysql_row_seek()
+ mysql_field_seek()
+ mysql_fetch_lengths()
+ mysql_fetch_field()
+ mysql_escape_string()
+ mysql_hex_string()
+ mysql_real_escape_string()
+ mysql_debug()
+ myodbc_remove_escape()
+ mysql_thread_safe()
+ mysql_embedded()
+ mariadb_connection()
+ mysql_stmt_init()
+ mysql_stmt_fetch_column()
+ mysql_stmt_param_count()
+ mysql_stmt_attr_set()
+ mysql_stmt_attr_get()
+ mysql_stmt_bind_param()
+ mysql_stmt_bind_result()
+ mysql_stmt_result_metadata()
+ mysql_stmt_param_metadata()
+ mysql_stmt_errno()
+ mysql_stmt_error()
+ mysql_stmt_sqlstate()
+ mysql_stmt_row_seek()
+ mysql_stmt_row_tell()
+ mysql_stmt_data_seek()
+ mysql_stmt_num_rows()
+ mysql_stmt_affected_rows()
+ mysql_stmt_insert_id()
+ mysql_stmt_field_count()
+ mysql_more_results()
+ mysql_get_socket()
+ mysql_get_timeout_value()
+*/
diff --git a/libmariadb/libmariadb/mariadb_charset.c b/libmariadb/libmariadb/mariadb_charset.c
new file mode 100644
index 00000000..a406af2f
--- /dev/null
+++ b/libmariadb/libmariadb/mariadb_charset.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+ 2016 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+// #include "mysys_err.h"
+#include <mariadb_ctype.h>
+#include <ma_string.h>
+
+MARIADB_CHARSET_INFO *ma_default_charset_info; /* will be set in mysql_server_init */
+MARIADB_CHARSET_INFO *ma_charset_bin= (MARIADB_CHARSET_INFO *)&mariadb_compiled_charsets[32];
+MARIADB_CHARSET_INFO *ma_charset_latin1= (MARIADB_CHARSET_INFO *)&mariadb_compiled_charsets[5];
+MARIADB_CHARSET_INFO *ma_charset_utf8_general_ci= (MARIADB_CHARSET_INFO *)&mariadb_compiled_charsets[21];
+MARIADB_CHARSET_INFO *ma_charset_utf16le_general_ci= (MARIADB_CHARSET_INFO *)&mariadb_compiled_charsets[68];
+
+MARIADB_CHARSET_INFO * STDCALL mysql_get_charset_by_nr(uint cs_number)
+{
+ int i= 0;
+
+ while (mariadb_compiled_charsets[i].nr && cs_number != mariadb_compiled_charsets[i].nr)
+ i++;
+
+ return (mariadb_compiled_charsets[i].nr) ? (MARIADB_CHARSET_INFO *)&mariadb_compiled_charsets[i] : NULL;
+}
+
+my_bool set_default_charset(uint cs, myf flags __attribute__((unused)))
+{
+ MARIADB_CHARSET_INFO *new_charset;
+ new_charset = mysql_get_charset_by_nr(cs);
+ if (!new_charset)
+ {
+ return(TRUE); /* error */
+ }
+ ma_default_charset_info = new_charset;
+ return(FALSE);
+}
+
+MARIADB_CHARSET_INFO * STDCALL mysql_get_charset_by_name(const char *cs_name)
+{
+ int i= 0;
+
+ while (mariadb_compiled_charsets[i].nr && strcmp(cs_name, mariadb_compiled_charsets[i].csname) != 0)
+ i++;
+
+ return (mariadb_compiled_charsets[i].nr) ? (MARIADB_CHARSET_INFO *)&mariadb_compiled_charsets[i] : NULL;
+}
+
+my_bool set_default_charset_by_name(const char *cs_name, myf flags __attribute__((unused)))
+{
+ MARIADB_CHARSET_INFO *new_charset;
+ new_charset = mysql_get_charset_by_name(cs_name);
+ if (!new_charset)
+ {
+ return(TRUE); /* error */
+ }
+
+ ma_default_charset_info = new_charset;
+ return(FALSE);
+}
diff --git a/libmariadb/libmariadb/mariadb_dyncol.c b/libmariadb/libmariadb/mariadb_dyncol.c
new file mode 100644
index 00000000..42de69ee
--- /dev/null
+++ b/libmariadb/libmariadb/mariadb_dyncol.c
@@ -0,0 +1,4369 @@
+/* Copyright (c) 2011,2013 Monty Program Ab;
+ Copyright (c) 2011,2012 Oleksandr Byelkin
+ 2013, 2022 MariaDB Corporation AB
+
+ 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 the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``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 <COPYRIGHT HOLDER> OR
+ CONTRIBUTORS 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.
+*/
+
+/*
+ Numeric format:
+ ===============
+ * Fixed header part
+ 1 byte flags:
+ 0,1 bits - <offset size> - 1
+ 2-7 bits - 0
+ 2 bytes column counter
+ * Columns directory sorted by column number, each entry contains of:
+ 2 bytes column number
+ <offset size> bytes (1-4) combined offset from beginning of
+ the data segment + 3 bit type
+ * Data of above columns size of data and length depend on type
+
+ Columns with names:
+ ===================
+ * Fixed header part
+ 1 byte flags:
+ 0,1 bits - <offset size> - 2
+ 2 bit - 1 (means format with names)
+ 3,4 bits - 00 (means <names offset size> - 2,
+ now 2 is the only supported size)
+ 5-7 bits - 0
+ 2 bytes column counter
+ * Variable header part (now it is actually fixed part)
+ <names offset size> (2) bytes size of stored names pool
+ * Column directory sorted by names, each consists of
+ <names offset size> (2) bytes offset of name
+ <offset size> bytes (2-5)bytes combined offset from beginning of
+ the data segment + 4 bit type
+ * Names stored one after another
+ * Data of above columns size of data and length depend on type
+*/
+
+#include <stdio.h>
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_string.h>
+//#include <ma_hashtbl.h>
+#include <mariadb_dyncol.h>
+#include <mysql.h>
+
+
+
+#ifndef LIBMARIADB
+uint32 copy_and_convert(char *to, uint32 to_length, MARIADB_CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length,
+ MARIADB_CHARSET_INFO *from_cs, uint *errors);
+#else
+
+size_t mariadb_time_to_string(const MYSQL_TIME *tm, char *time_str, size_t len,
+ unsigned int digits);
+size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, MARIADB_CHARSET_INFO *from_cs,
+ char *to, size_t *to_len, MARIADB_CHARSET_INFO *to_cs, int *errorcode);
+#endif
+/*
+ Flag byte bits
+
+ 2 bits which determinate size of offset in the header -1
+*/
+/* mask to get above bits */
+#define DYNCOL_FLG_OFFSET (1|2)
+#define DYNCOL_FLG_NAMES 4
+#define DYNCOL_FLG_NMOFFSET (8|16)
+/**
+ All known flags mask that could be set.
+
+ @note DYNCOL_FLG_NMOFFSET should be 0 for now.
+*/
+#define DYNCOL_FLG_KNOWN (1|2|4)
+
+/* formats */
+enum enum_dyncol_format
+{
+ dyncol_fmt_num= 0,
+ dyncol_fmt_str= 1
+};
+
+/* dynamic column size reserve */
+#define DYNCOL_SYZERESERVE 80
+
+#define DYNCOL_OFFSET_ERROR 0xffffffff
+
+/* length of fixed string header 1 byte - flags, 2 bytes - columns counter */
+#define FIXED_HEADER_SIZE 3
+/*
+ length of fixed string header with names
+ 1 byte - flags, 2 bytes - columns counter, 2 bytes - name pool size
+*/
+#define FIXED_HEADER_SIZE_NM 5
+
+#define COLUMN_NUMBER_SIZE 2
+/* 2 bytes offset from the name pool */
+#define COLUMN_NAMEPTR_SIZE 2
+
+#define MAX_OFFSET_LENGTH 4
+#define MAX_OFFSET_LENGTH_NM 5
+
+#define DYNCOL_NUM_CHAR 6
+
+my_bool mariadb_dyncol_has_names(DYNAMIC_COLUMN *str)
+{
+ if (str->length < 1)
+ return FALSE;
+ return test(str->str[0] & DYNCOL_FLG_NAMES);
+}
+
+static enum enum_dyncol_func_result
+dynamic_column_time_store(DYNAMIC_COLUMN *str,
+ MYSQL_TIME *value, enum enum_dyncol_format format);
+static enum enum_dyncol_func_result
+dynamic_column_date_store(DYNAMIC_COLUMN *str,
+ MYSQL_TIME *value);
+static enum enum_dyncol_func_result
+dynamic_column_time_read_internal(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length);
+static enum enum_dyncol_func_result
+dynamic_column_date_read_internal(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length);
+static enum enum_dyncol_func_result
+dynamic_column_get_internal(DYNAMIC_COLUMN *str,
+ DYNAMIC_COLUMN_VALUE *store_it_here,
+ uint num_key, LEX_STRING *str_key);
+static enum enum_dyncol_func_result
+dynamic_column_exists_internal(DYNAMIC_COLUMN *str, uint num_key,
+ LEX_STRING *str_key);
+static enum enum_dyncol_func_result
+dynamic_column_update_many_fmt(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ void *column_keys,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool string_keys);
+static int plan_sort_num(const void *a, const void *b);
+static int plan_sort_named(const void *a, const void *b);
+
+/*
+ Structure to hold information about dynamic columns record and
+ iterate through it.
+*/
+
+struct st_dyn_header
+{
+ uchar *header, *nmpool, *dtpool, *data_end;
+ size_t offset_size;
+ size_t entry_size;
+ size_t header_size;
+ size_t nmpool_size;
+ size_t data_size;
+ /* dyncol_fmt_num - numeric columns, dyncol_fmt_str - column names */
+ enum enum_dyncol_format format;
+ uint column_count;
+
+ uchar *entry, *data, *name;
+ size_t offset;
+ size_t length;
+ enum enum_dynamic_column_type type;
+};
+
+typedef struct st_dyn_header DYN_HEADER;
+
+static inline my_bool read_fixed_header(DYN_HEADER *hdr,
+ DYNAMIC_COLUMN *str);
+static void set_fixed_header(DYNAMIC_COLUMN *str,
+ uint offset_size,
+ uint column_count);
+
+/*
+ Calculate entry size (E) and header size (H) by offset size (O) and column
+ count (C) and fixed part of entry size (F).
+*/
+
+#define calc_param(E,H,F,O,C) do { \
+ (*(E))= (O) + F; \
+ (*(H))= (*(E)) * (C); \
+}while(0);
+
+
+/**
+ Name pool size functions, for numeric format it is 0
+*/
+
+static size_t name_size_num(void *keys __attribute__((unused)),
+ uint i __attribute__((unused)))
+{
+ return 0;
+}
+
+
+/**
+ Name pool size functions.
+*/
+static size_t name_size_named(void *keys, uint i)
+{
+ return ((LEX_STRING *) keys)[i].length;
+}
+
+
+/**
+ Comparator function for references on column numbers for qsort
+ (numeric format)
+*/
+
+static int column_sort_num(const void *a, const void *b)
+{
+ return **((uint **)a) - **((uint **)b);
+}
+
+/**
+ Comparator function for references on column numbers for qsort
+ (names format)
+*/
+
+int mariadb_dyncol_column_cmp_named(const LEX_STRING *s1, const LEX_STRING *s2)
+{
+ /*
+ We compare instead of subtraction to avoid data loss in case of huge
+ length difference (more then fit in int).
+ */
+ int rc= (s1->length > s2->length ? 1 :
+ (s1->length < s2->length ? -1 : 0));
+ if (rc == 0)
+ rc= memcmp((void *)s1->str, (void *)s2->str,
+ (size_t) s1->length);
+ return rc;
+}
+
+
+/**
+ Comparator function for references on column numbers for qsort
+ (names format)
+*/
+
+static int column_sort_named(const void *a, const void *b)
+{
+ return mariadb_dyncol_column_cmp_named(*((LEX_STRING **)a),
+ *((LEX_STRING **)b));
+}
+
+
+/**
+ Check limit function (numeric format)
+*/
+
+static my_bool check_limit_num(const void *val)
+{
+ return **((uint **)val) > UINT_MAX16;
+}
+
+
+/**
+ Check limit function (names format)
+*/
+
+static my_bool check_limit_named(const void *val)
+{
+ return (*((LEX_STRING **)val))->length > MAX_NAME_LENGTH;
+}
+
+
+/**
+ Write numeric format static header part.
+*/
+
+static void set_fixed_header_num(DYNAMIC_COLUMN *str, DYN_HEADER *hdr)
+{
+ set_fixed_header(str, (uint)hdr->offset_size, hdr->column_count);
+ hdr->header= (uchar *)str->str + FIXED_HEADER_SIZE;
+ hdr->nmpool= hdr->dtpool= hdr->header + hdr->header_size;
+}
+
+
+/**
+ Write names format static header part.
+*/
+
+static void set_fixed_header_named(DYNAMIC_COLUMN *str, DYN_HEADER *hdr)
+{
+ DBUG_ASSERT(hdr->column_count <= 0xffff);
+ DBUG_ASSERT(hdr->offset_size <= MAX_OFFSET_LENGTH_NM);
+ /* size of data offset, named format flag, size of names offset (0 means 2) */
+ str->str[0]=
+ (char) ((str->str[0] & ~(DYNCOL_FLG_OFFSET | DYNCOL_FLG_NMOFFSET)) |
+ (hdr->offset_size - 2) | DYNCOL_FLG_NAMES);
+ int2store(str->str + 1, hdr->column_count); /* columns number */
+ int2store(str->str + 3, hdr->nmpool_size);
+ hdr->header= (uchar *)str->str + FIXED_HEADER_SIZE_NM;
+ hdr->nmpool= hdr->header + hdr->header_size;
+ hdr->dtpool= hdr->nmpool + hdr->nmpool_size;
+}
+
+
+/**
+ Store offset and type information in the given place
+
+ @param place Beginning of the index entry
+ @param offset_size Size of offset field in bytes
+ @param type Type to be written
+ @param offset Offset to be written
+*/
+
+static my_bool type_and_offset_store_num(uchar *place, size_t offset_size,
+ DYNAMIC_COLUMN_TYPE type,
+ size_t offset)
+{
+ ulong val = (((ulong) offset) << 3) | (type - 1);
+ DBUG_ASSERT(type != DYN_COL_NULL);
+ DBUG_ASSERT(((type - 1) & (~7)) == 0); /* fit in 3 bits */
+ DBUG_ASSERT(offset_size >= 1 && offset_size <= 4);
+
+ /* Index entry starts with column number; jump over it */
+ place+= COLUMN_NUMBER_SIZE;
+
+ switch (offset_size) {
+ case 1:
+ if (offset >= 0x1f) /* all 1 value is reserved */
+ return TRUE;
+ place[0]= (uchar)val;
+ break;
+ case 2:
+ if (offset >= 0x1fff) /* all 1 value is reserved */
+ return TRUE;
+ int2store(place, val);
+ break;
+ case 3:
+ if (offset >= 0x1fffff) /* all 1 value is reserved */
+ return TRUE;
+ int3store(place, val);
+ break;
+ case 4:
+ if (offset >= 0x1fffffff) /* all 1 value is reserved */
+ return TRUE;
+ int4store(place, val);
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static my_bool type_and_offset_store_named(uchar *place, size_t offset_size,
+ DYNAMIC_COLUMN_TYPE type,
+ size_t offset)
+{
+ ulonglong val = (((ulong) offset) << 4) | (type - 1);
+ DBUG_ASSERT(type != DYN_COL_NULL);
+ DBUG_ASSERT(((type - 1) & (~0xf)) == 0); /* fit in 4 bits */
+ DBUG_ASSERT(offset_size >= 2 && offset_size <= 5);
+
+ /* Index entry starts with name offset; jump over it */
+ place+= COLUMN_NAMEPTR_SIZE;
+ switch (offset_size) {
+ case 2:
+ if (offset >= 0xfff) /* all 1 value is reserved */
+ return TRUE;
+ int2store(place, val);
+ break;
+ case 3:
+ if (offset >= 0xfffff) /* all 1 value is reserved */
+ return TRUE;
+ int3store(place, val);
+ break;
+ case 4:
+ if (offset >= 0xfffffff) /* all 1 value is reserved */
+ return TRUE;
+ int4store(place, val);
+ break;
+ case 5:
+#if SIZEOF_SIZE_T > 4
+ if (offset >= 0xfffffffffull) /* all 1 value is reserved */
+ return TRUE;
+#endif
+ int5store(place, val);
+ break;
+ case 1:
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Write numeric format header entry
+ 2 bytes - column number
+ 1-4 bytes - data offset combined with type
+
+ @param hdr descriptor of dynamic column record
+ @param column_key pointer to uint (column number)
+ @param value value which will be written (only type used)
+ @param offset offset of the data
+*/
+
+static my_bool put_header_entry_num(DYN_HEADER *hdr,
+ void *column_key,
+ DYNAMIC_COLUMN_VALUE *value,
+ size_t offset)
+{
+ uint *column_number= (uint *)column_key;
+ int2store(hdr->entry, *column_number);
+ DBUG_ASSERT(hdr->nmpool_size == 0);
+ if (type_and_offset_store_num(hdr->entry, hdr->offset_size,
+ value->type,
+ offset))
+ return TRUE;
+ hdr->entry= hdr->entry + hdr->entry_size;
+ return FALSE;
+}
+
+
+/**
+ Write names format header entry
+ 1 byte - name length
+ 2 bytes - name offset in the name pool
+ 1-4 bytes - data offset combined with type
+
+ @param hdr descriptor of dynamic column record
+ @param column_key pointer to LEX_STRING (column name)
+ @param value value which will be written (only type used)
+ @param offset offset of the data
+*/
+
+static my_bool put_header_entry_named(DYN_HEADER *hdr,
+ void *column_key,
+ DYNAMIC_COLUMN_VALUE *value,
+ size_t offset)
+{
+ LEX_STRING *column_name= (LEX_STRING *)column_key;
+ DBUG_ASSERT(column_name->length <= MAX_NAME_LENGTH);
+ DBUG_ASSERT(hdr->name - hdr->nmpool < (long) 0x10000L);
+ int2store(hdr->entry, hdr->name - hdr->nmpool);
+ memcpy(hdr->name, column_name->str, column_name->length);
+ DBUG_ASSERT(hdr->nmpool_size != 0 || column_name->length == 0);
+ if (type_and_offset_store_named(hdr->entry, hdr->offset_size,
+ value->type,
+ offset))
+ return TRUE;
+ hdr->entry+= hdr->entry_size;
+ hdr->name+= column_name->length;
+ return FALSE;
+}
+
+
+/**
+ Calculate length of offset field for given data length
+
+ @param data_length Length of the data segment
+
+ @return number of bytes
+*/
+
+static size_t dynamic_column_offset_bytes_num(size_t data_length)
+{
+ if (data_length < 0x1f) /* all 1 value is reserved */
+ return 1;
+ if (data_length < 0x1fff) /* all 1 value is reserved */
+ return 2;
+ if (data_length < 0x1fffff) /* all 1 value is reserved */
+ return 3;
+ if (data_length < 0x1fffffff) /* all 1 value is reserved */
+ return 4;
+ return MAX_OFFSET_LENGTH + 1; /* For an error generation*/
+}
+
+static size_t dynamic_column_offset_bytes_named(size_t data_length)
+{
+ if (data_length < 0xfff) /* all 1 value is reserved */
+ return 2;
+ if (data_length < 0xfffff) /* all 1 value is reserved */
+ return 3;
+ if (data_length < 0xfffffff) /* all 1 value is reserved */
+ return 4;
+#if SIZEOF_SIZE_T > 4
+ if (data_length < 0xfffffffffull) /* all 1 value is reserved */
+#endif
+ return 5;
+ return MAX_OFFSET_LENGTH_NM + 1; /* For an error generation */
+}
+
+/**
+ Read offset and type information from index entry
+
+ @param type Where to put type info
+ @param offset Where to put offset info
+ @param place beginning of the type and offset
+ @param offset_size Size of offset field in bytes
+*/
+
+static my_bool type_and_offset_read_num(DYNAMIC_COLUMN_TYPE *type,
+ size_t *offset,
+ uchar *place, size_t offset_size)
+{
+ ulong UNINIT_VAR(val);
+ ulong UNINIT_VAR(lim);
+
+ DBUG_ASSERT(offset_size >= 1 && offset_size <= 4);
+
+ switch (offset_size) {
+ case 1:
+ val= (ulong)place[0];
+ lim= 0x1f;
+ break;
+ case 2:
+ val= uint2korr(place);
+ lim= 0x1fff;
+ break;
+ case 3:
+ val= uint3korr(place);
+ lim= 0x1fffff;
+ break;
+ case 4:
+ val= uint4korr(place);
+ lim= 0x1fffffff;
+ break;
+ default:
+ DBUG_ASSERT(0); /* impossible */
+ return 1;
+ }
+ *type= (val & 0x7) + 1;
+ *offset= val >> 3;
+ return (*offset >= lim);
+}
+
+static my_bool type_and_offset_read_named(DYNAMIC_COLUMN_TYPE *type,
+ size_t *offset,
+ uchar *place, size_t offset_size)
+{
+ ulonglong UNINIT_VAR(val);
+ ulonglong UNINIT_VAR(lim);
+ DBUG_ASSERT(offset_size >= 2 && offset_size <= 5);
+
+ switch (offset_size) {
+ case 2:
+ val= uint2korr(place);
+ lim= 0xfff;
+ break;
+ case 3:
+ val= uint3korr(place);
+ lim= 0xfffff;
+ break;
+ case 4:
+ val= uint4korr(place);
+ lim= 0xfffffff;
+ break;
+ case 5:
+ val= uint5korr(place);
+ lim= 0xfffffffffull;
+ break;
+ case 1:
+ default:
+ DBUG_ASSERT(0); /* impossible */
+ return 1;
+ }
+ *type= (val & 0xf) + 1;
+ *offset= (size_t)(val >> 4);
+ return (*offset >= lim);
+}
+
+/**
+ Format descriptor, contain constants and function references for
+ format processing
+*/
+
+struct st_service_funcs
+{
+ /* size of fixed header */
+ uint fixed_hdr;
+ /* size of fixed part of header entry */
+ uint fixed_hdr_entry;
+
+ /*size of array element which stores keys */
+ uint key_size_in_array;
+
+ /* Maximum data offset size in bytes */
+ size_t max_offset_size;
+
+ size_t (*name_size)
+ (void *, uint);
+ int (*column_sort)
+ (const void *a, const void *b);
+ my_bool (*check_limit)
+ (const void *val);
+ void (*set_fixed_hdr)
+ (DYNAMIC_COLUMN *str, DYN_HEADER *hdr);
+ my_bool (*put_header_entry)(DYN_HEADER *hdr,
+ void *column_key,
+ DYNAMIC_COLUMN_VALUE *value,
+ size_t offset);
+ int (*plan_sort)(const void *a, const void *b);
+ size_t (*dynamic_column_offset_bytes)(size_t data_length);
+ my_bool (*type_and_offset_read)(DYNAMIC_COLUMN_TYPE *type,
+ size_t *offset,
+ uchar *place, size_t offset_size);
+
+};
+
+
+/**
+ Actual our 2 format descriptors
+*/
+
+static struct st_service_funcs fmt_data[2]=
+{
+ {
+ FIXED_HEADER_SIZE,
+ COLUMN_NUMBER_SIZE,
+ sizeof(uint),
+ MAX_OFFSET_LENGTH,
+ &name_size_num,
+ &column_sort_num,
+ &check_limit_num,
+ &set_fixed_header_num,
+ &put_header_entry_num,
+ &plan_sort_num,
+ &dynamic_column_offset_bytes_num,
+ &type_and_offset_read_num
+ },
+ {
+ FIXED_HEADER_SIZE_NM,
+ COLUMN_NAMEPTR_SIZE,
+ sizeof(LEX_STRING),
+ MAX_OFFSET_LENGTH_NM,
+ &name_size_named,
+ &column_sort_named,
+ &check_limit_named,
+ &set_fixed_header_named,
+ &put_header_entry_named,
+ &plan_sort_named,
+ &dynamic_column_offset_bytes_named,
+ &type_and_offset_read_named
+ }
+};
+
+
+/**
+ Read dynamic column record header and fill the descriptor
+
+ @param hdr dynamic columns record descriptor to fill
+ @param str dynamic columns record
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+init_read_hdr(DYN_HEADER *hdr, DYNAMIC_COLUMN *str)
+{
+ if (read_fixed_header(hdr, str))
+ return ER_DYNCOL_FORMAT;
+ hdr->header= (uchar*)str->str + fmt_data[hdr->format].fixed_hdr;
+ calc_param(&hdr->entry_size, &hdr->header_size,
+ fmt_data[hdr->format].fixed_hdr_entry, hdr->offset_size,
+ hdr->column_count);
+ hdr->nmpool= hdr->header + hdr->header_size;
+ hdr->dtpool= hdr->nmpool + hdr->nmpool_size;
+ hdr->data_size= str->length - fmt_data[hdr->format].fixed_hdr -
+ hdr->header_size - hdr->nmpool_size;
+ hdr->data_end= (uchar*)str->str + str->length;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Initialize dynamic column string with (make it empty but correct format)
+
+ @param str The string to initialize
+ @param size Amount of preallocated memory for the string.
+
+ @retval FALSE OK
+ @retval TRUE error
+*/
+
+static my_bool dynamic_column_init_named(DYNAMIC_COLUMN *str, size_t size)
+{
+ DBUG_ASSERT(size != 0);
+
+ /*
+ Make string with no fields (empty header)
+ - First \0 is flags
+ - other 2 \0 is number of fields
+ */
+ if (ma_init_dynamic_string(str, NULL, size, DYNCOL_SYZERESERVE))
+ return TRUE;
+ return FALSE;
+}
+
+
+/**
+ Calculate how many bytes needed to store val as variable length integer
+ where first bit indicate continuation of the sequence.
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+static size_t dynamic_column_var_uint_bytes(ulonglong val)
+{
+ size_t len= 0;
+ do
+ {
+ len++;
+ val>>= 7;
+ } while (val);
+ return len;
+}
+
+
+/**
+ Stores variable length unsigned integer value to a string
+
+ @param str The string where to append the value
+ @param val The value to put in the string
+
+ @return ER_DYNCOL_* return code
+
+ @notes
+ This is used to store a number together with other data in the same
+ object. (Like decimals, length of string etc)
+ (As we don't know the length of this object, we can't store 0 in 0 bytes)
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_var_uint_store(DYNAMIC_COLUMN *str, ulonglong val)
+{
+ if (ma_dynstr_realloc(str, 10)) /* max what we can use */
+ return ER_DYNCOL_RESOURCE;
+
+ do
+ {
+ ulonglong rest= val >> 7;
+ str->str[str->length++]= ((val & 0x7f) | (rest ? 0x80 : 0x00));
+ val= rest;
+ } while (val);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Reads variable length unsigned integer value from a string
+
+ @param data The string from which the int should be read
+ @param data_length Max length of data
+ @param len Where to put length of the string read in bytes
+
+ @return value of the unsigned integer read from the string
+
+ In case of error, *len is set to 0
+*/
+
+static ulonglong
+dynamic_column_var_uint_get(uchar *data, size_t data_length,
+ size_t *len)
+{
+ ulonglong val= 0;
+ uint length;
+ uchar *end= data + data_length;
+
+ for (length=0; data < end ; data++)
+ {
+ val+= (((ulonglong)((*data) & 0x7f)) << (length * 7));
+ length++;
+ if (!((*data) & 0x80))
+ {
+ /* End of data */
+ *len= length;
+ return val;
+ }
+ }
+ /* Something was wrong with data */
+ *len= 0; /* Mark error */
+ return 0;
+}
+
+
+/**
+ Calculate how many bytes needed to store val as unsigned.
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes (0-8)
+*/
+
+static size_t dynamic_column_uint_bytes(ulonglong val)
+{
+ size_t len;
+
+ for (len= 0; val ; val>>= 8, len++)
+ ;
+ return len;
+}
+
+
+/**
+ Append the string with given unsigned int value.
+
+ @param str The string where to put the value
+ @param val The value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_uint_store(DYNAMIC_COLUMN *str, ulonglong val)
+{
+ if (ma_dynstr_realloc(str, 8)) /* max what we can use */
+ return ER_DYNCOL_RESOURCE;
+
+ for (; val; val>>= 8)
+ str->str[str->length++]= (char) (val & 0xff);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read unsigned int value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_uint_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ ulonglong value= 0;
+ size_t i;
+
+ for (i= 0; i < length; i++)
+ value+= ((ulonglong)data[i]) << (i*8);
+
+ store_it_here->x.ulong_value= value;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Calculate how many bytes needed to store val as signed in following encoding:
+ 0 -> 0
+ -1 -> 1
+ 1 -> 2
+ -2 -> 3
+ 2 -> 4
+ ...
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+static size_t dynamic_column_sint_bytes(longlong val)
+{
+ return dynamic_column_uint_bytes((val << 1) ^
+ (val < 0 ? 0xffffffffffffffffull : 0));
+}
+
+
+/**
+ Append the string with given signed int value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_sint_store(DYNAMIC_COLUMN *str, longlong val)
+{
+ return dynamic_column_uint_store(str,
+ (val << 1) ^
+ (val < 0 ? 0xffffffffffffffffULL : 0));
+}
+
+
+/**
+ Read signed int value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_sint_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ ulonglong val;
+ dynamic_column_uint_read(store_it_here, data, length);
+ val= store_it_here->x.ulong_value;
+ if (val & 1)
+ val= (val >> 1) ^ 0xffffffffffffffffULL;
+ else
+ val>>= 1;
+ store_it_here->x.long_value= (longlong) val;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Calculate how many bytes needed to store the value.
+
+ @param value The value for which we are calculating length
+
+ @return
+ Error: (size_t) ~0
+ ok number of bytes
+*/
+
+static size_t
+dynamic_column_value_len(DYNAMIC_COLUMN_VALUE *value,
+ enum enum_dyncol_format format)
+{
+ switch (value->type) {
+ case DYN_COL_NULL:
+ return 0;
+ case DYN_COL_INT:
+ return dynamic_column_sint_bytes(value->x.long_value);
+ case DYN_COL_UINT:
+ return dynamic_column_uint_bytes(value->x.ulong_value);
+ case DYN_COL_DOUBLE:
+ return 8;
+ case DYN_COL_STRING:
+#ifdef LIBMARIADB
+ return (dynamic_column_var_uint_bytes(value->x.string.charset->nr) +
+ value->x.string.value.length);
+#else
+ return (dynamic_column_var_uint_bytes(value->x.string.charset->number) +
+ value->x.string.value.length);
+#endif
+#ifndef LIBMARIADB
+ case DYN_COL_DECIMAL:
+ {
+ int precision= value->x.decimal.value.intg + value->x.decimal.value.frac;
+ int scale= value->x.decimal.value.frac;
+
+ if (precision == 0 || decimal_is_zero(&value->x.decimal.value))
+ {
+ /* This is here to simplify dynamic_column_decimal_store() */
+ value->x.decimal.value.intg= value->x.decimal.value.frac= 0;
+ return 0;
+ }
+ /*
+ Check if legal decimal; This is needed to not get an assert in
+ decimal_bin_size(). However this should be impossible as all
+ decimals entered here should be valid and we have the special check
+ above to handle the unlikely but possible case that decimal.value.intg
+ and decimal.frac is 0.
+ */
+ if (scale < 0 || precision <= 0)
+ {
+ DBUG_ASSERT(0); /* Impossible */
+ return (size_t) ~0;
+ }
+ return (dynamic_column_var_uint_bytes(value->x.decimal.value.intg) +
+ dynamic_column_var_uint_bytes(value->x.decimal.value.frac) +
+ decimal_bin_size(precision, scale));
+ }
+#endif
+ case DYN_COL_DATETIME:
+ if (format == dyncol_fmt_num || value->x.time_value.second_part)
+ /* date+time in bits: 14 + 4 + 5 + 10 + 6 + 6 + 20 + 1 66bits ~= 9 bytes*/
+ return 9;
+ else
+ return 6;
+ case DYN_COL_DATE:
+ /* date in dits: 14 + 4 + 5 = 23bits ~= 3bytes*/
+ return 3;
+ case DYN_COL_TIME:
+ if (format == dyncol_fmt_num || value->x.time_value.second_part)
+ /* time in bits: 10 + 6 + 6 + 20 + 1 = 43bits ~= 6bytes*/
+ return 6;
+ else
+ return 3;
+ case DYN_COL_DYNCOL:
+ return value->x.string.value.length;
+ default:
+ break;
+ }
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
+/**
+ Append double value to a string
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_double_store(DYNAMIC_COLUMN *str, double val)
+{
+ if (ma_dynstr_realloc(str, 8))
+ return ER_DYNCOL_RESOURCE;
+ float8store(str->str + str->length, val);
+ str->length+= 8;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read double value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_double_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ if (length != 8)
+ return ER_DYNCOL_FORMAT;
+ float8get(store_it_here->x.double_value, data);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Append the string with given string value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_string_store(DYNAMIC_COLUMN *str, LEX_STRING *string,
+ MARIADB_CHARSET_INFO *charset)
+{
+ enum enum_dyncol_func_result rc;
+#ifdef LIBMARIADB
+ if ((rc= dynamic_column_var_uint_store(str, charset->nr)))
+#else
+ if ((rc= dynamic_column_var_uint_store(str, charset->number)))
+#endif
+ return rc;
+ if (ma_dynstr_append_mem(str, string->str, string->length))
+ return ER_DYNCOL_RESOURCE;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Append the string with given string value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_dyncol_store(DYNAMIC_COLUMN *str, LEX_STRING *string)
+{
+ if (ma_dynstr_append_mem(str, string->str, string->length))
+ return ER_DYNCOL_RESOURCE;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Read string value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_string_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ size_t len;
+ uint charset_nr= (uint)dynamic_column_var_uint_get(data, length, &len);
+ if (len == 0) /* Wrong packed number */
+ return ER_DYNCOL_FORMAT;
+#ifndef LIBMARIADB
+ store_it_here->x.string.charset= get_charset_by_nr(charset_nr);
+#else
+ store_it_here->x.string.charset= mariadb_get_charset_by_nr(charset_nr);
+#endif
+ if (store_it_here->x.string.charset == NULL)
+ return ER_DYNCOL_UNKNOWN_CHARSET;
+ data+= len;
+ store_it_here->x.string.value.length= (length-= len);
+ store_it_here->x.string.value.str= (char*) data;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Read Dynamic columns packet string value of given length
+ from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_dyncol_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ store_it_here->x.string.charset= ma_charset_bin;
+ store_it_here->x.string.value.length= length;
+ store_it_here->x.string.value.str= (char*) data;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Append the string with given decimal value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+#ifndef LIBMARIADB
+static enum enum_dyncol_func_result
+dynamic_column_decimal_store(DYNAMIC_COLUMN *str,
+ decimal_t *value)
+{
+ uint bin_size;
+ int precision= value->intg + value->frac;
+
+ /* Store decimal zero as empty string */
+ if (precision == 0)
+ return ER_DYNCOL_OK;
+
+ bin_size= decimal_bin_size(precision, value->frac);
+ if (ma_dynstr_realloc(str, bin_size + 20))
+ return ER_DYNCOL_RESOURCE;
+
+ /* The following can't fail as memory is already allocated */
+ (void) dynamic_column_var_uint_store(str, value->intg);
+ (void) dynamic_column_var_uint_store(str, value->frac);
+
+ decimal2bin(value, (uchar *) str->str + str->length,
+ precision, value->frac);
+ str->length+= bin_size;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Prepare the value to be used as decimal.
+
+ @param value The value structure which should be setup.
+*/
+
+void mariadb_dyncol_prepare_decimal(DYNAMIC_COLUMN_VALUE *value)
+{
+ value->x.decimal.value.buf= value->x.decimal.buffer;
+ value->x.decimal.value.len= DECIMAL_BUFF_LENGTH;
+ /* just to be safe */
+ value->type= DYN_COL_DECIMAL;
+ decimal_make_zero(&value->x.decimal.value);
+}
+
+void dynamic_column_prepare_decimal(DYNAMIC_COLUMN_VALUE *value)
+{
+ mariadb_dyncol_prepare_decimal(value);
+}
+
+
+
+/**
+ Read decimal value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_decimal_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ size_t intg_len, frac_len;
+ int intg, frac, precision, scale;
+
+ dynamic_column_prepare_decimal(store_it_here);
+ /* Decimals 0.0 is stored as a zero length string */
+ if (length == 0)
+ return ER_DYNCOL_OK; /* value contains zero */
+
+ intg= (int)dynamic_column_var_uint_get(data, length, &intg_len);
+ data+= intg_len;
+ frac= (int)dynamic_column_var_uint_get(data, length - intg_len, &frac_len);
+ data+= frac_len;
+
+ /* Check the size of data is correct */
+ precision= intg + frac;
+ scale= frac;
+ if (scale < 0 || precision <= 0 || scale > precision ||
+ (length - intg_len - frac_len) >
+ (size_t) (DECIMAL_BUFF_LENGTH*sizeof(decimal_digit_t)) ||
+ decimal_bin_size(intg + frac, frac) !=
+ (int) (length - intg_len - frac_len))
+ return ER_DYNCOL_FORMAT;
+
+ if (bin2decimal(data, &store_it_here->x.decimal.value, precision, scale) !=
+ E_DEC_OK)
+ return ER_DYNCOL_FORMAT;
+ return ER_DYNCOL_OK;
+}
+#endif
+
+/**
+ Append the string with given datetime value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_date_time_store(DYNAMIC_COLUMN *str, MYSQL_TIME *value,
+ enum enum_dyncol_format format)
+{
+ enum enum_dyncol_func_result rc;
+ /*
+ 0<----year----><mn><day>00000!<-hours--><min-><sec-><---microseconds--->
+ 12345678901234123412345 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456><123456><123456><123456>
+ */
+ if ((rc= dynamic_column_date_store(str, value)) ||
+ (rc= dynamic_column_time_store(str, value, format)))
+ return rc;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read datetime value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_date_time_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ enum enum_dyncol_func_result rc= ER_DYNCOL_FORMAT;
+ /*
+ 0<----year----><mn><day>00000!<-hours--><min-><sec-><---microseconds--->
+ 12345678901234123412345 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456><123456><123456><123456>
+ */
+ if (length != 9 && length != 6)
+ goto err;
+ store_it_here->x.time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
+ if ((rc= dynamic_column_date_read_internal(store_it_here, data, 3)) ||
+ (rc= dynamic_column_time_read_internal(store_it_here, data + 3,
+ length - 3)))
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->x.time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return rc;
+}
+
+
+/**
+ Append the string with given time value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_time_store(DYNAMIC_COLUMN *str, MYSQL_TIME *value,
+ enum enum_dyncol_format format)
+{
+ uchar *buf;
+ if (ma_dynstr_realloc(str, 6))
+ return ER_DYNCOL_RESOURCE;
+
+ buf= ((uchar *)str->str) + str->length;
+
+ if (value->time_type == MYSQL_TIMESTAMP_NONE ||
+ value->time_type == MYSQL_TIMESTAMP_ERROR ||
+ value->time_type == MYSQL_TIMESTAMP_DATE)
+ {
+ value->neg= 0;
+ value->second_part= 0;
+ value->hour= 0;
+ value->minute= 0;
+ value->second= 0;
+ }
+ DBUG_ASSERT(value->hour <= 838);
+ DBUG_ASSERT(value->minute <= 59);
+ DBUG_ASSERT(value->second <= 59);
+ DBUG_ASSERT(value->second_part <= 999999);
+ if (format == dyncol_fmt_num || value->second_part)
+ {
+ /*
+ 00000!<-hours--><min-><sec-><---microseconds--->
+ 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456>
+ */
+ buf[0]= (value->second_part & 0xff);
+ buf[1]= ((value->second_part & 0xff00) >> 8);
+ buf[2]= (uchar)(((value->second & 0xf) << 4) |
+ ((value->second_part & 0xf0000) >> 16));
+ buf[3]= ((value->minute << 2) | ((value->second & 0x30) >> 4));
+ buf[4]= (value->hour & 0xff);
+ buf[5]= ((value->neg ? 0x4 : 0) | (value->hour >> 8));
+ str->length+= 6;
+ }
+ else
+ {
+ /*
+ !<-hours--><min-><sec->
+ 11234567890123456123456
+ <123456><123456><123456>
+ */
+ buf[0]= (value->second) | ((value->minute & 0x3) << 6);
+ buf[1]= (value->minute >> 2) | ((value->hour & 0xf) << 4);
+ buf[2]= (value->hour >> 4) | (value->neg ? 0x80 : 0);
+ str->length+= 3;
+ }
+
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read time value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_time_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ store_it_here->x.time_value.year= store_it_here->x.time_value.month=
+ store_it_here->x.time_value.day= 0;
+ store_it_here->x.time_value.time_type= MYSQL_TIMESTAMP_TIME;
+ return dynamic_column_time_read_internal(store_it_here, data, length);
+}
+
+/**
+ Internal function for reading time part from the string.
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_time_read_internal(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ if (length != 6 && length != 3)
+ goto err;
+ if (length == 6)
+ {
+ /*
+ 00000!<-hours--><min-><sec-><---microseconds--->
+ 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456>
+ */
+ store_it_here->x.time_value.second_part= (data[0] |
+ (data[1] << 8) |
+ ((data[2] & 0xf) << 16));
+ store_it_here->x.time_value.second= ((data[2] >> 4) |
+ ((data[3] & 0x3) << 4));
+ store_it_here->x.time_value.minute= (data[3] >> 2);
+ store_it_here->x.time_value.hour= (((((uint)data[5]) & 0x3 ) << 8) | data[4]);
+ store_it_here->x.time_value.neg= ((data[5] & 0x4) ? 1 : 0);
+ }
+ else
+ {
+ /*
+ !<-hours--><min-><sec->
+ 11234567890123456123456
+ <123456><123456><123456>
+ */
+ store_it_here->x.time_value.second_part= 0;
+ store_it_here->x.time_value.second= (data[0] & 0x3f);
+ store_it_here->x.time_value.minute= (data[0] >> 6) | ((data[1] & 0xf) << 2);
+ store_it_here->x.time_value.hour= (data[1] >> 4) | ((data[2] & 0x3f) << 4);
+ store_it_here->x.time_value.neg= ((data[2] & 0x80) ? 1 : 0);
+ }
+ if (store_it_here->x.time_value.second > 59 ||
+ store_it_here->x.time_value.minute > 59 ||
+ store_it_here->x.time_value.hour > 838 ||
+ store_it_here->x.time_value.second_part > 999999)
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->x.time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return ER_DYNCOL_FORMAT;
+}
+
+
+/**
+ Append the string with given date value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_date_store(DYNAMIC_COLUMN *str, MYSQL_TIME *value)
+{
+ uchar *buf;
+ if (ma_dynstr_realloc(str, 3))
+ return ER_DYNCOL_RESOURCE;
+
+ buf= ((uchar *)str->str) + str->length;
+ if (value->time_type == MYSQL_TIMESTAMP_NONE ||
+ value->time_type == MYSQL_TIMESTAMP_ERROR ||
+ value->time_type == MYSQL_TIMESTAMP_TIME)
+ value->year= value->month= value->day = 0;
+ DBUG_ASSERT(value->year <= 9999);
+ DBUG_ASSERT(value->month <= 12);
+ DBUG_ASSERT(value->day <= 31);
+ /*
+ 0<----year----><mn><day>
+ 012345678901234123412345
+ <123456><123456><123456>
+ */
+ buf[0]= (value->day |
+ ((value->month & 0x7) << 5));
+ buf[1]= ((value->month >> 3) | ((value->year & 0x7F) << 1));
+ buf[2]= (value->year >> 7);
+ str->length+= 3;
+ return ER_DYNCOL_OK;
+}
+
+
+
+/**
+ Read date value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_date_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length)
+{
+ store_it_here->x.time_value.neg= 0;
+ store_it_here->x.time_value.second_part= 0;
+ store_it_here->x.time_value.hour= 0;
+ store_it_here->x.time_value.minute= 0;
+ store_it_here->x.time_value.second= 0;
+ store_it_here->x.time_value.time_type= MYSQL_TIMESTAMP_DATE;
+ return dynamic_column_date_read_internal(store_it_here, data, length);
+}
+
+/**
+ Internal function for reading date part from the string.
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_date_read_internal(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ if (length != 3)
+ goto err;
+ /*
+ 0<----year----><mn><day>
+ 12345678901234123412345
+ <123456><123456><123456>
+ */
+ store_it_here->x.time_value.day= (data[0] & 0x1f);
+ store_it_here->x.time_value.month= (((data[1] & 0x1) << 3) |
+ (data[0] >> 5));
+ store_it_here->x.time_value.year= ((((uint)data[2]) << 7) |
+ (data[1] >> 1));
+ if (store_it_here->x.time_value.day > 31 ||
+ store_it_here->x.time_value.month > 12 ||
+ store_it_here->x.time_value.year > 9999)
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->x.time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return ER_DYNCOL_FORMAT;
+}
+
+
+/**
+ Append the string with given value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+data_store(DYNAMIC_COLUMN *str, DYNAMIC_COLUMN_VALUE *value,
+ enum enum_dyncol_format format)
+{
+ switch (value->type) {
+ case DYN_COL_INT:
+ return dynamic_column_sint_store(str, value->x.long_value);
+ case DYN_COL_UINT:
+ return dynamic_column_uint_store(str, value->x.ulong_value);
+ case DYN_COL_DOUBLE:
+ return dynamic_column_double_store(str, value->x.double_value);
+ case DYN_COL_STRING:
+ return dynamic_column_string_store(str, &value->x.string.value,
+ value->x.string.charset);
+#ifndef LIBMARIADB
+ case DYN_COL_DECIMAL:
+ return dynamic_column_decimal_store(str, &value->x.decimal.value);
+#endif
+ case DYN_COL_DATETIME:
+ /* date+time in bits: 14 + 4 + 5 + 5 + 6 + 6 40bits = 5 bytes */
+ return dynamic_column_date_time_store(str, &value->x.time_value, format);
+ case DYN_COL_DATE:
+ /* date in dits: 14 + 4 + 5 = 23bits ~= 3bytes*/
+ return dynamic_column_date_store(str, &value->x.time_value);
+ case DYN_COL_TIME:
+ /* time in bits: 5 + 6 + 6 = 17bits ~= 3bytes*/
+ return dynamic_column_time_store(str, &value->x.time_value, format);
+ case DYN_COL_DYNCOL:
+ return dynamic_column_dyncol_store(str, &value->x.string.value);
+ case DYN_COL_NULL:
+ break; /* Impossible */
+ default:
+ break;
+ }
+ DBUG_ASSERT(0);
+ return ER_DYNCOL_OK; /* Impossible */
+}
+
+
+/**
+ Write information to the fixed header
+
+ @param str String where to write the header
+ @param offset_size Size of offset field in bytes
+ @param column_count Number of columns
+*/
+
+static void set_fixed_header(DYNAMIC_COLUMN *str,
+ uint offset_size,
+ uint column_count)
+{
+ DBUG_ASSERT(column_count <= 0xffff);
+ DBUG_ASSERT(offset_size <= MAX_OFFSET_LENGTH);
+ str->str[0]= ((str->str[0] & ~DYNCOL_FLG_OFFSET) |
+ (offset_size - 1)); /* size of offset */
+ int2store(str->str + 1, column_count); /* columns number */
+ DBUG_ASSERT((str->str[0] & (~DYNCOL_FLG_KNOWN)) == 0);
+}
+
+/**
+ Adds columns into the empty string
+
+ @param str String where to write the data (the record)
+ @param hdr Dynamic columns record descriptor
+ @param column_count Number of columns in the arrays
+ @param column_keys Array of columns keys (uint or LEX_STRING)
+ @param values Array of columns values
+ @param new_str True if we need to allocate new string
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_new_column_store(DYNAMIC_COLUMN *str,
+ DYN_HEADER *hdr,
+ uint column_count,
+ void *column_keys,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_str)
+{
+ struct st_service_funcs *fmt= fmt_data + hdr->format;
+ void **columns_order;
+ uchar *element;
+ uint i;
+ enum enum_dyncol_func_result rc= ER_DYNCOL_RESOURCE;
+ size_t all_headers_size;
+
+ if (!(columns_order= malloc(sizeof(void*)*column_count)))
+ return ER_DYNCOL_RESOURCE;
+ if (new_str || str->str == 0)
+ {
+ if (column_count)
+ {
+ if (dynamic_column_init_named(str,
+ fmt->fixed_hdr +
+ hdr->header_size +
+ hdr->nmpool_size +
+ hdr->data_size +
+ DYNCOL_SYZERESERVE))
+ goto err;
+ }
+ else
+ {
+ dynamic_column_initialize(str);
+ }
+ }
+ else
+ {
+ str->length= 0;
+ if (ma_dynstr_realloc(str,
+ fmt->fixed_hdr +
+ hdr->header_size +
+ hdr->nmpool_size +
+ hdr->data_size +
+ DYNCOL_SYZERESERVE))
+ goto err;
+ }
+ if (!column_count)
+ {
+ free(columns_order);
+ return ER_DYNCOL_OK;
+ }
+
+ memset(str->str, 0, fmt->fixed_hdr);
+ str->length= fmt->fixed_hdr;
+
+ /* sort columns for the header */
+ for (i= 0, element= (uchar *) column_keys;
+ i < column_count;
+ i++, element+= fmt->key_size_in_array)
+ columns_order[i]= (void *)element;
+ qsort(columns_order, (size_t)column_count, sizeof(void*), fmt->column_sort);
+
+ /*
+ For now we don't allow creating two columns with the same number
+ at the time of create. This can be fixed later to just use the later
+ by comparing the pointers.
+ */
+ for (i= 0; i < column_count - 1; i++)
+ {
+ if ((*fmt->check_limit)(&columns_order[i]) ||
+ (*fmt->column_sort)(&columns_order[i], &columns_order[i + 1]) == 0)
+ {
+ rc= ER_DYNCOL_DATA;
+ goto err;
+ }
+ }
+ if ((*fmt->check_limit)(&columns_order[i]))
+ {
+ rc= ER_DYNCOL_DATA;
+ goto err;
+ }
+
+ (*fmt->set_fixed_hdr)(str, hdr);
+ /* reserve place for header and name pool */
+ str->length+= hdr->header_size + hdr->nmpool_size;
+
+ hdr->entry= hdr->header;
+ hdr->name= hdr->nmpool;
+ all_headers_size= fmt->fixed_hdr + hdr->header_size + hdr->nmpool_size;
+ for (i= 0; i < column_count; i++)
+ {
+ uint ord= (uint)(((uchar*)columns_order[i] - (uchar*)column_keys) /
+ fmt->key_size_in_array);
+ if (values[ord].type != DYN_COL_NULL)
+ {
+ /* Store header first in the str */
+ if ((*fmt->put_header_entry)(hdr, columns_order[i], values + ord,
+ str->length - all_headers_size))
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto err;
+ }
+
+ /* Store value in 'str + str->length' and increase str->length */
+ if ((rc= data_store(str, values + ord, hdr->format)))
+ goto err;
+ }
+ }
+ rc= ER_DYNCOL_OK;
+err:
+ free(columns_order);
+ return rc;
+}
+
+/**
+ Calculate size of header, name pool and data pool
+
+ @param hdr descriptor of dynamic column record
+ @param column_count number of elements in arrays
+ @param column_count Number of columns in the arrays
+ @param column_keys Array of columns keys (uint or LEX_STRING)
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+calc_var_sizes(DYN_HEADER *hdr,
+ uint column_count,
+ void *column_keys,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ struct st_service_funcs *fmt= fmt_data + hdr->format;
+ uint i;
+ hdr->nmpool_size= hdr->data_size= 0;
+ hdr->column_count= 0;
+ for (i= 0; i < column_count; i++)
+ {
+ if (values[i].type != DYN_COL_NULL)
+ {
+ size_t tmp;
+ hdr->column_count++;
+ hdr->data_size+= (tmp= dynamic_column_value_len(values + i,
+ hdr->format));
+ if (tmp == (size_t) ~0)
+ return ER_DYNCOL_DATA;
+ hdr->nmpool_size+= (*fmt->name_size)(column_keys, i);
+ }
+ }
+ /*
+ We can handle data up to 0x1fffffff (old format) and
+ 0xfffffffff (new format) bytes now.
+ */
+ if ((hdr->offset_size= fmt->dynamic_column_offset_bytes(hdr->data_size)) >=
+ fmt->max_offset_size)
+ return ER_DYNCOL_LIMIT;
+
+ /* header entry is column number or string pointer + offset & type */
+ hdr->entry_size= fmt->fixed_hdr_entry + hdr->offset_size;
+ hdr->header_size= hdr->column_count * hdr->entry_size;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Create packed string which contains given columns (internal multi format)
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_keys Array of columns keys (format dependent)
+ @param values Array of columns values
+ @param new_str True if we need allocate new string
+ @param string_keys keys are strings
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_create_many_internal_fmt(DYNAMIC_COLUMN *str,
+ uint column_count,
+ void *column_keys,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_str,
+ my_bool string_keys)
+{
+ DYN_HEADER header;
+ enum enum_dyncol_func_result rc;
+ memset(&header, 0, sizeof(header));
+ header.format= (string_keys ? 1 : 0);
+
+ if (new_str)
+ {
+ /* to make dynstr_free() working in case of errors */
+ memset(str, 0, sizeof(DYNAMIC_COLUMN));
+ }
+
+ if ((rc= calc_var_sizes(&header, column_count, column_keys, values)) < 0)
+ return rc;
+
+ return dynamic_new_column_store(str, &header,
+ column_count,
+ column_keys, values,
+ new_str);
+}
+
+
+/**
+ Create packed string which contains given columns
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+dynamic_column_create_many(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ return(dynamic_column_create_many_internal_fmt(str, column_count,
+ column_numbers, values,
+ TRUE, FALSE));
+}
+
+/**
+ Create packed string which contains given columns
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+ @param new_string True if we need allocate new string
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_create_many_num(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_string)
+{
+ return(dynamic_column_create_many_internal_fmt(str, column_count,
+ column_numbers, values,
+ new_string, FALSE));
+}
+
+/**
+ Create packed string which contains given columns
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_keys Array of columns keys
+ @param values Array of columns value
+ @param new_string True if we need allocate new string
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_create_many_named(DYNAMIC_COLUMN *str,
+ uint column_count,
+ LEX_STRING *column_keys,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_string)
+{
+ return(dynamic_column_create_many_internal_fmt(str, column_count,
+ column_keys, values,
+ new_string, TRUE));
+}
+
+/**
+ Create packed string which contains given column
+
+ @param str String where to write the data
+ @param column_number Column number
+ @param value The columns value
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+dynamic_column_create(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value)
+{
+ return(dynamic_column_create_many(str, 1, &column_nr, value));
+}
+
+
+/**
+ Calculate length of data between given two header entries
+
+ @param entry Pointer to the first entry
+ @param entry_next Pointer to the last entry
+ @param header_end Pointer to the header end
+ @param offset_size Size of offset field in bytes
+ @param last_offset Size of the data segment
+
+ @return number of bytes
+*/
+
+static size_t get_length_interval(uchar *entry, uchar *entry_next,
+ uchar *header_end, size_t offset_size,
+ size_t last_offset)
+{
+ size_t offset, offset_next;
+ DYNAMIC_COLUMN_TYPE type, type_next;
+ DBUG_ASSERT(entry < entry_next);
+
+ if (type_and_offset_read_num(&type, &offset, entry + COLUMN_NUMBER_SIZE,
+ offset_size))
+ return DYNCOL_OFFSET_ERROR;
+ if (entry_next >= header_end)
+ return (last_offset - offset);
+ if (type_and_offset_read_num(&type_next, &offset_next,
+ entry_next + COLUMN_NUMBER_SIZE, offset_size))
+ return DYNCOL_OFFSET_ERROR;
+ return (offset_next - offset);
+}
+
+
+/**
+ Calculate length of data between given hdr->entry and next_entry
+
+ @param hdr descriptor of dynamic column record
+ @param next_entry next header entry (can point just after last header
+ entry)
+
+ @return number of bytes
+*/
+
+static size_t hdr_interval_length(DYN_HEADER *hdr, uchar *next_entry)
+{
+ struct st_service_funcs *fmt= fmt_data + hdr->format;
+ size_t next_entry_offset;
+ DYNAMIC_COLUMN_TYPE next_entry_type;
+ DBUG_ASSERT(hdr->entry < next_entry);
+ DBUG_ASSERT(hdr->entry >= hdr->header);
+ DBUG_ASSERT(next_entry <= hdr->header + hdr->header_size);
+
+ if ((*fmt->type_and_offset_read)(&hdr->type, &hdr->offset,
+ hdr->entry + fmt->fixed_hdr_entry,
+ hdr->offset_size))
+ return DYNCOL_OFFSET_ERROR;
+ if (next_entry == hdr->header + hdr->header_size)
+ return hdr->data_size - hdr->offset;
+ if ((*fmt->type_and_offset_read)(&next_entry_type, &next_entry_offset,
+ next_entry + fmt->fixed_hdr_entry,
+ hdr->offset_size))
+ return DYNCOL_OFFSET_ERROR;
+ return (next_entry_offset - hdr->offset);
+}
+
+
+/**
+ Comparator function for references to header entries for qsort
+*/
+
+static int header_compar_num(const void *a, const void *b)
+{
+ uint va= uint2korr((uchar*)a), vb= uint2korr((uchar*)b);
+ return (va > vb ? 1 : (va < vb ? -1 : 0));
+}
+
+
+/**
+ Find entry in the numeric format header by the column number
+
+ @param hdr descriptor of dynamic column record
+ @param key number to find
+
+ @return pointer to the entry or NULL
+*/
+
+static uchar *find_entry_num(DYN_HEADER *hdr, uint key)
+{
+ uchar header_entry[2+4];
+ DBUG_ASSERT(hdr->format == dyncol_fmt_num);
+ int2store(header_entry, key);
+ return hdr->entry= bsearch(header_entry, hdr->header,
+ (size_t)hdr->column_count,
+ hdr->entry_size, &header_compar_num);
+}
+
+
+/**
+ Read name from header entry
+
+ @param hdr descriptor of dynamic column record
+ @param entry pointer to the header entry
+ @param name where to put name
+
+ @return 0 ok
+ @return 1 error in data
+*/
+
+static my_bool read_name(DYN_HEADER *hdr, uchar *entry, LEX_STRING *name)
+{
+ size_t nmoffset= uint2korr(entry);
+ uchar *next_entry= entry + hdr->entry_size;
+
+ if (nmoffset > hdr->nmpool_size)
+ return 1;
+
+ name->str= (char *)hdr->nmpool + nmoffset;
+ if (next_entry == hdr->header + hdr->header_size)
+ name->length= hdr->nmpool_size - nmoffset;
+ else
+ {
+ size_t next_nmoffset= uint2korr(next_entry);
+ if (next_nmoffset > hdr->nmpool_size)
+ return 1;
+ name->length= next_nmoffset - nmoffset;
+ }
+ return 0;
+}
+
+
+/**
+ Find entry in the names format header by the column number
+
+ @param hdr descriptor of dynamic column record
+ @param key name to find
+
+ @return pointer to the entry or NULL
+*/
+static uchar *find_entry_named(DYN_HEADER *hdr, LEX_STRING *key)
+{
+ uchar *min= hdr->header;
+ uchar *max= hdr->header + (hdr->column_count - 1) * hdr->entry_size;
+ uchar *mid;
+ DBUG_ASSERT(hdr->format == dyncol_fmt_str);
+ DBUG_ASSERT(hdr->nmpool != NULL);
+ while (max >= min)
+ {
+ LEX_STRING name;
+ int cmp;
+ mid= hdr->header + ((min - hdr->header) +
+ (max - hdr->header)) /
+ 2 /
+ hdr->entry_size * hdr->entry_size;
+ if (read_name(hdr, mid, &name))
+ return NULL;
+ cmp= mariadb_dyncol_column_cmp_named(&name, key);
+ if (cmp < 0)
+ min= mid + hdr->entry_size;
+ else if (cmp > 0)
+ max= mid - hdr->entry_size;
+ else
+ return mid;
+ }
+ return NULL;
+}
+
+
+/**
+ Write number in the buffer (backward direction - starts from the buffer end)
+
+ @return pointer on the number beginning
+*/
+
+static char *backwritenum(char *chr, uint numkey)
+{
+ if (numkey == 0)
+ *(--chr)= '0';
+ else
+ while (numkey > 0)
+ {
+ *(--chr)= '0' + numkey % 10;
+ numkey/= 10;
+ }
+ return chr;
+}
+
+
+/**
+ Find column and fill information about it
+
+ @param hdr descriptor of dynamic column record
+ @param numkey Number of the column to fetch (if strkey is NULL)
+ @param strkey Name of the column to fetch (or NULL)
+
+ @return 0 ok
+ @return 1 error in data
+*/
+
+static my_bool
+find_column(DYN_HEADER *hdr, uint numkey, LEX_STRING *strkey)
+{
+ LEX_STRING nmkey;
+ char nmkeybuff[DYNCOL_NUM_CHAR]; /* to fit max 2 bytes number */
+ DBUG_ASSERT(hdr->header != NULL);
+
+ if (hdr->header + hdr->header_size > hdr->data_end)
+ return TRUE;
+
+ /* fix key */
+ if (hdr->format == dyncol_fmt_num && strkey != NULL)
+ {
+ char *end;
+ numkey= (uint) strtoul(strkey->str, &end, 10);
+ if (end != strkey->str + strkey->length)
+ {
+ /* we can't find non-numeric key among numeric ones */
+ hdr->type= DYN_COL_NULL;
+ return 0;
+ }
+ }
+ else if (hdr->format == dyncol_fmt_str && strkey == NULL)
+ {
+ nmkey.str= backwritenum(nmkeybuff + sizeof(nmkeybuff), numkey);
+ nmkey.length= (nmkeybuff + sizeof(nmkeybuff)) - nmkey.str;
+ strkey= &nmkey;
+ }
+ if (hdr->format == dyncol_fmt_num)
+ hdr->entry= find_entry_num(hdr, numkey);
+ else
+ hdr->entry= find_entry_named(hdr, strkey);
+
+ if (!hdr->entry)
+ {
+ /* Column not found */
+ hdr->type= DYN_COL_NULL;
+ return 0;
+ }
+ hdr->length= hdr_interval_length(hdr, hdr->entry + hdr->entry_size);
+ hdr->data= hdr->dtpool + hdr->offset;
+ /*
+ Check that the found data is within the ranges. This can happen if
+ we get data with wrong offsets.
+ */
+ if (hdr->length == DYNCOL_OFFSET_ERROR ||
+ hdr->length > INT_MAX || hdr->offset > hdr->data_size)
+ return 1;
+
+ return 0;
+}
+
+
+/**
+ Read and check the header of the dynamic string
+
+ @param hdr descriptor of dynamic column record
+ @param str Dynamic string
+
+ @retval FALSE OK
+ @retval TRUE error
+
+ Note
+ We don't check for str->length == 0 as all code that calls this
+ already have handled this case.
+*/
+
+static inline my_bool read_fixed_header(DYN_HEADER *hdr,
+ DYNAMIC_COLUMN *str)
+{
+ DBUG_ASSERT(str != NULL && str->length != 0);
+ if ((str->length < 1) ||
+ (str->str[0] & (~DYNCOL_FLG_KNOWN)))
+ return 1;
+ hdr->format= ((str->str[0] & DYNCOL_FLG_NAMES) ?
+ dyncol_fmt_str:
+ dyncol_fmt_num);
+ if ((str->length < fmt_data[hdr->format].fixed_hdr))
+ return 1; /* Wrong header */
+ hdr->offset_size= (str->str[0] & DYNCOL_FLG_OFFSET) + 1 +
+ (hdr->format == dyncol_fmt_str ? 1 : 0);
+ hdr->column_count= uint2korr(str->str + 1);
+ if (hdr->format == dyncol_fmt_str)
+ hdr->nmpool_size= uint2korr(str->str + 3); // only 2 bytes supported for now
+ else
+ hdr->nmpool_size= 0;
+ return 0;
+}
+
+
+/**
+ Get dynamic column value by column number
+
+ @param str The packed string to extract the column
+ @param column_nr Number of column to fetch
+ @param store_it_here Where to store the extracted value
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+dynamic_column_get(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here)
+{
+ return dynamic_column_get_internal(str, store_it_here, column_nr, NULL);
+}
+
+enum enum_dyncol_func_result
+mariadb_dyncol_get_num(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here)
+{
+ return dynamic_column_get_internal(str, store_it_here, column_nr, NULL);
+}
+
+
+/**
+ Get dynamic column value by name
+
+ @param str The packed string to extract the column
+ @param name Name of column to fetch
+ @param store_it_here Where to store the extracted value
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_get_named(DYNAMIC_COLUMN *str, LEX_STRING *name,
+ DYNAMIC_COLUMN_VALUE *store_it_here)
+{
+ DBUG_ASSERT(name != NULL);
+ return dynamic_column_get_internal(str, store_it_here, 0, name);
+}
+
+
+static enum enum_dyncol_func_result
+dynamic_column_get_value(DYN_HEADER *hdr, DYNAMIC_COLUMN_VALUE *store_it_here)
+{
+ static enum enum_dyncol_func_result rc;
+ switch ((store_it_here->type= hdr->type)) {
+ case DYN_COL_INT:
+ rc= dynamic_column_sint_read(store_it_here, hdr->data, hdr->length);
+ break;
+ case DYN_COL_UINT:
+ rc= dynamic_column_uint_read(store_it_here, hdr->data, hdr->length);
+ break;
+ case DYN_COL_DOUBLE:
+ rc= dynamic_column_double_read(store_it_here, hdr->data, hdr->length);
+ break;
+ case DYN_COL_STRING:
+ rc= dynamic_column_string_read(store_it_here, hdr->data, hdr->length);
+ break;
+#ifndef LIBMARIADB
+ case DYN_COL_DECIMAL:
+ rc= dynamic_column_decimal_read(store_it_here, hdr->data, hdr->length);
+ break;
+#endif
+ case DYN_COL_DATETIME:
+ rc= dynamic_column_date_time_read(store_it_here, hdr->data,
+ hdr->length);
+ break;
+ case DYN_COL_DATE:
+ rc= dynamic_column_date_read(store_it_here, hdr->data, hdr->length);
+ break;
+ case DYN_COL_TIME:
+ rc= dynamic_column_time_read(store_it_here, hdr->data, hdr->length);
+ break;
+ case DYN_COL_NULL:
+ rc= ER_DYNCOL_OK;
+ break;
+ case DYN_COL_DYNCOL:
+ rc= dynamic_column_dyncol_read(store_it_here, hdr->data, hdr->length);
+ break;
+ default:
+ rc= ER_DYNCOL_FORMAT;
+ store_it_here->type= DYN_COL_NULL;
+ break;
+ }
+ return rc;
+}
+
+/**
+ Get dynamic column value by number or name
+
+ @param str The packed string to extract the column
+ @param store_it_here Where to store the extracted value
+ @param numkey Number of the column to fetch (if strkey is NULL)
+ @param strkey Name of the column to fetch (or NULL)
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_get_internal(DYNAMIC_COLUMN *str,
+ DYNAMIC_COLUMN_VALUE *store_it_here,
+ uint num_key, LEX_STRING *str_key)
+{
+ DYN_HEADER header;
+ enum enum_dyncol_func_result rc= ER_DYNCOL_FORMAT;
+ memset(&header, 0, sizeof(header));
+
+ if (str->length == 0)
+ goto null;
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ goto err;
+
+ if (header.column_count == 0)
+ goto null;
+
+ if (find_column(&header, num_key, str_key))
+ goto err;
+
+ rc= dynamic_column_get_value(&header, store_it_here);
+ return rc;
+
+null:
+ rc= ER_DYNCOL_OK;
+err:
+ store_it_here->type= DYN_COL_NULL;
+ return rc;
+}
+
+
+/**
+ Check existence of the column in the packed string (by number)
+
+ @param str The packed string to check the column
+ @param column_nr Number of column to check
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_exists_num(DYNAMIC_COLUMN *str, uint column_nr)
+{
+ return dynamic_column_exists_internal(str, column_nr, NULL);
+}
+
+/**
+ Check existence of the column in the packed string (by name)
+
+ @param str The packed string to check the column
+ @param name Name of column to check
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_exists_named(DYNAMIC_COLUMN *str, LEX_STRING *name)
+{
+ DBUG_ASSERT(name != NULL);
+ return dynamic_column_exists_internal(str, 0, name);
+}
+
+
+/**
+ Check existence of the column in the packed string (by name of number)
+
+ @param str The packed string to check the column
+ @param num_key Number of the column to fetch (if strkey is NULL)
+ @param str_key Name of the column to fetch (or NULL)
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_exists_internal(DYNAMIC_COLUMN *str, uint num_key,
+ LEX_STRING *str_key)
+{
+ DYN_HEADER header;
+ enum enum_dyncol_func_result rc;
+ memset(&header, 0, sizeof(header));
+
+ if (str->length == 0)
+ return ER_DYNCOL_NO; /* no columns */
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ return rc;
+
+ if (header.column_count == 0)
+ return ER_DYNCOL_NO; /* no columns */
+
+ if (find_column(&header, num_key, str_key))
+ return ER_DYNCOL_FORMAT;
+
+ return (header.type != DYN_COL_NULL ? ER_DYNCOL_YES : ER_DYNCOL_NO);
+}
+
+
+/**
+ List not-null columns in the packed string (only numeric format)
+
+ @param str The packed string
+ @param array_of_uint Where to put reference on created array
+
+ @return ER_DYNCOL_* return code
+*/
+enum enum_dyncol_func_result
+dynamic_column_list(DYNAMIC_COLUMN *str, DYNAMIC_ARRAY *array_of_uint)
+{
+ DYN_HEADER header;
+ uchar *read;
+ uint i;
+ enum enum_dyncol_func_result rc;
+
+ memset(array_of_uint, 0, sizeof(*array_of_uint)); /* In case of errors */
+ if (str->length == 0)
+ return ER_DYNCOL_OK; /* no columns */
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ return rc;
+
+ if (header.format != dyncol_fmt_num)
+ return ER_DYNCOL_FORMAT;
+
+ if (header.entry_size * header.column_count + FIXED_HEADER_SIZE >
+ str->length)
+ return ER_DYNCOL_FORMAT;
+
+ if (ma_init_dynamic_array(array_of_uint, sizeof(uint), header.column_count, 0))
+ return ER_DYNCOL_RESOURCE;
+
+ for (i= 0, read= header.header;
+ i < header.column_count;
+ i++, read+= header.entry_size)
+ {
+ uint nm= uint2korr(read);
+ /* Insert can't never fail as it's pre-allocated above */
+ (void) ma_insert_dynamic(array_of_uint, (uchar *)&nm);
+ }
+ return ER_DYNCOL_OK;
+}
+
+/**
+ List not-null columns in the packed string (only numeric format)
+
+ @param str The packed string
+ @param array_of_uint Where to put reference on created array
+
+ @return ER_DYNCOL_* return code
+*/
+enum enum_dyncol_func_result
+mariadb_dyncol_list_num(DYNAMIC_COLUMN *str, uint *count, uint **nums)
+{
+ DYN_HEADER header;
+ uchar *read;
+ uint i;
+ enum enum_dyncol_func_result rc;
+
+ (*nums)= 0; (*count)= 0; /* In case of errors */
+ if (str->length == 0)
+ return ER_DYNCOL_OK; /* no columns */
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ return rc;
+
+ if (header.format != dyncol_fmt_num)
+ return ER_DYNCOL_FORMAT;
+
+ if (header.entry_size * header.column_count + FIXED_HEADER_SIZE >
+ str->length)
+ return ER_DYNCOL_FORMAT;
+
+ if (!((*nums)= (uint *)malloc(sizeof(uint) * header.column_count)))
+ return ER_DYNCOL_RESOURCE;
+
+ for (i= 0, read= header.header;
+ i < header.column_count;
+ i++, read+= header.entry_size)
+ {
+ (*nums)[i]= uint2korr(read);
+ }
+ (*count)= header.column_count;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ List not-null columns in the packed string (any format)
+
+ @param str The packed string
+ @param count Number of names in the list
+ @param names Where to put names list (should be freed)
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_list_named(DYNAMIC_COLUMN *str, uint *count, LEX_STRING **names)
+{
+ DYN_HEADER header;
+ uchar *read;
+ char *pool;
+ struct st_service_funcs *fmt;
+ uint i;
+ enum enum_dyncol_func_result rc;
+
+ (*names)= 0; (*count)= 0;
+
+ if (str->length == 0)
+ return ER_DYNCOL_OK; /* no columns */
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ return rc;
+
+ fmt= fmt_data + header.format;
+
+ if (header.entry_size * header.column_count + fmt->fixed_hdr >
+ str->length)
+ return ER_DYNCOL_FORMAT;
+
+ if (header.format == dyncol_fmt_num)
+ *names= (LEX_STRING *)malloc(sizeof(LEX_STRING) * header.column_count +
+ DYNCOL_NUM_CHAR * header.column_count);
+ else
+ *names= (LEX_STRING *)malloc(sizeof(LEX_STRING) * header.column_count +
+ header.nmpool_size + header.column_count);
+ if (!(*names))
+ return ER_DYNCOL_RESOURCE;
+ pool= ((char *)(*names)) + sizeof(LEX_STRING) * header.column_count;
+
+ for (i= 0, read= header.header;
+ i < header.column_count;
+ i++, read+= header.entry_size)
+ {
+ if (header.format == dyncol_fmt_num)
+ {
+ uint nm= uint2korr(read);
+ (*names)[i].str= pool;
+ pool+= DYNCOL_NUM_CHAR;
+ (*names)[i].length=
+ ma_ll2str(nm, (*names)[i].str, 10) - (*names)[i].str;
+ }
+ else
+ {
+ LEX_STRING tmp;
+ if (read_name(&header, read, &tmp))
+ return ER_DYNCOL_FORMAT;
+ (*names)[i].length= tmp.length;
+ (*names)[i].str= pool;
+ pool+= tmp.length + 1;
+ memcpy((*names)[i].str, (const void *)tmp.str, tmp.length);
+ (*names)[i].str[tmp.length]= '\0'; // just for safety
+ }
+ }
+ (*count)= header.column_count;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Find the place of the column in the header or place where it should be put
+
+ @param hdr descriptor of dynamic column record
+ @param key Name or number of column to fetch
+ (depends on string_key)
+ @param string_key True if we gave pointer to LEX_STRING.
+
+ @retval TRUE found
+ @retval FALSE pointer set to the next row
+*/
+
+static my_bool
+find_place(DYN_HEADER *hdr, void *key, my_bool string_keys)
+{
+ uint mid, start, end, val;
+ int UNINIT_VAR(flag);
+ LEX_STRING str;
+ char buff[DYNCOL_NUM_CHAR];
+ my_bool need_conversion= ((string_keys ? dyncol_fmt_str : dyncol_fmt_num) !=
+ hdr->format);
+ /* new format can't be numeric if the old one is names */
+ DBUG_ASSERT(string_keys ||
+ hdr->format == dyncol_fmt_num);
+
+ start= 0;
+ end= hdr->column_count -1;
+ mid= 1;
+ while (start != end)
+ {
+ uint val;
+ mid= (start + end) / 2;
+ hdr->entry= hdr->header + mid * hdr->entry_size;
+ if (!string_keys)
+ {
+ val= uint2korr(hdr->entry);
+ flag= CMP_NUM(*((uint *)key), val);
+ }
+ else
+ {
+ if (need_conversion)
+ {
+ str.str= backwritenum(buff + sizeof(buff), uint2korr(hdr->entry));
+ str.length= (buff + sizeof(buff)) - str.str;
+ }
+ else
+ {
+ DBUG_ASSERT(hdr->format == dyncol_fmt_str);
+ if (read_name(hdr, hdr->entry, &str))
+ return 0;
+ }
+ flag= mariadb_dyncol_column_cmp_named((LEX_STRING *)key, &str);
+ }
+ if (flag <= 0)
+ end= mid;
+ else
+ start= mid + 1;
+ }
+ hdr->entry= hdr->header + start * hdr->entry_size;
+ if (start != mid)
+ {
+ if (!string_keys)
+ {
+ val= uint2korr(hdr->entry);
+ flag= CMP_NUM(*((uint *)key), val);
+ }
+ else
+ {
+ if (need_conversion)
+ {
+ str.str= backwritenum(buff + sizeof(buff), uint2korr(hdr->entry));
+ str.length= (buff + sizeof(buff)) - str.str;
+ }
+ else
+ {
+ DBUG_ASSERT(hdr->format == dyncol_fmt_str);
+ if (read_name(hdr, hdr->entry, &str))
+ return 0;
+ }
+ flag= mariadb_dyncol_column_cmp_named((LEX_STRING *)key, &str);
+ }
+ }
+ if (flag > 0)
+ hdr->entry+= hdr->entry_size; /* Point at next bigger key */
+ return flag == 0;
+}
+
+
+/*
+ It is internal structure which describes a plan of changing the record
+ of dynamic columns
+*/
+
+typedef enum {PLAN_REPLACE, PLAN_ADD, PLAN_DELETE, PLAN_NOP} PLAN_ACT;
+
+struct st_plan {
+ DYNAMIC_COLUMN_VALUE *val;
+ void *key;
+ uchar *place;
+ size_t length;
+ long long hdelta, ddelta, ndelta;
+ long long mv_offset, mv_length;
+ uint mv_end;
+ PLAN_ACT act;
+};
+typedef struct st_plan PLAN;
+
+
+/**
+ Sort function for plan by column number
+*/
+
+static int plan_sort_num(const void *a, const void *b)
+{
+ return *((uint *)((PLAN *)a)->key) - *((uint *)((PLAN *)b)->key);
+}
+
+
+/**
+ Sort function for plan by column name
+*/
+
+static int plan_sort_named(const void *a, const void *b)
+{
+ return mariadb_dyncol_column_cmp_named((LEX_STRING *)((PLAN *)a)->key,
+ (LEX_STRING *)((PLAN *)b)->key);
+}
+
+#define DELTA_CHECK(S, D, C) \
+ if ((S) == 0) \
+ (S)= (D); \
+ else if (((S) > 0 && (D) < 0) || \
+ ((S) < 0 && (D) > 0)) \
+ { \
+ (C)= TRUE; \
+ }
+
+/**
+ Update dynamic column by copying in a new record (string).
+
+ @param str Dynamic column record to change
+ @param plan Plan of changing the record
+ @param add_column_count number of records in the plan array.
+ @param hdr descriptor of old dynamic column record
+ @param new_hdr descriptor of new dynamic column record
+ @param convert need conversion from numeric to names format
+
+ @return ER_DYNCOL_* return code
+*/
+
+static enum enum_dyncol_func_result
+dynamic_column_update_copy(DYNAMIC_COLUMN *str, PLAN *plan,
+ uint add_column_count,
+ DYN_HEADER *hdr, DYN_HEADER *new_hdr,
+ my_bool convert)
+{
+ DYNAMIC_COLUMN tmp;
+ struct st_service_funcs *fmt= fmt_data + hdr->format,
+ *new_fmt= fmt_data + new_hdr->format;
+ uint i, j, k;
+ size_t all_headers_size;
+
+ if (dynamic_column_init_named(&tmp,
+ (new_fmt->fixed_hdr + new_hdr->header_size +
+ new_hdr->nmpool_size +
+ new_hdr->data_size + DYNCOL_SYZERESERVE)))
+ {
+ return ER_DYNCOL_RESOURCE;
+ }
+ memset(tmp.str, 0, new_fmt->fixed_hdr);
+ (*new_fmt->set_fixed_hdr)(&tmp, new_hdr);
+ /* Adjust tmp to contain whole the future header */
+ tmp.length= new_fmt->fixed_hdr + new_hdr->header_size + new_hdr->nmpool_size;
+
+
+ /*
+ Copy data to the new string
+ i= index in array of changes
+ j= index in packed string header index
+ */
+ new_hdr->entry= new_hdr->header;
+ new_hdr->name= new_hdr->nmpool;
+ all_headers_size= new_fmt->fixed_hdr +
+ new_hdr->header_size + new_hdr->nmpool_size;
+ for (i= 0, j= 0; i < add_column_count || j < hdr->column_count; i++)
+ {
+ size_t first_offset= 0;
+ uint start= j, end;
+
+ /*
+ Search in i and j for the next column to add from i and where to
+ add.
+ */
+
+ while (i < add_column_count && plan[i].act == PLAN_NOP)
+ i++; /* skip NOP */
+
+ if (i == add_column_count)
+ j= end= hdr->column_count;
+ else
+ {
+ /*
+ old data portion. We don't need to check that j < column_count
+ as plan[i].place is guaranteed to have a pointer inside the
+ data.
+ */
+ while (hdr->header + j * hdr->entry_size < plan[i].place)
+ j++;
+ end= j;
+ if ((plan[i].act == PLAN_REPLACE || plan[i].act == PLAN_DELETE))
+ j++; /* data at 'j' will be removed */
+ }
+
+ /*
+ Adjust all headers since last loop.
+ We have to do this as the offset for data has moved
+ */
+ for (k= start; k < end; k++)
+ {
+ uchar *read= hdr->header + k * hdr->entry_size;
+ void *key;
+ LEX_STRING name;
+ size_t offs;
+ uint nm;
+ DYNAMIC_COLUMN_TYPE tp;
+ char buff[DYNCOL_NUM_CHAR];
+
+ if (hdr->format == dyncol_fmt_num)
+ {
+ if (convert)
+ {
+ name.str= backwritenum(buff + sizeof(buff), uint2korr(read));
+ name.length= (buff + sizeof(buff)) - name.str;
+ key= &name;
+ }
+ else
+ {
+ nm= uint2korr(read); /* Column number */
+ key= &nm;
+ }
+ }
+ else
+ {
+ if (read_name(hdr, read, &name))
+ goto err;
+ key= &name;
+ }
+ if (fmt->type_and_offset_read(&tp, &offs,
+ read + fmt->fixed_hdr_entry,
+ hdr->offset_size))
+ goto err;
+ if (k == start)
+ first_offset= offs;
+ else if (offs < first_offset)
+ goto err;
+
+ offs+= (size_t)plan[i].ddelta;
+ {
+ DYNAMIC_COLUMN_VALUE val;
+ val.type= tp; // only the type used in the header
+ if ((*new_fmt->put_header_entry)(new_hdr, key, &val, offs))
+ goto err;
+ }
+ }
+
+ /* copy first the data that was not replaced in original packed data */
+ if (start < end)
+ {
+ size_t data_size;
+ /* Add old data last in 'tmp' */
+ hdr->entry= hdr->header + start * hdr->entry_size;
+ data_size=
+ hdr_interval_length(hdr, hdr->header + end * hdr->entry_size);
+ if (data_size == DYNCOL_OFFSET_ERROR ||
+ (long) data_size < 0 ||
+ data_size > hdr->data_size - first_offset)
+ goto err;
+
+ memcpy(tmp.str + tmp.length, (char *)hdr->dtpool + first_offset,
+ data_size);
+ tmp.length+= data_size;
+ }
+
+ /* new data adding */
+ if (i < add_column_count)
+ {
+ if( plan[i].act == PLAN_ADD || plan[i].act == PLAN_REPLACE)
+ {
+ if ((*new_fmt->put_header_entry)(new_hdr, plan[i].key,
+ plan[i].val,
+ tmp.length - all_headers_size))
+ goto err;
+ data_store(&tmp, plan[i].val, new_hdr->format); /* Append new data */
+ }
+ }
+ }
+ dynamic_column_column_free(str);
+ *str= tmp;
+ return ER_DYNCOL_OK;
+err:
+ dynamic_column_column_free(&tmp);
+ return ER_DYNCOL_FORMAT;
+}
+
+static enum enum_dyncol_func_result
+dynamic_column_update_move_left(DYNAMIC_COLUMN *str, PLAN *plan,
+ size_t offset_size,
+ size_t entry_size,
+ size_t header_size,
+ size_t new_offset_size,
+ size_t new_entry_size,
+ size_t new_header_size,
+ uint column_count,
+ uint new_column_count,
+ uint add_column_count,
+ uchar *header_end,
+ size_t max_offset)
+{
+ uchar *write;
+ uchar *header_base= (uchar *)str->str + FIXED_HEADER_SIZE;
+ uint i, j, k;
+ size_t curr_offset;
+
+ write= (uchar *)str->str + FIXED_HEADER_SIZE;
+ set_fixed_header(str, (uint)new_offset_size, new_column_count);
+
+ /*
+ Move headers first.
+ i= index in array of changes
+ j= index in packed string header index
+ */
+ for (curr_offset= 0, i= 0, j= 0;
+ i < add_column_count || j < column_count;
+ i++)
+ {
+ size_t UNINIT_VAR(first_offset);
+ uint start= j, end;
+
+ /*
+ Search in i and j for the next column to add from i and where to
+ add.
+ */
+
+ while (i < add_column_count && plan[i].act == PLAN_NOP)
+ i++; /* skip NOP */
+
+ if (i == add_column_count)
+ j= end= column_count;
+ else
+ {
+ /*
+ old data portion. We don't need to check that j < column_count
+ as plan[i].place is guaranteed to have a pointer inside the
+ data.
+ */
+ while (header_base + j * entry_size < plan[i].place)
+ j++;
+ end= j;
+ if ((plan[i].act == PLAN_REPLACE || plan[i].act == PLAN_DELETE))
+ j++; /* data at 'j' will be removed */
+ }
+ plan[i].mv_end= end;
+
+ {
+ DYNAMIC_COLUMN_TYPE tp;
+ if (type_and_offset_read_num(&tp, &first_offset,
+ header_base + start * entry_size +
+ COLUMN_NUMBER_SIZE, offset_size))
+ return ER_DYNCOL_FORMAT;
+ }
+ /* find data to be moved */
+ if (start < end)
+ {
+ size_t data_size=
+ get_length_interval(header_base + start * entry_size,
+ header_base + end * entry_size,
+ header_end, offset_size, max_offset);
+ if (data_size == DYNCOL_OFFSET_ERROR ||
+ (long) data_size < 0 ||
+ data_size > max_offset - first_offset)
+ {
+ str->length= 0; // just something valid
+ return ER_DYNCOL_FORMAT;
+ }
+ DBUG_ASSERT(curr_offset == first_offset + plan[i].ddelta);
+ plan[i].mv_offset= first_offset;
+ plan[i].mv_length= data_size;
+ curr_offset+= data_size;
+ }
+ else
+ {
+ plan[i].mv_length= 0;
+ plan[i].mv_offset= curr_offset;
+ }
+
+ if (plan[i].ddelta == 0 && offset_size == new_offset_size &&
+ plan[i].act != PLAN_DELETE)
+ write+= entry_size * (end - start);
+ else
+ {
+ /*
+ Adjust all headers since last loop.
+ We have to do this as the offset for data has moved
+ */
+ for (k= start; k < end; k++)
+ {
+ uchar *read= header_base + k * entry_size;
+ size_t offs;
+ uint nm;
+ DYNAMIC_COLUMN_TYPE tp;
+
+ nm= uint2korr(read); /* Column number */
+ if (type_and_offset_read_num(&tp, &offs, read + COLUMN_NUMBER_SIZE,
+ offset_size))
+ return ER_DYNCOL_FORMAT;
+
+ if (k > start && offs < first_offset)
+ {
+ str->length= 0; // just something valid
+ return ER_DYNCOL_FORMAT;
+ }
+
+ offs+= (size_t)plan[i].ddelta;
+ int2store(write, nm);
+ /* write rest of data at write + COLUMN_NUMBER_SIZE */
+ type_and_offset_store_num(write, new_offset_size, tp, offs);
+ write+= new_entry_size;
+ }
+ }
+
+ /* new data adding */
+ if (i < add_column_count)
+ {
+ if( plan[i].act == PLAN_ADD || plan[i].act == PLAN_REPLACE)
+ {
+ int2store(write, *((uint *)plan[i].key));
+ type_and_offset_store_num(write, new_offset_size,
+ plan[i].val[0].type,
+ curr_offset);
+ write+= new_entry_size;
+ curr_offset+= plan[i].length;
+ }
+ }
+ }
+
+ /*
+ Move data.
+ i= index in array of changes
+ j= index in packed string header index
+ */
+ str->length= (FIXED_HEADER_SIZE + new_header_size);
+ for (i= 0, j= 0;
+ i < add_column_count || j < column_count;
+ i++)
+ {
+ uint start= j, end;
+
+ /*
+ Search in i and j for the next column to add from i and where to
+ add.
+ */
+
+ while (i < add_column_count && plan[i].act == PLAN_NOP)
+ i++; /* skip NOP */
+
+ j= end= plan[i].mv_end;
+ if (i != add_column_count &&
+ (plan[i].act == PLAN_REPLACE || plan[i].act == PLAN_DELETE))
+ j++;
+
+ /* copy first the data that was not replaced in original packed data */
+ if (start < end && plan[i].mv_length)
+ {
+ memmove((header_base + new_header_size +
+ (size_t)plan[i].mv_offset + (size_t)plan[i].ddelta),
+ header_base + header_size + (size_t)plan[i].mv_offset,
+ (size_t)plan[i].mv_length);
+ }
+ str->length+= (size_t)plan[i].mv_length;
+
+ /* new data adding */
+ if (i < add_column_count)
+ {
+ if( plan[i].act == PLAN_ADD || plan[i].act == PLAN_REPLACE)
+ {
+ data_store(str, plan[i].val, dyncol_fmt_num);/* Append new data */
+ }
+ }
+ }
+ return ER_DYNCOL_OK;
+}
+
+#ifdef UNUSED
+static enum enum_dyncol_func_result
+dynamic_column_update_move_right(DYNAMIC_COLUMN *str, PLAN *plan,
+ size_t offset_size,
+ size_t entry_size,
+ size_t header_size,
+ size_t new_offset_size,
+ size_t new_entry_size,
+ size_t new_header_size,
+ uint column_count,
+ uint new_column_count,
+ uint add_column_count,
+ uchar *header_end,
+ size_t max_offset)
+{
+ uchar *write;
+ uchar *header_base= (uchar *)str->str + FIXED_HEADER_SIZE;
+ uint i, j, k;
+ size_t curr_offset;
+
+ write= (uchar *)str->str + FIXED_HEADER_SIZE;
+ set_fixed_header(str, new_offset_size, new_column_count);
+
+ /*
+ Move data first.
+ i= index in array of changes
+ j= index in packed string header index
+ */
+ for (curr_offset= 0, i= 0, j= 0;
+ i < add_column_count || j < column_count;
+ i++)
+ {
+ size_t UNINIT_VAR(first_offset);
+ uint start= j, end;
+
+ /*
+ Search in i and j for the next column to add from i and where to
+ add.
+ */
+
+ while (i < add_column_count && plan[i].act == PLAN_NOP)
+ i++; /* skip NOP */
+
+ if (i == add_column_count)
+ j= end= column_count;
+ else
+ {
+ /*
+ old data portion. We don't need to check that j < column_count
+ as plan[i].place is guaranteed to have a pointer inside the
+ data.
+ */
+ while (header_base + j * entry_size < plan[i].place)
+ j++;
+ end= j;
+ if ((plan[i].act == PLAN_REPLACE || plan[i].act == PLAN_DELETE))
+ j++; /* data at 'j' will be removed */
+ }
+ plan[i].mv_end= end;
+
+ {
+ DYNAMIC_COLUMN_TYPE tp;
+ type_and_offset_read_num(&tp, &first_offset,
+ header_base +
+ start * entry_size + COLUMN_NUMBER_SIZE,
+ offset_size);
+ }
+ /* find data to be moved */
+ if (start < end)
+ {
+ size_t data_size=
+ get_length_interval(header_base + start * entry_size,
+ header_base + end * entry_size,
+ header_end, offset_size, max_offset);
+ if (data_size == DYNCOL_OFFSET_ERROR ||
+ (long) data_size < 0 ||
+ data_size > max_offset - first_offset)
+ {
+ str->length= 0; // just something valid
+ return ER_DYNCOL_FORMAT;
+ }
+ DBUG_ASSERT(curr_offset == first_offset + plan[i].ddelta);
+ plan[i].mv_offset= first_offset;
+ plan[i].mv_length= data_size;
+ curr_offset+= data_size;
+ }
+ else
+ {
+ plan[i].mv_length= 0;
+ plan[i].mv_offset= curr_offset;
+ }
+
+ if (plan[i].ddelta == 0 && offset_size == new_offset_size &&
+ plan[i].act != PLAN_DELETE)
+ write+= entry_size * (end - start);
+ else
+ {
+ /*
+ Adjust all headers since last loop.
+ We have to do this as the offset for data has moved
+ */
+ for (k= start; k < end; k++)
+ {
+ uchar *read= header_base + k * entry_size;
+ size_t offs;
+ uint nm;
+ DYNAMIC_COLUMN_TYPE tp;
+
+ nm= uint2korr(read); /* Column number */
+ type_and_offset_read_num(&tp, &offs, read + COLUMN_NUMBER_SIZE,
+ offset_size);
+ if (k > start && offs < first_offset)
+ {
+ str->length= 0; // just something valid
+ return ER_DYNCOL_FORMAT;
+ }
+
+ offs+= plan[i].ddelta;
+ int2store(write, nm);
+ /* write rest of data at write + COLUMN_NUMBER_SIZE */
+ if (type_and_offset_store_num(write, new_offset_size, tp, offs))
+ {
+ str->length= 0; // just something valid
+ return ER_DYNCOL_FORMAT;
+ }
+ write+= new_entry_size;
+ }
+ }
+
+ /* new data adding */
+ if (i < add_column_count)
+ {
+ if( plan[i].act == PLAN_ADD || plan[i].act == PLAN_REPLACE)
+ {
+ int2store(write, *((uint *)plan[i].key));
+ if (type_and_offset_store_num(write, new_offset_size,
+ plan[i].val[0].type,
+ curr_offset))
+ {
+ str->length= 0; // just something valid
+ return ER_DYNCOL_FORMAT;
+ }
+ write+= new_entry_size;
+ curr_offset+= plan[i].length;
+ }
+ }
+ }
+
+ /*
+ Move headers.
+ i= index in array of changes
+ j= index in packed string header index
+ */
+ str->length= (FIXED_HEADER_SIZE + new_header_size);
+ for (i= 0, j= 0;
+ i < add_column_count || j < column_count;
+ i++)
+ {
+ uint start= j, end;
+
+ /*
+ Search in i and j for the next column to add from i and where to
+ add.
+ */
+
+ while (i < add_column_count && plan[i].act == PLAN_NOP)
+ i++; /* skip NOP */
+
+ j= end= plan[i].mv_end;
+ if (i != add_column_count &&
+ (plan[i].act == PLAN_REPLACE || plan[i].act == PLAN_DELETE))
+ j++;
+
+ /* copy first the data that was not replaced in original packed data */
+ if (start < end && plan[i].mv_length)
+ {
+ memmove((header_base + new_header_size +
+ plan[i].mv_offset + plan[i].ddelta),
+ header_base + header_size + plan[i].mv_offset,
+ plan[i].mv_length);
+ }
+ str->length+= plan[i].mv_length;
+
+ /* new data adding */
+ if (i < add_column_count)
+ {
+ if( plan[i].act == PLAN_ADD || plan[i].act == PLAN_REPLACE)
+ {
+ data_store(str, plan[i].val, dyncol_fmt_num); /* Append new data */
+ }
+ }
+ }
+ return ER_DYNCOL_OK;
+}
+#endif
+
+/**
+ Update the packed string with the given columns
+
+ @param str String where to write the data
+ @param add_column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+/* plan allocated on the stack */
+#define IN_PLACE_PLAN 4
+
+enum enum_dyncol_func_result
+dynamic_column_update_many(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ return dynamic_column_update_many_fmt(str, add_column_count, column_numbers,
+ values, FALSE);
+}
+
+enum enum_dyncol_func_result
+mariadb_dyncol_update_many_num(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ return dynamic_column_update_many_fmt(str, add_column_count, column_numbers,
+ values, FALSE);
+}
+
+enum enum_dyncol_func_result
+mariadb_dyncol_update_many_named(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ LEX_STRING *column_names,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ return dynamic_column_update_many_fmt(str, add_column_count, column_names,
+ values, TRUE);
+}
+
+static uint numlen(uint val)
+{
+ uint res;
+ if (val == 0)
+ return 1;
+ res= 0;
+ while(val)
+ {
+ res++;
+ val/=10;
+ }
+ return res;
+}
+
+static enum enum_dyncol_func_result
+dynamic_column_update_many_fmt(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ void *column_keys,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool string_keys)
+{
+ PLAN *plan, *alloc_plan= NULL, in_place_plan[IN_PLACE_PLAN];
+ uchar *element;
+ DYN_HEADER header, new_header;
+ struct st_service_funcs *fmt, *new_fmt;
+ long long data_delta= 0, name_delta= 0;
+ uint i;
+ uint not_null;
+ long long header_delta= 0;
+ long long header_delta_sign, data_delta_sign;
+ int copy= FALSE;
+ enum enum_dyncol_func_result rc;
+ my_bool convert;
+
+ if (add_column_count == 0)
+ return ER_DYNCOL_OK;
+
+ memset(&header, 0, sizeof(header));
+ memset(&new_header, 0, sizeof(new_header));
+ new_header.format= (string_keys ? dyncol_fmt_str : dyncol_fmt_num);
+ new_fmt= fmt_data + new_header.format;
+
+ /*
+ Get columns in column order. As the data in 'str' is already
+ in column order this allows to replace all columns in one loop.
+ */
+ if (IN_PLACE_PLAN > add_column_count)
+ plan= in_place_plan;
+ else if (!(alloc_plan= plan=
+ (PLAN *)malloc(sizeof(PLAN) * (add_column_count + 1))))
+ return ER_DYNCOL_RESOURCE;
+
+ not_null= add_column_count;
+ for (i= 0, element= (uchar *) column_keys;
+ i < add_column_count;
+ i++, element+= new_fmt->key_size_in_array)
+ {
+ if ((*new_fmt->check_limit)(&element))
+ {
+ rc= ER_DYNCOL_DATA;
+ goto end;
+ }
+
+ plan[i].val= values + i;
+ plan[i].key= element;
+ if (values[i].type == DYN_COL_NULL)
+ not_null--;
+
+ }
+
+ if (str->length == 0)
+ {
+ /*
+ Just add new columns. If there was no columns to add we return
+ an empty string.
+ */
+ goto create_new_string;
+ }
+
+ /* Check that header is ok */
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ goto end;
+ fmt= fmt_data + header.format;
+ /* new format can't be numeric if the old one is names */
+ DBUG_ASSERT(new_header.format == dyncol_fmt_str ||
+ header.format == dyncol_fmt_num);
+ if (header.column_count == 0)
+ goto create_new_string;
+
+ qsort(plan, (size_t)add_column_count, sizeof(PLAN), new_fmt->plan_sort);
+
+ new_header.column_count= header.column_count;
+ new_header.nmpool_size= header.nmpool_size;
+ if ((convert= (new_header.format == dyncol_fmt_str &&
+ header.format == dyncol_fmt_num)))
+ {
+ DBUG_ASSERT(new_header.nmpool_size == 0);
+ for(i= 0, header.entry= header.header;
+ i < header.column_count;
+ i++, header.entry+= header.entry_size)
+ {
+ new_header.nmpool_size+= numlen(uint2korr(header.entry));
+ }
+ }
+
+ if (fmt->fixed_hdr + header.header_size + header.nmpool_size > str->length)
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto end;
+ }
+
+ /*
+ Calculate how many columns and data is added/deleted and make a 'plan'
+ for each of them.
+ */
+ for (i= 0; i < add_column_count; i++)
+ {
+ /*
+ For now we don't allow creating two columns with the same number
+ at the time of create. This can be fixed later to just use the later
+ by comparing the pointers.
+ */
+ if (i < add_column_count - 1 &&
+ new_fmt->column_sort(&plan[i].key, &plan[i + 1].key) == 0)
+ {
+ rc= ER_DYNCOL_DATA;
+ goto end;
+ }
+
+ /* Set common variables for all plans */
+ plan[i].ddelta= data_delta;
+ plan[i].ndelta= name_delta;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta;
+ plan[i].length= 0; /* Length if NULL */
+
+ if (find_place(&header, plan[i].key, string_keys))
+ {
+ size_t entry_data_size, entry_name_size= 0;
+
+ /* Data existed; We have to replace or delete it */
+
+ entry_data_size= hdr_interval_length(&header, header.entry +
+ header.entry_size);
+ if (entry_data_size == DYNCOL_OFFSET_ERROR ||
+ (long) entry_data_size < 0)
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto end;
+ }
+
+ if (new_header.format == dyncol_fmt_str)
+ {
+ if (header.format == dyncol_fmt_str)
+ {
+ LEX_STRING name;
+ if (read_name(&header, header.entry, &name))
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto end;
+ }
+ entry_name_size= name.length;
+ }
+ else
+ entry_name_size= numlen(uint2korr(header.entry));
+ }
+
+ if (plan[i].val->type == DYN_COL_NULL)
+ {
+ /* Inserting a NULL means delete the old data */
+
+ plan[i].act= PLAN_DELETE; /* Remove old value */
+ header_delta--; /* One row less in header */
+ data_delta-= entry_data_size; /* Less data to store */
+ name_delta-= entry_name_size;
+ }
+ else
+ {
+ /* Replace the value */
+
+ plan[i].act= PLAN_REPLACE;
+ /* get data delta in bytes */
+ if ((plan[i].length= dynamic_column_value_len(plan[i].val,
+ new_header.format)) ==
+ (size_t) ~0)
+ {
+ rc= ER_DYNCOL_DATA;
+ goto end;
+ }
+ data_delta+= plan[i].length - entry_data_size;
+ if (new_header.format == dyncol_fmt_str)
+ {
+ name_delta+= ((LEX_STRING *)(plan[i].key))->length - entry_name_size;
+ }
+ }
+ }
+ else
+ {
+ /* Data did not exists. Add if it it's not NULL */
+
+ if (plan[i].val->type == DYN_COL_NULL)
+ {
+ plan[i].act= PLAN_NOP; /* Mark entry to be skipped */
+ }
+ else
+ {
+ /* Add new value */
+
+ plan[i].act= PLAN_ADD;
+ header_delta++; /* One more row in header */
+ /* get data delta in bytes */
+ if ((plan[i].length= dynamic_column_value_len(plan[i].val,
+ new_header.format)) ==
+ (size_t) ~0)
+ {
+ rc= ER_DYNCOL_DATA;
+ goto end;
+ }
+ data_delta+= plan[i].length;
+ if (new_header.format == dyncol_fmt_str)
+ name_delta+= ((LEX_STRING *)plan[i].key)->length;
+ }
+ }
+ plan[i].place= header.entry;
+ }
+ plan[add_column_count].hdelta= header_delta;
+ plan[add_column_count].ddelta= data_delta;
+ plan[add_column_count].act= PLAN_NOP;
+ plan[add_column_count].place= header.dtpool;
+
+ new_header.column_count= (uint)(header.column_count + header_delta);
+
+ /*
+ Check if it is only "increasing" or only "decreasing" plan for (header
+ and data separately).
+ */
+ new_header.data_size= header.data_size + (size_t)data_delta;
+ new_header.nmpool_size= new_header.nmpool_size + (size_t)name_delta;
+ DBUG_ASSERT(new_header.format != dyncol_fmt_num ||
+ new_header.nmpool_size == 0);
+ if ((new_header.offset_size=
+ new_fmt->dynamic_column_offset_bytes(new_header.data_size)) >=
+ new_fmt->max_offset_size)
+ {
+ rc= ER_DYNCOL_LIMIT;
+ goto end;
+ }
+
+ copy= ((header.format != new_header.format) ||
+ (new_header.format == dyncol_fmt_str));
+ /* if (new_header.offset_size!=offset_size) then we have to rewrite header */
+ header_delta_sign=
+ ((int)new_header.offset_size + new_fmt->fixed_hdr_entry) -
+ ((int)header.offset_size + fmt->fixed_hdr_entry);
+ data_delta_sign= 0;
+ // plan[add_column_count] contains last deltas.
+ for (i= 0; i <= add_column_count && !copy; i++)
+ {
+ /* This is the check for increasing/decreasing */
+ DELTA_CHECK(header_delta_sign, plan[i].hdelta, copy);
+ DELTA_CHECK(data_delta_sign, plan[i].ddelta, copy);
+ }
+ calc_param(&new_header.entry_size, &new_header.header_size,
+ new_fmt->fixed_hdr_entry,
+ new_header.offset_size, new_header.column_count);
+
+ /*
+ Need copy because:
+ 1, Header/data parts moved in different directions.
+ 2. There is no enough allocated space in the string.
+ 3. Header and data moved in different directions.
+ */
+ if (copy || /*1.*/
+ str->max_length < str->length + header_delta + data_delta || /*2.*/
+ ((header_delta_sign < 0 && data_delta_sign > 0) ||
+ (header_delta_sign > 0 && data_delta_sign < 0))) /*3.*/
+ rc= dynamic_column_update_copy(str, plan, add_column_count,
+ &header, &new_header,
+ convert);
+ else
+ if (header_delta_sign < 0)
+ rc= dynamic_column_update_move_left(str, plan, header.offset_size,
+ header.entry_size,
+ header.header_size,
+ new_header.offset_size,
+ new_header.entry_size,
+ new_header.header_size,
+ header.column_count,
+ new_header.column_count,
+ add_column_count, header.dtpool,
+ header.data_size);
+ else
+ /*
+ rc= dynamic_column_update_move_right(str, plan, offset_size,
+ entry_size, header_size,
+ new_header.offset_size,
+ new_header.entry_size,
+ new_heder.header_size, column_count,
+ new_header.column_count,
+ add_column_count, header_end,
+ header.data_size);
+ */
+ rc= dynamic_column_update_copy(str, plan, add_column_count,
+ &header, &new_header,
+ convert);
+end:
+ free(alloc_plan);
+ return rc;
+
+create_new_string:
+ /* There is no columns from before, so let's just add the new ones */
+ rc= ER_DYNCOL_OK;
+ if (not_null != 0)
+ rc= dynamic_column_create_many_internal_fmt(str, add_column_count,
+ (uint*)column_keys, values,
+ str->str == NULL,
+ string_keys);
+ goto end;
+}
+
+
+/**
+ Update the packed string with the given column
+
+ @param str String where to write the data
+ @param column_number Array of columns number
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+
+int dynamic_column_update(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value)
+{
+ return dynamic_column_update_many(str, 1, &column_nr, value);
+}
+
+
+enum enum_dyncol_func_result
+mariadb_dyncol_check(DYNAMIC_COLUMN *str)
+{
+ struct st_service_funcs *fmt;
+ enum enum_dyncol_func_result rc= ER_DYNCOL_FORMAT;
+ DYN_HEADER header;
+ uint i;
+ size_t data_offset= 0, name_offset= 0;
+ size_t prev_data_offset= 0, prev_name_offset= 0;
+ LEX_STRING name= {0,0}, prev_name= {0,0};
+ uint num= 0, prev_num= 0;
+ void *key, *prev_key;
+ enum enum_dynamic_column_type type= DYN_COL_NULL, prev_type= DYN_COL_NULL;
+
+ if (str->length == 0)
+ {
+ return(ER_DYNCOL_OK);
+ }
+
+ memset(&header, 0, sizeof(header));
+
+ /* Check that header is OK */
+ if (read_fixed_header(&header, str))
+ {
+ goto end;
+ }
+ fmt= fmt_data + header.format;
+ calc_param(&header.entry_size, &header.header_size,
+ fmt->fixed_hdr_entry, header.offset_size,
+ header.column_count);
+ /* headers are out of string length (no space for data and part of headers) */
+ if (fmt->fixed_hdr + header.header_size + header.nmpool_size > str->length)
+ {
+ goto end;
+ }
+ header.header= (uchar*)str->str + fmt->fixed_hdr;
+ header.nmpool= header.header + header.header_size;
+ header.dtpool= header.nmpool + header.nmpool_size;
+ header.data_size= str->length - fmt->fixed_hdr -
+ header.header_size - header.nmpool_size;
+
+ /* read and check headers */
+ if (header.format == dyncol_fmt_num)
+ {
+ key= &num;
+ prev_key= &prev_num;
+ }
+ else
+ {
+ key= &name;
+ prev_key= &prev_name;
+ }
+ for (i= 0, header.entry= header.header;
+ i < header.column_count;
+ i++, header.entry+= header.entry_size)
+ {
+
+ if (header.format == dyncol_fmt_num)
+ {
+ num= uint2korr(header.entry);
+ }
+ else
+ {
+ DBUG_ASSERT(header.format == dyncol_fmt_str);
+ if (read_name(&header, header.entry, &name))
+ {
+ goto end;
+ }
+ name_offset= name.str - (char *)header.nmpool;
+ }
+ if ((*fmt->type_and_offset_read)(&type, &data_offset,
+ header.entry + fmt->fixed_hdr_entry,
+ header.offset_size))
+ goto end;
+
+ DBUG_ASSERT(type != DYN_COL_NULL);
+ if (data_offset > header.data_size)
+ {
+ goto end;
+ }
+ if (prev_type != DYN_COL_NULL)
+ {
+ /* It is not first entry */
+ if (prev_data_offset >= data_offset)
+ {
+ goto end;
+ }
+ if (prev_name_offset > name_offset)
+ {
+ goto end;
+ }
+ if ((*fmt->column_sort)(&prev_key, &key) >= 0)
+ {
+ goto end;
+ }
+ }
+ prev_num= num;
+ prev_name= name;
+ prev_data_offset= data_offset;
+ prev_name_offset= name_offset;
+ prev_type= type;
+ }
+
+ /* check data, which we can */
+ for (i= 0, header.entry= header.header;
+ i < header.column_count;
+ i++, header.entry+= header.entry_size)
+ {
+ DYNAMIC_COLUMN_VALUE store;
+ /* already checked by previous pass */
+ (*fmt->type_and_offset_read)(&header.type, &header.offset,
+ header.entry + fmt->fixed_hdr_entry,
+ header.offset_size);
+ header.length=
+ hdr_interval_length(&header, header.entry + header.entry_size);
+ header.data= header.dtpool + header.offset;
+ switch ((header.type)) {
+ case DYN_COL_INT:
+ rc= dynamic_column_sint_read(&store, header.data, header.length);
+ break;
+ case DYN_COL_UINT:
+ rc= dynamic_column_uint_read(&store, header.data, header.length);
+ break;
+ case DYN_COL_DOUBLE:
+ rc= dynamic_column_double_read(&store, header.data, header.length);
+ break;
+ case DYN_COL_STRING:
+ rc= dynamic_column_string_read(&store, header.data, header.length);
+ break;
+#ifndef LIBMARIADB
+ case DYN_COL_DECIMAL:
+ rc= dynamic_column_decimal_read(&store, header.data, header.length);
+ break;
+#endif
+ case DYN_COL_DATETIME:
+ rc= dynamic_column_date_time_read(&store, header.data,
+ header.length);
+ break;
+ case DYN_COL_DATE:
+ rc= dynamic_column_date_read(&store, header.data, header.length);
+ break;
+ case DYN_COL_TIME:
+ rc= dynamic_column_time_read(&store, header.data, header.length);
+ break;
+ case DYN_COL_DYNCOL:
+ rc= dynamic_column_dyncol_read(&store, header.data, header.length);
+ break;
+ case DYN_COL_NULL:
+ default:
+ rc= ER_DYNCOL_FORMAT;
+ goto end;
+ }
+ if (rc != ER_DYNCOL_OK)
+ {
+ DBUG_ASSERT(rc < 0);
+ goto end;
+ }
+ }
+
+ rc= ER_DYNCOL_OK;
+end:
+ return(rc);
+}
+
+enum enum_dyncol_func_result
+mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
+ MARIADB_CHARSET_INFO *cs, char quote)
+{
+ char buff[40];
+ size_t len;
+ switch (val->type) {
+ case DYN_COL_INT:
+ len= snprintf(buff, sizeof(buff), "%lld", val->x.long_value);
+ if (ma_dynstr_append_mem(str, buff, len))
+ return ER_DYNCOL_RESOURCE;
+ break;
+ case DYN_COL_UINT:
+ len= snprintf(buff, sizeof(buff), "%llu", val->x.ulong_value);
+ if (ma_dynstr_append_mem(str, buff, len))
+ return ER_DYNCOL_RESOURCE;
+ break;
+ case DYN_COL_DOUBLE:
+ len= snprintf(buff, sizeof(buff), "%g", val->x.double_value);
+ if (ma_dynstr_realloc(str, len + (quote ? 2 : 0)))
+ return ER_DYNCOL_RESOURCE;
+ if (quote)
+ str->str[str->length++]= quote;
+ ma_dynstr_append_mem(str, buff, len);
+ if (quote)
+ str->str[str->length++]= quote;
+ break;
+ case DYN_COL_DYNCOL:
+ case DYN_COL_STRING:
+ {
+ char *alloc= NULL;
+ char *from= val->x.string.value.str;
+ ulong bufflen;
+ my_bool conv= ((val->x.string.charset == cs) ||
+ !strcmp(val->x.string.charset->name, cs->name));
+ my_bool rc;
+ len= val->x.string.value.length;
+ bufflen= (ulong)(len * (conv ? cs->char_maxlen : 1));
+ if (ma_dynstr_realloc(str, bufflen))
+ return ER_DYNCOL_RESOURCE;
+
+ // guaranty UTF-8 string for value
+ if (!conv)
+ {
+#ifndef LIBMARIADB
+ uint dumma_errors;
+#else
+ int dumma_errors;
+#endif
+ if (!quote)
+ {
+ /* convert to the destination */
+ str->length+=
+#ifndef LIBMARIADB
+ copy_and_convert_extended(str->str, bufflen,
+ cs,
+ from, (uint32)len,
+ val->x.string.charset,
+ &dumma_errors);
+#else
+ mariadb_convert_string(from, &len, val->x.string.charset,
+ str->str, (size_t *)&bufflen, cs, &dumma_errors);
+#endif
+ return ER_DYNCOL_OK;
+ }
+ if ((alloc= (char *)malloc(bufflen)))
+ {
+ len=
+#ifndef LIBMARIADB
+ copy_and_convert_extended(alloc, bufflen, cs,
+ from, (uint32)len,
+ val->x.string.charset,
+ &dumma_errors);
+#else
+ mariadb_convert_string(from, &len, val->x.string.charset,
+ alloc, (size_t *)&bufflen, cs, &dumma_errors);
+#endif
+ from= alloc;
+ }
+ else
+ return ER_DYNCOL_RESOURCE;
+ }
+ if (quote)
+ rc= ma_dynstr_append_quoted(str, from, len, quote);
+ else
+ rc= ma_dynstr_append_mem(str, from, len);
+ if (alloc)
+ free(alloc);
+ if (rc)
+ return ER_DYNCOL_RESOURCE;
+ break;
+ }
+#ifndef LIBMARIADB
+ case DYN_COL_DECIMAL:
+ {
+ int len= sizeof(buff);
+ decimal2string(&val->x.decimal.value, buff, &len,
+ 0, val->x.decimal.value.frac,
+ '0');
+ if (ma_dynstr_append_mem(str, buff, len))
+ return ER_DYNCOL_RESOURCE;
+ break;
+ }
+#endif
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+#ifndef LIBMARIADB
+ len= my_TIME_to_str(&val->x.time_value, buff, AUTO_SEC_PART_DIGITS);
+#else
+ len= mariadb_time_to_string(&val->x.time_value, buff, 39, AUTO_SEC_PART_DIGITS);
+#endif
+ if (ma_dynstr_realloc(str, len + (quote ? 2 : 0)))
+ return ER_DYNCOL_RESOURCE;
+ if (quote)
+ str->str[str->length++]= '"';
+ ma_dynstr_append_mem(str, buff, len);
+ if (quote)
+ str->str[str->length++]= '"';
+ break;
+ case DYN_COL_NULL:
+ if (ma_dynstr_append_mem(str, "null", 4))
+ return ER_DYNCOL_RESOURCE;
+ break;
+ default:
+ return(ER_DYNCOL_FORMAT);
+ }
+ return(ER_DYNCOL_OK);
+}
+
+enum enum_dyncol_func_result
+mariadb_dyncol_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val)
+{
+ enum enum_dyncol_func_result rc= ER_DYNCOL_OK;
+ *ll= 0;
+ switch (val->type) {
+ case DYN_COL_INT:
+ *ll= val->x.long_value;
+ break;
+ case DYN_COL_UINT:
+ *ll= (longlong)val->x.ulong_value;
+ if (*ll > (longlong)ULONGLONG_MAX)
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+ case DYN_COL_DOUBLE:
+ *ll= (longlong)val->x.double_value;
+ if (((double) *ll) != val->x.double_value)
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+ case DYN_COL_STRING:
+ {
+ char *src= val->x.string.value.str;
+ size_t len= val->x.string.value.length;
+ longlong i= 0, sign= 1;
+
+ while (len && isspace(*src)) src++,len--;
+
+ if (len)
+ {
+ if (*src == '-')
+ {
+ sign= -1;
+ src++;
+ }
+ while(len && isdigit(*src))
+ {
+ i= i * 10 + (*src - '0');
+ src++;
+ }
+ }
+ else
+ rc= ER_DYNCOL_TRUNCATED;
+ if (len)
+ rc= ER_DYNCOL_TRUNCATED;
+ *ll= i * sign;
+ break;
+ }
+#ifndef LIBMARIADB
+ case DYN_COL_DECIMAL:
+ if (decimal2longlong(&val->x.decimal.value, ll) != E_DEC_OK)
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+#endif
+ case DYN_COL_DATETIME:
+ *ll= (val->x.time_value.year * 10000000000ull +
+ val->x.time_value.month * 100000000L +
+ val->x.time_value.day * 1000000 +
+ val->x.time_value.hour * 10000 +
+ val->x.time_value.minute * 100 +
+ val->x.time_value.second) *
+ (val->x.time_value.neg ? -1 : 1);
+ break;
+ case DYN_COL_DATE:
+ *ll= (val->x.time_value.year * 10000 +
+ val->x.time_value.month * 100 +
+ val->x.time_value.day) *
+ (val->x.time_value.neg ? -1 : 1);
+ break;
+ case DYN_COL_TIME:
+ *ll= (val->x.time_value.hour * 10000 +
+ val->x.time_value.minute * 100 +
+ val->x.time_value.second) *
+ (val->x.time_value.neg ? -1 : 1);
+ break;
+ case DYN_COL_DYNCOL:
+ case DYN_COL_NULL:
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+ default:
+ return(ER_DYNCOL_FORMAT);
+ }
+ return(rc);
+}
+
+
+enum enum_dyncol_func_result
+mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val)
+{
+ enum enum_dyncol_func_result rc= ER_DYNCOL_OK;
+ *dbl= 0;
+ switch (val->type) {
+ case DYN_COL_INT:
+ *dbl= (double)val->x.long_value;
+ if (((longlong) *dbl) != val->x.long_value)
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+ case DYN_COL_UINT:
+ *dbl= (double)val->x.ulong_value;
+ if (((ulonglong) *dbl) != val->x.ulong_value)
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+ case DYN_COL_DOUBLE:
+ *dbl= val->x.double_value;
+ break;
+ case DYN_COL_STRING:
+ {
+ char *str, *end;
+ if (!(str= malloc(val->x.string.value.length + 1)))
+ return ER_DYNCOL_RESOURCE;
+ memcpy(str, val->x.string.value.str, val->x.string.value.length);
+ str[val->x.string.value.length]= '\0';
+ *dbl= strtod(str, &end);
+ if (*end != '\0')
+ rc= ER_DYNCOL_TRUNCATED;
+ free(str);
+ break;
+ }
+#ifndef LIBMARIADB
+ case DYN_COL_DECIMAL:
+ if (decimal2double(&val->x.decimal.value, dbl) != E_DEC_OK)
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+#endif
+ case DYN_COL_DATETIME:
+ *dbl= (double)(val->x.time_value.year * 10000000000ull +
+ val->x.time_value.month * 100000000L +
+ val->x.time_value.day * 1000000 +
+ val->x.time_value.hour * 10000 +
+ val->x.time_value.minute * 100 +
+ val->x.time_value.second) *
+ (val->x.time_value.neg ? -1 : 1);
+ break;
+ case DYN_COL_DATE:
+ *dbl= (double)(val->x.time_value.year * 10000 +
+ val->x.time_value.month * 100 +
+ val->x.time_value.day) *
+ (val->x.time_value.neg ? -1 : 1);
+ break;
+ case DYN_COL_TIME:
+ *dbl= (double)(val->x.time_value.hour * 10000 +
+ val->x.time_value.minute * 100 +
+ val->x.time_value.second) *
+ (val->x.time_value.neg ? -1 : 1);
+ break;
+ case DYN_COL_DYNCOL:
+ case DYN_COL_NULL:
+ rc= ER_DYNCOL_TRUNCATED;
+ break;
+ default:
+ return(ER_DYNCOL_FORMAT);
+ }
+ return(rc);
+}
+
+
+/**
+ Convert to JSON
+
+ @param str The packed string
+ @param json Where to put json result
+
+ @return ER_DYNCOL_* return code
+*/
+
+#define JSON_STACK_PROTECTION 10
+
+static enum enum_dyncol_func_result
+mariadb_dyncol_json_internal(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json,
+ uint lvl)
+{
+ DYN_HEADER header;
+ uint i;
+ enum enum_dyncol_func_result rc;
+
+ if (lvl >= JSON_STACK_PROTECTION)
+ {
+ rc= ER_DYNCOL_RESOURCE;
+ goto err;
+ }
+
+
+ if (str->length == 0)
+ return ER_DYNCOL_OK; /* no columns */
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ goto err;
+
+ if (header.entry_size * header.column_count + FIXED_HEADER_SIZE >
+ str->length)
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto err;
+ }
+
+ rc= ER_DYNCOL_RESOURCE;
+
+ if (ma_dynstr_append_mem(json, "{", 1))
+ goto err;
+ for (i= 0, header.entry= header.header;
+ i < header.column_count;
+ i++, header.entry+= header.entry_size)
+ {
+ DYNAMIC_COLUMN_VALUE val;
+ if (i != 0 && ma_dynstr_append_mem(json, ",", 1))
+ goto err;
+ header.length=
+ hdr_interval_length(&header, header.entry + header.entry_size);
+ header.data= header.dtpool + header.offset;
+ /*
+ Check that the found data is within the ranges. This can happen if
+ we get data with wrong offsets.
+ */
+ if (header.length == DYNCOL_OFFSET_ERROR ||
+ header.length > INT_MAX || header.offset > header.data_size)
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto err;
+ }
+ if ((rc= dynamic_column_get_value(&header, &val)) < 0)
+ goto err;
+ if (header.format == dyncol_fmt_num)
+ {
+ uint nm= uint2korr(header.entry);
+ if (ma_dynstr_realloc(json, DYNCOL_NUM_CHAR + 3))
+ goto err;
+ json->str[json->length++]= '"';
+ json->length+= snprintf(json->str + json->length,
+ DYNCOL_NUM_CHAR, "%u", nm);
+ }
+ else
+ {
+ LEX_STRING name;
+ if (read_name(&header, header.entry, &name))
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto err;
+ }
+ if (ma_dynstr_realloc(json, name.length + 3))
+ goto err;
+ json->str[json->length++]= '"';
+ memcpy(json->str + json->length, name.str, name.length);
+ json->length+= name.length;
+ }
+ json->str[json->length++]= '"';
+ json->str[json->length++]= ':';
+ if (val.type == DYN_COL_DYNCOL)
+ {
+ /* here we use it only for read so can cheat a bit */
+ DYNAMIC_COLUMN dc;
+ memset(&dc, 0, sizeof(dc));
+ dc.str= val.x.string.value.str;
+ dc.length= val.x.string.value.length;
+ if (mariadb_dyncol_json_internal(&dc, json, lvl + 1) < 0)
+ {
+ dc.str= NULL; dc.length= 0;
+ goto err;
+ }
+ dc.str= NULL; dc.length= 0;
+ }
+ else
+ {
+ if ((rc= mariadb_dyncol_val_str(json, &val,
+ ma_charset_utf8_general_ci, '"')) < 0)
+ goto err;
+ }
+ }
+ if (ma_dynstr_append_mem(json, "}", 1))
+ {
+ rc= ER_DYNCOL_RESOURCE;
+ goto err;
+ }
+ return ER_DYNCOL_OK;
+
+err:
+ json->length= 0;
+ return rc;
+}
+
+enum enum_dyncol_func_result
+mariadb_dyncol_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json)
+{
+
+ if (ma_init_dynamic_string(json, NULL, str->length * 2, 100))
+ return ER_DYNCOL_RESOURCE;
+
+ return mariadb_dyncol_json_internal(str, json, 1);
+}
+
+/**
+ Convert to DYNAMIC_COLUMN_VALUE values and names (LEX_STING) dynamic array
+
+ @param str The packed string
+ @param count number of elements in the arrays
+ @param names Where to put names (should be free by user)
+ @param vals Where to put values (should be free by user)
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_unpack(DYNAMIC_COLUMN *str,
+ uint *count,
+ LEX_STRING **names, DYNAMIC_COLUMN_VALUE **vals)
+{
+ DYN_HEADER header;
+ char *nm;
+ uint i;
+ enum enum_dyncol_func_result rc;
+
+ *count= 0; *names= 0; *vals= 0;
+
+ if (str->length == 0)
+ return ER_DYNCOL_OK; /* no columns */
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ return rc;
+
+
+ if (header.entry_size * header.column_count + FIXED_HEADER_SIZE >
+ str->length)
+ return ER_DYNCOL_FORMAT;
+
+ *vals= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE)* header.column_count);
+ if (header.format == dyncol_fmt_num)
+ {
+ *names= (LEX_STRING *)malloc(sizeof(LEX_STRING) * header.column_count +
+ DYNCOL_NUM_CHAR * header.column_count);
+ nm= (char *)((*names) + header.column_count);
+ }
+ else
+ {
+ *names= (LEX_STRING *)malloc(sizeof(LEX_STRING) * header.column_count);
+ nm= 0;
+ }
+ if (!(*vals) || !(*names))
+ {
+ rc= ER_DYNCOL_RESOURCE;
+ goto err;
+ }
+
+ for (i= 0, header.entry= header.header;
+ i < header.column_count;
+ i++, header.entry+= header.entry_size)
+ {
+ header.length=
+ hdr_interval_length(&header, header.entry + header.entry_size);
+ header.data= header.dtpool + header.offset;
+ /*
+ Check that the found data is within the ranges. This can happen if
+ we get data with wrong offsets.
+ */
+ if (header.length == DYNCOL_OFFSET_ERROR ||
+ header.length > INT_MAX || header.offset > header.data_size)
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto err;
+ }
+ if ((rc= dynamic_column_get_value(&header, (*vals) + i)) < 0)
+ goto err;
+
+ if (header.format == dyncol_fmt_num)
+ {
+ uint num= uint2korr(header.entry);
+ (*names)[i].str= nm;
+ (*names)[i].length= snprintf(nm, DYNCOL_NUM_CHAR, "%u", num);
+ nm+= (*names)[i].length + 1;
+ }
+ else
+ {
+ if (read_name(&header, header.entry, (*names) + i))
+ {
+ rc= ER_DYNCOL_FORMAT;
+ goto err;
+ }
+ }
+ }
+
+ *count= header.column_count;
+ return ER_DYNCOL_OK;
+
+err:
+ if (*vals)
+ {
+ free(*vals);
+ *vals= 0;
+ }
+ if (*names)
+ {
+ free(*names);
+ *names= 0;
+ }
+ return rc;
+}
+
+
+/**
+ Get not NULL column count
+
+ @param str The packed string
+ @param column_count Where to put column count
+
+ @return ER_DYNCOL_* return code
+*/
+
+enum enum_dyncol_func_result
+mariadb_dyncol_column_count(DYNAMIC_COLUMN *str, uint *column_count)
+{
+ DYN_HEADER header;
+ enum enum_dyncol_func_result rc;
+
+ (*column_count)= 0;
+ if (str->length == 0)
+ return ER_DYNCOL_OK;
+
+ if ((rc= init_read_hdr(&header, str)) < 0)
+ return rc;
+ *column_count= header.column_count;
+ return rc;
+}
+
+/**
+ Release dynamic column memory
+
+ @param str dynamic column
+ @return void
+*/
+void mariadb_dyncol_free(DYNAMIC_COLUMN *str)
+{
+ ma_dynstr_free(str);
+}
diff --git a/libmariadb/libmariadb/mariadb_lib.c b/libmariadb/libmariadb/mariadb_lib.c
new file mode 100644
index 00000000..e8db51a0
--- /dev/null
+++ b/libmariadb/libmariadb/mariadb_lib.c
@@ -0,0 +1,4979 @@
+/************************************************************************************
+ Copyright (C) 2000, 2012 MySQL AB & MySQL Finland AB & TCX DataKonsult AB,
+ Monty Program AB
+ 2013, 2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*************************************************************************************/
+
+#include <ma_global.h>
+
+#include <ma_sys.h>
+#include <ma_string.h>
+#include <mariadb_ctype.h>
+#include <ma_common.h>
+#include "ma_priv.h"
+#include "ma_context.h"
+#include "mysql.h"
+#include "mariadb_version.h"
+#include "ma_server_error.h"
+#include <mariadb/ma_io.h>
+#include "errmsg.h"
+#include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <mariadb_dyncol.h>
+#include <mariadb_rpl.h>
+
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#if !defined(_WIN32)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#ifdef HAVE_SELECT_H
+# include <select.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+#include <ma_sha1.h>
+#ifndef _WIN32
+#include <poll.h>
+#endif
+#include <ma_pvio.h>
+#ifdef HAVE_TLS
+#include <ma_tls.h>
+#endif
+#include <mysql/client_plugin.h>
+#ifdef _WIN32
+#include "shlwapi.h"
+#include "ws2tcpip.h"
+#define strncasecmp _strnicmp
+#endif
+
+#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
+#define MA_RPL_VERSION_HACK "5.5.5-"
+
+#define CHARSET_NAME_LEN 64
+
+#undef max_allowed_packet
+#undef net_buffer_length
+extern ulong max_allowed_packet; /* net.c */
+extern ulong net_buffer_length; /* net.c */
+
+static MYSQL_PARAMETERS mariadb_internal_parameters= {&max_allowed_packet, &net_buffer_length, 0};
+static my_bool mysql_client_init=0;
+static void mysql_close_options(MYSQL *mysql);
+static void ma_clear_session_state(MYSQL *mysql);
+static int parse_connection_string(MYSQL *mysql, const char *unused, const char *conn_str, ssize_t len);
+extern void release_configuration_dirs();
+extern char **get_default_configuration_dirs();
+extern my_bool ma_init_done;
+extern my_bool mysql_ps_subsystem_initialized;
+extern my_bool mysql_handle_local_infile(MYSQL *mysql, const char *filename, my_bool can_local_infile);
+extern const MARIADB_CHARSET_INFO * mysql_find_charset_nr(uint charsetnr);
+extern const MARIADB_CHARSET_INFO * mysql_find_charset_name(const char * const name);
+extern my_bool set_default_charset_by_name(const char *cs_name, myf flags __attribute__((unused)));
+extern int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ const char *data_plugin, const char *db);
+extern int net_add_multi_command(NET *net, uchar command, const uchar *packet,
+ size_t length);
+extern unsigned char* ma_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *request_len, my_bool internal);
+
+extern LIST *pvio_callback;
+
+/* prepare statement methods from my_stmt.c */
+extern my_bool mthd_supported_buffer_type(enum enum_field_types type);
+extern my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt);
+extern my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt);
+extern my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt);
+extern int mthd_stmt_read_execute_response(MYSQL_STMT *stmt);
+extern int mthd_stmt_fetch_row(MYSQL_STMT *stmt, unsigned char **row);
+extern int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row);
+extern int mthd_stmt_read_all_rows(MYSQL_STMT *stmt);
+extern void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt);
+extern my_bool _mariadb_read_options(MYSQL *mysql, const char *dir, const char *config_file, const char *group, unsigned int recursion);
+extern unsigned char *mysql_net_store_length(unsigned char *packet, ulonglong length);
+
+extern void
+my_context_install_suspend_resume_hook(struct mysql_async_context *b,
+ void (*hook)(my_bool, void *),
+ void *user_data);
+
+uint mysql_port=0;
+my_string mysql_unix_port=0;
+
+#define CONNECT_TIMEOUT 0
+
+struct st_mariadb_methods MARIADB_DEFAULT_METHODS;
+
+#if defined(_WIN32)
+// socket_errno is defined in ma_global.h for all platforms
+#define perror(A)
+#else
+#include <errno.h>
+#define SOCKET_ERROR -1
+#endif /* _WIN32 */
+
+#include <mysql/client_plugin.h>
+
+#define IS_CONNHDLR_ACTIVE(mysql)\
+ ((mysql)->extension && (mysql)->extension->conn_hdlr)
+
+static void end_server(MYSQL *mysql);
+static void mysql_close_memory(MYSQL *mysql);
+void read_user_name(char *name);
+my_bool STDCALL mariadb_reconnect(MYSQL *mysql);
+static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length);
+
+extern int mysql_client_plugin_init();
+extern void mysql_client_plugin_deinit();
+
+/* net_get_error */
+void net_get_error(char *buf, size_t buf_len,
+ char *error, size_t error_len,
+ unsigned int *error_no,
+ char *sqlstate)
+{
+ char *p= buf;
+ size_t error_msg_len= 0;
+
+ if (buf_len > 2)
+ {
+ *error_no= uint2korr(p);
+ p+= 2;
+
+ /* since 4.1 sqlstate is following */
+ if (*p == '#')
+ {
+ memcpy(sqlstate, ++p, SQLSTATE_LENGTH);
+ p+= SQLSTATE_LENGTH;
+ }
+ error_msg_len= buf_len - (p - buf);
+ error_msg_len= MIN(error_msg_len, error_len - 1);
+ memcpy(error, p, error_msg_len);
+ }
+ else
+ {
+ *error_no= CR_UNKNOWN_ERROR;
+ memcpy(sqlstate, SQLSTATE_UNKNOWN, SQLSTATE_LENGTH);
+ }
+}
+
+/*****************************************************************************
+** read a packet from server. Give error message if socket was down
+** or packet is an error message
+*****************************************************************************/
+
+ulong
+ma_net_safe_read(MYSQL *mysql)
+{
+ NET *net= &mysql->net;
+ ulong len=0;
+
+restart:
+ if (net->pvio != 0)
+ len=ma_net_read(net);
+
+ if (len == packet_error || len == 0)
+ {
+ end_server(mysql);
+#ifdef HAVE_TLS
+ /* don't overwrite possible tls protocol errors */
+ if (net->last_errno != CR_SSL_CONNECTION_ERROR)
+#endif
+ {
+ my_set_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
+ CR_NET_PACKET_TOO_LARGE:
+ CR_SERVER_LOST,
+ SQLSTATE_UNKNOWN, 0, errno);
+ }
+ return(packet_error);
+ }
+ if (net->read_pos[0] == 255)
+ {
+ if (len > 3)
+ {
+ char *pos=(char*) net->read_pos+1;
+ uint last_errno=uint2korr(pos);
+ pos+=2;
+ len-=2;
+
+ if (last_errno== 65535 &&
+ ((mariadb_connection(mysql) && (mysql->server_capabilities & CLIENT_PROGRESS)) ||
+ (!(mysql->extension->mariadb_server_capabilities & MARIADB_CLIENT_PROGRESS << 32))))
+ {
+ if (cli_report_progress(mysql, (uchar *)pos, (uint) (len-1)))
+ {
+ /* Wrong packet */
+ my_set_error(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
+ return (packet_error);
+ }
+ goto restart;
+ }
+ net->last_errno= last_errno;
+ if (pos[0]== '#')
+ {
+ ma_strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
+ pos+= SQLSTATE_LENGTH + 1;
+ }
+ else
+ {
+ strncpy(net->sqlstate, SQLSTATE_UNKNOWN, SQLSTATE_LENGTH);
+ }
+ ma_strmake(net->last_error,(char*) pos,
+ min(len,sizeof(net->last_error)-1));
+ }
+ else
+ {
+ my_set_error(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
+ }
+
+ mysql->server_status&= ~SERVER_MORE_RESULTS_EXIST;
+
+ return(packet_error);
+ }
+ return len;
+}
+
+/*
+ Report progress to the client
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length)
+{
+ uint stage, max_stage, proc_length;
+ double progress;
+ uchar *start= packet;
+
+ if (length < 5)
+ return 1; /* Wrong packet */
+
+ if (!(mysql->options.extension && mysql->options.extension->report_progress))
+ return 0; /* No callback, ignore packet */
+
+ packet++; /* Ignore number of strings */
+ stage= (uint) *packet++;
+ max_stage= (uint) *packet++;
+ progress= uint3korr(packet)/1000.0;
+ packet+= 3;
+ proc_length= net_field_length(&packet);
+ if (packet + proc_length > start + length)
+ return 1; /* Wrong packet */
+ (*mysql->options.extension->report_progress)(mysql, stage, max_stage,
+ progress, (char*) packet,
+ proc_length);
+ return 0;
+}
+
+/* Get the length of next field. Change parameter to point at fieldstart */
+ulong
+net_field_length(uchar **packet)
+{
+ reg1 uchar *pos= *packet;
+ if (*pos < 251)
+ {
+ (*packet)++;
+ return (ulong) *pos;
+ }
+ if (*pos == 251)
+ {
+ (*packet)++;
+ return NULL_LENGTH;
+ }
+ if (*pos == 252)
+ {
+ (*packet)+=3;
+ return (ulong) uint2korr(pos+1);
+ }
+ if (*pos == 253)
+ {
+ (*packet)+=4;
+ return (ulong) uint3korr(pos+1);
+ }
+ (*packet)+=9; /* Must be 254 when here */
+ return (ulong) uint4korr(pos+1);
+}
+
+/* Same as above, but returns ulonglong values */
+
+static unsigned long long
+net_field_length_ll(uchar **packet)
+{
+ reg1 uchar *pos= *packet;
+ if (*pos < 251)
+ {
+ (*packet)++;
+ return (unsigned long long) *pos;
+ }
+ if (*pos == 251)
+ {
+ (*packet)++;
+ return (unsigned long long) NULL_LENGTH;
+ }
+ if (*pos == 252)
+ {
+ (*packet)+=3;
+ return (unsigned long long) uint2korr(pos+1);
+ }
+ if (*pos == 253)
+ {
+ (*packet)+=4;
+ return (unsigned long long) uint3korr(pos+1);
+ }
+ (*packet)+=9; /* Must be 254 when here */
+#ifdef NO_CLIENT_LONGLONG
+ return (unsigned long long) uint4korr(pos+1);
+#else
+ return (unsigned long long) uint8korr(pos+1);
+#endif
+}
+
+
+void free_rows(MYSQL_DATA *cur)
+{
+ if (cur)
+ {
+ ma_free_root(&cur->alloc,MYF(0));
+ free(cur);
+ }
+}
+
+int
+mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ size_t length, my_bool skip_check, void *opt_arg)
+{
+ NET *net= &mysql->net;
+ int result= -1;
+ if (mysql->net.pvio == 0)
+ {
+ /* Do reconnect if possible */
+ if (mariadb_reconnect(mysql))
+ return(1);
+ }
+ if (mysql->status != MYSQL_STATUS_READY ||
+ mysql->server_status & SERVER_MORE_RESULTS_EXIST)
+ {
+ SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+
+ if (IS_CONNHDLR_ACTIVE(mysql))
+ {
+ result= mysql->extension->conn_hdlr->plugin->set_connection(mysql, command, arg, length, skip_check, opt_arg);
+ if (result== -1)
+ return(result);
+ }
+
+ CLEAR_CLIENT_ERROR(mysql);
+
+ if (command == COM_QUERY ||
+ command == COM_STMT_PREPARE)
+ {
+ if ((mysql->options.client_flag & CLIENT_LOCAL_FILES) &&
+ mysql->options.extension && mysql->extension->auto_local_infile == WAIT_FOR_QUERY &&
+ arg && (*arg == 'l' || *arg == 'L'))
+ {
+ if (strncasecmp(arg, "load", 4) == 0)
+ mysql->extension->auto_local_infile= ACCEPT_FILE_REQUEST;
+ }
+ }
+
+ mysql->info=0;
+ mysql->affected_rows= ~(unsigned long long) 0;
+ ma_net_clear(net); /* Clear receive buffer */
+ if (!arg)
+ arg="";
+
+ if (net->extension->multi_status== COM_MULTI_ENABLED)
+ {
+ return net_add_multi_command(net, command, (const uchar *)arg, length);
+ }
+
+ if (ma_net_write_command(net,(uchar) command,arg,
+ length ? length : (ulong) strlen(arg), 0))
+ {
+ if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
+ {
+ my_set_error(mysql, CR_NET_PACKET_TOO_LARGE, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ end_server(mysql);
+ if (mariadb_reconnect(mysql))
+ goto end;
+ if (ma_net_write_command(net,(uchar) command,arg,
+ length ? length : (ulong) strlen(arg), 0))
+ {
+ my_set_error(mysql, CR_SERVER_GONE_ERROR, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ }
+ result=0;
+
+ if (net->extension->multi_status > COM_MULTI_OFF)
+ skip_check= 1;
+
+ if (!skip_check)
+ {
+ result= ((mysql->packet_length=ma_net_safe_read(mysql)) == packet_error ?
+ 1 : 0);
+ }
+ end:
+ return(result);
+}
+
+int
+ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ size_t length, my_bool skip_check, void *opt_arg)
+{
+ return mysql->methods->db_command(mysql, command, arg, length, skip_check, opt_arg);
+}
+
+int ma_multi_command(MYSQL *mysql, enum enum_multi_status status)
+{
+ NET *net= &mysql->net;
+
+ switch (status) {
+ case COM_MULTI_OFF:
+ ma_net_clear(net);
+ net->extension->multi_status= status;
+ return 0;
+ case COM_MULTI_ENABLED:
+ if (net->extension->multi_status > COM_MULTI_DISABLED)
+ return 1;
+ ma_net_clear(net);
+ net->extension->multi_status= status;
+ return 0;
+ case COM_MULTI_DISABLED:
+ /* Opposite to COM_MULTI_OFF we don't clear net buffer,
+ next command or com_nulti_end will flush entire buffer */
+ net->extension->multi_status= status;
+ return 0;
+ case COM_MULTI_END:
+ {
+ size_t len= net->write_pos - net->buff - NET_HEADER_SIZE;
+
+ if (len < NET_HEADER_SIZE) /* don't send empty request */
+ {
+ ma_net_clear(net);
+ return 1;
+ }
+ net->extension->multi_status= COM_MULTI_OFF;
+ return ma_net_flush(net);
+ }
+ case COM_MULTI_CANCEL:
+ ma_net_clear(net);
+ net->extension->multi_status= COM_MULTI_OFF;
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+static void free_old_query(MYSQL *mysql)
+{
+ if (mysql->fields)
+ ma_free_root(&mysql->field_alloc,MYF(0));
+ ma_init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */
+ mysql->fields=0;
+ mysql->field_count=0; /* For API */
+ mysql->info= 0;
+ return;
+}
+
+#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
+struct passwd *getpwuid(uid_t);
+char* getlogin(void);
+#endif
+
+#if !defined(_WIN32)
+void read_user_name(char *name)
+{
+ if (geteuid() == 0)
+ strcpy(name,"root"); /* allow use of surun */
+ else
+ {
+#ifdef HAVE_GETPWUID
+ struct passwd *skr;
+ const char *str;
+ if ((skr=getpwuid(geteuid())) != NULL)
+ {
+ str=skr->pw_name;
+ } else if ((str=getlogin()) == NULL)
+ {
+ if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
+ !(str=getenv("LOGIN")))
+ str="UNKNOWN_USER";
+ }
+ ma_strmake(name,str,USERNAME_LENGTH);
+#elif defined(HAVE_CUSERID)
+ (void) cuserid(name);
+#else
+ ma_strmake(name,"UNKNOWN_USER", USERNAME_LENGTH);
+#endif
+ }
+ return;
+}
+
+#else /* WIN32 */
+
+void read_user_name(char *name)
+{
+ char *str=getenv("USERNAME"); /* ODBC will send user variable */
+ ma_strmake(name,str ? str : "ODBC", USERNAME_LENGTH);
+}
+
+#endif
+
+
+/**************************************************************************
+** Shut down connection
+**************************************************************************/
+
+static void
+end_server(MYSQL *mysql)
+{
+ /* if net->error 2 and reconnect is activated, we need to inform
+ connection handler */
+ if (mysql->net.pvio != 0)
+ {
+ ma_pvio_close(mysql->net.pvio);
+ mysql->net.pvio= 0; /* Marker */
+ }
+ ma_net_end(&mysql->net);
+ free_old_query(mysql);
+ return;
+}
+
+void mthd_my_skip_result(MYSQL *mysql)
+{
+ ulong pkt_len;
+
+ do {
+ pkt_len= ma_net_safe_read(mysql);
+ if (pkt_len == packet_error)
+ break;
+ } while (pkt_len > 8 || mysql->net.read_pos[0] != 254);
+ return;
+}
+
+void STDCALL
+mysql_free_result(MYSQL_RES *result)
+{
+ if (result)
+ {
+ if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
+ {
+ result->handle->methods->db_skip_result(result->handle);
+ result->handle->status=MYSQL_STATUS_READY;
+ }
+ free_rows(result->data);
+ if (result->fields)
+ ma_free_root(&result->field_alloc,MYF(0));
+ if (result->row)
+ free(result->row);
+ free(result);
+ }
+ return;
+}
+
+
+/****************************************************************************
+** Get options from my.cnf
+****************************************************************************/
+enum enum_option_type {
+ MARIADB_OPTION_NONE,
+ MARIADB_OPTION_BOOL,
+ MARIADB_OPTION_INT,
+ MARIADB_OPTION_SIZET,
+ MARIADB_OPTION_STR,
+ MARIADB_OPTION_FUNC,
+};
+
+struct st_default_options {
+ union {
+ enum mysql_option option;
+ int (*option_func)(MYSQL *mysql, const char *key, const char *value, ssize_t len);
+ } u;
+ enum enum_option_type type;
+ const char *conf_key;
+};
+
+struct st_default_options mariadb_defaults[] =
+{
+ {{MARIADB_OPT_PORT}, MARIADB_OPTION_INT,"port"},
+ {{MARIADB_OPT_UNIXSOCKET}, MARIADB_OPTION_STR, "socket"},
+ {{MYSQL_OPT_COMPRESS}, MARIADB_OPTION_BOOL, "compress"},
+ {{MARIADB_OPT_PASSWORD}, MARIADB_OPTION_STR, "password"},
+ {{MYSQL_OPT_NAMED_PIPE}, MARIADB_OPTION_BOOL, "pipe"},
+ {{MYSQL_OPT_CONNECT_TIMEOUT}, MARIADB_OPTION_INT, "timeout"},
+ {{MARIADB_OPT_USER}, MARIADB_OPTION_STR, "user"},
+ {{MYSQL_INIT_COMMAND}, MARIADB_OPTION_STR, "init-command"},
+ {{MARIADB_OPT_HOST}, MARIADB_OPTION_STR, "host"},
+ {{MARIADB_OPT_SCHEMA}, MARIADB_OPTION_STR, "database"},
+ {{MARIADB_OPT_DEBUG}, MARIADB_OPTION_STR, "debug"},
+ {{MARIADB_OPT_FOUND_ROWS}, MARIADB_OPTION_NONE, "return-found-rows"},
+ {{MYSQL_OPT_SSL_KEY}, MARIADB_OPTION_STR, "ssl-key"},
+ {{MYSQL_OPT_SSL_CERT}, MARIADB_OPTION_STR,"ssl-cert"},
+ {{MYSQL_OPT_SSL_CA}, MARIADB_OPTION_STR,"ssl-ca"},
+ {{MYSQL_OPT_SSL_CAPATH}, MARIADB_OPTION_STR,"ssl-capath"},
+ {{MYSQL_OPT_SSL_CRL}, MARIADB_OPTION_STR,"ssl-crl"},
+ {{MYSQL_OPT_SSL_CRLPATH}, MARIADB_OPTION_STR,"ssl-crlpath"},
+ {{MYSQL_OPT_SSL_VERIFY_SERVER_CERT}, MARIADB_OPTION_BOOL,"ssl-verify-server-cert"},
+ {{MYSQL_SET_CHARSET_DIR}, MARIADB_OPTION_STR, "character-sets-dir"},
+ {{MYSQL_SET_CHARSET_NAME}, MARIADB_OPTION_STR, "default-character-set"},
+ {{MARIADB_OPT_INTERACTIVE}, MARIADB_OPTION_NONE, "interactive-timeout"},
+ {{MYSQL_OPT_CONNECT_TIMEOUT}, MARIADB_OPTION_INT, "connect-timeout"},
+ {{MYSQL_OPT_LOCAL_INFILE}, MARIADB_OPTION_BOOL, "local-infile"},
+ {{0}, 0 ,"disable-local-infile",},
+ {{MYSQL_OPT_SSL_CIPHER}, MARIADB_OPTION_STR, "ssl-cipher"},
+ {{MYSQL_OPT_MAX_ALLOWED_PACKET}, MARIADB_OPTION_SIZET, "max-allowed-packet"},
+ {{MYSQL_OPT_NET_BUFFER_LENGTH}, MARIADB_OPTION_SIZET, "net-buffer-length"},
+ {{MYSQL_OPT_PROTOCOL}, MARIADB_OPTION_INT, "protocol"},
+ {{MYSQL_SHARED_MEMORY_BASE_NAME}, MARIADB_OPTION_STR,"shared-memory-base-name"},
+ {{MARIADB_OPT_MULTI_RESULTS}, MARIADB_OPTION_BOOL, "multi-results"},
+ {{MARIADB_OPT_MULTI_STATEMENTS}, MARIADB_OPTION_BOOL, "multi-statements"},
+ {{MARIADB_OPT_MULTI_STATEMENTS}, MARIADB_OPTION_BOOL, "multi-queries"},
+ {{MYSQL_SECURE_AUTH}, MARIADB_OPTION_BOOL, "secure-auth"},
+ {{MYSQL_REPORT_DATA_TRUNCATION}, MARIADB_OPTION_BOOL, "report-data-truncation"},
+ {{MYSQL_OPT_RECONNECT}, MARIADB_OPTION_BOOL, "reconnect"},
+ {{MYSQL_PLUGIN_DIR}, MARIADB_OPTION_STR, "plugin-dir"},
+ {{MYSQL_DEFAULT_AUTH}, MARIADB_OPTION_STR, "default-auth"},
+ {{MARIADB_OPT_SSL_FP}, MARIADB_OPTION_STR, "ssl-fp"},
+ {{MARIADB_OPT_SSL_FP_LIST}, MARIADB_OPTION_STR, "ssl-fp-list"},
+ {{MARIADB_OPT_SSL_FP_LIST}, MARIADB_OPTION_STR, "ssl-fplist"},
+ {{MARIADB_OPT_TLS_PASSPHRASE}, MARIADB_OPTION_STR, "ssl-passphrase"},
+ {{MARIADB_OPT_TLS_VERSION}, MARIADB_OPTION_STR, "tls-version"},
+ {{MYSQL_SERVER_PUBLIC_KEY}, MARIADB_OPTION_STR, "server-public-key"},
+ {{MYSQL_OPT_BIND}, MARIADB_OPTION_STR, "bind-address"},
+ {{MYSQL_OPT_SSL_ENFORCE}, MARIADB_OPTION_BOOL, "ssl-enforce"},
+ {{MARIADB_OPT_RESTRICTED_AUTH}, MARIADB_OPTION_STR, "restricted-auth"},
+ {{.option_func=parse_connection_string}, MARIADB_OPTION_FUNC, "connection"},
+ /* Aliases */
+ {{MARIADB_OPT_SCHEMA}, MARIADB_OPTION_STR, "db"},
+ {{MARIADB_OPT_UNIXSOCKET}, MARIADB_OPTION_STR, "unix_socket"},
+ {{MARIADB_OPT_HOST}, MARIADB_OPTION_STR, "servername"},
+ {{MARIADB_OPT_PASSWORD}, MARIADB_OPTION_STR, "passwd"},
+ {{MARIADB_OPT_SSL_FP}, MARIADB_OPTION_STR, "tls-fp"},
+ {{MARIADB_OPT_SSL_FP_LIST}, MARIADB_OPTION_STR, "tls-fplist"},
+ {{MYSQL_OPT_SSL_KEY}, MARIADB_OPTION_STR, "tls-key"},
+ {{MYSQL_OPT_SSL_CERT}, MARIADB_OPTION_STR,"tls-cert"},
+ {{MYSQL_OPT_SSL_CA}, MARIADB_OPTION_STR,"tls-ca"},
+ {{MYSQL_OPT_SSL_CAPATH}, MARIADB_OPTION_STR,"tls-capath"},
+ {{MYSQL_OPT_SSL_CRL}, MARIADB_OPTION_STR,"tls-crl"},
+ {{MYSQL_OPT_SSL_CRLPATH}, MARIADB_OPTION_STR,"tls-crlpath"},
+ {{MYSQL_OPT_SSL_CIPHER}, MARIADB_OPTION_STR, "tls-cipher"},
+ {{MARIADB_OPT_TLS_PASSPHRASE}, MARIADB_OPTION_STR, "tls-passphrase"},
+ {{MYSQL_OPT_SSL_ENFORCE}, MARIADB_OPTION_BOOL, "tls-enforce"},
+ {{MYSQL_OPT_SSL_VERIFY_SERVER_CERT}, MARIADB_OPTION_BOOL,"tls-verify-peer"},
+ {{0}, 0, NULL}
+};
+
+#define CHECK_OPT_EXTENSION_SET(OPTS)\
+ if (!(OPTS)->extension) \
+ (OPTS)->extension= (struct st_mysql_options_extension *) \
+ calloc(1, sizeof(struct st_mysql_options_extension));
+
+#define OPT_SET_EXTENDED_VALUE_BIN(OPTS, KEY, KEY_LEN, VAL, LEN)\
+ CHECK_OPT_EXTENSION_SET(OPTS) \
+ free((gptr)(OPTS)->extension->KEY); \
+ if((VAL) && (LEN)) { \
+ if (((OPTS)->extension->KEY= malloc((LEN)))) { \
+ memcpy((OPTS)->extension->KEY, (VAL), (LEN)); \
+ (OPTS)->extension->KEY_LEN= (LEN); \
+ } \
+ } \
+ else \
+ (OPTS)->extension->KEY= NULL
+
+#define OPT_SET_EXTENDED_VALUE_STR(OPTS, KEY, VAL) \
+ CHECK_OPT_EXTENSION_SET(OPTS) \
+ free((gptr)(OPTS)->extension->KEY); \
+ if((VAL)) \
+ (OPTS)->extension->KEY= strdup((char *)(VAL)); \
+ else \
+ (OPTS)->extension->KEY= NULL
+
+#define OPT_SET_EXTENDED_VALUE(OPTS, KEY, VAL) \
+ CHECK_OPT_EXTENSION_SET(OPTS) \
+ (OPTS)->extension->KEY= (VAL)
+
+#define OPT_SET_EXTENDED_VALUE_INT(A,B,C) OPT_SET_EXTENDED_VALUE(A,B,C)
+
+#define OPT_SET_VALUE_STR(OPTS, KEY, VAL) \
+ free((OPTS)->KEY); \
+ if((VAL)) \
+ (OPTS)->KEY= strdup((char *)(VAL)); \
+ else \
+ (OPTS)->KEY= NULL
+
+#define OPT_SET_VALUE_INT(OPTS, KEY, VAL) \
+ (OPTS)->KEY= (VAL)
+
+static void options_add_initcommand(struct st_mysql_options *options,
+ const char *init_cmd)
+{
+ char *insert= strdup(init_cmd);
+ if (!options->init_command)
+ {
+ options->init_command= (DYNAMIC_ARRAY*)malloc(sizeof(DYNAMIC_ARRAY));
+ ma_init_dynamic_array(options->init_command, sizeof(char*), 5, 5);
+ }
+
+ if (ma_insert_dynamic(options->init_command, (gptr)&insert))
+ free(insert);
+}
+my_bool _mariadb_set_conf_option(MYSQL *mysql, const char *config_option, const char *config_value)
+{
+ if (config_option)
+ {
+ int i;
+ char *c;
+
+ /* CONC-395: replace underscore "_" by dash "-" */
+ while ((c= strchr(config_option, '_')))
+ *c= '-';
+
+ for (i=0; mariadb_defaults[i].conf_key; i++)
+ {
+ if (!strcmp(mariadb_defaults[i].conf_key, config_option))
+ {
+ my_bool val_bool;
+ int val_int;
+ size_t val_sizet;
+ int rc;
+ void *option_val= NULL;
+ switch (mariadb_defaults[i].type) {
+ case MARIADB_OPTION_FUNC:
+ return mariadb_defaults[i].u.option_func(mysql, config_option, config_value, -1);
+ break;
+ case MARIADB_OPTION_BOOL:
+ val_bool= 0;
+ if (config_value)
+ val_bool= atoi(config_value);
+ option_val= &val_bool;
+ break;
+ case MARIADB_OPTION_INT:
+ val_int= 0;
+ if (config_value)
+ val_int= atoi(config_value);
+ option_val= &val_int;
+ break;
+ case MARIADB_OPTION_SIZET:
+ val_sizet= 0;
+ if (config_value)
+ val_sizet= strtol(config_value, NULL, 10);
+ option_val= &val_sizet;
+ break;
+ case MARIADB_OPTION_STR:
+ option_val= (void*)config_value;
+ break;
+ case MARIADB_OPTION_NONE:
+ break;
+ }
+ rc= mysql_optionsv(mysql, mariadb_defaults[i].u.option, option_val);
+ return(test(rc));
+ }
+ }
+ }
+ /* unknown key */
+ return 1;
+}
+
+/**
+ * @brief: simple connection string parser
+ *
+ * key/value pairs (or key only) are separated by semicolons.
+ * If a semicolon is part of a value, it must be enclosed in
+ * curly braces.
+ *
+ * Unknown keys will be ignored.
+ */
+static int parse_connection_string(MYSQL *mysql, const char *unused __attribute__((unused)),
+ const char *conn_str, ssize_t len)
+{
+ char *conn_save,
+ *end, *pos,
+ *key= NULL, *val= NULL;
+ my_bool in_curly_brace= 0;
+
+ if (len == -1)
+ len= strlen(conn_str);
+
+ /* don't modify original dsn */
+ conn_save= (char *)malloc(len + 1);
+ memcpy(conn_save, conn_str, len);
+ conn_save[len]= 0;
+
+ /* start and end */
+ pos= conn_save;
+ end= conn_save + len;
+
+ while (pos <= end)
+ {
+ /* ignore white space, unless it is between curly braces */
+ if (isspace(*pos) && !in_curly_brace)
+ {
+ pos++;
+ continue;
+ }
+
+ switch (*pos) {
+ case '{':
+ if (!key)
+ goto error;
+ if (!in_curly_brace)
+ {
+ in_curly_brace= 1;
+ if (pos < end)
+ {
+ pos++;
+ val= pos;
+ continue;
+ }
+ }
+ break;
+ case '}':
+ if (in_curly_brace)
+ {
+ if (!key)
+ goto error;
+ if (pos < end && *(pos + 1) == '}')
+ {
+ memmove(pos, pos + 1, end - pos - 1);
+ end--;
+ pos += 2;
+ continue;
+ }
+ if (in_curly_brace)
+ in_curly_brace= 0;
+ else
+ goto error;
+ *pos++= 0;
+ continue;
+ }
+ break;
+ case '=':
+ if (in_curly_brace)
+ {
+ pos++;
+ continue;
+ }
+ if (!key)
+ goto error;
+ *pos++= 0;
+ if (pos < end)
+ val= pos;
+ continue;
+ break;
+ case ';':
+ if (in_curly_brace)
+ {
+ pos++;
+ continue;
+ }
+ if (!key)
+ goto error;
+ *pos++= 0;
+ if (key && strcasecmp(key, "connection") != 0)
+ _mariadb_set_conf_option(mysql, key, val);
+ key= val= NULL;
+ continue;
+ break;
+ }
+ if (!key && *pos)
+ key= pos;
+ pos++;
+ }
+ if (key && strcasecmp(key, "connection") != 0)
+ _mariadb_set_conf_option(mysql, key, val);
+ free(conn_save);
+ return 0;
+
+error:
+ my_set_error(mysql, CR_CONNSTR_PARSE_ERROR, SQLSTATE_UNKNOWN, 0, pos - conn_save);
+ free(conn_save);
+ return 1;
+}
+
+
+static MARIADB_CONST_STRING null_const_string= {0,0};
+
+/***************************************************************************
+** Allocate a string copy on memroot
+***************************************************************************/
+static MARIADB_CONST_STRING ma_const_string_copy_root(MA_MEM_ROOT *memroot,
+ const char *str,
+ size_t length)
+{
+ MARIADB_CONST_STRING res;
+ if (!str || !(res.str= ma_memdup_root(memroot, str, length)))
+ return null_const_string;
+ res.length= length;
+ return res;
+}
+
+
+/***************************************************************************
+** Allocate and initialize MA_FIELD_EXTENSION
+***************************************************************************/
+MA_FIELD_EXTENSION *new_ma_field_extension(MA_MEM_ROOT *memroot)
+{
+ MA_FIELD_EXTENSION *ext= ma_alloc_root(memroot, sizeof(MA_FIELD_EXTENSION));
+ if (ext)
+ memset((void *) ext, 0, sizeof(*ext));
+ return ext;
+}
+
+
+/***************************************************************************
+** Populate field extension from a type info packet
+***************************************************************************/
+
+static void ma_field_extension_init_type_info(MA_MEM_ROOT *memroot,
+ MA_FIELD_EXTENSION *ext,
+ const char *ptr, size_t length)
+{
+ const char *end= ptr + length;
+ for ( ; ptr < end; )
+ {
+ uint itype= (uchar) *ptr++;
+ uint len= (uchar) *ptr++;
+ if (ptr + len > end || len > 127)
+ break; /*Badly encoded data*/
+ if (itype <= 127 && itype <= MARIADB_FIELD_ATTR_LAST)
+ ext->metadata[itype]= ma_const_string_copy_root(memroot, ptr, len);
+ ptr+= len;
+ }
+}
+
+
+/***************************************************************************
+** Allocate a field extension deep copy
+***************************************************************************/
+
+MA_FIELD_EXTENSION *ma_field_extension_deep_dup(MA_MEM_ROOT *memroot,
+ const MA_FIELD_EXTENSION *from)
+{
+ MA_FIELD_EXTENSION *ext= new_ma_field_extension(memroot);
+ uint i;
+ if (!ext)
+ return NULL;
+ for (i= 0; i < MARIADB_FIELD_ATTR_LAST; i++)
+ {
+ if (from->metadata[i].str)
+ ext->metadata[i]= ma_const_string_copy_root(memroot,
+ from->metadata[i].str,
+ from->metadata[i].length);
+ }
+ return ext;
+}
+
+/***************************************************************************
+** Change field rows to field structs
+***************************************************************************/
+
+static size_t rset_field_offsets[]= {
+ OFFSET(MYSQL_FIELD, catalog),
+ OFFSET(MYSQL_FIELD, catalog_length),
+ OFFSET(MYSQL_FIELD, db),
+ OFFSET(MYSQL_FIELD, db_length),
+ OFFSET(MYSQL_FIELD, table),
+ OFFSET(MYSQL_FIELD, table_length),
+ OFFSET(MYSQL_FIELD, org_table),
+ OFFSET(MYSQL_FIELD, org_table_length),
+ OFFSET(MYSQL_FIELD, name),
+ OFFSET(MYSQL_FIELD, name_length),
+ OFFSET(MYSQL_FIELD, org_name),
+ OFFSET(MYSQL_FIELD, org_name_length)
+};
+
+MYSQL_FIELD *
+unpack_fields(const MYSQL *mysql,
+ MYSQL_DATA *data, MA_MEM_ROOT *alloc, uint fields,
+ my_bool default_value)
+{
+ MYSQL_ROWS *row;
+ MYSQL_FIELD *field,*result;
+ char *p;
+ unsigned int i, field_count= sizeof(rset_field_offsets)/sizeof(size_t)/2;
+
+ field=result=(MYSQL_FIELD*) ma_alloc_root(alloc,sizeof(MYSQL_FIELD)*fields);
+ if (!result)
+ return(0);
+
+ for (row=data->data; row ; row = row->next,field++)
+ {
+ if (field >= result + fields)
+ goto error;
+
+ for (i=0; i < field_count; i++)
+ {
+ uint length= (uint)(row->data[i+1] - row->data[i] - 1);
+ if (!row->data[i] || row->data[i][length])
+ goto error;
+
+ *(char **)(((char *)field) + rset_field_offsets[i*2])=
+ ma_strdup_root(alloc, (char *)row->data[i]);
+ *(unsigned int *)(((char *)field) + rset_field_offsets[i*2+1])= length;
+ }
+
+ field->extension= NULL;
+ if (ma_has_extended_type_info(mysql))
+ {
+ if (row->data[i+1] - row->data[i] > 1)
+ {
+ size_t len= row->data[i+1] - row->data[i] - 1;
+ MA_FIELD_EXTENSION *ext= new_ma_field_extension(alloc);
+ if ((field->extension= ext))
+ ma_field_extension_init_type_info(alloc, ext, row->data[i], len);
+ }
+ i++;
+ }
+
+ p= (char *)row->data[i];
+ /* filler */
+ field->charsetnr= uint2korr(p);
+ p+= 2;
+ field->length= (uint) uint4korr(p);
+ p+= 4;
+ field->type= (enum enum_field_types)uint1korr(p);
+ p++;
+ field->flags= uint2korr(p);
+ p+= 2;
+ field->decimals= (uint) p[0];
+ p++;
+
+ /* filler */
+ p+= 2;
+
+ if (INTERNAL_NUM_FIELD(field))
+ field->flags|= NUM_FLAG;
+
+ i++;
+ /* This is used by deprecated function mysql_list_fields only,
+ however the reported length is not correct, so we always zero it */
+ if (default_value && row->data[i])
+ field->def=ma_strdup_root(alloc,(char*) row->data[i]);
+ else
+ field->def=0;
+ field->def_length= 0;
+
+ field->max_length= 0;
+ }
+ if (field < result + fields)
+ goto error;
+ free_rows(data); /* Free old data */
+ return(result);
+error:
+ free_rows(data);
+ ma_free_root(alloc, MYF(0));
+ return(0);
+}
+
+
+/* Read all rows (fields or data) from server */
+
+MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ uint fields)
+{
+ uint field;
+ ulong pkt_len;
+ ulong len;
+ uchar *cp;
+ char *to, *end_to;
+ MYSQL_DATA *result;
+ MYSQL_ROWS **prev_ptr,*cur;
+ NET *net = &mysql->net;
+
+ if ((pkt_len= ma_net_safe_read(mysql)) == packet_error)
+ return(0);
+ if (!(result=(MYSQL_DATA*) calloc(1, sizeof(MYSQL_DATA))))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ ma_init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
+ result->alloc.min_malloc=sizeof(MYSQL_ROWS);
+ prev_ptr= &result->data;
+ result->rows=0;
+ result->fields=fields;
+
+ while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
+ {
+ result->rows++;
+ if (!(cur= (MYSQL_ROWS*) ma_alloc_root(&result->alloc,
+ sizeof(MYSQL_ROWS))) ||
+ !(cur->data= ((MYSQL_ROW)
+ ma_alloc_root(&result->alloc,
+ (fields+1)*sizeof(char *)+fields+pkt_len))))
+ {
+ free_rows(result);
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ *prev_ptr=cur;
+ prev_ptr= &cur->next;
+ to= (char*) (cur->data+fields+1);
+ end_to=to+fields+pkt_len-1;
+ for (field=0 ; field < fields ; field++)
+ {
+ if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
+ { /* null field */
+ cur->data[field] = 0;
+ }
+ else
+ {
+ cur->data[field] = to;
+ if (len > (ulong)(end_to - to) || to > end_to)
+ {
+ free_rows(result);
+ SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ memcpy(to,(char*) cp,len); to[len]=0;
+ to+=len+1;
+ cp+=len;
+ if (mysql_fields)
+ {
+ if (mysql_fields[field].max_length < len)
+ mysql_fields[field].max_length=len;
+ }
+ }
+ }
+ cur->data[field]=to; /* End of last field */
+ if ((pkt_len=ma_net_safe_read(mysql)) == packet_error)
+ {
+ free_rows(result);
+ return(0);
+ }
+ }
+ *prev_ptr=0; /* last pointer is null */
+ /* save status */
+ if (pkt_len > 1)
+ {
+ unsigned int last_status= mysql->server_status;
+ cp++;
+ mysql->warning_count= uint2korr(cp);
+ cp+= 2;
+ mysql->server_status= uint2korr(cp);
+ ma_status_callback(mysql, last_status)
+ }
+ return(result);
+}
+
+
+/*
+** Read one row. Uses packet buffer as storage for fields.
+** When next packet is read, the previous field values are destroyed
+*/
+
+
+int mthd_my_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
+{
+ uint field;
+ ulong pkt_len,len;
+ uchar *pos,*prev_pos, *end_pos;
+
+ if ((pkt_len=(uint) ma_net_safe_read(mysql)) == packet_error)
+ return -1;
+
+ if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
+ {
+ unsigned int last_status= mysql->server_status;
+ mysql->warning_count= uint2korr(mysql->net.read_pos + 1);
+ mysql->server_status= uint2korr(mysql->net.read_pos + 3);
+ ma_status_callback(mysql, last_status);
+ return 1; /* End of data */
+ }
+ prev_pos= 0; /* allowed to write at packet[-1] */
+ pos=mysql->net.read_pos;
+ end_pos=pos+pkt_len;
+ for (field=0 ; field < fields ; field++)
+ {
+ if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
+ { /* null field */
+ row[field] = 0;
+ *lengths++=0;
+ }
+ else
+ {
+ if (len > (ulong) (end_pos - pos) || pos > end_pos)
+ {
+ mysql->net.last_errno=CR_UNKNOWN_ERROR;
+ strncpy(mysql->net.last_error,ER(mysql->net.last_errno),
+ MYSQL_ERRMSG_SIZE - 1);
+ return -1;
+ }
+ row[field] = (char*) pos;
+ pos+=len;
+ *lengths++=len;
+ }
+ if (prev_pos)
+ *prev_pos=0; /* Terminate prev field */
+ prev_pos=pos;
+ }
+ row[field]=(char*) prev_pos+1; /* End of last field */
+ *prev_pos=0; /* Terminate last field */
+ return 0;
+}
+
+/****************************************************************************
+** Init MySQL structure or allocate one
+****************************************************************************/
+
+MYSQL * STDCALL
+mysql_init(MYSQL *mysql)
+{
+ if (mysql_server_init(0, NULL, NULL))
+ return NULL;
+ if (!mysql)
+ {
+ if (!(mysql=(MYSQL*) calloc(1, sizeof(MYSQL))))
+ return 0;
+ mysql->free_me=1;
+ mysql->net.pvio= 0;
+ mysql->net.extension= 0;
+ }
+ else
+ {
+ memset((char*) (mysql), 0, sizeof(*(mysql)));
+ mysql->net.pvio= 0;
+ mysql->free_me= 0;
+ mysql->net.extension= 0;
+ }
+
+ if (!(mysql->net.extension= (struct st_mariadb_net_extension *)
+ calloc(1, sizeof(struct st_mariadb_net_extension))) ||
+ !(mysql->extension= (struct st_mariadb_extension *)
+ calloc(1, sizeof(struct st_mariadb_extension))))
+ goto error;
+ mysql->options.report_data_truncation= 1;
+ mysql->options.connect_timeout=CONNECT_TIMEOUT;
+ mysql->charset= mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
+ mysql->methods= &MARIADB_DEFAULT_METHODS;
+ strcpy(mysql->net.sqlstate, "00000");
+ mysql->net.last_error[0]= mysql->net.last_errno= mysql->net.extension->extended_errno= 0;
+
+ if (ENABLED_LOCAL_INFILE != LOCAL_INFILE_MODE_OFF)
+ mysql->options.client_flag|= CLIENT_LOCAL_FILES;
+ mysql->extension->auto_local_infile= ENABLED_LOCAL_INFILE == LOCAL_INFILE_MODE_AUTO
+ ? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
+ mysql->options.reconnect= 0;
+ return mysql;
+error:
+ if (mysql->free_me)
+ free(mysql);
+ return 0;
+}
+
+int STDCALL
+mysql_ssl_set(MYSQL *mysql __attribute__((unused)),
+ const char *key __attribute__((unused)),
+ const char *cert __attribute__((unused)),
+ const char *ca __attribute__((unused)),
+ const char *capath __attribute__((unused)),
+ const char *cipher __attribute__((unused)))
+{
+#ifdef HAVE_TLS
+ char enable= 1;
+ return (mysql_optionsv(mysql, MYSQL_OPT_SSL_ENFORCE, &enable) |
+ mysql_optionsv(mysql, MYSQL_OPT_SSL_KEY, key) |
+ mysql_optionsv(mysql, MYSQL_OPT_SSL_CERT, cert) |
+ mysql_optionsv(mysql, MYSQL_OPT_SSL_CA, ca) |
+ mysql_optionsv(mysql, MYSQL_OPT_SSL_CAPATH, capath) |
+ mysql_optionsv(mysql, MYSQL_OPT_SSL_CIPHER, cipher)) ? 1 : 0;
+#else
+ return 0;
+#endif
+}
+
+/**************************************************************************
+**************************************************************************/
+
+const char * STDCALL
+mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
+{
+#ifdef HAVE_TLS
+ if (mysql->net.pvio && mysql->net.pvio->ctls)
+ {
+ return ma_pvio_tls_cipher(mysql->net.pvio->ctls);
+ }
+#endif
+ return(NULL);
+}
+
+/**************************************************************************
+** Free strings in the SSL structure and clear 'use_ssl' flag.
+** NB! Errors are not reported until you do mysql_real_connect.
+**************************************************************************/
+
+char *ma_send_connect_attr(MYSQL *mysql, unsigned char *buffer)
+{
+ if (mysql->server_capabilities & CLIENT_CONNECT_ATTRS)
+ {
+ buffer= (unsigned char *)mysql_net_store_length((unsigned char *)buffer, (mysql->options.extension) ?
+ mysql->options.extension->connect_attrs_len : 0);
+ if (mysql->options.extension &&
+ ma_hashtbl_inited(&mysql->options.extension->connect_attrs))
+ {
+ uint i;
+ for (i=0; i < mysql->options.extension->connect_attrs.records; i++)
+ {
+ size_t len;
+ uchar *p= ma_hashtbl_element(&mysql->options.extension->connect_attrs, i);
+
+ len= strlen((char *)p);
+ buffer= mysql_net_store_length(buffer, len);
+ memcpy(buffer, p, len);
+ buffer+= (len);
+ p+= (len + 1);
+ len= strlen((char *)p);
+ buffer= mysql_net_store_length(buffer, len);
+ memcpy(buffer, p, len);
+ buffer+= len;
+ }
+ }
+ }
+ return (char *)buffer;
+}
+
+/** set some default attributes */
+static my_bool
+ma_set_connect_attrs(MYSQL *mysql, const char *host)
+{
+ char buffer[255];
+ int rc= 0;
+
+ rc= mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_client_name") +
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_client_version") +
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_os") +
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_server_host") +
+#ifdef _WIN32
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_thread") +
+#endif
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_pid") +
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "_platform");
+
+ rc+= mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_name", "libmariadb")
+ + mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_version", MARIADB_PACKAGE_VERSION)
+ + mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_os", MARIADB_SYSTEM_TYPE);
+
+ if (host && *host)
+ rc+= mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_server_host", host);
+
+#ifdef _WIN32
+ snprintf(buffer, 255, "%lu", (ulong) GetCurrentThreadId());
+ rc+= mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_thread", buffer);
+ snprintf(buffer, 255, "%lu", (ulong) GetCurrentProcessId());
+#else
+ snprintf(buffer, 255, "%lu", (ulong) getpid());
+#endif
+ rc+= mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_pid", buffer);
+
+ rc+= mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_platform", MARIADB_MACHINE_TYPE);
+ return(test(rc>0));
+}
+
+/*
+** Note that the mysql argument must be initialized with mysql_init()
+** before calling mysql_real_connect !
+*/
+
+MYSQL * STDCALL
+mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
+ const char *passwd, const char *db,
+ uint port, const char *unix_socket,unsigned long client_flag)
+{
+ char *end= NULL;
+ char *connection_handler= (mysql->options.extension) ?
+ mysql->options.extension->connection_handler : 0;
+
+ if (!mysql->methods)
+ mysql->methods= &MARIADB_DEFAULT_METHODS;
+
+ /* set default */
+ if (!mysql->options.extension || !mysql->options.extension->status_callback)
+ mysql_optionsv(mysql, MARIADB_OPT_STATUS_CALLBACK, NULL, NULL);
+
+ /* if host contains a semicolon, we need to parse connection string */
+ if (host && strchr(host, ';'))
+ {
+ if (parse_connection_string(mysql, NULL, host, strlen(host)))
+ return NULL;
+ /* if host was passed in connection string, it is now
+ stored in mysql->options.host */
+ host= NULL;
+ } else if (connection_handler ||
+ (host && (end= strstr(host, "://"))))
+ {
+ MARIADB_CONNECTION_PLUGIN *plugin;
+ char plugin_name[64];
+
+ if (!connection_handler || !connection_handler[0])
+ {
+ memset(plugin_name, 0, 64);
+ ma_strmake(plugin_name, host, MIN(end - host, 63));
+ end+= 3;
+ }
+ else
+ ma_strmake(plugin_name, connection_handler, MIN(63, strlen(connection_handler)));
+
+ if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN)))
+ return NULL;
+
+ if (!(mysql->extension->conn_hdlr= (MA_CONNECTION_HANDLER *)calloc(1, sizeof(MA_CONNECTION_HANDLER))))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return NULL;
+ }
+
+ /* save URL for reconnect */
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, url, host);
+
+ mysql->extension->conn_hdlr->plugin= plugin;
+
+ if (plugin && plugin->connect)
+ {
+ MYSQL *my= plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag);
+ if (!my)
+ {
+ free(mysql->extension->conn_hdlr);
+ mysql->extension->conn_hdlr= NULL;
+ }
+ return my;
+ }
+ }
+#ifndef HAVE_SCHANNEL
+ return mysql->methods->db_connect(mysql, host, user, passwd,
+ db, port, unix_socket, client_flag);
+#else
+/*
+ With older windows versions (prior Win 10) TLS connections periodically
+ fail with SEC_E_INVALID_TOKEN, SEC_E_BUFFER_TOO_SMALL or SEC_E_MESSAGE_ALTERED
+ error (see MDEV-13492). If the connect attempt returns on of these error codes
+ in mysql->net.extended_errno we will try to connect again (max. 3 times)
+*/
+#define MAX_SCHANNEL_CONNECT_ATTEMPTS 3
+ {
+ int ssl_retry= (mysql->options.use_ssl) ? MAX_SCHANNEL_CONNECT_ATTEMPTS : 1;
+ MYSQL *my= NULL;
+ while (ssl_retry)
+ {
+ if ((my= mysql->methods->db_connect(mysql, host, user, passwd,
+ db, port, unix_socket, client_flag | CLIENT_REMEMBER_OPTIONS)))
+ return my;
+
+ switch (mysql->net.extension->extended_errno) {
+ case SEC_E_INVALID_TOKEN:
+ case SEC_E_BUFFER_TOO_SMALL:
+ case SEC_E_MESSAGE_ALTERED:
+ ssl_retry--;
+ break;
+ default:
+ ssl_retry= 0;
+ break;
+ }
+ }
+ if (!my && !(client_flag & CLIENT_REMEMBER_OPTIONS))
+ mysql_close_options(mysql);
+ return my;
+ }
+#endif
+}
+
+struct st_host {
+ char *host;
+ int port;
+};
+
+static void ma_get_host_list(char *host_list, struct st_host *host_info, int default_port)
+{
+ char *token, *start, *save;
+ int host_nr= 0;
+
+ start= host_list;
+ while ((token= strtok_r(start, ",", &save)))
+ {
+ char *p;
+
+ /* ipv6 hostname */
+ if ((p= strchr(token, ']')))
+ {
+ host_info[host_nr].host= token + 1;
+ *p++= 0;
+ token= p;
+ }
+ else
+ host_info[host_nr].host= token;
+ /* check if port was specified */
+ if ((p= strchr(token, ':')))
+ {
+ *p++= 0;
+ host_info[host_nr].port= atoi(p);
+ }
+ else
+ host_info[host_nr].port= default_port;
+ host_nr++;
+ start= NULL;
+ }
+ return;
+}
+
+MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
+ const char *passwd, const char *db,
+ uint port, const char *unix_socket, unsigned long client_flag)
+{
+ char buff[NAME_LEN+USERNAME_LENGTH+100];
+ char *end, *end_pkt, *host_info;
+ MA_PVIO_CINFO cinfo= {NULL, NULL, 0, -1, NULL};
+ MARIADB_PVIO *pvio= NULL;
+ char *scramble_data;
+ const char *scramble_plugin;
+ uint pkt_length, scramble_len, pkt_scramble_len= 0;
+ NET *net= &mysql->net;
+ my_bool is_multi= 0;
+ char *host_copy= NULL;
+ struct st_host *host_list= NULL;
+ int connect_attempts= 0;
+
+ if (!mysql->methods)
+ mysql->methods= &MARIADB_DEFAULT_METHODS;
+
+ if (net->pvio) /* check if we are already connected */
+ {
+ SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0);
+ return(NULL);
+ }
+
+ /* use default options */
+ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
+ {
+ _mariadb_read_options(mysql, NULL,
+ (mysql->options.my_cnf_file ?
+ mysql->options.my_cnf_file : NULL),
+ mysql->options.my_cnf_group, 0);
+ free(mysql->options.my_cnf_file);
+ free(mysql->options.my_cnf_group);
+ mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
+ }
+
+ if (!port)
+ port=mysql->options.port;
+ if (!host || !host[0])
+ host= mysql->options.host;
+
+ /* check if we have multi hosts */
+ if (host && host[0] && strchr(host, ','))
+ {
+ char *p;
+ size_t host_count= 1;
+
+ is_multi= 1;
+
+ /* don't change original entry, so let's make a copy */
+ if (!(host_copy= strdup(host)))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+
+ p= host_copy;
+
+ while ((p = strchr(p, ',')))
+ {
+ host_count++;
+ p++;
+ }
+
+ if (!(host_list= (struct st_host *)calloc(host_count + 1, sizeof(struct st_host))))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+
+ ma_get_host_list(host_copy, host_list, port);
+ }
+
+restart:
+ /* check if we reached end of list */
+ if (is_multi)
+ {
+ if (!host_list[connect_attempts].host)
+ goto error;
+
+ host= host_list[connect_attempts].host;
+ port= host_list[connect_attempts].port;
+ }
+
+ ma_set_connect_attrs(mysql, host);
+
+#ifndef WIN32
+ if (mysql->options.protocol > MYSQL_PROTOCOL_SOCKET)
+ {
+ SET_CLIENT_ERROR(mysql, CR_CONN_UNKNOWN_PROTOCOL, SQLSTATE_UNKNOWN, 0);
+ return(NULL);
+ }
+#endif
+
+ /* Some empty-string-tests are done because of ODBC */
+ if (!user || !user[0])
+ user=mysql->options.user;
+ if (!passwd)
+ {
+ passwd=mysql->options.password;
+#ifndef DONT_USE_MYSQL_PWD
+ if (!passwd)
+ passwd=getenv("MYSQL_PWD"); /* get it from environment (haneke) */
+ if (!passwd)
+ passwd= "";
+#endif
+ }
+ if (!db || !db[0])
+ db=mysql->options.db;
+ if (!unix_socket)
+ unix_socket=mysql->options.unix_socket;
+
+ mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
+
+ /* try to connect via pvio_init */
+ cinfo.host= host;
+ cinfo.unix_socket= unix_socket;
+ cinfo.port= port;
+ cinfo.mysql= mysql;
+
+ /*
+ ** Grab a socket and connect it to the server
+ */
+#ifndef _WIN32
+#if defined(HAVE_SYS_UN_H)
+ if ((!host || strcmp(host,LOCAL_HOST) == 0) &&
+ mysql->options.protocol != MYSQL_PROTOCOL_TCP &&
+ (unix_socket || mysql_unix_port))
+ {
+ cinfo.host= LOCAL_HOST;
+ cinfo.unix_socket= (unix_socket) ? unix_socket : mysql_unix_port;
+ cinfo.type= PVIO_TYPE_UNIXSOCKET;
+ sprintf(host_info=buff,ER(CR_LOCALHOST_CONNECTION),cinfo.host);
+ }
+ else
+#endif
+#else
+ if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)
+ {
+ cinfo.host= mysql->options.shared_memory_base_name;
+ cinfo.type= PVIO_TYPE_SHAREDMEM;
+ sprintf(host_info=buff,ER(CR_SHARED_MEMORY_CONNECTION), cinfo.host ? cinfo.host : SHM_DEFAULT_NAME);
+ }
+ /* named pipe */
+ else if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
+ (host && strcmp(host,LOCAL_HOST_NAMEDPIPE) == 0))
+ {
+ cinfo.type= PVIO_TYPE_NAMEDPIPE;
+ sprintf(host_info=buff,ER(CR_NAMEDPIPE_CONNECTION),cinfo.host);
+ }
+ else
+#endif
+ {
+ cinfo.unix_socket=0; /* This is not used */
+ if (!port)
+ port=mysql_port;
+ if (!host)
+ host=LOCAL_HOST;
+ cinfo.host= host;
+ cinfo.port= port;
+ cinfo.type= PVIO_TYPE_SOCKET;
+ sprintf(host_info=buff,ER(CR_TCP_CONNECTION), cinfo.host);
+ }
+ /* Initialize and load pvio plugin */
+ if (!(pvio= ma_pvio_init(&cinfo)))
+ goto error;
+
+ /* try to connect */
+ if (ma_pvio_connect(pvio, &cinfo) != 0)
+ {
+ ma_pvio_close(pvio);
+ if (mysql->options.extension && mysql->options.extension->async_context &&
+ mysql->options.extension->async_context->pvio)
+ {
+ /* pvio delegated to mysql->net.pvio by ma_net_init().
+ * invalidate the pvio pointer in the async context */
+ mysql->options.extension->async_context->pvio = NULL;
+ }
+
+ if (is_multi)
+ {
+ connect_attempts++;
+ goto restart;
+ }
+ goto error;
+ }
+
+ if (mysql->options.extension && mysql->options.extension->proxy_header)
+ {
+ char *hdr = mysql->options.extension->proxy_header;
+ size_t len = mysql->options.extension->proxy_header_len;
+ if (ma_pvio_write(pvio, (unsigned char *)hdr, len) <= 0)
+ {
+ ma_pvio_close(pvio);
+ goto error;
+ }
+ }
+
+ if (ma_net_init(net, pvio))
+ {
+ ma_pvio_close(pvio);
+ goto error;
+ }
+
+ if (mysql->options.extension && mysql->options.extension->async_context && mysql->options.extension->async_context->pvio)
+ {
+ /* pvio delegated to mysql->net.pvio by ma_net_init().
+ * invalidate the pvio pointer in the async context */
+ mysql->options.extension->async_context->pvio = NULL;
+ }
+
+
+ if (mysql->options.max_allowed_packet)
+ net->max_packet_size= mysql->options.max_allowed_packet;
+
+ ma_pvio_keepalive(net->pvio);
+ strcpy(mysql->net.sqlstate, "00000");
+
+ /* Get version info */
+ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */
+/*
+ if (ma_pvio_wait_io_or_timeout(net->pvio, FALSE, 0) < 1)
+ {
+ my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "handshake: waiting for initial communication packet",
+ errno);
+ goto error;
+ }
+ */
+ if ((pkt_length=ma_net_safe_read(mysql)) == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "handshake: reading initial communication packet",
+ errno);
+
+ goto error;
+ }
+ end= (char *)net->read_pos;
+ end_pkt= (char *)net->read_pos + pkt_length;
+
+ /* Check if version of protocol matches current one */
+
+ mysql->protocol_version= end[0];
+ end++;
+
+ /* Check if server sends an error */
+ if (mysql->protocol_version == 0XFF)
+ {
+ net_get_error(end, pkt_length - 1, net->last_error, sizeof(net->last_error),
+ &net->last_errno, net->sqlstate);
+ /* fix for bug #26426 */
+ if (net->last_errno == 1040)
+ memcpy(net->sqlstate, "08004", SQLSTATE_LENGTH);
+ goto error;
+ }
+
+ if (mysql->protocol_version < PROTOCOL_VERSION)
+ {
+ net->last_errno= CR_VERSION_ERROR;
+ sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version,
+ PROTOCOL_VERSION);
+ goto error;
+ }
+ /* Save connection information */
+ if (!user) user="";
+
+ if (!(mysql->host_info= strdup(host_info)) ||
+ !(mysql->host= strdup(cinfo.host ? cinfo.host : "")) ||
+ !(mysql->user=strdup(user)) ||
+ !(mysql->passwd=strdup(passwd)))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+ if (cinfo.unix_socket)
+ mysql->unix_socket= strdup(cinfo.unix_socket);
+ else
+ mysql->unix_socket=0;
+ mysql->port=port;
+ client_flag|=mysql->options.client_flag;
+
+ if (strncmp(end, MA_RPL_VERSION_HACK, sizeof(MA_RPL_VERSION_HACK) - 1) == 0)
+ {
+ mysql->server_version= strdup(end + sizeof(MA_RPL_VERSION_HACK) - 1);
+ }
+ else
+ {
+ if (!(mysql->server_version= strdup(end)))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+ }
+ end+= strlen(end) + 1;
+
+ mysql->thread_id=uint4korr(end);
+ end+=4;
+
+ /* This is the first part of scramble packet. In 4.1 and later
+ a second package will follow later */
+ scramble_data= end;
+ scramble_len= SCRAMBLE_LENGTH_323 + 1;
+ scramble_plugin= old_password_plugin_name;
+ end+= SCRAMBLE_LENGTH_323;
+
+ /* 1st pad */
+ end++;
+
+ if (end + 1<= end_pkt)
+ {
+ mysql->server_capabilities=uint2korr(end);
+ }
+
+ /* mysql 5.5 protocol */
+ if (end + 18 <= end_pkt)
+ {
+ mysql->server_language= uint1korr(end + 2);
+ mysql->server_status= uint2korr(end + 3);
+ mysql->server_capabilities|= (unsigned int)(uint2korr(end + 5)) << 16;
+ pkt_scramble_len= uint1korr(end + 7);
+
+ /* check if MariaD2B specific capabilities are available */
+ if (mariadb_connection(mysql) && !(mysql->server_capabilities & CLIENT_MYSQL))
+ {
+ mysql->extension->mariadb_server_capabilities= (ulonglong) uint4korr(end + 14);
+ }
+ }
+
+ /* pad 2 */
+ end+= 18;
+
+ /* second scramble package */
+ if (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 <= end_pkt)
+ {
+ memcpy(end - SCRAMBLE_LENGTH_323, scramble_data, SCRAMBLE_LENGTH_323);
+ scramble_data= end - SCRAMBLE_LENGTH_323;
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ scramble_len= pkt_scramble_len;
+ scramble_plugin= scramble_data + scramble_len;
+ if (scramble_data + scramble_len > end_pkt)
+ {
+ SET_CLIENT_ERROR(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+ } else
+ {
+ scramble_len= (uint)(end_pkt - scramble_data);
+ scramble_plugin= native_password_plugin_name;
+ }
+ } else
+ {
+ mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
+ if (mysql->options.secure_auth)
+ {
+ SET_CLIENT_ERROR(mysql, CR_SECURE_AUTH, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+ }
+
+ /* Set character set */
+ if (mysql->options.charset_name)
+ mysql->charset= mysql_find_charset_name(mysql->options.charset_name);
+ else
+ mysql->charset=mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
+
+ if (!mysql->charset)
+ {
+ net->last_errno=CR_CANT_READ_CHARSET;
+ sprintf(net->last_error,ER(net->last_errno),
+ mysql->options.charset_name ? mysql->options.charset_name :
+ MARIADB_DEFAULT_CHARSET,
+ "compiled_in");
+ goto error;
+ }
+
+ mysql->client_flag= client_flag;
+
+ if (run_plugin_auth(mysql, scramble_data, scramble_len,
+ scramble_plugin, db))
+ goto error;
+
+ if (mysql->client_flag & CLIENT_COMPRESS ||
+ mysql->client_flag & CLIENT_ZSTD_COMPRESSION)
+ {
+ if (!compression_plugin(net) ||
+ (!(compression_ctx(net) = compression_plugin(net)->init_ctx(COMPRESSION_LEVEL_DEFAULT))))
+ {
+ int alg= (mysql->client_flag & CLIENT_ZSTD_COMPRESSION) ?
+ COMPRESSION_ZSTD : COMPRESSION_ZLIB;
+ compression_plugin(net)= NULL;
+ my_set_error(mysql, CR_ERR_LOAD_PLUGIN, SQLSTATE_UNKNOWN, NULL,
+ _mariadb_compression_algorithm_str(alg));
+ goto error;
+ }
+ net->compress= 1;
+ }
+
+ /* last part: select default db */
+ if (!(mysql->server_capabilities & CLIENT_CONNECT_WITH_DB) &&
+ (db && !mysql->db))
+ {
+ if (mysql_select_db(mysql, db))
+ {
+ my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "Setting intital database",
+ errno);
+ goto error;
+ }
+ }
+
+ if (mysql->options.init_command)
+ {
+ char **begin= (char **)mysql->options.init_command->buffer;
+ char **end= begin + mysql->options.init_command->elements;
+
+ /* Avoid reconnect in mysql_real_connect */
+ my_bool save_reconnect= mysql->options.reconnect;
+ mysql->options.reconnect= 0;
+
+ for (;begin < end; begin++)
+ {
+ if (mysql_real_query(mysql, *begin, (unsigned long)strlen(*begin)))
+ goto error;
+
+ /* check if query produced a result set */
+ do {
+ MYSQL_RES *res;
+ if ((res= mysql_use_result(mysql)))
+ mysql_free_result(res);
+ } while (!mysql_next_result(mysql));
+ }
+ mysql->options.reconnect= save_reconnect;
+ }
+
+ strcpy(mysql->net.sqlstate, "00000");
+
+ /* connection established, apply timeouts */
+ ma_pvio_set_timeout(mysql->net.pvio, PVIO_READ_TIMEOUT, mysql->options.read_timeout);
+ ma_pvio_set_timeout(mysql->net.pvio, PVIO_WRITE_TIMEOUT, mysql->options.write_timeout);
+
+ free(host_list);
+ free(host_copy);
+
+ return(mysql);
+
+error:
+ /* Free allocated memory */
+ free(host_list);
+ free(host_copy);
+ end_server(mysql);
+ /* only free the allocated memory, user needs to call mysql_close */
+ mysql_close_memory(mysql);
+ if (!(client_flag & CLIENT_REMEMBER_OPTIONS) &&
+ !(IS_MYSQL_ASYNC(mysql)))
+ mysql_close_options(mysql);
+ return(0);
+}
+
+struct my_hook_data {
+ MYSQL *orig_mysql;
+ MYSQL *new_mysql;
+ /* This is always NULL currently, but restoring does not hurt just in case. */
+ MARIADB_PVIO *orig_pvio;
+};
+/*
+ Callback hook to make the new VIO accessible via the old MYSQL to calling
+ application when suspending a non-blocking call during automatic reconnect.
+*/
+static void
+my_suspend_hook(my_bool suspend, void *data)
+{
+ struct my_hook_data *hook_data= (struct my_hook_data *)data;
+ if (suspend)
+ {
+ hook_data->orig_pvio= hook_data->orig_mysql->net.pvio;
+ hook_data->orig_mysql->net.pvio= hook_data->new_mysql->net.pvio;
+ }
+ else
+ hook_data->orig_mysql->net.pvio= hook_data->orig_pvio;
+}
+
+my_bool STDCALL mariadb_reconnect(MYSQL *mysql)
+{
+ MYSQL tmp_mysql;
+ struct my_hook_data hook_data;
+ struct mysql_async_context *ctxt= NULL;
+ LIST *li_stmt= mysql->stmts;
+
+ /* check if connection handler is active */
+ if (IS_CONNHDLR_ACTIVE(mysql))
+ {
+ if (mysql->extension->conn_hdlr->plugin && mysql->extension->conn_hdlr->plugin->reconnect)
+ return(mysql->extension->conn_hdlr->plugin->reconnect(mysql));
+ }
+
+ if (!mysql->options.reconnect ||
+ (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
+ {
+ /* Allow reconnect next time */
+ mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
+ my_set_error(mysql, CR_SERVER_GONE_ERROR, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ mysql_init(&tmp_mysql);
+ tmp_mysql.free_me= 0;
+ tmp_mysql.options=mysql->options;
+ if (mysql->extension->conn_hdlr)
+ {
+ tmp_mysql.extension->conn_hdlr= mysql->extension->conn_hdlr;
+ mysql->extension->conn_hdlr= 0;
+ }
+
+ /* don't reread options from configuration files */
+ tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL;
+ if (IS_MYSQL_ASYNC_ACTIVE(mysql))
+ {
+ ctxt= mysql->options.extension->async_context;
+ hook_data.orig_mysql= mysql;
+ hook_data.new_mysql= &tmp_mysql;
+ hook_data.orig_pvio= mysql->net.pvio;
+ my_context_install_suspend_resume_hook(ctxt, my_suspend_hook, &hook_data);
+ }
+
+ if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
+ mysql->db, mysql->port, mysql->unix_socket,
+ mysql->client_flag | CLIENT_REMEMBER_OPTIONS) ||
+ mysql_set_character_set(&tmp_mysql, mysql->charset->csname))
+ {
+ if (ctxt)
+ my_context_install_suspend_resume_hook(ctxt, NULL, NULL);
+ /* don't free options (CONC-118) */
+ memset(&tmp_mysql.options, 0, sizeof(struct st_mysql_options));
+ my_set_error(mysql, tmp_mysql.net.last_errno,
+ tmp_mysql.net.sqlstate,
+ tmp_mysql.net.last_error);
+ mysql_close(&tmp_mysql);
+ return(1);
+ }
+
+ for (;li_stmt;li_stmt= li_stmt->next)
+ {
+ MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
+
+ if (stmt->state != MYSQL_STMT_INITTED)
+ {
+ stmt->state= MYSQL_STMT_INITTED;
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ }
+ }
+
+ tmp_mysql.free_me= mysql->free_me;
+ tmp_mysql.stmts= mysql->stmts;
+ mysql->stmts= NULL;
+
+ if (ctxt)
+ my_context_install_suspend_resume_hook(ctxt, NULL, NULL);
+ /* Don't free options, we moved them to tmp_mysql */
+ memset(&mysql->options, 0, sizeof(mysql->options));
+ mysql->free_me=0;
+ mysql_close(mysql);
+ *mysql=tmp_mysql;
+ mysql->net.pvio->mysql= mysql;
+#ifdef HAVE_TLS
+ /* CONC-604: Set new connection handle */
+ if (mysql_get_ssl_cipher(mysql))
+ ma_pvio_tls_set_connection(mysql);
+#endif
+ ma_net_clear(&mysql->net);
+ mysql->affected_rows= ~(unsigned long long) 0;
+ mysql->info= 0;
+ return(0);
+}
+
+void ma_invalidate_stmts(MYSQL *mysql, const char *function_name)
+{
+ if (mysql->stmts)
+ {
+ LIST *li_stmt= mysql->stmts;
+
+ for (; li_stmt; li_stmt= li_stmt->next)
+ {
+ MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
+ stmt->mysql= NULL;
+ stmt_set_error(stmt, CR_STMT_CLOSED, SQLSTATE_UNKNOWN, 0, function_name);
+ }
+ mysql->stmts= NULL;
+ }
+}
+
+/*
+ Legacy support of the MariaDB 5.5 version, where timeouts where only in
+ seconds resolution. Applications that use this will be asked to set a timeout
+ at the nearest higher whole-seconds value.
+*/
+unsigned int STDCALL
+mysql_get_timeout_value(const MYSQL *mysql)
+{
+ unsigned int timeout= 0;
+
+ if (mysql->options.extension && mysql->options.extension->async_context)
+ timeout= mysql->options.extension->async_context->timeout_value;
+ /* Avoid overflow. */
+ if (timeout > UINT_MAX - 999)
+ return (timeout - 1)/1000 + 1;
+ else
+ return (timeout+999)/1000;
+}
+
+
+unsigned int STDCALL
+mysql_get_timeout_value_ms(const MYSQL *mysql)
+{
+ if (mysql->options.extension && mysql->options.extension->async_context)
+ return mysql->options.extension->async_context->timeout_value;
+ return 0;
+}
+
+/**************************************************************************
+** Change user and database
+**************************************************************************/
+
+my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
+ const char *passwd, const char *db)
+{
+ const MARIADB_CHARSET_INFO *s_cs= mysql->charset;
+ char *s_user= mysql->user,
+ *s_passwd= mysql->passwd,
+ *s_db= mysql->db;
+ int rc;
+
+ if (mysql->options.charset_name)
+ mysql->charset= mysql_find_charset_name(mysql->options.charset_name);
+ else
+ mysql->charset=mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
+
+ mysql->user= strdup(user ? user : "");
+ mysql->passwd= strdup(passwd ? passwd : "");
+
+ /* db will be set in run_plugin_auth */
+ mysql->db= 0;
+ rc= run_plugin_auth(mysql, 0, 0, 0, db);
+
+ /* COM_CHANGE_USER always releases prepared statements, so we need to invalidate them */
+ ma_invalidate_stmts(mysql, "mysql_change_user()");
+
+ if (rc==0)
+ {
+ free(s_user);
+ free(s_passwd);
+ free(s_db);
+
+ if (!mysql->db && db && !(mysql->db= strdup(db)))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ rc= 1;
+ }
+ } else
+ {
+ free(mysql->user);
+ free(mysql->passwd);
+ free(mysql->db);
+
+ mysql->user= s_user;
+ mysql->passwd= s_passwd;
+ mysql->db= s_db;
+ mysql->charset= s_cs;
+ }
+ return(rc);
+}
+
+
+/**************************************************************************
+** Set current database
+**************************************************************************/
+
+int STDCALL
+mysql_select_db(MYSQL *mysql, const char *db)
+{
+ int error;
+
+ if (!db)
+ return 1;
+
+ if ((error=ma_simple_command(mysql, COM_INIT_DB, db,
+ (uint) strlen(db),0,0)))
+ return(error);
+ free(mysql->db);
+ mysql->db=strdup(db);
+ return(0);
+}
+
+
+/*************************************************************************
+** Send a QUIT to the server and close the connection
+** If handle is allocated by mysql connect free it.
+*************************************************************************/
+
+static void mysql_close_options(MYSQL *mysql)
+{
+ if (mysql->options.init_command)
+ {
+ char **begin= (char **)mysql->options.init_command->buffer;
+ char **end= begin + mysql->options.init_command->elements;
+
+ for (;begin < end; begin++)
+ free(*begin);
+ ma_delete_dynamic(mysql->options.init_command);
+ free(mysql->options.init_command);
+ }
+ free(mysql->options.user);
+ free(mysql->options.host);
+ free(mysql->options.password);
+ free(mysql->options.unix_socket);
+ free(mysql->options.db);
+ free(mysql->options.my_cnf_file);
+ free(mysql->options.my_cnf_group);
+ free(mysql->options.charset_dir);
+ free(mysql->options.charset_name);
+ free(mysql->options.bind_address);
+ free(mysql->options.ssl_key);
+ free(mysql->options.ssl_cert);
+ free(mysql->options.ssl_ca);
+ free(mysql->options.ssl_capath);
+ free(mysql->options.ssl_cipher);
+
+ if (mysql->options.extension)
+ {
+ struct mysql_async_context *ctxt;
+ if ((ctxt = mysql->options.extension->async_context))
+ {
+ my_context_destroy(&ctxt->async_context);
+ free(ctxt);
+ mysql->options.extension->async_context= 0;
+ }
+ free(mysql->options.extension->plugin_dir);
+ free(mysql->options.extension->default_auth);
+ free(mysql->options.extension->db_driver);
+ free(mysql->options.extension->ssl_crl);
+ free(mysql->options.extension->ssl_crlpath);
+ free(mysql->options.extension->tls_fp);
+ free(mysql->options.extension->tls_fp_list);
+ free(mysql->options.extension->tls_pw);
+ free(mysql->options.extension->tls_version);
+ free(mysql->options.extension->url);
+ free(mysql->options.extension->connection_handler);
+ free(mysql->options.extension->proxy_header);
+ if(ma_hashtbl_inited(&mysql->options.extension->connect_attrs))
+ ma_hashtbl_free(&mysql->options.extension->connect_attrs);
+ if (ma_hashtbl_inited(&mysql->options.extension->userdata))
+ ma_hashtbl_free(&mysql->options.extension->userdata);
+ free(mysql->options.extension->restricted_auth);
+ free(mysql->options.extension->rpl_host);
+
+ }
+ free(mysql->options.extension);
+ /* clear all pointer */
+ memset(&mysql->options, 0, sizeof(mysql->options));
+}
+
+static void mysql_close_memory(MYSQL *mysql)
+{
+ ma_clear_session_state(mysql);
+ free(mysql->host_info);
+ free(mysql->host);
+ free(mysql->user);
+ free(mysql->passwd);
+ free(mysql->db);
+ free(mysql->unix_socket);
+ free(mysql->server_version);
+ mysql->host_info= mysql->host= mysql->unix_socket=
+ mysql->server_version=mysql->user=mysql->passwd=mysql->db=0;
+}
+
+void my_set_error(MYSQL *mysql,
+ unsigned int error_nr,
+ const char *sqlstate,
+ const char *format,
+ ...)
+{
+ va_list ap;
+
+ const char *errmsg= format;
+
+ mysql->net.last_errno= error_nr;
+ ma_strmake(mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH);
+
+ if (!format)
+ {
+ if (IS_MYSQL_ERROR(error_nr) || IS_MARIADB_ERROR(error_nr))
+ errmsg= ER(error_nr);
+ else {
+ snprintf(mysql->net.last_error, MYSQL_ERRMSG_SIZE - 1,
+ ER_UNKNOWN_ERROR_CODE, error_nr);
+ return;
+ }
+ }
+
+ va_start(ap, format);
+ vsnprintf(mysql->net.last_error, MYSQL_ERRMSG_SIZE - 1, errmsg, ap);
+ va_end(ap);
+ return;
+}
+
+void mysql_close_slow_part(MYSQL *mysql)
+{
+ if (mysql->net.pvio)
+ {
+ free_old_query(mysql);
+ mysql->status=MYSQL_STATUS_READY; /* Force command */
+ mysql->options.reconnect=0;
+ if (mysql->net.pvio && mysql->net.buff)
+ ma_simple_command(mysql, COM_QUIT,NullS,0,1,0);
+ end_server(mysql);
+ }
+ /* there is an ongoing async operation */
+ else if (mysql->options.extension && mysql->options.extension->async_context)
+ {
+ if (mysql->options.extension->async_context->pending_gai_res)
+ {
+ freeaddrinfo(mysql->options.extension->async_context->pending_gai_res);
+ mysql->options.extension->async_context->pending_gai_res = 0;
+ }
+ if (mysql->options.extension->async_context->pvio)
+ {
+ ma_pvio_close(mysql->options.extension->async_context->pvio);
+ mysql->options.extension->async_context->pvio = 0;
+ }
+ }
+}
+
+static void ma_clear_session_state(MYSQL *mysql)
+{
+ uint i;
+
+ if (!mysql || !mysql->extension)
+ return;
+
+ for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
+ {
+ list_free(mysql->extension->session_state[i].list, 0);
+ }
+ memset(mysql->extension->session_state, 0, sizeof(struct st_mariadb_session_state) * SESSION_TRACK_TYPES);
+}
+
+void STDCALL
+mysql_close(MYSQL *mysql)
+{
+ if (mysql) /* Some simple safety */
+ {
+ if (mysql->extension && mysql->extension->conn_hdlr)
+ {
+ MA_CONNECTION_HANDLER *p= mysql->extension->conn_hdlr;
+ if (p->plugin->close)
+ p->plugin->close(mysql);
+ free(p);
+ /* Fix for CONC-294: Since we already called plugin->close function
+ we need to prevent that mysql_close_slow_part (which sends COM_QUIT
+ to the server) will be handled by plugin again. */
+ mysql->extension->conn_hdlr= NULL;
+ }
+
+ if (mysql->methods)
+ mysql->methods->db_close(mysql);
+
+ /* reset the connection in all active statements */
+ ma_invalidate_stmts(mysql, "mysql_close()");
+
+ mysql_close_memory(mysql);
+ mysql_close_options(mysql);
+ ma_clear_session_state(mysql);
+
+ if (mysql->net.extension)
+ {
+ if (compression_plugin(&mysql->net))
+ compression_plugin(&mysql->net)->free_ctx(compression_ctx(&mysql->net));
+ free(mysql->net.extension);
+ }
+
+ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
+
+ /* Clear pointers for better safety */
+ memset((char*) &mysql->options, 0, sizeof(mysql->options));
+
+ if (mysql->extension)
+ free(mysql->extension);
+
+ /* Clear pointers for better safety */
+ mysql->net.extension = NULL;
+ mysql->extension = NULL;
+
+ mysql->net.pvio= 0;
+ if (mysql->free_me)
+ free(mysql);
+ }
+ return;
+}
+
+
+/**************************************************************************
+** Do a query. If query returned rows, free old rows.
+** Read data by mysql_store_result or by repeating calls to mysql_fetch_row
+**************************************************************************/
+
+int STDCALL
+mysql_query(MYSQL *mysql, const char *query)
+{
+ return mysql_real_query(mysql,query, (unsigned long) strlen(query));
+}
+
+/*
+ Send the query and return so we can do something else.
+ Needs to be followed by mysql_read_query_result() when we want to
+ finish processing it.
+*/
+
+
+
+int STDCALL
+mysql_send_query(MYSQL* mysql, const char* query, unsigned long length)
+{
+ return ma_simple_command(mysql, COM_QUERY, query, length, 1,0);
+}
+
+void ma_save_session_track_info(void *ptr, enum enum_mariadb_status_info type, ...)
+{
+ MYSQL *mysql= (MYSQL *)ptr;
+ enum enum_session_state_type track_type;
+ va_list ap;
+
+ DBUG_ASSERT(mysql != NULL);
+
+ /* We only handle SESSION_TRACK_TYPE here */
+ if (type != SESSION_TRACK_TYPE)
+ return;
+
+ va_start(ap, type);
+
+ track_type= va_arg(ap, enum enum_session_state_type);
+
+ switch (track_type) {
+ case SESSION_TRACK_SCHEMA:
+ case SESSION_TRACK_STATE_CHANGE:
+ case SESSION_TRACK_TRANSACTION_CHARACTERISTICS:
+ case SESSION_TRACK_TRANSACTION_STATE:
+ case SESSION_TRACK_GTIDS:
+ case SESSION_TRACK_SYSTEM_VARIABLES:
+ {
+ LIST *session_item;
+ MYSQL_LEX_STRING *str;
+ char *tmp;
+ MARIADB_CONST_STRING *data1= va_arg(ap, MARIADB_CONST_STRING *);
+
+ if (!(session_item= ma_multi_malloc(0,
+ &session_item, sizeof(LIST),
+ &str, sizeof(MYSQL_LEX_STRING),
+ &tmp, data1->length,
+ NULL)))
+ goto mem_error;
+
+ str->str= tmp;
+ memcpy(str->str, data1->str, data1->length);
+ str->length= data1->length;
+ session_item->data= str;
+ mysql->extension->session_state[track_type].list= list_add(mysql->extension->session_state[track_type].list,
+ session_item);
+ if (track_type == SESSION_TRACK_SYSTEM_VARIABLES)
+ {
+ MARIADB_CONST_STRING *data2= va_arg(ap, MARIADB_CONST_STRING *);
+ if (!(session_item= ma_multi_malloc(0,
+ &session_item, sizeof(LIST),
+ &str, sizeof(MYSQL_LEX_STRING),
+ &tmp, data2->length,
+ NULL)))
+ goto mem_error;
+
+ str->str= tmp;
+ memcpy(str->str, data2->str, data2->length);
+ str->length= data2->length;
+ session_item->data= str;
+ mysql->extension->session_state[track_type].list= list_add(mysql->extension->session_state[track_type].list,
+ session_item);
+ }
+ }
+ break;
+ }
+ return;
+
+mem_error:
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return;
+}
+
+int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
+{
+ uchar *end= mysql->net.read_pos+length;
+ size_t item_len;
+ unsigned int last_status= mysql->server_status;
+ mysql->affected_rows= net_field_length_ll(&pos);
+ mysql->insert_id= net_field_length_ll(&pos);
+ mysql->server_status=uint2korr(pos);
+
+ /* clear error */
+ mysql->net.last_error[0]= mysql->net.last_errno= mysql->net.extension->extended_errno= 0;
+
+ /* callback */
+ ma_status_callback(mysql, last_status);
+ pos+=2;
+ mysql->warning_count=uint2korr(pos);
+ pos+=2;
+ if (pos > end)
+ goto corrupted;
+ if (pos < end)
+ {
+ if ((item_len= net_field_length(&pos)))
+ mysql->info=(char*) pos;
+ if (pos + item_len > end)
+ goto corrupted;
+
+ /* check if server supports session tracking */
+ if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
+ {
+ ma_clear_session_state(mysql);
+ pos+= item_len;
+
+ if (mysql->server_status & SERVER_SESSION_STATE_CHANGED)
+ {
+ int i;
+ if (pos < end)
+ {
+ enum enum_session_state_type si_type;
+ uchar *old_pos= pos;
+
+ item_len= net_field_length(&pos); /* length for all items */
+ if (pos + item_len > end)
+ goto corrupted;
+ end= pos + item_len;
+
+ /* length was already set, so make sure that info will be zero terminated */
+ if (mysql->info)
+ *old_pos= 0;
+
+ while (pos < end)
+ {
+ size_t plen;
+ MARIADB_CONST_STRING data1, data2;
+ si_type= (enum enum_session_state_type)net_field_length(&pos);
+
+ switch(si_type) {
+ case SESSION_TRACK_SCHEMA:
+ case SESSION_TRACK_STATE_CHANGE:
+ case SESSION_TRACK_TRANSACTION_CHARACTERISTICS:
+ case SESSION_TRACK_SYSTEM_VARIABLES:
+ case SESSION_TRACK_TRANSACTION_STATE:
+ case SESSION_TRACK_GTIDS:
+ if (si_type != SESSION_TRACK_STATE_CHANGE)
+ {
+ net_field_length(&pos); /* ignore total length, item length will follow next */
+ }
+ if (si_type == SESSION_TRACK_GTIDS)
+ {
+ /* skip encoding */
+ net_field_length(&pos);
+ }
+ plen= net_field_length(&pos);
+ if (pos + plen > end)
+ goto corrupted;
+
+ data1.str= (char *)pos;
+ data1.length= plen;
+ if (si_type != SESSION_TRACK_SYSTEM_VARIABLES)
+ {
+ mysql->options.extension->status_callback(mysql->options.extension->status_data,
+ SESSION_TRACK_TYPE, si_type,
+ &data1);
+ if (mysql->net.last_errno)
+ goto oom;
+ }
+ pos+= plen;
+ /* in case schema has changed, we have to update mysql->db */
+ if (si_type == SESSION_TRACK_SCHEMA)
+ {
+ free(mysql->db);
+ mysql->db= malloc(plen + 1);
+ memcpy(mysql->db, data1.str, data1.length);
+ mysql->db[data1.length]= 0;
+ }
+ else if (si_type == SESSION_TRACK_SYSTEM_VARIABLES)
+ {
+ my_bool set_charset= 0;
+ /* make sure that we update charset in case it has changed */
+ if (!strncmp(data1.str, "character_set_client", plen))
+ set_charset= 1;
+ plen= net_field_length(&pos);
+ if (pos + plen > end)
+ goto corrupted;
+ data2.str= (char *)pos;
+ data2.length= plen;
+
+ mysql->options.extension->status_callback(mysql->options.extension->status_data,
+ SESSION_TRACK_TYPE, si_type,
+ &data1, &data2);
+ if (mysql->net.last_errno)
+ goto oom;
+
+ pos+= plen;
+ if (set_charset && plen < CHARSET_NAME_LEN &&
+ strncmp(mysql->charset->csname, data2.str, data2.length) != 0)
+ {
+ char cs_name[CHARSET_NAME_LEN];
+ const MARIADB_CHARSET_INFO *cs_info;
+ memcpy(cs_name, data2.str, data2.length);
+ cs_name[plen]= 0;
+ if ((cs_info = mysql_find_charset_name(cs_name)))
+ mysql->charset= cs_info;
+ }
+ }
+ break;
+ default:
+ /* not supported yet */
+ plen= net_field_length(&pos);
+ if (pos + plen > end)
+ goto corrupted;
+ pos+= plen;
+ break;
+ }
+ }
+ }
+ for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
+ {
+ mysql->extension->session_state[i].list= list_reverse(mysql->extension->session_state[i].list);
+ mysql->extension->session_state[i].current= mysql->extension->session_state[i].list;
+ }
+ }
+ }
+ }
+ /* CONC-351: clear session state information */
+ else if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
+ ma_clear_session_state(mysql);
+ return(0);
+
+oom:
+ ma_clear_session_state(mysql);
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return -1;
+
+corrupted:
+ ma_clear_session_state(mysql);
+ SET_CLIENT_ERROR(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
+ return -1;
+}
+
+
+static int ma_deep_copy_field(const MYSQL_FIELD *src, MYSQL_FIELD *dst,
+ MA_MEM_ROOT *r)
+{
+#define MA_STRDUP(f) \
+ do \
+ { \
+ if (src->f) \
+ { \
+ if ((dst->f= ma_strdup_root(r, src->f)) == NULL) \
+ return -1; \
+ } \
+ else \
+ { \
+ dst->f= NULL; \
+ } \
+ } \
+ while (0)
+
+
+ MA_STRDUP(catalog);
+ MA_STRDUP(db);
+ MA_STRDUP(def);
+ MA_STRDUP(name);
+ MA_STRDUP(org_name);
+ MA_STRDUP(org_table);
+ MA_STRDUP(table);
+#undef MA_STRDUP
+
+ dst->catalog_length= src->catalog_length;
+ dst->charsetnr= src->charsetnr;
+ dst->db_length= src->db_length;
+ dst->decimals= src->decimals;
+ dst->def_length= src->def_length;
+ dst->extension=
+ src->extension
+ ? ma_field_extension_deep_dup(r,
+ src->extension)
+ : NULL;
+ dst->flags= src->flags;
+ dst->length= src->length;
+ dst->max_length = src->max_length;
+ dst->name_length= src->name_length;
+ dst->org_name_length= src->org_name_length;
+ dst->org_table_length= src->org_table_length;
+ dst->table_length= src->table_length;
+ dst->type= src->type;
+ return 0;
+}
+
+
+MYSQL_FIELD *ma_duplicate_resultset_metadata(MYSQL_FIELD *fields, size_t count,
+ MA_MEM_ROOT *memroot)
+{
+ size_t i;
+ MYSQL_FIELD *result=
+ (MYSQL_FIELD *) ma_alloc_root(memroot, sizeof(MYSQL_FIELD) * count);
+ if (!result)
+ return NULL;
+
+ for (i= 0; i < count; i++)
+ {
+ if (ma_deep_copy_field(&fields[i], &result[i], memroot))
+ return NULL;
+ }
+ return result;
+}
+
+
+int mthd_my_read_query_result(MYSQL *mysql)
+{
+ uchar *pos;
+ ulong field_count;
+ MYSQL_DATA *fields;
+ ulong length;
+ const uchar *end;
+ uchar has_metadata;
+
+ my_bool can_local_infile= (mysql->options.extension) && (mysql->extension->auto_local_infile != WAIT_FOR_QUERY);
+
+ if (mysql->options.extension && mysql->extension->auto_local_infile == ACCEPT_FILE_REQUEST)
+ mysql->extension->auto_local_infile= WAIT_FOR_QUERY;
+
+ if ((length = ma_net_safe_read(mysql)) == packet_error)
+ {
+ return(1);
+ }
+ free_old_query(mysql); /* Free old result */
+get_info:
+ pos=(uchar*) mysql->net.read_pos;
+ end= pos + length;
+ if ((field_count= net_field_length(&pos)) == 0)
+ return ma_read_ok_packet(mysql, pos, length);
+ if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
+ {
+ int error=mysql_handle_local_infile(mysql, (char *)pos, can_local_infile);
+
+ if ((length=ma_net_safe_read(mysql)) == packet_error || error)
+ return(-1);
+ goto get_info; /* Get info packet */
+ }
+
+ has_metadata= 1;
+ if (ma_supports_cache_metadata(mysql))
+ {
+ assert(mysql->fields == NULL);
+ if (pos < end)
+ {
+ has_metadata= *pos;
+ pos++;
+ }
+ }
+
+ if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
+ mysql->server_status|= SERVER_STATUS_IN_TRANS;
+
+ if (has_metadata)
+ {
+ if (!(fields= mysql->methods->db_read_rows(mysql, (MYSQL_FIELD *) 0,
+ ma_result_set_rows(mysql))))
+ return (-1);
+ if (!(mysql->fields= unpack_fields(mysql, fields, &mysql->field_alloc,
+ (uint) field_count, 1)))
+ return (-1);
+ }
+ else
+ {
+ unsigned int last_status= mysql->server_status;
+ /* Read EOF, to get the status and warning count. */
+ if ((length= ma_net_safe_read(mysql)) == packet_error)
+ {
+ return -1;
+ }
+ pos= (uchar *) mysql->net.read_pos;
+ if (length != 5 || pos[0] != 0xfe)
+ {
+ return -1;
+ }
+ mysql->warning_count= uint2korr(pos + 1);
+ mysql->server_status= uint2korr(pos + 3);
+ ma_status_callback(mysql, last_status);
+ }
+ mysql->status=MYSQL_STATUS_GET_RESULT;
+ mysql->field_count=field_count;
+ return(0);
+}
+
+int STDCALL mysql_session_track_get_next(MYSQL *mysql, enum enum_session_state_type type,
+ const char **data, size_t *length)
+{
+ MYSQL_LEX_STRING *str;
+ if (!mysql->extension->session_state[type].current)
+ return 1;
+
+ str= (MYSQL_LEX_STRING *)mysql->extension->session_state[type].current->data;
+ mysql->extension->session_state[type].current= mysql->extension->session_state[type].current->next;
+
+ *data= str->str ? str->str : NULL;
+ *length= str->str ? str->length : 0;
+ return 0;
+}
+
+int STDCALL mysql_session_track_get_first(MYSQL *mysql, enum enum_session_state_type type,
+ const char **data, size_t *length)
+{
+ mysql->extension->session_state[type].current= mysql->extension->session_state[type].list;
+ return mysql_session_track_get_next(mysql, type, data, length);
+}
+
+my_bool STDCALL
+mysql_read_query_result(MYSQL *mysql)
+{
+ return test(mysql->methods->db_read_query_result(mysql)) ? 1 : 0;
+}
+
+int STDCALL
+mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)
+{
+ my_bool skip_result= OPT_EXT_VAL(mysql, multi_command);
+
+ if (length == (unsigned long)-1)
+ length= (unsigned long)strlen(query);
+
+ free_old_query(mysql);
+
+ if (ma_simple_command(mysql, COM_QUERY,query,length,1,0))
+ return(-1);
+ if (!skip_result && !mysql->options.extension->skip_read_response)
+ return(mysql->methods->db_read_query_result(mysql));
+ return(0);
+}
+
+/**************************************************************************
+** Alloc result struct for buffered results. All rows are read to buffer.
+** mysql_data_seek may be used.
+**************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_store_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+
+ if (!mysql->fields)
+ return(0);
+ if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ {
+ SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ mysql->status=MYSQL_STATUS_READY; /* server is ready */
+ if (!(result=(MYSQL_RES*) calloc(1, sizeof(MYSQL_RES)+
+ sizeof(ulong)*mysql->field_count)))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ result->eof=1; /* Marker for buffered */
+ result->lengths=(ulong*) (result+1);
+ if (!(result->data=mysql->methods->db_read_rows(mysql,mysql->fields,mysql->field_count)))
+ {
+ free(result);
+ return(0);
+ }
+ mysql->affected_rows= result->row_count= result->data->rows;
+ result->data_cursor= result->data->data;
+ result->fields= mysql->fields;
+ result->field_alloc= mysql->field_alloc;
+ result->field_count= mysql->field_count;
+ result->current_field=0;
+ result->current_row=0; /* Must do a fetch first */
+ mysql->fields=0; /* fields is now in result */
+ return(result); /* Data fetched */
+}
+
+
+/**************************************************************************
+** Alloc struct for use with unbuffered reads. Data is fetched by domand
+** when calling to mysql_fetch_row.
+** mysql_data_seek is a noop.
+**
+** No other queries may be specified with the same MYSQL handle.
+** There shouldn't be much processing per row because mysql server shouldn't
+** have to wait for the client (and will not wait more than 30 sec/packet).
+**************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_use_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+
+ if (!mysql->fields)
+ return(0);
+ if (mysql->status != MYSQL_STATUS_GET_RESULT)
+ {
+ SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ if (!(result=(MYSQL_RES*) calloc(1, sizeof(*result)+
+ sizeof(ulong)*mysql->field_count)))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ result->lengths=(ulong*) (result+1);
+ if (!(result->row=(MYSQL_ROW)
+ malloc(sizeof(result->row[0])*(mysql->field_count+1))))
+ { /* Ptrs: to one row */
+ free(result);
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(0);
+ }
+ result->fields= mysql->fields;
+ result->field_alloc= mysql->field_alloc;
+ result->field_count= mysql->field_count;
+ result->current_field=0;
+ result->handle= mysql;
+ result->current_row= 0;
+ mysql->fields=0; /* fields is now in result */
+ mysql->status=MYSQL_STATUS_USE_RESULT;
+ return(result); /* Data is read to be fetched */
+}
+
+/**************************************************************************
+** Return next field of the query results
+**************************************************************************/
+MYSQL_FIELD * STDCALL
+mysql_fetch_field(MYSQL_RES *result)
+{
+ if (result->current_field >= result->field_count)
+ return(NULL);
+ return &result->fields[result->current_field++];
+}
+
+
+/**************************************************************************
+** Return mysql field metadata
+**************************************************************************/
+int STDCALL
+mariadb_field_attr(MARIADB_CONST_STRING *attr,
+ const MYSQL_FIELD *field,
+ enum mariadb_field_attr_t type)
+{
+ MA_FIELD_EXTENSION *ext= (MA_FIELD_EXTENSION*) field->extension;
+ if (!ext || type > MARIADB_FIELD_ATTR_LAST)
+ {
+ *attr= null_const_string;
+ return 1;
+ }
+ *attr= ext->metadata[type];
+ return 0;
+}
+
+
+/**************************************************************************
+** Return next row of the query results
+**************************************************************************/
+MYSQL_ROW STDCALL
+mysql_fetch_row(MYSQL_RES *res)
+{
+ if (!res)
+ return 0;
+ if (res->handle)
+ {
+ if (res->handle->status != MYSQL_STATUS_USE_RESULT &&
+ res->handle->status != MYSQL_STATUS_GET_RESULT)
+ return 0;
+ }
+ if (!res->data)
+ { /* Unbufferred fetch */
+ if (!res->eof && res->handle)
+ {
+ if (!(res->handle->methods->db_read_one_row(res->handle,res->field_count,res->row, res->lengths)))
+ {
+ res->row_count++;
+ return(res->current_row=res->row);
+ }
+ res->eof=1;
+ res->handle->status=MYSQL_STATUS_READY;
+ /* Don't clear handle in mysql_free_results */
+ res->handle=0;
+ }
+ return((MYSQL_ROW) NULL);
+ }
+ {
+ MYSQL_ROW tmp;
+ if (!res->data_cursor)
+ {
+ return(res->current_row=(MYSQL_ROW) NULL);
+ }
+ tmp = res->data_cursor->data;
+ res->data_cursor = res->data_cursor->next;
+ return(res->current_row=tmp);
+ }
+}
+
+/**************************************************************************
+** Get column lengths of the current row
+** If one uses mysql_use_result, res->lengths contains the length information,
+** else the lengths are calculated from the offset between pointers.
+**************************************************************************/
+
+ulong * STDCALL
+mysql_fetch_lengths(MYSQL_RES *res)
+{
+ ulong *lengths,*prev_length;
+ char *start;
+ MYSQL_ROW column,end;
+
+ if (!(column=res->current_row))
+ return 0; /* Something is wrong */
+ if (res->data)
+ {
+ start=0;
+ prev_length=0; /* Keep gcc happy */
+ lengths=res->lengths;
+ for (end=column+res->field_count+1 ; column != end ; column++,lengths++)
+ {
+ if (!*column)
+ {
+ *lengths=0; /* Null */
+ continue;
+ }
+ if (start) /* Found end of prev string */
+ *prev_length= (uint) (*column-start-1);
+ start= *column;
+ prev_length=lengths;
+ }
+ }
+ return res->lengths;
+}
+
+/**************************************************************************
+** Move to a specific row and column
+**************************************************************************/
+
+void STDCALL
+mysql_data_seek(MYSQL_RES *result, unsigned long long row)
+{
+ MYSQL_ROWS *tmp=0;
+ if (result->data)
+ for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
+ result->current_row=0;
+ result->data_cursor = tmp;
+}
+
+/*************************************************************************
+** put the row or field cursor one a position one got from mysql_row_tell()
+** This doesn't restore any data. The next mysql_fetch_row or
+** mysql_fetch_field will return the next row or field after the last used
+*************************************************************************/
+
+MYSQL_ROW_OFFSET STDCALL
+mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row)
+{
+ MYSQL_ROW_OFFSET return_value=result->data_cursor;
+ result->current_row= 0;
+ result->data_cursor= row;
+ return return_value;
+}
+
+
+MYSQL_FIELD_OFFSET STDCALL
+mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset)
+{
+ MYSQL_FIELD_OFFSET return_value=result->current_field;
+ result->current_field=field_offset;
+ return return_value;
+}
+
+/********************************************************
+ Warning: mysql_list_dbs is deprecated and will be
+ removed. Use SQL statement "SHOW DATABASES"
+ instead
+ ********************************************************/
+
+/*****************************************************************************
+** List all databases
+*****************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_list_dbs(MYSQL *mysql, const char *wild)
+{
+ char buff[255];
+ snprintf(buff, 255, "SHOW DATABASES LIKE '%s'", wild ? wild : "%");
+ if (mysql_query(mysql,buff))
+ return(0);
+ return (mysql_store_result(mysql));
+}
+
+
+/********************************************************
+ Warning: mysql_list_tables is deprecated and will be
+ removed. Use SQL statement "SHOW TABLES"
+ instead
+ ********************************************************/
+/*****************************************************************************
+** List all tables in a database
+** If wild is given then only the tables matching wild are returned
+*****************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_list_tables(MYSQL *mysql, const char *wild)
+{
+ char buff[255];
+
+ snprintf(buff, 255, "SHOW TABLES LIKE '%s'", wild ? wild : "%");
+ if (mysql_query(mysql,buff))
+ return(0);
+ return (mysql_store_result(mysql));
+}
+
+
+/**************************************************************************
+** List all fields in a table
+** If wild is given then only the fields matching wild are returned
+** Instead of this use query:
+** show fields in 'table' like "wild"
+**************************************************************************/
+
+MYSQL_RES * STDCALL
+mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
+{
+ MYSQL_RES *result;
+ MYSQL_DATA *query;
+ char buff[255];
+ int length= 0;
+
+ LINT_INIT(query);
+
+ length= snprintf(buff, 128, "%s%c%s", table, '\0', wild ? wild : "");
+
+ if (ma_simple_command(mysql, COM_FIELD_LIST,buff,length,1,0) ||
+ !(query = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,
+ ma_result_set_rows(mysql))))
+ return(NULL);
+
+ free_old_query(mysql);
+ if (!(result = (MYSQL_RES *) calloc(1, sizeof(MYSQL_RES))))
+ {
+ free_rows(query);
+ return(NULL);
+ }
+ result->field_alloc=mysql->field_alloc;
+ mysql->fields=0;
+ result->eof=1;
+ result->field_count = (uint) query->rows;
+ result->fields= unpack_fields(mysql, query, &result->field_alloc,
+ result->field_count, 1);
+ if (result->fields)
+ return(result);
+
+ free(result);
+ return(NULL);
+}
+
+/********************************************************
+ Warning: mysql_list_processes is deprecated and will be
+ removed. Use SQL statement "SHOW PROCESSLIST"
+ instead
+ ********************************************************/
+
+/* List all running processes (threads) in server */
+
+MYSQL_RES * STDCALL
+mysql_list_processes(MYSQL *mysql)
+{
+ MYSQL_DATA *fields;
+ uint field_count;
+ uchar *pos;
+
+ LINT_INIT(fields);
+ if (ma_simple_command(mysql, COM_PROCESS_INFO,0,0,0,0))
+ return(NULL);
+ free_old_query(mysql);
+ pos=(uchar*) mysql->net.read_pos;
+ field_count=(uint) net_field_length(&pos);
+ if (!(fields = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,7)))
+ return(NULL);
+ if (!(mysql->fields= unpack_fields(mysql, fields, &mysql->field_alloc,
+ field_count, 0)))
+ return(NULL);
+ mysql->status=MYSQL_STATUS_GET_RESULT;
+ mysql->field_count=field_count;
+ return(mysql_store_result(mysql));
+}
+
+/* In 5.0 this version became an additional parameter shutdown_level */
+int STDCALL
+mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
+{
+ uchar s_level[2];
+ s_level[0]= (uchar)shutdown_level;
+ return(ma_simple_command(mysql, COM_SHUTDOWN, (char *)s_level, 1, 0, 0));
+}
+
+int STDCALL
+mysql_refresh(MYSQL *mysql,uint options)
+{
+ uchar bits[1];
+ bits[0]= (uchar) options;
+ return(ma_simple_command(mysql, COM_REFRESH,(char*) bits,1,0,0));
+}
+
+int STDCALL
+mysql_kill(MYSQL *mysql,ulong pid)
+{
+ char buff[12];
+ int4store(buff,pid);
+ /* if we kill our own thread, reading the response packet will fail */
+ return(ma_simple_command(mysql, COM_PROCESS_KILL,buff,4,0,0));
+}
+
+
+int STDCALL
+mysql_dump_debug_info(MYSQL *mysql)
+{
+ return(ma_simple_command(mysql, COM_DEBUG,0,0,0,0));
+}
+
+char * STDCALL
+mysql_stat(MYSQL *mysql)
+{
+ if (ma_simple_command(mysql, COM_STATISTICS,0,0,0,0))
+ return mysql->net.last_error;
+ mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
+ if (!mysql->net.read_pos[0])
+ {
+ SET_CLIENT_ERROR(mysql, CR_WRONG_HOST_INFO , SQLSTATE_UNKNOWN, 0);
+ return mysql->net.last_error;
+ }
+ return((char*) mysql->net.read_pos);
+}
+
+int STDCALL
+mysql_ping(MYSQL *mysql)
+{
+ int rc;
+ rc= ma_simple_command(mysql, COM_PING, 0, 0, 0, 0);
+ if (rc && mysql->options.reconnect)
+ rc= ma_simple_command(mysql, COM_PING, 0, 0, 0, 0);
+ return rc;
+}
+
+char * STDCALL
+mysql_get_server_info(MYSQL *mysql)
+{
+ return((char*) mysql->server_version);
+}
+
+static size_t mariadb_server_version_id(MYSQL *mysql)
+{
+ size_t major, minor, patch;
+ char *p;
+
+ if (!(p = mysql->server_version)) {
+ return 0;
+ }
+
+ major = strtol(p, &p, 10);
+ p += 1; /* consume the dot */
+ minor = strtol(p, &p, 10);
+ p += 1; /* consume the dot */
+ patch = strtol(p, &p, 10);
+
+ return (major * 10000L + (unsigned long)(minor * 100L + patch));
+}
+
+unsigned long STDCALL mysql_get_server_version(MYSQL *mysql)
+{
+ return (unsigned long)mariadb_server_version_id(mysql);
+}
+
+char * STDCALL
+mysql_get_host_info(MYSQL *mysql)
+{
+ return(mysql->host_info);
+}
+
+uint STDCALL
+mysql_get_proto_info(MYSQL *mysql)
+{
+ return (mysql->protocol_version);
+}
+
+const char * STDCALL
+mysql_get_client_info(void)
+{
+ return (char*) MARIADB_PACKAGE_VERSION;
+}
+
+static size_t get_store_length(size_t length)
+{
+ #define MAX_STORE_SIZE 9
+ unsigned char buffer[MAX_STORE_SIZE], *p;
+
+ /* We just store the length and subtract offset of our buffer
+ to determine the length */
+ p= mysql_net_store_length(buffer, length);
+ return p - buffer;
+}
+
+uchar *ma_get_hash_keyval(const uchar *hash_entry,
+ unsigned int *length,
+ my_bool not_used __attribute__((unused)))
+{
+ /* Hash entry has the following format:
+ Offset: 0 key (\0 terminated)
+ key_length + 1 value (\0 terminated)
+ */
+ uchar *p= (uchar *)hash_entry;
+ size_t len= strlen((char *)p);
+ *length= (unsigned int)len;
+ return p;
+}
+
+void ma_int_hash_free(void *p)
+{
+ free(p);
+}
+
+int
+mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
+{
+ va_list ap;
+ void *arg1;
+ size_t stacksize;
+ struct mysql_async_context *ctxt;
+
+ va_start(ap, option);
+
+ arg1= va_arg(ap, void *);
+
+ switch (option) {
+ case MYSQL_OPT_CONNECT_TIMEOUT:
+ mysql->options.connect_timeout= *(uint*) arg1;
+ break;
+ case MYSQL_OPT_COMPRESS:
+ mysql->options.compress= 1; /* Remember for connect */
+ mysql->options.client_flag|= CLIENT_COMPRESS;
+ break;
+ case MYSQL_OPT_NAMED_PIPE:
+ mysql->options.named_pipe=1; /* Force named pipe */
+ break;
+ case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
+ if (!arg1 || test(*(unsigned int*) arg1))
+ mysql->options.client_flag|= CLIENT_LOCAL_FILES;
+ else
+ mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
+ if (arg1) {
+ CHECK_OPT_EXTENSION_SET(&mysql->options);
+ mysql->extension->auto_local_infile= *(uint*)arg1 == LOCAL_INFILE_MODE_AUTO
+ ? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
+ }
+ break;
+ case MYSQL_INIT_COMMAND:
+ options_add_initcommand(&mysql->options, (char *)arg1);
+ break;
+ case MYSQL_READ_DEFAULT_FILE:
+ OPT_SET_VALUE_STR(&mysql->options, my_cnf_file, (char *)arg1);
+ break;
+ case MYSQL_READ_DEFAULT_GROUP:
+ OPT_SET_VALUE_STR(&mysql->options, my_cnf_group, arg1 ? (char *)arg1 : "");
+ break;
+ case MYSQL_SET_CHARSET_DIR:
+ OPT_SET_VALUE_STR(&mysql->options, charset_dir, arg1);
+ break;
+ case MYSQL_SET_CHARSET_NAME:
+ OPT_SET_VALUE_STR(&mysql->options, charset_name, arg1);
+ break;
+ case MYSQL_OPT_RECONNECT:
+ mysql->options.reconnect= *(my_bool *)arg1;
+ break;
+ case MYSQL_OPT_PROTOCOL:
+ mysql->options.protocol= *((uint *)arg1);
+ break;
+#ifdef _WIN32
+ case MYSQL_SHARED_MEMORY_BASE_NAME:
+ OPT_SET_VALUE_STR(&mysql->options, shared_memory_base_name, arg1);
+ break;
+#endif
+ case MYSQL_OPT_READ_TIMEOUT:
+ mysql->options.read_timeout= *(uint *)arg1;
+ break;
+ case MYSQL_OPT_WRITE_TIMEOUT:
+ mysql->options.write_timeout= *(uint *)arg1;
+ break;
+ case MYSQL_REPORT_DATA_TRUNCATION:
+ mysql->options.report_data_truncation= *(my_bool *)arg1;
+ break;
+ case MYSQL_PROGRESS_CALLBACK:
+ CHECK_OPT_EXTENSION_SET(&mysql->options);
+ if (mysql->options.extension)
+ mysql->options.extension->report_progress=
+ (void (*)(const MYSQL *, uint, uint, double, const char *, uint)) arg1;
+ break;
+ case MYSQL_SERVER_PUBLIC_KEY:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, server_public_key, (char *)arg1);
+ break;
+ case MYSQL_PLUGIN_DIR:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, plugin_dir, (char *)arg1);
+ break;
+ case MYSQL_DEFAULT_AUTH:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, default_auth, (char *)arg1);
+ break;
+ case MYSQL_OPT_NONBLOCK:
+ if (mysql->options.extension &&
+ (ctxt = mysql->options.extension->async_context) != 0)
+ {
+ /*
+ We must not allow changing the stack size while a non-blocking call is
+ suspended (as the stack is then in use).
+ */
+ if (ctxt->suspended)
+ goto end;
+ my_context_destroy(&ctxt->async_context);
+ free(ctxt);
+ }
+ if (!(ctxt= (struct mysql_async_context *)
+ calloc(1, sizeof(*ctxt))))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ stacksize= 0;
+ if (arg1)
+ stacksize= *(const size_t *)arg1;
+ if (!stacksize)
+ stacksize= ASYNC_CONTEXT_DEFAULT_STACK_SIZE;
+ if (my_context_init(&ctxt->async_context, stacksize))
+ {
+ free(ctxt);
+ goto end;
+ }
+ if (!mysql->options.extension)
+ if(!(mysql->options.extension= (struct st_mysql_options_extension *)
+ calloc(1, sizeof(struct st_mysql_options_extension))))
+ {
+ free(ctxt);
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ mysql->options.extension->async_context= ctxt;
+ break;
+ case MYSQL_OPT_MAX_ALLOWED_PACKET:
+ if (mysql)
+ mysql->options.max_allowed_packet= (unsigned long)(*(size_t *)arg1);
+ else
+ max_allowed_packet= (unsigned long)(*(size_t *)arg1);
+ break;
+ case MYSQL_OPT_NET_BUFFER_LENGTH:
+ net_buffer_length= (unsigned long)(*(size_t *)arg1);
+ break;
+ case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
+ if (*(my_bool *)arg1)
+ mysql->options.client_flag |= CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS;
+ else
+ mysql->options.client_flag &= ~CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS;
+ break;
+ case MYSQL_OPT_SSL_ENFORCE:
+ mysql->options.use_ssl= (*(my_bool *)arg1);
+ break;
+ case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
+ OPT_SET_EXTENDED_VALUE(&mysql->options, tls_verify_server_cert, *(my_bool *)arg1);
+ break;
+ case MYSQL_OPT_SSL_KEY:
+ OPT_SET_VALUE_STR(&mysql->options, ssl_key, (char *)arg1);
+ break;
+ case MYSQL_OPT_SSL_CERT:
+ OPT_SET_VALUE_STR(&mysql->options, ssl_cert, (char *)arg1);
+ break;
+ case MYSQL_OPT_SSL_CA:
+ OPT_SET_VALUE_STR(&mysql->options, ssl_ca, (char *)arg1);
+ break;
+ case MYSQL_OPT_SSL_CAPATH:
+ OPT_SET_VALUE_STR(&mysql->options, ssl_capath, (char *)arg1);
+ break;
+ case MYSQL_OPT_SSL_CIPHER:
+ OPT_SET_VALUE_STR(&mysql->options, ssl_cipher, (char *)arg1);
+ break;
+ case MYSQL_OPT_SSL_CRL:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crl, (char *)arg1);
+ break;
+ case MYSQL_OPT_SSL_CRLPATH:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crlpath, (char *)arg1);
+ break;
+ case MYSQL_OPT_CONNECT_ATTR_DELETE:
+ {
+ uchar *h;
+ CHECK_OPT_EXTENSION_SET(&mysql->options);
+ if (ma_hashtbl_inited(&mysql->options.extension->connect_attrs) &&
+ (h= (uchar *)ma_hashtbl_search(&mysql->options.extension->connect_attrs, (uchar *)arg1,
+ arg1 ? (uint)strlen((char *)arg1) : 0)))
+ {
+ uchar *p= h;
+ size_t key_len= strlen((char *)p);
+ mysql->options.extension->connect_attrs_len-= key_len + get_store_length(key_len);
+ p+= key_len + 1;
+ key_len= strlen((char *)p);
+ mysql->options.extension->connect_attrs_len-= key_len + get_store_length(key_len);
+ ma_hashtbl_delete(&mysql->options.extension->connect_attrs, h);
+ }
+
+ }
+ break;
+ case MYSQL_OPT_CONNECT_ATTR_RESET:
+ CHECK_OPT_EXTENSION_SET(&mysql->options);
+ if (ma_hashtbl_inited(&mysql->options.extension->connect_attrs))
+ {
+ ma_hashtbl_free(&mysql->options.extension->connect_attrs);
+ mysql->options.extension->connect_attrs_len= 0;
+ }
+ break;
+ case MARIADB_OPT_CONNECTION_HANDLER:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, connection_handler, (char *)arg1);
+ break;
+ case MARIADB_OPT_PORT:
+ OPT_SET_VALUE_INT(&mysql->options, port, *((uint *)arg1));
+ break;
+ case MARIADB_OPT_UNIXSOCKET:
+ OPT_SET_VALUE_STR(&mysql->options, unix_socket, arg1);
+ break;
+ case MARIADB_OPT_USER:
+ OPT_SET_VALUE_STR(&mysql->options, user, arg1);
+ break;
+ case MARIADB_OPT_HOST:
+ OPT_SET_VALUE_STR(&mysql->options, host, arg1);
+ break;
+ case MARIADB_OPT_SCHEMA:
+ OPT_SET_VALUE_STR(&mysql->options, db, arg1);
+ break;
+ case MARIADB_OPT_DEBUG:
+ break;
+ case MARIADB_OPT_FOUND_ROWS:
+ mysql->options.client_flag|= CLIENT_FOUND_ROWS;
+ break;
+ case MARIADB_OPT_INTERACTIVE:
+ mysql->options.client_flag|= CLIENT_INTERACTIVE;
+ break;
+ case MARIADB_OPT_MULTI_RESULTS:
+ mysql->options.client_flag|= CLIENT_MULTI_RESULTS;
+ break;
+ case MARIADB_OPT_MULTI_STATEMENTS:
+ mysql->options.client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
+ break;
+ case MARIADB_OPT_PASSWORD:
+ OPT_SET_VALUE_STR(&mysql->options, password, arg1);
+ break;
+ case MARIADB_OPT_USERDATA:
+ {
+ void *data= va_arg(ap, void *);
+ uchar *buffer, *p;
+ char *key= (char *)arg1;
+
+ if (!key || !data)
+ {
+ SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+
+ CHECK_OPT_EXTENSION_SET(&mysql->options);
+ if (!ma_hashtbl_inited(&mysql->options.extension->userdata))
+ {
+ if (_ma_hashtbl_init(&mysql->options.extension->userdata,
+ 0, 0, 0, ma_get_hash_keyval, ma_int_hash_free, 0))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ }
+ /* check if key is already in buffer */
+ p= (uchar *)ma_hashtbl_search(&mysql->options.extension->userdata,
+ (uchar *)key,
+ (uint)strlen(key));
+ if (p)
+ {
+ p+= strlen(key) + 1;
+ memcpy(p, &data, sizeof(void *));
+ break;
+ }
+
+ if (!(buffer= (uchar *)malloc(strlen(key) + 1 + sizeof(void *))))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+
+ p= buffer;
+ strcpy((char *)p, key);
+ p+= strlen(key) + 1;
+ memcpy(p, &data, sizeof(void *));
+
+ if (ma_hashtbl_insert(&mysql->options.extension->userdata, buffer))
+ {
+ free(buffer);
+ SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ }
+ break;
+ case MYSQL_OPT_CONNECT_ATTR_ADD:
+ {
+ uchar *buffer;
+ void *arg2= va_arg(ap, void *);
+ size_t storage_len, key_len= arg1 ? strlen((char *)arg1) : 0,
+ value_len= arg2 ? strlen((char *)arg2) : 0;
+ if (!key_len || !value_len)
+ {
+ SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ storage_len= key_len + value_len +
+ get_store_length(key_len) +
+ get_store_length(value_len);
+
+ /* since we store terminating zero character in hash, we need
+ * to increase lengths */
+ key_len++;
+ value_len++;
+
+ CHECK_OPT_EXTENSION_SET(&mysql->options);
+ if (!key_len ||
+ storage_len + mysql->options.extension->connect_attrs_len > 0xFFFF)
+ {
+ SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+
+ if (!ma_hashtbl_inited(&mysql->options.extension->connect_attrs))
+ {
+ if (_ma_hashtbl_init(&mysql->options.extension->connect_attrs,
+ 0, 0, 0, ma_get_hash_keyval, ma_int_hash_free, 0))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ }
+ if ((buffer= (uchar *)malloc(key_len + value_len)))
+ {
+ uchar *p= buffer;
+ strcpy((char *)p, arg1);
+ p+= (strlen(arg1) + 1);
+ if (arg2)
+ strcpy((char *)p, arg2);
+
+ if (ma_hashtbl_insert(&mysql->options.extension->connect_attrs, buffer))
+ {
+ free(buffer);
+ SET_CLIENT_ERROR(mysql, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ mysql->options.extension->connect_attrs_len+= storage_len;
+ }
+ else
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto end;
+ }
+ }
+ break;
+ case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
+ break;
+ case MYSQL_SECURE_AUTH:
+ mysql->options.secure_auth= *(my_bool *)arg1;
+ break;
+ case MYSQL_OPT_BIND:
+ OPT_SET_VALUE_STR(&mysql->options, bind_address, arg1);
+ break;
+ case MARIADB_OPT_TLS_CIPHER_STRENGTH:
+ OPT_SET_EXTENDED_VALUE_INT(&mysql->options, tls_cipher_strength, *((unsigned int *)arg1));
+ break;
+ case MARIADB_OPT_SSL_FP:
+ case MARIADB_OPT_TLS_PEER_FP:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, tls_fp, (char *)arg1);
+ mysql->options.use_ssl= 1;
+ break;
+ case MARIADB_OPT_SSL_FP_LIST:
+ case MARIADB_OPT_TLS_PEER_FP_LIST:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, tls_fp_list, (char *)arg1);
+ mysql->options.use_ssl= 1;
+ break;
+ case MARIADB_OPT_TLS_PASSPHRASE:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, tls_pw, (char *)arg1);
+ break;
+ case MARIADB_OPT_CONNECTION_READ_ONLY:
+ OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1);
+ break;
+ case MARIADB_OPT_PROXY_HEADER:
+ {
+ size_t arg2 = va_arg(ap, size_t);
+ OPT_SET_EXTENDED_VALUE_BIN(&mysql->options, proxy_header, proxy_header_len, (char *)arg1, arg2);
+ }
+ break;
+ case MARIADB_OPT_TLS_VERSION:
+ case MYSQL_OPT_TLS_VERSION:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, tls_version, (char *)arg1);
+ break;
+ case MARIADB_OPT_IO_WAIT:
+ CHECK_OPT_EXTENSION_SET(&mysql->options);
+ mysql->options.extension->io_wait = (int(*)(my_socket, my_bool, int))arg1;
+ break;
+ case MARIADB_OPT_SKIP_READ_RESPONSE:
+ OPT_SET_EXTENDED_VALUE_INT(&mysql->options, skip_read_response, *(my_bool *)arg1);
+ break;
+ case MARIADB_OPT_RESTRICTED_AUTH:
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, restricted_auth, (char *)arg1);
+ break;
+ case MARIADB_OPT_RPL_REGISTER_REPLICA:
+ {
+ unsigned int arg2 = va_arg(ap, unsigned int);
+ OPT_SET_EXTENDED_VALUE_STR(&mysql->options, rpl_host,(char *)arg1);
+ OPT_SET_EXTENDED_VALUE(&mysql->options, rpl_port, (ushort)arg2);
+ }
+ break;
+ case MARIADB_OPT_STATUS_CALLBACK:
+ {
+ void *arg2= va_arg(ap, void *);
+ if (arg1 || arg2)
+ {
+ if (arg1) {
+ OPT_SET_EXTENDED_VALUE(&mysql->options, status_callback, arg1);
+ }
+ if (arg2) {
+ OPT_SET_EXTENDED_VALUE(&mysql->options, status_data, arg2);
+ }
+ } else {
+ OPT_SET_EXTENDED_VALUE(&mysql->options, status_callback, ma_save_session_track_info);
+ OPT_SET_EXTENDED_VALUE(&mysql->options, status_data, mysql);
+ }
+ }
+ break;
+ default:
+ va_end(ap);
+ SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ va_end(ap);
+ return(0);
+end:
+ va_end(ap);
+ return(1);
+}
+
+int
+mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+
+ switch(option) {
+ case MYSQL_OPT_CONNECT_TIMEOUT:
+ *((uint *)arg)= mysql->options.connect_timeout;
+ break;
+ case MYSQL_OPT_COMPRESS:
+ *((my_bool *)arg)= mysql->options.compress;
+ break;
+ case MYSQL_OPT_NAMED_PIPE:
+ *((my_bool *)arg)= mysql->options.named_pipe;
+ break;
+ case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
+ *((uint *)arg)= test(mysql->options.client_flag & CLIENT_LOCAL_FILES);
+ break;
+ case MYSQL_INIT_COMMAND:
+ /* mysql_get_optionsv(mysql, MYSQL_INIT_COMMAND, commands, elements) */
+ {
+ unsigned int *elements;
+ if (arg)
+ *((char **)arg)= mysql->options.init_command ? mysql->options.init_command->buffer : NULL;
+ if ((elements= va_arg(ap, unsigned int *)))
+ *elements= mysql->options.init_command ? mysql->options.init_command->elements : 0;
+ }
+ break;
+ case MYSQL_READ_DEFAULT_FILE:
+ *((char **)arg)= mysql->options.my_cnf_file;
+ break;
+ case MYSQL_READ_DEFAULT_GROUP:
+ *((char **)arg)= mysql->options.my_cnf_group;
+ break;
+ case MYSQL_SET_CHARSET_DIR:
+ /* not supported in this version. Since all character sets
+ are internally available, we don't throw an error */
+ *((char **)arg)= NULL;
+ break;
+ case MYSQL_SET_CHARSET_NAME:
+ if (mysql->charset)
+ *((const char **)arg)= mysql->charset->csname;
+ else
+ *((char **)arg)= mysql->options.charset_name;
+ break;
+ case MYSQL_OPT_RECONNECT:
+ *((my_bool *)arg)= mysql->options.reconnect;
+ break;
+ case MYSQL_OPT_PROTOCOL:
+ *((uint *)arg)= mysql->options.protocol;
+ break;
+ case MYSQL_OPT_READ_TIMEOUT:
+ *((uint *)arg)= mysql->options.read_timeout;
+ break;
+ case MYSQL_OPT_WRITE_TIMEOUT:
+ *((uint *)arg)= mysql->options.write_timeout;
+ break;
+ case MYSQL_REPORT_DATA_TRUNCATION:
+ *((my_bool *)arg)= mysql->options.report_data_truncation;
+ break;
+ case MYSQL_PROGRESS_CALLBACK:
+ *((void (**)(const MYSQL *, uint, uint, double, const char *, uint))arg)=
+ mysql->options.extension ? mysql->options.extension->report_progress : NULL;
+ break;
+ case MYSQL_SERVER_PUBLIC_KEY:
+ *((char **)arg)= mysql->options.extension ?
+ mysql->options.extension->server_public_key : NULL;
+ break;
+ case MYSQL_PLUGIN_DIR:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->plugin_dir : NULL;
+ break;
+ case MYSQL_DEFAULT_AUTH:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->default_auth : NULL;
+ break;
+ case MYSQL_OPT_NONBLOCK:
+ *((my_bool *)arg)= test(mysql->options.extension && mysql->options.extension->async_context);
+ break;
+ case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
+ *((my_bool *)arg)= test(mysql->options.client_flag & CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS);
+ break;
+ case MYSQL_OPT_SSL_ENFORCE:
+ *((my_bool *)arg)= mysql->options.use_ssl;
+ break;
+ case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
+ *((my_bool*)arg) = mysql->options.extension ? mysql->options.extension->tls_verify_server_cert : 0;
+ break;
+ case MYSQL_OPT_SSL_KEY:
+ *((char **)arg)= mysql->options.ssl_key;
+ break;
+ case MYSQL_OPT_SSL_CERT:
+ *((char **)arg)= mysql->options.ssl_cert;
+ break;
+ case MYSQL_OPT_SSL_CA:
+ *((char **)arg)= mysql->options.ssl_ca;
+ break;
+ case MYSQL_OPT_SSL_CAPATH:
+ *((char **)arg)= mysql->options.ssl_capath;
+ break;
+ case MYSQL_OPT_SSL_CIPHER:
+ *((char **)arg)= mysql->options.ssl_cipher;
+ break;
+ case MYSQL_OPT_SSL_CRL:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_crl : NULL;
+ break;
+ case MYSQL_OPT_SSL_CRLPATH:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_crlpath : NULL;
+ break;
+ case MARIADB_OPT_TLS_VERSION:
+ case MYSQL_OPT_TLS_VERSION:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->tls_version : NULL;
+ break;
+ case MYSQL_OPT_CONNECT_ATTRS:
+ /* mysql_get_optionsv(mysql, MYSQL_OPT_CONNECT_ATTRS, keys, vals, elements) */
+ {
+ unsigned int i, *elements;
+ char **key= NULL;
+ void *arg1;
+ char **val= NULL;
+
+ if (arg)
+ key= *(char ***)arg;
+
+ arg1= va_arg(ap, char **);
+ if (arg1)
+ val= *(char ***)arg1;
+
+ if (!(elements= va_arg(ap, unsigned int *)))
+ goto error;
+
+ *elements= 0;
+
+ if (!mysql->options.extension ||
+ !ma_hashtbl_inited(&mysql->options.extension->connect_attrs))
+ break;
+
+ *elements= mysql->options.extension->connect_attrs.records;
+
+ if (val || key)
+ {
+ for (i=0; i < *elements; i++)
+ {
+ uchar *p= ma_hashtbl_element(&mysql->options.extension->connect_attrs, i);
+ if (key)
+ key[i]= (char *)p;
+ p+= strlen((char *)p) + 1;
+ if (val)
+ val[i]= (char *)p;
+ }
+ }
+ }
+ break;
+ case MYSQL_OPT_MAX_ALLOWED_PACKET:
+ *((unsigned long *)arg)= (mysql) ? mysql->options.max_allowed_packet :
+ max_allowed_packet;
+ break;
+ case MYSQL_OPT_NET_BUFFER_LENGTH:
+ *((unsigned long *)arg)= net_buffer_length;
+ break;
+ case MYSQL_SECURE_AUTH:
+ *((my_bool *)arg)= mysql->options.secure_auth;
+ break;
+ case MYSQL_OPT_BIND:
+ *((char **)arg)= mysql->options.bind_address;
+ break;
+ case MARIADB_OPT_TLS_CIPHER_STRENGTH:
+ *((unsigned int *)arg) = mysql->options.extension ? mysql->options.extension->tls_cipher_strength : 0;
+ break;
+ case MARIADB_OPT_SSL_FP:
+ case MARIADB_OPT_TLS_PEER_FP:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->tls_fp : NULL;
+ break;
+ case MARIADB_OPT_SSL_FP_LIST:
+ case MARIADB_OPT_TLS_PEER_FP_LIST:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->tls_fp_list : NULL;
+ break;
+ case MARIADB_OPT_TLS_PASSPHRASE:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->tls_pw : NULL;
+ break;
+ case MARIADB_OPT_CONNECTION_READ_ONLY:
+ *((my_bool *)arg)= mysql->options.extension ? mysql->options.extension->read_only : 0;
+ break;
+ case MARIADB_OPT_USERDATA:
+ /* nysql_get_optionv(mysql, MARIADB_OPT_USERDATA, key, value) */
+ {
+ uchar *p;
+ void *data= va_arg(ap, void *);
+ char *key= (char *)arg;
+ if (key && data && mysql->options.extension && ma_hashtbl_inited(&mysql->options.extension->userdata) &&
+ (p= (uchar *)ma_hashtbl_search(&mysql->options.extension->userdata, (uchar *)key,
+ (uint)strlen((char *)key))))
+ {
+ p+= strlen(key) + 1;
+ *((void **)data)= *((void **)p);
+ break;
+ }
+ if (data)
+ *((void **)data)= NULL;
+ }
+ break;
+ case MARIADB_OPT_CONNECTION_HANDLER:
+ *((char **)arg)= mysql->options.extension ? mysql->options.extension->connection_handler : NULL;
+ break;
+ case MARIADB_OPT_IO_WAIT:
+ *((int(**)(my_socket, my_bool, int))arg) = mysql->options.extension ? mysql->options.extension->io_wait : NULL;
+ break;
+ case MARIADB_OPT_SKIP_READ_RESPONSE:
+ *((my_bool*)arg)= mysql->options.extension ? mysql->options.extension->skip_read_response : 0;
+ break;
+ default:
+ va_end(ap);
+ SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ va_end(ap);
+ return(0);
+error:
+ va_end(ap);
+ return(1);
+}
+
+int STDCALL mysql_get_option(MYSQL *mysql, enum mysql_option option, void *arg)
+{
+ return mysql_get_optionv(mysql, option, arg);
+}
+
+int STDCALL
+mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
+{
+ return mysql_optionsv(mysql, option, arg);
+}
+
+int STDCALL
+mysql_options4(MYSQL *mysql,enum mysql_option option, const void *arg1, const void *arg2)
+{
+ return mysql_optionsv(mysql, option, arg1, arg2);
+}
+/****************************************************************************
+** Functions to get information from the MySQL structure
+** These are functions to make shared libraries more usable.
+****************************************************************************/
+
+/* MYSQL_RES */
+my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res)
+{
+ return res->row_count;
+}
+
+unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
+{
+ return res->field_count;
+}
+
+/* deprecated */
+my_bool STDCALL mysql_eof(MYSQL_RES *res)
+{
+ return res->eof;
+}
+
+MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr)
+{
+ return &(res)->fields[fieldnr];
+}
+
+MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res)
+{
+ return (res)->fields;
+}
+
+MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res)
+{
+ return res->data_cursor;
+}
+
+uint STDCALL mysql_field_tell(MYSQL_RES *res)
+{
+ return (res)->current_field;
+}
+
+/* MYSQL */
+
+unsigned int STDCALL mysql_field_count(MYSQL *mysql)
+{
+ return mysql->field_count;
+}
+
+my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
+{
+ return (mysql)->affected_rows;
+}
+
+my_bool STDCALL mysql_autocommit(MYSQL *mysql, my_bool mode)
+{
+ return((my_bool) mysql_real_query(mysql, (mode) ? "SET autocommit=1" :
+ "SET autocommit=0", 16));
+}
+
+my_bool STDCALL mysql_commit(MYSQL *mysql)
+{
+ return((my_bool)mysql_real_query(mysql, "COMMIT", (unsigned long)strlen("COMMIT")));
+}
+
+my_bool STDCALL mysql_rollback(MYSQL *mysql)
+{
+ return((my_bool)mysql_real_query(mysql, "ROLLBACK", (unsigned long)strlen("ROLLBACK")));
+}
+
+my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
+{
+ return (mysql)->insert_id;
+}
+
+uint STDCALL mysql_errno(MYSQL *mysql)
+{
+ return mysql ? mysql->net.last_errno : 0;
+}
+
+const char * STDCALL mysql_error(MYSQL *mysql)
+{
+ return mysql ? (mysql)->net.last_error : (char *)"";
+}
+
+const char *STDCALL mysql_info(MYSQL *mysql)
+{
+ return (mysql)->info;
+}
+
+my_bool STDCALL mysql_more_results(MYSQL *mysql)
+{
+ return(test(mysql->server_status & SERVER_MORE_RESULTS_EXIST));
+}
+
+int STDCALL mysql_next_result(MYSQL *mysql)
+{
+
+ /* make sure communication is not blocking */
+ if (mysql->status != MYSQL_STATUS_READY)
+ {
+ SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ /* clear error, and mysql status variables */
+ CLEAR_CLIENT_ERROR(mysql);
+ mysql->affected_rows = (ulonglong) ~0;
+
+ if (mysql->server_status & SERVER_MORE_RESULTS_EXIST)
+ {
+ return(mysql->methods->db_read_query_result(mysql));
+ }
+
+ return(-1);
+}
+
+ulong STDCALL mysql_thread_id(MYSQL *mysql)
+{
+ return (mysql)->thread_id;
+}
+
+const char * STDCALL mysql_character_set_name(MYSQL *mysql)
+{
+ return mysql->charset->csname;
+}
+
+
+uint STDCALL mysql_thread_safe(void)
+{
+#ifdef THREAD
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+/****************************************************************************
+** Some support functions
+****************************************************************************/
+
+/*
+** Add escape characters to a string (blob?) to make it suitable for a insert
+** to should at least have place for length*2+1 chars
+** Returns the length of the to string
+*/
+
+ulong STDCALL
+mysql_escape_string(char *to,const char *from, ulong length)
+{
+ return (ulong)mysql_cset_escape_slashes(ma_default_charset_info, to, from, length);
+}
+
+ulong STDCALL
+mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
+ ulong length)
+{
+ if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
+ return (ulong)mysql_cset_escape_quotes(mysql->charset, to, from, length);
+ else
+ return (ulong)mysql_cset_escape_slashes(mysql->charset, to, from, length);
+}
+
+static void mariadb_get_charset_info(MYSQL *mysql, MY_CHARSET_INFO *cs)
+{
+ if (!cs)
+ return;
+
+ cs->number= mysql->charset->nr;
+ cs->csname= mysql->charset->csname;
+ cs->name= mysql->charset->name;
+ cs->state= 0;
+ cs->comment= NULL;
+ cs->dir= NULL;
+ cs->mbminlen= mysql->charset->char_minlen;
+ cs->mbmaxlen= mysql->charset->char_maxlen;
+
+ return;
+}
+
+void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs)
+{
+ mariadb_get_charset_info(mysql, cs);
+}
+
+int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname)
+{
+ const MARIADB_CHARSET_INFO *cs;
+
+ if (!csname)
+ goto error;
+
+ if ((cs= mysql_find_charset_name(csname)))
+ {
+ char buff[64];
+
+ snprintf(buff, 63, "SET NAMES %s", cs->csname);
+ if (!mysql_real_query(mysql, buff, (unsigned long)strlen(buff)))
+ {
+ mysql->charset= cs;
+ return(0);
+ }
+ return(mysql->net.last_errno);
+ }
+
+error:
+ my_set_error(mysql, CR_CANT_READ_CHARSET, SQLSTATE_UNKNOWN,
+ 0, csname, "compiled_in");
+ return(mysql->net.last_errno);
+}
+
+unsigned int STDCALL mysql_warning_count(MYSQL *mysql)
+{
+ return mysql->warning_count;
+}
+
+const char * STDCALL mysql_sqlstate(MYSQL *mysql)
+{
+ return mysql->net.sqlstate;
+}
+
+#ifndef _WIN32
+#include <signal.h>
+static void ignore_sigpipe()
+{
+ signal(SIGPIPE, SIG_IGN);
+}
+#else
+#define ignore_sigpipe()
+#endif
+
+#ifdef _WIN32
+static int mysql_once_init()
+#else
+static void mysql_once_init()
+#endif
+{
+ ma_init(); /* Will init threads */
+ init_client_errs();
+ get_default_configuration_dirs();
+ set_default_charset_by_name(MARIADB_DEFAULT_CHARSET, 0);
+ if (mysql_client_plugin_init())
+ {
+#ifdef _WIN32
+ return 1;
+#else
+ return;
+#endif
+ }
+ if (!mysql_port)
+ {
+#if !__has_feature(memory_sanitizer) /* work around MSAN deficiency */
+ struct servent *serv_ptr;
+#endif
+ char *env;
+
+ mysql_port = MARIADB_PORT;
+#if !__has_feature(memory_sanitizer) /* work around MSAN deficiency */
+ if ((serv_ptr = getservbyname("mysql", "tcp")))
+ mysql_port = (uint)ntohs((ushort)serv_ptr->s_port);
+#endif
+ if ((env = getenv("MYSQL_TCP_PORT")))
+ mysql_port =(uint)atoi(env);
+ }
+ if (!mysql_unix_port)
+ {
+ char *env;
+#ifdef _WIN32
+ mysql_unix_port = (char*)MARIADB_NAMEDPIPE;
+#else
+ mysql_unix_port = (char*)MARIADB_UNIX_ADDR;
+#endif
+ if ((env = getenv("MYSQL_UNIX_PORT")) ||
+ (env = getenv("MARIADB_UNIX_PORT")))
+ mysql_unix_port = env;
+ }
+ if (!mysql_ps_subsystem_initialized)
+ mysql_init_ps_subsystem();
+#ifdef HAVE_TLS
+ ma_tls_start(0, 0);
+#endif
+ ignore_sigpipe();
+ mysql_client_init = 1;
+#ifdef _WIN32
+ return 0;
+#endif
+}
+
+#ifdef _WIN32
+static INIT_ONCE init_once= INIT_ONCE_STATIC_INIT;
+BOOL CALLBACK win_init_once(
+ PINIT_ONCE InitOnce,
+ PVOID Parameter,
+ PVOID *lpContext)
+{
+ return !mysql_once_init();
+ return TRUE;
+}
+#else
+static pthread_once_t init_once = PTHREAD_ONCE_INIT;
+#endif
+
+int STDCALL mysql_server_init(int argc __attribute__((unused)),
+ char **argv __attribute__((unused)),
+ char **groups __attribute__((unused)))
+{
+#ifdef _WIN32
+ BOOL ret = InitOnceExecuteOnce(&init_once, win_init_once, NULL, NULL);
+ return ret? 0: 1;
+#else
+ return pthread_once(&init_once, mysql_once_init);
+#endif
+}
+
+void STDCALL mysql_server_end(void)
+{
+ if (!mysql_client_init)
+ return;
+
+ release_configuration_dirs();
+ mysql_client_plugin_deinit();
+
+ list_free(pvio_callback, 0);
+ if (ma_init_done)
+ ma_end(0);
+#ifdef HAVE_TLS
+ ma_pvio_tls_end();
+#endif
+ mysql_client_init= 0;
+ ma_init_done= 0;
+#ifdef WIN32
+ init_once = (INIT_ONCE)INIT_ONCE_STATIC_INIT;
+#else
+ init_once = (pthread_once_t)PTHREAD_ONCE_INIT;
+#endif
+}
+
+my_bool STDCALL mysql_thread_init(void)
+{
+ return 0;
+}
+
+void STDCALL mysql_thread_end(void)
+{
+}
+
+int STDCALL mysql_set_server_option(MYSQL *mysql,
+ enum enum_mysql_set_option option)
+{
+ char buffer[2];
+ int2store(buffer, (uint)option);
+ return(ma_simple_command(mysql, COM_SET_OPTION, buffer, sizeof(buffer), 0, 0));
+}
+
+ulong STDCALL mysql_get_client_version(void)
+{
+ return MARIADB_PACKAGE_VERSION_ID;
+}
+
+ulong STDCALL mysql_hex_string(char *to, const char *from, unsigned long len)
+{
+ char *start= to;
+ char hexdigits[]= "0123456789ABCDEF";
+
+ while (len--)
+ {
+ *to++= hexdigits[((unsigned char)*from) >> 4];
+ *to++= hexdigits[((unsigned char)*from) & 0x0F];
+ from++;
+ }
+ *to= 0;
+ return (ulong)(to - start);
+}
+
+my_bool STDCALL mariadb_connection(MYSQL *mysql)
+{
+ return (strstr(mysql->server_version, "MariaDB") ||
+ strstr(mysql->server_version, "-maria-"));
+}
+
+const char * STDCALL
+mysql_get_server_name(MYSQL *mysql)
+{
+ if (mysql->options.extension &&
+ mysql->options.extension->db_driver != NULL)
+ return mysql->options.extension->db_driver->name;
+ return mariadb_connection(mysql) ? "MariaDB" : "MySQL";
+}
+
+static my_socket mariadb_get_socket(MYSQL *mysql)
+{
+ my_socket sock= INVALID_SOCKET;
+ if (mysql->net.pvio)
+ {
+ ma_pvio_get_handle(mysql->net.pvio, &sock);
+
+ }
+ /* if an asynchronous connect is in progress, we need to obtain
+ pvio handle from async_context until the connection was
+ successfully established.
+ */
+ else if (mysql->options.extension && mysql->options.extension->async_context &&
+ mysql->options.extension->async_context->pvio)
+ {
+ ma_pvio_get_handle(mysql->options.extension->async_context->pvio, &sock);
+ }
+ return sock;
+}
+
+my_socket STDCALL
+mysql_get_socket(MYSQL *mysql)
+{
+ return mariadb_get_socket(mysql);
+}
+
+MARIADB_CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname)
+{
+ return (MARIADB_CHARSET_INFO *)mysql_find_charset_name(csname);
+}
+
+MARIADB_CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr)
+{
+ return (MARIADB_CHARSET_INFO *)mysql_find_charset_nr(csnr);
+}
+
+my_bool mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+
+ switch(value) {
+ case MARIADB_MAX_ALLOWED_PACKET:
+ *((size_t *)arg)= (size_t)max_allowed_packet;
+ break;
+ case MARIADB_NET_BUFFER_LENGTH:
+ *((size_t *)arg)= (size_t)net_buffer_length;
+ break;
+ case MARIADB_CONNECTION_ERROR_ID:
+ if (!mysql)
+ goto error;
+ *((unsigned int *)arg)= mysql->net.last_errno;
+ break;
+ case MARIADB_CONNECTION_ERROR:
+ if (!mysql)
+ goto error;
+ *((char **)arg)= mysql->net.last_error;
+ break;
+ case MARIADB_CONNECTION_SQLSTATE:
+ if (!mysql)
+ goto error;
+ *((char **)arg)= mysql->net.sqlstate;
+ break;
+ case MARIADB_CONNECTION_TLS_VERSION:
+ #ifdef HAVE_TLS
+ if (mysql && mysql->net.pvio && mysql->net.pvio->ctls)
+ *((char **)arg)= (char *)ma_pvio_tls_get_protocol_version(mysql->net.pvio->ctls);
+ else
+ #endif
+ goto error;
+ break;
+ case MARIADB_CONNECTION_TLS_VERSION_ID:
+ #ifdef HAVE_TLS
+ if (mysql && mysql->net.pvio && mysql->net.pvio->ctls)
+ *((unsigned int *)arg)= ma_pvio_tls_get_protocol_version_id(mysql->net.pvio->ctls);
+ else
+ #endif
+ goto error;
+ break;
+ case MARIADB_TLS_LIBRARY:
+#ifdef HAVE_TLS
+ *((const char **)arg)= tls_library_version;
+#else
+ *((const char **)arg)= "Off";
+#endif
+ break;
+ case MARIADB_CLIENT_VERSION:
+ *((const char **)arg)= MARIADB_CLIENT_VERSION_STR;
+ break;
+ case MARIADB_CLIENT_VERSION_ID:
+ *((size_t *)arg)= MARIADB_VERSION_ID;
+ break;
+ case MARIADB_CONNECTION_SERVER_VERSION:
+ if (mysql)
+ *((char **)arg)= mysql->server_version;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_SERVER_TYPE:
+ if (mysql)
+ *((const char **)arg)= mariadb_connection(mysql) ? "MariaDB" : "MySQL";
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_SERVER_VERSION_ID:
+ if (mysql)
+ *((size_t *)arg)= mariadb_server_version_id(mysql);
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_PROTOCOL_VERSION_ID:
+ if (mysql)
+ *((unsigned int *)arg)= mysql->protocol_version;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_MARIADB_CHARSET_INFO:
+ if (mysql)
+ mariadb_get_charset_info(mysql, (MY_CHARSET_INFO *)arg);
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_SOCKET:
+ if (mysql)
+ *((my_socket *)arg)= mariadb_get_socket(mysql);
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_TYPE:
+ if (mysql && mysql->net.pvio)
+ *((int *)arg)= (int)mysql->net.pvio->type;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_ASYNC_TIMEOUT_MS:
+ if (mysql && mysql->options.extension && mysql->options.extension->async_context)
+ *((unsigned int *)arg)= mysql->options.extension->async_context->timeout_value;
+ break;
+ case MARIADB_CONNECTION_ASYNC_TIMEOUT:
+ if (mysql && mysql->options.extension && mysql->options.extension->async_context)
+ {
+ unsigned int timeout= mysql->options.extension->async_context->timeout_value;
+ if (timeout > UINT_MAX - 999)
+ *((unsigned int *)arg)= (timeout - 1)/1000 + 1;
+ else
+ *((unsigned int *)arg)= (timeout+999)/1000;
+ }
+ break;
+ case MARIADB_CHARSET_NAME:
+ {
+ char *name;
+ name= va_arg(ap, char *);
+ if (name)
+ *((MARIADB_CHARSET_INFO **)arg)= (MARIADB_CHARSET_INFO *)mysql_find_charset_name(name);
+ else
+ goto error;
+ }
+ break;
+ case MARIADB_CHARSET_ID:
+ {
+ unsigned int nr;
+ nr= va_arg(ap, unsigned int);
+ *((MARIADB_CHARSET_INFO **)arg)= (MARIADB_CHARSET_INFO *)mysql_find_charset_nr(nr);
+ }
+ break;
+ case MARIADB_CONNECTION_SSL_CIPHER:
+ #ifdef HAVE_TLS
+ if (mysql && mysql->net.pvio && mysql->net.pvio->ctls)
+ *((char **)arg)= (char *)ma_pvio_tls_cipher(mysql->net.pvio->ctls);
+ else
+ #endif
+ *((char **)arg)= NULL;
+ break;
+ case MARIADB_CLIENT_ERRORS:
+ *((char ***)arg)= (char **)client_errors;
+ break;
+ case MARIADB_CONNECTION_INFO:
+ if (mysql)
+ *((char **)arg)= (char *)mysql->info;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_PVIO_TYPE:
+ if (mysql && mysql->net.pvio)
+ *((unsigned int *)arg)= (unsigned int)mysql->net.pvio->type;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_SCHEMA:
+ if (mysql)
+ *((char **)arg)= mysql->db;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_USER:
+ if (mysql)
+ *((char **)arg)= mysql->user;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_PORT:
+ if (mysql)
+ *((unsigned int *)arg)= mysql->port;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_UNIX_SOCKET:
+ if (mysql)
+ *((char **)arg)= mysql->unix_socket;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_HOST:
+ if (mysql)
+ *((char **)arg)= mysql->host;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_SERVER_STATUS:
+ if (mysql)
+ *((unsigned int *)arg)= mysql->server_status;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_SERVER_CAPABILITIES:
+ if (mysql)
+ *((unsigned long *)arg)= mysql->server_capabilities;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_EXTENDED_SERVER_CAPABILITIES:
+ if (mysql)
+ *((unsigned long *)arg)= mysql->extension->mariadb_server_capabilities;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_CLIENT_CAPABILITIES:
+ if (mysql)
+ *((unsigned long *)arg)= mysql->client_flag;
+ else
+ goto error;
+ break;
+ case MARIADB_CONNECTION_BYTES_READ:
+ *((size_t *)arg)= mysql->net.pvio->bytes_read;
+ break;
+ case MARIADB_CONNECTION_BYTES_SENT:
+ *((size_t *)arg)= mysql->net.pvio->bytes_sent;
+ break;
+ default:
+ va_end(ap);
+ return(-1);
+ }
+ va_end(ap);
+ return(0);
+error:
+ va_end(ap);
+ return(-1);
+}
+
+my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *arg)
+{
+ return mariadb_get_infov(mysql, value, arg);
+}
+
+/*
+ Immediately aborts connection, making all subsequent read/write operations fail.
+ Does not invalidate memory used for mysql structure, nor closes any communication
+ channels - mysql_close is still needed.
+ Useful to break long query, in situation sending KILL is not possible.
+*/
+int STDCALL mariadb_cancel(MYSQL *mysql)
+{
+ if (!mysql || !mysql->net.pvio || !mysql->net.pvio->methods || !mysql->net.pvio->methods->shutdown)
+ {
+ return 1;
+ }
+ else
+ {
+ MARIADB_PVIO *pvio = mysql->net.pvio;
+ return pvio->methods->shutdown(pvio);
+ }
+}
+
+/* compatibility functions for MariaDB */
+void STDCALL
+mysql_debug(const char *debug __attribute__((unused)))
+{
+ return;
+}
+
+/********************************************************************
+ mysql_net_ functions - low-level API to MySQL protocol
+*********************************************************************/
+ulong STDCALL mysql_net_read_packet(MYSQL *mysql)
+{
+ return ma_net_safe_read(mysql);
+}
+
+ulong STDCALL mysql_net_field_length(uchar **packet)
+{
+ return net_field_length(packet);
+}
+
+my_bool STDCALL mysql_embedded(void)
+{
+#ifdef EMBEDDED_LIBRARY
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+MYSQL_PARAMETERS *STDCALL
+mysql_get_parameters(void)
+{
+ return &mariadb_internal_parameters;
+}
+
+int STDCALL mysql_reset_connection(MYSQL *mysql)
+{
+ int rc;
+
+ /* check if connection handler is active */
+ if (IS_CONNHDLR_ACTIVE(mysql))
+ {
+ if (mysql->extension->conn_hdlr->plugin && mysql->extension->conn_hdlr->plugin->reset)
+ return(mysql->extension->conn_hdlr->plugin->reset(mysql));
+ }
+
+ /* skip result sets */
+ if (mysql->status == MYSQL_STATUS_USE_RESULT ||
+ mysql->status == MYSQL_STATUS_GET_RESULT)
+ {
+ mthd_my_skip_result(mysql);
+ }
+
+ if (mysql->server_status & SERVER_MORE_RESULTS_EXIST)
+ {
+ while (mysql_next_result(mysql))
+ {
+ MYSQL_RES *res= mysql_use_result(mysql);
+ mysql_free_result(res);
+ }
+ }
+
+ mysql->status= MYSQL_STATUS_READY;
+
+ rc= ma_simple_command(mysql, COM_RESET_CONNECTION, 0, 0, 0, 0);
+ if (rc && mysql->options.reconnect)
+ {
+ /* There is no big sense in resetting but we need reconnect */
+ rc= ma_simple_command(mysql, COM_RESET_CONNECTION,0,0,0,0);
+ }
+ if (rc)
+ return 1;
+
+ /* reset the connection in all active statements */
+ ma_invalidate_stmts(mysql, "mysql_reset_connection()");
+ free_old_query(mysql);
+ mysql->status= MYSQL_STATUS_READY;
+ mysql->affected_rows= ~(my_ulonglong)0;
+ mysql->insert_id= 0;
+ return 0;
+}
+
+#undef STDCALL
+/* API functions for usage in dynamic plugins */
+struct st_mariadb_api MARIADB_API=
+{
+ mysql_num_rows,
+ mysql_num_fields,
+ mysql_eof,
+ mysql_fetch_field_direct,
+ mysql_fetch_fields,
+ mysql_row_tell,
+ mysql_field_tell,
+ mysql_field_count,
+ mysql_more_results,
+ mysql_next_result,
+ mysql_affected_rows,
+ mysql_autocommit,
+ mysql_commit,
+ mysql_rollback,
+ mysql_insert_id,
+ mysql_errno,
+ mysql_error,
+ mysql_info,
+ mysql_thread_id,
+ mysql_character_set_name,
+ mysql_get_character_set_info,
+ mysql_set_character_set,
+ mariadb_get_infov,
+ mariadb_get_info,
+ mysql_init,
+ mysql_ssl_set,
+ mysql_get_ssl_cipher,
+ mysql_change_user,
+ mysql_real_connect,
+ mysql_close,
+ mysql_select_db,
+ mysql_query,
+ mysql_send_query,
+ mysql_read_query_result,
+ mysql_real_query,
+ mysql_shutdown,
+ mysql_dump_debug_info,
+ mysql_refresh,
+ mysql_kill,
+ mysql_ping,
+ mysql_stat,
+ mysql_get_server_info,
+ mysql_get_server_version,
+ mysql_get_host_info,
+ mysql_get_proto_info,
+ mysql_list_dbs,
+ mysql_list_tables,
+ mysql_list_fields,
+ mysql_list_processes,
+ mysql_store_result,
+ mysql_use_result,
+ mysql_options,
+ mysql_free_result,
+ mysql_data_seek,
+ mysql_row_seek,
+ mysql_field_seek,
+ mysql_fetch_row,
+ mysql_fetch_lengths,
+ mysql_fetch_field,
+ mysql_escape_string,
+ mysql_real_escape_string,
+ mysql_thread_safe,
+ mysql_warning_count,
+ mysql_sqlstate,
+ mysql_server_init,
+ mysql_server_end,
+ mysql_thread_end,
+ mysql_thread_init,
+ mysql_set_server_option,
+ mysql_get_client_info,
+ mysql_get_client_version,
+ mariadb_connection,
+ mysql_get_server_name,
+ mariadb_get_charset_by_name,
+ mariadb_get_charset_by_nr,
+ mariadb_convert_string,
+ mysql_optionsv,
+ mysql_get_optionv,
+ mysql_get_option,
+ mysql_hex_string,
+ mysql_get_socket,
+ mysql_get_timeout_value,
+ mysql_get_timeout_value_ms,
+ mariadb_reconnect,
+ mysql_stmt_init,
+ mysql_stmt_prepare,
+ mysql_stmt_execute,
+ mysql_stmt_fetch,
+ mysql_stmt_fetch_column,
+ mysql_stmt_store_result,
+ mysql_stmt_param_count,
+ mysql_stmt_attr_set,
+ mysql_stmt_attr_get,
+ mysql_stmt_bind_param,
+ mysql_stmt_bind_result,
+ mysql_stmt_close,
+ mysql_stmt_reset,
+ mysql_stmt_free_result,
+ mysql_stmt_send_long_data,
+ mysql_stmt_result_metadata,
+ mysql_stmt_param_metadata,
+ mysql_stmt_errno,
+ mysql_stmt_error,
+ mysql_stmt_sqlstate,
+ mysql_stmt_row_seek,
+ mysql_stmt_row_tell,
+ mysql_stmt_data_seek,
+ mysql_stmt_num_rows,
+ mysql_stmt_affected_rows,
+ mysql_stmt_insert_id,
+ mysql_stmt_field_count,
+ mysql_stmt_next_result,
+ mysql_stmt_more_results,
+ mariadb_stmt_execute_direct,
+ mysql_reset_connection
+};
+
+/*
+ * Default methods for a connection. These methods are
+ * stored in mysql->methods and can be overwritten by
+ * a plugin, e.g. for using another database
+ */
+struct st_mariadb_methods MARIADB_DEFAULT_METHODS = {
+ /* open a connection */
+ mthd_my_real_connect,
+ /* close connection */
+ mysql_close_slow_part,
+ /* send command to server */
+ mthd_my_send_cmd,
+ /* skip result set */
+ mthd_my_skip_result,
+ /* read response packet */
+ mthd_my_read_query_result,
+ /* read all rows from a result set */
+ mthd_my_read_rows,
+ /* read one/next row */
+ mthd_my_read_one_row,
+ /* check if datatype is supported */
+ mthd_supported_buffer_type,
+ /* read response packet from prepare */
+ mthd_stmt_read_prepare_response,
+ /* read response from stmt execute */
+ mthd_my_read_query_result,
+ /* get result set metadata for a prepared statement */
+ mthd_stmt_get_result_metadata,
+ /* get param metadata for a prepared statement */
+ mthd_stmt_get_param_metadata,
+ /* read all rows (buffered) */
+ mthd_stmt_read_all_rows,
+ /* fetch one row (unbuffered) */
+ mthd_stmt_fetch_row,
+ /* store values in bind buffer */
+ mthd_stmt_fetch_to_bind,
+ /* skip unbuffered stmt result */
+ mthd_stmt_flush_unbuffered,
+ /* set error */
+ my_set_error,
+ /* invalidate statements */
+ ma_invalidate_stmts,
+ /* API functions */
+ &MARIADB_API,
+ /* read execute response */
+ mthd_stmt_read_execute_response,
+ /* generate execute request */
+ ma_stmt_execute_generate_request,
+};
diff --git a/libmariadb/libmariadb/mariadb_rpl.c b/libmariadb/libmariadb/mariadb_rpl.c
new file mode 100644
index 00000000..0019f246
--- /dev/null
+++ b/libmariadb/libmariadb/mariadb_rpl.c
@@ -0,0 +1,2099 @@
+/************************************************************************************
+ Copyright (C) 2018,2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+*************************************************************************************/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+#include <mysql.h>
+#include <errmsg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <zlib.h>
+#include <ma_decimal.h>
+#include <mariadb_rpl.h>
+
+
+#ifdef WIN32
+#include <malloc.h>
+#undef alloca
+#define alloca _malloca
+#endif
+
+#define RPL_EVENT_HEADER_SIZE 19
+#define RPL_ERR_POS(r) (r)->filename_length, (r)->filename, (r)->start_position
+#define RPL_CHECK_NULL_POS(position, end)\
+{\
+ uchar *tmp= (position);\
+ while (*tmp && tmp < (end))\
+ tmp++;\
+ if (tmp > (end))\
+ goto malformed_packet;\
+}
+
+#define RPL_CHECK_POS(position, end, bytes)\
+if ((end)-(position) < (ssize_t)(bytes))\
+ goto malformed_packet;
+
+#define RPL_CHECK_FIELD_LENGTH(position, end)\
+{\
+ RPL_CHECK_POS((position), (end), 1);\
+ RPL_CHECK_POS((position), (end), net_field_size((position)));\
+}
+
+#define RPL_CHECK_POST_HEADER_LEN(position, end, type)\
+if (rpl->post_header_len[(type) - 1])\
+{\
+ RPL_CHECK_POS((position), (end), rpl->post_header_len[(type)-1])\
+}
+
+static inline uint64_t uintNkorr(uint8_t len, u_char *p)
+{
+ switch (len) {
+ case 1:
+ return *p;
+ case 2:
+ return uint2korr(p);
+ case 3:
+ return uint3korr(p);
+ case 4:
+ return uint4korr(p);
+ case 8:
+ return uint8korr(p);
+ default:
+ return 0;
+ }
+}
+
+static inline int net_field_size(uchar *p)
+{
+ if (*p <= 251)
+ return 1;
+ if (*p == 252)
+ return 3;
+ if (*p == 253)
+ return 4;
+ return 9;
+}
+
+static inline int rpl_bit_size(uint32_t x)
+{
+ int bits= 1;
+
+ while (x >>= 1)
+ bits++;
+
+ return bits;
+}
+
+static inline int rpl_byte_size(uint32_t x)
+{
+ int bits= rpl_bit_size(x);
+
+ return (bits + 7) / 8;
+}
+
+void rpl_set_error(MARIADB_RPL *rpl,
+ unsigned int error_nr,
+ const char *format,
+ ...)
+{
+ va_list ap;
+
+ const char *errmsg;
+
+ return;
+ if (!format)
+ {
+ if (error_nr >= CR_MIN_ERROR && error_nr <= CR_MYSQL_LAST_ERROR)
+ errmsg= ER(error_nr);
+ else if (error_nr >= CER_MIN_ERROR && error_nr <= CR_MARIADB_LAST_ERROR)
+ errmsg= CER(error_nr);
+ else
+ errmsg= ER(CR_UNKNOWN_ERROR);
+ }
+
+ rpl->error_no= error_nr;
+ va_start(ap, format);
+ vsnprintf(rpl->error_msg, MYSQL_ERRMSG_SIZE - 1,
+ format ? format : errmsg, ap);
+ va_end(ap);
+
+ /* For backward compatibility we also need to set a connection
+ error, if we read from primary instead of file */
+ if (rpl->mysql)
+ {
+ my_set_error(rpl->mysql, error_nr, SQLSTATE_UNKNOWN, rpl->error_msg);
+ }
+}
+
+const char * STDCALL mariadb_rpl_error(MARIADB_RPL *rpl)
+{
+ return rpl->error_msg;
+}
+
+uint32_t STDCALL mariadb_rpl_errno(MARIADB_RPL *rpl)
+{
+ return rpl->error_no;
+}
+
+uint8_t rpl_parse_opt_metadata(MARIADB_RPL_EVENT *event, const uchar *buffer, size_t length)
+{
+ const uchar *pos= buffer, *end= buffer + length;
+ struct st_mariadb_rpl_table_map_event *tm_event= (struct st_mariadb_rpl_table_map_event *)&event->event;
+
+ if (event->event_type != TABLE_MAP_EVENT)
+ return 1;
+
+ while (pos < end)
+ {
+ uint8_t meta_type= *pos++;
+ uint32_t len;
+
+ RPL_CHECK_FIELD_LENGTH((uchar *)pos, end);
+ len= net_field_length((uchar **)&pos);
+ RPL_CHECK_POS(pos, end,len);
+
+ switch(meta_type)
+ {
+ case SIGNEDNESS:
+ tm_event->signed_indicator= (uchar *)pos;
+ pos+= len;
+ break;
+ case DEFAULT_CHARSET:
+ tm_event->default_charset= *pos;
+ pos+= len;
+ break;
+ case COLUMN_CHARSET:
+ tm_event->column_charsets.data= pos;
+ tm_event->column_charsets.length= len;
+ pos+= len;
+ break;
+ case COLUMN_NAME:
+ tm_event->column_names.data= pos;
+ tm_event->column_names.length= len;
+ pos+= len;
+ break;
+ case SIMPLE_PRIMARY_KEY:
+ tm_event->simple_primary_keys.data= pos;
+ tm_event->simple_primary_keys.length= len;
+ pos+= len;
+ break;
+ case PRIMARY_KEY_WITH_PREFIX:
+ tm_event->prefixed_primary_keys.data= pos;
+ tm_event->prefixed_primary_keys.length= len;
+ pos+= len;
+ break;
+ case GEOMETRY_TYPE:
+ {
+ tm_event->geometry_types.data= pos;
+ tm_event->geometry_types.length= len;
+ pos+= len;
+ break;
+ }
+ /* Default character set used by all columns */
+ case ENUM_AND_SET_DEFAULT_CHARSET:
+ tm_event->enum_set_default_charset= *pos;
+ pos+= len;
+ break;
+ case ENUM_AND_SET_COLUMN_CHARSET:
+ tm_event->enum_set_column_charsets.data= pos;
+ tm_event->enum_set_column_charsets.length= len;
+ pos+= len;
+ break;
+ case SET_STR_VALUE:
+ tm_event->set_values.data= pos;
+ tm_event->set_values.length= len;
+ pos+= len;
+ break;
+ case ENUM_STR_VALUE:
+ tm_event->enum_values.data= pos;
+ tm_event->enum_values.length= len;
+ pos+= len;
+ break;
+ default:
+ rpl_set_error(event->rpl, CR_BINLOG_ERROR, 0, RPL_ERR_POS(event->rpl), "Unknown/unsupported event type");
+ pos+= len;
+ break;
+ }
+ }
+ return 0;
+malformed_packet:
+ return 1;
+}
+
+static void *ma_calloc_root(void *memroot, size_t len)
+{
+ void *p;
+
+ if ((p= ma_alloc_root(memroot, len)))
+ memset(p, 0, len);
+ return p;
+}
+
+static void rpl_set_string_and_len(MARIADB_STRING *s,
+ unsigned char *buffer,
+ size_t len)
+{
+ if (!buffer || !len)
+ {
+ s->length= 0;
+ return;
+ }
+ s->str= (char *)buffer;
+ s->length= len;
+}
+
+static uint8_t rpl_alloc_set_string_and_len(MARIADB_RPL_EVENT *event,
+ MARIADB_STRING *s,
+ void *buffer,
+ size_t len)
+{
+ if (!buffer || !len)
+ {
+ s->length= 0;
+ return 0;
+ }
+
+ if (!(s->str = (char *)ma_alloc_root(&event->memroot, len)))
+ return 1;
+
+ memcpy(s->str, buffer, len);
+ s->length= len;
+ return 0;
+}
+
+static uint8_t rpl_metadata_size(enum enum_field_types field_type)
+{
+ switch (field_type) {
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_DATETIME2:
+ case MYSQL_TYPE_TIMESTAMP2:
+ case MYSQL_TYPE_TIME2:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ return 1;
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_BIT:
+ return 2;
+ default:
+ return 0;
+ }
+}
+
+static uint8_t ma_rpl_get_second_part(MYSQL_TIME *tm, uchar *ptr, uchar *metadata)
+{
+ switch(metadata[0])
+ {
+ case 0:
+ tm->second_part= 0;
+ return 0;
+ case 1:
+ case 2:
+ tm->second_part= (uint32_t)ptr[0] * 10000;
+ return 1;
+ case 3:
+ case 4:
+ tm->second_part= myisam_sint2korr(ptr) * 100;
+ return 2;
+ case 5:
+ case 6:
+ tm->second_part= myisam_sint3korr(ptr);
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+MARIADB_RPL_ROW * STDCALL
+mariadb_rpl_extract_rows(MARIADB_RPL *rpl,
+ MARIADB_RPL_EVENT *tm_event,
+ MARIADB_RPL_EVENT *row_event)
+{
+ uchar *start, *pos, *end;
+ MARIADB_RPL_ROW *f_row= NULL, *p_row= NULL, *c_row= NULL;
+ uint32_t column_count;
+
+ if (!rpl || !tm_event || !row_event)
+ return NULL;
+
+ if (tm_event->event_type != TABLE_MAP_EVENT || !(IS_ROW_EVENT(row_event)))
+ {
+ rpl_set_error(rpl, CR_BINLOG_ERROR, 0, RPL_ERR_POS(rpl), "Event with wrong event type passed.");
+ return NULL;
+ }
+
+ if (row_event->event.rows.table_id != tm_event->event.table_map.table_id)
+ {
+ rpl_set_error(rpl, CR_BINLOG_ERROR, 0, RPL_ERR_POS(rpl), "table_id in table_map event differs.");
+ return NULL;
+ }
+
+ if (!row_event->event.rows.row_data_size ||
+ !row_event->event.rows.row_data)
+ {
+ rpl_set_error(rpl, CR_BINLOG_ERROR, 0, "Row event has no data.");
+ return NULL;
+ }
+
+ column_count= tm_event->event.table_map.column_count;
+
+ start= pos = row_event->event.rows.row_data;
+ end= start + row_event->event.rows.row_data_size;
+
+ while (pos < end)
+ {
+ uchar *n_bitmap;
+ uint32_t i;
+
+ uchar *metadata= (uchar *)tm_event->event.table_map.metadata.str;
+
+ if (!(c_row = (MARIADB_RPL_ROW *)ma_calloc_root(&row_event->memroot, sizeof(MARIADB_RPL_ROW))) ||
+ !(c_row->columns= (MARIADB_RPL_VALUE *)ma_calloc_root(&row_event->memroot,
+ sizeof(MARIADB_RPL_VALUE) * column_count)))
+ {
+ rpl_set_error(rpl, CR_OUT_OF_MEMORY, 0);
+ return NULL;
+ }
+
+ if (!f_row)
+ f_row= c_row;
+ if (p_row)
+ p_row->next= c_row;
+
+ c_row->column_count= column_count;
+ n_bitmap= pos;
+ pos+= (column_count + 7) / 8;
+
+ for (i= 0; i < column_count; i++)
+ {
+ MARIADB_RPL_VALUE *column= &c_row->columns[i];
+ column->field_type= (uchar)tm_event->event.table_map.column_types.str[i];
+ /* enum, set and string types are stored as string - first metadata
+ byte contains real_type, second byte contains the length */
+ if (column->field_type == MYSQL_TYPE_STRING)
+ {
+ if (metadata[0] == MYSQL_TYPE_ENUM || metadata[0] == MYSQL_TYPE_SET)
+ column->field_type = metadata[0];
+ }
+
+ if ((n_bitmap[i / 8] >> (i % 8)) & 1)
+ {
+ column->is_null= 1;
+ metadata+= rpl_metadata_size(column->field_type);
+ continue;
+ }
+ if (column->field_type == MYSQL_TYPE_BLOB)
+ {
+ switch(metadata[0])
+ {
+ case 1:
+ column->field_type= MYSQL_TYPE_TINY_BLOB;
+ break;
+ case 3:
+ column->field_type= MYSQL_TYPE_MEDIUM_BLOB;
+ break;
+ case 4:
+ column->field_type= MYSQL_TYPE_LONG_BLOB;
+ break;
+ default:
+ break;
+ }
+ }
+ switch (column->field_type) {
+ case MYSQL_TYPE_TINY:
+ column->val.ll= sint1korr(pos);
+ column->val.ull= uint1korr(pos);
+ pos++;
+ break;
+ case MYSQL_TYPE_YEAR:
+ column->val.ull= uint1korr(pos++) + 1900;
+ break;
+ case MYSQL_TYPE_SHORT:
+ column->val.ll= sint2korr(pos);
+ column->val.ull= uint2korr(pos);
+ pos+= 2;
+ break;
+ case MYSQL_TYPE_INT24:
+ column->val.ll= sint3korr(pos);
+ column->val.ull= uint3korr(pos);
+ pos+= 3;
+ break;
+ case MYSQL_TYPE_LONG:
+ column->val.ll= sint4korr(pos);
+ column->val.ull= uint4korr(pos);
+ pos+= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ column->val.ll= sint8korr(pos);
+ column->val.ull= uint8korr(pos);
+ pos+= 8;
+ break;
+ case MYSQL_TYPE_NEWDECIMAL:
+ {
+ uint8_t precision= *metadata++;
+ uint8_t scale= *metadata++;
+ uint32_t bin_size;
+ decimal dec;
+ char str[200];
+ char buf[100];
+ int s_len= sizeof(str) - 1;
+
+ dec.buf= (void *)buf;
+ dec.len= sizeof(buf) / sizeof(decimal_digit);
+
+ bin_size= decimal_bin_size(precision, scale);
+ bin2decimal((char *)pos, &dec, precision, scale);
+ decimal2string(&dec, str, &s_len);
+ pos+= bin_size;
+
+ if (rpl_alloc_set_string_and_len(row_event, &column->val.str, str, s_len))
+ goto mem_error;
+
+ break;
+ }
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ {
+ uint8_t flen= *metadata++;
+ if (flen == 4)
+ {
+ float4get(column->val.f, pos);
+ }
+ if (flen == 8)
+ {
+ float8get(column->val.d, pos);
+ }
+ pos+= flen;
+ break;
+ }
+ case MYSQL_TYPE_BIT:
+ {
+ uint8_t num_bits= (metadata[0] & 0xFF) + metadata[1] * 8;
+ uint8_t b_len= (num_bits + 7) / 8;
+ metadata+= 2;
+ if (rpl_alloc_set_string_and_len(row_event, &column->val.str, pos, b_len))
+ goto mem_error;
+ pos+= b_len;
+ break;
+ }
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ column->val.ull= uint4korr(pos);
+ pos+= 4;
+ break;
+ }
+ case MYSQL_TYPE_TIMESTAMP2:
+ {
+ char tmp[20];
+ uint32_t p1= uint4korr(pos);
+ uint8_t f_len= *metadata++;
+ uint32_t p2;
+ pos+= 4;
+ p2= (uint32_t)uintNkorr(f_len, pos);
+ pos+= f_len;
+ sprintf(tmp, "%d.%d", p1, p2);
+ if (rpl_alloc_set_string_and_len(row_event, &column->val.str, tmp, strlen(tmp)))
+ goto mem_error;
+ break;
+ }
+ case MYSQL_TYPE_DATE:
+ {
+ MYSQL_TIME *tm= &column->val.tm;
+ uint32_t d_val= uint3korr(pos);
+ pos+= 3;
+ tm->year= (int)(d_val / (16 * 32));
+ tm->month= (int)(d_val / 32 % 16);
+ tm->day= d_val % 32;
+ tm->time_type= MYSQL_TIMESTAMP_DATE;
+ break;
+ }
+ case MYSQL_TYPE_TIME2:
+ {
+ MYSQL_TIME *tm= &column->val.tm;
+ int64_t t_val= myisam_uint3korr(pos) - 0x800000LL;
+
+ if ((tm->neg = t_val < 0))
+ t_val= -t_val;
+
+ pos+= 3;
+ tm->hour= (t_val >> 12) % (1 << 10);
+ tm->minute= (t_val >> 6) % (1 << 6);
+ tm->second= t_val % (1 << 6);
+
+ pos+= ma_rpl_get_second_part(tm, pos, metadata);
+ metadata++;
+ tm->time_type= MYSQL_TIMESTAMP_TIME;
+ column->field_type= MYSQL_TYPE_TIME;
+ break;
+ }
+ case MYSQL_TYPE_DATETIME2:
+ {
+ MYSQL_TIME *tm= &column->val.tm;
+ uint64_t dt_val= mi_uint5korr(pos) - 0x8000000000LL,
+ date_part, time_part;
+ pos+= 5;
+
+ date_part= dt_val >> 17;
+ time_part= dt_val % (1 << 17);
+
+ tm->day= (unsigned int)date_part % (1 << 5);
+ tm->month= (unsigned int)(date_part >> 5) % 13;
+ tm->year= (unsigned int)(date_part >> 5) / 13;
+
+ tm->second= time_part % (1 << 6);
+ tm->minute= (time_part >> 6) % (1 << 6);
+ tm->hour= (uint32_t)(time_part >> 12);
+
+ tm->time_type= MYSQL_TIMESTAMP_DATETIME;
+ column->field_type= MYSQL_TYPE_DATETIME;
+
+ pos+= ma_rpl_get_second_part(tm, pos, metadata);
+ metadata++;
+ break;
+ }
+ case MYSQL_TYPE_STRING:
+ {
+ uint8_t s_len= metadata[2];
+ metadata+= 2;
+ if (rpl_alloc_set_string_and_len(row_event, &column->val.str, pos, s_len))
+ goto mem_error;
+ pos+= s_len;
+ break;
+ }
+ case MYSQL_TYPE_ENUM:
+ {
+ uint8_t e_len= metadata[2];
+ metadata+= 2;
+ column->val.ull= uintNkorr(e_len, pos);
+ pos+= e_len;
+ break;
+ }
+ case MYSQL_TYPE_SET:
+ {
+ uint8_t e_len= metadata[2];
+ metadata+= 2;
+ column->val.ull= uintNkorr(e_len, pos);
+ pos+= e_len;
+ break;
+ }
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_GEOMETRY:
+ {
+ uint8_t h_len= *metadata++;
+ uint64_t b_len= uintNkorr(h_len, pos);
+ pos+= h_len;
+ if (rpl_alloc_set_string_and_len(row_event, &column->val.str, pos, (size_t)b_len))
+ goto mem_error;
+ pos+= b_len;
+ break;
+ }
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ {
+ uint32_t s_len= uint2korr(metadata);
+ uint8_t byte_len= rpl_byte_size(s_len);
+ metadata+= 2;
+ s_len= (uint32_t)uintNkorr(byte_len, pos);
+ pos+= byte_len;
+ if (rpl_alloc_set_string_and_len(row_event, &column->val.str, pos, s_len))
+ goto mem_error;
+ pos+= s_len;
+ break;
+ }
+ case MYSQL_TYPE_TIME:
+ {
+ MYSQL_TIME *tm= &column->val.tm;
+ uint64_t t= uint8korr(pos);
+ pos+= 8;
+ tm->hour= (unsigned int)(t/100)/100;
+ tm->minute= (unsigned int)(t/100) % 100;
+ tm->second= (unsigned int)t % 100;
+ tm->time_type= MYSQL_TIMESTAMP_TIME;
+ break;
+ }
+ case MYSQL_TYPE_DATETIME:
+ {
+ MYSQL_TIME *tm= &column->val.tm;
+ uint64_t t= uint8korr(pos);
+ uint32_t d_val= (uint32_t)t / 1000000,
+ t_val= (uint32_t)t % 1000000;
+ pos+= 8;
+ tm->year= (unsigned int)(d_val / 100) / 100;
+ tm->month= (unsigned int)(d_val / 100) % 100;
+ tm->day= (unsigned int)d_val % 100;
+ tm->hour= (t_val/100)/100;
+ tm->minute= (t_val/100) % 100;
+ tm->second= t_val % 100;
+ tm->time_type= MYSQL_TIMESTAMP_DATETIME;
+ break;
+ }
+
+
+ default:
+ break;
+ }
+ }
+ p_row= c_row;
+ }
+ return f_row;
+
+mem_error:
+ rpl_set_error(rpl, CR_OUT_OF_MEMORY, 0);
+ return NULL;
+}
+
+MARIADB_RPL * STDCALL mariadb_rpl_init_ex(MYSQL *mysql, unsigned int version)
+{
+ MARIADB_RPL *rpl;
+
+ if (version < MARIADB_RPL_REQUIRED_VERSION ||
+ version > MARIADB_RPL_VERSION)
+ {
+ if (mysql)
+ my_set_error(mysql, CR_VERSION_MISMATCH, SQLSTATE_UNKNOWN, 0, version,
+ MARIADB_RPL_VERSION, MARIADB_RPL_REQUIRED_VERSION);
+ return 0;
+ }
+
+ if (!(rpl= (MARIADB_RPL *)calloc(1, sizeof(MARIADB_RPL))))
+ {
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return 0;
+ }
+ rpl->version= version;
+
+ if ((rpl->mysql= mysql))
+ {
+ MYSQL_RES *result;
+ if (!mysql_query(mysql, "select @@binlog_checksum"))
+ {
+ if ((result= mysql_store_result(mysql)))
+ {
+ MYSQL_ROW row= mysql_fetch_row(result);
+ if (!strcmp(row[0], "CRC32"))
+ {
+ rpl->artificial_checksum= 1;
+ }
+ mysql_free_result(result);
+ }
+ }
+ }
+
+ /* recommended way to set replica host and port is via rpl_optionsv(), however if
+ hostname and port was set via mysql_optionsv, we set it here to rpl */
+ if (rpl->mysql && rpl->mysql->options.extension && rpl->mysql->options.extension->rpl_host)
+ {
+ mariadb_rpl_optionsv(rpl, MARIADB_RPL_HOST, rpl->mysql->options.extension->rpl_host);
+ mariadb_rpl_optionsv(rpl, MARIADB_RPL_PORT, rpl->mysql->options.extension->rpl_port);
+ }
+ return rpl;
+}
+
+void STDCALL mariadb_free_rpl_event(MARIADB_RPL_EVENT *event)
+{
+ if (event)
+ {
+ ma_free_root(&event->memroot, MYF(0));
+ free(event);
+ }
+}
+
+int STDCALL mariadb_rpl_open(MARIADB_RPL *rpl)
+{
+ unsigned char *ptr, *buf;
+
+ if (!rpl)
+ return 1;
+
+ /* COM_BINLOG_DUMP:
+ Ofs Len Data
+ 0 1 COM_BINLOG_DUMP
+ 1 4 position
+ 5 2 flags
+ 7 4 server id
+ 11 * filename
+
+ * = filename length
+
+ */
+ rpl_clear_error(rpl);
+
+ /* if replica was specified, we will register replica via
+ COM_REGISTER_SLAVE */
+ if (rpl->host)
+ {
+ /* Protocol:
+ Ofs Len Data
+ 0 1 COM_REGISTER_SLAVE
+ 1 4 server id
+ 5 1 replica host name length
+ 6 <n> replica host name
+ 1 user name length
+ <n> user name
+ 1 password length
+ <n> password
+ 2 replica port
+ 4 replication rank (unused)
+ 4 source server id (unused)
+ */
+ unsigned char *p, buffer[1024];
+ size_t len= MIN(strlen(rpl->host), 255);
+
+ p= buffer;
+ int4store(p, rpl->server_id);
+ p+= 4;
+ *p++= (unsigned char)len;
+ memcpy(p, rpl->host, len);
+ p+= len;
+
+ /* Don't send user, password, rank and server_id */
+ *p++= 0;
+ *p++= 0;
+ int2store(p, rpl->port);
+ p+= 2;
+
+ int4store(p, 0);
+ p+= 4;
+ int4store(p, 0);
+ p+= 4;
+
+ if (ma_simple_command(rpl->mysql, COM_REGISTER_SLAVE, (const char *)buffer, p - buffer, 0, 0))
+ {
+ rpl_set_error(rpl, mysql_errno(rpl->mysql), 0, NULL, 0);
+ return 1;
+ }
+ }
+
+ if (rpl->mysql)
+ {
+ uint32_t replica_id= rpl->server_id;
+ ptr= buf= (unsigned char *)alloca(rpl->filename_length + 11);
+
+ if (!ptr)
+ {
+ rpl_set_error(rpl, CR_OUT_OF_MEMORY, 0);
+ }
+
+ if (rpl->is_semi_sync)
+ {
+ if (mysql_query(rpl->mysql, "SET @rpl_semi_sync_slave=1"))
+ {
+ rpl_set_error(rpl, mysql_errno(rpl->mysql), 0, mysql_error(rpl->mysql));
+ return 1;
+ }
+ }
+ else {
+ MYSQL_RES* result;
+ MYSQL_ROW row;
+ if (mysql_query(rpl->mysql, "SELECT @rpl_semi_sync_slave=1"))
+ {
+ rpl_set_error(rpl, mysql_errno(rpl->mysql), 0, mysql_error(rpl->mysql));
+ return 1;
+ }
+ if ((result = mysql_store_result(rpl->mysql)))
+ {
+ if ((row = mysql_fetch_row(result)))
+ rpl->is_semi_sync = (row[0] != NULL && row[0][0] == '1');
+ mysql_free_result(result);
+ }
+ }
+
+ int4store(ptr, (unsigned int)rpl->start_position);
+ ptr+= 4;
+ int2store(ptr, rpl->flags);
+ ptr+= 2;
+ if ((rpl->flags & MARIADB_RPL_BINLOG_DUMP_NON_BLOCK) && !replica_id)
+ replica_id= 1;
+ int4store(ptr, replica_id);
+ ptr+= 4;
+ memcpy(ptr, rpl->filename, rpl->filename_length);
+ ptr+= rpl->filename_length;
+
+ return (ma_simple_command(rpl->mysql, COM_BINLOG_DUMP, (const char *)buf, ptr - buf, 1, 0));
+ } else
+ {
+ char *buf[RPL_BINLOG_MAGIC_SIZE];
+ MYSQL mysql;
+
+ /* Semi sync doesn't work when processing files */
+ rpl->is_semi_sync = 0;
+
+ if (rpl->fp)
+ ma_close(rpl->fp);
+
+ if (!(rpl->fp= ma_open((const char *)rpl->filename, "r", &mysql)))
+ {
+ rpl_set_error(rpl, CR_FILE_NOT_FOUND, 0, rpl->filename, errno);
+ return errno;
+ }
+
+ if (ma_read(buf, 1, RPL_BINLOG_MAGIC_SIZE, rpl->fp) != 4)
+ {
+ rpl_set_error(rpl, CR_FILE_READ, 0, rpl->filename, errno);
+ return errno;
+ }
+
+ /* check if it is a valid binlog file */
+ if (memcmp(buf, RPL_BINLOG_MAGIC, RPL_BINLOG_MAGIC_SIZE) != 0)
+ {
+ rpl_set_error(rpl, CR_BINLOG_INVALID_FILE, 0, rpl->filename, errno);
+ return errno;
+ }
+
+ return 0;
+ }
+}
+
+static int ma_set_rpl_filename(MARIADB_RPL *rpl, const unsigned char *filename, size_t len)
+{
+ if (!rpl)
+ return 1;
+ free(rpl->filename);
+ if (!(rpl->filename= (char *)malloc(len)))
+ return 1;
+ memcpy(rpl->filename, filename, len);
+ rpl->filename_length= (uint32_t)len;
+ return 0;
+}
+
+/*
+ * Returns compression info:
+ * Ofs Len
+ * 0 1 header:
+ * ofs & 0x07 >> 4: algorithm, always 0=zlib
+ * ofs & 0x07: header size
+ * 1 header size uncompressed length in MyISAM format.
+ */
+static uint32_t get_compression_info(const unsigned char *buf,
+ uint8_t *algorithm,
+ uint8_t *header_size)
+{
+ uint8_t alg, header;
+ uint32 len= 0;
+
+ if (!algorithm)
+ algorithm= &alg;
+ if (!header_size)
+ header_size= &header;
+
+ *header_size= 0;
+ *algorithm= 0;
+
+ if (!buf)
+ return len;
+
+ if ((buf[0] & 0xe0) != 0x80)
+ return len;
+
+ *header_size= buf[0] & 0x07;
+ *algorithm = (buf[0] & 0x07) >> 4;
+
+ buf++;
+
+ /* Attention: we can't use uint*korr, here, we need myisam macros since
+ length is stored in high byte first order
+ */
+ switch(*header_size) {
+ case 1:
+ len= *buf;
+ break;
+ case 2:
+ len= myisam_uint2korr(buf);
+ break;
+ case 3:
+ len= myisam_uint3korr(buf);
+ break;
+ case 4:
+ len= myisam_uint4korr(buf);
+ break;
+ default:
+ len= 0;
+ break;
+ }
+
+ *header_size += 1;
+ return len;
+}
+
+static uint8_t mariadb_rpl_send_semisync_ack(MARIADB_RPL* rpl, MARIADB_RPL_EVENT* event)
+{
+ size_t buf_size = 0;
+ uchar* buf;
+
+ if (!rpl)
+ return 1;
+
+ if (!event)
+ {
+ rpl_set_error(rpl, CR_BINLOG_SEMI_SYNC_ERROR, 0, "Invalid event");
+ return 1;
+ }
+
+ if (!rpl->is_semi_sync)
+ {
+ rpl_set_error(rpl, CR_BINLOG_SEMI_SYNC_ERROR, 0, "semi synchronous replication is not enabled");
+ return 1;
+ }
+ if (!event->is_semi_sync || (event->semi_sync_flags != SEMI_SYNC_ACK_REQ))
+ {
+ rpl_set_error(rpl, CR_BINLOG_SEMI_SYNC_ERROR, 0, "This event doesn't require to send semi synchronous acknoledgement");
+ return 1;
+ }
+
+ buf_size = rpl->filename_length + 9;
+ buf = alloca(buf_size);
+
+ buf[0] = SEMI_SYNC_INDICATOR;
+ int8store(buf + 1, (uint64_t)event->next_event_pos);
+ memcpy(buf + 9, rpl->filename, rpl->filename_length);
+
+ ma_net_clear(&rpl->mysql->net);
+
+ if (ma_net_write(&rpl->mysql->net, buf, buf_size) ||
+ (ma_net_flush(&rpl->mysql->net)))
+ {
+ rpl_set_error(rpl, CR_CONNECTION_ERROR, 0);
+ return 1;
+ }
+
+ return 0;
+}
+
+MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVENT *event)
+{
+ unsigned char *ev= 0;
+ unsigned char *checksum_start= 0;
+ unsigned char *ev_start= 0;
+ unsigned char *ev_end= 0;
+ size_t len= 0;
+ MARIADB_RPL_EVENT *rpl_event= 0;
+
+ if (!rpl || (!rpl->mysql && !rpl->fp))
+ return 0;
+
+ if (event)
+ {
+ MA_MEM_ROOT memroot= event->memroot;
+ rpl_event= event;
+ ma_free_root(&memroot, MYF(MY_KEEP_PREALLOC));
+ memset(rpl_event, 0, sizeof(MARIADB_RPL_EVENT));
+ rpl_event->memroot= memroot;
+ } else {
+ if (!(rpl_event = (MARIADB_RPL_EVENT *)malloc(sizeof(MARIADB_RPL_EVENT))))
+ goto mem_error;
+ memset(rpl_event, 0, sizeof(MARIADB_RPL_EVENT));
+ ma_init_alloc_root(&rpl_event->memroot, 8192, 0);
+ }
+
+ rpl_event->rpl= rpl;
+
+ while (1) {
+ unsigned long pkt_len;
+
+ if (rpl->mysql)
+ {
+ pkt_len= ma_net_safe_read(rpl->mysql);
+
+ if (pkt_len == packet_error)
+ {
+ mariadb_free_rpl_event(rpl_event);
+ return 0;
+ }
+
+ /* EOF packet:
+ see https://mariadb.com/kb/en/library/eof_packet/
+ Packet length must be less than 9 bytes, EOF header
+ is 0xFE.
+ */
+ if (pkt_len < 9 && rpl->mysql->net.read_pos[0] == 0xFE)
+ {
+ mariadb_free_rpl_event(rpl_event);
+ return 0;
+ }
+
+ /* if ignore heartbeat flag was set, we ignore this
+ record and continue to fetch next record.
+ The first byte is always status byte (0x00)
+ For event header description see
+ https://mariadb.com/kb/en/library/2-binlog-event-header/ */
+ if (rpl->flags & MARIADB_RPL_IGNORE_HEARTBEAT)
+ {
+ if (rpl->mysql->net.read_pos[1 + 4] == HEARTBEAT_LOG_EVENT)
+ continue;
+ }
+
+ if (!(rpl_event->raw_data= ma_alloc_root(&rpl_event->memroot, pkt_len)))
+ goto mem_error;
+
+ rpl_event->raw_data_size= pkt_len;
+ memcpy(rpl_event->raw_data, rpl->mysql->net.read_pos, pkt_len);
+ ev= rpl_event->raw_data;
+ } else if (rpl->fp) {
+ char buf[EVENT_HEADER_OFS]; /* header */
+ size_t rc;
+ uint32_t len= 0;
+ char *p= buf;
+
+ if (ma_feof(rpl->fp))
+ {
+ return NULL;
+ }
+
+ memset(buf, 0, EVENT_HEADER_OFS);
+ if ((rc= ma_read(buf, 1, EVENT_HEADER_OFS - 1, rpl->fp)) != EVENT_HEADER_OFS - 1)
+ {
+ rpl_set_error(rpl, CR_BINLOG_ERROR, 0, "Can't read event header");
+ mariadb_free_rpl_event(rpl_event);
+ return NULL;
+ }
+ len= uint4korr(p + 9);
+
+ if (!(rpl_event->raw_data= ma_alloc_root(&rpl_event->memroot, len)))
+ {
+ rpl_set_error(rpl, CR_OUT_OF_MEMORY, 0);
+ mariadb_free_rpl_event(rpl_event);
+ return NULL;
+ }
+
+ rpl_event->raw_data_size= len;
+ memcpy(rpl_event->raw_data, buf, EVENT_HEADER_OFS - 1);
+ len-= (EVENT_HEADER_OFS - 1);
+ rc= ma_read(rpl_event->raw_data + EVENT_HEADER_OFS - 1, 1, len, rpl->fp);
+ if (rc != len)
+ {
+ rpl_set_error(rpl, CR_BINLOG_ERROR, 0, "Error while reading post header");
+ mariadb_free_rpl_event(rpl_event);
+ return NULL;
+ }
+ ev= rpl_event->raw_data;
+
+ /* We don't decrypt yet */
+ if (rpl->encrypted) {
+ return rpl_event;
+ }
+ }
+
+ ev_end= rpl_event->raw_data + rpl_event->raw_data_size;
+
+
+ if (rpl->mysql)
+ {
+ RPL_CHECK_POS(ev, ev_end, 1);
+ rpl_event->ok= *ev++;
+
+ /* CONC-470: add support for semi snychronous replication */
+ if (rpl->is_semi_sync && (rpl_event->is_semi_sync= (*ev == SEMI_SYNC_INDICATOR)))
+ {
+ RPL_CHECK_POS(ev, ev_end, 1);
+ ev++;
+ rpl_event->semi_sync_flags= *ev++;
+ }
+ }
+ rpl_event->raw_data_ofs= ev - rpl_event->raw_data;
+
+ /* check sum verification:
+ check sum will be calculated from begin of binlog header
+ */
+ checksum_start= ev;
+
+ /******************************************************************
+ Binlog event header:
+
+ All binary log events have the same header:
+ - uint32_t timestamp: creation time
+ - uint8_t event_type: type code of the event
+ - uint32_t server_id: server which created the event
+ - uint32_t event_len: length of the event. If checksum is
+ enabled, the length also include 4 bytes
+ of checksum
+ ------------- if START_ENCRYPTION_EVENT was sent, ---------------
+ encrypted part starts here:
+ - uint32_t next_pos: Position of next binary log event
+ - uint16_t flags: flags
+
+ The size of binlog event header must match the header size returned
+ by FORMAT_DESCIPTION_EVENT. In version 4 it is always 19.
+ ********************************************************************/
+ RPL_CHECK_POS(ev, ev_end, RPL_EVENT_HEADER_SIZE);
+ rpl_event->timestamp= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event_type= (unsigned char)*ev++;
+ rpl_event->server_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event_length= uint4korr(ev);
+ ev+= 4;
+ rpl_event->next_event_pos= uint4korr(ev);
+ ev+= 4;
+ rpl_event->flags= uint2korr(ev);
+ ev+=2;
+ rpl_event->checksum= 0;
+
+ /* start of post_header */
+ ev_start= ev;
+
+ DBUG_ASSERT(rpl_event->event_type < ENUM_END_EVENT);
+
+ switch(rpl_event->event_type) {
+ case UNKNOWN_EVENT:
+ case SLAVE_EVENT:
+ return rpl_event;
+ break;
+ case HEARTBEAT_LOG_EVENT:
+ /* no post header size */
+ RPL_CHECK_POS(ev, ev_end, 11);
+ rpl_event->event.heartbeat.timestamp= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.heartbeat.next_position= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.heartbeat.type= (uint8_t)*ev;
+ ev+= 1;
+ rpl_event->event.heartbeat.flags= uint2korr(ev);
+ ev+= 2;
+
+ break;
+
+ case BEGIN_LOAD_QUERY_EVENT:
+ /* check post header size */
+ RPL_CHECK_POST_HEADER_LEN(ev, ev_end, BEGIN_LOAD_QUERY_EVENT);
+ rpl_event->event.begin_load_query.file_id= uint4korr(ev);
+ ev+= 4;
+
+ /* Payload: query_data (zero terminated) */
+ RPL_CHECK_NULL_POS(ev, ev_end);
+ rpl_event->event.begin_load_query.data= ev;
+ RPL_CHECK_NULL_POS(ev, ev_end);
+ ev+= strlen((char *)ev);
+ /* terminating zero */
+ RPL_CHECK_POS(ev, ev_end, 1);
+ ev++;
+ break;
+
+ case START_ENCRYPTION_EVENT:
+ /* Post header */
+ RPL_CHECK_POS(ev, ev_end, 17);
+ rpl_event->event.start_encryption.scheme= *ev++;
+ rpl_event->event.start_encryption.key_version= uint4korr(ev);
+ ev+= 4;
+ memcpy(rpl_event->event.start_encryption.nonce, ev, 12);
+ memcpy(rpl->nonce, ev, 12);
+ ev+= 12;
+ rpl->encrypted= 1;
+ break;
+
+ case EXECUTE_LOAD_QUERY_EVENT:
+ {
+ uint16_t status_len;
+ uint8_t schema_len;
+
+ /* Post header */
+ RPL_CHECK_POS(ev, ev_end, rpl->post_header_len[EXECUTE_LOAD_QUERY_EVENT - 1]);
+ rpl_event->event.execute_load_query.thread_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.execute_load_query.execution_time= uint4korr(ev);
+ ev+= 4;
+ schema_len= *ev++;
+ rpl_event->event.execute_load_query.error_code= uint2korr(ev);
+ ev+= 2;
+ status_len= uint2korr(ev);
+ ev+= 2;
+ rpl_event->event.execute_load_query.file_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.execute_load_query.ofs1= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.execute_load_query.ofs2= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.execute_load_query.duplicate_flag= *ev++;
+
+ /* Payload:
+ - status variables
+ - query schema
+ - statement */
+ RPL_CHECK_POS(ev, ev_end, status_len);
+ rpl_set_string_and_len(&rpl_event->event.execute_load_query.status_vars, ev, status_len);
+ ev+= status_len;
+ RPL_CHECK_POS(ev, ev_end, schema_len);
+ rpl_set_string_and_len(&rpl_event->event.execute_load_query.schema, ev, schema_len);
+ /* terminating zero */
+ RPL_CHECK_POS(ev, ev_end, 1);
+ ev+= (schema_len + 1);
+
+ len= rpl_event->event_length - (ev - ev_start) - (rpl->use_checksum ? 4 : 0) - (EVENT_HEADER_OFS - 1);
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_set_string_and_len(&rpl_event->event.execute_load_query.statement, ev, len);
+ ev+= len;
+ break;
+ }
+ case BINLOG_CHECKPOINT_EVENT:
+ /* Post header */
+ RPL_CHECK_POS(ev, ev_end, rpl->post_header_len[BINLOG_CHECKPOINT_EVENT - 1]);
+ len= uint4korr(ev);
+ ev+= 4;
+
+ /* payload: filename */
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_set_string_and_len(&rpl_event->event.checkpoint.filename, ev, len);
+ if (ma_set_rpl_filename(rpl, ev, len))
+ goto mem_error;
+ ev+= len;
+ break;
+
+ case FORMAT_DESCRIPTION_EVENT:
+ /*
+ FORMAT_DESCRIPTION_EVENT:
+
+ Header:
+ uint<2> binary log version
+ (we support only version 4)
+ str<50> server version, right padded with \0
+ uint<4> timestamp <redundant>
+ uint<1> header length
+ byte<n> post header lengths. Length can be calculated by
+ ev_end - end - 1 - 4
+ uint<1> check sum algorithm byte
+ uint<4> CRC32 checksum
+ */
+
+
+ /* We don't speak bing log protocol version < 4, in case it's an older
+ protocol version an error will be returned. */
+ RPL_CHECK_POS(ev, ev_end, 57);
+ if ((rpl_event->event.format_description.format = uint2korr(ev)) < 4)
+ {
+ mariadb_free_rpl_event(rpl_event);
+ rpl_set_error(rpl, CR_ERR_UNSUPPORTED_BINLOG_FORMAT, SQLSTATE_UNKNOWN, 0,
+ RPL_ERR_POS(rpl), uint2korr(ev));
+ return 0;
+ }
+
+ ev+= 2;
+ rpl_event->event.format_description.server_version = (char *)(ev);
+ ev+= 50;
+ rpl_event->event.format_description.timestamp= uint4korr(ev);
+ ev+= 4;
+ rpl->fd_header_len= rpl_event->event.format_description.header_len= *ev;
+ ev+= 1;
+ /*Post header lengths: 1 byte for each event, non used events/gaps in enum should
+ have a zero value */
+ len= ev_end - ev - 5;
+ rpl_set_string_and_len(&rpl_event->event.format_description.post_header_lengths, ev, len);
+ memset(rpl->post_header_len, 0, ENUM_END_EVENT);
+ memcpy(rpl->post_header_len, rpl_event->event.format_description.post_header_lengths.str,
+ MIN(len, ENUM_END_EVENT));
+
+ ev+= len;
+ RPL_CHECK_POS(ev, ev_end, 5);
+ if ((rpl->use_checksum= *ev++))
+ {
+ rpl_event->checksum= uint4korr(ev);
+ ev+= 4;
+ }
+ break;
+
+ case QUERY_COMPRESSED_EVENT:
+ case QUERY_EVENT:
+ {
+ size_t db_len, status_len;
+
+ /***********
+ post_header
+ ***********/
+ RPL_CHECK_POS(ev, ev_end, rpl->post_header_len[rpl_event->event_type - 1]);
+ rpl_event->event.query.thread_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.query.seconds= uint4korr(ev);
+ ev+= 4;
+ db_len= *ev;
+ ev++;
+ rpl_event->event.query.errornr= uint2korr(ev);
+ ev+= 2;
+ status_len= uint2korr(ev);
+ ev+= 2;
+
+ /*******
+ payload
+ ******/
+ RPL_CHECK_POS(ev, ev_end, status_len + db_len + 1);
+ rpl_set_string_and_len(&rpl_event->event.query.status, ev, status_len);
+ ev+= status_len;
+
+ rpl_set_string_and_len(&rpl_event->event.query.database, ev, db_len);
+ ev+= db_len + 1; /* zero terminated */
+
+ len= rpl_event->event_length - (ev - ev_start) - (rpl->use_checksum ? 4 : 0) - (EVENT_HEADER_OFS - 1);
+ RPL_CHECK_POS(ev, ev_end, len);
+
+ if (rpl_event->event_type == QUERY_EVENT || !rpl->uncompress) {
+ rpl_set_string_and_len(&rpl_event->event.query.statement, ev, len);
+ }
+ else if (rpl_event->event_type == QUERY_COMPRESSED_EVENT)
+ {
+ uint8_t header_size= 0,
+ algorithm= 0;
+
+ uint32_t uncompressed_len= get_compression_info(ev, &algorithm, &header_size);
+
+ len-= header_size;
+ if (!(rpl_event->event.query.statement.str = ma_calloc_root(&rpl_event->memroot, uncompressed_len)))
+ goto mem_error;
+
+ if ((uncompress((Bytef*)rpl_event->event.query.statement.str, (uLongf *)&uncompressed_len,
+ (Bytef*)ev + header_size, (uLongf)*&len) != Z_OK))
+ {
+ mariadb_free_rpl_event(rpl_event);
+ rpl_set_error(rpl, CR_ERR_BINLOG_UNCOMPRESS, SQLSTATE_UNKNOWN, RPL_ERR_POS(rpl));
+ return 0;
+ }
+ rpl_event->event.query.statement.length= uncompressed_len;
+ }
+ break;
+ }
+ case TABLE_MAP_EVENT:
+ {
+ /*
+ TABLE_MAP_EVENT:
+
+ Header:
+ uint<6> table_id
+ uint<2> unused
+
+ Payload:
+ uint<1> schema_name length
+ str<NULL> schema_name (zero terminated)
+ uint<1> table_name length
+ str<NULL> table_name (zero terminated)
+ int<lenc> column_count
+ byte<n> column_types[column_count], 1 byte for
+ each column
+ int<lenc> meta_data_size
+ byte<n> netadata{metadata_size]
+ byte<n> bit fields, indicating which column can be null
+ n= (column_count + 7) / 8;
+
+ if (remaining_bytes)
+ byte<n> optional metadata
+ */
+ RPL_CHECK_POST_HEADER_LEN(ev, ev_end, TABLE_MAP_EVENT);
+
+ /* Post header */
+ rpl_event->event.table_map.table_id= uint6korr(ev);
+ ev+= 8; /* 2 byte in header ignored */
+
+ /* Payload */
+ RPL_CHECK_POS(ev, ev_end, 1);
+ len= *ev++;
+ RPL_CHECK_POS(ev, ev_end, len + 1);
+
+ rpl_set_string_and_len(&rpl_event->event.table_map.database, ev, len);
+ ev+= len + 1; /* Zero terminated */
+
+ RPL_CHECK_POS(ev, ev_end, 1);
+ len= *ev++;
+ RPL_CHECK_POS(ev, ev_end, len + 1);
+ rpl_set_string_and_len(&rpl_event->event.table_map.table, ev, len);
+ ev+= len + 1; /* Zero terminated */
+
+ RPL_CHECK_FIELD_LENGTH(ev, ev_end);
+ len= rpl_event->event.table_map.column_count= mysql_net_field_length(&ev);
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_set_string_and_len(&rpl_event->event.table_map.column_types, ev, len);
+ ev+= len;
+
+ RPL_CHECK_FIELD_LENGTH(ev, ev_end);
+ len= mysql_net_field_length(&ev);
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_set_string_and_len(&rpl_event->event.table_map.metadata, ev, len);
+ ev+= len;
+
+ len= (rpl_event->event.table_map.column_count + 7) / 8;
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_event->event.table_map.null_indicator= ev;
+ ev+= len;
+
+ len= ev_end - ev - (rpl->use_checksum ? 4 : 0);
+
+ if (len > 0) /* optional metadata */
+ {
+ rpl_parse_opt_metadata(rpl_event, ev, len);
+ ev+= len;
+ }
+
+ break;
+
+ case RAND_EVENT:
+ RPL_CHECK_POS(ev, ev_end, 16);
+ rpl_event->event.rand.first_seed= uint8korr(ev);
+ ev+= 8;
+ rpl_event->event.rand.second_seed= uint8korr(ev);
+ ev+= 8;
+
+ break;
+ }
+
+ case INTVAR_EVENT:
+ RPL_CHECK_POS(ev, ev_end, 9);
+ rpl_event->event.intvar.type= *ev;
+ ev++;
+ rpl_event->event.intvar.value= uint8korr(ev);
+ ev+= 8;
+ break;
+
+ case USER_VAR_EVENT:
+ RPL_CHECK_POS(ev, ev_end, 4);
+ len= uint4korr(ev);
+ ev+= 4;
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_set_string_and_len(&rpl_event->event.uservar.name, ev, len);
+ ev+= len;
+ RPL_CHECK_POS(ev, ev_end, 1);
+ if (!(rpl_event->event.uservar.is_null= (uint8)*ev))
+ {
+ ev++;
+ RPL_CHECK_POS(ev, ev_end, 9);
+ rpl_event->event.uservar.type= *ev;
+ ev++;
+ rpl_event->event.uservar.charset_nr= uint4korr(ev);
+ ev+= 4;
+ len= uint4korr(ev);
+ ev+= 4;
+ RPL_CHECK_POS(ev, ev_end, len);
+
+ if (rpl_event->event.uservar.type == DECIMAL_RESULT)
+ {
+ char str[200];
+ int s_len= sizeof(str) - 1;
+ int precision= (int)ev[0],
+ scale= (int)ev[1];
+ decimal d;
+ decimal_digit buf[10];
+ d.len= 10;
+ d.buf= buf;
+ bin2decimal((char *)(ev+2), &d, precision, scale);
+ decimal2string(&d, str, &s_len);
+ if (!(rpl_event->event.uservar.value.str =
+ (char *)ma_calloc_root(&rpl_event->memroot, s_len)))
+ goto mem_error;
+ memcpy(rpl_event->event.uservar.value.str, str, s_len);
+ rpl_event->event.uservar.value.length= s_len;
+ } else if (rpl_event->event.uservar.type == INT_RESULT)
+ {
+ uint64_t val64;
+ if (!(rpl_event->event.uservar.value.str =
+ (char *)ma_calloc_root(&rpl_event->memroot, sizeof(longlong))))
+ goto mem_error;
+ val64= uint8korr(ev);
+ memcpy(rpl_event->event.uservar.value.str, &val64, sizeof(uint64_t));
+ rpl_event->event.uservar.value.length= sizeof(uint64_t);
+ } else if (rpl_event->event.uservar.type == REAL_RESULT)
+ {
+ double d;
+ float8get(d, ev);
+ ev+= 8;
+ if (!(rpl_event->event.uservar.value.str =
+ (char *)ma_calloc_root(&rpl_event->memroot, 24)))
+ goto mem_error;
+ memset(rpl_event->event.uservar.value.str, 0, 24);
+ sprintf(rpl_event->event.uservar.value.str, "%.14g", d);
+ rpl_event->event.uservar.value.length= strlen(rpl_event->event.uservar.value.str);
+ }
+ else
+ rpl_set_string_and_len(&rpl_event->event.uservar.value, ev, len);
+ ev+= len;
+ if ((unsigned long)(ev - rpl_event->raw_data) < rpl_event->raw_data_size)
+ rpl_event->event.uservar.flags= *ev;
+ ev++;
+ }
+ break;
+
+ case ANNOTATE_ROWS_EVENT:
+ /* Payload */
+ len= ev_end - ev - (rpl->use_checksum ? 4 : 0);
+ if (len > 0)
+ rpl_set_string_and_len(&rpl_event->event.annotate_rows.statement, ev, len);
+ break;
+
+ case ROTATE_EVENT:
+ RPL_CHECK_POST_HEADER_LEN(ev, ev_end, ROTATE_EVENT);
+
+ rpl_event->event.rotate.position= uint8korr(ev);
+ ev+= 8;
+
+ /* Payload */
+ len= ev_end - ev - 4;
+ if (!len)
+ goto malformed_packet;
+
+ if (rpl_event->timestamp == 0 &&
+ rpl_event->flags & LOG_EVENT_ARTIFICIAL_F)
+ {
+ if (rpl->artificial_checksum)
+ {
+ unsigned long crc= crc32(0L, Z_NULL, 0);
+ rpl_event->checksum= (uint32_t) crc32(crc, checksum_start, (uint32_t)(ev_end - checksum_start));
+ }
+ }
+ rpl_set_string_and_len(&rpl_event->event.rotate.filename, ev, len);
+ if (ma_set_rpl_filename(rpl, ev, len))
+ goto mem_error;
+
+ ev+= len;
+ break;
+
+ case XID_EVENT:
+ /*
+ XID_EVENT was generated if a transaction which modified tables was
+ committed.
+
+ Header:
+ - uint64_t transaction number
+ */
+ RPL_CHECK_POS(ev, ev_end, 8);
+
+ rpl_event->event.xid.transaction_nr= uint8korr(ev);
+ break;
+
+ case XA_PREPARE_LOG_EVENT:
+ /*
+ MySQL only!
+
+ Header:
+ uint8_t one phase commit
+ uint32_t format_id
+ uint32_t length of gtrid
+ uint32_t length of bqual
+
+ Payload:
+ char<n> xid, where n is sum of gtrid and bqual lengths
+ */
+ RPL_CHECK_POS(ev, ev_end, 13);
+
+ rpl_event->event.xa_prepare_log.one_phase= *ev;
+ ev++;
+ rpl_event->event.xa_prepare_log.format_id= uint4korr(ev);
+ ev+= 4;
+ len= rpl_event->event.xa_prepare_log.gtrid_len= uint4korr(ev);
+ ev+= 4;
+ len+= rpl_event->event.xa_prepare_log.bqual_len= uint4korr(ev);
+ ev+= 4;
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_set_string_and_len(&rpl_event->event.xa_prepare_log.xid, ev, len);
+ break;
+
+ case STOP_EVENT:
+ /*
+ STOP_EVENT - server shutdown or crash. It's always the last written
+ event after shutdown or after resuming from crash.
+
+ After starting the server a new binary log file will be created, additionally
+ a ROTATE_EVENT will be appended to the old log file.
+
+ No data to process.
+ */
+ break;
+
+ case PREVIOUS_GTIDS_LOG_EVENT:
+ {
+ /*
+ PREVIOUS_GTID_LOG_EVENT (MySQL only):
+
+ 8-bytes, always zero ?!
+ */
+ ssize_t len= ev_end - ev - rpl->use_checksum * 4;
+
+ if (len)
+ {
+ rpl_event->event.previous_gtid.content.data= ev;
+ rpl_event->event.previous_gtid.content.length= len;
+ ev+= len;
+ }
+ break;
+ }
+ case ANONYMOUS_GTID_LOG_EVENT:
+ case GTID_LOG_EVENT:
+ /*
+ ANONYMOUS_GTID_LOG_EVENT
+
+ uint32_t thread_id
+
+ Header:
+ uint8_t flag: commit flag
+ byte<16> source_id: numerical representation of server's UUID
+ uint64_t sequence_nr: sequence number
+ */
+ RPL_CHECK_POS(ev, ev_end, 25);
+ rpl_event->event.gtid_log.commit_flag= *ev;
+ ev++;
+ memcpy(rpl_event->event.gtid_log.source_id, ev, 16);
+ ev+= 16;
+ rpl_event->event.gtid_log.sequence_nr= uint8korr(ev);
+ ev+= 8;
+ break;
+
+ case GTID_EVENT:
+ /*
+ GTID_EVENT (MariaDB Only):
+
+ A New transaction (BEGIN) was started, or a single transaction
+ (ddl) statement was executed. In case a single transaction was
+ executed, the FL_GROUP_COMMIT id flag is not set.
+
+ Header:
+ uint64_t sequence_nr
+ uint64_t domain_id
+ uint8_t flags
+
+ if (flags & FL_GROUP_COMMIT_D)
+ uint64_t commit_id
+ else
+ char[6] unused
+ */
+ RPL_CHECK_POST_HEADER_LEN(ev, ev_end, GTID_EVENT);
+ rpl_event->event.gtid.sequence_nr= uint8korr(ev);
+ ev+= 8;
+ rpl_event->event.gtid.domain_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.gtid.flags= *ev;
+ ev++;
+ if (rpl_event->event.gtid.flags & FL_GROUP_COMMIT_ID)
+ {
+ RPL_CHECK_POS(ev, ev_end, 8);
+ rpl_event->event.gtid.commit_id= uint8korr(ev);
+ ev+= 8;
+ }
+ else if (rpl_event->event.gtid.flags & (FL_PREPARED_XA | FL_COMPLETED_XA))
+ {
+ uint16_t len;
+ RPL_CHECK_POS(ev, ev_end, 6);
+ rpl_event->event.gtid.format_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.gtid.gtrid_len= *ev;
+ ev++;
+ rpl_event->event.gtid.bqual_len= *ev;
+ ev++;
+ len= rpl_event->event.gtid.gtrid_len + rpl_event->event.gtid.bqual_len;
+ RPL_CHECK_POS(ev, ev_end, len);
+ rpl_set_string_and_len(&rpl_event->event.gtid.xid, ev, len);
+ ev+= len;
+ }
+ else
+ ev+= 6;
+ break;
+
+ case GTID_LIST_EVENT:
+ /*
+ GTID_LIST_EVENT (MariaDB only)
+
+ Logged in every binlog to record the current replication state.
+ Consists of the last GTID seen for each replication domain.
+
+ The Global Transaction ID, GTID for short, consists of three components:
+ replication domain id, server id and sequence nr
+
+ Header:
+ uint32_t gtid_cnt - number of global transaction id's
+
+ Payload:
+ for i=0; i < gtid_cnt; i++
+ uint32_t domain_id
+ uint32_t server_id
+ uint64_t sequence_nr
+ */
+
+ RPL_CHECK_POST_HEADER_LEN(ev, ev_end, GTID_LIST_EVENT);
+ rpl_event->event.gtid_list.gtid_cnt= uint4korr(ev);
+ ev+=4;
+
+ RPL_CHECK_POS(ev, ev_end, rpl_event->event.gtid_list.gtid_cnt * 16);
+ /* Payload */
+ if (rpl_event->event.gtid_list.gtid_cnt)
+ {
+ uint32_t i;
+ if (!(rpl_event->event.gtid_list.gtid=
+ (MARIADB_GTID *)ma_calloc_root(&rpl_event->memroot,
+ sizeof(MARIADB_GTID) * rpl_event->event.gtid_list.gtid_cnt)))
+ goto mem_error;
+ for (i=0; i < rpl_event->event.gtid_list.gtid_cnt; i++)
+ {
+ rpl_event->event.gtid_list.gtid[i].domain_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.gtid_list.gtid[i].server_id= uint4korr(ev);
+ ev+= 4;
+ rpl_event->event.gtid_list.gtid[i].sequence_nr= uint8korr(ev);
+ ev+= 8;
+ }
+ }
+ break;
+
+ case WRITE_ROWS_COMPRESSED_EVENT_V1:
+ case UPDATE_ROWS_COMPRESSED_EVENT_V1:
+ case DELETE_ROWS_COMPRESSED_EVENT_V1:
+ case WRITE_ROWS_EVENT_V1:
+ case UPDATE_ROWS_EVENT_V1:
+ case DELETE_ROWS_EVENT_V1:
+ case WRITE_ROWS_EVENT:
+ case UPDATE_ROWS_EVENT:
+ case DELETE_ROWS_EVENT:
+ {
+ /*
+ WRITE/UPDATE/DELETE_ROWS_EVENT_V1 (MariaDB only)
+ WRITE/UPDATE/DELETE_ROWS_EVENT_COMPRESSED_V1 (MariaDB only)
+ WRITE/UPDATE/DELETE_ROWS_EVENT (MySQL only)
+
+ ROWS events are written for row based replicatoin if data is
+ inserted, deleted or updated.
+
+ Header
+ uint<6> table_id
+ uint<2> flags
+
+ if MySQL (version 2)
+ uint<<2> extra_data_length
+ char[extra_data_length] extra_data
+
+ uint<lenenc> number of columns
+ uint8_t<n> Bitmap of columns used.
+ n= (number of columns + 7) / 8
+
+ if UPDATE_ROWS_v1 (MariaDB)
+ uint8_t<n> columns updated
+ n= (number of columns + 7) / 8
+
+ uint7_t<n> null bitmap
+ n= (number of columns + 7) / 8
+
+ str<len> Column data. If event is not compressed,
+ length must be calculated.
+
+ if UPDATE_ROWS_v1 (MariaDB)
+ byte<n> Null bitmap update
+ n= (number of columns + 7) / 8
+ str<len> Update column data
+
+ */
+
+ uint32_t bitmap_len= 0;
+
+ RPL_CHECK_POST_HEADER_LEN(ev, ev_end, rpl_event->event_type);
+
+ if (rpl_event->event_type >= WRITE_ROWS_COMPRESSED_EVENT) {
+ return rpl_event;
+ rpl_event->event.rows.compressed= 1;
+ rpl_event->event.rows.type= rpl_event->event_type - WRITE_ROWS_COMPRESSED_EVENT;
+ } else if (rpl_event->event_type >= WRITE_ROWS_COMPRESSED_EVENT_V1) {
+ rpl_event->event.rows.compressed= 1;
+ rpl_event->event.rows.type= rpl_event->event_type - WRITE_ROWS_COMPRESSED_EVENT_V1;
+ } else if (rpl_event->event_type >= WRITE_ROWS_EVENT)
+ rpl_event->event.rows.type= rpl_event->event_type - WRITE_ROWS_EVENT;
+ else
+ rpl_event->event.rows.type= rpl_event->event_type - WRITE_ROWS_EVENT_V1;
+
+ rpl_event->event.rows.table_id= uint6korr(ev);
+ ev+= 6;
+
+ rpl_event->event.rows.flags= uint2korr(ev);
+ ev+= 2;
+
+ /* payload */
+
+ /* ROWS_EVENT V2 has the extra-data field.
+ See also: https://dev.mysql.com/doc/internals/en/rows-event.html
+ */
+ if (IS_ROW_VERSION2(rpl_event->event_type))
+ {
+ RPL_CHECK_POS(ev, ev_end, 2);
+ rpl_event->event.rows.extra_data_size= uint2korr(ev);
+ ev+= 2;
+ RPL_CHECK_POS(ev, ev_end, rpl_event->event.rows.extra_data_size);
+ if (rpl_event->event.rows.extra_data_size - 2 > 0)
+ {
+ rpl_alloc_set_string_and_len(rpl_event, rpl_event->event.rows.extra_data, ev, rpl_event->event.rows.extra_data_size - 2);
+ ev+= rpl_event->event.rows.extra_data_size;
+ }
+ }
+ /* END_ROWS_EVENT_V2 */
+
+ /* number of columns */
+ RPL_CHECK_FIELD_LENGTH(ev, ev_end);
+ rpl_event->event.rows.column_count= mysql_net_field_length(&ev);
+ bitmap_len= (rpl_event->event.rows.column_count + 7) / 8;
+ DBUG_ASSERT(rpl_event->event.rows.column_count > 0);
+
+ /* columns updated bitmap */
+ RPL_CHECK_POS(ev, ev_end, bitmap_len);
+ rpl_event->event.rows.column_bitmap= ev;
+ ev+= bitmap_len;
+
+ if (rpl_event->event_type == UPDATE_ROWS_EVENT_V1 ||
+ rpl_event->event_type == UPDATE_ROWS_COMPRESSED_EVENT_V1)
+ {
+ RPL_CHECK_POS(ev, ev_end, bitmap_len);
+ rpl_event->event.rows.column_update_bitmap= ev;
+ ev+= bitmap_len;
+ }
+
+ len= ev_end - ev - (rpl->use_checksum ? 4 : 0);
+
+ if (rpl_event->event.rows.compressed)
+ {
+ uint8_t algorithm= 0, header_size= 0;
+ uint32_t uncompressed_len= get_compression_info(ev, &algorithm, &header_size);
+
+ if (!(rpl_event->event.rows.row_data = ma_calloc_root(&rpl_event->memroot, uncompressed_len)))
+ goto mem_error;
+
+ if ((uncompress((Bytef*)rpl_event->event.rows.row_data, (uLong *)&uncompressed_len,
+ (Bytef*)ev + header_size, (uLongf )len) != Z_OK))
+ {
+ rpl_set_error(rpl, CR_ERR_BINLOG_UNCOMPRESS, SQLSTATE_UNKNOWN, 0, RPL_ERR_POS(rpl));
+ mariadb_free_rpl_event(rpl_event);
+ return 0;
+ }
+ rpl_event->event.rows.row_data_size= uncompressed_len;
+ RPL_CHECK_POS(ev, ev_end, header_size + len);
+ ev+= header_size + len;
+ } else {
+ rpl_event->event.rows.row_data_size= ev_end - ev - (rpl->use_checksum ? 4 : 0);
+ if (!(rpl_event->event.rows.row_data =
+ (char *)ma_calloc_root(&rpl_event->memroot, rpl_event->event.rows.row_data_size)))
+ goto mem_error;
+ memcpy(rpl_event->event.rows.row_data, ev, rpl_event->event.rows.row_data_size);
+ }
+ break;
+ }
+ default:
+ /* We need to report an error if this event can't be ignored */
+ if (!(rpl_event->flags & LOG_EVENT_IGNORABLE_F))
+ {
+ mariadb_free_rpl_event(rpl_event);
+ rpl_set_error(rpl, CR_UNKNOWN_BINLOG_EVENT, 0, RPL_ERR_POS(rpl),
+ rpl_event->event_type);
+ return 0;
+ }
+ return rpl_event;
+ break;
+ }
+
+ /* check if we have to send acknowledgement to primary
+ when semi sync replication is used */
+ if (rpl_event->is_semi_sync &&
+ rpl_event->semi_sync_flags == SEMI_SYNC_ACK_REQ)
+ {
+ if (mariadb_rpl_send_semisync_ack(rpl, rpl_event))
+ {
+ /* ACK failed and rpl->error was set */
+ return rpl_event;
+ }
+ }
+
+ if (rpl->use_checksum && !rpl_event->checksum)
+ {
+ rpl_event->checksum= uint4korr(ev_end - 4);
+
+ if (rpl_event->checksum && rpl->verify_checksum)
+ {
+ unsigned long crc= crc32(0L, Z_NULL, 0);
+ crc= crc32(crc, checksum_start, (uint32_t)(ev_end - checksum_start - 4));
+ if (rpl_event->checksum != (uint32_t)crc)
+ {
+ rpl_set_error(rpl, CR_ERR_CHECKSUM_VERIFICATION_ERROR, SQLSTATE_UNKNOWN, 0,
+ RPL_ERR_POS(rpl),
+ rpl_event->checksum, (uint32_t)crc);
+ mariadb_free_rpl_event(rpl_event);
+ return 0;
+ }
+ }
+ }
+ return rpl_event;
+ }
+mem_error:
+ mariadb_free_rpl_event(rpl_event);
+ rpl_set_error(rpl, CR_OUT_OF_MEMORY, 0);
+ return 0;
+malformed_packet:
+ rpl_set_error(rpl, CR_BINLOG_ERROR, 0, RPL_ERR_POS(rpl),
+ "Malformed packet");
+ mariadb_free_rpl_event(rpl_event);
+ return 0;
+}
+
+void STDCALL mariadb_rpl_close(MARIADB_RPL *rpl)
+{
+ if (!rpl)
+ return;
+ free((void *)rpl->filename);
+ if (rpl->fp)
+ {
+ ma_close(rpl->fp);
+ }
+ free(rpl->host);
+ free(rpl);
+ return;
+}
+
+int STDCALL mariadb_rpl_optionsv(MARIADB_RPL *rpl,
+ enum mariadb_rpl_option option,
+ ...)
+{
+ va_list ap;
+ int rc= 0;
+
+ if (!rpl)
+ return 1;
+
+ va_start(ap, option);
+
+ switch (option) {
+ case MARIADB_RPL_FILENAME:
+ {
+ char *arg1= va_arg(ap, char *);
+ rpl->filename_length= (uint32_t)va_arg(ap, size_t);
+ free((void *)rpl->filename);
+ rpl->filename= NULL;
+ if (rpl->filename_length)
+ {
+ rpl->filename= (char *)malloc(rpl->filename_length);
+ memcpy((void *)rpl->filename, arg1, rpl->filename_length);
+ }
+ else if (arg1)
+ {
+ rpl->filename= strdup((const char *)arg1);
+ rpl->filename_length= (uint32_t)strlen(rpl->filename);
+ }
+ break;
+ }
+ case MARIADB_RPL_SERVER_ID:
+ {
+ rpl->server_id= va_arg(ap, unsigned int);
+ break;
+ }
+ case MARIADB_RPL_FLAGS:
+ {
+ rpl->flags= va_arg(ap, unsigned int);
+ break;
+ }
+ case MARIADB_RPL_START:
+ {
+ rpl->start_position= va_arg(ap, unsigned long);
+ break;
+ }
+ case MARIADB_RPL_VERIFY_CHECKSUM:
+ {
+ rpl->verify_checksum= va_arg(ap, uint32_t);
+ break;
+ }
+ case MARIADB_RPL_UNCOMPRESS:
+ {
+ rpl->uncompress= (uint8_t)va_arg(ap, uint32_t);
+ break;
+ }
+ case MARIADB_RPL_PORT:
+ {
+ rpl->port= va_arg(ap, uint32_t);
+ break;
+ }
+ case MARIADB_RPL_HOST:
+ {
+ rpl->host= strdup(va_arg(ap, char *));
+ break;
+ }
+ case MARIADB_RPL_EXTRACT_VALUES:
+ {
+ rpl->extract_values= (uint8_t)va_arg(ap, uint32_t);
+ break;
+ }
+ case MARIADB_RPL_SEMI_SYNC:
+ {
+ rpl->is_semi_sync = (uint8_t)va_arg(ap, uint32_t);
+ break;
+ }
+ default:
+ rc= -1;
+ goto end;
+ }
+end:
+ va_end(ap);
+ return rc;
+}
+
+int STDCALL mariadb_rpl_get_optionsv(MARIADB_RPL *rpl,
+ enum mariadb_rpl_option option,
+ ...)
+{
+ va_list ap;
+
+ if (!rpl)
+ return 1;
+
+ va_start(ap, option);
+
+ switch (option) {
+ case MARIADB_RPL_FILENAME:
+ {
+ const char **name= (const char **)va_arg(ap, char **);
+ size_t *len= (size_t*)va_arg(ap, size_t *);
+
+ *name= rpl->filename;
+ *len= rpl->filename_length;
+ break;
+ }
+ case MARIADB_RPL_SERVER_ID:
+ {
+ unsigned int *id= va_arg(ap, unsigned int *);
+ *id= rpl->server_id;
+ break;
+ }
+ case MARIADB_RPL_FLAGS:
+ {
+ unsigned int *flags= va_arg(ap, unsigned int *);
+ *flags= rpl->flags;
+ break;
+ }
+ case MARIADB_RPL_START:
+ {
+ unsigned long *start= va_arg(ap, unsigned long *);
+ *start= rpl->start_position;
+ break;
+ }
+ case MARIADB_RPL_SEMI_SYNC:
+ {
+ unsigned int* semi_sync = va_arg(ap, unsigned int*);
+ *semi_sync = rpl->is_semi_sync;
+ break;
+ }
+
+ default:
+ va_end(ap);
+ return 1;
+ break;
+ }
+ va_end(ap);
+ return 0;
+}
diff --git a/libmariadb/libmariadb/mariadb_stmt.c b/libmariadb/libmariadb/mariadb_stmt.c
new file mode 100644
index 00000000..5bcecfde
--- /dev/null
+++ b/libmariadb/libmariadb/mariadb_stmt.c
@@ -0,0 +1,2636 @@
+/****************************************************************************
+ Copyright (C) 2012 Monty Program AB
+ 2013, 2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+ *****************************************************************************/
+
+/* The implementation for prepared statements was ported from PHP's mysqlnd
+ extension, written by Andrey Hristov, Georg Richter and Ulf Wendel
+
+ Original file header:
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "ma_global.h"
+#include <ma_sys.h>
+#include <ma_string.h>
+#include <mariadb_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <ma_pvio.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <mysql/client_plugin.h>
+#include <ma_common.h>
+#include "ma_priv.h"
+#include <assert.h>
+
+
+#define UPDATE_STMT_ERROR(stmt)\
+stmt_set_error((stmt), (stmt)->mysql->net.last_errno, (stmt)->mysql->net.sqlstate, (stmt)->mysql->net.last_error)
+
+#define STMT_NUM_OFS(type, a, r) (((type *)(a))[r])
+#define MADB_RESET_ERROR 1
+#define MADB_RESET_LONGDATA 2
+#define MADB_RESET_SERVER 4
+#define MADB_RESET_BUFFER 8
+#define MADB_RESET_STORED 16
+
+#define MAX_TIME_STR_LEN 13
+#define MAX_DATE_STR_LEN 5
+#define MAX_DATETIME_STR_LEN 12
+
+typedef struct
+{
+ MA_MEM_ROOT fields_ma_alloc_root;
+} MADB_STMT_EXTENSION;
+
+static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove);
+
+static my_bool is_not_null= 0;
+static my_bool is_null= 1;
+
+void stmt_set_error(MYSQL_STMT *stmt,
+ unsigned int error_nr,
+ const char *sqlstate,
+ const char *format,
+ ...)
+{
+ va_list ap;
+
+ const char *errmsg= format;
+
+ stmt->last_errno= error_nr;
+ ma_strmake(stmt->sqlstate, sqlstate, SQLSTATE_LENGTH);
+
+ if (!format)
+ {
+ if (IS_MYSQL_ERROR(error_nr) || IS_MARIADB_ERROR(error_nr))
+ errmsg= ER(error_nr);
+ else {
+ snprintf(stmt->last_error, MYSQL_ERRMSG_SIZE - 1,
+ ER_UNKNOWN_ERROR_CODE, error_nr);
+ return;
+ }
+ }
+
+ /* Fix for CONC-627: If this is a server error message, we don't
+ need to substitute and possible variadic arguments will be
+ ignored */
+ if (!IS_MYSQL_ERROR(error_nr) && !IS_MARIADB_ERROR(error_nr))
+ {
+ strncpy(stmt->last_error, format, MYSQL_ERRMSG_SIZE - 1);
+ return;
+ }
+
+ va_start(ap, format);
+ vsnprintf(stmt->last_error, MYSQL_ERRMSG_SIZE - 1, errmsg, ap);
+ va_end(ap);
+ return;
+}
+
+my_bool mthd_supported_buffer_type(enum enum_field_types type)
+{
+ switch (type) {
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_NULL:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_JSON:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_YEAR:
+ return 1;
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags);
+static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close);
+static int stmt_unbuffered_eof(MYSQL_STMT *stmt __attribute__((unused)),
+ uchar **row __attribute__((unused)))
+{
+ return MYSQL_NO_DATA;
+}
+
+static int stmt_unbuffered_fetch(MYSQL_STMT *stmt, uchar **row)
+{
+ ulong pkt_len;
+
+ pkt_len= ma_net_safe_read(stmt->mysql);
+
+ if (pkt_len == packet_error)
+ {
+ stmt->fetch_row_func= stmt_unbuffered_eof;
+ return(1);
+ }
+
+ if (stmt->mysql->net.read_pos[0] == 254)
+ {
+ *row = NULL;
+ stmt->fetch_row_func= stmt_unbuffered_eof;
+ return(MYSQL_NO_DATA);
+ }
+ else
+ *row = stmt->mysql->net.read_pos;
+ stmt->result.rows++;
+ return(0);
+}
+
+static int stmt_buffered_fetch(MYSQL_STMT *stmt, uchar **row)
+{
+ if (!stmt->result_cursor)
+ {
+ *row= NULL;
+ stmt->state= MYSQL_STMT_FETCH_DONE;
+ return MYSQL_NO_DATA;
+ }
+ stmt->state= MYSQL_STMT_USER_FETCHING;
+ *row= (uchar *)stmt->result_cursor->data;
+
+ stmt->result_cursor= stmt->result_cursor->next;
+ return 0;
+}
+
+int mthd_stmt_read_all_rows(MYSQL_STMT *stmt)
+{
+ MYSQL_DATA *result= &stmt->result;
+ MYSQL_ROWS *current, **pprevious;
+ ulong packet_len;
+ unsigned char *p;
+
+ pprevious= &result->data;
+
+ while ((packet_len = ma_net_safe_read(stmt->mysql)) != packet_error)
+ {
+ p= stmt->mysql->net.read_pos;
+ if (packet_len > 7 || p[0] != 254)
+ {
+ /* allocate space for rows */
+ if (!(current= (MYSQL_ROWS *)ma_alloc_root(&result->alloc, sizeof(MYSQL_ROWS) + packet_len)))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ current->data= (MYSQL_ROW)(current + 1);
+ *pprevious= current;
+ pprevious= &current->next;
+
+ /* copy binary row, we will encode it during mysql_stmt_fetch */
+ memcpy((char *)current->data, (char *)p, packet_len);
+
+ if (stmt->update_max_length)
+ {
+ uchar *null_ptr, bit_offset= 4;
+ uchar *cp= p;
+ unsigned int i;
+
+ cp++; /* skip first byte */
+ null_ptr= cp;
+ cp+= (stmt->field_count + 9) / 8;
+
+ for (i=0; i < stmt->field_count; i++)
+ {
+ if (!(*null_ptr & bit_offset))
+ {
+ if (mysql_ps_fetch_functions[stmt->fields[i].type].pack_len < 0)
+ {
+ /* We need to calculate the sizes for date and time types */
+ size_t len= net_field_length(&cp);
+ switch(stmt->fields[i].type) {
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ stmt->fields[i].max_length= mysql_ps_fetch_functions[stmt->fields[i].type].max_len;
+ break;
+ default:
+ if (len > stmt->fields[i].max_length)
+ stmt->fields[i].max_length= (ulong)len;
+ break;
+ }
+ cp+= len;
+ }
+ else
+ {
+ if (stmt->fields[i].flags & ZEROFILL_FLAG)
+ {
+ /* The -1 is because a ZEROFILL:ed field is always unsigned */
+ size_t len= MAX(stmt->fields[i].length, mysql_ps_fetch_functions[stmt->fields[i].type].max_len-1);
+ if (len > stmt->fields[i].max_length)
+ stmt->fields[i].max_length= (unsigned long)len;
+ }
+ else if (!stmt->fields[i].max_length)
+ {
+ stmt->fields[i].max_length= mysql_ps_fetch_functions[stmt->fields[i].type].max_len;
+ if (stmt->fields[i].flags & UNSIGNED_FLAG &&
+ stmt->fields[i].type != MYSQL_TYPE_INT24 &&
+ stmt->fields[i].type != MYSQL_TYPE_LONGLONG)
+ {
+ /*
+ Unsigned integers has one character less than signed integers
+ as '-' is counted as part of max_length
+ */
+ stmt->fields[i].max_length--;
+ }
+ }
+ cp+= mysql_ps_fetch_functions[stmt->fields[i].type].pack_len;
+ }
+ }
+ if (!((bit_offset <<=1) & 255))
+ {
+ bit_offset= 1; /* To next byte */
+ null_ptr++;
+ }
+ }
+ }
+ current->length= packet_len;
+ result->rows++;
+ } else /* end of stream */
+ {
+ unsigned int last_status= stmt->mysql->server_status;
+ *pprevious= 0;
+ /* sace status info */
+ p++;
+ stmt->upsert_status.warning_count= stmt->mysql->warning_count= uint2korr(p);
+ p+=2;
+ stmt->upsert_status.server_status= stmt->mysql->server_status= uint2korr(p);
+ ma_status_callback(stmt->mysql, last_status);
+ stmt->result_cursor= result->data;
+ return(0);
+ }
+ }
+ stmt->result_cursor= 0;
+ stmt_set_error(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate,
+ stmt->mysql->net.last_error);
+ return(1);
+}
+
+static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row)
+{
+ uchar buf[STMT_ID_LENGTH + 4];
+ MYSQL_DATA *result= &stmt->result;
+
+ if (stmt->state < MYSQL_STMT_USE_OR_STORE_CALLED)
+ {
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ /* do we have some prefetched rows available ? */
+ if (stmt->result_cursor)
+ return(stmt_buffered_fetch(stmt, row));
+ if (stmt->upsert_status.server_status & SERVER_STATUS_LAST_ROW_SENT)
+ stmt->upsert_status.server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
+ else
+ {
+ int4store(buf, stmt->stmt_id);
+ int4store(buf + STMT_ID_LENGTH, stmt->prefetch_rows);
+
+ if (stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_FETCH, (char *)buf, sizeof(buf), 1, stmt))
+ {
+ UPDATE_STMT_ERROR(stmt);
+ return(1);
+ }
+
+ /* free previously allocated buffer */
+ ma_free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
+ result->data= 0;
+ result->rows= 0;
+
+ if (!stmt->mysql->options.extension->skip_read_response)
+ {
+ if (stmt->mysql->methods->db_stmt_read_all_rows(stmt))
+ return(1);
+
+ return(stmt_buffered_fetch(stmt, row));
+ }
+ }
+ /* no more cursor data available */
+ *row= NULL;
+ return(MYSQL_NO_DATA);
+}
+
+/* flush one result set */
+void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt)
+{
+ ulong packet_len;
+ int in_resultset= stmt->state > MYSQL_STMT_EXECUTED &&
+ stmt->state < MYSQL_STMT_FETCH_DONE;
+ while ((packet_len = ma_net_safe_read(stmt->mysql)) != packet_error)
+ {
+ unsigned int last_status= stmt->mysql->server_status;
+ uchar *pos= stmt->mysql->net.read_pos;
+
+ if (!in_resultset && *pos == 0) /* OK */
+ {
+ pos++;
+ net_field_length(&pos);
+ net_field_length(&pos);
+ stmt->mysql->server_status= uint2korr(pos);
+ ma_status_callback(stmt->mysql, last_status);
+ goto end;
+ }
+ if (packet_len < 8 && *pos == 254) /* EOF */
+ {
+ if (mariadb_connection(stmt->mysql))
+ {
+ stmt->mysql->server_status= uint2korr(pos + 3);
+ ma_status_callback(stmt->mysql, last_status);
+ if (in_resultset)
+ goto end;
+ in_resultset= 1;
+ }
+ else
+ goto end;
+ }
+ }
+end:
+ stmt->state= MYSQL_STMT_FETCH_DONE;
+}
+
+int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row)
+{
+ uint i;
+ size_t truncations= 0;
+ unsigned char *null_ptr, bit_offset= 4;
+ row++; /* skip status byte */
+ null_ptr= row;
+ row+= (stmt->field_count + 9) / 8;
+
+ for (i=0; i < stmt->field_count; i++)
+ {
+ /* save row position for fetching values in pieces */
+ if (*null_ptr & bit_offset)
+ {
+ if (stmt->result_callback)
+ stmt->result_callback(stmt->user_data, i, NULL);
+ else
+ {
+ if (!stmt->bind[i].is_null)
+ stmt->bind[i].is_null= &stmt->bind[i].is_null_value;
+ *stmt->bind[i].is_null= 1;
+ stmt->bind[i].u.row_ptr= NULL;
+ }
+ } else
+ {
+ stmt->bind[i].u.row_ptr= row;
+ if (!stmt->bind_result_done ||
+ stmt->bind[i].flags & MADB_BIND_DUMMY)
+ {
+ unsigned long length;
+
+ if (stmt->result_callback)
+ stmt->result_callback(stmt->user_data, i, &row);
+ else {
+ if (mysql_ps_fetch_functions[stmt->fields[i].type].pack_len >= 0)
+ length= mysql_ps_fetch_functions[stmt->fields[i].type].pack_len;
+ else
+ length= net_field_length(&row);
+ row+= length;
+ if (!stmt->bind[i].length)
+ stmt->bind[i].length= &stmt->bind[i].length_value;
+ *stmt->bind[i].length= stmt->bind[i].length_value= length;
+ }
+ }
+ else
+ {
+ if (!stmt->bind[i].length)
+ stmt->bind[i].length= &stmt->bind[i].length_value;
+ if (!stmt->bind[i].is_null)
+ stmt->bind[i].is_null= &stmt->bind[i].is_null_value;
+ *stmt->bind[i].is_null= 0;
+ mysql_ps_fetch_functions[stmt->fields[i].type].func(&stmt->bind[i], &stmt->fields[i], &row);
+ if (stmt->mysql->options.report_data_truncation)
+ truncations+= *stmt->bind[i].error;
+ }
+ }
+
+ if (!((bit_offset <<=1) & 255)) {
+ bit_offset= 1; /* To next byte */
+ null_ptr++;
+ }
+ }
+ return((truncations) ? MYSQL_DATA_TRUNCATED : 0);
+}
+
+MYSQL_RES *_mysql_stmt_use_result(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+
+ if (!stmt->field_count ||
+ (!stmt->cursor_exists && mysql->status != MYSQL_STATUS_STMT_RESULT) ||
+ (stmt->cursor_exists && mysql->status != MYSQL_STATUS_READY) ||
+ (stmt->state != MYSQL_STMT_WAITING_USE_OR_STORE))
+ {
+ SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(NULL);
+ }
+
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+
+ stmt->state = MYSQL_STMT_USE_OR_STORE_CALLED;
+ if (!stmt->cursor_exists)
+ stmt->fetch_row_func= stmt_unbuffered_fetch; //mysql_stmt_fetch_unbuffered_row;
+ else
+ stmt->fetch_row_func= stmt_cursor_fetch;
+
+ return(NULL);
+}
+
+unsigned char *mysql_net_store_length(unsigned char *packet, ulonglong length)
+{
+ if (length < (unsigned long long) L64(251)) {
+ *packet = (unsigned char) length;
+ return packet + 1;
+ }
+
+ if (length < (unsigned long long) L64(65536)) {
+ *packet++ = 252;
+ int2store(packet,(uint) length);
+ return packet + 2;
+ }
+
+ if (length < (unsigned long long) L64(16777216)) {
+ *packet++ = 253;
+ int3store(packet,(ulong) length);
+ return packet + 3;
+ }
+ *packet++ = 254;
+ int8store(packet, length);
+ return packet + 8;
+}
+
+static long ma_get_length(MYSQL_STMT *stmt, unsigned int param_nr, unsigned long row_nr)
+{
+ if (!stmt->params[param_nr].length)
+ return 0;
+ if (stmt->param_callback)
+ return (long)*stmt->params[param_nr].length;
+ if (stmt->row_size)
+ return *(long *)((char *)stmt->params[param_nr].length + row_nr * stmt->row_size);
+ else
+ return stmt->params[param_nr].length[row_nr];
+}
+
+static signed char ma_get_indicator(MYSQL_STMT *stmt, unsigned int param_nr, unsigned long row_nr)
+{
+ if (!MARIADB_STMT_BULK_SUPPORTED(stmt) ||
+ !stmt->array_size ||
+ !stmt->params[param_nr].u.indicator)
+ return 0;
+ if (stmt->param_callback)
+ return *stmt->params[param_nr].u.indicator;
+ if (stmt->row_size)
+ return *((char *)stmt->params[param_nr].u.indicator + (row_nr * stmt->row_size));
+ return stmt->params[param_nr].u.indicator[row_nr];
+}
+
+static void *ma_get_buffer_offset(MYSQL_STMT *stmt, enum enum_field_types type,
+ void *buffer, unsigned long row_nr)
+{
+ if (stmt->param_callback)
+ return buffer;
+
+ if (stmt->array_size)
+ {
+ int len;
+ if (stmt->row_size)
+ return (void *)((char *)buffer + stmt->row_size * row_nr);
+ len= mysql_ps_fetch_functions[type].pack_len;
+ if (len > 0)
+ return (void *)((char *)buffer + len * row_nr);
+ return ((void **)buffer)[row_nr];
+ }
+ return buffer;
+}
+
+int store_param(MYSQL_STMT *stmt, int column, unsigned char **p, unsigned long row_nr)
+{
+ void *buf= ma_get_buffer_offset(stmt, stmt->params[column].buffer_type,
+ stmt->params[column].buffer, row_nr);
+ signed char indicator= ma_get_indicator(stmt, column, row_nr);
+
+ switch (stmt->params[column].buffer_type) {
+ case MYSQL_TYPE_TINY:
+ int1store(*p, (*(uchar *)buf));
+ (*p) += 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ int2store(*p, (*(short *)buf));
+ (*p) += 2;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ float4store(*p, (*(float *)buf));
+ (*p) += 4;
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ float8store(*p, (*(double *)buf));
+ (*p) += 8;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ int8store(*p, (*(ulonglong *)buf));
+ (*p) += 8;
+ break;
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_INT24:
+ int4store(*p, (*(int32 *)buf));
+ (*p)+= 4;
+ break;
+ case MYSQL_TYPE_TIME:
+ {
+ /* binary encoding:
+ Offset Length Field
+ 0 1 Length
+ 1 1 negative
+ 2-5 4 day
+ 6 1 hour
+ 7 1 minute
+ 8 1 second;
+ 9-13 4 second_part
+ */
+ MYSQL_TIME *t= (MYSQL_TIME *)ma_get_buffer_offset(stmt, stmt->params[column].buffer_type,
+ stmt->params[column].buffer, row_nr);
+ char t_buffer[MAX_TIME_STR_LEN];
+ uint len= 0;
+
+ t_buffer[1]= t->neg ? 1 : 0;
+ int4store(t_buffer + 2, t->day);
+ t_buffer[6]= (uchar) t->hour;
+ t_buffer[7]= (uchar) t->minute;
+ t_buffer[8]= (uchar) t->second;
+ if (t->second_part)
+ {
+ int4store(t_buffer + 9, t->second_part);
+ len= 12;
+ }
+ else if (t->day || t->hour || t->minute || t->second)
+ len= 8;
+ t_buffer[0]= len++;
+ memcpy(*p, t_buffer, len);
+ (*p)+= len;
+ break;
+ }
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ {
+ /* binary format for date, timestamp and datetime
+ Offset Length Field
+ 0 1 Length
+ 1-2 2 Year
+ 3 1 Month
+ 4 1 Day
+ 5 1 Hour
+ 6 1 minute
+ 7 1 second
+ 8-11 4 secondpart
+ */
+ MYSQL_TIME *t= (MYSQL_TIME *)ma_get_buffer_offset(stmt, stmt->params[column].buffer_type,
+ stmt->params[column].buffer, row_nr);
+ char t_buffer[MAX_DATETIME_STR_LEN];
+ uint len= 0;
+
+ int2store(t_buffer + 1, t->year);
+ t_buffer[3]= (char) t->month;
+ t_buffer[4]= (char) t->day;
+ t_buffer[5]= (char) t->hour;
+ t_buffer[6]= (char) t->minute;
+ t_buffer[7]= (char) t->second;
+ if (t->second_part)
+ {
+ int4store(t_buffer + 8, t->second_part);
+ len= 11;
+ }
+ else if (t->hour || t->minute || t->second)
+ len= 7;
+ else if (t->year || t->month || t->day)
+ len= 4;
+ else
+ len=0;
+ t_buffer[0]= len++;
+ memcpy(*p, t_buffer, len);
+ (*p)+= len;
+ break;
+ }
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_JSON:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ {
+ ulong len;
+ /* to is after p. The latter hasn't been moved */
+ uchar *to;
+
+ if (indicator == STMT_INDICATOR_NTS)
+ len= -1;
+ else
+ len= ma_get_length(stmt, column, row_nr);
+
+ if (len == (ulong)-1)
+ len= (ulong)strlen((char *)buf);
+
+ to = mysql_net_store_length(*p, len);
+
+ if (len)
+ memcpy(to, buf, len);
+ (*p) = to + len;
+ break;
+ }
+
+ default:
+ /* unsupported parameter type */
+ stmt_set_error(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+ return 0;
+}
+
+/* {{{ ma_stmt_execute_generate_simple_request */
+unsigned char* ma_stmt_execute_generate_simple_request(MYSQL_STMT *stmt, size_t *request_len)
+{
+ /* execute packet has the following format:
+ Offset Length Description
+ -----------------------------------------
+ 0 4 Statement id
+ 4 1 Flags (cursor type)
+ 5 4 Iteration count
+ -----------------------------------------
+ if (stmt->param_count):
+ 6 (paramcount+7)/8 null bitmap
+ ------------------------------------------
+ if (stmt->send_types_to_server):
+ param_count*2 parameter types
+ 1st byte: parameter type
+ 2nd byte flag:
+ unsigned flag (32768)
+ indicator variable exists (16384)
+ ------------------------------------------
+ n data from bind_buffer
+
+ */
+
+ size_t length= 1024;
+ size_t free_bytes= 0;
+ size_t null_byte_offset= 0;
+ uchar *tmp_start;
+ uint i;
+
+ uchar *start= NULL, *p;
+
+ /* preallocate length bytes */
+ /* check: gr */
+ if (!(start= p= (uchar *)malloc(length)))
+ goto mem_error;
+
+ int4store(p, stmt->stmt_id);
+ p += STMT_ID_LENGTH;
+
+ /* flags is 4 bytes, we store just 1 */
+ int1store(p, (unsigned char) stmt->flags);
+ p++;
+
+ int4store(p, 1);
+ p+= 4;
+
+ if (stmt->param_count)
+ {
+ size_t null_count= (stmt->param_count + 7) / 8;
+
+ free_bytes= length - (p - start);
+ if (null_count + 20 > free_bytes)
+ {
+ size_t offset= p - start;
+ length+= offset + null_count + 20;
+ if (!(tmp_start= (uchar *)realloc(start, length)))
+ goto mem_error;
+ start= tmp_start;
+ p= start + offset;
+ }
+
+ null_byte_offset= p - start;
+ memset(p, 0, null_count);
+ p += null_count;
+
+ int1store(p, stmt->send_types_to_server);
+ p++;
+
+ free_bytes= length - (p - start);
+
+ /* Store type information:
+ 2 bytes per type
+ */
+ if (stmt->send_types_to_server)
+ {
+ if (free_bytes < stmt->param_count * 2 + 20)
+ {
+ size_t offset= p - start;
+ length= offset + stmt->param_count * 2 + 20;
+ if (!(tmp_start= (uchar *)realloc(start, length)))
+ goto mem_error;
+ start= tmp_start;
+ p= start + offset;
+ }
+ for (i = 0; i < stmt->param_count; i++)
+ {
+ /* this differs from mysqlnd, c api supports unsigned !! */
+ uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
+ /* check if parameter requires indicator variable */
+ int2store(p, buffer_type);
+ p+= 2;
+ }
+ }
+
+ /* calculate data size */
+ for (i=0; i < stmt->param_count; i++)
+ {
+ size_t size= 0;
+ my_bool has_data= TRUE;
+
+ if (stmt->params[i].long_data_used)
+ {
+ has_data= FALSE;
+ stmt->params[i].long_data_used= 0;
+ }
+
+ if (has_data)
+ {
+ switch (stmt->params[i].buffer_type) {
+ case MYSQL_TYPE_NULL:
+ has_data= FALSE;
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_JSON:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_SET:
+ size+= 9; /* max 8 bytes for size */
+ size+= (size_t)ma_get_length(stmt, i, 0);
+ break;
+ case MYSQL_TYPE_TIME:
+ size+= MAX_TIME_STR_LEN;
+ break;
+ case MYSQL_TYPE_DATE:
+ size+= MAX_DATE_STR_LEN;
+ break;
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ size+= MAX_DATETIME_STR_LEN;
+ break;
+ default:
+ size+= mysql_ps_fetch_functions[stmt->params[i].buffer_type].pack_len;
+ break;
+ }
+ }
+ free_bytes= length - (p - start);
+ if (free_bytes < size + 20)
+ {
+ size_t offset= p - start;
+ length= MAX(2 * length, offset + size + 20);
+ if (!(tmp_start= (uchar *)realloc(start, length)))
+ goto mem_error;
+ start= tmp_start;
+ p= start + offset;
+ }
+ if (((stmt->params[i].is_null && *stmt->params[i].is_null) ||
+ stmt->params[i].buffer_type == MYSQL_TYPE_NULL ||
+ !stmt->params[i].buffer))
+ {
+ has_data= FALSE;
+ (start + null_byte_offset)[i/8] |= (unsigned char) (1 << (i & 7));
+ }
+
+ if (has_data)
+ {
+ store_param(stmt, i, &p, 0);
+ }
+ }
+ }
+ stmt->send_types_to_server= 0;
+ *request_len = (size_t)(p - start);
+ return start;
+mem_error:
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ free(start);
+ *request_len= 0;
+ return NULL;
+}
+/* }}} */
+
+/* {{{ mysql_stmt_skip_paramset */
+my_bool mysql_stmt_skip_paramset(MYSQL_STMT *stmt, uint row)
+{
+ uint i;
+ for (i=0; i < stmt->param_count; i++)
+ {
+ if (ma_get_indicator(stmt, i, row) == STMT_INDICATOR_IGNORE_ROW)
+ return '\1';
+ }
+
+ return '\0';
+}
+/* }}} */
+
+/* {{{ ma_stmt_execute_generate_bulk_request */
+unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *request_len)
+{
+ /* execute packet has the following format:
+ Offset Length Description
+ -----------------------------------------
+ 0 4 Statement id
+ 4 2 Flags (cursor type):
+ STMT_BULK_FLAG_CLIENT_SEND_TYPES = 128
+ STMT_BULK_FLAG_INSERT_ID_REQUEST = 64
+ -----------------------------------------
+ if (stmt->send_types_to_server):
+ for (i=0; i < param_count; i++)
+ 1st byte: parameter type
+ 2nd byte flag:
+ unsigned flag (32768)
+ ------------------------------------------
+ for (i=0; i < param_count; i++)
+ 1 indicator variable
+ STMT_INDICATOR_NONE 0
+ STMT_INDICATOR_NULL 1
+ STMT_INDICATOR_DEFAULT 2
+ STMT_INDICATOR_IGNORE 3
+ STMT_INDICATOR_SKIP_SET 4
+ n data from bind buffer
+
+ */
+
+ size_t length= 1024;
+ size_t free_bytes= 0;
+ ushort flags= 0;
+ uchar *tmp_start;
+ uint i, j;
+
+ uchar *start= NULL, *p;
+
+ if (!MARIADB_STMT_BULK_SUPPORTED(stmt))
+ {
+ stmt_set_error(stmt, CR_FUNCTION_NOT_SUPPORTED, "IM001",
+ CER(CR_FUNCTION_NOT_SUPPORTED), "Bulk operation");
+ return NULL;
+ }
+
+ if (!stmt->param_count)
+ {
+ stmt_set_error(stmt, CR_BULK_WITHOUT_PARAMETERS, "IM001",
+ CER(CR_BULK_WITHOUT_PARAMETERS));
+ return NULL;
+ }
+
+ /* preallocate length bytes */
+ if (!(start= p= (uchar *)malloc(length)))
+ {
+ goto mem_error;
+ }
+
+ int4store(p, stmt->stmt_id);
+ p += STMT_ID_LENGTH;
+
+ /* todo: request to return auto generated ids */
+ if (stmt->send_types_to_server)
+ flags|= STMT_BULK_FLAG_CLIENT_SEND_TYPES;
+ int2store(p, flags);
+ p+=2;
+
+ /* When using mariadb_stmt_execute_direct stmt->paran_count is
+ not known, so we need to assign prebind_params, which was previously
+ set by mysql_stmt_attr_set
+ */
+ if (!stmt->param_count && stmt->prebind_params)
+ stmt->param_count= stmt->prebind_params;
+
+ if (stmt->param_count)
+ {
+ free_bytes= length - (p - start);
+
+ /* Store type information:
+ 2 bytes per type
+ */
+ if (stmt->send_types_to_server)
+ {
+ if (free_bytes < stmt->param_count * 2 + 20)
+ {
+ size_t offset= p - start;
+ length= offset + stmt->param_count * 2 + 20;
+ if (!(tmp_start= (uchar *)realloc(start, length)))
+ {
+ goto mem_error;
+ }
+ start= tmp_start;
+ p= start + offset;
+ }
+ for (i = 0; i < stmt->param_count; i++)
+ {
+ /* this differs from mysqlnd, c api supports unsigned !! */
+ uint buffer_type= stmt->params[i].buffer_type | (stmt->params[i].is_unsigned ? 32768 : 0);
+ int2store(p, buffer_type);
+ p+= 2;
+ }
+ }
+
+ /* calculate data size */
+ for (j=0; j < stmt->array_size; j++)
+ {
+ /* If callback for parameters was specified, we need to
+ update bind information for new row */
+ if (stmt->param_callback)
+ {
+ if (stmt->param_callback(stmt->user_data, stmt->params, j))
+ {
+ stmt_set_error(stmt, CR_ERR_STMT_PARAM_CALLBACK, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+ }
+
+ if (mysql_stmt_skip_paramset(stmt, j))
+ continue;
+
+ for (i=0; i < stmt->param_count; i++)
+ {
+ size_t size= 0;
+ my_bool has_data= TRUE;
+ signed char indicator= ma_get_indicator(stmt, i, j);
+ /* check if we need to send data */
+ if (indicator > 0)
+ has_data= FALSE;
+ size= 1;
+
+ /* Please note that mysql_stmt_send_long_data is not supported
+ current when performing bulk execute */
+
+ if (has_data)
+ {
+ switch (stmt->params[i].buffer_type) {
+ case MYSQL_TYPE_NULL:
+ has_data= FALSE;
+ indicator= STMT_INDICATOR_NULL;
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_JSON:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_SET:
+ size+= 5; /* max 8 bytes for size */
+ if (!stmt->param_callback)
+ {
+ if (indicator == STMT_INDICATOR_NTS ||
+ (!stmt->row_size && ma_get_length(stmt,i,j) == -1))
+ {
+ size+= strlen(ma_get_buffer_offset(stmt,
+ stmt->params[i].buffer_type,
+ stmt->params[i].buffer,j));
+ }
+ else
+ size+= (size_t)ma_get_length(stmt, i, j);
+ }
+ else {
+ size+= stmt->params[i].buffer_length;
+ }
+ break;
+ default:
+ size+= mysql_ps_fetch_functions[stmt->params[i].buffer_type].pack_len;
+ break;
+ }
+ }
+ free_bytes= length - (p - start);
+ if (free_bytes < size + 20)
+ {
+ size_t offset= p - start;
+ length= MAX(2 * length, offset + size + 20);
+ if (!(tmp_start= (uchar *)realloc(start, length)))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+ start= tmp_start;
+ p= start + offset;
+ }
+
+ int1store(p, indicator > 0 ? indicator : 0);
+ p++;
+ if (has_data) {
+ store_param(stmt, i, &p, (stmt->param_callback) ? 0 : j);
+ }
+ }
+ }
+
+ }
+ stmt->send_types_to_server= 0;
+ *request_len = (size_t)(p - start);
+ return start;
+mem_error:
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+error:
+ free(start);
+ *request_len= 0;
+ return NULL;
+}
+/* }}} */
+
+
+unsigned char* ma_stmt_execute_generate_request(MYSQL_STMT *stmt, size_t *request_len, my_bool internal)
+{
+ unsigned char *buf;
+
+
+ if (stmt->request_buffer)
+ {
+ *request_len= stmt->request_length;
+ buf= stmt->request_buffer;
+ /* store actual stmt id */
+ int4store(buf, stmt->stmt_id);
+ /* clear buffer, memory will be freed in execute */
+ stmt->request_buffer= NULL;
+ stmt->request_length= 0;
+ return buf;
+ }
+ if (stmt->array_size > 0)
+ buf= ma_stmt_execute_generate_bulk_request(stmt, request_len);
+ else
+ buf= ma_stmt_execute_generate_simple_request(stmt, request_len);
+
+ if (internal)
+ {
+ if (stmt->request_buffer)
+ free(stmt->request_buffer);
+ stmt->request_buffer= buf;
+ stmt->request_length= *request_len;
+ }
+ return buf;
+}
+
+
+/*!
+ *******************************************************************************
+
+ \fn unsigned long long mysql_stmt_affected_rows
+ \brief returns the number of affected rows from last mysql_stmt_execute
+ call
+
+ \param[in] stmt The statement handle
+ *******************************************************************************
+ */
+unsigned long long STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
+{
+ return stmt->upsert_status.affected_rows;
+}
+
+my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *value)
+{
+ switch (attr_type) {
+ case STMT_ATTR_STATE:
+ *(enum mysql_stmt_state *)value= stmt->state;
+ break;
+ case STMT_ATTR_UPDATE_MAX_LENGTH:
+ *(my_bool *)value= stmt->update_max_length;
+ break;
+ case STMT_ATTR_CURSOR_TYPE:
+ *(unsigned long *)value= stmt->flags;
+ break;
+ case STMT_ATTR_PREFETCH_ROWS:
+ *(unsigned long *)value= stmt->prefetch_rows;
+ break;
+ case STMT_ATTR_PREBIND_PARAMS:
+ *(unsigned int *)value= stmt->prebind_params;
+ break;
+ case STMT_ATTR_ARRAY_SIZE:
+ *(unsigned int *)value= stmt->array_size;
+ break;
+ case STMT_ATTR_ROW_SIZE:
+ *(size_t *)value= stmt->row_size;
+ break;
+ case STMT_ATTR_CB_USER_DATA:
+ *((void **)value) = stmt->user_data;
+ break;
+ default:
+ return(1);
+ }
+ return(0);
+}
+
+my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, const void *value)
+{
+ switch (attr_type) {
+ case STMT_ATTR_UPDATE_MAX_LENGTH:
+ stmt->update_max_length= *(my_bool *)value;
+ break;
+ case STMT_ATTR_CURSOR_TYPE:
+ if (*(ulong *)value > (unsigned long) CURSOR_TYPE_READ_ONLY)
+ {
+ stmt_set_error(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ stmt->flags = *(ulong *)value;
+ break;
+ case STMT_ATTR_PREFETCH_ROWS:
+ if (*(ulong *)value == 0)
+ *(long *)value= MYSQL_DEFAULT_PREFETCH_ROWS;
+ else
+ stmt->prefetch_rows= *(long *)value;
+ break;
+ case STMT_ATTR_PREBIND_PARAMS:
+ if (stmt->state > MYSQL_STMT_INITTED)
+ {
+ mysql_stmt_internal_reset(stmt, 1);
+ net_stmt_close(stmt, 0);
+ stmt->state= MYSQL_STMT_INITTED;
+ stmt->params= 0;
+ }
+ stmt->prebind_params= stmt->param_count= *(unsigned int *)value;
+ break;
+ case STMT_ATTR_ARRAY_SIZE:
+ stmt->array_size= *(unsigned int *)value;
+ break;
+ case STMT_ATTR_ROW_SIZE:
+ stmt->row_size= *(size_t *)value;
+ break;
+ case STMT_ATTR_CB_RESULT:
+ stmt->result_callback= (ps_result_callback)value;
+ break;
+ case STMT_ATTR_CB_PARAM:
+ stmt->param_callback= (ps_param_callback)value;
+ break;
+ case STMT_ATTR_CB_USER_DATA:
+ stmt->user_data= (void *)value;
+ break;
+ default:
+ stmt_set_error(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ return(0);
+}
+
+my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
+{
+ MYSQL *mysql= stmt->mysql;
+
+ if (!mysql)
+ {
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ /* If number of parameters was specified via mysql_stmt_attr_set we need to realloc
+ them, e.g. for mariadb_stmt_execute_direct()
+ */
+ if ((stmt->state < MYSQL_STMT_PREPARED || stmt->state >= MYSQL_STMT_EXECUTED) &&
+ stmt->prebind_params > 0)
+ {
+ if (!stmt->params && stmt->prebind_params)
+ {
+ if (!(stmt->params= (MYSQL_BIND *)ma_alloc_root(&stmt->mem_root, stmt->prebind_params * sizeof(MYSQL_BIND))))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ memset(stmt->params, '\0', stmt->prebind_params * sizeof(MYSQL_BIND));
+ }
+ stmt->param_count= stmt->prebind_params;
+ }
+ else if (stmt->state < MYSQL_STMT_PREPARED) {
+ stmt_set_error(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (stmt->param_count && bind)
+ {
+ uint i;
+
+ memcpy(stmt->params, bind, sizeof(MYSQL_BIND) * stmt->param_count);
+ stmt->send_types_to_server= 1;
+
+ for (i=0; i < stmt->param_count; i++)
+ {
+ if (stmt->mysql->methods->db_supported_buffer_type &&
+ !stmt->mysql->methods->db_supported_buffer_type(stmt->params[i].buffer_type))
+ {
+ stmt_set_error(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ if (!stmt->params[i].is_null)
+ stmt->params[i].is_null= &is_not_null;
+
+ if (stmt->params[i].long_data_used)
+ stmt->params[i].long_data_used= 0;
+
+ if (!stmt->params[i].length)
+ stmt->params[i].length= &stmt->params[i].buffer_length;
+
+ switch(stmt->params[i].buffer_type) {
+ case MYSQL_TYPE_NULL:
+ stmt->params[i].is_null= &is_null;
+ break;
+ case MYSQL_TYPE_TINY:
+ stmt->params[i].buffer_length= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ stmt->params[i].buffer_length= 2;
+ break;
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_FLOAT:
+ stmt->params[i].buffer_length= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_DOUBLE:
+ stmt->params[i].buffer_length= 8;
+ break;
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ stmt->params[i].buffer_length= 12;
+ break;
+ case MYSQL_TYPE_TIME:
+ stmt->params[i].buffer_length= 13;
+ break;
+ case MYSQL_TYPE_DATE:
+ stmt->params[i].buffer_length= 5;
+ break;
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_JSON:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ break;
+ default:
+ stmt_set_error(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ break;
+ }
+ }
+ }
+ stmt->bind_param_done= stmt->send_types_to_server= 1;
+
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+ return(0);
+}
+
+my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
+{
+ uint i;
+
+ if (stmt->state < MYSQL_STMT_PREPARED)
+ {
+ stmt_set_error(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (!stmt->field_count)
+ {
+ stmt_set_error(stmt, CR_NO_STMT_METADATA, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (!bind)
+ return(1);
+
+ /* In case of a stored procedure we don't allocate memory for bind
+ in mysql_stmt_prepare
+ */
+
+ if (stmt->field_count && !stmt->bind)
+ {
+ MA_MEM_ROOT *fields_ma_alloc_root=
+ &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
+ if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ }
+
+ memcpy(stmt->bind, bind, sizeof(MYSQL_BIND) * stmt->field_count);
+
+ for (i=0; i < stmt->field_count; i++)
+ {
+ if (stmt->mysql->methods->db_supported_buffer_type &&
+ !stmt->mysql->methods->db_supported_buffer_type(bind[i].buffer_type))
+ {
+ stmt_set_error(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (!stmt->bind[i].is_null)
+ stmt->bind[i].is_null= &stmt->bind[i].is_null_value;
+ if (!stmt->bind[i].length)
+ stmt->bind[i].length= &stmt->bind[i].length_value;
+ if (!stmt->bind[i].error)
+ stmt->bind[i].error= &stmt->bind[i].error_value;
+
+ /* set length values for numeric types */
+ switch(bind[i].buffer_type) {
+ case MYSQL_TYPE_NULL:
+ *stmt->bind[i].length= stmt->bind[i].length_value= 0;
+ break;
+ case MYSQL_TYPE_TINY:
+ *stmt->bind[i].length= stmt->bind[i].length_value= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ *stmt->bind[i].length= stmt->bind[i].length_value= 2;
+ break;
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_FLOAT:
+ *stmt->bind[i].length= stmt->bind[i].length_value= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_DOUBLE:
+ *stmt->bind[i].length= stmt->bind[i].length_value= 8;
+ break;
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ *stmt->bind[i].length= stmt->bind[i].length_value= sizeof(MYSQL_TIME);
+ break;
+ default:
+ break;
+ }
+ }
+ stmt->bind_result_done= 1;
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+
+ return(0);
+}
+
+static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove)
+{
+ char stmt_id[STMT_ID_LENGTH];
+ MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
+
+ /* clear memory */
+ ma_free_root(&stmt->result.alloc, MYF(0)); /* allocated in mysql_stmt_store_result */
+ ma_free_root(&stmt->mem_root,MYF(0));
+ ma_free_root(fields_ma_alloc_root, MYF(0));
+
+ if (stmt->mysql)
+ {
+ CLEAR_CLIENT_ERROR(stmt->mysql);
+
+ /* remove from stmt list */
+ if (remove)
+ stmt->mysql->stmts= list_delete(stmt->mysql->stmts, &stmt->list);
+
+ /* check if all data are fetched */
+ if (stmt->mysql->status != MYSQL_STATUS_READY)
+ {
+ do {
+ stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
+ } while(mysql_stmt_more_results(stmt));
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ }
+ if (stmt->state > MYSQL_STMT_INITTED)
+ {
+ int4store(stmt_id, stmt->stmt_id);
+ if (stmt->mysql->methods->db_command(stmt->mysql,COM_STMT_CLOSE, stmt_id,
+ sizeof(stmt_id), 1, stmt))
+ {
+ UPDATE_STMT_ERROR(stmt);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
+{
+ my_bool rc= 1;
+
+ if (stmt)
+ {
+ if (stmt->mysql && stmt->mysql->net.pvio)
+ mysql_stmt_internal_reset(stmt, 1);
+
+ rc= net_stmt_close(stmt, 1);
+
+ free(stmt->extension);
+ free(stmt);
+ }
+ return(rc);
+}
+
+void STDCALL mysql_stmt_data_seek(MYSQL_STMT *stmt, unsigned long long offset)
+{
+ unsigned long long i= offset;
+ MYSQL_ROWS *ptr= stmt->result.data;
+
+ while(i-- && ptr)
+ ptr= ptr->next;
+
+ stmt->result_cursor= ptr;
+ stmt->state= MYSQL_STMT_USER_FETCHING;
+
+ return;
+}
+
+unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT *stmt)
+{
+ return stmt->last_errno;
+}
+
+const char * STDCALL mysql_stmt_error(MYSQL_STMT *stmt)
+{
+ return (const char *)stmt->last_error;
+}
+
+int mthd_stmt_fetch_row(MYSQL_STMT *stmt, unsigned char **row)
+{
+ return stmt->fetch_row_func(stmt, row);
+}
+
+int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
+{
+ unsigned char *row;
+ int rc;
+
+ if (stmt->state <= MYSQL_STMT_EXECUTED)
+ {
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (stmt->state < MYSQL_STMT_WAITING_USE_OR_STORE || !stmt->field_count)
+ {
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ } else if (stmt->state== MYSQL_STMT_WAITING_USE_OR_STORE)
+ {
+ stmt->default_rset_handler(stmt);
+ }
+
+ if (stmt->state == MYSQL_STMT_FETCH_DONE)
+ return(MYSQL_NO_DATA);
+
+ if ((rc= stmt->mysql->methods->db_stmt_fetch(stmt, &row)))
+ {
+ stmt->state= MYSQL_STMT_FETCH_DONE;
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ /* to fetch data again, stmt must be executed again */
+ return(rc);
+ }
+
+ rc= stmt->mysql->methods->db_stmt_fetch_to_bind(stmt, row);
+
+ stmt->state= MYSQL_STMT_USER_FETCHING;
+ CLEAR_CLIENT_ERROR(stmt->mysql);
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+ return(rc);
+}
+
+int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset)
+{
+ if (stmt->state < MYSQL_STMT_USER_FETCHING || column >= stmt->field_count ||
+ stmt->state == MYSQL_STMT_FETCH_DONE) {
+ stmt_set_error(stmt, CR_NO_DATA, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (!stmt->bind[column].u.row_ptr)
+ {
+ /* we set row_ptr only for columns which contain data, so this must be a NULL column */
+ if (bind[0].is_null)
+ *bind[0].is_null= 1;
+ }
+ else
+ {
+ unsigned char *save_ptr;
+ if (bind[0].length)
+ *bind[0].length= *stmt->bind[column].length;
+ else
+ bind[0].length= &stmt->bind[column].length_value;
+ if (bind[0].is_null)
+ *bind[0].is_null= 0;
+ else
+ bind[0].is_null= &bind[0].is_null_value;
+ if (!bind[0].error)
+ bind[0].error= &bind[0].error_value;
+ *bind[0].error= 0;
+ bind[0].offset= offset;
+ save_ptr= stmt->bind[column].u.row_ptr;
+ mysql_ps_fetch_functions[stmt->fields[column].type].func(&bind[0], &stmt->fields[column], &stmt->bind[column].u.row_ptr);
+ stmt->bind[column].u.row_ptr= save_ptr;
+ }
+ return(0);
+}
+
+unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
+{
+ return stmt->field_count;
+}
+
+my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
+{
+ return madb_reset_stmt(stmt, MADB_RESET_LONGDATA | MADB_RESET_STORED |
+ MADB_RESET_BUFFER | MADB_RESET_ERROR);
+}
+
+MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql)
+{
+
+ MYSQL_STMT *stmt= NULL;
+
+ if (!(stmt= (MYSQL_STMT *)calloc(1, sizeof(MYSQL_STMT))) ||
+ !(stmt->extension= (MADB_STMT_EXTENSION *)calloc(1, sizeof(MADB_STMT_EXTENSION))))
+ {
+ free(stmt);
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(NULL);
+ }
+
+
+ /* fill mysql's stmt list */
+ stmt->list.data= stmt;
+ stmt->mysql= mysql;
+ stmt->stmt_id= 0;
+ mysql->stmts= list_add(mysql->stmts, &stmt->list);
+
+
+ /* clear flags */
+ strcpy(stmt->sqlstate, "00000");
+
+ stmt->state= MYSQL_STMT_INITTED;
+
+ /* set default */
+ stmt->prefetch_rows= 1;
+
+ ma_init_alloc_root(&stmt->mem_root, 2048, 2048);
+ ma_init_alloc_root(&stmt->result.alloc, 4096, 4096);
+ ma_init_alloc_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root, 2048, 2048);
+
+ return(stmt);
+}
+
+my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt)
+{
+ ulong packet_length;
+ uchar *p;
+
+ if ((packet_length= ma_net_safe_read(stmt->mysql)) == packet_error)
+ return(1);
+
+ p= (uchar *)stmt->mysql->net.read_pos;
+
+ if (0xFF == p[0]) /* Error occurred */
+ {
+ return(1);
+ }
+
+ p++;
+ stmt->stmt_id= uint4korr(p);
+ p+= 4;
+ stmt->field_count= uint2korr(p);
+ p+= 2;
+ stmt->param_count= uint2korr(p);
+ p+= 2;
+
+ /* filler */
+ p++;
+ /* for backward compatibility we also update mysql->warning_count */
+ stmt->mysql->warning_count= stmt->upsert_status.warning_count= uint2korr(p);
+
+/* metadata not supported yet */
+
+ if (stmt->param_count &&
+ stmt->mysql->methods->db_stmt_get_param_metadata(stmt))
+ {
+ return 1;
+ }
+
+ /* allocated bind buffer for parameters */
+ if (stmt->field_count &&
+ stmt->mysql->methods->db_stmt_get_result_metadata(stmt))
+ {
+ return 1;
+ }
+ if (stmt->param_count)
+ {
+ if (stmt->prebind_params)
+ {
+ if (stmt->prebind_params != stmt->param_count)
+ {
+ stmt_set_error(stmt, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
+ stmt->param_count= stmt->prebind_params;
+ return 1;
+ }
+ } else {
+ if (!(stmt->params= (MYSQL_BIND *)ma_alloc_root(&stmt->mem_root, stmt->param_count * sizeof(MYSQL_BIND))))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+ memset(stmt->params, '\0', stmt->param_count * sizeof(MYSQL_BIND));
+ }
+ }
+ /* allocated bind buffer for result */
+ if (stmt->field_count)
+ {
+ MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
+ if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+ memset(stmt->bind, 0, sizeof(MYSQL_BIND) * stmt->field_count);
+ }
+ stmt->state = MYSQL_STMT_PREPARED;
+
+ return(0);
+}
+
+my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt)
+{
+ MYSQL_DATA *result;
+
+ if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0,
+ 7 + ma_extended_type_info_rows(stmt->mysql))))
+ return(1);
+
+ free_rows(result);
+ return(0);
+}
+
+my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt)
+{
+ MYSQL_DATA *result;
+ MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
+
+ if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0,
+ 7 + ma_extended_type_info_rows(stmt->mysql))))
+ return(1);
+ if (!(stmt->fields= unpack_fields(stmt->mysql, result, fields_ma_alloc_root,
+ stmt->field_count, 0)))
+ return(1);
+ return(0);
+}
+
+int STDCALL mysql_stmt_warning_count(MYSQL_STMT *stmt)
+{
+ return stmt->upsert_status.warning_count;
+}
+
+int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)
+{
+ MYSQL *mysql= stmt->mysql;
+ int rc= 1;
+ my_bool is_multi= 0;
+
+ if (!stmt->mysql)
+ {
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (length == (unsigned long) -1)
+ length= (unsigned long)strlen(query);
+
+ /* clear flags */
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+ CLEAR_CLIENT_ERROR(stmt->mysql);
+ stmt->upsert_status.affected_rows= mysql->affected_rows= (unsigned long long) ~0;
+
+ /* check if we have to clear results */
+ if (stmt->state > MYSQL_STMT_INITTED)
+ {
+ char stmt_id[STMT_ID_LENGTH];
+ is_multi= (mysql->net.extension->multi_status > COM_MULTI_OFF);
+ /* We need to semi-close the prepared statement:
+ reset stmt and free all buffers and close the statement
+ on server side. Statement handle will get a new stmt_id */
+
+ if (!is_multi)
+ ma_multi_command(mysql, COM_MULTI_ENABLED);
+
+ if (mysql_stmt_internal_reset(stmt, 1))
+ goto fail;
+
+ ma_free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
+ ma_free_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root, MYF(0));
+
+ stmt->param_count= 0;
+ stmt->field_count= 0;
+ stmt->fields= NULL;
+ stmt->params= NULL;
+
+ int4store(stmt_id, stmt->stmt_id);
+ if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id,
+ sizeof(stmt_id), 1, stmt))
+ goto fail;
+ }
+ if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt))
+ goto fail;
+
+ if (!is_multi && mysql->net.extension->multi_status == COM_MULTI_ENABLED)
+ if (ma_multi_command(mysql, COM_MULTI_END))
+ goto fail;
+
+ if (mysql->net.extension->multi_status > COM_MULTI_OFF ||
+ mysql->options.extension->skip_read_response)
+ return 0;
+
+ if (mysql->methods->db_read_prepare_response &&
+ mysql->methods->db_read_prepare_response(stmt))
+ goto fail;
+
+ return(0);
+
+fail:
+ stmt->state= MYSQL_STMT_INITTED;
+ UPDATE_STMT_ERROR(stmt);
+ return(rc);
+}
+
+int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
+{
+ unsigned int last_server_status;
+
+ if (!stmt->mysql)
+ {
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (!stmt->field_count)
+ return(0);
+
+ /* test_pure_coverage requires checking of error_no */
+ if (stmt->last_errno)
+ return(1);
+
+ if (stmt->state < MYSQL_STMT_EXECUTED)
+ {
+ SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ last_server_status= stmt->mysql->server_status;
+
+ /* if stmt is a cursor, we need to tell server to send all rows */
+ if (stmt->cursor_exists && stmt->mysql->status == MYSQL_STATUS_READY)
+ {
+ char buff[STMT_ID_LENGTH + 4];
+ int4store(buff, stmt->stmt_id);
+ int4store(buff + STMT_ID_LENGTH, (int)~0);
+
+ if (stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_FETCH,
+ buff, sizeof(buff), 1, stmt))
+ {
+ UPDATE_STMT_ERROR(stmt);
+ return(1);
+ }
+ }
+ else if (stmt->mysql->status != MYSQL_STATUS_STMT_RESULT)
+ {
+ SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (stmt->mysql->methods->db_stmt_read_all_rows(stmt))
+ {
+ /* error during read - reset stmt->data */
+ ma_free_root(&stmt->result.alloc, 0);
+ stmt->result.data= NULL;
+ stmt->result.rows= 0;
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ return(1);
+ }
+
+ /* workaround for MDEV 6304:
+ more results not set if the resultset has
+ SERVER_PS_OUT_PARAMS set
+ */
+ if (last_server_status & SERVER_PS_OUT_PARAMS &&
+ !(stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST))
+ stmt->mysql->server_status|= SERVER_MORE_RESULTS_EXIST;
+
+ stmt->result_cursor= stmt->result.data;
+ stmt->fetch_row_func= stmt_buffered_fetch;
+ stmt->mysql->status= MYSQL_STATUS_READY;
+
+ if (!stmt->result.rows)
+ stmt->state= MYSQL_STMT_FETCH_DONE;
+ else
+ stmt->state= MYSQL_STMT_USE_OR_STORE_CALLED;
+
+ /* set affected rows: see bug 2247 */
+ stmt->upsert_status.affected_rows= stmt->result.rows;
+ stmt->mysql->affected_rows= stmt->result.rows;
+
+ return(0);
+}
+
+static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
+{
+ MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
+ MYSQL *mysql= stmt->mysql;
+ if (!mysql->field_count)
+ return 0;
+
+ stmt->field_count= mysql->field_count;
+ if (mysql->fields)
+ {
+ /* Column info was sent by server */
+ ma_free_root(fields_ma_alloc_root, MYF(0));
+ if (!(stmt->fields= ma_duplicate_resultset_metadata(
+ mysql->fields, mysql->field_count,
+ fields_ma_alloc_root)))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ if (!(stmt->bind= (MYSQL_BIND *) ma_alloc_root(
+ fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return (1);
+ }
+ }
+ memset(stmt->bind, 0, stmt->field_count * sizeof(MYSQL_BIND));
+ stmt->bind_result_done= 0;
+ return(0);
+}
+
+int mthd_stmt_read_execute_response(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ int ret;
+ unsigned int last_status= mysql->server_status;
+
+ if (!mysql)
+ return(1);
+
+ /* if a reconnect occurred, our connection handle is invalid */
+ if (!stmt->mysql)
+ return (1);
+
+ ret= test((mysql->methods->db_read_stmt_result &&
+ mysql->methods->db_read_stmt_result(mysql)));
+
+ if (!ret && mysql->field_count && !mysql->fields)
+ {
+ /*
+ Column info was not sent by server, copy
+ from stmt->fields
+ */
+ assert(stmt->fields);
+ /*
+ Too bad, C/C resets stmt->field_count to 0
+ before reading SP output variables result sets.
+ */
+ if(!stmt->field_count)
+ stmt->field_count = mysql->field_count;
+ else
+ assert(mysql->field_count == stmt->field_count);
+ mysql->fields= ma_duplicate_resultset_metadata(
+ stmt->fields, stmt->field_count, &mysql->field_alloc);
+ if (!mysql->fields)
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return (1);
+ }
+ }
+
+ /* update affected rows, also if an error occurred */
+ stmt->upsert_status.affected_rows= stmt->mysql->affected_rows;
+
+ if (ret)
+ {
+ stmt_set_error(stmt, mysql->net.last_errno, mysql->net.sqlstate,
+ mysql->net.last_error);
+ /* if mariadb_stmt_execute_direct was used, we need to send the number
+ of parameters to the specified prebinded value to prevent possible
+ memory overrun */
+ if (stmt->prebind_params)
+ {
+ stmt->param_count= stmt->prebind_params;
+ }
+ stmt->state= MYSQL_STMT_PREPARED;
+ return(1);
+ }
+ stmt->upsert_status.last_insert_id= mysql->insert_id;
+ stmt->upsert_status.server_status= mysql->server_status;
+ ma_status_callback(stmt->mysql, last_status);
+ stmt->upsert_status.warning_count= mysql->warning_count;
+
+ CLEAR_CLIENT_ERROR(mysql);
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+
+ stmt->execute_count++;
+ stmt->send_types_to_server= 0;
+
+ stmt->state= MYSQL_STMT_EXECUTED;
+
+ if (mysql->field_count)
+ {
+ if (!stmt->field_count ||
+ mysql->server_status & SERVER_MORE_RESULTS_EXIST) /* fix for ps_bug: test_misc */
+ {
+ MA_MEM_ROOT *fields_ma_alloc_root=
+ &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root;
+ uint i;
+
+ ma_free_root(fields_ma_alloc_root, MYF(0));
+ if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root,
+ sizeof(MYSQL_BIND) * mysql->field_count)) ||
+ !(stmt->fields= (MYSQL_FIELD *)ma_alloc_root(fields_ma_alloc_root,
+ sizeof(MYSQL_FIELD) * mysql->field_count)))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ memset(stmt->bind, 0, sizeof(MYSQL_BIND) * mysql->field_count);
+ stmt->field_count= mysql->field_count;
+
+ for (i=0; i < stmt->field_count; i++)
+ {
+ memcpy(&stmt->fields[i], &mysql->fields[i], sizeof(MYSQL_FIELD));
+
+ /* since all pointers will be incorrect if another statement will
+ be executed, so we need to allocate memory and copy the
+ information */
+ if (mysql->fields[i].db)
+ stmt->fields[i].db= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].db);
+ if (mysql->fields[i].table)
+ stmt->fields[i].table= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].table);
+ if (mysql->fields[i].org_table)
+ stmt->fields[i].org_table= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].org_table);
+ if (mysql->fields[i].name)
+ stmt->fields[i].name= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].name);
+ if (mysql->fields[i].org_name)
+ stmt->fields[i].org_name= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].org_name);
+ if (mysql->fields[i].catalog)
+ stmt->fields[i].catalog= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].catalog);
+ if (mysql->fields[i].def)
+ stmt->fields[i].def= ma_strdup_root(fields_ma_alloc_root, mysql->fields[i].def);
+ stmt->fields[i].extension=
+ mysql->fields[i].extension ?
+ ma_field_extension_deep_dup(fields_ma_alloc_root,
+ mysql->fields[i].extension) :
+ NULL;
+ }
+ }
+
+ if ((stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) &&
+ (stmt->flags & CURSOR_TYPE_READ_ONLY))
+ {
+ stmt->cursor_exists = TRUE;
+ mysql->status = MYSQL_STATUS_READY;
+
+ /* Only cursor read */
+ stmt->default_rset_handler = _mysql_stmt_use_result;
+
+ } else if (stmt->flags & CURSOR_TYPE_READ_ONLY &&
+ !(stmt->upsert_status.server_status & SERVER_MORE_RESULTS_EXIST))
+ {
+ /*
+ We have asked for CURSOR but got no cursor, because the condition
+ above is not fulfilled. Then...
+ This is a single-row result set, a result set with no rows, EXPLAIN,
+ SHOW VARIABLES, or some other command which either a) bypasses the
+ cursors framework in the server and writes rows directly to the
+ network or b) is more efficient if all (few) result set rows are
+ precached on client and server's resources are freed.
+ */
+
+ /* preferred is buffered read */
+ if (mysql_stmt_store_result(stmt))
+ return 1;
+ stmt->mysql->status= MYSQL_STATUS_STMT_RESULT;
+ } else
+ {
+ /* preferred is unbuffered read */
+ stmt->default_rset_handler = _mysql_stmt_use_result;
+ stmt->mysql->status= MYSQL_STATUS_STMT_RESULT;
+ }
+ stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE;
+ /* in certain cases parameter types can change: For example see bug
+ 4026 (SELECT ?), so we need to update field information */
+ if (mysql->field_count == stmt->field_count)
+ {
+ uint i;
+ for (i=0; i < stmt->field_count; i++)
+ {
+ stmt->fields[i].type= mysql->fields[i].type;
+ stmt->fields[i].length= mysql->fields[i].length;
+ stmt->fields[i].flags= mysql->fields[i].flags;
+ stmt->fields[i].decimals= mysql->fields[i].decimals;
+ stmt->fields[i].charsetnr= mysql->fields[i].charsetnr;
+ stmt->fields[i].max_length= mysql->fields[i].max_length;
+ }
+ } else
+ {
+ /* table was altered, see test_wl4166_2 */
+ stmt_set_error(stmt, CR_NEW_STMT_METADATA, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ char *request;
+ int ret;
+ size_t request_len= 0;
+
+ if (!stmt->mysql)
+ {
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (stmt->state < MYSQL_STMT_PREPARED)
+ {
+ SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (stmt->param_count && !stmt->bind_param_done)
+ {
+ stmt_set_error(stmt, CR_PARAMS_NOT_BOUND, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
+ {
+ stmt->default_rset_handler = _mysql_stmt_use_result;
+ stmt->default_rset_handler(stmt);
+ }
+ if (stmt->state > MYSQL_STMT_WAITING_USE_OR_STORE && stmt->state < MYSQL_STMT_FETCH_DONE && !stmt->result.data)
+ {
+ if (!stmt->cursor_exists)
+ do {
+ stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
+ } while(mysql_stmt_more_results(stmt));
+ stmt->state= MYSQL_STMT_PREPARED;
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ }
+
+ /* clear data, in case mysql_stmt_store_result was called */
+ if (stmt->result.data)
+ {
+ ma_free_root(&stmt->result.alloc, MYF(MY_KEEP_PREALLOC));
+ stmt->result_cursor= stmt->result.data= 0;
+ }
+ /* CONC-344: set row count to zero */
+ stmt->result.rows= 0;
+
+ request= (char *)ma_stmt_execute_generate_request(stmt, &request_len, 0);
+ if (!request)
+ return 1;
+
+ ret= stmt->mysql->methods->db_command(mysql,
+ stmt->array_size > 0 ? COM_STMT_BULK_EXECUTE : COM_STMT_EXECUTE,
+ request, request_len, 1, stmt);
+ if (request)
+ free(request);
+
+ if (ret)
+ {
+ UPDATE_STMT_ERROR(stmt);
+ return(1);
+ }
+
+ if (mysql->net.extension->multi_status > COM_MULTI_OFF ||
+ mysql->options.extension->skip_read_response)
+ return(0);
+
+ return(mthd_stmt_read_execute_response(stmt));
+}
+
+static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
+{
+ MYSQL *mysql= stmt->mysql;
+ my_bool ret= 0;
+
+ if (!stmt->mysql)
+ {
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ /* clear error */
+ if (flags & MADB_RESET_ERROR)
+ {
+ CLEAR_CLIENT_ERROR(stmt->mysql);
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+ }
+
+ if (stmt->stmt_id)
+ {
+ /* free buffered resultset, previously allocated
+ * by mysql_stmt_store_result
+ */
+ if (flags & MADB_RESET_STORED &&
+ stmt->result_cursor)
+ {
+ ma_free_root(&stmt->result.alloc, MYF(MY_KEEP_PREALLOC));
+ stmt->result.data= NULL;
+ stmt->result.rows= 0;
+ stmt->result_cursor= NULL;
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ stmt->state= MYSQL_STMT_FETCH_DONE;
+ }
+
+ /* if there is a pending result set, we will flush it */
+ if (flags & MADB_RESET_BUFFER)
+ {
+ if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
+ {
+ stmt->default_rset_handler(stmt);
+ stmt->state = MYSQL_STMT_USER_FETCHING;
+ }
+
+ if (stmt->mysql->status!= MYSQL_STATUS_READY && stmt->field_count)
+ {
+ mysql->methods->db_stmt_flush_unbuffered(stmt);
+ mysql->status= MYSQL_STATUS_READY;
+ }
+ }
+
+ if (flags & MADB_RESET_SERVER)
+ {
+ /* reset statement on server side */
+ if (stmt->mysql && stmt->mysql->status == MYSQL_STATUS_READY &&
+ stmt->mysql->net.pvio)
+ {
+ unsigned char cmd_buf[STMT_ID_LENGTH];
+ int4store(cmd_buf, stmt->stmt_id);
+ if ((ret= stmt->mysql->methods->db_command(mysql,COM_STMT_RESET, (char *)cmd_buf,
+ sizeof(cmd_buf), 0, stmt)))
+ {
+ UPDATE_STMT_ERROR(stmt);
+ return(ret);
+ }
+ }
+ }
+
+ if (flags & MADB_RESET_LONGDATA)
+ {
+ if (stmt->params)
+ {
+ ulonglong i;
+ for (i=0; i < stmt->param_count; i++)
+ if (stmt->params[i].long_data_used)
+ stmt->params[i].long_data_used= 0;
+ }
+ }
+
+ }
+ return(ret);
+}
+
+static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close)
+{
+ MYSQL *mysql= stmt->mysql;
+ my_bool ret= 1;
+ unsigned int flags= MADB_RESET_LONGDATA | MADB_RESET_BUFFER | MADB_RESET_ERROR;
+ unsigned int last_status;
+
+ if (!mysql)
+ {
+ /* connection could be invalid, e.g. after mysql_stmt_close or failed reconnect
+ attempt (see bug CONC-97) */
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ last_status= mysql->server_status;
+
+ if (stmt->state >= MYSQL_STMT_USER_FETCHING &&
+ stmt->fetch_row_func == stmt_unbuffered_fetch)
+ flags|= MADB_RESET_BUFFER;
+
+ ret= madb_reset_stmt(stmt, flags);
+
+ if (stmt->stmt_id)
+ {
+ if ((stmt->state > MYSQL_STMT_EXECUTED &&
+ stmt->mysql->status != MYSQL_STATUS_READY) ||
+ stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST)
+ {
+ /* flush any pending (multiple) result sets */
+ if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
+ {
+ stmt->default_rset_handler(stmt);
+ stmt->state = MYSQL_STMT_USER_FETCHING;
+ }
+
+ if (stmt->field_count)
+ {
+ while (mysql_stmt_next_result(stmt) == 0);
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ }
+ }
+ if (!is_close)
+ ret= madb_reset_stmt(stmt, MADB_RESET_SERVER);
+ stmt->state= MYSQL_STMT_PREPARED;
+ }
+ else
+ stmt->state= MYSQL_STMT_INITTED;
+
+ stmt->upsert_status.affected_rows= mysql->affected_rows;
+ stmt->upsert_status.last_insert_id= mysql->insert_id;
+ stmt->upsert_status.server_status= mysql->server_status;
+ ma_status_callback(stmt->mysql, last_status);
+ stmt->upsert_status.warning_count= mysql->warning_count;
+ mysql->status= MYSQL_STATUS_READY;
+
+ return(ret);
+}
+
+MYSQL_RES * STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt)
+{
+ MYSQL_RES *res;
+
+ if (!stmt->field_count)
+ return(NULL);
+
+ /* allocate result set structure and copy stmt information */
+ if (!(res= (MYSQL_RES *)calloc(1, sizeof(MYSQL_RES))))
+ {
+ stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return(NULL);
+ }
+
+ res->eof= 1;
+ res->fields= stmt->fields;
+ res->field_count= stmt->field_count;
+ return(res);
+}
+
+my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
+{
+ if (stmt->stmt_id > 0 &&
+ stmt->stmt_id != (unsigned long) -1)
+ return mysql_stmt_internal_reset(stmt, 0);
+ return 0;
+}
+
+const char * STDCALL mysql_stmt_sqlstate(MYSQL_STMT *stmt)
+{
+ return stmt->sqlstate;
+}
+
+MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_tell(MYSQL_STMT *stmt)
+{
+ return(stmt->result_cursor);
+}
+
+unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT *stmt)
+{
+ return stmt->param_count;
+}
+
+MYSQL_ROW_OFFSET STDCALL mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET new_row)
+{
+ MYSQL_ROW_OFFSET old_row; /* for returning old position */
+
+ old_row= stmt->result_cursor;
+ stmt->result_cursor= new_row;
+
+ return(old_row);
+}
+
+my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
+ const char *data, unsigned long length)
+{
+ CLEAR_CLIENT_ERROR(stmt->mysql);
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+
+ if (stmt->state < MYSQL_STMT_PREPARED || !stmt->params)
+ {
+ stmt_set_error(stmt, CR_NO_PREPARE_STMT, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (param_number >= stmt->param_count)
+ {
+ stmt_set_error(stmt, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (length || !stmt->params[param_number].long_data_used)
+ {
+ int ret;
+ size_t packet_len= STMT_ID_LENGTH + 2 + length;
+ uchar *cmd_buff= (uchar *)calloc(1, packet_len);
+ int4store(cmd_buff, stmt->stmt_id);
+ int2store(cmd_buff + STMT_ID_LENGTH, param_number);
+ memcpy(cmd_buff + STMT_ID_LENGTH + 2, data, length);
+ stmt->params[param_number].long_data_used= 1;
+ ret= stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_SEND_LONG_DATA,
+ (char *)cmd_buff, packet_len, 1, stmt);
+ if (ret)
+ UPDATE_STMT_ERROR(stmt);
+ free(cmd_buff);
+ return(ret);
+ }
+ return(0);
+}
+
+unsigned long long STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
+{
+ return stmt->upsert_status.last_insert_id;
+}
+
+unsigned long long STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
+{
+ return stmt->result.rows;
+}
+
+MYSQL_RES* STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt __attribute__((unused)))
+{
+ /* server doesn't deliver any information yet,
+ so we just return NULL
+ */
+ return(NULL);
+}
+
+my_bool STDCALL mysql_stmt_more_results(MYSQL_STMT *stmt)
+{
+ /* MDEV 4604: Server doesn't set MORE_RESULT flag for
+ OutParam result set, so we need to check
+ for SERVER_MORE_RESULTS_EXIST and for
+ SERVER_PS_OUT_PARAMS)
+ */
+ return (stmt &&
+ stmt->mysql &&
+ ((stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST) ||
+ (stmt->mysql->server_status & SERVER_PS_OUT_PARAMS)));
+}
+
+int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
+{
+ int rc= 0;
+
+ if (!stmt->mysql)
+ {
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (stmt->state < MYSQL_STMT_EXECUTED)
+ {
+ SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return(1);
+ }
+
+ if (!mysql_stmt_more_results(stmt))
+ return(-1);
+
+ if (stmt->state > MYSQL_STMT_EXECUTED &&
+ stmt->state < MYSQL_STMT_FETCH_DONE)
+ madb_reset_stmt(stmt, MADB_RESET_ERROR | MADB_RESET_BUFFER | MADB_RESET_LONGDATA);
+ stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE;
+
+ if (mysql_next_result(stmt->mysql))
+ {
+ stmt->state= MYSQL_STMT_FETCH_DONE;
+ stmt_set_error(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate,
+ stmt->mysql->net.last_error);
+ return(1);
+ }
+
+ if (stmt->mysql->status == MYSQL_STATUS_GET_RESULT)
+ stmt->mysql->status= MYSQL_STATUS_STMT_RESULT;
+
+ if (stmt->mysql->field_count)
+ rc= madb_alloc_stmt_fields(stmt);
+ else
+ {
+ unsigned int last_status= stmt->mysql->server_status;
+ stmt->upsert_status.affected_rows= stmt->mysql->affected_rows;
+ stmt->upsert_status.last_insert_id= stmt->mysql->insert_id;
+ stmt->upsert_status.server_status= stmt->mysql->server_status;
+ ma_status_callback(stmt->mysql, last_status);
+ stmt->upsert_status.warning_count= stmt->mysql->warning_count;
+ }
+
+ stmt->field_count= stmt->mysql->field_count;
+ stmt->result.rows= 0;
+
+ return(rc);
+}
+
+int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt,
+ const char *stmt_str,
+ size_t length)
+{
+ MYSQL *mysql;
+ my_bool emulate_cmd;
+ my_bool clear_result= 0;
+
+ if (!stmt)
+ return 1;
+
+ mysql= stmt->mysql;
+ if (!mysql)
+ {
+ stmt_set_error(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+
+ emulate_cmd= !(!(stmt->mysql->server_capabilities & CLIENT_MYSQL) &&
+ (stmt->mysql->extension->mariadb_server_capabilities &
+ (MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32))) || mysql->net.compress;
+
+ /* Server versions < 10.2 don't support execute_direct, so we need to
+ emulate it */
+ if (emulate_cmd)
+ {
+ int rc;
+
+ /* avoid sending close + prepare in 2 packets */
+ if ((rc= mysql_stmt_prepare(stmt, stmt_str, (unsigned long)length)))
+ return rc;
+ return mysql_stmt_execute(stmt);
+ }
+
+ if (ma_multi_command(mysql, COM_MULTI_ENABLED))
+ {
+ stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
+ return 1;
+ }
+
+ if (length == (size_t) -1)
+ length= strlen(stmt_str);
+
+ /* clear flags */
+ CLEAR_CLIENT_STMT_ERROR(stmt);
+ CLEAR_CLIENT_ERROR(stmt->mysql);
+ stmt->upsert_status.affected_rows= mysql->affected_rows= (unsigned long long) ~0;
+
+ /* check if we have to clear results */
+ if (stmt->state > MYSQL_STMT_INITTED)
+ {
+ /* We need to semi-close the prepared statement:
+ reset stmt and free all buffers and close the statement
+ on server side. Statement handle will get a new stmt_id */
+ char stmt_id[STMT_ID_LENGTH];
+
+ if (mysql_stmt_internal_reset(stmt, 1))
+ goto fail;
+
+ ma_free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
+ ma_free_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root, MYF(0));
+ stmt->field_count= 0;
+ stmt->param_count= 0;
+ stmt->params= 0;
+
+ int4store(stmt_id, stmt->stmt_id);
+ if (mysql->methods->db_command(mysql, COM_STMT_CLOSE, stmt_id,
+ sizeof(stmt_id), 1, stmt))
+ goto fail;
+ }
+ stmt->stmt_id= -1;
+ if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, stmt_str, length, 1, stmt))
+ goto fail;
+
+ /* in case prepare fails, we need to clear the result package from execute, which
+ is always an error packet (invalid statement id) */
+ clear_result= 1;
+
+ stmt->state= MYSQL_STMT_PREPARED;
+ /* Since we can't determine stmt_id here, we need to set it to -1, so server will know that the
+ * execute command belongs to previous prepare */
+ stmt->stmt_id= -1;
+ if (mysql_stmt_execute(stmt))
+ goto fail;
+
+ /* flush multi buffer */
+ if (ma_multi_command(mysql, COM_MULTI_END))
+ goto fail;
+
+ if (!mysql->options.extension->skip_read_response)
+ {
+ /* read prepare response */
+ if (mysql->methods->db_read_prepare_response &&
+ mysql->methods->db_read_prepare_response(stmt))
+ goto fail;
+
+ clear_result= 0;
+
+ /* read execute response packet */
+ return mthd_stmt_read_execute_response(stmt);
+ }
+fail:
+ /* check if we need to set error message */
+ if (!mysql_stmt_errno(stmt))
+ UPDATE_STMT_ERROR(stmt);
+ if (clear_result) {
+ do {
+ stmt->mysql->methods->db_stmt_flush_unbuffered(stmt);
+ } while(mysql_stmt_more_results(stmt));
+ }
+
+ /* CONC-633: If prepare returned an error, we ignore error from execute */
+ if (mysql_stmt_errno(stmt))
+ {
+ my_set_error(mysql, mysql_stmt_errno(stmt), mysql_stmt_sqlstate(stmt),
+ mysql_stmt_error(stmt));
+ stmt->state= MYSQL_STMT_INITTED;
+ }
+ return 1;
+}
+
+MYSQL_FIELD * STDCALL mariadb_stmt_fetch_fields(MYSQL_STMT *stmt)
+{
+ if (stmt)
+ return stmt->fields;
+ return NULL;
+}
diff --git a/libmariadb/libmariadb/secure/gnutls.c b/libmariadb/libmariadb/secure/gnutls.c
new file mode 100644
index 00000000..4782be62
--- /dev/null
+++ b/libmariadb/libmariadb/secure/gnutls.c
@@ -0,0 +1,1438 @@
+/************************************************************************************
+ Copyright (C) 2014 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ *************************************************************************************/
+#ifdef HAVE_GNUTLS
+
+#include <ma_global.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+#include <ma_pvio.h>
+#include <errmsg.h>
+#include <ma_pthread.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <ma_tls.h>
+#include <mariadb_async.h>
+#include <ma_context.h>
+
+pthread_mutex_t LOCK_gnutls_config;
+
+extern my_bool ma_tls_initialized;
+extern unsigned int mariadb_deinitialize_ssl;
+
+enum ma_pem_type {
+ MA_TLS_PEM_CERT= 0,
+ MA_TLS_PEM_KEY,
+ MA_TLS_PEM_CA,
+ MA_TLS_PEM_CRL
+};
+
+static int my_verify_callback(gnutls_session_t ssl);
+
+char tls_library_version[TLS_VERSION_LENGTH];
+
+struct st_cipher_map {
+ unsigned char sid[2];
+ const char *iana_name;
+ const char *openssl_name;
+ const char *gnutls_name;
+};
+
+const struct st_cipher_map tls_ciphers[]=
+{
+ { {0x00, 0x01},
+ "TLS_RSA_WITH_NULL_MD5",
+ NULL,
+ "TLS_RSA_NULL_MD5"},
+ { {0x00, 0x02},
+ "TLS_RSA_WITH_NULL_SHA",
+ NULL,
+ "TLS_RSA_NULL_SHA1"},
+ { {0x00, 0x3B},
+ "TLS_RSA_WITH_NULL_SHA256",
+ NULL,
+ "TLS_RSA_NULL_SHA256"},
+ { {0x00, 0x05},
+ "TLS_RSA_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_RSA_ARCFOUR_128_SHA1"},
+ { {0x00, 0x04},
+ "TLS_RSA_WITH_RC4_128_MD5",
+ NULL,
+ "TLS_RSA_ARCFOUR_128_MD5"},
+ { {0x00, 0x0A},
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+ "DES-CBC3-SHA",
+ "TLS_RSA_3DES_EDE_CBC_SHA1"},
+ { {0x00, 0x2F},
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "AES128-SHA",
+ "TLS_RSA_AES_128_CBC_SHA1"},
+ { {0x00, 0x35},
+ "TLS_RSA_WITH_AES_256_CBC_SHA",
+ "AES256-SHA",
+ "TLS_RSA_AES_256_CBC_SHA1"},
+ { {0x00, 0xBA},
+ "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+ "CAMELLIA128-SHA256",
+ "TLS_RSA_CAMELLIA_128_CBC_SHA256"},
+ { {0x00, 0xC0},
+ "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
+ NULL,
+ "TLS_RSA_CAMELLIA_256_CBC_SHA256"},
+ { {0x00, 0x41},
+ "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
+ "CAMELLIA128-SHA",
+ "TLS_RSA_CAMELLIA_128_CBC_SHA1"},
+ { {0x00, 0x84},
+ "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
+ "CAMELLIA256-SHA",
+ "TLS_RSA_CAMELLIA_256_CBC_SHA1"},
+ { {0x00, 0x3C},
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ "AES128-SHA256",
+ "TLS_RSA_AES_128_CBC_SHA256"},
+ { {0x00, 0x3D},
+ "TLS_RSA_WITH_AES_256_CBC_SHA256",
+ "AES256-SHA256",
+ "TLS_RSA_AES_256_CBC_SHA256"},
+ { {0x00, 0x9C},
+ "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "AES128-GCM-SHA256",
+ "TLS_RSA_AES_128_GCM_SHA256"},
+ { {0x00, 0x9D},
+ "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ "AES256-GCM-SHA384",
+ "TLS_RSA_AES_256_GCM_SHA384"},
+ { {0xC0, 0x7A},
+ "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_RSA_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x7B},
+ "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_RSA_CAMELLIA_256_GCM_SHA384"},
+ { {0xC0, 0x9C},
+ "TLS_RSA_WITH_AES_128_CCM",
+ NULL,
+ "TLS_RSA_AES_128_CCM"},
+ { {0xC0, 0x9D},
+ "TLS_RSA_WITH_AES_256_CCM",
+ NULL,
+ "TLS_RSA_AES_256_CCM"},
+ { {0xC0, 0xA0},
+ "TLS_RSA_WITH_AES_128_CCM_8",
+ NULL,
+ "TLS_RSA_AES_128_CCM_8"},
+ { {0xC0, 0xA1},
+ "TLS_RSA_WITH_AES_256_CCM_8",
+ NULL,
+ "TLS_RSA_AES_256_CCM_8"},
+ { {0x00, 0x66},
+ "TLS_DHE_DSS_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_DHE_DSS_ARCFOUR_128_SHA1"},
+ { {0x00, 0x13},
+ "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ NULL,
+ "TLS_DHE_DSS_3DES_EDE_CBC_SHA1"},
+ { {0x00, 0x32},
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ NULL,
+ "TLS_DHE_DSS_AES_128_CBC_SHA1"},
+ { {0x00, 0x38},
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+ NULL,
+ "TLS_DHE_DSS_AES_256_CBC_SHA1"},
+ { {0x00, 0xBD},
+ "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA256"},
+ { {0x00, 0xC3},
+ "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
+ NULL,
+ "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA256"},
+ { {0x00, 0x44},
+ "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",
+ NULL,
+ "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA1"},
+ { {0x00, 0x87},
+ "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",
+ NULL,
+ "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA1"},
+ { {0x00, 0x40},
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+ NULL,
+ "TLS_DHE_DSS_AES_128_CBC_SHA256"},
+ { {0x00, 0x6A},
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+ NULL,
+ "TLS_DHE_DSS_AES_256_CBC_SHA256"},
+ { {0x00, 0xA2},
+ "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+ NULL,
+ "TLS_DHE_DSS_AES_128_GCM_SHA256"},
+ { {0x00, 0xA3},
+ "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+ NULL,
+ "TLS_DHE_DSS_AES_256_GCM_SHA384"},
+ { {0xC0, 0x80},
+ "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_DHE_DSS_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x81},
+ "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_DHE_DSS_CAMELLIA_256_GCM_SHA384"},
+ { {0x00, 0x16},
+ "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "EDH-RSA-DES-CBC3-SHA",
+ "TLS_DHE_RSA_3DES_EDE_CBC_SHA1"},
+ { {0x00, 0x33},
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "DHE-RSA-AES128-SHA",
+ "TLS_DHE_RSA_AES_128_CBC_SHA1"},
+ { {0x00, 0x39},
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+ "DHE-RSA-AES256-SHA",
+ "TLS_DHE_RSA_AES_256_CBC_SHA1"},
+ { {0x00, 0xBE},
+ "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA256"},
+ { {0x00, 0xC4},
+ "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
+ NULL,
+ "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA256"},
+ { {0x00, 0x45},
+ "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
+ "DHE-RSA-CAMELLIA128-SHA",
+ "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA1"},
+ { {0x00, 0x88},
+ "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
+ "DHE-RSA-CAMELLIA256-SHA",
+ "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA1"},
+ { {0x00, 0x67},
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ "DHE-RSA-AES128-SHA256",
+ "TLS_DHE_RSA_AES_128_CBC_SHA256"},
+ { {0x00, 0x6B},
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ "DHE-RSA-AES256-SHA256",
+ "TLS_DHE_RSA_AES_256_CBC_SHA256"},
+ { {0x00, 0x9E},
+ "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+ "DHE-RSA-AES128-GCM-SHA256",
+ "TLS_DHE_RSA_AES_128_GCM_SHA256"},
+ { {0x00, 0x9F},
+ "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+ "DHE-RSA-AES256-GCM-SHA384",
+ "TLS_DHE_RSA_AES_256_GCM_SHA384"},
+ { {0xC0, 0x7C},
+ "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_DHE_RSA_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x7D},
+ "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_DHE_RSA_CAMELLIA_256_GCM_SHA384"},
+ { {0xCC, 0xAA},
+ "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ "DHE-RSA-CHACHA20-POLY1305",
+ "TLS_DHE_RSA_CHACHA20_POLY1305"},
+ { {0xC0, 0x9E},
+ "TLS_DHE_RSA_WITH_AES_128_CCM",
+ NULL,
+ "TLS_DHE_RSA_AES_128_CCM"},
+ { {0xC0, 0x9F},
+ "TLS_DHE_RSA_WITH_AES_256_CCM",
+ NULL,
+ "TLS_DHE_RSA_AES_256_CCM"},
+ { {0xC0, 0xA2},
+ "TLS_DHE_RSA_WITH_AES_128_CCM_8",
+ NULL,
+ "TLS_DHE_RSA_AES_128_CCM_8"},
+ { {0xC0, 0xA3},
+ "TLS_DHE_RSA_WITH_AES_256_CCM_8",
+ NULL,
+ "TLS_DHE_RSA_AES_256_CCM_8"},
+ { {0xC0, 0x10},
+ "TLS_ECDHE_RSA_WITH_",
+ NULL,
+ "TLS_ECDHE_RSA_NULL_SHA1"},
+ { {0xC0, 0x12},
+ "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "ECDHE-RSA-DES-CBC3-SHA",
+ "TLS_ECDHE_RSA_3DES_EDE_CBC_SHA1"},
+ { {0xC0, 0x13},
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ "ECDHE-RSA-AES128-SHA",
+ "TLS_ECDHE_RSA_AES_128_CBC_SHA1"},
+ { {0xC0, 0x14},
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ "ECDHE-RSA-AES256-SHA",
+ "TLS_ECDHE_RSA_AES_256_CBC_SHA1"},
+ { {0xC0, 0x28},
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+ "ECDHE-RSA-AES256-SHA384",
+ "TLS_ECDHE_RSA_AES_256_CBC_SHA384"},
+ { {0xC0, 0x11},
+ "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_ECDHE_RSA_ARCFOUR_128_SHA1"},
+ { {0xC0, 0x76},
+ "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_ECDHE_RSA_CAMELLIA_128_CBC_SHA256"},
+ { {0xC0, 0x77},
+ "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
+ NULL,
+ "TLS_ECDHE_RSA_CAMELLIA_256_CBC_SHA384"},
+ { {0xC0, 0x06},
+ "TLS_ECDHE_ECDSA_WITH_",
+ NULL,
+ "TLS_ECDHE_ECDSA_NULL_SHA1"},
+ { {0xC0, 0x08},
+ "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "ECDHE-ECDSA-DES-CBC3-SHA",
+ "TLS_ECDHE_ECDSA_3DES_EDE_CBC_SHA1"},
+ { {0xC0, 0x09},
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "ECDHE-ECDSA-AES128-SHA",
+ "TLS_ECDHE_ECDSA_AES_128_CBC_SHA1"},
+ { {0xC0, 0x0A},
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ "ECDHE-ECDSA-AES256-SHA",
+ "TLS_ECDHE_ECDSA_AES_256_CBC_SHA1"},
+ { {0xC0, 0x07},
+ "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_ECDHE_ECDSA_ARCFOUR_128_SHA1"},
+ { {0xC0, 0x72},
+ "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_ECDHE_ECDSA_CAMELLIA_128_CBC_SHA256"},
+ { {0xC0, 0x73},
+ "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
+ NULL,
+ "TLS_ECDHE_ECDSA_CAMELLIA_256_CBC_SHA384"},
+ { {0xC0, 0x23},
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ "ECDHE-ECDSA-AES128-SHA256",
+ "TLS_ECDHE_ECDSA_AES_128_CBC_SHA256"},
+ { {0xC0, 0x27},
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+ "ECDHE-RSA-AES128-SHA256",
+ "TLS_ECDHE_RSA_AES_128_CBC_SHA256"},
+ { {0xC0, 0x86},
+ "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_ECDHE_ECDSA_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x87},
+ "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_ECDHE_ECDSA_CAMELLIA_256_GCM_SHA384"},
+ { {0xC0, 0x2B},
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ "ECDHE-ECDSA-AES128-GCM-SHA256",
+ "TLS_ECDHE_ECDSA_AES_128_GCM_SHA256"},
+ { {0xC0, 0x2C},
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ "ECDHE-ECDSA-AES256-GCM-SHA384",
+ "TLS_ECDHE_ECDSA_AES_256_GCM_SHA384"},
+ { {0xC0, 0x2F},
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "ECDHE-RSA-AES128-GCM-SHA256",
+ "TLS_ECDHE_RSA_AES_128_GCM_SHA256"},
+ { {0xC0, 0x30},
+ "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ "ECDHE-RSA-AES256-GCM-SHA384",
+ "TLS_ECDHE_RSA_AES_256_GCM_SHA384"},
+ { {0xC0, 0x24},
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+ "ECDHE-ECDSA-AES256-SHA384",
+ "TLS_ECDHE_ECDSA_AES_256_CBC_SHA384"},
+ { {0xC0, 0x8A},
+ "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_ECDHE_RSA_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x8B},
+ "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_ECDHE_RSA_CAMELLIA_256_GCM_SHA384"},
+ { {0xCC, 0xA8},
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ "ECDHE-RSA-CHACHA20-POLY1305",
+ "TLS_ECDHE_RSA_CHACHA20_POLY1305"},
+ { {0xCC, 0xA9},
+ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ "ECDHE-ECDSA-CHACHA20-POLY1305",
+ "TLS_ECDHE_ECDSA_CHACHA20_POLY1305"},
+ { {0xC0, 0xAC},
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
+ NULL,
+ "TLS_ECDHE_ECDSA_AES_128_CCM"},
+ { {0xC0, 0xAD},
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CCM",
+ NULL,
+ "TLS_ECDHE_ECDSA_AES_256_CCM"},
+ { {0xC0, 0xAE},
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",
+ NULL,
+ "TLS_ECDHE_ECDSA_AES_128_CCM_8"},
+ { {0xC0, 0xAF},
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",
+ NULL,
+ "TLS_ECDHE_ECDSA_AES_256_CCM_8"},
+ { {0xC0, 0x34},
+ "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",
+ "ECDHE-PSK-3DES-EDE-CBC-SHA",
+ "TLS_ECDHE_PSK_3DES_EDE_CBC_SHA1"},
+ { {0xC0, 0x35},
+ "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
+ "ECDHE-PSK-AES128-CBC-SHA",
+ "TLS_ECDHE_PSK_AES_128_CBC_SHA1"},
+ { {0xC0, 0x36},
+ "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
+ "ECDHE-PSK-AES256-CBC-SHA",
+ "TLS_ECDHE_PSK_AES_256_CBC_SHA1"},
+ { {0xC0, 0x37},
+ "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",
+ "ECDHE-PSK-AES128-CBC-SHA256",
+ "TLS_ECDHE_PSK_AES_128_CBC_SHA256"},
+ { {0xC0, 0x38},
+ "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",
+ "ECDHE-PSK-AES256-CBC-SHA384",
+ "TLS_ECDHE_PSK_AES_256_CBC_SHA384"},
+ { {0xC0, 0x33},
+ "TLS_ECDHE_PSK_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_ECDHE_PSK_ARCFOUR_128_SHA1"},
+ { {0xC0, 0x39},
+ "TLS_ECDHE_PSK_WITH_NULL_SHA",
+ NULL,
+ "TLS_ECDHE_PSK_NULL_SHA1"},
+ { {0xC0, 0x3A},
+ "TLS_ECDHE_PSK_WITH_NULL_SHA256",
+ NULL,
+ "TLS_ECDHE_PSK_NULL_SHA256"},
+ { {0xC0, 0x3B},
+ "TLS_ECDHE_PSK_WITH_NULL_SHA384",
+ NULL,
+ "TLS_ECDHE_PSK_NULL_SHA384"},
+ { {0xC0, 0x9A},
+ "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_ECDHE_PSK_CAMELLIA_128_CBC_SHA256"},
+ { {0xC0, 0x9B},
+ "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+ NULL,
+ "TLS_ECDHE_PSK_CAMELLIA_256_CBC_SHA384"},
+ { {0x00, 0x8A},
+ "TLS_PSK_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_PSK_ARCFOUR_128_SHA1"},
+ { {0x00, 0x8B},
+ "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
+ "PSK-3DES-EDE-CBC-SHA",
+ "TLS_PSK_3DES_EDE_CBC_SHA1"},
+ { {0x00, 0x8C},
+ "TLS_PSK_WITH_AES_128_CBC_SHA",
+ "PSK-AES128-CBC-SHA",
+ "TLS_PSK_AES_128_CBC_SHA1"},
+ { {0x00, 0x8D},
+ "TLS_PSK_WITH_AES_256_CBC_SHA",
+ "PSK-AES256-CBC-SHA",
+ "TLS_PSK_AES_256_CBC_SHA1"},
+ { {0x00, 0xAE},
+ "TLS_PSK_WITH_AES_128_CBC_SHA256",
+ "PSK-AES128-CBC-SHA256",
+ "TLS_PSK_AES_128_CBC_SHA256"},
+ { {0x00, 0xA9},
+ "TLS_PSK_WITH_AES_256_GCM_SHA384",
+ "PSK-AES256-GCM-SHA384",
+ "TLS_PSK_AES_256_GCM_SHA384"},
+ { {0xC0, 0x8E},
+ "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_PSK_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x8F},
+ "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_PSK_CAMELLIA_256_GCM_SHA384"},
+ { {0x00, 0xA8},
+ "TLS_PSK_WITH_AES_128_GCM_SHA256",
+ "PSK-AES128-GCM-SHA256",
+ "TLS_PSK_AES_128_GCM_SHA256"},
+ { {0x00, 0x2C},
+ "TLS_PSK_WITH_",
+ NULL,
+ "TLS_PSK_NULL_SHA1"},
+ { {0x00, 0xB0},
+ "TLS_PSK_WITH_",
+ NULL,
+ "TLS_PSK_NULL_SHA256"},
+ { {0xC0, 0x94},
+ "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_PSK_CAMELLIA_128_CBC_SHA256"},
+ { {0xC0, 0x95},
+ "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+ NULL,
+ "TLS_PSK_CAMELLIA_256_CBC_SHA384"},
+ { {0x00, 0xAF},
+ "TLS_PSK_WITH_AES_256_CBC_SHA384",
+ "PSK-AES256-CBC-SHA384",
+ "TLS_PSK_AES_256_CBC_SHA384"},
+ { {0x00, 0xB1},
+ "TLS_PSK_WITH_",
+ NULL,
+ "TLS_PSK_NULL_SHA384"},
+ { {0x00, 0x92},
+ "TLS_RSA_PSK_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_RSA_PSK_ARCFOUR_128_SHA1"},
+ { {0x00, 0x93},
+ "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",
+ "RSA-PSK-3DES-EDE-CBC-SHA",
+ "TLS_RSA_PSK_3DES_EDE_CBC_SHA1"},
+ { {0x00, 0x94},
+ "TLS_RSA_PSK_WITH_AES_128_CBC_SHA",
+ "RSA-PSK-AES128-CBC-SHA",
+ "TLS_RSA_PSK_AES_128_CBC_SHA1"},
+ { {0x00, 0x95},
+ "TLS_RSA_PSK_WITH_AES_256_CBC_SHA",
+ "RSA-PSK-AES256-CBC-SHA",
+ "TLS_RSA_PSK_AES_256_CBC_SHA1"},
+ { {0xC0, 0x92},
+ "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_RSA_PSK_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x93},
+ "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_RSA_PSK_CAMELLIA_256_GCM_SHA384"},
+ { {0x00, 0xAC},
+ "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",
+ "RSA-PSK-AES128-GCM-SHA256",
+ "TLS_RSA_PSK_AES_128_GCM_SHA256"},
+ { {0x00, 0xB6},
+ "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",
+ "RSA-PSK-AES128-CBC-SHA256",
+ "TLS_RSA_PSK_AES_128_CBC_SHA256"},
+ { {0x00, 0x2E},
+ "TLS_RSA_PSK_WITH_NULL_SHA",
+ NULL,
+ "TLS_RSA_PSK_NULL_SHA1"},
+ { {0x00, 0xB8},
+ "TLS_RSA_PSK_WITH_",
+ NULL,
+ "TLS_RSA_PSK_NULL_SHA256"},
+ { {0x00, 0xAD},
+ "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",
+ "RSA-PSK-AES256-GCM-SHA384",
+ "TLS_RSA_PSK_AES_256_GCM_SHA384"},
+ { {0x00, 0xB7},
+ "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",
+ "RSA-PSK-AES256-CBC-SHA384",
+ "TLS_RSA_PSK_AES_256_CBC_SHA384"},
+ { {0x00, 0xB9},
+ "TLS_RSA_PSK_WITH_",
+ NULL,
+ "TLS_RSA_PSK_NULL_SHA384"},
+ { {0xC0, 0x98},
+ "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_RSA_PSK_CAMELLIA_128_CBC_SHA256"},
+ { {0xC0, 0x99},
+ "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+ NULL,
+ "TLS_RSA_PSK_CAMELLIA_256_CBC_SHA384"},
+ { {0x00, 0x8E},
+ "TLS_DHE_PSK_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_DHE_PSK_ARCFOUR_128_SHA1"},
+ { {0x00, 0x8F},
+ "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",
+ "DHE-PSK-3DES-EDE-CBC-SHA",
+ "TLS_DHE_PSK_3DES_EDE_CBC_SHA1"},
+ { {0x00, 0x90},
+ "TLS_DHE_PSK_WITH_AES_128_CBC_SHA",
+ "DHE-PSK-AES128-CBC-SHA",
+ "TLS_DHE_PSK_AES_128_CBC_SHA1"},
+ { {0x00, 0x91},
+ "TLS_DHE_PSK_WITH_AES_256_CBC_SHA",
+ "DHE-PSK-AES256-CBC-SHA",
+ "TLS_DHE_PSK_AES_256_CBC_SHA1"},
+ { {0x00, 0xB2},
+ "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",
+ "DHE-PSK-AES128-CBC-SHA256",
+ "TLS_DHE_PSK_AES_128_CBC_SHA256"},
+ { {0x00, 0xAA},
+ "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",
+ "DHE-PSK-AES128-GCM-SHA256",
+ "TLS_DHE_PSK_AES_128_GCM_SHA256"},
+ { {0x00, 0x2D},
+ "TLS_DHE_PSK_WITH_",
+ NULL,
+ "TLS_DHE_PSK_NULL_SHA1"},
+ { {0x00, 0xB4},
+ "TLS_DHE_PSK_WITH_",
+ NULL,
+ "TLS_DHE_PSK_NULL_SHA256"},
+ { {0x00, 0xB5},
+ "TLS_DHE_PSK_WITH_",
+ NULL,
+ "TLS_DHE_PSK_NULL_SHA384"},
+ { {0x00, 0xB3},
+ "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",
+ "DHE-PSK-AES256-CBC-SHA384",
+ "TLS_DHE_PSK_AES_256_CBC_SHA384"},
+ { {0x00, 0xAB},
+ "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",
+ "DHE-PSK-AES256-GCM-SHA384",
+ "TLS_DHE_PSK_AES_256_GCM_SHA384"},
+ { {0xC0, 0x96},
+ "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_DHE_PSK_CAMELLIA_128_CBC_SHA256"},
+ { {0xC0, 0x97},
+ "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384",
+ NULL,
+ "TLS_DHE_PSK_CAMELLIA_256_CBC_SHA384"},
+ { {0xC0, 0x90},
+ "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_DHE_PSK_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x91},
+ "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_DHE_PSK_CAMELLIA_256_GCM_SHA384"},
+ { {0xC0, 0xA4},
+ "TLS_PSK_WITH_AES_128_CCM",
+ NULL,
+ "TLS_PSK_AES_128_CCM"},
+ { {0xC0, 0xA5},
+ "TLS_PSK_WITH_AES_256_CCM",
+ NULL,
+ "TLS_PSK_AES_256_CCM"},
+ { {0xC0, 0xA6},
+ "TLS_DHE_PSK_WITH_AES_128_CCM",
+ NULL,
+ "TLS_DHE_PSK_AES_128_CCM"},
+ { {0xC0, 0xA7},
+ "TLS_DHE_PSK_WITH_AES_256_CCM",
+ NULL,
+ "TLS_DHE_PSK_AES_256_CCM"},
+ { {0xC0, 0xA8},
+ "TLS_PSK_WITH_AES_128_CCM_8",
+ NULL,
+ "TLS_PSK_AES_128_CCM_8"},
+ { {0xC0, 0xA9},
+ "TLS_PSK_WITH_AES_256_CCM_8",
+ NULL,
+ "TLS_PSK_AES_256_CCM_8"},
+ { {0xC0, 0xAA},
+ "TLS_PSK_DHE_WITH_AES_128_CCM_8",
+ NULL,
+ "TLS_DHE_PSK_AES_128_CCM_8"},
+ { {0xC0, 0xAB},
+ "TLS_PSK_DHE_WITH_AES_256_CCM_8",
+ NULL,
+ "TLS_DHE_PSK_AES_256_CCM_8"},
+ { {0xCC, 0xAD},
+ "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "DHE-PSK-CHACHA20-POLY1305",
+ "TLS_DHE_PSK_CHACHA20_POLY1305"},
+ { {0xCC, 0xAC},
+ "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "ECDHE-PSK-CHACHA20-POLY1305",
+ "TLS_ECDHE_PSK_CHACHA20_POLY1305"},
+ { {0xCC, 0xAE},
+ "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "RSA-PSK-CHACHA20-POLY1305",
+ "TLS_RSA_PSK_CHACHA20_POLY1305"},
+ { {0xCC, 0xAB},
+ "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "PSK-CHACHA20-POLY1305",
+ "TLS_PSK_CHACHA20_POLY1305"},
+ { {0x00, 0x18},
+ "TLS_DH_anon_WITH_RC4_128_MD5",
+ NULL,
+ "TLS_DH_ANON_ARCFOUR_128_MD5"},
+ { {0x00, 0x1B},
+ "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",
+ NULL,
+ "TLS_DH_ANON_3DES_EDE_CBC_SHA1"},
+ { {0x00, 0x34},
+ "TLS_DH_anon_WITH_AES_128_CBC_SHA",
+ NULL,
+ "TLS_DH_ANON_AES_128_CBC_SHA1"},
+ { {0x00, 0x3A},
+ "TLS_DH_anon_WITH_AES_256_CBC_SHA",
+ NULL,
+ "TLS_DH_ANON_AES_256_CBC_SHA1"},
+ { {0x00, 0xBF},
+ "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",
+ NULL,
+ "TLS_DH_ANON_CAMELLIA_128_CBC_SHA256"},
+ { {0x00, 0xC5},
+ "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",
+ NULL,
+ "TLS_DH_ANON_CAMELLIA_256_CBC_SHA256"},
+ { {0x00, 0x46},
+ "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",
+ NULL,
+ "TLS_DH_ANON_CAMELLIA_128_CBC_SHA1"},
+ { {0x00, 0x89},
+ "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
+ NULL,
+ "TLS_DH_ANON_CAMELLIA_256_CBC_SHA1"},
+ { {0x00, 0x6C},
+ "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
+ NULL,
+ "TLS_DH_ANON_AES_128_CBC_SHA256"},
+ { {0x00, 0x6D},
+ "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
+ NULL,
+ "TLS_DH_ANON_AES_256_CBC_SHA256"},
+ { {0x00, 0xA6},
+ "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
+ NULL,
+ "TLS_DH_ANON_AES_128_GCM_SHA256"},
+ { {0x00, 0xA7},
+ "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
+ NULL,
+ "TLS_DH_ANON_AES_256_GCM_SHA384"},
+ { {0xC0, 0x84},
+ "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256",
+ NULL,
+ "TLS_DH_ANON_CAMELLIA_128_GCM_SHA256"},
+ { {0xC0, 0x85},
+ "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384",
+ NULL,
+ "TLS_DH_ANON_CAMELLIA_256_GCM_SHA384"},
+ { {0xC0, 0x15},
+ "TLS_ECDH_anon_WITH_",
+ NULL,
+ "TLS_ECDH_ANON_NULL_SHA1"},
+ { {0xC0, 0x17},
+ "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+ NULL,
+ "TLS_ECDH_ANON_3DES_EDE_CBC_SHA1"},
+ { {0xC0, 0x18},
+ "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
+ NULL,
+ "TLS_ECDH_ANON_AES_128_CBC_SHA1"},
+ { {0xC0, 0x19},
+ "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
+ NULL,
+ "TLS_ECDH_ANON_AES_256_CBC_SHA1"},
+ { {0xC0, 0x16},
+ "TLS_ECDH_anon_WITH_RC4_128_SHA",
+ NULL,
+ "TLS_ECDH_ANON_ARCFOUR_128_SHA1"},
+ { {0xC0, 0x1A},
+ "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",
+ "SRP-3DES-EDE-CBC-SHA",
+ "TLS_SRP_SHA_3DES_EDE_CBC_SHA1"},
+ { {0xC0, 0x1D},
+ "TLS_SRP_SHA_WITH_AES_128_CBC_SHA",
+ "SRP-AES-128-CBC-SHA",
+ "TLS_SRP_SHA_AES_128_CBC_SHA1"},
+ { {0xC0, 0x20},
+ "TLS_SRP_SHA_WITH_AES_256_CBC_SHA",
+ "SRP-AES-256-CBC-SHA",
+ "TLS_SRP_SHA_AES_256_CBC_SHA1"},
+ { {0xC0, 0x1C},
+ "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",
+ NULL,
+ "TLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1"},
+ { {0xC0, 0x1B},
+ "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",
+ "SRP-RSA-3DES-EDE-CBC-SHA",
+ "TLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1"},
+ { {0xC0, 0x1F},
+ "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",
+ NULL,
+ "TLS_SRP_SHA_DSS_AES_128_CBC_SHA1"},
+ { {0xC0, 0x1E},
+ "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",
+ "SRP-RSA-AES-128-CBC-SHA",
+ "TLS_SRP_SHA_RSA_AES_128_CBC_SHA1"},
+ { {0xC0, 0x22},
+ "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",
+ NULL,
+ "TLS_SRP_SHA_DSS_AES_256_CBC_SHA1"},
+ { {0xC0, 0x21},
+ "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",
+ "SRP-RSA-AES-256-CBC-SHA",
+ "TLS_SRP_SHA_RSA_AES_256_CBC_SHA1"},
+ { {0x00, 0x00},
+ NULL,
+ NULL,
+ NULL}
+};
+
+/* map the gnutls cipher suite (defined by key exchange algorithm, cipher
+ and mac algorithm) to the corresponding OpenSSL cipher name */
+static const char *openssl_cipher_name(gnutls_kx_algorithm_t kx,
+ gnutls_cipher_algorithm_t cipher,
+ gnutls_mac_algorithm_t mac)
+{
+ unsigned int i=0;
+ const char *name= 0;
+ unsigned char sid[2];
+ gnutls_kx_algorithm_t lkx;
+ gnutls_cipher_algorithm_t lcipher;
+ gnutls_mac_algorithm_t lmac;
+
+ while ((name= gnutls_cipher_suite_info(i++, (unsigned char *)&sid, &lkx, &lcipher, &lmac, NULL)))
+ {
+ if (lkx == kx &&
+ lcipher == cipher &&
+ lmac == mac)
+ {
+ i=0;
+ while (tls_ciphers[i].iana_name)
+ {
+ if (!memcmp(tls_ciphers[i].sid, &sid, 2))
+ {
+ if (tls_ciphers[i].openssl_name)
+ return tls_ciphers[i].openssl_name;
+ if (tls_ciphers[i].gnutls_name)
+ return tls_ciphers[i].gnutls_name;
+ return tls_ciphers[i].iana_name;
+ }
+ i++;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* get priority string for a given openssl cipher name */
+static char *get_priority(const char *cipher_name, char *priority, size_t len)
+{
+ unsigned int i= 0;
+ while (tls_ciphers[i].iana_name)
+ {
+ if (strcmp(tls_ciphers[i].iana_name, cipher_name) == 0 ||
+ (tls_ciphers[i].openssl_name &&
+ strcmp(tls_ciphers[i].openssl_name, cipher_name) == 0) ||
+ (tls_ciphers[i].gnutls_name &&
+ strcmp(tls_ciphers[i].gnutls_name, cipher_name) == 0))
+ {
+ const char *name;
+ gnutls_kx_algorithm_t kx;
+ gnutls_cipher_algorithm_t cipher;
+ gnutls_mac_algorithm_t mac;
+ gnutls_protocol_t min_version;
+ unsigned j= 0;
+
+ if (!tls_ciphers[i].gnutls_name)
+ return NULL;
+
+ while ((name= gnutls_cipher_suite_info(j++, NULL, &kx, &cipher,
+ &mac, &min_version)))
+ {
+ if (!strcmp(name, tls_ciphers[i].gnutls_name))
+ {
+ snprintf(priority, len - 1, ":+%s:+%s:+%s",
+ gnutls_cipher_get_name(cipher),
+ gnutls_mac_get_name(mac),
+ gnutls_kx_get_name(kx));
+ return priority;
+ }
+ }
+ return NULL;
+ }
+ i++;
+ }
+ return NULL;
+}
+
+#define MAX_SSL_ERR_LEN 100
+
+static void ma_tls_set_error(MYSQL *mysql, void *ssl, int ssl_errno)
+{
+ char ssl_error[MAX_SSL_ERR_LEN];
+ const char *ssl_error_reason;
+ MARIADB_PVIO *pvio= mysql->net.pvio;
+ int save_errno= errno;
+
+ /* give a more descriptive error message for alerts */
+ if (ssl_errno == GNUTLS_E_FATAL_ALERT_RECEIVED)
+ {
+ gnutls_alert_description_t alert_desc;
+ const char *alert_name;
+ alert_desc= gnutls_alert_get((gnutls_session_t)ssl);
+ alert_name= gnutls_alert_get_name(alert_desc);
+ snprintf(ssl_error, MAX_SSL_ERR_LEN, "fatal alert received: %s",
+ alert_name);
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, ssl_error);
+ return;
+ }
+
+ if (ssl_errno && (ssl_error_reason= gnutls_strerror(ssl_errno)))
+ {
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0,
+ ssl_error_reason);
+ return;
+ }
+
+ strerror_r(save_errno, ssl_error, MAX_SSL_ERR_LEN);
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "TLS/SSL error: %s (%d)",
+ ssl_error, save_errno);
+}
+
+
+static void ma_tls_get_error(char *errmsg, size_t length, int ssl_errno)
+{
+ const char *ssl_error_reason;
+
+ if (!ssl_errno)
+ {
+ strncpy(errmsg, "Unknown SSL error", length);
+ return;
+ }
+ if ((ssl_error_reason= gnutls_strerror(ssl_errno)))
+ {
+ strncpy(errmsg, ssl_error_reason, length);
+ return;
+ }
+ snprintf(errmsg, length, "SSL errno=%d", ssl_errno);
+}
+
+/*
+ Initializes SSL and allocate global
+ context SSL_context
+
+ SYNOPSIS
+ my_gnutls_start
+ mysql connection handle
+
+ RETURN VALUES
+ 0 success
+ 1 error
+*/
+int ma_tls_start(char *errmsg, size_t errmsg_len)
+{
+ int rc= 0;
+
+ if (ma_tls_initialized)
+ return 0;
+
+ pthread_mutex_init(&LOCK_gnutls_config,NULL);
+ pthread_mutex_lock(&LOCK_gnutls_config);
+
+ if ((rc= gnutls_global_init()) != GNUTLS_E_SUCCESS)
+ {
+ ma_tls_get_error(errmsg, errmsg_len, rc);
+ goto end;
+ }
+ snprintf(tls_library_version, TLS_VERSION_LENGTH - 1, "GnuTLS %s",
+ gnutls_check_version(NULL));
+
+ ma_tls_initialized= TRUE;
+end:
+ pthread_mutex_unlock(&LOCK_gnutls_config);
+ return rc;
+}
+
+/*
+ Release SSL and free resources
+ Will be automatically executed by
+ mysql_server_end() function
+
+ SYNOPSIS
+ my_gnutls_end()
+ void
+
+ RETURN VALUES
+ void
+*/
+void ma_tls_end()
+{
+ if (ma_tls_initialized)
+ {
+ pthread_mutex_lock(&LOCK_gnutls_config);
+ if (mariadb_deinitialize_ssl)
+ gnutls_global_deinit();
+ ma_tls_initialized= FALSE;
+ pthread_mutex_unlock(&LOCK_gnutls_config);
+ pthread_mutex_destroy(&LOCK_gnutls_config);
+ }
+ return;
+}
+
+static size_t ma_gnutls_get_protocol_version(const char *tls_version_option,
+ char *priority_string,
+ size_t prio_len)
+{
+ char tls_versions[128];
+
+ tls_versions[0]= 0;
+ if (!tls_version_option || !tls_version_option[0])
+ goto end;
+
+
+ if (strstr(tls_version_option, "TLSv1.0"))
+ strcat(tls_versions, ":+VERS-TLS1.0");
+ if (strstr(tls_version_option, "TLSv1.1"))
+ strcat(tls_versions, ":+VERS-TLS1.1");
+ if (strstr(tls_version_option, "TLSv1.2"))
+ strcat(tls_versions, ":+VERS-TLS1.2");
+#if GNUTLS_VERSION_NUMBER > 0x030605
+ if (strstr(tls_version_option, "TLSv1.3"))
+ strcat(tls_versions, ":+VERS-TLS1.3");
+#endif
+end:
+ if (tls_versions[0])
+ snprintf(priority_string, prio_len - 1, "-VERS-TLS-ALL%s:NORMAL", tls_versions);
+ else
+ strncpy(priority_string, "NORMAL:+VERS-ALL", prio_len - 1);
+ return strlen(priority_string);
+}
+
+static int ma_gnutls_set_ciphers(gnutls_session_t ssl,
+ const char *cipher_str,
+ const char *tls_version)
+{
+ const char *err;
+ char *token;
+#define PRIO_SIZE 1024
+ char prio[PRIO_SIZE];
+
+ ma_gnutls_get_protocol_version(tls_version, prio, PRIO_SIZE);
+
+ if (!cipher_str)
+ return gnutls_priority_set_direct(ssl, prio, &err);
+
+ token= strtok((char *)cipher_str, ":");
+
+ strcpy(prio, "NONE:+VERS-TLS-ALL:+SIGN-ALL:+COMP-NULL:+CURVE-ALL");
+
+ while (token)
+ {
+ char priority[1024];
+ char *p= get_priority(token, priority, 1024);
+ if (p)
+ strncat(prio, p, PRIO_SIZE - strlen(prio));
+ token = strtok(NULL, ":");
+ }
+ return gnutls_priority_set_direct(ssl, prio , &err);
+}
+
+static int ma_tls_set_certs(MYSQL *mysql,
+ gnutls_certificate_credentials_t ctx)
+{
+ int ssl_error= 0;
+
+ if (mysql->options.ssl_ca)
+ {
+
+ ssl_error= gnutls_certificate_set_x509_trust_file(ctx,
+ mysql->options.ssl_ca,
+ GNUTLS_X509_FMT_PEM);
+ if (ssl_error < 0)
+ goto error;
+ }
+
+ if (mysql->options.ssl_capath)
+ {
+ ssl_error= gnutls_certificate_set_x509_trust_dir(ctx,
+ mysql->options.ssl_capath,
+ GNUTLS_X509_FMT_PEM);
+ if (ssl_error < 0)
+ goto error;
+ }
+
+ if (mysql->options.extension && mysql->options.extension->ssl_crl)
+ {
+ ssl_error= gnutls_certificate_set_x509_crl_file(ctx,
+ mysql->options.extension->ssl_crl, GNUTLS_X509_FMT_PEM);
+ if (ssl_error < 0)
+ goto error;
+ }
+
+ if (!mysql->options.ssl_ca && !mysql->options.ssl_capath)
+ {
+ ssl_error= gnutls_certificate_set_x509_system_trust(ctx);
+ if (ssl_error < 0)
+ goto error;
+ }
+
+ gnutls_certificate_set_verify_function(ctx,
+ my_verify_callback);
+
+ if (mysql->options.ssl_key || mysql->options.ssl_cert)
+ {
+ char *keyfile= mysql->options.ssl_key;
+ char *certfile= mysql->options.ssl_cert;
+
+ if (!certfile)
+ certfile= keyfile;
+ else if (!keyfile)
+ keyfile= certfile;
+
+ /* load cert/key into context */
+ if ((ssl_error= gnutls_certificate_set_x509_key_file2(ctx,
+ certfile, keyfile, GNUTLS_X509_FMT_PEM,
+ mysql->options.extension ? mysql->options.extension->tls_pw : NULL, 0)) < 0)
+ goto error;
+ }
+
+error:
+ return ssl_error;
+}
+
+void *ma_tls_init(MYSQL *mysql)
+{
+ gnutls_session_t ssl= NULL;
+ gnutls_certificate_credentials_t ctx;
+ int ssl_error= 0;
+
+ pthread_mutex_lock(&LOCK_gnutls_config);
+
+ if (gnutls_certificate_allocate_credentials(&ctx) != GNUTLS_E_SUCCESS)
+ goto error;
+
+ if ((ssl_error= ma_tls_set_certs(mysql, ctx)) < 0)
+ goto error;
+
+ if ((ssl_error = gnutls_init(&ssl, GNUTLS_CLIENT | GNUTLS_NONBLOCK | GNUTLS_NO_SIGNAL)) < 0)
+ goto error;
+
+ gnutls_session_set_ptr(ssl, (void *)mysql);
+ /*
+ gnutls_certificate_set_retrieve_function2(GNUTLS_xcred, client_cert_callback);
+ */
+ ssl_error= ma_gnutls_set_ciphers(ssl, mysql->options.ssl_cipher, mysql->options.extension ? mysql->options.extension->tls_version : NULL);
+ if (ssl_error < 0)
+ goto error;
+
+ /* we don't load private key and cert by default - if the server requests
+ a client certificate we will send it via callback function */
+ if ((ssl_error= gnutls_credentials_set(ssl, GNUTLS_CRD_CERTIFICATE, ctx)) < 0)
+ goto error;
+
+ pthread_mutex_unlock(&LOCK_gnutls_config);
+ return (void *)ssl;
+error:
+ ma_tls_set_error(mysql, ssl, ssl_error);
+ gnutls_certificate_free_credentials(ctx);
+ if (ssl)
+ gnutls_deinit(ssl);
+ pthread_mutex_unlock(&LOCK_gnutls_config);
+ return NULL;
+}
+
+#ifdef GNUTLS_EXTERNAL_TRANSPORT
+ssize_t ma_tls_push(gnutls_transport_ptr_t ptr, const void* data, size_t len)
+{
+ MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
+ ssize_t rc= pvio->methods->write(pvio, data, len);
+ return rc;
+}
+
+ssize_t ma_tls_pull(gnutls_transport_ptr_t ptr, void* data, size_t len)
+{
+ MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
+ ssize_t rc= pvio->methods->read(pvio, data, len);
+ return rc;
+}
+
+static int ma_tls_pull_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
+{
+ MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
+ return pvio->methods->wait_io_or_timeout(pvio, 0, ms);
+}
+#endif
+
+my_bool ma_tls_connect(MARIADB_TLS *ctls)
+{
+ gnutls_session_t ssl = (gnutls_session_t)ctls->ssl;
+ my_bool blocking;
+ MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
+ MARIADB_PVIO *pvio;
+ int ret;
+
+ if (!mysql)
+ return 1;
+
+ pvio= mysql->net.pvio;
+
+ /* Set socket to blocking if not already set */
+ if (!(blocking= pvio->methods->is_blocking(pvio)))
+ pvio->methods->blocking(pvio, TRUE, 0);
+
+
+#ifdef GNUTLS_EXTERNAL_TRANSPORT
+ /* we don't use GnuTLS read/write functions */
+ gnutls_transport_set_ptr(ssl, pvio);
+ gnutls_transport_set_push_function(ssl, ma_tls_push);
+ gnutls_transport_set_pull_function(ssl, ma_tls_pull);
+ gnutls_transport_set_pull_timeout_function(ssl, ma_tls_pull_timeout);
+ gnutls_handshake_set_timeout(ssl, pvio->timeout[PVIO_CONNECT_TIMEOUT]);
+#else
+ gnutls_transport_set_int(ssl, mysql_get_socket(mysql));
+#endif
+
+ do {
+ ret = gnutls_handshake(ssl);
+ } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret < 0)
+ {
+ /* If error message was not set while calling certification callback function,
+ use default error message (which is not very descriptive */
+ if (!mysql_errno(mysql))
+ ma_tls_set_error(mysql, ssl, ret);
+
+ ma_tls_close(ctls);
+
+ /* restore blocking mode */
+ if (!blocking)
+ pvio->methods->blocking(pvio, FALSE, 0);
+ return 1;
+ }
+ ctls->ssl= (void *)ssl;
+ return 0;
+}
+
+ssize_t ma_tls_write_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ ssize_t res;
+ struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
+ MARIADB_TLS *ctls= pvio->ctls;
+
+ for (;;)
+ {
+ b->events_to_wait_for= 0;
+ res= gnutls_record_send((gnutls_session_t)ctls->ssl, (void *)buffer, length);
+ if (res > 0)
+ return res;
+ if (res == GNUTLS_E_AGAIN)
+ b->events_to_wait_for|= MYSQL_WAIT_WRITE;
+ else
+ return res;
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ }
+}
+
+
+ssize_t ma_tls_read_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ ssize_t res;
+ struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
+ MARIADB_TLS *ctls= pvio->ctls;
+
+ for (;;)
+ {
+ b->events_to_wait_for= 0;
+ res= gnutls_record_recv((gnutls_session_t)ctls->ssl, (void *)buffer, length);
+ if (res > 0)
+ return res;
+ if (res == GNUTLS_E_AGAIN)
+ b->events_to_wait_for|= MYSQL_WAIT_READ;
+ else
+ return res;
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ }
+}
+
+ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ ssize_t rc;
+ MARIADB_PVIO *pvio= ctls->pvio;
+
+ while ((rc= gnutls_record_recv((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0)
+ {
+ if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED)
+ break;
+ if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1)
+ break;
+ }
+ if (rc <= 0) {
+ MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
+ ma_tls_set_error(mysql, ctls->ssl, rc);
+ }
+ return rc;
+}
+
+ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ ssize_t rc;
+ MARIADB_PVIO *pvio= ctls->pvio;
+
+ while ((rc= gnutls_record_send((gnutls_session_t)ctls->ssl, (void *)buffer, length)) <= 0)
+ {
+ if (rc != GNUTLS_E_AGAIN && rc != GNUTLS_E_INTERRUPTED)
+ break;
+ if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1)
+ break;
+ }
+ if (rc <= 0) {
+ MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
+ ma_tls_set_error(mysql, ctls->ssl, rc);
+ }
+ return rc;
+}
+
+my_bool ma_tls_close(MARIADB_TLS *ctls)
+{
+ if (ctls->ssl)
+ {
+ gnutls_certificate_credentials_t ctx;
+ /* this would be the correct way, however can't detect afterwards
+ if the socket is closed or not, so we don't send encrypted
+ finish alert.
+ rc= gnutls_bye((gnutls_session_t )ctls->ssl, GNUTLS_SHUT_WR);
+ */
+ gnutls_credentials_get(ctls->ssl, GNUTLS_CRD_CERTIFICATE, (void **)&ctx);
+ gnutls_certificate_free_keys(ctx);
+ gnutls_certificate_free_cas(ctx);
+ gnutls_certificate_free_crls(ctx);
+ gnutls_certificate_free_ca_names(ctx);
+ gnutls_certificate_free_credentials(ctx);
+ gnutls_deinit((gnutls_session_t )ctls->ssl);
+ ctls->ssl= NULL;
+ }
+ return 0;
+}
+
+int ma_tls_verify_server_cert(MARIADB_TLS *ctls __attribute__((unused)))
+{
+ /* server verification is already handled before during handshake */
+ return 0;
+}
+
+const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
+{
+ gnutls_kx_algorithm_t kx;
+ gnutls_cipher_algorithm_t cipher;
+ gnutls_mac_algorithm_t mac;
+
+ if (!ctls || !ctls->ssl)
+ return NULL;
+
+ mac= gnutls_mac_get((gnutls_session_t)ctls->ssl);
+ cipher= gnutls_cipher_get((gnutls_session_t)ctls->ssl);
+ kx= gnutls_kx_get((gnutls_session_t)ctls->ssl);
+ return openssl_cipher_name(kx, cipher, mac);
+}
+
+static int my_verify_callback(gnutls_session_t ssl)
+{
+ unsigned int status= 0;
+ MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl);
+
+ CLEAR_CLIENT_ERROR(mysql);
+
+ if ((mysql->options.extension->tls_verify_server_cert))
+ {
+ const char *hostname= mysql->host;
+
+ if (gnutls_certificate_verify_peers3 (ssl, hostname, &status) < 0)
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ } else {
+ if (gnutls_certificate_verify_peers2 (ssl, &status) < 0)
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+ if (status & GNUTLS_CERT_INVALID)
+ {
+ gnutls_datum_t out;
+ int type;
+ /* accept self signed certificates if we don't have to verify server cert */
+ if (!(mysql->options.extension->tls_verify_server_cert) &&
+ (status & GNUTLS_CERT_SIGNER_NOT_FOUND))
+ return 0;
+
+ /* gnutls default error message "certificate validation failed" isn't very
+ descriptive, so we provide more information about the error here */
+ type= gnutls_certificate_type_get(ssl);
+ gnutls_certificate_verification_status_print(status, type, &out, 0);
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR), out.data);
+ gnutls_free(out.data);
+
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+
+
+ return 0;
+}
+
+unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
+{
+ MYSQL *mysql;
+ size_t fp_len= len;
+ const gnutls_datum_t *cert_list;
+ unsigned int cert_list_size;
+
+ if (!ctls || !ctls->ssl)
+ return 0;
+
+ mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
+
+ cert_list = gnutls_certificate_get_peers (ctls->ssl, &cert_list_size);
+ if (cert_list == NULL)
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Unable to get server certificate");
+ return 0;
+ }
+
+ if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &cert_list[0], fp, &fp_len) == 0)
+ return fp_len;
+ else
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Finger print buffer too small");
+ return 0;
+ }
+}
+
+int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
+{
+ if (!ctls || !ctls->ssl)
+ return 1;
+
+ return gnutls_protocol_get_version(ctls->ssl) - 1;
+}
+
+void ma_tls_set_connection(MYSQL *mysql)
+{
+ (void)gnutls_session_set_ptr(mysql->net.pvio->ctls->ssl, (void *)mysql);
+}
+#endif /* HAVE_GNUTLS */
diff --git a/libmariadb/libmariadb/secure/gnutls_crypt.c b/libmariadb/libmariadb/secure/gnutls_crypt.c
new file mode 100644
index 00000000..a669e88e
--- /dev/null
+++ b/libmariadb/libmariadb/secure/gnutls_crypt.c
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*/
+#include <ma_crypt.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
+static gnutls_digest_algorithm_t ma_hash_get_algorithm(unsigned int alg)
+{
+ switch(alg)
+ {
+ case MA_HASH_MD5:
+ return GNUTLS_DIG_MD5;
+ case MA_HASH_SHA1:
+ return GNUTLS_DIG_SHA1;
+ case MA_HASH_SHA256:
+ return GNUTLS_DIG_SHA256;
+ case MA_HASH_SHA384:
+ return GNUTLS_DIG_SHA384;
+ case MA_HASH_SHA512:
+ return GNUTLS_DIG_SHA512;
+ case MA_HASH_RIPEMD160:
+ return GNUTLS_DIG_RMD160;
+ default:
+ return GNUTLS_DIG_UNKNOWN;
+ }
+}
+
+MA_HASH_CTX *ma_hash_new(unsigned int algorithm)
+{
+ gnutls_hash_hd_t ctx= NULL;
+ gnutls_digest_algorithm_t hash_alg= ma_hash_get_algorithm(algorithm);
+
+ /* unknown or unsupported hash algorithm */
+ if (hash_alg == GNUTLS_DIG_UNKNOWN)
+ return NULL;
+
+ if (gnutls_hash_init(&ctx, hash_alg) < 0)
+ return NULL;
+
+ return (MA_HASH_CTX *)ctx;
+}
+
+void ma_hash_free(MA_HASH_CTX *ctx)
+{
+ if (ctx)
+ gnutls_hash_deinit((gnutls_hash_hd_t)ctx, NULL);
+}
+
+void ma_hash_input(MA_HASH_CTX *ctx,
+ const unsigned char *buffer,
+ size_t len)
+{
+ gnutls_hash((gnutls_hash_hd_t)ctx, (const void *)buffer, len);
+}
+
+void ma_hash_result(MA_HASH_CTX *ctx, unsigned char *digest)
+{
+ gnutls_hash_output((gnutls_hash_hd_t)ctx, digest);
+}
+
+
diff --git a/libmariadb/libmariadb/secure/ma_schannel.c b/libmariadb/libmariadb/secure/ma_schannel.c
new file mode 100644
index 00000000..be4148c7
--- /dev/null
+++ b/libmariadb/libmariadb/secure/ma_schannel.c
@@ -0,0 +1,629 @@
+/************************************************************************************
+ Copyright (C) 2014 MariaDB Corporation Ab
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Author: Georg Richter
+
+ *************************************************************************************/
+#include "ma_schannel.h"
+#include "schannel_certs.h"
+#include <assert.h>
+
+#define SC_IO_BUFFER_SIZE 0x4000
+#define MAX_SSL_ERR_LEN 100
+
+#define SCHANNEL_PAYLOAD(A) ((A).cbMaximumMessage + (A).cbHeader + (A).cbTrailer)
+void ma_schannel_set_win_error(MARIADB_PVIO *pvio, DWORD ErrorNo);
+
+
+
+
+/* {{{ void ma_schannel_set_sec_error */
+void ma_schannel_set_sec_error(MARIADB_PVIO* pvio, DWORD ErrorNo)
+{
+ MYSQL* mysql = pvio->mysql;
+ if (ErrorNo != SEC_E_OK)
+ mysql->net.extension->extended_errno = ErrorNo;
+ if (ErrorNo == SEC_E_INTERNAL_ERROR && GetLastError())
+ {
+ ma_schannel_set_win_error(pvio, GetLastError());
+ return;
+ }
+ ma_schannel_set_win_error(pvio, ErrorNo);
+}
+/* }}} */
+
+#include "win32_errmsg.h"
+/* {{{ void ma_schnnel_set_win_error */
+void ma_schannel_set_win_error(MARIADB_PVIO *pvio, DWORD ErrorNo)
+{
+ char buffer[256];
+ ma_format_win32_error(buffer, sizeof(buffer), ErrorNo, "TLS/SSL error: ");
+ pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, buffer);
+ return;
+}
+/* }}} */
+
+
+/* }}} */
+
+/* {{{ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData) */
+/*
+ perform handshake loop
+
+ SYNOPSIS
+ ma_schannel_handshake_loop()
+ pvio Pointer to an Communication/IO structure
+ InitialRead TRUE if it's the very first read
+ ExtraData Pointer to an SecBuffer which contains extra data (sent by application)
+
+
+*/
+
+SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData)
+{
+ SecBufferDesc OutBuffer, InBuffer;
+ SecBuffer InBuffers[2], OutBuffers;
+ DWORD dwSSPIFlags, dwSSPIOutFlags, cbData, cbIoBuffer;
+ TimeStamp tsExpiry;
+ SECURITY_STATUS rc;
+ PUCHAR IoBuffer;
+ BOOL fDoRead;
+ MARIADB_TLS *ctls= pvio->ctls;
+ SC_CTX *sctx= (SC_CTX *)ctls->ssl;
+
+
+ dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
+ ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONFIDENTIALITY |
+ ISC_RET_EXTENDED_ERROR |
+ ISC_REQ_ALLOCATE_MEMORY |
+ ISC_REQ_STREAM;
+
+
+ /* Allocate data buffer */
+ if (!(IoBuffer = malloc(SC_IO_BUFFER_SIZE)))
+ return SEC_E_INSUFFICIENT_MEMORY;
+
+ cbIoBuffer = 0;
+ fDoRead = InitialRead;
+
+ /* handshake loop: We will leave if handshake is finished
+ or an error occurs */
+
+ rc = SEC_I_CONTINUE_NEEDED;
+
+ while (rc == SEC_I_CONTINUE_NEEDED ||
+ rc == SEC_E_INCOMPLETE_MESSAGE ||
+ rc == SEC_I_INCOMPLETE_CREDENTIALS )
+ {
+ /* Read data */
+ if (rc == SEC_E_INCOMPLETE_MESSAGE ||
+ !cbIoBuffer)
+ {
+ if(fDoRead)
+ {
+ ssize_t nbytes = pvio->methods->read(pvio, IoBuffer + cbIoBuffer, (size_t)(SC_IO_BUFFER_SIZE - cbIoBuffer));
+ if (nbytes <= 0)
+ {
+ rc = SEC_E_INTERNAL_ERROR;
+ break;
+ }
+ cbData = (DWORD)nbytes;
+ cbIoBuffer += cbData;
+ }
+ else
+ fDoRead = TRUE;
+ }
+
+ /* input buffers
+ First buffer stores data received from server. leftover data
+ will be stored in second buffer with BufferType SECBUFFER_EXTRA */
+
+ InBuffers[0].pvBuffer = IoBuffer;
+ InBuffers[0].cbBuffer = cbIoBuffer;
+ InBuffers[0].BufferType = SECBUFFER_TOKEN;
+
+ InBuffers[1].pvBuffer = NULL;
+ InBuffers[1].cbBuffer = 0;
+ InBuffers[1].BufferType = SECBUFFER_EMPTY;
+
+ InBuffer.cBuffers = 2;
+ InBuffer.pBuffers = InBuffers;
+ InBuffer.ulVersion = SECBUFFER_VERSION;
+
+
+ /* output buffer */
+ OutBuffers.pvBuffer = NULL;
+ OutBuffers.BufferType= SECBUFFER_TOKEN;
+ OutBuffers.cbBuffer = 0;
+
+ OutBuffer.cBuffers = 1;
+ OutBuffer.pBuffers = &OutBuffers;
+ OutBuffer.ulVersion = SECBUFFER_VERSION;
+
+
+ rc = InitializeSecurityContextA(&sctx->CredHdl,
+ &sctx->hCtxt,
+ NULL,
+ dwSSPIFlags,
+ 0,
+ SECURITY_NATIVE_DREP,
+ &InBuffer,
+ 0,
+ NULL,
+ &OutBuffer,
+ &dwSSPIOutFlags,
+ &tsExpiry );
+
+
+ if (rc == SEC_E_OK ||
+ rc == SEC_I_CONTINUE_NEEDED ||
+ (FAILED(rc) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)))
+ {
+ if(OutBuffers.cbBuffer && OutBuffers.pvBuffer)
+ {
+ ssize_t nbytes = pvio->methods->write(pvio, (uchar *)OutBuffers.pvBuffer, (size_t)OutBuffers.cbBuffer);
+ if(nbytes <= 0)
+ {
+ FreeContextBuffer(OutBuffers.pvBuffer);
+ DeleteSecurityContext(&sctx->hCtxt);
+ return SEC_E_INTERNAL_ERROR;
+ }
+ cbData= (DWORD)nbytes;
+ /* Free output context buffer */
+ FreeContextBuffer(OutBuffers.pvBuffer);
+ OutBuffers.pvBuffer = NULL;
+ }
+ }
+ /* check if we need to read more data */
+ switch (rc) {
+ case SEC_E_INCOMPLETE_MESSAGE:
+ /* we didn't receive all data, so just continue loop */
+ continue;
+ break;
+ case SEC_E_OK:
+ /* handshake completed, but we need to check if extra
+ data was sent (which contains encrypted application data) */
+ if (InBuffers[1].BufferType == SECBUFFER_EXTRA)
+ {
+ if (!(pExtraData->pvBuffer= LocalAlloc(0, InBuffers[1].cbBuffer)))
+ return SEC_E_INSUFFICIENT_MEMORY;
+
+ MoveMemory(pExtraData->pvBuffer, IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer );
+ pExtraData->BufferType = SECBUFFER_TOKEN;
+ pExtraData->cbBuffer = InBuffers[1].cbBuffer;
+ }
+ else
+ {
+ pExtraData->BufferType= SECBUFFER_EMPTY;
+ pExtraData->pvBuffer= NULL;
+ pExtraData->cbBuffer= 0;
+ }
+ break;
+
+ case SEC_I_INCOMPLETE_CREDENTIALS:
+ /* Provided credentials didn't contain a valid client certificate.
+ We will try to connect anonymously, using current credentials */
+ fDoRead= FALSE;
+ rc= SEC_I_CONTINUE_NEEDED;
+ continue;
+ break;
+ default:
+ if (FAILED(rc))
+ {
+ goto loopend;
+ }
+ break;
+ }
+
+ if ( InBuffers[1].BufferType == SECBUFFER_EXTRA )
+ {
+ MoveMemory( IoBuffer, IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer );
+ cbIoBuffer = InBuffers[1].cbBuffer;
+ }
+ else
+ cbIoBuffer = 0;
+ }
+loopend:
+ if (FAILED(rc))
+ {
+ ma_schannel_set_sec_error(pvio, rc);
+ DeleteSecurityContext(&sctx->hCtxt);
+ }
+ free(IoBuffer);
+
+ return rc;
+}
+/* }}} */
+
+/* {{{ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls) */
+/*
+ performs client side handshake
+
+ SYNOPSIS
+ ma_schannel_client_handshake()
+ ctls Pointer to a MARIADB_TLS structure
+
+ DESCRIPTION
+ initiates a client/server handshake. This function can be used
+ by clients only
+
+ RETURN
+ SEC_E_OK on success
+*/
+
+SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls)
+{
+ MARIADB_PVIO *pvio;
+ SECURITY_STATUS sRet;
+ DWORD OutFlags;
+ SC_CTX *sctx;
+ SecBuffer ExtraData;
+ DWORD SFlags= ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+ ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR |
+ ISC_REQ_USE_SUPPLIED_CREDS |
+ ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM;
+
+ SecBufferDesc BufferOut;
+ SecBuffer BuffersOut;
+
+ if (!ctls || !ctls->pvio)
+ return 1;
+
+ pvio= ctls->pvio;
+ sctx= (SC_CTX *)ctls->ssl;
+
+ /* Initialie securifty context */
+ BuffersOut.BufferType= SECBUFFER_TOKEN;
+ BuffersOut.cbBuffer= 0;
+ BuffersOut.pvBuffer= NULL;
+
+
+ BufferOut.cBuffers= 1;
+ BufferOut.pBuffers= &BuffersOut;
+ BufferOut.ulVersion= SECBUFFER_VERSION;
+
+ sRet = InitializeSecurityContext(&sctx->CredHdl,
+ NULL,
+ pvio->mysql->host,
+ SFlags,
+ 0,
+ SECURITY_NATIVE_DREP,
+ NULL,
+ 0,
+ &sctx->hCtxt,
+ &BufferOut,
+ &OutFlags,
+ NULL);
+
+ if(sRet != SEC_I_CONTINUE_NEEDED)
+ {
+ ma_schannel_set_sec_error(pvio, sRet);
+ return sRet;
+ }
+
+ /* send client hello */
+ if(BuffersOut.cbBuffer != 0 && BuffersOut.pvBuffer != NULL)
+ {
+ ssize_t nbytes = (DWORD)pvio->methods->write(pvio, (uchar *)BuffersOut.pvBuffer, (size_t)BuffersOut.cbBuffer);
+
+ if (nbytes <= 0)
+ {
+ sRet= SEC_E_INTERNAL_ERROR;
+ goto end;
+ }
+ }
+ sRet= ma_schannel_handshake_loop(pvio, TRUE, &ExtraData);
+
+ /* allocate IO-Buffer for write operations: After handshake
+ was successful, we are able now to calculate payload */
+ if ((sRet = QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_STREAM_SIZES, &sctx->Sizes )))
+ goto end;
+
+ sctx->IoBufferSize= SCHANNEL_PAYLOAD(sctx->Sizes);
+ if (!(sctx->IoBuffer= (PUCHAR)LocalAlloc(0, sctx->IoBufferSize)))
+ {
+ sRet= SEC_E_INSUFFICIENT_MEMORY;
+ goto end;
+ }
+
+ return sRet;
+end:
+ if (BuffersOut.pvBuffer)
+ FreeContextBuffer(BuffersOut.pvBuffer);
+ return sRet;
+}
+/* }}} */
+
+/* {{{ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio, PCredHandle phCreds, CtxtHandle * phContext,
+ DWORD DecryptLength, uchar *ReadBuffer, DWORD ReadBufferSize) */
+/*
+ Reads encrypted data from a SSL stream and decrypts it.
+
+ SYNOPSIS
+ ma_schannel_read
+ pvio pointer to Communication IO structure
+ phContext a context handle
+ DecryptLength size of decrypted buffer
+ ReadBuffer Buffer for decrypted data
+ ReadBufferSize size of ReadBuffer
+
+
+ DESCRIPTION
+ Reads decrypted data from a SSL stream and encrypts it.
+
+ RETURN
+ SEC_E_OK on success
+ SEC_E_* if an error occurred
+*/
+
+SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
+ CtxtHandle * phContext,
+ DWORD *DecryptLength,
+ uchar *ReadBuffer,
+ DWORD ReadBufferSize)
+{
+ ssize_t nbytes = 0;
+ DWORD dwOffset = 0;
+ SC_CTX *sctx;
+ SECURITY_STATUS sRet = 0;
+ SecBufferDesc Msg;
+ SecBuffer Buffers[4];
+ int i;
+
+ if (!pvio || !pvio->methods || !pvio->methods->read || !pvio->ctls || !DecryptLength)
+ return SEC_E_INTERNAL_ERROR;
+
+ sctx = (SC_CTX *)pvio->ctls->ssl;
+ *DecryptLength = 0;
+
+ if (sctx->dataBuf.cbBuffer)
+ {
+ /* Have unread decrypted data from the last time, copy. */
+ nbytes = MIN(ReadBufferSize, sctx->dataBuf.cbBuffer);
+ memcpy(ReadBuffer, sctx->dataBuf.pvBuffer, nbytes);
+ sctx->dataBuf.pvBuffer = (char *)(sctx->dataBuf.pvBuffer) + nbytes;
+ sctx->dataBuf.cbBuffer -= (DWORD)nbytes;
+ *DecryptLength = (DWORD)nbytes;
+ return SEC_E_OK;
+ }
+
+
+ while (1)
+ {
+ /* Check for any encrypted data returned by last DecryptMessage() in SECBUFFER_EXTRA buffer. */
+ if (sctx->extraBuf.cbBuffer)
+ {
+ memmove(sctx->IoBuffer, sctx->extraBuf.pvBuffer, sctx->extraBuf.cbBuffer);
+ dwOffset = sctx->extraBuf.cbBuffer;
+ sctx->extraBuf.cbBuffer = 0;
+ }
+
+ do {
+ assert(sctx->IoBufferSize > dwOffset);
+ if (dwOffset == 0 || sRet == SEC_E_INCOMPLETE_MESSAGE)
+ {
+ nbytes = pvio->methods->read(pvio, sctx->IoBuffer + dwOffset, (size_t)(sctx->IoBufferSize - dwOffset));
+ if (nbytes <= 0)
+ {
+ /* server closed connection, or an error */
+ // todo: error
+ return SEC_E_INVALID_HANDLE;
+ }
+ dwOffset += (DWORD)nbytes;
+ }
+ ZeroMemory(Buffers, sizeof(SecBuffer) * 4);
+ Buffers[0].pvBuffer = sctx->IoBuffer;
+ Buffers[0].cbBuffer = dwOffset;
+
+ Buffers[0].BufferType = SECBUFFER_DATA;
+ Buffers[1].BufferType = SECBUFFER_EMPTY;
+ Buffers[2].BufferType = SECBUFFER_EMPTY;
+ Buffers[3].BufferType = SECBUFFER_EMPTY;
+
+ Msg.ulVersion = SECBUFFER_VERSION; // Version number
+ Msg.cBuffers = 4;
+ Msg.pBuffers = Buffers;
+
+ sRet = DecryptMessage(phContext, &Msg, 0, NULL);
+
+ } while (sRet == SEC_E_INCOMPLETE_MESSAGE); /* Continue reading until full message arrives */
+
+
+ if (sRet != SEC_E_OK)
+ {
+ ma_schannel_set_sec_error(pvio, sRet);
+ return sRet;
+ }
+
+ sctx->extraBuf.cbBuffer = 0;
+ sctx->dataBuf.cbBuffer = 0;
+ for (i = 0; i < 4; i++)
+ {
+ if (Buffers[i].BufferType == SECBUFFER_DATA)
+ sctx->dataBuf = Buffers[i];
+ if (Buffers[i].BufferType == SECBUFFER_EXTRA)
+ sctx->extraBuf = Buffers[i];
+ }
+
+
+ if (sctx->dataBuf.cbBuffer)
+ {
+ assert(sctx->dataBuf.pvBuffer);
+ /*
+ Copy at most ReadBufferSize bytes to output.
+ Store the rest (if any) to be processed next time.
+ */
+ nbytes = MIN(sctx->dataBuf.cbBuffer, ReadBufferSize);
+ memcpy((char *)ReadBuffer, sctx->dataBuf.pvBuffer, nbytes);
+ sctx->dataBuf.cbBuffer -= (unsigned long)nbytes;
+ sctx->dataBuf.pvBuffer = (char *)sctx->dataBuf.pvBuffer + nbytes;
+
+ *DecryptLength = (DWORD)nbytes;
+ return SEC_E_OK;
+ }
+ // No data buffer, loop
+ }
+}
+/* }}} */
+#include "win32_errmsg.h"
+my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name)
+{
+ SECURITY_STATUS status;
+
+ MARIADB_PVIO *pvio= ctls->pvio;
+ MYSQL *mysql= pvio->mysql;
+ SC_CTX *sctx = (SC_CTX *)ctls->ssl;
+ const char *ca_file= mysql->options.ssl_ca;
+ const char* ca_path = mysql->options.ssl_capath;
+ const char *crl_file= mysql->options.extension ? mysql->options.extension->ssl_crl : NULL;
+ const char* crl_path = mysql->options.extension ? mysql->options.extension->ssl_crlpath : NULL;
+ PCCERT_CONTEXT pServerCert= NULL;
+ char errmsg[256];
+ HCERTSTORE store= NULL;
+ int ret= 0;
+
+ status = schannel_create_store(ca_file, ca_path, crl_file, crl_path, &store, errmsg, sizeof(errmsg));
+ if(status)
+ goto end;
+
+ status = QueryContextAttributesA(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert);
+ if (status)
+ {
+ ma_format_win32_error(errmsg, sizeof(errmsg), GetLastError(),
+ "QueryContextAttributes(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed.");
+ goto end;
+ }
+
+ status = schannel_verify_server_certificate(
+ pServerCert,
+ store,
+ crl_file != 0 || crl_path != 0,
+ mysql->host,
+ verify_server_name,
+ errmsg, sizeof(errmsg));
+
+ if (status)
+ goto end;
+
+ ret= 1;
+
+end:
+ if (!ret)
+ {
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, errmsg);
+ }
+ if (pServerCert)
+ CertFreeCertificateContext(pServerCert);
+ if(store)
+ schannel_free_store(store);
+ return ret;
+}
+
+
+/* {{{ size_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio, PCredHandle phCreds, CtxtHandle * phContext) */
+/*
+ Decrypts data and write to SSL stream
+ SYNOPSIS
+ ma_schannel_write_decrypt
+ pvio pointer to Communication IO structure
+ phContext a context handle
+ DecryptLength size of decrypted buffer
+ ReadBuffer Buffer for decrypted data
+ ReadBufferSize size of ReadBuffer
+
+ DESCRIPTION
+ Write encrypted data to SSL stream.
+
+ RETURN
+ SEC_E_OK on success
+ SEC_E_* if an error occurred
+*/
+ssize_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
+ uchar *WriteBuffer,
+ size_t WriteBufferSize)
+{
+ SECURITY_STATUS scRet;
+ SecBufferDesc Message;
+ SecBuffer Buffers[4];
+ SC_CTX *sctx= (SC_CTX *)pvio->ctls->ssl;
+ size_t payload;
+ ssize_t nbytes;
+ DWORD write_size;
+
+ payload= MIN(WriteBufferSize, sctx->Sizes.cbMaximumMessage);
+
+ memcpy(&sctx->IoBuffer[sctx->Sizes.cbHeader], WriteBuffer, payload);
+
+ Buffers[0].pvBuffer = sctx->IoBuffer;
+ Buffers[0].cbBuffer = sctx->Sizes.cbHeader;
+ Buffers[0].BufferType = SECBUFFER_STREAM_HEADER; // Type of the buffer
+
+ Buffers[1].pvBuffer = &sctx->IoBuffer[sctx->Sizes.cbHeader];
+ Buffers[1].cbBuffer = (DWORD)payload;
+ Buffers[1].BufferType = SECBUFFER_DATA;
+
+ Buffers[2].pvBuffer = &sctx->IoBuffer[sctx->Sizes.cbHeader] + payload;
+ Buffers[2].cbBuffer = sctx->Sizes.cbTrailer;
+ Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
+
+ Buffers[3].pvBuffer = SECBUFFER_EMPTY;
+ Buffers[3].cbBuffer = SECBUFFER_EMPTY;
+ Buffers[3].BufferType = SECBUFFER_EMPTY;
+
+ Message.ulVersion = SECBUFFER_VERSION;
+ Message.cBuffers = 4;
+ Message.pBuffers = Buffers;
+ if ((scRet = EncryptMessage(&sctx->hCtxt, 0, &Message, 0))!= SEC_E_OK)
+ return -1;
+ write_size = Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer;
+ nbytes = pvio->methods->write(pvio, sctx->IoBuffer, write_size);
+ return nbytes == write_size ? payload : -1;
+}
+/* }}} */
+
+extern char *ssl_protocol_version[5];
+
+/* {{{ ma_tls_get_protocol_version(MARIADB_TLS *ctls) */
+int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
+{
+ SC_CTX *sctx;
+ SecPkgContext_ConnectionInfo ConnectionInfo;
+ if (!ctls->ssl)
+ return 1;
+
+ sctx= (SC_CTX *)ctls->ssl;
+
+ if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_CONNECTION_INFO, &ConnectionInfo) != SEC_E_OK)
+ return -1;
+
+ switch(ConnectionInfo.dwProtocol)
+ {
+ case SP_PROT_SSL3_CLIENT:
+ return PROTOCOL_SSLV3;
+ case SP_PROT_TLS1_CLIENT:
+ return PROTOCOL_TLS_1_0;
+ case SP_PROT_TLS1_1_CLIENT:
+ return PROTOCOL_TLS_1_1;
+ case SP_PROT_TLS1_2_CLIENT:
+ return PROTOCOL_TLS_1_2;
+ default:
+ return -1;
+ }
+}
+/* }}} */
diff --git a/libmariadb/libmariadb/secure/ma_schannel.h b/libmariadb/libmariadb/secure/ma_schannel.h
new file mode 100644
index 00000000..af7fc602
--- /dev/null
+++ b/libmariadb/libmariadb/secure/ma_schannel.h
@@ -0,0 +1,87 @@
+/************************************************************************************
+ Copyright (C) 2014 MariaDB Corporation Ab
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Author: Georg Richter
+
+ *************************************************************************************/
+#ifndef _ma_schannel_h_
+#define _ma_schannel_h_
+
+#define SECURITY_WIN32
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+#include <ma_pvio.h>
+#include <errmsg.h>
+
+
+#include <wincrypt.h>
+#include <wintrust.h>
+
+
+#include <security.h>
+
+#include <schnlsp.h>
+#undef SECURITY_WIN32
+#include <windows.h>
+#include <sspi.h>
+
+#define SC_IO_BUFFER_SIZE 0x4000
+
+
+#include <ma_pthread.h>
+
+struct st_DER {
+ char* der_buffer;
+ DWORD der_length;
+};
+
+struct st_schannel {
+ CredHandle CredHdl;
+ PUCHAR IoBuffer;
+ DWORD IoBufferSize;
+ SecPkgContext_StreamSizes Sizes;
+ CtxtHandle hCtxt;
+
+ /* Cached data from the last read/decrypt call.*/
+ SecBuffer extraBuf; /* encrypted data read from server. */
+ SecBuffer dataBuf; /* decrypted but still unread data from server.*/
+
+};
+
+typedef struct st_schannel SC_CTX;
+
+extern HCERTSTORE ca_CertStore, crl_CertStore;
+extern my_bool ca_Check, crl_Check;
+
+;
+SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls);
+SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData);
+
+my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name);
+ssize_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
+ uchar *WriteBuffer,
+ size_t WriteBufferSize);
+SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
+ CtxtHandle* phContext,
+ DWORD *DecryptLength,
+ uchar *ReadBuffer,
+ DWORD ReadBufferSize);
+
+
+#endif /* _ma_schannel_h_ */
diff --git a/libmariadb/libmariadb/secure/openssl.c b/libmariadb/libmariadb/secure/openssl.c
new file mode 100644
index 00000000..2a272504
--- /dev/null
+++ b/libmariadb/libmariadb/secure/openssl.c
@@ -0,0 +1,786 @@
+/************************************************************************************
+ Copyright (C) 2012 Monty Program AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ *************************************************************************************/
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+#include <ma_pvio.h>
+#include <errmsg.h>
+#include <string.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <openssl/ssl.h> /* SSL and SSL_CTX */
+#include <openssl/err.h> /* error reporting */
+#include <openssl/conf.h>
+#include <openssl/md4.h>
+
+#if defined(_WIN32) && !defined(_OPENSSL_Applink) && defined(HAVE_OPENSSL_APPLINK_C)
+#include <openssl/applink.c>
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+#include <openssl/x509v3.h>
+#define HAVE_OPENSSL_CHECK_HOST 1
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#define HAVE_OPENSSL_1_1_API
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
+#define SSL_OP_NO_TLSv1_1 0L
+#define SSL_OP_NO_TLSv1_2 0L
+#define CRYPTO_THREADID_set_callback CRYPTO_set_id_callback
+#define CRYPTO_THREADID_get_callback CRYPTO_get_id_callback
+#endif
+
+#if defined(OPENSSL_USE_BIOMETHOD)
+#undef OPENSSL_USE_BIOMETHOD
+#endif
+#ifndef HAVE_OPENSSL_DEFAULT
+#include <memory.h>
+#define ma_malloc(A,B) malloc((A))
+#undef ma_free
+#define ma_free(A) free((A))
+#define ma_snprintf snprintf
+#define ma_vsnprintf vsnprintf
+#undef SAFE_MUTEX
+#endif
+#include <ma_pthread.h>
+
+#include <mariadb_async.h>
+#include <ma_context.h>
+
+extern my_bool ma_tls_initialized;
+extern unsigned int mariadb_deinitialize_ssl;
+
+#define MAX_SSL_ERR_LEN 100
+char tls_library_version[TLS_VERSION_LENGTH];
+
+static pthread_mutex_t LOCK_openssl_config;
+#ifndef HAVE_OPENSSL_1_1_API
+static pthread_mutex_t *LOCK_crypto= NULL;
+#endif
+#if defined(OPENSSL_USE_BIOMETHOD)
+static int ma_bio_read(BIO *h, char *buf, int size);
+static int ma_bio_write(BIO *h, const char *buf, int size);
+static BIO_METHOD ma_BIO_method;
+#endif
+
+
+static long ma_tls_version_options(const char *version)
+{
+ long protocol_options,
+ disable_all_protocols;
+
+ protocol_options= disable_all_protocols=
+ SSL_OP_NO_SSLv2 |
+ SSL_OP_NO_SSLv3 |
+ SSL_OP_NO_TLSv1 |
+ SSL_OP_NO_TLSv1_1 |
+ SSL_OP_NO_TLSv1_2
+#ifdef TLS1_3_VERSION
+ | SSL_OP_NO_TLSv1_3
+#endif
+ ;
+
+ if (!version)
+ return 0;
+
+ if (strstr(version, "TLSv1.0"))
+ protocol_options&= ~SSL_OP_NO_TLSv1;
+ if (strstr(version, "TLSv1.1"))
+ protocol_options&= ~SSL_OP_NO_TLSv1_1;
+ if (strstr(version, "TLSv1.2"))
+ protocol_options&= ~SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+ if (strstr(version, "TLSv1.3"))
+ protocol_options&= ~SSL_OP_NO_TLSv1_3;
+#endif
+
+ if (protocol_options != disable_all_protocols)
+ return protocol_options;
+ return 0;
+}
+
+static void ma_tls_set_error(MYSQL *mysql)
+{
+ ulong ssl_errno= ERR_get_error();
+ char ssl_error[MAX_SSL_ERR_LEN];
+ const char *ssl_error_reason;
+ MARIADB_PVIO *pvio= mysql->net.pvio;
+ int save_errno= errno;
+
+ if (ssl_errno && (ssl_error_reason= ERR_reason_error_string(ssl_errno)))
+ {
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ 0, ssl_error_reason);
+ return;
+ } else if (!save_errno) {
+ pvio->set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST));
+ return;
+ }
+
+ strerror_r(save_errno, ssl_error, MAX_SSL_ERR_LEN);
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "TLS/SSL error: %s (%d)",
+ ssl_error, save_errno);
+ return;
+}
+
+#ifndef HAVE_OPENSSL_1_1_API
+static void my_cb_locking(int mode, int n,
+ const char *file __attribute__((unused)),
+ int line __attribute__((unused)))
+{
+ if (mode & CRYPTO_LOCK)
+ pthread_mutex_lock(&LOCK_crypto[n]);
+ else
+ pthread_mutex_unlock(&LOCK_crypto[n]);
+}
+
+static int ssl_thread_init()
+{
+ if (LOCK_crypto == NULL)
+ {
+ int i, max= CRYPTO_num_locks();
+
+ if (!(LOCK_crypto=
+ (pthread_mutex_t *)ma_malloc(sizeof(pthread_mutex_t) * max, MYF(0))))
+ return 1;
+
+ for (i=0; i < max; i++)
+ pthread_mutex_init(&LOCK_crypto[i], NULL);
+
+ CRYPTO_set_locking_callback(my_cb_locking);
+ }
+ return 0;
+}
+#endif
+
+#if defined(_WIN32) || !defined(DISABLE_SIGPIPE)
+#define disable_sigpipe()
+#else
+#include <signal.h>
+static void ma_sigpipe_handler()
+{
+}
+
+static void disable_sigpipe()
+{
+ struct sigaction old_handler, new_handler={NULL};
+ if (!sigaction (SIGPIPE, NULL, &old_handler) &&
+ !old_handler.sa_handler)
+ {
+ new_handler.sa_handler= ma_sigpipe_handler;
+ new_handler.sa_flags= 0;
+ if (!sigemptyset(&new_handler.sa_mask))
+ sigaction(SIGPIPE, &new_handler, NULL);
+ }
+}
+#endif
+
+/*
+ Initializes SSL
+
+ SYNOPSIS
+ my_ssl_start
+ mysql connection handle
+
+ RETURN VALUES
+ 0 success
+ 1 error
+*/
+int ma_tls_start(char *errmsg __attribute__((unused)), size_t errmsg_len __attribute__((unused)))
+{
+ int rc= 1;
+ char *p;
+ if (ma_tls_initialized)
+ return 0;
+
+ /* lock mutex to prevent multiple initialization */
+ pthread_mutex_init(&LOCK_openssl_config, NULL);
+ pthread_mutex_lock(&LOCK_openssl_config);
+#ifdef HAVE_OPENSSL_1_1_API
+ if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL))
+ goto end;
+#else
+ if (ssl_thread_init())
+ {
+ strncpy(errmsg, "Not enough memory", errmsg_len);
+ goto end;
+ }
+ SSL_library_init();
+#if SSLEAY_VERSION_NUMBER >= 0x00907000L
+ OPENSSL_config(NULL);
+#endif
+#endif
+#ifndef HAVE_OPENSSL_1_1_API
+ /* load errors */
+ SSL_load_error_strings();
+ /* digests and ciphers */
+ OpenSSL_add_all_algorithms();
+#endif
+ disable_sigpipe();
+#ifdef OPENSSL_USE_BIOMETHOD
+ memcpy(&ma_BIO_method, BIO_s_socket(), sizeof(BIO_METHOD));
+ ma_BIO_method.bread= ma_bio_read;
+ ma_BIO_method.bwrite= ma_bio_write;
+#endif
+ snprintf(tls_library_version, TLS_VERSION_LENGTH - 1, "%s",
+#if defined(LIBRESSL_VERSION_NUMBER) || !defined(HAVE_OPENSSL_1_1_API)
+ SSLeay_version(SSLEAY_VERSION));
+#else
+ OpenSSL_version(OPENSSL_VERSION));
+#endif
+ /* remove date from version */
+ if ((p= strstr(tls_library_version, " ")))
+ *p= 0;
+ rc= 0;
+ ma_tls_initialized= TRUE;
+end:
+ pthread_mutex_unlock(&LOCK_openssl_config);
+ return rc;
+}
+
+/*
+ Release SSL and free resources
+ Will be automatically executed by
+ mysql_server_end() function
+
+ SYNOPSIS
+ my_ssl_end()
+ void
+
+ RETURN VALUES
+ void
+*/
+void ma_tls_end()
+{
+ if (ma_tls_initialized)
+ {
+ pthread_mutex_lock(&LOCK_openssl_config);
+#ifndef HAVE_OPENSSL_1_1_API
+ if (LOCK_crypto)
+ {
+ int i;
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_THREADID_set_callback(NULL);
+
+ for (i=0; i < CRYPTO_num_locks(); i++)
+ pthread_mutex_destroy(&LOCK_crypto[i]);
+ ma_free((gptr)LOCK_crypto);
+ LOCK_crypto= NULL;
+ }
+#endif
+ if (mariadb_deinitialize_ssl)
+ {
+#ifndef HAVE_OPENSSL_1_1_API
+ ERR_remove_thread_state(NULL);
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ ERR_free_strings();
+ CONF_modules_free();
+ CONF_modules_unload(1);
+#endif
+ }
+ ma_tls_initialized= FALSE;
+ pthread_mutex_unlock(&LOCK_openssl_config);
+ pthread_mutex_destroy(&LOCK_openssl_config);
+ }
+ return;
+}
+
+int ma_tls_get_password(char *buf, int size,
+ int rwflag __attribute__((unused)),
+ void *userdata)
+{
+ memset(buf, 0, size);
+ if (userdata)
+ strncpy(buf, (char *)userdata, size);
+ return (int)strlen(buf);
+}
+
+
+static int ma_tls_set_certs(MYSQL *mysql, SSL_CTX *ctx)
+{
+ char *certfile= mysql->options.ssl_cert,
+ *keyfile= mysql->options.ssl_key;
+ char *pw= (mysql->options.extension) ?
+ mysql->options.extension->tls_pw : NULL;
+
+ /* add cipher */
+ if ((mysql->options.ssl_cipher &&
+ mysql->options.ssl_cipher[0] != 0))
+ {
+ if(
+#ifdef TLS1_3_VERSION
+ SSL_CTX_set_ciphersuites(ctx, mysql->options.ssl_cipher) == 0 &&
+#endif
+ SSL_CTX_set_cipher_list(ctx, mysql->options.ssl_cipher) == 0)
+ goto error;
+ }
+
+ /* ca_file and ca_path */
+ if (!SSL_CTX_load_verify_locations(ctx,
+ mysql->options.ssl_ca,
+ mysql->options.ssl_capath))
+ {
+ if (mysql->options.ssl_ca || mysql->options.ssl_capath)
+ goto error;
+ if (SSL_CTX_set_default_verify_paths(ctx) == 0)
+ goto error;
+ }
+
+ if (mysql->options.extension &&
+ (mysql->options.extension->ssl_crl || mysql->options.extension->ssl_crlpath))
+ {
+ X509_STORE *certstore;
+
+ if ((certstore= SSL_CTX_get_cert_store(ctx)))
+ {
+ if (X509_STORE_load_locations(certstore, mysql->options.extension->ssl_crl,
+ mysql->options.extension->ssl_crlpath) == 0)
+ goto error;
+
+ if (X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL) == 0)
+ goto error;
+ }
+ }
+
+ if (keyfile && !certfile)
+ certfile= keyfile;
+ if (certfile && !keyfile)
+ keyfile= certfile;
+
+ /* set cert */
+ if (certfile && certfile[0] != 0)
+ {
+ if (SSL_CTX_use_certificate_chain_file(ctx, certfile) != 1)
+ {
+ goto error;
+ }
+ }
+
+ if (keyfile && keyfile[0])
+ {
+ FILE *fp;
+ if ((fp= fopen(keyfile, "rb")))
+ {
+ EVP_PKEY *key= EVP_PKEY_new();
+ PEM_read_PrivateKey(fp, &key, NULL, pw);
+ fclose(fp);
+ if (SSL_CTX_use_PrivateKey(ctx, key) != 1)
+ {
+ unsigned long err= ERR_peek_error();
+ EVP_PKEY_free(key);
+ if (!(ERR_GET_LIB(err) == ERR_LIB_X509 &&
+ ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE))
+ goto error;
+ }
+ EVP_PKEY_free(key);
+ } else {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ CER(CR_FILE_NOT_FOUND), keyfile);
+ return 1;
+ }
+ }
+ /* verify key */
+ if (certfile && SSL_CTX_check_private_key(ctx) != 1)
+ goto error;
+
+ SSL_CTX_set_verify(ctx, (mysql->options.ssl_ca || mysql->options.ssl_capath) ?
+ SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
+ return 0;
+
+error:
+ ma_tls_set_error(mysql);
+ return 1;
+}
+
+void *ma_tls_init(MYSQL *mysql)
+{
+ SSL *ssl= NULL;
+ SSL_CTX *ctx= NULL;
+ long default_options= SSL_OP_ALL |
+ SSL_OP_NO_SSLv2 |
+ SSL_OP_NO_SSLv3;
+ long options= 0;
+ pthread_mutex_lock(&LOCK_openssl_config);
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if (!(ctx= SSL_CTX_new(TLS_client_method())))
+#else
+ if (!(ctx= SSL_CTX_new(SSLv23_client_method())))
+#endif
+ goto error;
+ if (mysql->options.extension)
+ options= ma_tls_version_options(mysql->options.extension->tls_version);
+ SSL_CTX_set_options(ctx, options ? options : default_options);
+
+ if (ma_tls_set_certs(mysql, ctx))
+ {
+ goto error;
+ }
+
+ if (!(ssl= SSL_new(ctx)))
+ goto error;
+
+ if (!SSL_set_app_data(ssl, mysql))
+ goto error;
+
+ pthread_mutex_unlock(&LOCK_openssl_config);
+ return (void *)ssl;
+error:
+ pthread_mutex_unlock(&LOCK_openssl_config);
+ if (ctx)
+ SSL_CTX_free(ctx);
+ if (ssl)
+ SSL_free(ssl);
+ return NULL;
+}
+
+my_bool ma_tls_connect(MARIADB_TLS *ctls)
+{
+ SSL *ssl = (SSL *)ctls->ssl;
+ my_bool blocking, try_connect= 1;
+ MYSQL *mysql;
+ MARIADB_PVIO *pvio;
+ int rc;
+#ifdef OPENSSL_USE_BIOMETHOD
+ BIO_METHOD *bio_method= NULL;
+ BIO *bio;
+#endif
+
+ mysql= (MYSQL *)SSL_get_app_data(ssl);
+ pvio= mysql->net.pvio;
+
+ /* Set socket to non blocking if not already set */
+ if (!(blocking= pvio->methods->is_blocking(pvio)))
+ pvio->methods->blocking(pvio, FALSE, 0);
+
+ SSL_clear(ssl);
+
+#ifdef OPENSSL_USE_BIOMETHOD
+ bio= BIO_new(&ma_BIO_method);
+ bio->ptr= pvio;
+ SSL_set_bio(ssl, bio, bio);
+ BIO_set_fd(bio, mysql_get_socket(mysql), BIO_NOCLOSE);
+#else
+ SSL_set_fd(ssl, (int)mysql_get_socket(mysql));
+#endif
+
+ while (try_connect && (rc= SSL_connect(ssl)) == -1)
+ {
+ switch((SSL_get_error(ssl, rc))) {
+ case SSL_ERROR_WANT_READ:
+ if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.connect_timeout) < 1)
+ try_connect= 0;
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.connect_timeout) < 1)
+ try_connect= 0;
+ break;
+ default:
+ try_connect= 0;
+ }
+ }
+
+ /* In case handshake failed or if a root certificate (ca) was specified,
+ we need to check the result code of X509 verification. A detailed check
+ of the peer certificate (hostname checking will follow later) */
+ if (rc != 1 || mysql->options.extension->tls_verify_server_cert ||
+ mysql->options.ssl_ca || mysql->options.ssl_capath)
+ {
+ long x509_err= SSL_get_verify_result(ssl);
+ if (x509_err != X509_V_OK)
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(x509_err));
+ /* restore blocking mode */
+ if (!blocking)
+ pvio->methods->blocking(pvio, FALSE, 0);
+
+ return 1;
+ } else if (rc != 1) {
+ ma_tls_set_error(mysql);
+ return 1;
+ }
+ }
+ pvio->ctls->ssl= ctls->ssl= (void *)ssl;
+
+ return 0;
+}
+
+static my_bool
+ma_tls_async_check_result(int res, struct mysql_async_context *b, SSL *ssl)
+{
+ int ssl_err;
+ b->events_to_wait_for= 0;
+ if (res >= 0)
+ return 1;
+ ssl_err= SSL_get_error(ssl, res);
+ if (ssl_err == SSL_ERROR_WANT_READ)
+ b->events_to_wait_for|= MYSQL_WAIT_READ;
+ else if (ssl_err == SSL_ERROR_WANT_WRITE)
+ b->events_to_wait_for|= MYSQL_WAIT_WRITE;
+ else
+ return 1;
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
+ my_context_yield(&b->async_context);
+ if (b->suspend_resume_hook)
+ (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
+ return 0;
+}
+
+ssize_t ma_tls_read_async(MARIADB_PVIO *pvio,
+ const unsigned char *buffer,
+ size_t length)
+{
+ int res;
+ struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
+ MARIADB_TLS *ctls= pvio->ctls;
+
+ for (;;)
+ {
+ res= SSL_read((SSL *)ctls->ssl, (void *)buffer, (int)length);
+ if (ma_tls_async_check_result(res, b, (SSL *)ctls->ssl))
+ return res;
+ }
+}
+
+ssize_t ma_tls_write_async(MARIADB_PVIO *pvio,
+ const unsigned char *buffer,
+ size_t length)
+{
+ int res;
+ struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
+ MARIADB_TLS *ctls= pvio->ctls;
+
+ for (;;)
+ {
+ res= SSL_write((SSL *)ctls->ssl, (void *)buffer, (int)length);
+ if (ma_tls_async_check_result(res, b, (SSL *)ctls->ssl))
+ return res;
+ }
+}
+
+
+ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ int rc;
+ MARIADB_PVIO *pvio= ctls->pvio;
+
+ while ((rc= SSL_read((SSL *)ctls->ssl, (void *)buffer, (int)length)) <= 0)
+ {
+ int error= SSL_get_error((SSL *)ctls->ssl, rc);
+ if (error != SSL_ERROR_WANT_READ)
+ break;
+ if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1)
+ break;
+ }
+ if (rc <= 0)
+ {
+ MYSQL *mysql= SSL_get_app_data(ctls->ssl);
+ ma_tls_set_error(mysql);
+ }
+ return rc;
+}
+
+ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ int rc;
+ MARIADB_PVIO *pvio= ctls->pvio;
+
+ while ((rc= SSL_write((SSL *)ctls->ssl, (void *)buffer, (int)length)) <= 0)
+ {
+ int error= SSL_get_error((SSL *)ctls->ssl, rc);
+ if (error != SSL_ERROR_WANT_WRITE)
+ break;
+ if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1)
+ break;
+ }
+ if (rc <= 0)
+ {
+ MYSQL *mysql= SSL_get_app_data(ctls->ssl);
+ ma_tls_set_error(mysql);
+ }
+ return rc;
+}
+
+my_bool ma_tls_close(MARIADB_TLS *ctls)
+{
+ int i, rc;
+ SSL *ssl;
+ SSL_CTX *ctx= NULL;
+
+ if (!ctls || !ctls->ssl)
+ return 1;
+ ssl= (SSL *)ctls->ssl;
+ ctx= SSL_get_SSL_CTX(ssl);
+ if (ctx)
+ SSL_CTX_free(ctx);
+
+ SSL_set_quiet_shutdown(ssl, 1);
+ /* 2 x pending + 2 * data = 4 */
+ for (i=0; i < 4; i++)
+ if ((rc= SSL_shutdown(ssl)))
+ break;
+
+ /* Since we transferred ownership of BIO to ssl, BIO will
+ automatically freed - no need for an explicit BIO_free_all */
+
+ SSL_free(ssl);
+ ctls->ssl= NULL;
+
+ return rc;
+}
+
+int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
+{
+ X509 *cert;
+ MYSQL *mysql;
+ SSL *ssl;
+ MARIADB_PVIO *pvio;
+#if !defined(HAVE_OPENSSL_CHECK_HOST)
+ X509_NAME *x509sn;
+ int cn_pos;
+ X509_NAME_ENTRY *cn_entry;
+ ASN1_STRING *cn_asn1;
+ const char *cn_str;
+#endif
+ if (!ctls || !ctls->ssl)
+ return 1;
+ ssl= (SSL *)ctls->ssl;
+
+ mysql= (MYSQL *)SSL_get_app_data(ssl);
+ pvio= mysql->net.pvio;
+
+ if (!mysql->host)
+ {
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR), "Invalid (empty) hostname");
+ return 1;
+ }
+
+ if (!(cert= SSL_get_peer_certificate(ssl)))
+ {
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR), "Unable to get server certificate");
+ return 1;
+ }
+#ifdef HAVE_OPENSSL_CHECK_HOST
+ if (X509_check_host(cert, mysql->host, strlen(mysql->host), 0, 0) != 1
+ && X509_check_ip_asc(cert, mysql->host, 0) != 1)
+ goto error;
+#else
+ x509sn= X509_get_subject_name(cert);
+
+ if ((cn_pos= X509_NAME_get_index_by_NID(x509sn, NID_commonName, -1)) < 0)
+ goto error;
+
+ if (!(cn_entry= X509_NAME_get_entry(x509sn, cn_pos)))
+ goto error;
+
+ if (!(cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry)))
+ goto error;
+
+ cn_str = (char *)ASN1_STRING_data(cn_asn1);
+
+ /* Make sure there is no embedded \0 in the CN */
+ if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn_str))
+ goto error;
+
+ if (strcmp(cn_str, mysql->host))
+ goto error;
+#endif
+ X509_free(cert);
+
+ return 0;
+error:
+ X509_free(cert);
+
+ pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR), "Validation of SSL server certificate failed");
+ return 1;
+}
+
+const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
+{
+ if (!ctls || !ctls->ssl)
+ return NULL;
+ return SSL_get_cipher_name(ctls->ssl);
+}
+
+unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
+{
+ X509 *cert= NULL;
+ MYSQL *mysql;
+ unsigned int fp_len;
+
+ if (!ctls || !ctls->ssl)
+ return 0;
+
+ mysql= SSL_get_app_data(ctls->ssl);
+
+ if (!(cert= SSL_get_peer_certificate(ctls->ssl)))
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Unable to get server certificate");
+ goto end;
+ }
+
+ if (len < EVP_MAX_MD_SIZE)
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "Finger print buffer too small");
+ goto end;
+ }
+ if (!X509_digest(cert, EVP_sha1(), (unsigned char *)fp, &fp_len))
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "invalid finger print of server certificate");
+ goto end;
+ }
+
+ X509_free(cert);
+ return (fp_len);
+end:
+ X509_free(cert);
+ return 0;
+}
+
+
+int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
+{
+ if (!ctls || !ctls->ssl)
+ return -1;
+
+ return SSL_version(ctls->ssl) & 0xFF;
+}
+
+void ma_tls_set_connection(MYSQL *mysql)
+{
+ (void)SSL_set_app_data(mysql->net.pvio->ctls->ssl, mysql);
+}
+
diff --git a/libmariadb/libmariadb/secure/openssl_crypt.c b/libmariadb/libmariadb/secure/openssl_crypt.c
new file mode 100644
index 00000000..faf755c9
--- /dev/null
+++ b/libmariadb/libmariadb/secure/openssl_crypt.c
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*/
+#include <ma_global.h>
+#include <ma_crypt.h>
+#include <openssl/evp.h>
+
+static const EVP_MD *ma_hash_get_algorithm(unsigned int alg)
+{
+ switch(alg)
+ {
+ case MA_HASH_MD5:
+ return EVP_md5();
+ case MA_HASH_SHA1:
+ return EVP_sha1();
+ case MA_HASH_SHA224:
+ return EVP_sha224();
+ case MA_HASH_SHA256:
+ return EVP_sha256();
+ case MA_HASH_SHA384:
+ return EVP_sha384();
+ case MA_HASH_SHA512:
+ return EVP_sha512();
+ case MA_HASH_RIPEMD160:
+ return EVP_ripemd160();
+ default:
+ return NULL;
+ }
+}
+
+MA_HASH_CTX *ma_hash_new(unsigned int algorithm)
+{
+ EVP_MD_CTX *ctx= NULL;
+ const EVP_MD *evp_md= ma_hash_get_algorithm(algorithm);
+
+ /* unknown or unsupported hash algorithm */
+ if (!evp_md)
+ return NULL;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ if (!(ctx= EVP_MD_CTX_new()))
+#else
+ if (!(ctx= EVP_MD_CTX_create()))
+#endif
+ return NULL;
+ if (!EVP_DigestInit(ctx, evp_md))
+ {
+ ma_hash_free(ctx);
+ return NULL;
+ }
+ return ctx;
+}
+
+void ma_hash_free(MA_HASH_CTX *ctx)
+{
+ if (ctx)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ EVP_MD_CTX_free(ctx);
+#else
+ EVP_MD_CTX_destroy(ctx);
+#endif
+}
+
+void ma_hash_input(MA_HASH_CTX *ctx,
+ const unsigned char *buffer,
+ size_t len)
+{
+ EVP_DigestUpdate(ctx, buffer, len);
+}
+
+void ma_hash_result(MA_HASH_CTX *ctx, unsigned char *digest)
+{
+ EVP_DigestFinal_ex(ctx, digest, NULL);
+}
diff --git a/libmariadb/libmariadb/secure/schannel.c b/libmariadb/libmariadb/secure/schannel.c
new file mode 100644
index 00000000..8069af53
--- /dev/null
+++ b/libmariadb/libmariadb/secure/schannel.c
@@ -0,0 +1,567 @@
+/************************************************************************************
+ Copyright (C) 2014 MariaDB Corporation Ab
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ *************************************************************************************/
+#include "ma_schannel.h"
+#include "schannel_certs.h"
+#include <string.h>
+
+extern my_bool ma_tls_initialized;
+char tls_library_version[] = "Schannel";
+
+#define PROT_SSL3 1
+#define PROT_TLS1_0 2
+#define PROT_TLS1_2 4
+#define PROT_TLS1_3 8
+
+static struct
+{
+ DWORD cipher_id;
+ DWORD protocol;
+ const char *iana_name;
+ const char *openssl_name;
+ ALG_ID algs[4]; /* exchange, encryption, hash, signature */
+}
+cipher_map[] =
+{
+ {
+ 0x0002,
+ PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
+ "TLS_RSA_WITH_NULL_SHA", "NULL-SHA",
+ { CALG_RSA_KEYX, 0, CALG_SHA1, CALG_RSA_SIGN }
+ },
+ {
+ 0x0004,
+ PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
+ "TLS_RSA_WITH_RC4_128_MD5", "RC4-MD5",
+ { CALG_RSA_KEYX, CALG_RC4, CALG_MD5, CALG_RSA_SIGN }
+ },
+ {
+ 0x0005,
+ PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
+ "TLS_RSA_WITH_RC4_128_SHA", "RC4-SHA",
+ { CALG_RSA_KEYX, CALG_RC4, CALG_SHA1, CALG_RSA_SIGN }
+ },
+ {
+ 0x000A,
+ PROT_SSL3,
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "DES-CBC3-SHA",
+ {CALG_RSA_KEYX, CALG_3DES, CALG_SHA1, CALG_DSS_SIGN}
+ },
+ {
+ 0x0013,
+ PROT_TLS1_0 | PROT_TLS1_2 | PROT_SSL3,
+ "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "EDH-DSS-DES-CBC3-SHA",
+ { CALG_DH_EPHEM, CALG_3DES, CALG_SHA1, CALG_DSS_SIGN }
+ },
+ {
+ 0x002F,
+ PROT_SSL3 | PROT_TLS1_0 | PROT_TLS1_2,
+ "TLS_RSA_WITH_AES_128_CBC_SHA", "AES128-SHA",
+ { CALG_RSA_KEYX, CALG_AES_128, CALG_SHA, CALG_RSA_SIGN}
+ },
+ {
+ 0x0032,
+ PROT_TLS1_0 | PROT_TLS1_2,
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "DHE-DSS-AES128-SHA",
+ { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA1, CALG_RSA_SIGN }
+ },
+ {
+ 0x0033,
+ PROT_TLS1_0 | PROT_TLS1_2,
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "DHE-RSA-AES128-SHA",
+ { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA1, CALG_RSA_SIGN }
+ },
+ {
+ 0x0035,
+ PROT_TLS1_0 | PROT_TLS1_2,
+ "TLS_RSA_WITH_AES_256_CBC_SHA", "AES256-SHA",
+ { CALG_RSA_KEYX, CALG_AES_256, CALG_SHA1, CALG_RSA_SIGN }
+ },
+ {
+ 0x0038,
+ PROT_TLS1_0 | PROT_TLS1_2,
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "DHE-DSS-AES256-SHA",
+ { CALG_DH_EPHEM, CALG_AES_256, CALG_SHA1, CALG_DSS_SIGN }
+ },
+ {
+ 0x0039,
+ PROT_TLS1_0 | PROT_TLS1_2,
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "DHE-RSA-AES256-SHA",
+ { CALG_DH_EPHEM, CALG_AES_256, CALG_SHA1, CALG_RSA_SIGN }
+ },
+ {
+ 0x003B,
+ PROT_TLS1_2,
+ "TLS_RSA_WITH_NULL_SHA256", "NULL-SHA256",
+ { CALG_RSA_KEYX, 0, CALG_SHA_256, CALG_RSA_SIGN }
+ },
+ {
+ 0x003C,
+ PROT_TLS1_2,
+ "TLS_RSA_WITH_AES_128_CBC_SHA256", "AES128-SHA256",
+ { CALG_RSA_KEYX, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
+ },
+ {
+ 0x003D,
+ PROT_TLS1_2,
+ "TLS_RSA_WITH_AES_256_CBC_SHA256", "AES256-SHA256",
+ { CALG_RSA_KEYX, CALG_AES_256, CALG_SHA_256, CALG_RSA_SIGN }
+ },
+ {
+ 0x0040,
+ PROT_TLS1_2,
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "DHE-DSS-AES128-SHA256",
+ { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA_256, CALG_DSS_SIGN }
+ },
+ {
+ 0x009C,
+ PROT_TLS1_2,
+ "TLS_RSA_WITH_AES_128_GCM_SHA256", "AES128-GCM-SHA256",
+ { CALG_RSA_KEYX, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
+ },
+ {
+ 0x009D,
+ PROT_TLS1_2,
+ "TLS_RSA_WITH_AES_256_GCM_SHA384", "AES256-GCM-SHA384",
+ { CALG_RSA_KEYX, CALG_AES_256, CALG_SHA_384, CALG_RSA_SIGN }
+ },
+ {
+ 0x009E,
+ PROT_TLS1_2,
+ "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "DHE-RSA-AES128-GCM-SHA256",
+ { CALG_DH_EPHEM, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
+ },
+ {
+ 0x009F,
+ PROT_TLS1_2,
+ "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "DHE-RSA-AES256-GCM-SHA384",
+ { CALG_DH_EPHEM, CALG_AES_256, CALG_SHA_384, CALG_RSA_SIGN }
+ },
+ {
+ 0xC027,
+ PROT_TLS1_2,
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "ECDHE-RSA-AES128-SHA256",
+ { CALG_ECDH, CALG_AES_128, CALG_SHA_256, CALG_RSA_SIGN }
+ },
+ {
+ 0xC028,
+ PROT_TLS1_2,
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "ECDHE-RSA-AES256-SHA384",
+ { CALG_ECDH, CALG_AES_256, CALG_SHA_384, CALG_RSA_SIGN }
+ }
+};
+
+#define MAX_ALG_ID 50
+
+extern void ma_schannel_set_sec_error(MARIADB_PVIO *pvio, DWORD ErrorNo);
+
+/*
+ Initializes SSL and allocate global
+ context SSL_context
+
+ SYNOPSIS
+ ma_tls_start
+
+ RETURN VALUES
+ 0 success
+ 1 error
+*/
+int ma_tls_start(char *errmsg, size_t errmsg_len)
+{
+ ma_tls_initialized = TRUE;
+ return 0;
+}
+
+/*
+ Release SSL and free resources
+ Will be automatically executed by
+ mysql_server_end() function
+
+ SYNOPSIS
+ ma_tls_end()
+ void
+
+ RETURN VALUES
+ void
+*/
+void ma_tls_end()
+{
+ return;
+}
+
+/* {{{ static int ma_tls_set_client_certs(MARIADB_TLS *ctls) */
+static int ma_tls_set_client_certs(MARIADB_TLS *ctls,const CERT_CONTEXT **cert_ctx)
+{
+ MYSQL *mysql= ctls->pvio->mysql;
+ char *certfile= mysql->options.ssl_cert,
+ *keyfile= mysql->options.ssl_key;
+ MARIADB_PVIO *pvio= ctls->pvio;
+ char errmsg[256];
+
+ if (!certfile && keyfile)
+ certfile= keyfile;
+ if (!keyfile && certfile)
+ keyfile= certfile;
+
+ if (!certfile)
+ return 0;
+
+ *cert_ctx = schannel_create_cert_context(certfile, keyfile, errmsg, sizeof(errmsg));
+ if (!*cert_ctx)
+ {
+ pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, errmsg);
+ return 1;
+ }
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ void *ma_tls_init(MARIADB_TLS *ctls, MYSQL *mysql) */
+void *ma_tls_init(MYSQL *mysql)
+{
+ SC_CTX *sctx = (SC_CTX *)LocalAlloc(LMEM_ZEROINIT, sizeof(SC_CTX));
+ if (sctx)
+ {
+ SecInvalidateHandle(&sctx->CredHdl);
+ SecInvalidateHandle(&sctx->hCtxt);
+ }
+ return sctx;
+}
+/* }}} */
+
+
+/*
+ Maps between openssl suite names and schannel alg_ids.
+ Every suite has 4 algorithms (for exchange, encryption, hash and signing).
+
+ The input string is a set of suite names (openssl), separated
+ by ':'
+
+ The output is written into the array 'arr' of size 'arr_size'
+ The function returns number of elements written to the 'arr'.
+*/
+
+static struct _tls_version {
+ const char *tls_version;
+ DWORD protocol;
+} tls_version[]= {
+ {"TLSv1.0", PROT_TLS1_0},
+ {"TLSv1.2", PROT_TLS1_2},
+ {"TLSv1.3", PROT_TLS1_3},
+ {"SSLv3", PROT_SSL3}
+};
+
+/* The following list was produced with OpenSSL 1.1.1j
+ by executing `openssl ciphers -V`. */
+static struct {
+ DWORD dwCipherSuite;
+ const char *openssl_name;
+} openssl_ciphers[] = {
+ {0x002F, "AES128-SHA"},
+ {0x0033, "DHE-RSA-AES128-SHA"},
+ {0x0035, "AES256-SHA"},
+ {0x0039, "DHE-RSA-AES256-SHA"},
+ {0x003C, "AES128-SHA256"},
+ {0x003D, "AES256-SHA256"},
+ {0x0067, "DHE-RSA-AES128-SHA256"},
+ {0x006B, "DHE-RSA-AES256-SHA256"},
+ {0x008C, "PSK-AES128-CBC-SHA"},
+ {0x008D, "PSK-AES256-CBC-SHA"},
+ {0x0090, "DHE-PSK-AES128-CBC-SHA"},
+ {0x0091, "DHE-PSK-AES256-CBC-SHA"},
+ {0x0094, "RSA-PSK-AES128-CBC-SHA"},
+ {0x0095, "RSA-PSK-AES256-CBC-SHA"},
+ {0x009C, "AES128-GCM-SHA256"},
+ {0x009D, "AES256-GCM-SHA384"},
+ {0x009E, "DHE-RSA-AES128-GCM-SHA256"},
+ {0x009F, "DHE-RSA-AES256-GCM-SHA384"},
+ {0x00A8, "PSK-AES128-GCM-SHA256"},
+ {0x00A9, "PSK-AES256-GCM-SHA384"},
+ {0x00AA, "DHE-PSK-AES128-GCM-SHA256"},
+ {0x00AB, "DHE-PSK-AES256-GCM-SHA384"},
+ {0x00AC, "RSA-PSK-AES128-GCM-SHA256"},
+ {0x00AD, "RSA-PSK-AES256-GCM-SHA384"},
+ {0x00AE, "PSK-AES128-CBC-SHA256"},
+ {0x00AF, "PSK-AES256-CBC-SHA384"},
+ {0x00B2, "DHE-PSK-AES128-CBC-SHA256"},
+ {0x00B3, "DHE-PSK-AES256-CBC-SHA384"},
+ {0x00B6, "RSA-PSK-AES128-CBC-SHA256"},
+ {0x00B7, "RSA-PSK-AES256-CBC-SHA384"},
+ {0x1301, "TLS_AES_128_GCM_SHA256"},
+ {0x1302, "TLS_AES_256_GCM_SHA384"},
+ {0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
+ {0xC009, "ECDHE-ECDSA-AES128-SHA"},
+ {0xC00A, "ECDHE-ECDSA-AES256-SHA"},
+ {0xC013, "ECDHE-RSA-AES128-SHA"},
+ {0xC014, "ECDHE-RSA-AES256-SHA"},
+ {0xC01D, "SRP-AES-128-CBC-SHA"},
+ {0xC01E, "SRP-RSA-AES-128-CBC-SHA"},
+ {0xC020, "SRP-AES-256-CBC-SHA"},
+ {0xC021, "SRP-RSA-AES-256-CBC-SHA"},
+ {0xC023, "ECDHE-ECDSA-AES128-SHA256"},
+ {0xC024, "ECDHE-ECDSA-AES256-SHA384"},
+ {0xC027, "ECDHE-RSA-AES128-SHA256"},
+ {0xC028, "ECDHE-RSA-AES256-SHA384"},
+ {0xC02B, "ECDHE-ECDSA-AES128-GCM-SHA256"},
+ {0xC02C, "ECDHE-ECDSA-AES256-GCM-SHA384"},
+ {0xC02F, "ECDHE-RSA-AES128-GCM-SHA256"},
+ {0xC030, "ECDHE-RSA-AES256-GCM-SHA384"},
+ {0xC035, "ECDHE-PSK-AES128-CBC-SHA"},
+ {0xC036, "ECDHE-PSK-AES256-CBC-SHA"},
+ {0xC037, "ECDHE-PSK-AES128-CBC-SHA256"},
+ {0xC038, "ECDHE-PSK-AES256-CBC-SHA384"},
+ {0xCCA8, "ECDHE-RSA-CHACHA20-POLY1305"},
+ {0xCCA9, "ECDHE-ECDSA-CHACHA20-POLY1305"},
+ {0xCCAA, "DHE-RSA-CHACHA20-POLY1305"},
+ {0xCCAB, "PSK-CHACHA20-POLY1305"},
+ {0xCCAC, "ECDHE-PSK-CHACHA20-POLY1305"},
+ {0xCCAD, "DHE-PSK-CHACHA20-POLY1305"},
+ {0xCCAE, "RSA-PSK-CHACHA20-POLY1305"}
+};
+
+static size_t set_cipher(char * cipher_str, DWORD protocol, ALG_ID *arr , size_t arr_size)
+{
+ char *token = strtok(cipher_str, ":");
+ size_t pos = 0;
+
+ while (token)
+ {
+ size_t i;
+
+ for(i = 0; i < sizeof(cipher_map)/sizeof(cipher_map[0]) ; i++)
+ {
+ if((pos + 4 < arr_size && strcmp(cipher_map[i].openssl_name, token) == 0) ||
+ (cipher_map[i].protocol <= protocol))
+ {
+ memcpy(arr + pos, cipher_map[i].algs, sizeof(ALG_ID)* 4);
+ pos += 4;
+ break;
+ }
+ }
+ token = strtok(NULL, ":");
+ }
+ return pos;
+}
+
+my_bool ma_tls_connect(MARIADB_TLS *ctls)
+{
+ MYSQL *mysql;
+ SCHANNEL_CRED Cred = {0};
+ MARIADB_PVIO *pvio;
+ my_bool rc= 1;
+ SC_CTX *sctx;
+ SECURITY_STATUS sRet;
+ ALG_ID AlgId[MAX_ALG_ID];
+ size_t i;
+ DWORD protocol = 0;
+ int verify_certs;
+ const CERT_CONTEXT* cert_context = NULL;
+
+ if (!ctls)
+ return 1;
+
+ pvio= ctls->pvio;
+ sctx= (SC_CTX *)ctls->ssl;
+ if (!pvio || !sctx)
+ return 1;
+
+ mysql= pvio->mysql;
+ if (!mysql)
+ return 1;
+
+ /* Set cipher */
+ if (mysql->options.ssl_cipher)
+ {
+
+ /* check if a protocol was specified as a cipher:
+ * In this case don't allow cipher suites which belong to newer protocols
+ * Please note: There are no cipher suites for TLS1.1
+ */
+ for (i = 0; i < sizeof(tls_version) / sizeof(tls_version[0]); i++)
+ {
+ if (!_stricmp(mysql->options.ssl_cipher, tls_version[i].tls_version))
+ protocol |= tls_version[i].protocol;
+ }
+ memset(AlgId, 0, sizeof(AlgId));
+ Cred.cSupportedAlgs = (DWORD)set_cipher(mysql->options.ssl_cipher, protocol, AlgId, MAX_ALG_ID);
+ if (Cred.cSupportedAlgs)
+ {
+ Cred.palgSupportedAlgs = AlgId;
+ }
+ else if (!protocol)
+ {
+ ma_schannel_set_sec_error(pvio, SEC_E_ALGORITHM_MISMATCH);
+ goto end;
+ }
+ }
+
+ Cred.dwVersion= SCHANNEL_CRED_VERSION;
+
+ Cred.dwFlags = SCH_CRED_NO_SERVERNAME_CHECK | SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION;
+
+ if (mysql->options.extension && mysql->options.extension->tls_version)
+ {
+ if (strstr(mysql->options.extension->tls_version, "TLSv1.0"))
+ Cred.grbitEnabledProtocols|= SP_PROT_TLS1_0_CLIENT;
+ if (strstr(mysql->options.extension->tls_version, "TLSv1.1"))
+ Cred.grbitEnabledProtocols|= SP_PROT_TLS1_1_CLIENT;
+ if (strstr(mysql->options.extension->tls_version, "TLSv1.2"))
+ Cred.grbitEnabledProtocols|= SP_PROT_TLS1_2_CLIENT;
+ }
+ if (!Cred.grbitEnabledProtocols)
+ Cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
+
+
+ if (ma_tls_set_client_certs(ctls, &cert_context))
+ goto end;
+
+ if (cert_context)
+ {
+ Cred.cCreds = 1;
+ Cred.paCred = &cert_context;
+ }
+ sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
+ NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL);
+ if (sRet)
+ {
+ ma_schannel_set_sec_error(pvio, sRet);
+ goto end;
+ }
+ if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
+ goto end;
+
+ verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath ||
+ (mysql->options.extension->tls_verify_server_cert);
+
+ if (verify_certs)
+ {
+ if (!ma_schannel_verify_certs(ctls, mysql->options.extension->tls_verify_server_cert))
+ goto end;
+ }
+
+ rc = 0;
+
+end:
+ if (cert_context)
+ schannel_free_cert_context(cert_context);
+ return rc;
+}
+
+ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ SC_CTX *sctx= (SC_CTX *)ctls->ssl;
+ MARIADB_PVIO *pvio= ctls->pvio;
+ DWORD dlength= 0;
+ SECURITY_STATUS status = ma_schannel_read_decrypt(pvio, &sctx->hCtxt, &dlength, (uchar *)buffer, (DWORD)length);
+ if (status == SEC_I_CONTEXT_EXPIRED)
+ return 0; /* other side shut down the connection. */
+ if (status == SEC_I_RENEGOTIATE)
+ return -1; /* Do not handle renegotiate yet */
+
+ return (status == SEC_E_OK)? (ssize_t)dlength : -1;
+}
+
+ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
+{
+ MARIADB_PVIO *pvio= ctls->pvio;
+ ssize_t rc, wlength= 0;
+ ssize_t remain= length;
+
+ while (remain > 0)
+ {
+ if ((rc= ma_schannel_write_encrypt(pvio, (uchar *)buffer + wlength, remain)) <= 0)
+ return rc;
+ wlength+= rc;
+ remain-= rc;
+ }
+ return length;
+}
+
+/* {{{ my_bool ma_tls_close(MARIADB_PVIO *pvio) */
+my_bool ma_tls_close(MARIADB_TLS *ctls)
+{
+ SC_CTX *sctx= (SC_CTX *)ctls->ssl;
+
+ if (sctx)
+ {
+ LocalFree(sctx->IoBuffer);
+
+ if (SecIsValidHandle(&sctx->CredHdl))
+ FreeCredentialHandle(&sctx->CredHdl);
+
+ if (SecIsValidHandle(&sctx->hCtxt))
+ DeleteSecurityContext(&sctx->hCtxt);
+ }
+ LocalFree(sctx);
+ return 0;
+}
+/* }}} */
+
+int ma_tls_verify_server_cert(MARIADB_TLS *ctls)
+{
+ /* Done elsewhere */
+ return 0;
+}
+
+static const char *cipher_name(const SecPkgContext_CipherInfo *CipherInfo)
+{
+ size_t i;
+
+ for(i = 0; i < sizeof(openssl_ciphers)/sizeof(openssl_ciphers[0]) ; i++)
+ {
+ if (CipherInfo->dwCipherSuite == openssl_ciphers[i].dwCipherSuite)
+ return openssl_ciphers[i].openssl_name;
+ }
+ return "";
+};
+
+const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
+{
+ SecPkgContext_CipherInfo CipherInfo = { SECPKGCONTEXT_CIPHERINFO_V1 };
+ SECURITY_STATUS sRet;
+ SC_CTX *sctx;
+
+ if (!ctls || !ctls->ssl)
+ return NULL;
+
+ sctx= (SC_CTX *)ctls->ssl;
+ sRet= QueryContextAttributesA(&sctx->hCtxt, SECPKG_ATTR_CIPHER_INFO, (PVOID)&CipherInfo);
+
+ if (sRet != SEC_E_OK)
+ return NULL;
+
+ return cipher_name(&CipherInfo);
+}
+
+unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
+{
+ SC_CTX *sctx= (SC_CTX *)ctls->ssl;
+ PCCERT_CONTEXT pRemoteCertContext = NULL;
+ if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext) != SEC_E_OK)
+ return 0;
+ CertGetCertificateContextProperty(pRemoteCertContext, CERT_HASH_PROP_ID, fp, (DWORD *)&len);
+ CertFreeCertificateContext(pRemoteCertContext);
+ return len;
+}
+
+void ma_tls_set_connection(MYSQL *mysql __attribute__((unused)))
+{
+ return;
+}
diff --git a/libmariadb/libmariadb/secure/schannel_certs.c b/libmariadb/libmariadb/secure/schannel_certs.c
new file mode 100644
index 00000000..c8ff3753
--- /dev/null
+++ b/libmariadb/libmariadb/secure/schannel_certs.c
@@ -0,0 +1,852 @@
+/************************************************************************************
+ Copyright (C) 2019 MariaDB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ *************************************************************************************/
+
+ /*
+ This module contain X509 certificate handling on Windows.
+ PEM parsing, loading client certificate and key, server certificate validation
+ */
+
+ /*
+ CERT_CHAIN_ENGINE_CONFIG has additional members in Windows 8.1
+ To allow client to be work on pre-8.1 Windows, compile
+ with corresponding _WIN32_WINNT
+ */
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0601
+#endif
+#include "schannel_certs.h"
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <winhttp.h>
+#include <limits.h>
+#include <assert.h>
+#include "win32_errmsg.h"
+
+ /*
+ Return GetLastError(), or, if this unexpectedly gives success,
+ return ERROR_INTERNAL_ERROR.
+
+ Background - in several cases in this module we return GetLastError()
+ after an Windows function fails. However, we do not want the function to
+ return success, even if GetLastError() was suddenly 0.
+ */
+static DWORD get_last_error()
+{
+ DWORD ret = GetLastError();
+ if (ret)
+ return ret;
+
+ // We generally expect last error to be set API fails.
+ // thus the debug assertion-
+ assert(0);
+ return ERROR_INTERNAL_ERROR;
+}
+
+#define FAIL(...) \
+ do{\
+ status = get_last_error();\
+ ma_format_win32_error(errmsg, errmsg_len, status, __VA_ARGS__);\
+ goto cleanup;\
+ } while (0)
+
+/*
+ Load file into memory. Add null terminator at the end, so it will be a valid C string.
+*/
+static char* pem_file_to_string(const char* file, char* errmsg, size_t errmsg_len)
+{
+ LARGE_INTEGER file_size;
+ size_t file_bufsize = 0;
+ size_t total_bytes_read = 0;
+ char* file_buffer = NULL;
+ SECURITY_STATUS status = SEC_E_OK;
+
+ HANDLE file_handle = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file_handle == INVALID_HANDLE_VALUE)
+ {
+ FAIL("failed to open file '%s'", file);
+ }
+
+ if (!GetFileSizeEx(file_handle, &file_size))
+ {
+ FAIL("GetFileSizeEx failed on '%s'", file);
+ }
+
+ if (file_size.QuadPart > ULONG_MAX - 1)
+ {
+ SetLastError(SEC_E_INVALID_PARAMETER);
+ FAIL("file '%s' too large", file);
+ }
+
+ file_bufsize = (size_t)file_size.QuadPart;
+ file_buffer = (char*)LocalAlloc(0,file_bufsize + 1);
+ if (!file_buffer)
+ {
+ FAIL("LocalAlloc(0,%zu) failed", file_bufsize + 1);
+ }
+
+ while (total_bytes_read < file_bufsize)
+ {
+ DWORD bytes_to_read = (DWORD)(file_bufsize - total_bytes_read);
+ DWORD bytes_read = 0;
+
+ if (!ReadFile(file_handle, file_buffer + total_bytes_read,
+ bytes_to_read, &bytes_read, NULL))
+ {
+ FAIL("ReadFile() failed to read file '%s'", file);
+ }
+ if (bytes_read == 0)
+ {
+ /* Premature EOF -- adjust the bufsize to the new value */
+ file_bufsize = total_bytes_read;
+ }
+ else
+ {
+ total_bytes_read += bytes_read;
+ }
+ }
+
+ /* Null terminate the buffer */
+ file_buffer[file_bufsize] = '\0';
+
+cleanup:
+ if (file_handle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(file_handle);
+ }
+ if (status)
+ {
+ /* Some error happened. */
+ LocalFree(file_buffer);
+ file_buffer = NULL;
+ }
+ return file_buffer;
+}
+
+
+// Structure for parsing BEGIN/END sections inside pem.
+typedef struct _pem_type_desc
+{
+ const char* begin_tag;
+ size_t begin_tag_len;
+ const char* end_tag;
+ size_t end_tag_len;
+} pem_type_desc;
+
+#define BEGIN_TAG(x) "-----BEGIN " x "-----"
+#define END_TAG(x) "\n-----END " x "-----"
+#define PEM_SECTION(tag) {BEGIN_TAG(tag), sizeof(BEGIN_TAG(tag))-1, END_TAG(tag), sizeof(END_TAG(tag))-1}
+
+typedef enum {
+ PEM_TYPE_CERTIFICATE = 0,
+ PEM_TYPE_X509_CRL,
+ PEM_TYPE_RSA_PRIVATE_KEY,
+ PEM_TYPE_PRIVATE_KEY
+} PEM_TYPE;
+
+static const pem_type_desc pem_sections[] = {
+ PEM_SECTION("CERTIFICATE"),
+ PEM_SECTION("X509 CRL"),
+ PEM_SECTION("RSA PRIVATE KEY"),
+ PEM_SECTION("PRIVATE KEY")
+};
+
+/*
+ Locate a substring in pem for given type,
+ e.g section between BEGIN CERTIFICATE and END CERTIFICATE
+ in PEMs base64 format, with header and footer.
+
+ output parameters 'begin' and 'end' are set upon return.
+ it is possible that functions returns 'begin' != NULL but
+ 'end' = NULL. This is generally a format error, meaning that
+ the end tag was not found
+*/
+void pem_locate(char* pem_str,
+ PEM_TYPE type,
+ char** begin,
+ char** end)
+{
+ *begin = NULL;
+ *end = NULL;
+ char c;
+
+ const pem_type_desc* desc = &pem_sections[type];
+ *begin = strstr(pem_str, desc->begin_tag);
+ if (!(*begin))
+ return;
+
+ // We expect newline after the
+ // begin tag, LF or CRLF
+ c = (*begin)[desc->begin_tag_len];
+
+ if (c != '\r' && c != '\n')
+ {
+ *begin = NULL;
+ return;
+ }
+
+ *end = strstr(*begin + desc->begin_tag_len + 1, desc->end_tag);
+ if (!*end)
+ return; // error, end marker not found
+
+ (*end) += desc->end_tag_len;
+ return;
+}
+
+
+/*
+ Add certificates, or CRLs from a PEM file to Wincrypt store
+*/
+static SECURITY_STATUS add_certs_to_store(
+ HCERTSTORE trust_store,
+ const char* file,
+ PEM_TYPE type,
+ char* errmsg,
+ size_t errmsg_len)
+{
+ char* file_buffer = NULL;
+ char* cur = NULL;
+ SECURITY_STATUS status = SEC_E_OK;
+ CRL_CONTEXT* crl_context = NULL;
+ CERT_CONTEXT* cert_context = NULL;
+ char* begin;
+ char* end;
+
+ file_buffer = pem_file_to_string(file, errmsg, errmsg_len);
+ if (!file_buffer)
+ goto cleanup;
+
+ for (cur = file_buffer; ; cur = end)
+ {
+ pem_locate(cur, type, &begin, &end);
+
+ if (!begin)
+ break;
+
+ if (!end)
+ {
+ SetLastError(SEC_E_INVALID_PARAMETER);
+ FAIL("Invalid PEM file '%s', missing end marker corresponding to begin marker '%s' at offset %zu",
+ file, pem_sections[type].begin_tag, (size_t)(begin - file_buffer));
+ }
+ CERT_BLOB cert_blob;
+ void* context = NULL;
+ DWORD actual_content_type = 0;
+
+ cert_blob.pbData = (BYTE*)begin;
+ cert_blob.cbData = (DWORD)(end - begin);
+ if (!CryptQueryObject(
+ CERT_QUERY_OBJECT_BLOB, &cert_blob,
+ CERT_QUERY_CONTENT_FLAG_CERT | CERT_QUERY_CONTENT_FLAG_CRL,
+ CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type,
+ NULL, NULL, NULL, (const void**)&context))
+ {
+ FAIL("failed to extract certificate from PEM file '%s'",file);
+ }
+
+ if (!context)
+ {
+ SetLastError(SEC_E_INTERNAL_ERROR);
+ FAIL("unexpected result from CryptQueryObject(),cert_context is NULL"
+ " after successful completion, file '%s'",
+ file);
+ }
+
+ if (actual_content_type == CERT_QUERY_CONTENT_CERT)
+ {
+ CERT_CONTEXT* cert_context = (CERT_CONTEXT*)context;
+ if (!CertAddCertificateContextToStore(
+ trust_store, cert_context,
+ CERT_STORE_ADD_ALWAYS, NULL))
+ {
+ FAIL("CertAddCertificateContextToStore failed");
+ }
+ }
+ else if (actual_content_type == CERT_QUERY_CONTENT_CRL)
+ {
+ CRL_CONTEXT* crl_context = (CRL_CONTEXT*)context;
+ if (!CertAddCRLContextToStore(
+ trust_store, crl_context,
+ CERT_STORE_ADD_ALWAYS, NULL))
+ {
+ FAIL("CertAddCRLContextToStore() failed");
+ }
+ }
+ }
+cleanup:
+ LocalFree(file_buffer);
+ if (cert_context)
+ CertFreeCertificateContext(cert_context);
+ if (crl_context)
+ CertFreeCRLContext(crl_context);
+ return status;
+}
+
+/*
+Add a directory to store, i.e try to load all files.
+(extract certificates and add them to store)
+
+@return 0 on success, error only if directory is invalid.
+*/
+SECURITY_STATUS add_dir_to_store(HCERTSTORE trust_store, const char* dir,
+ PEM_TYPE type, char* errmsg, size_t errmsg_len)
+{
+ WIN32_FIND_DATAA ffd;
+ char path[MAX_PATH];
+ char pattern[MAX_PATH];
+ DWORD dwAttr;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ SECURITY_STATUS status = SEC_E_OK;
+
+ if ((dwAttr = GetFileAttributes(dir)) == INVALID_FILE_ATTRIBUTES)
+ {
+ SetLastError(SEC_E_INVALID_PARAMETER);
+ FAIL("directory '%s' does not exist", dir);
+ }
+ if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ SetLastError(SEC_E_INVALID_PARAMETER);
+ FAIL("'%s' is not a directory", dir);
+ }
+ sprintf_s(pattern, sizeof(pattern), "%s\\*", dir);
+ hFind = FindFirstFile(pattern, &ffd);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ FAIL("FindFirstFile(%s) failed",pattern);
+ }
+ do
+ {
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+ sprintf_s(path, sizeof(path), "%s\\%s", dir, ffd.cFileName);
+
+ // ignore error from add_certs_to_store(), not all file
+ // maybe PEM.
+ add_certs_to_store(trust_store, path, type, errmsg,
+ errmsg_len);
+ } while (FindNextFile(hFind, &ffd) != 0);
+
+cleanup:
+ if (hFind != INVALID_HANDLE_VALUE)
+ FindClose(hFind);
+
+ return status;
+}
+
+/* Count certificates in store. */
+static int count_certificates(HCERTSTORE store)
+{
+ int num_certs = 0;
+ PCCERT_CONTEXT c = NULL;
+
+ while ((c = CertEnumCertificatesInStore(store, c)))
+ num_certs++;
+
+ return num_certs;
+}
+
+/**
+ Creates certificate store with user defined CA chain and/or CRL.
+ Loads PEM certificate from files or directories.
+
+ If only CRLFile/CRLPath is defined, the "system" store is duplicated,
+ and new CRLs are added to it.
+
+ If CAFile/CAPAth is defined, then new empty store is created, and CAs
+ (and CRLs, if defined), are added to it.
+
+ The function throws an error, if none of the files in CAFile/CAPath have a valid certificate.
+ It is also an error if CRLFile does not exist.
+*/
+SECURITY_STATUS schannel_create_store(
+ const char* CAFile,
+ const char* CAPath,
+ const char* CRLFile,
+ const char* CRLPath,
+ HCERTSTORE* out_store,
+ char* errmsg,
+ size_t errmsg_len)
+{
+
+ HCERTSTORE store = NULL;
+ HCERTSTORE system_store = NULL;
+ int status = SEC_E_OK;
+
+ *out_store = NULL;
+ if (!CAFile && !CAPath && !CRLFile && !CRLPath)
+ {
+ /* Nothing to do, caller will use default store*/
+ *out_store = NULL;
+ return SEC_E_OK;
+ }
+ if (CAFile || CAPath)
+ {
+ /* Open the certificate store */
+ store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, (HCRYPTPROV)NULL,
+ CERT_STORE_CREATE_NEW_FLAG, NULL);
+ if (!store)
+ {
+ FAIL("CertOpenStore failed for memory store");
+ }
+ }
+ else if (CRLFile || CRLPath)
+ {
+ /* Only CRL was provided, copy system store, add revocation list to
+ * it. */
+ system_store =
+ CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, (HCRYPTPROV_LEGACY)NULL,
+ CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
+ if (!system_store)
+ {
+ FAIL("CertOpenStore failed for system store");
+ }
+
+ store = CertDuplicateStore(system_store);
+ if (!store)
+ {
+ FAIL("CertDuplicateStore failed");
+ }
+ }
+
+ if (CAFile)
+ {
+ status = add_certs_to_store(store, CAFile,
+ PEM_TYPE_CERTIFICATE, errmsg, errmsg_len);
+ if (status)
+ goto cleanup;
+ }
+ if (CAPath)
+ {
+ status = add_dir_to_store(store, CAPath,
+ PEM_TYPE_CERTIFICATE, errmsg, errmsg_len);
+ if (status)
+ goto cleanup;
+ }
+
+ if ((CAFile || CAPath) && store && !count_certificates(store))
+ {
+ SetLastError(SEC_E_INVALID_PARAMETER);
+ FAIL("no valid certificates were found, CAFile='%s', CAPath='%s'",
+ CAFile ? CAFile : "<not set>", CAPath ? CAPath : "<not set>");
+ }
+
+ if (CRLFile)
+ {
+ status = add_certs_to_store(store, CRLFile, PEM_TYPE_X509_CRL,
+ errmsg, errmsg_len);
+ }
+ if (CRLPath)
+ {
+ status = add_dir_to_store(store, CRLPath, PEM_TYPE_X509_CRL,
+ errmsg, errmsg_len);
+ }
+
+cleanup:
+ if (system_store)
+ CertCloseStore(system_store, 0);
+ if (status && store)
+ {
+ CertCloseStore(store, 0);
+ store = NULL;
+ }
+ *out_store = store;
+ return status;
+}
+
+/*
+ The main verification logic.
+ Taken almost completely from Windows 2003 Platform SDK 2003
+ (Samples\Security\SSPI\SSL\WebClient.c)
+
+ The only difference here is is usage of custom store
+ and chain engine.
+*/
+static SECURITY_STATUS VerifyServerCertificate(
+ PCCERT_CONTEXT pServerCert,
+ HCERTSTORE hStore,
+ LPWSTR pwszServerName,
+ DWORD dwRevocationCheckFlags,
+ DWORD dwVerifyFlags,
+ LPSTR errmsg,
+ size_t errmsg_len)
+{
+ SSL_EXTRA_CERT_CHAIN_POLICY_PARA polExtra;
+ CERT_CHAIN_POLICY_PARA PolicyPara;
+ CERT_CHAIN_POLICY_STATUS PolicyStatus;
+ CERT_CHAIN_PARA ChainPara;
+ HCERTCHAINENGINE hChainEngine = NULL;
+ PCCERT_CHAIN_CONTEXT pChainContext = NULL;
+ LPSTR rgszUsages[] = { szOID_PKIX_KP_SERVER_AUTH,
+ szOID_SERVER_GATED_CRYPTO,
+ szOID_SGC_NETSCAPE };
+ DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR);
+ SECURITY_STATUS status = SEC_E_OK;
+
+ if (pServerCert == NULL)
+ {
+ SetLastError(SEC_E_WRONG_PRINCIPAL);
+ FAIL("Invalid parameter pServerCert passed to VerifyServerCertificate");
+ }
+
+ ZeroMemory(&ChainPara, sizeof(ChainPara));
+ ChainPara.cbSize = sizeof(ChainPara);
+ ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
+ ChainPara.RequestedUsage.Usage.cUsageIdentifier = cUsages;
+ ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages;
+
+ if (hStore)
+ {
+ CERT_CHAIN_ENGINE_CONFIG EngineConfig = { 0 };
+ EngineConfig.cbSize = sizeof(EngineConfig);
+ EngineConfig.hExclusiveRoot = hStore;
+ if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
+ {
+ FAIL("CertCreateCertificateChainEngine failed");
+ }
+ }
+
+ if (!CertGetCertificateChain(
+ hChainEngine,
+ pServerCert,
+ NULL,
+ pServerCert->hCertStore,
+ &ChainPara,
+ dwRevocationCheckFlags,
+ NULL,
+ &pChainContext))
+ {
+ FAIL("CertGetCertificateChain failed");
+ goto cleanup;
+ }
+
+ // Validate certificate chain.
+ ZeroMemory(&polExtra, sizeof(SSL_EXTRA_CERT_CHAIN_POLICY_PARA));
+ polExtra.cbStruct = sizeof(SSL_EXTRA_CERT_CHAIN_POLICY_PARA);
+ polExtra.dwAuthType = AUTHTYPE_SERVER;
+ polExtra.fdwChecks = dwVerifyFlags;
+ polExtra.pwszServerName = pwszServerName;
+
+ memset(&PolicyPara, 0, sizeof(PolicyPara));
+ PolicyPara.cbSize = sizeof(PolicyPara);
+ PolicyPara.pvExtraPolicyPara = &polExtra;
+
+ memset(&PolicyStatus, 0, sizeof(PolicyStatus));
+ PolicyStatus.cbSize = sizeof(PolicyStatus);
+
+ if (!CertVerifyCertificateChainPolicy(
+ CERT_CHAIN_POLICY_SSL,
+ pChainContext,
+ &PolicyPara,
+ &PolicyStatus))
+ {
+ FAIL("CertVerifyCertificateChainPolicy failed");
+ }
+
+ if (PolicyStatus.dwError)
+ {
+ SetLastError(PolicyStatus.dwError);
+ FAIL("Server certificate validation failed");
+ }
+
+cleanup:
+ if (hChainEngine)
+ {
+ CertFreeCertificateChainEngine(hChainEngine);
+ }
+ if (pChainContext)
+ {
+ CertFreeCertificateChain(pChainContext);
+ }
+ return status;
+}
+
+
+void schannel_free_store(HCERTSTORE store)
+{
+ if (store)
+ CertCloseStore(store, 0);
+}
+
+
+/*
+Verify server certificate against a wincrypt store
+@return 0 - success, otherwise error occurred.
+*/
+SECURITY_STATUS schannel_verify_server_certificate(
+ const CERT_CONTEXT* cert,
+ HCERTSTORE store,
+ BOOL check_revocation,
+ const char* server_name,
+ BOOL check_server_name,
+ char* errmsg,
+ size_t errmsg_len)
+{
+ SECURITY_STATUS status = SEC_E_OK;
+ wchar_t* wserver_name = NULL;
+ DWORD dwVerifyFlags;
+ DWORD dwRevocationFlags;
+
+ if (check_server_name)
+ {
+ int cchServerName = (int)strlen(server_name) + 1;
+ wserver_name = (wchar_t*)LocalAlloc(0,sizeof(wchar_t) * cchServerName);
+ if (!wserver_name)
+ {
+ FAIL("LocalAlloc() failed");
+ }
+ if (MultiByteToWideChar(CP_UTF8, 0, server_name, cchServerName, wserver_name, cchServerName) < 0)
+ {
+ FAIL("MultiByteToWideChar() failed");
+ }
+ }
+
+ dwVerifyFlags = 0;
+ dwRevocationFlags = 0;
+ if (check_revocation)
+ dwRevocationFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT | CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
+ if (!check_server_name)
+ dwVerifyFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+
+ status = VerifyServerCertificate(cert, store, wserver_name ? wserver_name : L"SERVER_NAME",
+ dwRevocationFlags, dwVerifyFlags, errmsg, errmsg_len);
+
+cleanup:
+ LocalFree(wserver_name);
+ return status;
+}
+
+
+/* Attach private key (in PEM format) to client certificate */
+static SECURITY_STATUS load_private_key(CERT_CONTEXT* cert, char* private_key_str, size_t len, char* errmsg, size_t errmsg_len)
+{
+ DWORD derlen = (DWORD)len;
+ BYTE* derbuf = NULL;
+ DWORD keyblob_len = 0;
+ BYTE* keyblob = NULL;
+ HCRYPTPROV hProv = 0;
+ HCRYPTKEY hKey = 0;
+ CERT_KEY_CONTEXT cert_key_context = { 0 };
+ PCRYPT_PRIVATE_KEY_INFO pki = NULL;
+ DWORD pki_len = 0;
+ SECURITY_STATUS status = SEC_E_OK;
+
+ derbuf = LocalAlloc(0, derlen);
+ if (!derbuf)
+ {
+ FAIL("LocalAlloc failed");
+ }
+
+ if (!CryptStringToBinaryA(private_key_str, (DWORD)len, CRYPT_STRING_BASE64HEADER, derbuf, &derlen, NULL, NULL))
+ {
+ FAIL("Failed to convert BASE64 private key");
+ }
+
+ /*
+ To accommodate for both "BEGIN PRIVATE KEY" vs "BEGIN RSA PRIVATE KEY"
+ sections in PEM, we try to decode with PKCS_PRIVATE_KEY_INFO first,
+ and, if it fails, with PKCS_RSA_PRIVATE_KEY flag.
+ */
+ if (CryptDecodeObjectEx(
+ X509_ASN_ENCODING,
+ PKCS_PRIVATE_KEY_INFO,
+ derbuf, derlen,
+ CRYPT_DECODE_ALLOC_FLAG,
+ NULL, &pki, &pki_len))
+ {
+ // convert private key info to RSA private key blob
+ if (!CryptDecodeObjectEx(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ PKCS_RSA_PRIVATE_KEY,
+ pki->PrivateKey.pbData,
+ pki->PrivateKey.cbData,
+ CRYPT_DECODE_ALLOC_FLAG,
+ NULL, &keyblob, &keyblob_len))
+ {
+ FAIL("Failed to parse private key");
+ }
+ }
+ else if (!CryptDecodeObjectEx(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ PKCS_RSA_PRIVATE_KEY,
+ derbuf, derlen,
+ CRYPT_DECODE_ALLOC_FLAG, NULL,
+ &keyblob, &keyblob_len))
+ {
+ FAIL("Failed to parse private key");
+ }
+
+ if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ FAIL("CryptAcquireContext failed");
+ }
+
+ if (!CryptImportKey(hProv, keyblob, keyblob_len, 0, 0, (HCRYPTKEY*)&hKey))
+ {
+ FAIL("CryptImportKey failed");
+ }
+ cert_key_context.hCryptProv = hProv;
+ cert_key_context.dwKeySpec = AT_KEYEXCHANGE;
+ cert_key_context.cbSize = sizeof(cert_key_context);
+
+ /* assign private key to certificate context */
+ if (!CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
+ CERT_STORE_NO_CRYPT_RELEASE_FLAG,
+ &cert_key_context))
+ {
+ FAIL("CertSetCertificateContextProperty failed");
+ }
+
+cleanup:
+ LocalFree(derbuf);
+ LocalFree(keyblob);
+ LocalFree(pki);
+ if (hKey)
+ CryptDestroyKey(hKey);
+ if (status)
+ {
+ if (hProv)
+ CryptReleaseContext(hProv, 0);
+ }
+ return status;
+}
+
+/*
+ Given PEM strings for certificate and private key,
+ create a client certificate*
+*/
+static CERT_CONTEXT* create_client_certificate_mem(
+ char* cert_file_content,
+ char* key_file_content,
+ char* errmsg,
+ size_t errmsg_len)
+{
+ CERT_CONTEXT* ctx = NULL;
+ char* begin;
+ char* end;
+ CERT_BLOB cert_blob;
+ DWORD actual_content_type = 0;
+ SECURITY_STATUS status = SEC_E_OK;
+
+ /* Parse certificate */
+ pem_locate(cert_file_content, PEM_TYPE_CERTIFICATE,
+ &begin, &end);
+
+ if (!begin || !end)
+ {
+ SetLastError(SEC_E_INVALID_PARAMETER);
+ FAIL("Client certificate not found in PEM file");
+ }
+
+ cert_blob.pbData = (BYTE*)begin;
+ cert_blob.cbData = (DWORD)(end - begin);
+ if (!CryptQueryObject(
+ CERT_QUERY_OBJECT_BLOB, &cert_blob,
+ CERT_QUERY_CONTENT_FLAG_CERT,
+ CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type,
+ NULL, NULL, NULL, (const void**)&ctx))
+ {
+ FAIL("Can't parse client certficate");
+ }
+
+ /* Parse key */
+ PEM_TYPE types[] = { PEM_TYPE_RSA_PRIVATE_KEY, PEM_TYPE_PRIVATE_KEY };
+ for (int i = 0; i < sizeof(types) / sizeof(types[0]); i++)
+ {
+ pem_locate(key_file_content, types[i], &begin, &end);
+ if (begin && end)
+ {
+ /* Assign key to certificate.*/
+ status = load_private_key(ctx, begin, (end - begin), errmsg, errmsg_len);
+ goto cleanup;
+ }
+ }
+
+ if (!begin || !end)
+ {
+ SetLastError(SEC_E_INVALID_PARAMETER);
+ FAIL("Client private key not found in PEM");
+ }
+
+cleanup:
+ if (status && ctx)
+ {
+ CertFreeCertificateContext(ctx);
+ ctx = NULL;
+ }
+ return ctx;
+}
+
+
+/* Given cert and key, as PEM file names, create a client certificate */
+CERT_CONTEXT* schannel_create_cert_context(char* cert_file, char* key_file, char* errmsg, size_t errmsg_len)
+{
+ CERT_CONTEXT* ctx = NULL;
+ char* key_file_content = NULL;
+ char* cert_file_content = NULL;
+
+ cert_file_content = pem_file_to_string(cert_file, errmsg, errmsg_len);
+
+ if (!cert_file_content)
+ goto cleanup;
+
+ if (cert_file == key_file)
+ {
+ key_file_content = cert_file_content;
+ }
+ else
+ {
+ key_file_content = pem_file_to_string(key_file, errmsg, errmsg_len);
+ if (!key_file_content)
+ goto cleanup;
+ }
+
+ ctx = create_client_certificate_mem(cert_file_content, key_file_content, errmsg, errmsg_len);
+
+cleanup:
+ LocalFree(cert_file_content);
+ if (cert_file != key_file)
+ LocalFree(key_file_content);
+
+ return ctx;
+}
+
+/*
+ Free certificate, and all resources, created by schannel_create_cert_context()
+*/
+void schannel_free_cert_context(const CERT_CONTEXT* cert)
+{
+ /* release provider handle which was acquires in load_private_key() */
+ CERT_KEY_CONTEXT cert_key_context = { 0 };
+ cert_key_context.cbSize = sizeof(cert_key_context);
+ DWORD cbData = sizeof(CERT_KEY_CONTEXT);
+ HCRYPTPROV hProv = 0;
+
+ if (CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, &cert_key_context, &cbData))
+ {
+ hProv = cert_key_context.hCryptProv;
+ }
+ CertFreeCertificateContext(cert);
+ if (hProv)
+ {
+ CryptReleaseContext(cert_key_context.hCryptProv, 0);
+ }
+}
diff --git a/libmariadb/libmariadb/secure/schannel_certs.h b/libmariadb/libmariadb/secure/schannel_certs.h
new file mode 100644
index 00000000..67a8d11e
--- /dev/null
+++ b/libmariadb/libmariadb/secure/schannel_certs.h
@@ -0,0 +1,53 @@
+/************************************************************************************
+ Copyright (C) 2019 MariaDB Corporation Ab
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ *************************************************************************************/
+
+#pragma once
+#include <windows.h>
+#include <wincrypt.h>
+
+extern SECURITY_STATUS schannel_create_store(
+ const char* CAFile,
+ const char* CAPath,
+ const char* CRLFile,
+ const char* CRLPath,
+ HCERTSTORE* store,
+ char* errmsg,
+ size_t errmsg_len
+);
+
+extern SECURITY_STATUS schannel_verify_server_certificate(
+ const CERT_CONTEXT* cert,
+ HCERTSTORE store,
+ BOOL check_revocation,
+ const char* server_name,
+ BOOL check_server_name,
+ char* errmsg,
+ size_t errmsg_len);
+
+extern void schannel_free_store(HCERTSTORE store);
+
+extern CERT_CONTEXT* schannel_create_cert_context(
+ char* cert_file,
+ char* key_file,
+ char* errmsg,
+ size_t errmsg_len);
+
+extern void schannel_free_cert_context(const CERT_CONTEXT* cert);
+
diff --git a/libmariadb/libmariadb/secure/win_crypt.c b/libmariadb/libmariadb/secure/win_crypt.c
new file mode 100644
index 00000000..9d9fe495
--- /dev/null
+++ b/libmariadb/libmariadb/secure/win_crypt.c
@@ -0,0 +1,162 @@
+/*
+ Copyright (C) 2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*/
+#include <windows.h>
+#include <bcrypt.h>
+#include <ma_crypt.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ Error handling for bcrypt.
+ If we can't meaningfully return an error, dump error on stderr
+ and abort. Those errors are mostly likely programming errors
+ (invalid parameters and such)
+*/
+static inline void check_nt_status(int ret, const char *function,
+ const char *file, int line)
+{
+ if (ret)
+ {
+ fprintf(stderr,"invalid return %d from bcrypt, "
+ "function %s with file %s, line %d\n",
+ ret, function, file, line);
+ abort();
+ }
+}
+#define CHECK_NT_STATUS(ret) check_nt_status(ret, __func__, __FILE__, __LINE__)
+
+/*
+ Return Bcrypt algorithm ID (wchar string) for MariaDB numeric ID
+*/
+static LPCWSTR ma_hash_get_algorithm(unsigned int alg)
+{
+ switch (alg)
+ {
+ case MA_HASH_SHA1:
+ return BCRYPT_SHA1_ALGORITHM;
+ case MA_HASH_SHA256:
+ return BCRYPT_SHA256_ALGORITHM;
+ case MA_HASH_SHA384:
+ return BCRYPT_SHA384_ALGORITHM;
+ case MA_HASH_SHA512:
+ return BCRYPT_SHA512_ALGORITHM;
+ default:
+ return NULL;
+ }
+}
+
+/* Cached algorithm provides handles. */
+static BCRYPT_ALG_HANDLE cached_alg_handles[MA_HASH_MAX];
+
+/*
+ Cleanup cached algorithm handles. It runs either on process exit,
+ or when DLL is unloaded (see _onexit() documentation)
+*/
+static int win_crypt_onexit(void)
+{
+ int i;
+ for (i= 0; i < MA_HASH_MAX; i++)
+ {
+ if (cached_alg_handles[i])
+ BCryptCloseAlgorithmProvider(cached_alg_handles[i], 0);
+ }
+ return 0;
+}
+
+static void register_cleanup_onexit_once()
+{
+ static LONG onexit_called;
+ if (!InterlockedCompareExchange(&onexit_called, 1, 0))
+ _onexit(win_crypt_onexit);
+}
+
+/*
+ Given algorithm ID, return BCRYPT provider handle.
+ Uses or populates algorithm provider handle cache.
+*/
+static BCRYPT_ALG_HANDLE ma_hash_get_algorithm_handle(unsigned int alg)
+{
+ static SRWLOCK lock= SRWLOCK_INIT;
+ BCRYPT_ALG_HANDLE handle= NULL;
+ const wchar_t *name;
+
+ if ((handle= cached_alg_handles[alg]) != NULL)
+ return handle;
+
+ name= ma_hash_get_algorithm(alg);
+ if (!name)
+ return NULL;
+
+ AcquireSRWLockExclusive(&lock);
+ if ((handle= cached_alg_handles[alg]) == NULL)
+ {
+ if (BCryptOpenAlgorithmProvider(&handle, name, NULL, 0) == 0)
+ cached_alg_handles[alg]= handle;
+ else
+ handle= NULL;
+ }
+ ReleaseSRWLockExclusive(&lock);
+
+ if (handle)
+ register_cleanup_onexit_once();
+ return handle;
+}
+
+MA_HASH_CTX *ma_hash_new(unsigned int algorithm)
+{
+ BCRYPT_HASH_HANDLE hash_handle;
+ BCRYPT_ALG_HANDLE alg_handle= ma_hash_get_algorithm_handle(algorithm);
+
+ if (!alg_handle)
+ return NULL;
+
+ if (BCryptCreateHash(alg_handle, &hash_handle, NULL, 0, NULL, 0, 0))
+ return NULL;
+
+ return hash_handle;
+}
+
+void ma_hash_free(MA_HASH_CTX *ctx)
+{
+ NTSTATUS status;
+ if (!ctx)
+ return;
+ status= BCryptDestroyHash(ctx);
+ CHECK_NT_STATUS(status);
+}
+
+void ma_hash_input(MA_HASH_CTX *ctx, const unsigned char *buffer, size_t len)
+{
+ NTSTATUS status= BCryptHashData(ctx, (PUCHAR) buffer, (ULONG) len, 0);
+ CHECK_NT_STATUS(status);
+}
+
+void ma_hash_result(MA_HASH_CTX *ctx, unsigned char *digest)
+{
+ DWORD hash_length;
+ DWORD data_length;
+ NTSTATUS status=
+ BCryptGetProperty(ctx, BCRYPT_HASH_LENGTH, (PBYTE) &hash_length,
+ sizeof(DWORD), &data_length, 0);
+ CHECK_NT_STATUS(status);
+
+ status= BCryptFinishHash(ctx, digest, (ULONG) hash_length, 0);
+ CHECK_NT_STATUS(status);
+}
diff --git a/libmariadb/libmariadb/win32_errmsg.c b/libmariadb/libmariadb/win32_errmsg.c
new file mode 100644
index 00000000..f890c4f6
--- /dev/null
+++ b/libmariadb/libmariadb/win32_errmsg.c
@@ -0,0 +1,138 @@
+/************************************************************************************
+ Copyright (C) 2019 MariaDB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ *************************************************************************************/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ Format Windows error, with optional text.
+
+ For "known" errors we also output their symbolic error constant, e.g
+ CERT_E_CN_NO_MATCH in addition to numeric value.
+
+ We also try to output English text for all error messages, as not to mess up
+ with encodings.
+*/
+void ma_format_win32_error(char* buf, size_t buflen, DWORD code, _Printf_format_string_ const char* fmt, ...)
+{
+ char* cur = buf;
+ char* end = cur + buflen;
+ *cur = 0;
+ if (fmt)
+ {
+ va_list vargs;
+ va_start(vargs, fmt);
+ cur += vsnprintf_s(cur, end - cur, _TRUNCATE, fmt, vargs);
+ va_end(vargs);
+ }
+
+ if (code == 0)
+ return;
+
+ static struct map_entry
+ {
+ DWORD code;
+ const char* sym;
+ const char* msg;
+ }
+ map[] =
+ {
+#define ENTRY(x, y) {x,#x, y}
+ ENTRY(SEC_E_WRONG_PRINCIPAL, "The target principal name is incorrect"),
+ ENTRY(CERT_E_CN_NO_MATCH,"The certificate's CN name does not match the passed value"),
+ ENTRY(SEC_E_UNTRUSTED_ROOT,"The certificate chain was issued by an authority that is not trusted"),
+ ENTRY(TRUST_E_CERT_SIGNATURE,"The signature of the certificate cannot be verified"),
+ ENTRY(SEC_E_CERT_EXPIRED,"The received certificate has expired"),
+ ENTRY(CERT_E_EXPIRED,"A required certificate is not within its validity period when verifying against the current system clock or the timestamp in the signed file"),
+ ENTRY(CRYPT_E_NO_REVOCATION_CHECK, "The revocation function was unable to check revocation for the certificate"),
+ ENTRY(CRYPT_E_REVOCATION_OFFLINE,"The revocation function was unable to check revocation because the revocation server was offline"),
+ ENTRY(CRYPT_E_REVOKED,"The certificate is revoked"),
+ ENTRY(SEC_E_CERT_UNKNOWN,"An unknown error occurred while processing the certificate"),
+ ENTRY(CERT_E_ROLE," A certificate that can only be used as an end-entity is being used as a CA or vice versa"),
+ ENTRY(CERT_E_WRONG_USAGE,"The certificate is not valid for the requested usage"),
+ ENTRY(SEC_E_ILLEGAL_MESSAGE, "The message received was unexpected or badly formatted"),
+ ENTRY(CERT_E_VALIDITYPERIODNESTING,"The validity periods of the certification chain do not nest correctly"),
+ ENTRY(CERT_E_PATHLENCONST,"A path length constraint in the certification chain has been violated"),
+ ENTRY(CERT_E_CRITICAL,"A certificate contains an unknown extension that is marked 'critical'"),
+ ENTRY(CERT_E_PURPOSE,"A certificate being used for a purpose other than the ones specified by its CA"),
+ ENTRY(CERT_E_ISSUERCHAINING,"A parent of a given certificate in fact did not issue that child certificate"),
+ ENTRY(CERT_E_MALFORMED, "A certificate is missing or has an empty value for an important field, such as a subject or issuer name"),
+ ENTRY(CERT_E_CHAINING,"A certificate chain could not be built to a trusted root authority"),
+ ENTRY(TRUST_E_FAIL," Generic trust failure"),
+ ENTRY(CERT_E_UNTRUSTEDTESTROOT,"The certification path terminates with the test root which is not trusted with the current policy settings"),
+ ENTRY(CERT_E_UNTRUSTEDROOT,"A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider"),
+ ENTRY(CERT_E_REVOCATION_FAILURE,"The revocation process could not continue - the certificate(s) could not be checked"),
+ ENTRY(SEC_E_ILLEGAL_MESSAGE, "The message received was unexpected or badly formatted"),
+ ENTRY(SEC_E_UNTRUSTED_ROOT, "Untrusted root certificate"),
+ ENTRY(SEC_E_BUFFER_TOO_SMALL, "Buffer too small"),
+ ENTRY(SEC_E_CRYPTO_SYSTEM_INVALID, "Cipher is not supported"),
+ ENTRY(SEC_E_INSUFFICIENT_MEMORY, "Out of memory"),
+ ENTRY(SEC_E_OUT_OF_SEQUENCE, "Invalid message sequence"),
+ ENTRY(SEC_E_DECRYPT_FAILURE, "The specified data could not be decrypted"),
+ ENTRY(SEC_I_INCOMPLETE_CREDENTIALS, "Incomplete credentials"),
+ ENTRY(SEC_E_ENCRYPT_FAILURE, "The specified data could not be encrypted"),
+ ENTRY(SEC_I_CONTEXT_EXPIRED, "The context has expired and can no longer be used"),
+ ENTRY(SEC_E_ALGORITHM_MISMATCH, "no cipher match"),
+ ENTRY(SEC_E_NO_CREDENTIALS, "no credentials"),
+ ENTRY(SEC_E_INVALID_TOKEN, "The token supplied to function is invalid"),
+ ENTRY(SEC_E_UNSUPPORTED_FUNCTION,"The function requested is not supported")
+ };
+
+ struct map_entry* entry = NULL;
+
+ if (cur > buf && cur[-1] != ' ' && cur[-1] != '.')
+ {
+ strncpy_s(cur,end-cur, ". ", _TRUNCATE);
+ cur += 2;
+ }
+
+ for (size_t i = 0; i < sizeof(map) / sizeof(map[0]); i++)
+ {
+ if (code == map[i].code)
+ {
+ entry = &map[i];
+ break;
+ }
+ }
+ if (cur > end - 20)
+ return;
+ if (entry)
+ {
+ snprintf(cur, end - cur, "%s. Error 0x%08lX(%s)", entry->msg, code, entry->sym);
+ }
+ else
+ {
+ cur += FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, code, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ cur, (DWORD)(end - cur), NULL);
+ while (cur > buf && (*cur == '\0' || *cur == '\n' || *cur == '\r' || *cur == '.'))
+ cur--;
+ if (*cur)
+ {
+ cur++;
+ *cur = 0;
+ }
+ snprintf(cur, end - cur, ". Error %lu/0x%08lX", code, code);
+ }
+ end[-1] = 0;
+}
+
diff --git a/libmariadb/libmariadb/win32_errmsg.h b/libmariadb/libmariadb/win32_errmsg.h
new file mode 100644
index 00000000..865d9928
--- /dev/null
+++ b/libmariadb/libmariadb/win32_errmsg.h
@@ -0,0 +1,2 @@
+#include <windows.h>
+void ma_format_win32_error(char* buf, size_t buflen, DWORD code, _Printf_format_string_ const char* fmt, ...);
diff --git a/libmariadb/man/CMakeLists.txt b/libmariadb/man/CMakeLists.txt
new file mode 100644
index 00000000..227b233d
--- /dev/null
+++ b/libmariadb/man/CMakeLists.txt
@@ -0,0 +1,123 @@
+SET(CC_MAN_PAGES_3
+mariadb_cancel.3
+mariadb_connection.3
+mariadb_dyncol_check.3
+mariadb_dyncol_column_cmp_named.3
+mariadb_dyncol_column_count.3
+mariadb_dyncol_create_many_named.3
+mariadb_dyncol_create_many_num.3
+mariadb_dyncol_exists_named.3
+mariadb_dyncol_exists_num.3
+mariadb_dyncol_free.3
+mariadb_dyncol_list_named.3
+mariadb_dyncol_list_num.3
+mariadb_dyncol_unpack.3
+mariadb_dyncol_update_many_named.3
+mariadb_dyncol_update_many_num.3
+mariadb_get_infov.3
+mariadb_reconnect.3
+mariadb_rpl_close.3
+mariadb_rpl_fetch.3
+mariadb_rpl_get_optionsv.3
+mariadb_rpl_open.3
+mariadb_rpl_optionsv.3
+mariadb_stmt_execute_direct.3
+mariadb_stmt_fetch_fields.3
+mysql_affected_rows.3
+mysql_autocommit.3
+mysql_change_user.3
+mysql_close.3
+mysql_commit.3
+mysql_data_seek.3
+mysql_errno.3
+mysql_error.3
+mysql_fetch_field.3
+mysql_fetch_field_direct.3
+mysql_fetch_fields.3
+mysql_fetch_lengths.3
+mysql_fetch_row.3
+mysql_field_count.3
+mysql_field_seek.3
+mysql_field_tell.3
+mysql_free_result.3
+mysql_get_character_set_info.3
+mysql_get_client_info.3
+mysql_get_client_version.3
+mysql_get_host_info.3
+mysql_get_proto_info.3
+mysql_get_server_info.3
+mysql_get_server_version.3
+mysql_get_socket.3
+mysql_get_ssl_cipher.3
+mysql_hex_string.3
+mysql_info.3
+mysql_init.3
+mysql_kill.3
+mysql_more_results.3
+mysql_next_result.3
+mysql_num_fields.3
+mysql_num_rows.3
+mysql_options.3
+mysql_options4.3
+mysql_optionsv.3
+mysql_ping.3
+mysql_query.3
+mysql_read_query_result.3
+mysql_real_connect.3
+mysql_real_escape_string.3
+mysql_real_query.3
+mysql_refresh.3
+mysql_reset_connection.3
+mysql_rollback.3
+mysql_row_seek.3
+mysql_row_tell.3
+mysql_select_db.3
+mysql_send_query.3
+mysql_server_end.3
+mysql_server_init.3
+mysql_session_track_get_first.3
+mysql_session_track_get_next.3
+mysql_set_character_set.3
+mysql_set_server_option.3
+mysql_shutdown.3
+mysql_sqlstate.3
+mysql_ssl_set.3
+mysql_stat.3
+mysql_stmt_affected_rows.3
+mysql_stmt_attr_get.3
+mysql_stmt_attr_set.3
+mysql_stmt_bind_param.3
+mysql_stmt_bind_result.3
+mysql_stmt_close.3
+mysql_stmt_data_seek.3
+mysql_stmt_errno.3
+mysql_stmt_error.3
+mysql_stmt_execute.3
+mysql_stmt_fetch.3
+mysql_stmt_fetch_column.3
+mysql_stmt_field_count.3
+mysql_stmt_free_result.3
+mysql_stmt_init.3
+mysql_stmt_insert_id.3
+mysql_stmt_more_results.3
+mysql_stmt_next_result.3
+mysql_stmt_num_rows.3
+mysql_stmt_param_count.3
+mysql_stmt_param_metadata.3
+mysql_stmt_prepare.3
+mysql_stmt_reset.3
+mysql_stmt_result_metadata.3
+mysql_stmt_row_seek.3
+mysql_stmt_row_tell.3
+mysql_stmt_send_long_data.3
+mysql_stmt_sqlstate.3
+mysql_stmt_store_result.3
+mysql_stmt_warning_count.3
+mysql_store_result.3
+mysql_thread_end.3
+mysql_thread_id.3
+mysql_thread_init.3
+mysql_use_result.3
+mysql_warning_count.3)
+
+INSTALL(FILES ${CC_MAN_PAGES_3} DESTINATION ${INSTALL_MANDIR}/man3 COMPONENT ManPagesDevelopment)
diff --git a/libmariadb/man/mariadb_cancel.3 b/libmariadb/man/mariadb_cancel.3
new file mode 100644
index 00000000..38729c2d
--- /dev/null
+++ b/libmariadb/man/mariadb_cancel.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_cancel" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_cancel \- Immediately aborts a connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mariadb_cancel(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Immediately aborts a connection by making all subsequent read/write
+operations fail.
+\f[C]mariadb_cancel()\f[R] does not invalidate memory used for
+\f[C]mysql\f[R] structure, nor close any communication channels.
+To free the memory, \f[B]mysql_close(3)\f[R] must be called.
+\f[C]mariadb_cancel()\f[R] is useful to break long queries in situations
+where sending KILL is not possible.
+.SS Parameter
+.PP
+\f[C]mysql\f[R] \- mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+Returns zero on success or a non\-zero value on error.
+.SS History
+.PP
+\f[C]mariadb_cancel()\f[R] was added in Connector/C 3.0
diff --git a/libmariadb/man/mariadb_connection.3 b/libmariadb/man/mariadb_connection.3
new file mode 100644
index 00000000..a2b571b5
--- /dev/null
+++ b/libmariadb/man/mariadb_connection.3
@@ -0,0 +1,29 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_connection" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_connection \- checks if the client is connected to a MariaDB
+database server
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mariadb_connection(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Checks if the client is connected to a MariaDB or MySQL database server.
+.SS Parameter
+.PP
+\f[C]mysql\f[R] \- mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+Returns a non zero value if connected to a MariaDB database server,
+otherwise zero.
diff --git a/libmariadb/man/mariadb_dyncol_check.3 b/libmariadb/man/mariadb_dyncol_check.3
new file mode 100644
index 00000000..5b425e31
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_check.3
@@ -0,0 +1,32 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_check" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_check \- Checks if a dynamic column has correct format
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_check(DYNAMIC_COLUMN *str);
+\f[R]
+.fi
+.SS Description
+.PP
+The function \f[C]mariadb_dyncol_check()\f[R] checks if a dynamic column
+has correct format.
+This can be used e.g.\ to check if a blob contains a dynamic column.
+.SS Parameter
+.IP \[bu] 2
+\f[C]str\f[R]\- pointer to a \f[C]DYNAMIC_COLUMN\f[R] structure.
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] if the dynamic column has correct format,
+otherwise \f[C]ER_DYNCOL_FORMAT\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_dyncol_count(3)\f[R]
diff --git a/libmariadb/man/mariadb_dyncol_column_cmp_named.3 b/libmariadb/man/mariadb_dyncol_column_cmp_named.3
new file mode 100644
index 00000000..ba345c28
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_column_cmp_named.3
@@ -0,0 +1,31 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_column_cmp_named" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_column_cmp_named \- Compare two column names
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+int mariadb_dyncol_column_cmp_named(const MYSQL_LEX_STRING *s1,
+ const MYSQL_LEX_STRING *s2);
+\f[R]
+.fi
+.SS Description
+.PP
+Compares two dynamic column keys represented as a pointer to a
+\f[C]MYSQL_LEX_STRING\f[R] structure.
+.SS Parameter
+.IP \[bu] 2
+\f[C]s1\f[R] \- First key
+.IP \[bu] 2
+\f[C]s2\f[R] \- Second key
+.SS Return value
+.PP
+Returns an integer less than, equal to, or greater than zero if the
+first bytes of \f[C]s1\f[R] is found, respectively, to be less than, to
+match, or be greater than the first bytes of \f[C]s2\f[R].
diff --git a/libmariadb/man/mariadb_dyncol_column_count.3 b/libmariadb/man/mariadb_dyncol_column_count.3
new file mode 100644
index 00000000..2d4fe142
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_column_count.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_column_count" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_column_count \- Get number of columns in dynamic column
+blob ## Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_column_count(DYNAMIC_COLUMN *str,
+ unsigned int *column_count);
+\f[R]
+.fi
+.SS Description
+.PP
+Gets the number of columnns in a dynamic column blob.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- A pointer to a \f[C]DYNAMIC_COLUMN\f[R] structure
+.IP \[bu] 2
+\f[C]column_count\f[R] \- An unsigned integer pointer where the number
+of columns will be stored.
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise error.
+.SS Notes
+.IP \[bu] 2
+\f[C]mariadb_dyncol_column_count()\f[R] doesn\[cq]t count NULL values.
+.SS See also
+.IP \[bu] 2
+Dynamic Column Error Codes (dyncol_typesanddefs#error-codes)
diff --git a/libmariadb/man/mariadb_dyncol_create_many_named.3 b/libmariadb/man/mariadb_dyncol_create_many_named.3
new file mode 100644
index 00000000..0778f722
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_create_many_named.3
@@ -0,0 +1,51 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_create_many_named" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_create_many_named \- Creates a dynamic column with named
+keys
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_create_many_named(DYNAMIC_COLUMN *str,
+ uint column_count,
+ MYSQL_LEX_STRING *column_keys,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_string);
+\f[R]
+.fi
+.SS Description
+.PP
+Create a dynamic column from arrays of values and names.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- A pointer to a dynamic column structure
+.IP \[bu] 2
+\f[C]column_count\f[R] \- number of columns
+.IP \[bu] 2
+\f[C]*column_keys\f[R] \- an array of column keys
+.IP \[bu] 2
+\f[C]*values\f[R] \- an array of values
+.IP \[bu] 2
+\f[C]new_string\f[R] \- if set \f[C]str\f[R] will be reinitialized (not
+freed) before usage
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise error.
+.SS Notes
+.IP \[bu] 2
+To delete, update or insert new columns into an existing dynamic column
+use <mariadb_dyncol_update_many_named> function
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_create_many_num>
+.IP \[bu] 2
+<mariadb_dyncol_update_many_named>
+.IP \[bu] 2
+Dynamic Column Error Codes (dyncol_typesanddefs#error-codes)
diff --git a/libmariadb/man/mariadb_dyncol_create_many_num.3 b/libmariadb/man/mariadb_dyncol_create_many_num.3
new file mode 100644
index 00000000..a49aaba3
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_create_many_num.3
@@ -0,0 +1,51 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_create_many_num" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_create_many_num \- Creates a dynamic column with numeric
+keys
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_create_many_num(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_string);
+\f[R]
+.fi
+.SS Description
+.PP
+Create a dynamic column from arrays of values and numb\['e]rs
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- A pointer to a dynamic column structure
+.IP \[bu] 2
+\f[C]column_count\f[R] \- number of columns
+.IP \[bu] 2
+\f[C]*column_numbers\f[R] \- an array of column numbers
+.IP \[bu] 2
+\f[C]*values\f[R] \- an array of values
+.IP \[bu] 2
+\f[C]new_string\f[R] \- if set \f[C]str\f[R] will be reinitialized (not
+freed) before usage
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise error.
+.SS Notes
+.IP \[bu] 2
+To delete, update or insert new columns into an existing dynamic column
+use <mariadb_dyncol_update_many_num> function
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_create_many_named>
+.IP \[bu] 2
+<mariadb_dyncol_update_many_num>
+.IP \[bu] 2
+Dynamic Column Error Codes (dyncol_typesanddefs#error-codes)
diff --git a/libmariadb/man/mariadb_dyncol_exists_named.3 b/libmariadb/man/mariadb_dyncol_exists_named.3
new file mode 100644
index 00000000..7bd54b4b
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_exists_named.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_exists_named" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_exists_named \- Check if column with given name exists.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+enum enum_dyncol_func_result
+mariadb_dyncol_exists_named(DYNAMIC_COLUMN *str,
+ MYSQL_LEX_STRING *column_key);
+\f[R]
+.fi
+.SS Description
+.PP
+Checks if a column with the specified column key exists.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- Dynamic column
+.IP \[bu] 2
+\f[C]*column_key\f[R] \- The column key to search for
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_YES\f[R] if a column with given key exists,
+\f[C]ER_DYNCOL_NO\f[R] if no column exists or error.
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_exists_num>
+.IP \[bu] 2
+Dynamic Column Error Codes (dyncol_typesanddefs#error-codes)
diff --git a/libmariadb/man/mariadb_dyncol_exists_num.3 b/libmariadb/man/mariadb_dyncol_exists_num.3
new file mode 100644
index 00000000..638c5d91
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_exists_num.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_exists_num" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_exists_num \- Check if column with given number exists.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+enum enum_dyncol_func_result
+mariadb_dyncol_exists_num(DYNAMIC_COLUMN *str,
+ uint column_number);
+\f[R]
+.fi
+.SS Description
+.PP
+Checks if a column with the specified column key exists.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- Dynamic column
+.IP \[bu] 2
+\f[C]column_number\f[R] \- The column number to search for
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_YES\f[R] if a column with given number exists,
+\f[C]ER_DYNCOL_NO\f[R] if no column exists or error.
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_exists_named>
+.IP \[bu] 2
+Dynamic Column Error Codes (dyncol_typesanddefs#error-codes)
diff --git a/libmariadb/man/mariadb_dyncol_free.3 b/libmariadb/man/mariadb_dyncol_free.3
new file mode 100644
index 00000000..4cee7c60
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_free.3
@@ -0,0 +1,30 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_free" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_free \- Free memory inside packed blob
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+void mariadb_dyncol_free(DYNAMIC_COLUMN *str)
+\f[R]
+.fi
+.SS Description
+.PP
+Frees memory associated by the specified dynamic column
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- A pointer to a \f[C]DYNAMIC_COLUMN\f[R] structure
+.SS Notes
+.IP \[bu] 2
+\f[C]mariadb_dyncol_free()\f[R] doesn\[cq]t free the memory of the
+passed \f[C]DYNAMIC_COLUMN\f[R] structure but all memory of stored
+columns.
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_dyncol_init(3)\f[R]
diff --git a/libmariadb/man/mariadb_dyncol_get_named.3 b/libmariadb/man/mariadb_dyncol_get_named.3
new file mode 100644
index 00000000..69153b9c
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_get_named.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_get_named" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_get_name \- Get value of a column with given key
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_get_named(DYNAMIC_COLUMN *str,
+ LEX_STRING *key,
+ DYNAMIC_COLUMN_VALUE *store_it_here)
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a dynamic column value by given key
+.SS Parameter
+.IP \[bu] 2
+\f[C]str\f[R]: Dynamic column
+.IP \[bu] 2
+\f[C]name\f[R]: Name to search for
+.IP \[bu] 2
+\f[C]value\f[R]: Value of dynamic column
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R]on success, otherwise error.
+If the column name could not be found, value will be NULL
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_dyncol_get_num(3)\f[R]
diff --git a/libmariadb/man/mariadb_dyncol_get_num.3 b/libmariadb/man/mariadb_dyncol_get_num.3
new file mode 100644
index 00000000..0224e68e
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_get_num.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_get_num" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_get_num \- Get value of a column with given number
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_get_num(DYNAMIC_COLUMN *str,
+ uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here)
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a dynamic column value by given number
+.SS Parameter
+.IP \[bu] 2
+\f[C]str\f[R]: Dynamic column
+.IP \[bu] 2
+\f[C]column_nr\f[R]: Number of column
+.IP \[bu] 2
+\f[C]value\f[R]: Value of dynamic column
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R]on success, otherwise error.
+If the column number could not be found, value will be NULL
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_dyncol_get_named(3)\f[R]
diff --git a/libmariadb/man/mariadb_dyncol_has_names.3 b/libmariadb/man/mariadb_dyncol_has_names.3
new file mode 100644
index 00000000..20f3fde5
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_has_names.3
@@ -0,0 +1,29 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_has_names" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_has_names \- Checks if dynamic column uses named keys
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+my_bool mariadb_dyncol_has_names(DYNAMIC_COLUMN *str)
+\f[R]
+.fi
+.SS Description
+.PP
+Checks if the specified dynamic column uses named keys.
+.SS Parameter
+.IP \[bu] 2
+\f[C]str\f[R]: Dynamic column
+.SS Return value
+.PP
+Returns 1 if the specified dynamic column uses named keys, otherwise
+zero.
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_dyncol_get_named(3)\f[R]
diff --git a/libmariadb/man/mariadb_dyncol_json.3 b/libmariadb/man/mariadb_dyncol_json.3
new file mode 100644
index 00000000..19a74212
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_json.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_json" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_json \- Get content of a dynamic column in JSON format
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_json(DYNAMIC_COLUMN *str,
+ DYNAMIC_STRING *json)
+\f[R]
+.fi
+.SS Description
+.PP
+Get content of a dynamic column in JSON format.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- Dynamic column
+.IP \[bu] 2
+\f[C]*json\f[R] \- Pointer to a dynamic string which contains json
+output
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R]on success, otherwise error.
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_dyncol_list_json(3)\f[R]
diff --git a/libmariadb/man/mariadb_dyncol_list_named.3 b/libmariadb/man/mariadb_dyncol_list_named.3
new file mode 100644
index 00000000..64b2cc5e
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_list_named.3
@@ -0,0 +1,43 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_list_named" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_list_named \- Lists column keys in dynamic column
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_list_named(DYNAMIC_COLUMN *str,
+ uint *column_count,
+ MYSQL_LEX_STRING **column_keys);
+\f[R]
+.fi
+.SS Description
+.PP
+Lists the column keys inside a dynamic column.
+.SS Notes
+.IP \[bu] 2
+The application program needs to free the allocated memory for
+\f[C]column_count\f[R] and \f[C]column_keys\f[R] parameter.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- Dynamic column
+.IP \[bu] 2
+\f[C]*column_count\f[R] \- A pointer to an unsigned integer which stores
+the number of columns
+.IP \[bu] 2
+\f[C]**column_keys\f[R] \- A pointer to an array of column keys, which
+stores the keys
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise error.
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_list_num>
+.IP \[bu] 2
+<mariadb_dyncol_list_json>
diff --git a/libmariadb/man/mariadb_dyncol_list_num.3 b/libmariadb/man/mariadb_dyncol_list_num.3
new file mode 100644
index 00000000..0334224b
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_list_num.3
@@ -0,0 +1,43 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_list_num" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_list_num \- Lists numeric column keys in dynamic column
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_list_named(DYNAMIC_COLUMN *str,
+ uint *column_count,
+ uint **column_numbers);
+\f[R]
+.fi
+.SS Description
+.PP
+Lists the column numbers inside a dynamic column.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- Dynamic column
+.IP \[bu] 2
+\f[C]*column_count\f[R] \- A pointer to an unsigned integer which stores
+the number of columns
+.IP \[bu] 2
+\f[C]**column_numbers\f[R] \- A pointer to an array of column numbers,
+which stores the numbers
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise error.
+.SS Notes
+.IP \[bu] 2
+The application program needs to free the allocated memory for
+\f[C]column_count\f[R] and \f[C]column_numbers\f[R] parameter.
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_list_named>
+.IP \[bu] 2
+<mariadb_dyncol_list_json>
diff --git a/libmariadb/man/mariadb_dyncol_unpack.3 b/libmariadb/man/mariadb_dyncol_unpack.3
new file mode 100644
index 00000000..57b80d4c
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_unpack.3
@@ -0,0 +1,50 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_unpack" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_unpack \- extracts keys and values of all columns
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_unpack(DYNAMIC_COLUMN *str,
+ uint *column_count,
+ MYSQL_LEX_STRING **column_keys,
+ DYNAMIC_COLUMN_VALUE **values);
+\f[R]
+.fi
+.SS Description
+.PP
+The \f[C]mariadb_dyncol_unpack()\f[R] function extracts all keys and
+values of a dynamic column.
+.SS Parameter
+.IP \[bu] 2
+\f[C]str\f[R] \- Pointer to a \f[C]DYNAMIC_COLUMN\f[R] structure
+.IP \[bu] 2
+\f[C]column count\f[R] \- Pointer to an unsigned integer which will
+receive the number of columns
+.IP \[bu] 2
+\f[C]column_keys\f[R] \- Pointer of an array of
+\f[C]MYSQL_LEX_STRING\f[R] structures, which will contain the column
+keys
+.IP \[bu] 2
+\f[C]values\f[R] \- Pointer of an array of
+\f[C]DYNAMIC_COLUMN_VALUE\f[R] structures, which will contain the
+values.
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise an error.
+.SS Notes
+.IP \[bu] 2
+The \f[C]column_keys\f[R] and \f[C]values\f[R] arrays will be allocated
+by \f[C]mariadb_dyncol_unpack()\f[R] and must be freed by application.
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_dyncol_get(3)\f[R]
+.IP \[bu] 2
+\f[B]mariadb_dyncol_list(3)\f[R]
diff --git a/libmariadb/man/mariadb_dyncol_update_many_named.3 b/libmariadb/man/mariadb_dyncol_update_many_named.3
new file mode 100644
index 00000000..81f0f594
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_update_many_named.3
@@ -0,0 +1,47 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_update_many_named" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_update_many_named \- Update, insert or delete values in a
+dynamic column
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_update_many_named(DYNAMIC_COLUMN *str,
+ uint column_count,
+ MYSQL_LEX_STRING *column_keys,
+ DYNAMIC_COLUMN_VALUE *values)
+\f[R]
+.fi
+.SS Description
+.PP
+Add, delete or update columns in a dynamic column.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- A pointer to a dynamic column structure
+.IP \[bu] 2
+\f[C]column_count\f[R] \- number of columns
+.IP \[bu] 2
+\f[C]*column_keys\f[R] \- an array of column keys
+.IP \[bu] 2
+\f[C]*values\f[R] \- an array of values
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise error.
+.SS Notes
+.IP \[bu] 2
+To delete a column, update its value to a \[lq]non\-value\[rq] of type
+\f[C]DYN_COL_NULL\f[R]
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_create_many_named>
+.IP \[bu] 2
+<mariadb_dyncol_update_many_num>
+.IP \[bu] 2
+Dynamic Column Error Codes (dyncol_typesanddefs#error-codes)
diff --git a/libmariadb/man/mariadb_dyncol_update_many_num.3 b/libmariadb/man/mariadb_dyncol_update_many_num.3
new file mode 100644
index 00000000..4d7a3ed3
--- /dev/null
+++ b/libmariadb/man/mariadb_dyncol_update_many_num.3
@@ -0,0 +1,47 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_dyncol_update_many_num" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_dyncol_update_many_num \- Update, insert or delete values in a
+dynamic column using numeric keys
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_dyncol.h>
+
+enum enum_dyncol_func_result
+mariadb_dyncol_update_many_num(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_keys,
+ DYNAMIC_COLUMN_VALUE *values)
+\f[R]
+.fi
+.SS Description
+.PP
+Add, delete or update columns in a dynamic column with a numeric key.
+.SS Parameter
+.IP \[bu] 2
+\f[C]*str\f[R] \- A pointer to a dynamic column structure
+.IP \[bu] 2
+\f[C]column_count\f[R] \- number of columns
+.IP \[bu] 2
+\f[C]*column_keys\f[R] \- an array of column keys
+.IP \[bu] 2
+\f[C]*values\f[R] \- an array of values
+.SS Return value
+.PP
+Returns \f[C]ER_DYNCOL_OK\f[R] on success, otherwise error.
+.SS Notes
+.IP \[bu] 2
+To delete a column, update its value to a \[lq]non\-value\[rq] of type
+\f[C]DYN_COL_NULL\f[R]
+.SS See also
+.IP \[bu] 2
+<mariadb_dyncol_create_many_num>
+.IP \[bu] 2
+<mariadb_dyncol_update_many_named>
+.IP \[bu] 2
+Dynamic Column Error Codes (dyncol_typesanddefs#error-codes)
diff --git a/libmariadb/man/mariadb_field_attr.3 b/libmariadb/man/mariadb_field_attr.3
new file mode 100644
index 00000000..80a2cb8c
--- /dev/null
+++ b/libmariadb/man/mariadb_field_attr.3
@@ -0,0 +1,92 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_field_attr" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_field_attr \- returns extended metadata information for
+pluggable field types
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int *mariadb_field_attr(MARIADB_CONST_STRING *attr,
+ const MYSQL_FIELD *field,
+ enum mariadb_field_attr_t type)
+\f[R]
+.fi
+.SS Description
+.PP
+Returns extended metadata information for pluggable field types like
+JSON and GEOMETRY.
+.SS Parameter
+.IP \[bu] 2
+\f[C]attr\f[R]: A pointer which returns extended metadata information
+.IP \[bu] 2
+\f[C]field\f[R]: Specifies the field which contains extended metadata
+information
+.IP \[bu] 2
+\f[C]type:\f[R] Specifies type of metadata information.
+Supported types are \f[C]MARIADB_FIELD_METADATA_DATA_TYPE_NAME\f[R] and
+\f[C]MARIADB_FIELD_METADATA_FORMAT_NAME\f[R].
+.SS Return value
+.PP
+Returns zero on success or non zero if the field doesn\[cq]t provide
+extended metadata information.
+.SS Notes
+.IP \[bu] 2
+Pluggable field type support is available in MariaDB server version
+10.5.2 and later
+.IP \[bu] 2
+To check if the server supports pluggable field types, check the
+extended server capabilities which can be obtained by api function
+\f[B]mariadb_get_info(3)\f[R]
+.SS Example
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int display_extended_field_attribute(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ MYSQL_FIELD *fields;
+
+ if (mysql_query(mysql, \[dq]CREATE TEMPORARY TABLE t1 (a POINT)\[dq]))
+ return 1;
+
+ if (mysql_query(mysql, \[dq]SELECT a FROM t1\[dq]))
+ return 1;
+
+ if (!(result= mysql_store_result(mysql)))
+ return 1;
+
+ if ((fields= mysql_fetch_fields(result)))
+ {
+ MARIADB_CONST_STRING field_attr;
+
+ if (!mariadb_field_attr(&field_attr, &fields[0],
+ MARIADB_FIELD_ATTR_DATA_TYPE_NAME))
+ {
+ printf(\[dq]Extended field attribute: %s\[rs]n\[dq], field_attr.str);
+ }
+ }
+ mysql_free_result(result);
+ return 0;
+}
+\f[R]
+.fi
+.SS History
+.PP
+mariadb_field_attr was added in MariaDB Connector/C 3.1.8
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mariadb_get_info(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_fetch_fields(3)\f[R]
diff --git a/libmariadb/man/mariadb_free_rpl_event.3 b/libmariadb/man/mariadb_free_rpl_event.3
new file mode 100644
index 00000000..e22ba3ff
--- /dev/null
+++ b/libmariadb/man/mariadb_free_rpl_event.3
@@ -0,0 +1,26 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_free_rpl_event" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_free_rpl_event \- free event memory
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_rpl.h>
+
+void mariadb_free_rpl_event(MARIADB_RPL_EVENT *event)
+\f[R]
+.fi
+.SS Description
+.PP
+Frees event memory.
+.SS Parameter
+.IP \[bu] 2
+\f[C]event\f[R] \- An event handle which was previously obtained by
+\f[B]mariadb_rpl_fetch(3)\f[R].
+.SS History
+.PP
+\f[C]mariadb_free_rpl_event\f[R] was added in MariaDB Connector/C 3.1.0
diff --git a/libmariadb/man/mariadb_get_infov.3 b/libmariadb/man/mariadb_get_infov.3
new file mode 100644
index 00000000..309cb936
--- /dev/null
+++ b/libmariadb/man/mariadb_get_infov.3
@@ -0,0 +1,325 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_get_infov" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_get_infov \- retrieves generic or connection releated
+information
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mariadb_get_infov(MYSQL * mysql,
+ enum mariadb_value value,
+ void * arg,
+ ...);
+\f[R]
+.fi
+.SH Description
+.PP
+Retrieves generic or connection specific information.
+\f[C]arg\f[R] (and further arguments) must be a pointer to a variable of
+the type appropriate for the \f[C]value\f[R] argument.
+The following table shows which variable type to use for each value.
+.PP
+.TS
+tab(@);
+lw(35.0n) lw(35.0n).
+T{
+Variable Type
+T}@T{
+Values
+T}
+_
+T{
+\f[C]unsigned int\f[R]
+T}@T{
+\f[C]MARIADB_CLIENT_VERSION_ID\f[R],
+\f[C]MARIADB_CONNECTION_ASYNC_TIMEOUT\f[R],
+\f[C]MARIADB_CONNECTION_ASYNC_TIMEOUT_MS\f[R],
+\f[C]MARIADB_CONNECTION_ERROR_ID\f[R],
+\f[C]MARIADB_CONNECTION_PORT\f[R],
+\f[C]MARIADB_CONNECTION_PROTOCOL_VERSION_ID\f[R],
+\f[C]MARIADB_CONNECTION_PVIO_TYPE\f[R],
+\f[C]MARIADB_CONNECTION_SERVER_STATUS\f[R],
+\f[C]MARIADB_CONNECTION_SERVER_VERSION_ID\f[R],
+\f[C]MARIADB_CONNECTION_TLS_VERSION_ID\f[R]
+T}
+T{
+\f[C]unsigned long\f[R]
+T}@T{
+\f[C]MARIADB_CONNECTION_CLIENT_CAPABILITIES\f[R],
+\f[C]MARIADB_CONNECTION_EXTENDED_SERVER_CAPABILITIES\f[R],
+\f[C]MARIADB_CONNECTION_SERVER_CAPABILITIES\f[R]
+T}
+T{
+\f[C]size_t\f[R]
+T}@T{
+\f[C]MARIADB_MAX_ALLOWED_PACKET\f[R],
+\f[C]MARIADB_NET_BUFFER_LENGTH\f[R]
+T}
+T{
+\f[C]const char *\f[R]
+T}@T{
+\f[C]MARIADB_CLIENT_VERSION\f[R], \f[C]MARIADB_TLS_VERSION\f[R],
+\f[C]MARIADB_CONNECTION_ERROR\f[R], \f[C]MARIADB_CONNECTION_HOST\f[R],
+\f[C]MARIADB_CONNECTION_INFO\f[R], \f[C]MARIADB_CONNECTION_SCHEMA\f[R],
+\f[C]MARIADB_CONNECTION_SERVER_TYPE\f[R],
+\f[C]MARIADB_CONNECTION_SERVER_VERSION\f[R],
+\f[C]MARIADB_CONNECTION_SQLSTATE\f[R],
+\f[C]MARIADB_CONNECTION_SSL_CIPHER\f[R],
+\f[C]MARIADB_CONNECTION_TLS_VERSION\f[R],
+\f[C]MARIADB_CONNECTUION_UNIX_SOCKET\f[R],
+\f[C]MARIADB_CONNECTION_USER\f[R],
+T}
+T{
+\f[C]const char **\f[R]
+T}@T{
+\f[C]MARIADB_CLIENT_ERRORS\f[R]
+T}
+T{
+\f[C]const *MY_CHARSET_INFO\f[R]
+T}@T{
+\f[C]MARIADB_CHARSET_NAME\f[R],
+\f[C]MARIADB_CONNECTION_CHARSET_INFO\f[R]
+T}
+T{
+\f[C]my_socket\f[R]
+T}@T{
+\f[C]MARIADB_CONNECTION_SOCKET\f[R]
+T}
+.TE
+.SS Value types
+.SS Generic information
+.PP
+For these information types parameter \f[C]mysql\f[R] needs to be set to
+NULL.
+.IP \[bu] 2
+\f[C]MARIADB_CHARSET_NAME\f[R]
+.PD 0
+.P
+.PD
+Retrieves the charset information for a character set by it\[cq]s
+literal representation.
+.IP \[bu] 2
+\f[C]MARIADB_CLIENT_ERRORS\f[R]
+.PD 0
+.P
+.PD
+Retrieve array of client errors.
+This can be used in plugins to set global error messages (which are not
+exported by MariaDB Connector/C).
+.IP \[bu] 2
+\f[C]MARIADB_CLIENT_VERSION\f[R]
+.PD 0
+.P
+.PD
+The client version in literal representation.
+.IP \[bu] 2
+\f[C]MARIADB_CLIENT_VERSION_ID\f[R]
+.PD 0
+.P
+.PD
+The client version in numeric format.
+.IP \[bu] 2
+\f[C]MARIADB_MAX_ALLOWED_PACKET\f[R]
+.PD 0
+.P
+.PD
+Retrieves value of maximum allowed packet size.
+.IP \[bu] 2
+\f[C]MARIADB_NET_BUFFER_LENGTH\f[R]
+.PD 0
+.P
+.PD
+Retrieves the length of net buffer.
+.IP \[bu] 2
+\f[C]MARIADB_SSL_LIBRARY\f[R]
+.PD 0
+.P
+.PD
+The TLS library MariaDB Connector/C is compiled against.
+.SS Connection related information
+.PP
+For these information types parameter mysql must be represent a valid
+connection handle which was allocated by \f[B]mysql_init(3)\f[R].
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_ASYNC_TIMEOUT\f[R]
+.PD 0
+.P
+.PD
+Retrieves the timeout for non blocking calls in seconds.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_ASYNC_TIMEOUT_MS\f[R]
+.PD 0
+.P
+.PD
+Retrieves the timeout for non blocking calls in milliseconds.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_CHARSET_INFO\f[R]
+.PD 0
+.P
+.PD
+Retrieves character set information for given connection.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_CLIENT_CAPABILITIES\f[R]
+.PD 0
+.P
+.PD
+Returns the handshak capability flags] of the client.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_ERROR\f[R]
+.PD 0
+.P
+.PD
+Retrieves error message for last used command.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_ERROR_ID\f[R]
+.PD 0
+.P
+.PD
+Retrieves error number for last used command.
+*\f[C]MARIADB_CONNECTION_EXTENDED_SERVER_CAPABILITIES\f[R]
+.PD 0
+.P
+.PD
+Returns the extended capability flags of the connected MariaDB server
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_HOST\f[R]
+.PD 0
+.P
+.PD
+Returns host name of the connected MariaDB server
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_INFO\f[R]
+.PD 0
+.P
+.PD
+Retrieves generic info for last used command.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_PORT\f[R]
+.PD 0
+.P
+.PD
+Retrieves the port number of server host.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_PROTOCOL_VERSION_ID\f[R]
+.PD 0
+.P
+.PD
+Retrieves the protocol version number.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_PVIO_TYPE\f[R]
+.PD 0
+.P
+.PD
+Retrieves the pvio plugin used for specified connection.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SCHEMA\f[R]
+.PD 0
+.P
+.PD
+Retrieves the current schema.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SERVER_CAPABILITIES\f[R]
+.PD 0
+.P
+.PD
+Retrievrs the capability flags of the connected server.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SERVER_STATUS\f[R]
+.PD 0
+.P
+.PD
+Returns server status after last operation.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SERVER_TYPE\f[R]
+.PD 0
+.P
+.PD
+Retrieves the type of the server.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SERVER_VERSION\f[R]
+.PD 0
+.P
+.PD
+Retrieves the server version in literal format.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SERVER_VERSION_ID\f[R]
+.PD 0
+.P
+.PD
+Retrieves the server version in numeric format.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SOCKET\f[R]
+.PD 0
+.P
+.PD
+Retrieves the handle (socket) for given connection.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SQLSTATE\f[R]
+.PD 0
+.P
+.PD
+Retrieves current sqlstate information for last used command.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_SSL_CIPHER\f[R]
+.PD 0
+.P
+.PD
+Retrieves the TLS/SSL cipher in use.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_TLS_VERSION\f[R]
+.PD 0
+.P
+.PD
+Retrieves the TLS protocol version used in literal format.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_TLS_VERSION_ID\f[R]
+.PD 0
+.P
+.PD
+Retrieves the TLS protocol version used in numeric format.
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_UNIX_SOCKET\f[R]
+.PD 0
+.P
+.PD
+Retrieves the file name of the unix socket
+.IP \[bu] 2
+\f[C]MARIADB_CONNECTION_USER\f[R]
+.PD 0
+.P
+.PD
+Retrieves connection\[cq]s user name.
+.SS Returns
+.PP
+Returns zero on success, non zero if an error occurred (e.g.\ if an
+invalid option was specified),
+.SS Source file
+.IP
+.nf
+\f[C]
+
+## History
+This function was added in MariaDB Connector/C 3.0,
+
+## Examples
+\f[R]
+.fi
+.PP
+/* get server port for current connection \f[I]/ unsigned int port;
+mariadb_get_infov(mysql, MARIADB_CONNECTION_PORT, (void \f[R])&port);
+.IP
+.nf
+\f[C]
+\f[R]
+.fi
+.PP
+/* get user name for current connection \f[I]/ const char \f[R]user;
+mariadb_get_infov(mysql, MARIADB_CONNECTION_USER, (void \f[I])&user);
+\[ga]\[ga]\[ga] ## See also \f[R] \f[B]mysql_get_optionv(3)\f[R]
diff --git a/libmariadb/man/mariadb_reconnect.3 b/libmariadb/man/mariadb_reconnect.3
new file mode 100644
index 00000000..3a89b545
--- /dev/null
+++ b/libmariadb/man/mariadb_reconnect.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_reconnect" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_reconnect \- reconnects to a server
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mariadb_reconnect(MYSQL * mysql)
+\f[R]
+.fi
+.SS Description
+.PP
+\f[C]mariadb_reconnect()\f[R] tries to reconnect to a server in case the
+connection died due to timeout or other errors.
+It uses the same credentials which were specified in
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+The function will return 0 on sucess, a non zero value on error
+.PP
+\f[B]Note\f[R]: The function will return an error, if the option
+\f[C]MYSQL_OPT_RECONNECT\f[R] wasn\[cq]t set before.
+.SS History
+.PP
+\f[C]mariadb_reconnect()\f[R] was added in MariaDB Connector/C 3.0
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_connect(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_optionsv(3)\f[R]
diff --git a/libmariadb/man/mariadb_rpl_close.3 b/libmariadb/man/mariadb_rpl_close.3
new file mode 100644
index 00000000..cc7b9893
--- /dev/null
+++ b/libmariadb/man/mariadb_rpl_close.3
@@ -0,0 +1,31 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_rpl_close" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_rpl_close \- Closes replication stream
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_rpl.h>
+
+void mariadb_rpl_close(MARIADB_RPL *rpl)
+\f[R]
+.fi
+.SS Description
+.PP
+Closes a replication stream.
+.SS Parameter
+.PP
+\f[C]rpl\f[R] \- A replication handle which was initialized by
+\f[B]mariadb_rpl_init(3)\f[R] and connected by
+\f[B]mariadb_rpl_open(3)\f[R].
+.SS Notes
+.PP
+To close the connection to the server, the api function
+\f[B]mariadb_close(3)\f[R] must be called.
+.SS History
+.PP
+\f[C]mariadb_rpl_close\f[R] was added in MariaDB Connector/C 3.1
diff --git a/libmariadb/man/mariadb_rpl_fetch.3 b/libmariadb/man/mariadb_rpl_fetch.3
new file mode 100644
index 00000000..38c77636
--- /dev/null
+++ b/libmariadb/man/mariadb_rpl_fetch.3
@@ -0,0 +1,42 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_rpl_fetch" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_rpl_fetch \- fetches next event from replication stream
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_rpl.h>
+
+MARIADB_RPL_EVENT *mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVENT *event)
+\f[R]
+.fi
+.SS Description
+.PP
+Fetches one event from the replication stream
+.SS Parameter
+.IP \[bu] 2
+\f[C]rpl\f[R] \- A replication handle which was initialized by
+\f[B]mariadb_rpl_init(3)\f[R] and connected by
+\f[B]mariadb_rpl_open(3)\f[R].
+.IP \[bu] 2
+\f[C]event\f[R] \- An event which was returned by a previous call to
+\f[C]mariadb_rpl_fetch\f[R].
+If this value is \f[C]NULL\f[R] the function will allocate new memory
+for the event, otherwise the passed event value will be overwritten.
+.SS Return value
+.PP
+An event handle or NULL if EOF packet was received.
+.SS Notes
+.PP
+Event memory needs to be freed by calling
+\f[B]mariadb_rpl_free_event(3)\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_rpl_free_event(3)\f[R]
+.SS History
+.PP
+\f[C]mariadb_rpl_fetch\f[R] was added in MariaDB Connector/C 3.1.0
diff --git a/libmariadb/man/mariadb_rpl_get_optionsv.3 b/libmariadb/man/mariadb_rpl_get_optionsv.3
new file mode 100644
index 00000000..a0520e60
--- /dev/null
+++ b/libmariadb/man/mariadb_rpl_get_optionsv.3
@@ -0,0 +1,74 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_rpl_get_optionsv" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_rpl_get_optionsv \- get replication option value
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_rpl.h>
+
+int mariadb_rpl_get_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option option, ...)
+\f[R]
+.fi
+.SS Parameter
+.IP \[bu] 2
+\f[C]rpl\f[R] \- a replication handle which was previously allocated by
+<mariadb_rpl_init>
+.IP \[bu] 2
+\f[C]option\f[R] \- The option to be set, followed by one or more values
+.PP
+.TS
+tab(@);
+lw(23.3n) lw(23.3n) lw(23.3n).
+T{
+Option
+T}@T{
+Type
+T}@T{
+Description
+T}
+_
+T{
+MARIADB_RPL_FILENAME
+T}@T{
+char **, size_t *
+T}@T{
+The name and name length of binglog file
+T}
+T{
+MARIADB_RPL_START
+T}@T{
+unsigned long *
+T}@T{
+Start position
+T}
+T{
+MARIADB_RPL_SERVER_ID
+T}@T{
+uint32_t *
+T}@T{
+Server id
+T}
+T{
+MARIADB_RPL_FLAGS
+T}@T{
+uint32_t *
+T}@T{
+Flags
+T}
+.TE
+.SS Return value
+.PP
+Returns zero on success, non zero on error.
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_rpl_optionsv(3)\f[R]
+.SS History
+.PP
+\f[C]mariadb_rpl_get_optionsv\f[R] was added in MariaDB Connector/C
+3.1.0
diff --git a/libmariadb/man/mariadb_rpl_open.3 b/libmariadb/man/mariadb_rpl_open.3
new file mode 100644
index 00000000..babaa19b
--- /dev/null
+++ b/libmariadb/man/mariadb_rpl_open.3
@@ -0,0 +1,29 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_rpl_open" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_rpl_open \- opens a replication stream
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_rpl.h>
+
+int mariadb_rpl_open(MARIADB_RPL *rpl)
+\f[R]
+.fi
+.SS Description
+.PP
+Opens a replication stream
+.SS Parameter
+.IP \[bu] 2
+\f[C]rpl\f[R] \- A replication handle which was previously initialized
+by \f[B]mariadb_rpl_init(3)\f[R].
+.SS Return value
+.PP
+Zero on success, nonzero on error.
+.SS History
+.PP
+\f[C]mariadb_rpl_open\f[R] was added in MariaDB Connector/C 3.1.0
diff --git a/libmariadb/man/mariadb_rpl_optionsv.3 b/libmariadb/man/mariadb_rpl_optionsv.3
new file mode 100644
index 00000000..ac231a7a
--- /dev/null
+++ b/libmariadb/man/mariadb_rpl_optionsv.3
@@ -0,0 +1,75 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_rpl_optionsv" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_rpl_optionsv \- sets replication options
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mariadb_rpl.h>
+
+int mariadb_rpl_optionsv(MARIADB_RPL *rpl, enum mariadb_rpl_option option, ...)
+\f[R]
+.fi
+.SS Parameter
+.IP \[bu] 2
+\f[C]rpl\f[R] \- a replication handle which was previously allocated by
+<mariadb_rpl_init>
+.IP \[bu] 2
+\f[C]option\f[R] \- The option to be set, followed by one or more values
+.PP
+.TS
+tab(@);
+l l l.
+T{
+Option
+T}@T{
+Type
+T}@T{
+Description
+T}
+_
+T{
+MARIADB_RPL_FILENAME
+T}@T{
+char *
+T}@T{
+The name of binglog file
+T}
+T{
+MARIADB_RPL_START
+T}@T{
+unsigned long
+T}@T{
+Start position
+T}
+T{
+MARIADB_RPL_SERVER_ID
+T}@T{
+uint32_t
+T}@T{
+Server id
+T}
+T{
+MARIADB_RPL_FLAGS
+T}@T{
+uint32_t
+T}@T{
+Flags
+T}
+.TE
+.SS Return value
+.PP
+Returns zero on success, non zero on error.
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_rpl_get_optionsv(3)\f[R]
+.IP \[bu] 2
+\f[B]mariadb_rpl_open(3)\f[R]
+.SS History
+.PP
+\f[C]mariadb_rpl_optionsv\f[R] was added in MariaDB Connector/C 3.1.0
diff --git a/libmariadb/man/mariadb_stmt_execute_direct.3 b/libmariadb/man/mariadb_stmt_execute_direct.3
new file mode 100644
index 00000000..b441a9e9
--- /dev/null
+++ b/libmariadb/man/mariadb_stmt_execute_direct.3
@@ -0,0 +1,81 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_stmt_execute_direct" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_stmt_execute_direct \- prepares and executes a prepared
+statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mariadb_stmt_execute_direct(MYSQL_STMT * stmt,
+ const char *query,
+ size_t length);
+\f[R]
+.fi
+.SS Description
+.PP
+Prepares and executes a statement which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R], using the current values of the parameter
+variables if any parameters exist in the statement.
+.SS Parameters
+.IP \[bu] 2
+\f[C]stmt\f[R] \- A statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]query\f[R] SQL statement
+.IP \[bu] 2
+\f[C]length\f[R] Length of SQL statement
+.SS Return value
+.PP
+Returns zero on success, non\-zero on failure.
+.SS Notes
+.IP \[bu] 2
+Since the number of parameter of the statement is unknown before
+execution it is mandatory to set the number of parameters via the
+\f[B]mysql_stmt_attr_set(3)\f[R] function.
+.IP \[bu] 2
+If the SQL statement is a zero\-terminated string, you can also pass
+\f[C]\-1\f[R] as length.
+.IP \[bu] 2
+The statement handle is intended for one\-time execution.
+Reusing the statement handle might lead to unexpected behavior.
+.SS History
+.PP
+This function was added in Connector/C 3.0 and requires MariaDB 10.2 or
+later versions.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_attr_set(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_bind_param(3)\f[R]
+.SS Example
+.PP
+\[ga]\[ga]\[ga]C static int execute_direct_example(MYSQL \f[I]mysql) {
+MYSQL_STMT \f[R]stmt= mysql_stmt_init(mysql); MYSQL_BIND bind[2]; int
+intval= 1; int param_count= 2; char *strval=
+\[lq]execute_direct_example\[rq];
+.PP
+/* Direct execution without parameters */ if
+(mariadb_stmt_execute_direct(stmt, \[lq]CREATE TABLE execute_direct (a
+int, b varchar(30))\[rq], \-1)) goto error;
+.PP
+memset(&bind, 0, sizeof(MYSQL_BIND) * 2); bind[0].buffer_type=
+MYSQL_TYPE_SHORT; bind[0].buffer= &intval; bind[1].buffer_type=
+MYSQL_TYPE_STRING; bind[1].buffer= strval; bind[1].buffer_length=
+strlen(strval);
+.PP
+/* set number of parameters */ if (mysql_stmt_attr_set(stmt,
+STMT_ATTR_PREBIND_PARAMS, &param_count)) goto error;
+.PP
+/* bind parameters */ if (mysql_stmt_bind_param(stmt, bind)) goto error;
+.PP
+if (mariadb_stmt_execute_direct(stmt, \[lq]INSERT INTO execute_direct
+VALUES (?,?)\[rq], \-1)) goto error;
+.PP
+mysql_stmt_close(stmt); return 0; error: printf(\[lq]Error: %s\[rq],
+mysql_stmt_error(stmt)); mysql_stmt_close(stmt); return 1; }
diff --git a/libmariadb/man/mariadb_stmt_fetch_fields.3 b/libmariadb/man/mariadb_stmt_fetch_fields.3
new file mode 100644
index 00000000..dbd68de1
--- /dev/null
+++ b/libmariadb/man/mariadb_stmt_fetch_fields.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mariadb_stmt_fetch_fields" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mariadb_stmt_fetch_fields \- Returns an array of fields containing the
+column definitions ## Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_FIELD *mariadb_stmt_fetch_fields(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns an array of fields.
+Each field contains the definition for a column of the result set.
+If the statement doesn\[cq]t have a result set a NULL pointer will be
+returned.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- A statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Notes
+.PP
+The number of fields can be obtained by
+\f[B]mysql_stmt_field_count(3)\f[R]
+.SS History
+.PP
+This function was added in MariaDB Connector/C 3.1.0
+.SS See Also
+.PP
+*\f[B]mysql_stmt_field_count(3)\f[R]
diff --git a/libmariadb/man/mysql_affected_rows.3 b/libmariadb/man/mysql_affected_rows.3
new file mode 100644
index 00000000..c408ed78
--- /dev/null
+++ b/libmariadb/man/mysql_affected_rows.3
@@ -0,0 +1,46 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_affected_rows" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_affected_rows \- returns the number of rows affected by the last
+operation
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_ulonglong mysql_affected_rows(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of affected rows by the last operation associated
+with mysql, if the operation was an \[lq]upsert\[rq] (\f[C]INSERT\f[R],
+\f[C]UPDATE\f[R], \f[C]DELETE\f[R] or \f[C]REPLACE\f[R]) statement, or
+\-1 if the last operation failed.
+.SS Parameters:
+.PP
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes:
+.IP \[bu] 2
+When using \f[C]UPDATE\f[R], MariaDB will not update columns where the
+new value is the same as the old value.
+This creates the possibility that mysql_affected_rows may not actually
+equal the number of rows matched, only the number of rows that were
+literally affected by the query.
+.IP \[bu] 2
+The \f[C]REPLACE\f[R] statement first deletes the record with the same
+primary key and then inserts the new record.
+This function returns the number of deleted records in addition to the
+number of inserted records.
+.SH Return value
+.PP
+Returns the number of affected rows or \-1 on error.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_num_rows(3)\f[R]
diff --git a/libmariadb/man/mysql_autocommit.3 b/libmariadb/man/mysql_autocommit.3
new file mode 100644
index 00000000..9b12b9de
--- /dev/null
+++ b/libmariadb/man/mysql_autocommit.3
@@ -0,0 +1,82 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_autocommit" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_autocommit \- Toggles autocommit mode
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
+\f[R]
+.fi
+.SS Description
+.PP
+Toggles autocommit mode on or off for the current database connection.
+Autocommit mode will be set if mode=1 or unset if mode=0.
+.SS Parameters:
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]auto_mode\f[R] \- whether to turn autocommit on or not.
+.SS Notes
+.IP \[bu] 2
+Autocommit mode only affects operations on transactional table types.
+To determine the current state of autocommit mode use the SQL command
+\f[C]SELECT \[at]\[at]autocommit\f[R] or check the server status (see
+example below).
+.IP \[bu] 2
+Be aware: the [mysql_rollback()}(mysql_rollback() function will not work
+if autocommit mode is switched on.
+.SS Examples
+.SS SQL
+.IP
+.nf
+\f[C]
+# Turn of autocmmit
+SET AUTOCOMMIT=0;
+
+# Retrieve autocommit
+SELECT \[at]\[at]autocommit;
++\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+| \[at]\[at]autocommit |
++\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+| 0 |
++\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+\f[R]
+.fi
+.SS MariaDB Connector/C
+.IP
+.nf
+\f[C]
+static int test_autocommit(MYSQL *mysql)
+{
+ int rc;
+ unsigned int server_status;
+
+ /* Turn autocommit off */
+ rc= mysql_autocommit(mysql, 0);
+ if (rc)
+ return rc; /* Error */
+
+ /* If autocommit = 0 succeeded, the last OK packet updated the server status */
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_STATUS, &server_status);
+ if (rc)
+ return rc; /* Error */
+
+ if (server_status & SERVER_STATUS_AUTOCOMMIT)
+ {
+ printf(\[dq]Error: autocommit is on\[rs]n\[dq]);
+ return 1;
+ }
+ printf(\[dq]OK: autocommit is off\[rs]n\[dq]);
+ return 0;
+}
+\f[R]
+.fi
diff --git a/libmariadb/man/mysql_change_user.3 b/libmariadb/man/mysql_change_user.3
new file mode 100644
index 00000000..8f9939b8
--- /dev/null
+++ b/libmariadb/man/mysql_change_user.3
@@ -0,0 +1,62 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_change_user" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_change_user \- changes user and default database
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_change_user(MYSQL * mysql,
+ const char * user,
+ const char * passwd,
+ const char * db);
+\f[R]
+.fi
+.SS Description
+.PP
+Changes the user and default database of the current connection.
+.PP
+In order to successfully change users a valid username and password
+parameters must be provided and that user must have sufficient
+permissions to access the desired database.
+If for any reason authorization fails, the current user authentication
+will remain.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]user\f[R] \- the user name for server authentication
+.IP \[bu] 2
+\f[C]passwd\f[R] \- the password for server authentication
+.IP \[bu] 2
+\f[C]db\f[R] \- the default database.
+If desired, the NULL value may be passed resulting in only changing the
+user and not selecting a database.
+To select a database in this case use the \f[B]mysql_select_db(3)\f[R]
+function.
+.SS Notes
+.IP \[bu] 2
+mysql_change_user will always cause the current database connection to
+behave as if was a completely new database connection, regardless of if
+the operation was completed successfully.
+This reset includes performing a rollback on any active transactions,
+closing all temporary tables, and unlocking all locked tables.
+.IP \[bu] 2
+To prevent denial of service and brute\-force attacks the server will
+block the connection if \f[C]mysql_change_user()\f[R] failed three times
+in a row
+.SS Return value
+.PP
+Returns zero on success, nonzero if an error occurred.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_connect(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_select_db(3)\f[R]
diff --git a/libmariadb/man/mysql_close.3 b/libmariadb/man/mysql_close.3
new file mode 100644
index 00000000..7d212ac4
--- /dev/null
+++ b/libmariadb/man/mysql_close.3
@@ -0,0 +1,28 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_close" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_close \- Closes a previously opened connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_close(MYSQL *mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Closes a previously opened connection and deallocates all memory.
+.SS Notes
+.IP \[bu] 2
+To reuse a connection handle after \f[C]mysql_close()\f[R] the handle
+must be initialized again by \f[B]mysql_init(3)\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_init(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_real_connect(3)\f[R]
diff --git a/libmariadb/man/mysql_commit.3 b/libmariadb/man/mysql_commit.3
new file mode 100644
index 00000000..a35b234f
--- /dev/null
+++ b/libmariadb/man/mysql_commit.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_commit" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_commit \- Commits the current transaction
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_commit(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Commits the current transaction for the specified database connection.
+Returns zero on success, nonzero if an error occurred.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+Executing mysql_commit() will not affected the behaviour of autocommit.
+This means, any update or insert statements following mysql_commit()
+will be rolled back when the connection gets closed.
+.PP
+== See also * \f[B]mysql_autocommit(3)\f[R] *
+\f[B]mysql_rollback(3)\f[R]
diff --git a/libmariadb/man/mysql_data_seek.3 b/libmariadb/man/mysql_data_seek.3
new file mode 100644
index 00000000..7b4f0555
--- /dev/null
+++ b/libmariadb/man/mysql_data_seek.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_data_seek" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_data_seek \- seeks to an offset
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_data_seek(MYSQL_RES * result,
+ my_ulonglong offset);
+\f[R]
+.fi
+.SS Description
+.PP
+The mysql_data_seek() function seeks to an arbitrary function result
+pointer specified by the offset in the result set.
+Returns zero on success, nonzero if an error occurred.
+.SS Parameters
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+mysql_store_result().
+.IP \[bu] 2
+\f[C]offset\f[R] \- the field offset.
+Must be between zero and the total number of rows minus one
+(0..mysql_num_rows \- 1).
+.SS Notes
+.PP
+This function can only be used with buffered result sets obtained from
+the use of the \f[B]mysql_store_result(3)\f[R] function.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_num_rows(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_eof.3 b/libmariadb/man/mysql_eof.3
new file mode 100644
index 00000000..ca5da9bd
--- /dev/null
+++ b/libmariadb/man/mysql_eof.3
@@ -0,0 +1,29 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_eof" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_eof \- determines if the last row of a result set has been read
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_eof(MYSQL_RES *result);
+\f[R]
+.fi
+.SS Description
+.PP
+Determines if the last row of a result set has been read.
+.PP
+\f[B]Notes:\f[R] * This function is deprecated and will be removed.
+Instead determine the end of a result set by checking return value of
+\f[B]mysql_fetch_row(3)\f[R].
+* If a result set was acquired by \f[B]mysql_store_result(3)\f[R]
+mysql_eof will always return true.
+## Return value Returns true if the entire result set was read.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_fetch_row(3)\f[R]
diff --git a/libmariadb/man/mysql_errno.3 b/libmariadb/man/mysql_errno.3
new file mode 100644
index 00000000..c99a9e2c
--- /dev/null
+++ b/libmariadb/man/mysql_errno.3
@@ -0,0 +1,37 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_errno" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_errno \- returns the last error code for the most recent function
+call
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_errno(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the last error code for the most recent function call that can
+succeed or fail.
+Zero means no error occurred.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+Client error codes are listed in \f[C]errmsg.h\f[R] header file, server
+error codes are listed in \f[C]mysqld_error.h\f[R] header file of the
+server source distribution.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_error(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_sqlstate(3)\f[R]
diff --git a/libmariadb/man/mysql_error.3 b/libmariadb/man/mysql_error.3
new file mode 100644
index 00000000..a156a5af
--- /dev/null
+++ b/libmariadb/man/mysql_error.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_error" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_error \- returns the last error message for the most recent
+function call
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_error(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the last error message for the most recent function call that
+can succeed or fail.
+An empty string means no error occurred.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+Client error codes are listed in \f[C]errmsg.h\f[R] header file, server
+error codes are listed in \f[C]mysqld_error.h\f[R] header file of the
+server source distribution.
+.IP \[bu] 2
+Client error messages can be obtained by calling
+\f[B]mariadb_get_infov(3)\f[R] and passing the parameter
+\f[C]MARIADB_CLIENT_ERRORS\f[R]
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_errno(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_sqlstate(3)\f[R]
diff --git a/libmariadb/man/mysql_fetch_field.3 b/libmariadb/man/mysql_fetch_field.3
new file mode 100644
index 00000000..bb3e7e3c
--- /dev/null
+++ b/libmariadb/man/mysql_fetch_field.3
@@ -0,0 +1,49 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_fetch_field" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_fetch_field \- Returns the definition of one column of a result
+set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_FIELD * mysql_fetch_field(MYSQL_RES * result);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the definition of one column of a result set as a pointer to a
+MYSQL_FIELD structure.
+Call this function repeatedly to retrieve information about all columns
+in the result set.
+.SS Parameters
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+The field order will be reset if you execute a new SELECT query.
+.IP \[bu] 2
+In case only information for a specific field is required the field can
+be selected by using the \f[B]mysql_field_seek(3)\f[R] function or
+obtained by \f[B]mysql_fetch_field_direct(3)\f[R] function.
+.SS Return value
+.PP
+a pointer of a \f[C]MYSQL_FIELD\f[R] structure, or NULL if there are no
+more fields.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_field_seek(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_field_tell(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_fetch_field_direct(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
diff --git a/libmariadb/man/mysql_fetch_field_direct.3 b/libmariadb/man/mysql_fetch_field_direct.3
new file mode 100644
index 00000000..cc5d03ed
--- /dev/null
+++ b/libmariadb/man/mysql_fetch_field_direct.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_fetch_field_direct" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_fetch_field_direct \- Returns a pointer to a MYSQL_FIELD structure
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_FIELD * mysql_fetch_field_direct(MYSQL_RES * res,
+ unsigned int fieldnr);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a pointer to a \f[C]MYSQL_FIELD\f[R] structure which contains
+field information from the specified result set.
+### Parameter * \f[C]res\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+* \f[C]fieldnr\f[R] \- the field number.
+This value must be within the range from 0 to number of fields \- 1 ###
+Notes * The total number of fields can be obtained by
+mysql_field_count()
+.SS Return value
+.PP
+Pointer to a \f[C]MYSQL_FIELD\f[R] structure or \f[C]NULL\f[R] if an
+invalid field number was specified
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_fetch_field(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_field_count(3)\f[R]
diff --git a/libmariadb/man/mysql_fetch_fields.3 b/libmariadb/man/mysql_fetch_fields.3
new file mode 100644
index 00000000..cb9c2a22
--- /dev/null
+++ b/libmariadb/man/mysql_fetch_fields.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_fetch_fields" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_fetch_fields \- returns an array of fields
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_FIELD * mysql_fetch_fields(MYSQL_RES * res);
+\f[R]
+.fi
+.SS Description
+.PP
+This function serves an identical purpose to the
+\f[B]mysql_fetch_field(3)\f[R] function with the single difference that
+instead of returning one field at a time for each field, the fields are
+returned as an array.
+Each field contains the definition for a column of the result set.
+.SS Parameters
+.IP \[bu] 2
+\f[C]res\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+.SS Notes
+.PP
+The total number of fields can be obtained by
+\f[B]mysql_field_count(3)\f[R].
+.SS Return value
+.PP
+an array of type \f[C]MYSQL_FIELD\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_fetch_field(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_fetch_field_direct(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_field_count(3)\f[R]
diff --git a/libmariadb/man/mysql_fetch_lengths.3 b/libmariadb/man/mysql_fetch_lengths.3
new file mode 100644
index 00000000..deb99605
--- /dev/null
+++ b/libmariadb/man/mysql_fetch_lengths.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_fetch_lengths" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_fetch_lengths \- returns an array of length values for the current
+row
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned long * mysql_fetch_lengths(MYSQL_RES * result);
+\f[R]
+.fi
+.SS Description
+.PP
+The \f[C]mysql_fetch_lengths()\f[R] function returns an array containing
+the lengths of every column of the current row within the result set
+(not including terminating zero character) or \f[C]NULL\f[R] if an error
+occurred.
+.SS Parameter
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+### Notes \f[C]mysql_fetch_lengths()\f[R] is valid only for the current
+row of the result set.
+It returns \f[C]NULL\f[R] if you call it before calling
+\f[B]mysql_fetch_row(3)\f[R] or after retrieving all rows in the result.
+.SS Return value
+.PP
+An array of unsigned long values .
+The size of the array can be determined by the number of fields in
+current result set.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_field_count(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_fetch_row(3)\f[R]
diff --git a/libmariadb/man/mysql_fetch_row.3 b/libmariadb/man/mysql_fetch_row.3
new file mode 100644
index 00000000..2c20bf70
--- /dev/null
+++ b/libmariadb/man/mysql_fetch_row.3
@@ -0,0 +1,44 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_fetch_row" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_fetch_row \- fetches row of data from result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_ROW mysql_fetch_row(MYSQL_RES * result);
+\f[R]
+.fi
+.SS Description
+.PP
+Fetches one row of data from the result set and returns it as an array
+of char pointers (\f[C]MYSQL_ROW\f[R]), where each column is stored in
+an offset starting from 0 (zero).
+Each subsequent call to this function will return the next row within
+the result set, or NULL if there are no more rows.
+.SS Parameter
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+If a column contains a \f[C]NULL\f[R] value the corresponding char
+pointer will be set to \f[C]NULL\f[R].
+.IP \[bu] 2
+Memory associated to \f[C]MYSQL_ROW\f[R] will be freed when calling
+\f[B]mysql_free_result(3)\f[R] function.
+.SS Return value
+.PP
+A \f[C]MYSQL_ROW\f[R] structure (array of character pointers)
+representing the data of the current row.
+If there are no more rows available \f[C]NULL\f[R]will be returned.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_field_count.3 b/libmariadb/man/mysql_field_count.3
new file mode 100644
index 00000000..ad3144c6
--- /dev/null
+++ b/libmariadb/man/mysql_field_count.3
@@ -0,0 +1,43 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_field_count" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_field_count \- returns the number of columns for the most recent
+statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_field_count(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of columns for the most recent statement on the
+connection represented by the link parameter as an unsigned integer.
+This function can be useful when using the
+\f[B]mysql_store_result(3)\f[R] function to determine if the query
+should have produced a non\-empty result set or not without knowing the
+nature of the query.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+The \f[C]mysql_field_count()\f[R] function should be used to determine
+if there is a result set available.
+.SS Return value:
+.PP
+The number of columns for the most recent statemet.
+The value is zero, if the statemet didn\[cq]t produce a result set.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
diff --git a/libmariadb/man/mysql_field_seek.3 b/libmariadb/man/mysql_field_seek.3
new file mode 100644
index 00000000..364909aa
--- /dev/null
+++ b/libmariadb/man/mysql_field_seek.3
@@ -0,0 +1,43 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_field_seek" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_field_seek \- sets the field cursor to given offset
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES * result,
+ MYSQL_FIELD_OFFSET offset);
+\f[R]
+.fi
+.SS Description
+.PP
+Sets the field cursor to the given offset.
+The next call to \f[B]mysql_fetch_field(3)\f[R] will retrieve the field
+definition of the column associated with that offset.
+.SS Parameters
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+.IP \[bu] 2
+\f[C]offset\f[R] \- the field number.
+This number must be in the range from
+\f[C]0\f[R]..\f[C]number of fields \- 1\f[R].
+.SS Notes
+.IP \[bu] 2
+The number of fields can be obtained from \f[B]mysql_field_count(3)\f[R]
+\&.
+.IP \[bu] 2
+To move the field cursor to the first field offset parameter should be
+zero.
+.SS Return value
+.PP
+Returns the previous value of the field cursor
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_field_tell(3)\f[R]
diff --git a/libmariadb/man/mysql_field_tell.3 b/libmariadb/man/mysql_field_tell.3
new file mode 100644
index 00000000..ca0c6f8b
--- /dev/null
+++ b/libmariadb/man/mysql_field_tell.3
@@ -0,0 +1,32 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_field_tell" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_field_tell \- Returns offset of the field cursor
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES * result);
+\f[R]
+.fi
+.SS Description
+.PP
+Return the offset of the field cursor used for the last
+\f[B]mysql_fetch_field(3)\f[R] call.
+This value can be used as a parameter for the function
+\f[B]mysql_field_seek(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+.SS Return value
+.PP
+Returns the current offset of the field cursor
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_field_seek(3)\f[R]
diff --git a/libmariadb/man/mysql_free_result.3 b/libmariadb/man/mysql_free_result.3
new file mode 100644
index 00000000..4c138ea5
--- /dev/null
+++ b/libmariadb/man/mysql_free_result.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_free_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_free_result \- Frees result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_free_result(MYSQL_RES * result);
+\f[R]
+.fi
+.SS Description
+.PP
+Frees the memory associated with a result set.
+Returns void.
+.SS Parameters
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+You should always free your result set with mysql_free_result() as soon
+it\[cq]s not needed anymore
+.IP \[bu] 2
+Row values obtained by a prior \f[B]mysql_fetch_row(3)\f[R] call will
+become invalid after calling mysql_free_result().
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
diff --git a/libmariadb/man/mysql_get_character_set_info.3 b/libmariadb/man/mysql_get_character_set_info.3
new file mode 100644
index 00000000..3b9ef2f3
--- /dev/null
+++ b/libmariadb/man/mysql_get_character_set_info.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_character_set_info" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_character_set_info \- returns character set information
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_get_character_set_info(MYSQL * mysql,
+ MY_CHARSET_INFO * charset);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns information about the current default character set for the
+specified connection.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]charset\f[R] \- a pointer to a \f[C]MY_CHARSET_INFO\f[R] structure,
+in which the information will be copied.
+.SS Notes
+.IP \[bu] 2
+A complete list of supported character sets in the client library is
+listed in the function description for
+\f[B]mysql_set_character_set(3)\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_get_infov(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_set_character_set(3)\f[R]
diff --git a/libmariadb/man/mysql_get_client_info.3 b/libmariadb/man/mysql_get_client_info.3
new file mode 100644
index 00000000..59646f38
--- /dev/null
+++ b/libmariadb/man/mysql_get_client_info.3
@@ -0,0 +1,31 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_client_info" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_client_info \- returns client library version as string
+representation
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_get_client_info(void );
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a string representing the client library version
+.SS Notes
+.PP
+To obtain the numeric value of the client library version use
+\f[B]mysql_get_client_version(3)\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_client_version(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_get_host_info(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_get_proto_info(3)\f[R]
diff --git a/libmariadb/man/mysql_get_client_version.3 b/libmariadb/man/mysql_get_client_version.3
new file mode 100644
index 00000000..8c1fea4a
--- /dev/null
+++ b/libmariadb/man/mysql_get_client_version.3
@@ -0,0 +1,32 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_client_version" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_client_version \- returns client version number
+.SS Synopsis
+.IP
+.nf
+\f[C]
+unsigned long mysql_get_client_version(void);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a number representing the client library version.
+The value has the format XXYYZZ: major version * 10000 + minor version *
+100 + patch version.
+### Notes * To obtain a string containing the client library version use
+the \f[B]mysql_get_client_info(3)\f[R] function.
+* Note: Since MariaDB Server 10.2.6 and MariaDB Connector/C 3.0.1 the
+client library is bundled with server package and returns the server
+package version.
+To obtain the client version of the connector, please use the constant
+\f[C]MARIADB_PACKAGE_VERSION_ID\f[R]
+.SS Return value
+.PP
+A long integer representing the client version
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_client_info(3)\f[R]
diff --git a/libmariadb/man/mysql_get_host_info.3 b/libmariadb/man/mysql_get_host_info.3
new file mode 100644
index 00000000..9e0cf94e
--- /dev/null
+++ b/libmariadb/man/mysql_get_host_info.3
@@ -0,0 +1,32 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_host_info" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_host_info \- Returns host information
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+const char * mysql_get_host_info(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Describes the type of connection in use for the connection, including
+the server host name.
+Returns a string, or NULL if the connection is not valid.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+Returns a string, describing host information or \f[C]NULL\f[R] if the
+connection is not valid.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_server_version(3)\f[R]
diff --git a/libmariadb/man/mysql_get_proto_info.3 b/libmariadb/man/mysql_get_proto_info.3
new file mode 100644
index 00000000..6bc26f18
--- /dev/null
+++ b/libmariadb/man/mysql_get_proto_info.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_proto_info" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_proto_info \- Returns protocol version number
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_get_proto_info(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the protocol version number for the specified connection
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+MariaDB Connector/C doesn\[cq]t support protocol version 9 and prior.
+.SS Return value
+.PP
+The protocol version number in use
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_host_info(3)\f[R]
diff --git a/libmariadb/man/mysql_get_server_info.3 b/libmariadb/man/mysql_get_server_info.3
new file mode 100644
index 00000000..6f1d569a
--- /dev/null
+++ b/libmariadb/man/mysql_get_server_info.3
@@ -0,0 +1,37 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_server_info" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_server_info \- Returns server version as string
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_get_server_info(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the server version or \f[C]NULL\f[R] on failure.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+To obtain the numeric server version please use
+\f[B]mysql_get_server_version(3)\f[R].
+.SS Return value
+.PP
+Returns the server version as zero terminated string or \f[C]NULL\f[R]on
+failure.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_server_info(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_get_client_info(3)\f[R]
diff --git a/libmariadb/man/mysql_get_server_version.3 b/libmariadb/man/mysql_get_server_version.3
new file mode 100644
index 00000000..a74ab808
--- /dev/null
+++ b/libmariadb/man/mysql_get_server_version.3
@@ -0,0 +1,34 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_server_version" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_server_version \- returns numeric server version
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned long mysql_get_server_version(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns an integer representing the version of connected server.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+The form of the version number is VERSION_MAJOR * 10000 + VERSION_MINOR
+* 100 + VERSION_PATCH.
+.SS Return value
+.PP
+The version number of the connected server
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_server_info(3)\f[R]
diff --git a/libmariadb/man/mysql_get_socket.3 b/libmariadb/man/mysql_get_socket.3
new file mode 100644
index 00000000..a68e5e4f
--- /dev/null
+++ b/libmariadb/man/mysql_get_socket.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_socket" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_socket \- Returns the descriptor of the socket used for the
+current connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_socket mysql_get_socket(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the descriptor of the socket used for the current connection.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+A socket handle or INVALID_SOCKET (\-1) if the socket descriptor could
+not be determined, e.g.\ if the connection doesn\[cq]t use a socket
+connection.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_connect(3)\f[R]
diff --git a/libmariadb/man/mysql_get_ssl_cipher.3 b/libmariadb/man/mysql_get_ssl_cipher.3
new file mode 100644
index 00000000..5305d562
--- /dev/null
+++ b/libmariadb/man/mysql_get_ssl_cipher.3
@@ -0,0 +1,47 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_get_ssl_cipher" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_get_ssl_cipher \- returns the cipher suite in use
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char *mysql_get_ssl_cipher(MYSQL *mysql)
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the name of the currently used cipher suite of the secure
+connection, or NULL for non TLS connections.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+For using \f[C]mysql_get_ssl_cipher()\f[R] MariaDB Connector/C must be
+built with TLS/SSL support, otherwise the function will return NULL.
+.IP \[bu] 2
+\[ga]mysql_get_ssl_cipher()\[cq] can be used to determine if the client
+server connection is secure.
+.IP \[bu] 2
+Depending on the TLS library in use (OpenSSL, GnuTLS or Windows
+Schannel) the name of the cipher suites may differ.
+For example the cipher suite 0x002F
+(\f[C]TLS_RSA_WITH_AES_128_CBC_SHA\f[R]) has different names:
+\f[C]AES128\-SHA\f[R] for OpenSSL and Schannel and
+\f[C]TLS_RSA_AES_128_CBC_SHA1\f[R] for GnuTLS.
+.SS Return value
+.PP
+Returns a zero terminated string containing the cipher suite used for a
+secure connection, or \f[C]NULL\f[R] if connection doesn\[cq]t use
+TLS/SSL.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_ssl_set(3)\f[R]
diff --git a/libmariadb/man/mysql_hex_string.3 b/libmariadb/man/mysql_hex_string.3
new file mode 100644
index 00000000..da116595
--- /dev/null
+++ b/libmariadb/man/mysql_hex_string.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_hex_string" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_hex_string \- create a hexadecimal string
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+unsigned long mysql_hex_string(char * to,
+ const char * from,
+ unsigned long len);
+\f[R]
+.fi
+.SS Description
+.PP
+This function is used to create a hexadecimal string which can be used
+in SQL statements.
+e.g.\ \f[C]INSERT INTO my_blob VALUES(X\[aq]A0E1CD\[aq])\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]to\f[R] \- result buffer
+.IP \[bu] 2
+\f[C]from\f[R] \- the string which will be encoded
+.IP \[bu] 2
+\f[C]len\f[R] \- length of the string (from)
+.SS Notes
+.IP \[bu] 2
+The size of the buffer for the encoded string must be 2 * length + 1.
+.IP \[bu] 2
+The encoded string does not contain a leading X\[cq].
+.SS Return value
+.PP
+Returns the length of the encoded string without the trailing null
+character.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_escape_string(3)\f[R]
diff --git a/libmariadb/man/mysql_info.3 b/libmariadb/man/mysql_info.3
new file mode 100644
index 00000000..2b9cea23
--- /dev/null
+++ b/libmariadb/man/mysql_info.3
@@ -0,0 +1,76 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_info" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_info \- provides information about the last executed statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_info(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+The \f[C]mysql_info()\f[R] function returns a string providing
+information about the last statement executed.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+Statements which do not fall into one of the preceding formats are not
+supported (e.g.\ \f[C]SELECT\f[R]).
+In these situations mysql_info() will return an empty string.
+.SS Return value
+.PP
+Zero terminated information string.
+The information depends on statement type:
+.PP
+.TS
+tab(@);
+lw(35.0n) lw(35.0n).
+T{
+Query type
+T}@T{
+Example result string
+T}
+_
+T{
+\f[C]INSERT INTO...SELECT...\f[R]
+T}@T{
+Records: 100 Duplicates: 0 Warnings: 0
+T}
+T{
+\f[C]INSERT INTO...VALUES (...),(...),(...)\f[R]
+T}@T{
+Records: 3 Duplicates: 0 Warnings: 0
+T}
+T{
+\f[C]LOAD DATA INFILE\f[R]
+T}@T{
+Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
+T}
+T{
+\f[C]ALTER TABLE ...\f[R]
+T}@T{
+Records: 3 Duplicates: 0 Warnings: 0
+T}
+T{
+\f[C]UPDATE ...\f[R]
+T}@T{
+Rows matched: 40 Changed: 40 Warnings: 0
+T}
+.TE
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_affected_rows(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_warning_count(3)\f[R]
diff --git a/libmariadb/man/mysql_init.3 b/libmariadb/man/mysql_init.3
new file mode 100644
index 00000000..5f2c3f40
--- /dev/null
+++ b/libmariadb/man/mysql_init.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_init" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_init \- Prepares and initializes a \f[C]MYSQL\f[R] structure
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL *mysql_init(MYSQL *mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Prepares and initializes a \f[C]MYSQL\f[R] structure to be used with
+\f[B]mysql_real_connect(3)\f[R].
+If an address of a \f[C]MYSQL\f[R] structure was passed as parameter,
+the structure will be initialized, if \f[C]NULL\f[R] was passed, a new
+structure will be allocated and initialized.
+.PP
+\f[B]Notes:\f[R] * If parameter \f[C]mysql\f[R] is not \f[C]NULL\f[R]
+\f[B]mysql_close(3)\f[R] API function will not release the memory * Any
+subsequent calls to any function (except \f[B]mysql_optionsv(3)\f[R]
+will fail until \f[B]mysql_real_connect(3)\f[R] was called.
+* Memory allocated by \f[C]mysql_init()\f[R] must be freed with
+\f[B]mysql_close(3)\f[R].
+.SS Return value
+.PP
+The \f[C]mysql_init()\f[R] function returns an address of a
+\f[C]MYSQL\f[R] structure, or NULL in case of memory allcation error.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_close(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_optionsv(3)\f[R]
diff --git a/libmariadb/man/mysql_insert_id.3 b/libmariadb/man/mysql_insert_id.3
new file mode 100644
index 00000000..aa4b27e3
--- /dev/null
+++ b/libmariadb/man/mysql_insert_id.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_insert_id" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_insert_id \- returns the auto generated ID used in last statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_ulonglong mysql_insert_id(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the auto generated ID generated by a SQL statement (usually
+INSERT) on a table for a column defined with AUTO_INCREMENT attribute.
+.SS Parameters:
+.PP
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SH Return value
+.PP
+Returns the value of the modified column with AUTO_INCREMENT attribute.
+If the table doesn\[cq]t contain an auto_increment column or no
+INSERT/UPDATE statement was executed, this function will return zero.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_query(3)\f[R]
diff --git a/libmariadb/man/mysql_kill.3 b/libmariadb/man/mysql_kill.3
new file mode 100644
index 00000000..833a66ea
--- /dev/null
+++ b/libmariadb/man/mysql_kill.3
@@ -0,0 +1,51 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_kill" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_kill \- Kills a connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_kill(MYSQL * mysql,
+ unsigned long);
+\f[R]
+.fi
+.SS Description
+.PP
+This function is used to ask the server to kill a MariaDB thread
+specified by the processid parameter.
+This value must be retrieved by [show\-processlist()](SHOW
+PROCESSLIST]].
+If trying to kill the own connection \f[B]mysql_thread_id(3)\f[R] should
+be used.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+Returns 0 on success, otherwise nonzero.
+.IP \[bu] 2
+\f[C]long\f[R] \- process id
+.SS Notes
+.IP \[bu] 2
+To stop a running command without killing the connection use
+\f[C]KILL QUERY\f[R].
+.IP \[bu] 2
+The \f[C]mysql_kill()\f[R] function only kills a connection, it
+doesn\[cq]t free any memory \- this must be done explicitly by calling
+\f[B]mysql_close(3)\f[R].
+.SS Return value
+.PP
+Returns zero on success, non zero on error.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_thread_id(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_close(3)\f[R]
+.IP \[bu] 2
+\f[B]mariadb_cancel(3)\f[R]
diff --git a/libmariadb/man/mysql_more_results.3 b/libmariadb/man/mysql_more_results.3
new file mode 100644
index 00000000..d06dc61a
--- /dev/null
+++ b/libmariadb/man/mysql_more_results.3
@@ -0,0 +1,47 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_more_results" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_more_results \- indicates if one or more results are available
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_more_results(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Indicates if one or more result sets are available from a previous call
+to \f[B]mysql_real_query(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+The function \f[B]mysql_set_server_option(3)\f[R] enables or disables
+multi statement support.
+.IP \[bu] 2
+Multiple result sets can be obtained either by calling a stored
+procedure or by executing concatenated statements,
+e.g.\ \f[C]SELECT a FROM t1;SELECT b, c FROM t2\f[R].
+.SS Return value
+.PP
+Returns 1 if more result sets are available, otherwise zero.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_query(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_next_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_set_server_option(3)\f[R]
diff --git a/libmariadb/man/mysql_next_result.3 b/libmariadb/man/mysql_next_result.3
new file mode 100644
index 00000000..92da0942
--- /dev/null
+++ b/libmariadb/man/mysql_next_result.3
@@ -0,0 +1,45 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_next_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_next_result \- prepares next result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_next_result(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Prepares next result set from a previous call to
+\f[B]mysql_real_query(3)\f[R] which can be retrieved by
+\f[B]mysql_store_result(3)\f[R] or
+[mysql_use_result()](()](mysql_use_result).
+Returns zero on success, nonzero if an error occurred.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+If a multi query contains errors the return value of
+\f[B]mysql_errno(3)\f[R] and \f[B]mysql_error(3)\f[R] might change and
+there will be no result set available.
+.SS Return value
+.PP
+Returns zero on success, non zero value on error.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_query(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_more_results(3)\f[R]
diff --git a/libmariadb/man/mysql_num_fields.3 b/libmariadb/man/mysql_num_fields.3
new file mode 100644
index 00000000..0839f1e4
--- /dev/null
+++ b/libmariadb/man/mysql_num_fields.3
@@ -0,0 +1,31 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_num_fields" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_num_fields \- Returns number of fields in a result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_num_fields(MYSQL_RES * );
+\f[R]
+.fi
+.SS Description
+.PP
+Returns number of fields in a specified result set.
+.SS Parameter
+.IP \[bu] 2
+\f[C]MYSQL RES *\f[R] \- A result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+.SS Return value
+.PP
+Returns number of fields.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_fetch_field(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_field_count(3)\f[R]
diff --git a/libmariadb/man/mysql_num_rows.3 b/libmariadb/man/mysql_num_rows.3
new file mode 100644
index 00000000..c4c25d84
--- /dev/null
+++ b/libmariadb/man/mysql_num_rows.3
@@ -0,0 +1,35 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_num_rows" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_num_rows \- Returns number of rows in a result set.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_ulonglong mysql_num_rows(MYSQL_RES * );
+\f[R]
+.fi
+.SS Description
+.PP
+Returns number of rows in a result set.
+.SS Parameters
+.IP \[bu] 2
+\f[C]MYSQL_RES\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R] or \f[B]mysql_use_result(3)\f[R].
+### Notes The behaviour of \f[C]mysql_num_rows()\f[R] depends on whether
+buffered or unbuffered result sets are being used.
+For unbuffered result sets, \f[C]mysql_num_rows()\f[R] will not return
+the correct number of rows until all the rows in the result have been
+retrieved.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_affected_rows(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_options.3 b/libmariadb/man/mysql_options.3
new file mode 100644
index 00000000..eafc83bc
--- /dev/null
+++ b/libmariadb/man/mysql_options.3
@@ -0,0 +1,37 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_options" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_options \- Used to set extra connect options and affect behavior
+of a connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_options(MYSQL * mysql,
+ enum mysql_option,
+ const void * arg);
+\f[R]
+.fi
+.SS Description
+.PP
+Used to set extra connect options and affect behavior for a connection.
+This function may be called multiple times to set several options.
+\f[C]mysql_options()\f[R] should be called after
+\f[B]mysql_init(3)\f[R].
+.SS Notes
+.PP
+This function is deprecated, new implementations should use
+\f[B]mysql_optionsv(3)\f[R] api function instead.
+.SS Options
+.PP
+An overview of the possible options can be found in the description of
+the \f[B]mysql_optionsv(3)\f[R] API function.
+.SS See Also
+.PP
+\f[I]\f[BI]mysql_init(3)\f[I] \f[R]\f[B]mysql_optionsv(3)\f[R]
+*\f[B]mysql_real_connect(3)\f[R]
diff --git a/libmariadb/man/mysql_options4.3 b/libmariadb/man/mysql_options4.3
new file mode 100644
index 00000000..e3c4c6f6
--- /dev/null
+++ b/libmariadb/man/mysql_options4.3
@@ -0,0 +1,38 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_options4" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_options4 \- Used to set extra connect options and affect behavior
+of a connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_options4(MYSQL * mysql,
+ enum mysql_option,
+ const void * arg1,
+ const void * arg2);
+\f[R]
+.fi
+.SS Description
+.PP
+Used to set extra connect options and affect behavior for a connection.
+This function may be called multiple times to set several options.
+\f[C]mysql_options()\f[R] should be called after
+\f[B]mysql_init(3)\f[R].
+.SS Notes
+.PP
+This function is deprecated, new implementations should use
+\f[B]mysql_optionsv(3)\f[R] api function instead.
+.SS Options
+.PP
+An overview of the possible options can be found in the description of
+the \f[B]mysql_optionsv(3)\f[R] API function.
+.SS See Also
+.PP
+\f[I]\f[BI]mysql_init(3)\f[I] \f[R]\f[B]mysql_optionsv(3)\f[R]
+*\f[B]mysql_real_connect(3)\f[R]
diff --git a/libmariadb/man/mysql_optionsv.3 b/libmariadb/man/mysql_optionsv.3
new file mode 100644
index 00000000..b59e0ff4
--- /dev/null
+++ b/libmariadb/man/mysql_optionsv.3
@@ -0,0 +1,420 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_optionsv" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_optionsv \- Used to set extra connect options and affect behavior
+of a connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_optionsv(MYSQL * mysql,
+ enum mysql_option,
+ const void * arg,
+ ...);
+\f[R]
+.fi
+.SS Description
+.PP
+Used to set extra connect options and affect behavior for a connection.
+This function may be called multiple times to set several options.
+\f[C]mysql_optionsv()\f[R] should be called after
+\f[B]mysql_init(3)\f[R].
+.SS Options
+.PP
+The following table shows which variable type to use for each option.
+.PP
+.TS
+tab(@);
+lw(35.0n) lw(35.0n).
+T{
+Variable Type
+T}@T{
+Values
+T}
+_
+T{
+\f[C]my_bool\f[R]
+T}@T{
+\f[C]MYSQL_OPT_RECONNECT\f[R], \f[C]MYSQL_SECURE_AUTH\f[R],
+\f[C]MYSQL_REPORT_DATA_TRUNCATION\f[R], \f[C]MYSQL_OPT_SSL_ENFORCE\f[R],
+\f[C]MYSQL_OPT_SSL_VERIFY_SERVER_CERT\f[R]
+T}
+T{
+\f[C]unsigned int\f[R]
+T}@T{
+\f[C]MYSQL_OPT_PORT\f[R], \f[C]MYSQL_OPT_LOCAL_INFILE\f[R],
+\f[C]MYSQL_OPT_CONNECT_TIMEOUT\f[R], \f[C]MYSQL_OPT_PROTOCOL\f[R],
+\f[C]MYSQL_OPT_READ_TIMEOUT\f[R], \f[C]MYSQL_OPT_WRITE_TIMEOUT\f[R]
+T}
+T{
+\f[C]unsigned long\f[R]
+T}@T{
+\f[C]MYSQL_OPT_NET_BUFFER_LENGTH\f[R],
+\f[C]MYSQL_OPT_MAX_ALLOWED_PACKET\f[R]
+T}
+T{
+\f[C]const char *\f[R]
+T}@T{
+\f[C]MYSQL_INIT_COMMAND\f[R], \f[C]MARIADB_OPT_UNIXSOCKET\f[R],
+\f[C]MARIADB_OPT_PASSWORD\f[R] , \f[C]MARIADB_OPT_USER\f[R],
+\f[C]MARIADB_OPT_HOST\f[R], \f[C]MARIADB_OPT_SCHEMA\f[R],
+\f[C]MYSQL_OPT_SSL_KEY\f[R], \f[C]MYSQL_OPT_SSL_CERT\f[R],
+\f[C]MYSQL_OPT_SSL_CA\f[R], \f[C]MYSQL_OPT_SSL_CAPATH\f[R],
+\f[C]MYSQL_SET_CHARSET_NAME\f[R], \f[C]MYSQL_SET_CHARSET_DIR\f[R],
+\f[C]MYSQL_OPT_SSL_CIPHER\f[R], \f[C]MYSQL_SHARED_MEMORY_BASE_NAME\f[R],
+\f[C]MYSQL_PLUGIN_DIR\f[R], \f[C]MYSQL_DEFAULT_AUTH\f[R],
+\f[C]MARIADB_OPT_SSL_FP\f[R], \f[C]MARIADB_OPT_SSL_FP_LIST\f[R],
+\f[C]MARIADB_OPT_TLS_PASSPHRASE\f[R], \f[C]MARIADB_OPT_TLS_VERSION\f[R],
+\f[C]MYSQL_OPT_BIND\f[R], \f[C]MYSQL_OPT_CONNECT_ATTR_DELETE\f[R],
+\f[C]MYSQL_OPT_CONNECT_ATTR_ADD\f[R],
+\f[C]MARIADB_OPT_CONNECTION_HANDLER\f[R],
+\f[C]MYSQL_SERVER_PUBLIC_KEY\f[R], \f[C]MARIADB_OPT_RESTRICTED_AUTH\f[R]
+T}
+T{
+\-
+T}@T{
+\f[C]MYSQL_OPT_CONNECT_ATTR_RESET\f[R]
+T}
+T{
+void *
+T}@T{
+\f[C]MARIADB_OPT_PROXY_HEADER\f[R]
+T}
+.TE
+.IP \[bu] 2
+\f[C]MYSQL_INIT_COMMAND\f[R]
+.PD 0
+.P
+.PD
+Command(s) which will be executed when connecting and reconnecting to
+the server.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_COMPRESS\f[R]
+.PD 0
+.P
+.PD
+Use the compressed protocol for client server communication.
+If the server doesn\[cq]t support compressed protocol, the default
+protocol will be used.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_CONNECT_TIMEOUT\f[R]
+.PD 0
+.P
+.PD
+Connect timeout in seconds.
+This value will be passed as an unsigned ##int## parameter.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_LOCAL_INFILE\f[R]
+.PD 0
+.P
+.PD
+Enable or disable the use of \f[C]LOAD DATA LOCAL INFILE\f[R]
+.IP \[bu] 2
+\f[C]MYSQL_OPT_NAMED_PIPE\f[R]
+.PD 0
+.P
+.PD
+For Windows operating systems only: Use named pipes for client/server
+communication.
+.IP \[bu] 2
+\f[C]MYSQL_PROGRESS_CALLBACK\f[R]
+.PD 0
+.P
+.PD
+Specifies a callback function which will be able to visualize the
+progress of certain long running statements
+(i.e.\ \f[C]LOAD DATA LOCAL INFILE\f[R] or \f[C]ALTER TABLE\f[R]).
+The callback function must be defined as followed:
+.IP
+.nf
+\f[C]
+static void report_progress(const MYSQL *mysql __attribute__((unused)),
+ uint stage, uint max_stage,
+ double progress __attribute__((unused)),
+ const char *proc_info __attribute__((unused)),
+ uint proc_info_length __attribute__((unused)))
+\f[R]
+.fi
+.IP \[bu] 2
+\f[C]MYSQL_OPT_PROTOCOL\f[R]
+.PD 0
+.P
+.PD
+Specify the type of client/server protocol.
+Possible values are: \f[C]MYSQL_PROTOCOL_TCP\f[R],
+\f[C]MYSQL_PROTOCOL_SOCKET\f[R], \f[C]MYSQL_PROTOCOL_PIPE\f[R] and
+\f[C]MYSQL_PROTOCOL_MEMORY\f[R].
+.IP \[bu] 2
+\f[C]MYSQL_OPT_RECONNECT\f[R]
+.PD 0
+.P
+.PD
+Enable or disable automatic reconnect.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_READ_TIMEOUT\f[R]
+.PD 0
+.P
+.PD
+Specifies the timeout in seconds for reading packets from the server.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_WRITE_TIMEOUT\f[R]
+.PD 0
+.P
+.PD
+Specifies the timeout in seconds for sending packets to the server.
+.IP \[bu] 2
+\f[C]MYSQL_READ_DEFAULT_FILE\f[R]
+.PD 0
+.P
+.PD
+Read options from named configuration file.
+To read from default \f[C]my.cnf\f[R] configuration file, a NULL pointer
+has to be passed with option MYSQL_READ_DEFAULT_GROUP.
+\f[B]Note:\f[R] MariaDB Connector/C will not read the configuration by
+default.
+If \f[C]MYSQL_READ_DEFAULT_FILE\f[R] is specified the following sections
+will be always processed:
+.IP \[bu] 2
+[client]
+.IP \[bu] 2
+[client\-server]
+.IP \[bu] 2
+[client\-mariadb]
+.IP \[bu] 2
+\f[C]MYSQL_READ_DEFAULT_GROUP\f[R]
+.PD 0
+.P
+.PD
+Read options from the named group from default configuration
+file (config_files) or the file specified with MYSQL_READ_DEFAULT_FILE.
+.IP \[bu] 2
+\f[C]MYSQL_REPORT_DATA_TRUNCATION\f[R]
+.PD 0
+.P
+.PD
+Enable or disable reporting data truncation errors for prepared
+statements.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_BIND\f[R]
+.PD 0
+.P
+.PD
+Specify the network interface from which to connect to MariaDB Server.
+.IP \[bu] 2
+\f[C]MYSQL_PLUGIN_DIR\f[R]
+.PD 0
+.P
+.PD
+Specify the location of client plugins.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_NONBLOCK\f[R]
+.PD 0
+.P
+.PD
+Specify stack size for non blocking operations.
+The argument for MYSQL_OPT_NONBLOCK is the size of the stack used to
+save the state of a non\-blocking operation while it is waiting for I/O
+and the application is doing other processing.
+Normally, applications will not have to change this, and it can be
+passed as zero to use the default value.
+.IP \[bu] 2
+\f[C]MARIADB_OPT_CONNECTION_HANDLER\f[R]
+.PD 0
+.P
+.PD
+Specify the name of a connection handler plugin.
+.IP \[bu] 2
+\f[C]MARIADB_OPT_USERDATA\f[R]
+.PD 0
+.P
+.PD
+Bundle user data to the current connection, e.g.\ for use in connection
+handler plugins.
+This option requires 4 parameters: connection, option, key and value:
+.IP
+.nf
+\f[C]
+mysql_optionsv(mysql, MARIADB_OPT_USERDATA, (void *)\[dq]ssh_user\[dq], (void *)ssh_user);
+\f[R]
+.fi
+.IP \[bu] 2
+\f[C]MARIADB_OPT_CONNECTION_READ_ONLY\f[R]
+.PD 0
+.P
+.PD
+This option is used by connection handler plugins and indicates that the
+current connection will be used for read operations only.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS\f[R]
+.PD 0
+.P
+.PD
+If this option is set, the client indicates that it will be able to
+handle expired passwords by setting the
+\f[C]CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS\f[R] capability flag.
+If the password has expired and
+\f[C]CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS\f[R] is set, the server will
+not return an error when connecting, but put the connection in sandbox
+mode, where all commands will return error 1820
+(\f[C]ER_MUST_CHANGE_PASSWORD\f[R]) unless a new password was set.
+This option was added in MariaDB Connector/C 3.0.4
+.SS TLS/SSL and Security options
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_KEY\f[R]
+.PD 0
+.P
+.PD
+Specify the name of a key for a secure connection.
+If the key is protected with a passphrase, the passphrase needs to be
+specified with \f[C]MARIADB_OPT_PASSPHRASE\f[R] option.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_CERT\f[R]
+.PD 0
+.P
+.PD
+Specify the name of a certificate for a secure connection.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_CA\f[R]
+.PD 0
+.P
+.PD
+Specify the name of a file which contains one or more trusted CAs.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_CAPATH\f[R]
+.PD 0
+.P
+.PD
+Specify the path which contains trusted CAs.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_CIPHER\f[R]
+.PD 0
+.P
+.PD
+Specify one or more (SSLv3, TLSv1.0 or TLSv1.2) cipher suites for TLS
+encryption.
+Even if Connector/C supports TLSv1.3 protocol, it is not possible yet to
+specify TLSv1.3 cipher suites.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_CRL\f[R]
+.PD 0
+.P
+.PD
+Specify a file with a certificate revocation list.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_CRLPATH\f[R]
+.PD 0
+.P
+.PD
+Specify a directory with contains files with certificate revocation
+lists.
+.IP \[bu] 2
+\f[C]MARIADB_OPT_SSL_FP\f[R]
+.PD 0
+.P
+.PD
+Specify the SHA1 fingerprint of a server certificate for validation
+during the TLS handshake.
+.IP \[bu] 2
+\f[C]MARIADB_OPT_SSL_FP\f[R]
+.PD 0
+.P
+.PD
+Specify a file which contains one or more SHA1 fingerprints of server
+certificates for validation during the TLS handshake.
+.IP \[bu] 2
+\f[C]MARIADB_OPT_SSL_PASPHRASE\f[R]
+.PD 0
+.P
+.PD
+Specify a passphrase for a passphrase protected client key.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_SSL_VERIFY_SERVER_CERT\f[R]
+.PD 0
+.P
+.PD
+Enable (or disable) the verification of the hostname against common name
+(CN) of the server\[cq]s host certificate.
+.IP \[bu] 2
+\f[C]MYSQL_SERVER_PUBLIC_KEY\f[R]
+.PD 0
+.P
+.PD
+Specifies the name of the file which contains the RSA public key of the
+database server.
+The format of this file must be in PEM format.
+This option is used by the caching_sha2_password plugin and was added in
+Connector/C 3.1.0
+.IP \[bu] 2
+\f[C]MARIADB_OPT_TLS_CIPHER_STRENGTH\f[R]
+.PD 0
+.P
+.PD
+This option is not in use anymore.
+.IP \[bu] 2
+\f[C]MARIADB_OPT_RESTRICTED_AUTH\f[R]
+.PD 0
+.P
+.PD
+Specifies one or more comma separated authentication plugins which are
+allowed for authentication.
+If the database server asks for an authentication plugin not listed in
+this option, MariaDB Connector/C will return an error.
+This option was added in MariaDB Connector/C 3.3.0
+.SS Proxy settings
+.PP
+As per the proxy protocol specification, the connecting client can
+prefix its first packet with a proxy protocol header.
+The server will parse the header and assume the client\[cq]s IP address
+is the one set in the proxy header.
+* \f[C]MARIADB_OPT_PROXY_HEADER\f[R] \- specifies the proxy header which
+will be prefixed to the first packet.
+Parameters are void * for the prefix buffer and size_t for length of the
+buffer:
+.IP
+.nf
+\f[C]
+const char *hdr=\[dq]PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\[rs]r\[rs]n\[dq];
+mysql_optionsv(mysql, MARIADB_OPT_PROXY_HEADER, hdr, strlen(hdr));
+\f[R]
+.fi
+.SS Connection Attributes
+.PP
+Connection attributes are stored in the \f[C]session_connect_attrs\f[R]
+and \f[C]session_account_connect_attrs\f[R]Performance Schema tables.
+By default, MariaDB Connector/C sends the following connection
+attributes to the server: * \f[C]_client_name\f[R]: always
+\[lq]libmariadb\[rq] * \f[C]_client_version\f[R]: version of MariaDB
+Connector/C * \f[C]_os\f[R]: operation system * _pid: process id *
+\f[C]_platform\f[R]: e.g.\ x86 or x64 * \f[C]_server_host\f[R]: the
+hostname (as specified in mysql_real_connect).
+This attribute was added in Connector/C 3.0.5
+.PP
+\f[B]Note:\f[R] If the Performance Schema is disabled, connection
+attributes will not be stored on server.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_CONNECT_ATTR_DELETE\f[R]
+.PD 0
+.P
+.PD
+Deletes a connection attribute for the given key.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_CONNECT_ATTR_ADD\f[R]
+.PD 0
+.P
+.PD
+Adds a key/value pair to connection attributes.
+.IP \[bu] 2
+\f[C]MYSQL_OPT_CONNECT_ATTR_RESET\f[R]
+.PD 0
+.P
+.PD
+Clears the current list of connection attributes.
+.SS See Also
+.PP
+\f[I]\f[BI]mysql_init(3)\f[I] \f[R]\f[B]mysql_real_connect(3)\f[R]
diff --git a/libmariadb/man/mysql_ping.3 b/libmariadb/man/mysql_ping.3
new file mode 100644
index 00000000..40150920
--- /dev/null
+++ b/libmariadb/man/mysql_ping.3
@@ -0,0 +1,44 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_ping" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_ping \- checks if the connection between client and server is
+working
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_ping(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Checks whether the connection to the server is working.
+If it has gone down, and global option reconnect is enabled an automatic
+reconnection is attempted.
+.PP
+This function can be used by clients that remain idle for a long while,
+to check whether the server has closed the connection and reconnect if
+necessary.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+### Notes
+.IP \[bu] 2
+If a reconnect occurred the thread_id will change.
+Also resources bundled to the connection (prepared statements, locks,
+temporary tables, \&...) will be released.
+.SS Return value
+.PP
+Returns zero on success, nonzero if an error occured.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_optionsv(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_kill(3)\f[R]
diff --git a/libmariadb/man/mysql_query.3 b/libmariadb/man/mysql_query.3
new file mode 100644
index 00000000..f416d426
--- /dev/null
+++ b/libmariadb/man/mysql_query.3
@@ -0,0 +1,56 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_query" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_query \- executes a null terminated statement string
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_query(MYSQL * mysql,
+ const char * query);
+\f[R]
+.fi
+.SS Description
+.PP
+Performs a statement pointed to by the null terminate string query
+against the database.
+Contrary to \f[B]mysql_real_query(3)\f[R], mysql_query() is not binary
+safe.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]query\f[R] \-a null terminated string containing the statement to
+be performed.
+.SS Notes
+.IP \[bu] 2
+For executing multi statements the statements within the null terminated
+string statements must be separated by a semicolon.
+.IP \[bu] 2
+If your statement contains binary data you should use
+\f[B]mysql_real_query(3)\f[R] or escape your data with
+\f[B]mysql_hex_string(3)\f[R].
+.IP \[bu] 2
+To determine if a statement returned a result set use the function
+\f[B]mysql_field_count(3)\f[R].
+.SS Return value
+.PP
+Returns zero on success, non zero on failure.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_query(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_field_count(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_hex_string(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_read_query_result.3 b/libmariadb/man/mysql_read_query_result.3
new file mode 100644
index 00000000..5f066f0f
--- /dev/null
+++ b/libmariadb/man/mysql_read_query_result.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_read_query_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_read_query_result \- waits for a server result or response package
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_read_query_result(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Waits for a server result set or response package from a previously
+executed \f[B]mysql_send_query(3)\f[R].
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+Zero on success, non zero on error.
+.SS Example
+.PP
+For an example how to use \[cq]mysql_send_query()\[ga] in an event
+driven model, please check Jan Kneschke\[cq]s Blog entry \[lq]Async
+MySQL Queries with
+C\-API\[rq] (https://jan.kneschke.de/projects/mysql/async-mysql-queries-with-c-api/).
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_query(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_send_query(3)\f[R]
diff --git a/libmariadb/man/mysql_real_connect.3 b/libmariadb/man/mysql_real_connect.3
new file mode 100644
index 00000000..3a7a7f60
--- /dev/null
+++ b/libmariadb/man/mysql_real_connect.3
@@ -0,0 +1,171 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_real_connect" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_real_connect \- establishes a connection to a MariaDB database
+server
+.SS Synopsis
+.IP
+.nf
+\f[C]
+MYSQL * mysql_real_connect(MYSQL *mysql,
+ const char *host,
+ const char *user,
+ const char *passwd,
+ const char *db,
+ unsigned int port,
+ const char *unix_socket,
+ unsigned long flags);
+\f[R]
+.fi
+.SS Description
+.PP
+Establishes a connection to a database server.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R]
+.IP \[bu] 2
+\f[C]host\f[R] \- can be either a host name or an IP address.
+Passing the NULL value or the string \[lq]localhost\[rq] to this
+parameter, the local host is assumed.
+When possible, pipes will be used instead of the TCP/IP protocol.
+Since version 3.3.0 it is also possible to provide a comma separated
+list of hosts for simple fail over in case of one or more hosts are not
+available.
+.IP \[bu] 2
+\f[C]user\f[R] \- the user name.
+.IP \[bu] 2
+\f[C]passwd\f[R] \- If provided or NULL, the server will attempt to
+authenticate the user against those user records which have no password
+only.
+This allows one username to be used with different permissions
+(depending on if a password as provided or not).
+.IP \[bu] 2
+\f[C]db\f[R] \- if provided will specify the default database to be used
+when performing queries.
+.IP \[bu] 2
+\f[C]port\f[R] \- specifies the port number to attempt to connect to the
+server.
+.IP \[bu] 2
+\f[C]unix_socket\f[R] \- specifies the socket or named pipe that should
+be used.
+.IP \[bu] 2
+\f[C]flags\f[R] \- the flags allows various connection options to be set
+.PD 0
+.P
+.PD
+.PP
+.TS
+tab(@);
+lw(35.0n) lw(35.0n).
+T{
+Flag
+T}@T{
+Description
+T}
+_
+T{
+\f[C]CLIENT_FOUND_ROWS\f[R]
+T}@T{
+Return the number of matched rows instead of number of changed rows.
+T}
+T{
+\f[C]CLIENT_NO_SCHEMA\f[R]
+T}@T{
+Forbids the use of database.tablename.column syntax and forces the SQL
+parser to generate an error.
+T}
+T{
+\f[C]CLIENT_COMPRESS\f[R]
+T}@T{
+Use compression protocol
+T}
+T{
+\f[C]CLIENT_IGNORE_SPACE\f[R]
+T}@T{
+Allows spaces after function names.
+All function names will become reserved words.
+T}
+T{
+\f[C]CLIENT_LOCAL_FILES\f[R]
+T}@T{
+Allows LOAD DATA LOCAL statements
+T}
+T{
+\f[C]CLIENT_MULTI_STATEMENTS\f[R]
+T}@T{
+Allows the client to send multiple statements in one command.
+Statements will be divided by a semicolon.
+T}
+T{
+\f[C]CLIENT_MULTI_RESULTS\f[R]
+T}@T{
+Indicates that the client is able to handle multiple result sets from
+stored procedures or multi statements.
+This option will be automatically set if CLIENT_MULTI_STATEMENTS is set.
+T}
+T{
+\f[C]CLIENT_REMEMBER_OPTIONS\f[R]
+T}@T{
+Rembers options passed to \f[B]mysql_optionsv(3)\f[R] if a connect
+attempt failed.
+If MYSQL_OPTIONS_RECONNECT option was set to true, options will be saved
+and used for reconnection.
+T}
+.TE
+.SS Return value
+.PP
+returns a connection handle (same as passed for 1st parameter) or NULL
+on error.
+On error, please check \f[B]mysql_errno(3)\f[R] and
+\f[B]mysql_error(3)\f[R] functions for more information.
+.SS Notes
+.IP \[bu] 2
+The password doesn\[cq]t need to be encrypted before executing
+mysql_real_connect().
+This will be handled in the client server protocol.
+.IP \[bu] 2
+The connection handle can\[cq]t be reused for establishing a new
+connection.
+It must be closed and reinitialized before.
+.IP \[bu] 2
+mysql_real_connect() must complete successfully before you can execute
+any other API functions beside \f[B]mysql_optionsv(3)\f[R].
+.IP \[bu] 2
+host parameter may contain multiple host/port combinations (supported
+since version 3.3.0).
+The following syntax is required:
+.RS 2
+.IP \[bu] 2
+hostname and port must be seperated by a colon (:)
+.IP \[bu] 2
+IPv6 addresses must be enclosed within square brackets
+.IP \[bu] 2
+hostname:port pairs must be be seperated by a comma (,)
+.IP \[bu] 2
+if only one host:port was specified, the host string needs to end with a
+comma.
+.IP \[bu] 2
+if no port was specified, the default port will be used.
+.PP
+\f[B]Examples for failover host string:\f[R]
+.PP
+\f[C]host=[::1]:3306,192.168.0.1:3306,test.example.com\f[R]
+.PP
+\f[C]host=127.0.0.1:3306,\f[R]
+.RE
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_init(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_close(3)\f[R]
+.IP \[bu] 2
+\f[B]mariadb_reconnect(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_error(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_errno(3)\f[R]
diff --git a/libmariadb/man/mysql_real_escape_string.3 b/libmariadb/man/mysql_real_escape_string.3
new file mode 100644
index 00000000..0a0f51f4
--- /dev/null
+++ b/libmariadb/man/mysql_real_escape_string.3
@@ -0,0 +1,49 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_real_escape_string" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_real_escape_string \- escape string by taking into account
+character set of connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned long mysql_real_escape_string(MYSQL * mysql,
+ char * to,
+ const char * from,
+ unsigned long);
+\f[R]
+.fi
+.SS Description
+.PP
+This function is used to create a legal SQL string that you can use in
+an SQL statement.
+The given string is encoded to an escaped SQL string, taking into
+account the current character set of the connection.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]to\f[R] \- buffer for the encoded string.
+The size of this buffer must be length * 2 + 1 bytes: in worst case
+every character of the from string needs to be escaped.
+Additionally a trailing 0 character will be appended.
+.IP \[bu] 2
+\f[C]from\f[R] \- a string which will be encoded by
+mysql_real_escape_string().
+.IP \[bu] 2
+\f[C]long\f[R] \- the length of the \f[C]from\f[R] string.
+.SS Return value
+.PP
+Returns the length of the encoded (to) string.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_escape_string(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_hex_string(3)\f[R]
diff --git a/libmariadb/man/mysql_real_query.3 b/libmariadb/man/mysql_real_query.3
new file mode 100644
index 00000000..a3f33796
--- /dev/null
+++ b/libmariadb/man/mysql_real_query.3
@@ -0,0 +1,50 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_real_query" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_real_query \- execute a statement (binary safe)
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_real_query(MYSQL * mysql,
+ const char * query,
+ unsigned long length);
+\f[R]
+.fi
+.SS Description
+.PP
+mysql_real_query() is the binary safe function for performing a
+statement on the database server.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]query\f[R] \- a string containing the statement to be performed.
+.IP \[bu] 2
+\f[C]length\f[R] \- length of the string.
+.SS Notes
+.IP \[bu] 2
+Contrary to the \f[B]mysql_query(3)\f[R] function, mysql_real_query is
+binary safe.
+.IP \[bu] 2
+To determine if mysql_real_query returns a result set use the
+\f[B]mysql_num_fields(3)\f[R] function.
+.SS Return value
+.PP
+Returns zero on success, otherwise non zero.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_query(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_num_fields(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_use_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_refresh.3 b/libmariadb/man/mysql_refresh.3
new file mode 100644
index 00000000..dd1c098f
--- /dev/null
+++ b/libmariadb/man/mysql_refresh.3
@@ -0,0 +1,92 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_refresh" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_refresh \- flushes information on the server
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_refresh(MYSQL * mysql, unsigned int options);
+\f[R]
+.fi
+.SS Description
+.PP
+Flushes different types of information stored on the server.
+The bit\-masked parameter options specify which kind of information will
+be flushed.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]options\f[R] \- a bit masked composed integer.
+See below.
+.PP
+\f[C]options\f[R] can be any combinationation of the following flags:
+.PP
+.TS
+tab(@);
+l l.
+T{
+Option
+T}@T{
+Description
+T}
+_
+T{
+\f[C]REFRESH_GRANT\f[R]
+T}@T{
+Refresh grant tables.
+T}
+T{
+\f[C]REFRESH_LOG\f[R]
+T}@T{
+Flush logs.
+T}
+T{
+\f[C]REFRESH_TABLES\f[R]
+T}@T{
+Flush table cache.
+T}
+T{
+\f[C]REFRESH_HOSTS\f[R]
+T}@T{
+Flush host cache.
+T}
+T{
+\f[C]REFRESH_STATUS\f[R]
+T}@T{
+Reset status variables.
+T}
+T{
+\f[C]REFRESH_THREADS\f[R]
+T}@T{
+Flush thread cache.
+T}
+T{
+\f[C]REFRESH_SLAVE\f[R]
+T}@T{
+Reset master server information and restart slaves.
+T}
+T{
+\f[C]REFRESH_MASTER\f[R]
+T}@T{
+Remove binary log files.
+T}
+.TE
+.SS Notes
+.IP \[bu] 2
+To combine different values in the options parameter use the OR operator
+`|'.
+.IP \[bu] 2
+\f[C]mysql_reload()\f[R] is an alias for mysql_refresh().
+.SS Return value
+.PP
+Returns zero on success, otherwise non zero.
diff --git a/libmariadb/man/mysql_reset_connection.3 b/libmariadb/man/mysql_reset_connection.3
new file mode 100644
index 00000000..8cd4ef5c
--- /dev/null
+++ b/libmariadb/man/mysql_reset_connection.3
@@ -0,0 +1,48 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_reset_connection" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_reset_connection \- Resets connection and clears session state
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_reset_connection(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Resets the current connection and clears session state.
+Similar to \f[B]mysql_change_user(3)\f[R] or
+\f[B]mariadb_reconnect(3)\f[R], mysql_reset_connection() resets session
+status, but without disconnecting, opening, or reauthenticating.
+.PP
+On client side mysql_reset_connection() * clears pending or unprocessed
+result sets * clears status like affected_rows, info or last_insert_id *
+invalidates active prepared statements
+.PP
+On server side mysql_reset_connection() * drops temporary table(s) *
+rollbacks active transaction * resets autocommit mode * releases table
+locks * initializes session variables (and sets them to the value of
+corresponding global variables) * closes active prepared statements *
+clears user variables
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+Returns zero on success, non zero if an error occurred.
+.SS History
+.PP
+This function was added in MariaDB Connector/C 3.0.0.
+.SS See also
+.IP \[bu] 2
+\f[B]mariadb_cancel(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_kill(3)\f[R]
diff --git a/libmariadb/man/mysql_rollback.3 b/libmariadb/man/mysql_rollback.3
new file mode 100644
index 00000000..e69cbc6f
--- /dev/null
+++ b/libmariadb/man/mysql_rollback.3
@@ -0,0 +1,34 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_rollback" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_rollback \- Rolls back the current transaction
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_rollback(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Rolls back the current transaction for the database.
+Returns zero on success, nonzero if an error occurred.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+mysql_rollback() will not work as expected if autocommit mode was set or
+the storage engine does not support transactions.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_commit(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_autocommit(3)\f[R]
diff --git a/libmariadb/man/mysql_row_seek.3 b/libmariadb/man/mysql_row_seek.3
new file mode 100644
index 00000000..35a05ede
--- /dev/null
+++ b/libmariadb/man/mysql_row_seek.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_row_seek" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_row_seek \- Positions the row cursor to an arbitrary row
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES * result,
+ MYSQL_ROW_OFFSET offset);
+\f[R]
+.fi
+.SS Description
+.PP
+Positions the row cursor to an arbitrary row in a result set which was
+obtained by \f[B]mysql_store_result(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]result\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R].
+.IP \[bu] 2
+\f[C]offset\f[R] \- row offset.
+This value can be obtained either by mysql_row_seek() or
+\f[B]mysql_row_tell(3)\f[R]
+.SS Notes
+.IP \[bu] 2
+This function will not work if the result set was obtained by
+\f[B]mysql_use_result(3)\f[R].
+.SS Return value
+.PP
+Returns the previous row offset.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_row_tell(3)\f[R]
diff --git a/libmariadb/man/mysql_row_tell.3 b/libmariadb/man/mysql_row_tell.3
new file mode 100644
index 00000000..22dda28b
--- /dev/null
+++ b/libmariadb/man/mysql_row_tell.3
@@ -0,0 +1,34 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_row_tell" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_row_tell \- Returns row offset of a result cursor
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES * res);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the row offset of a result cursor.
+The returned offset value can be used to reposition the result cursor by
+calling \f[B]mysql_row_seek(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]res\f[R] \- a result set identifier returned by
+\f[B]mysql_store_result(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+This function will not work if the result set was obtained by
+\f[B]mysql_use_result(3)\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_row_seek(3)\f[R]
diff --git a/libmariadb/man/mysql_select_db.3 b/libmariadb/man/mysql_select_db.3
new file mode 100644
index 00000000..5a70797c
--- /dev/null
+++ b/libmariadb/man/mysql_select_db.3
@@ -0,0 +1,84 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_select_db" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_select_db \- selects a database as default
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_select_db(MYSQL * mysql,
+ const char * db);
+\f[R]
+.fi
+.SS Description
+.PP
+Selects a database as default.
+Returns zero on success, non\-zero on failure
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]db\f[R] \- the default database name
+.SS Notes
+.IP \[bu] 2
+To retrieve the name of the default database either execute the SQL
+command \f[C]SELECT DATABASE()\f[R] or retrieve the value via
+\f[B]mariadb_get_infov(3)\f[R] API function.
+.IP \[bu] 2
+The default database can also be set by the db parameter in
+\f[B]mysql_real_connect(3)\f[R].
+.SS Examples
+.SS SQL
+.IP
+.nf
+\f[C]
+# switch to default database test
+USE test;
+# check default database
+SELECT DATABASE();
++\-\-\-\-\-\-\-\-\-\-\-\-+
+| database() |
++\-\-\-\-\-\-\-\-\-\-\-\-+
+| test |
++\-\-\-\-\-\-\-\-\-\-\-\-+
+\f[R]
+.fi
+.SS MariadDB Connector/C
+.IP
+.nf
+\f[C]
+static int set_default_db(MYSQL *mysql)
+{
+ int rc;
+ char *default_db;
+
+ /* change default database to test */
+ rc= mysql_select_db(mysql, \[dq]test\[dq]);
+ if (rc)
+ return rc; /* Error */
+
+ /* get the default database */
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SCHEMA, &default_db);
+ if (rc)
+ return rc; /* Error */
+
+ if (strcmp(\[dq]test\[dq], default_db) != NULL)
+ {
+ printf(\[dq]Wrong default database\[rs]n\[dq]);
+ return 1;
+ }
+ printf(\[dq]Default database: %s\[dq], default_db);
+ return 0;
+}
+\f[R]
+.fi
+.SS See also
+.PP
+\f[B]mysql_real_connect(3)\f[R]
diff --git a/libmariadb/man/mysql_send_query.3 b/libmariadb/man/mysql_send_query.3
new file mode 100644
index 00000000..dea08137
--- /dev/null
+++ b/libmariadb/man/mysql_send_query.3
@@ -0,0 +1,52 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_send_query" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_send_query \- sends a SQL statement without waiting for server
+reponse
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_send_query(MYSQL * mysql,
+ const char *query,
+ unsigned long length);
+\f[R]
+.fi
+.SS Description
+.PP
+Sends a statement to the server, without waiting for the Server OK
+packet and/or resultset.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]query\f[R] \- SQL statement
+.IP \[bu] 2
+\f[C]length\f[R] \- length of the SQL statement
+.SS Notes
+.IP \[bu] 2
+The OK and result set package need to be retrieved by
+\f[B]mysql_read_query_result(3)\f[R] function
+.IP \[bu] 2
+\f[C]mysql_send_query()\f[R] can be used for semi asynchronous
+operation.
+While the function itself is blocking, an event driven application can
+do other tasks until result set is available.
+.SS Example
+.PP
+For an example how to use \[cq]mysql_send_query()\[ga] in an event
+driven model, please check Jan Kneschke\[cq]s article \[lq]Async MySQL
+Queries with
+C\-API\[rq] (https://jan.kneschke.de/projects/mysql/async-mysql-queries-with-c-api/).
+.SS See also
+.IP \[bu] 2
+<mysql_real_query>
+.IP \[bu] 2
+<mysql_read_query_result>
diff --git a/libmariadb/man/mysql_server_end.3 b/libmariadb/man/mysql_server_end.3
new file mode 100644
index 00000000..c3182baf
--- /dev/null
+++ b/libmariadb/man/mysql_server_end.3
@@ -0,0 +1,33 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_server_end" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_server_end \- Called when finished using MariaDB Connector/C
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_server_end(void)
+\f[R]
+.fi
+.SS Description
+.PP
+Call when finished using the library, such as after disconnecting from
+the server.
+For a client program, only cleans up by performing memory management
+tasks.
+.SS Notes
+.IP \[bu] 2
+\f[C]mysql_library_end()\f[R] is an alias for
+\f[C]mysql_server_end()\f[R].
+.IP \[bu] 2
+In MySQL Connector/C versions 3.0.1 to 3.0.4 it was not possible to call
+multiple times \f[B]mysql_server_init(3)\f[R] and
+\f[C]mysql_server_end()\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_server_init(3)\f[R]
diff --git a/libmariadb/man/mysql_server_init.3 b/libmariadb/man/mysql_server_init.3
new file mode 100644
index 00000000..19f7492c
--- /dev/null
+++ b/libmariadb/man/mysql_server_init.3
@@ -0,0 +1,38 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_server_init" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_server_init \- Initializes library
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_library_init(int argc __attribute__((unused)),
+ char **argv __attribute__((unused)),
+ char **groups __attribute__((unused)))
+\f[R]
+.fi
+.SS Description
+.PP
+Call to initialize the library before calling other functions.
+.SS Parameters
+.PP
+All parameters are unused, they only exist for compatibility reasons.
+.SS Notes
+.IP \[bu] 2
+Call \f[B]mysql_server_end(3)\f[R] to clean up after completion.
+.IP \[bu] 2
+If the library was not explicetly initialized by
+\f[C]mysql_server_init()\f[R] any call to \f[B]mysql_init(3)\f[R] will
+automatically initialize the library.
+.IP \[bu] 2
+\f[C]mysql_library_init()\f[R] is an alias for
+\f[C]mysql_server_init()\f[R]
+.SS Return value
+.PP
+Returns zero for success, or nonzero if an error occurred.
+## See also * \f[B]mysql_server_end(3)\f[R]
diff --git a/libmariadb/man/mysql_session_track_get_first.3 b/libmariadb/man/mysql_session_track_get_first.3
new file mode 100644
index 00000000..1274f47c
--- /dev/null
+++ b/libmariadb/man/mysql_session_track_get_first.3
@@ -0,0 +1,74 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_session_track_get_first" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_session_track_get_first \- retrieves first session status change
+information
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_session_track_get_first(MYSQL * mysql,
+ enum enum_session_state_type type,
+ const char **data,
+ size_t *length );
+\f[R]
+.fi
+.SS Description
+.PP
+\f[C]mysql_session_track_get_first()\f[R] retrieves the first session
+status change information received from the server.
+.PP
+Depending on the specified type the read only data pointer will contain
+the following information: * \f[C]SESSION_TRACK_SCHEMA\f[R]: The name of
+the default schema (database) *
+\f[C]SESSION_TRACK_SYSTEM_VARIABLES\f[R]: If a session system variable
+is changed, the first call contains the name of the changed system
+variable, the second call contains the new value.
+Both name and value are represented as strings.
+* \f[C]SESSION_TRACK_STATE_CHANGE\f[R]: shows whether the session status
+has changed.
+The value is changed as string \[lq]1\[rq] (changed) or \[lq]0\[rq]
+(unchanged).
+.PP
+Further data needs to be obtained by calling
+\f[B]mysql_session_track_get_next(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]type\f[R] \- type of information.
+Valid values are
+.RS 2
+.IP \[bu] 2
+\f[C]SESSION_TRACK_SYSTEM_VARIABLES\f[R]
+.IP \[bu] 2
+\f[C]SESSION_TRACK_SCHEMA\f[R]
+.IP \[bu] 2
+\f[C]SESSION_TRACK_STATE_CHANGE\f[R]
+.IP \[bu] 2
+\f[C]SESSION_TRACK_GTIDS\f[R] (unsupported)
+.RE
+.IP \[bu] 2
+\f[C]data\f[R] \- pointer to data, which must be declared as
+\f[C]const char *\f[R]
+.IP \[bu] 2
+\f[C]length\f[R] \- pointer to a \f[C]size_t\f[R] variable, which will
+contain the length of data
+.SS Returns
+.PP
+Zero for success, nonzero if no session tracking information is
+available.
+.SS History
+.PP
+\f[C]mysql_session_track_get_first()\f[R] was added in Connector/C 3.0
+and MariaDB Server 10.2.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_session_track_get_next(3)\f[R]
diff --git a/libmariadb/man/mysql_session_track_get_next.3 b/libmariadb/man/mysql_session_track_get_next.3
new file mode 100644
index 00000000..5b849ef7
--- /dev/null
+++ b/libmariadb/man/mysql_session_track_get_next.3
@@ -0,0 +1,62 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_session_track_get_next" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_session_track_get_next \- Retrieves the next session status change
+information
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_session_track_get_next(MYSQL * mysql,
+ enum enum_session_state_type type,
+ const char **data,
+ size_t *length );
+\f[R]
+.fi
+.SS Description
+.PP
+\f[C]mysql_session_track_get_next()\f[R] retrieves the session status
+change information received from the server after a successful call to
+\f[B]mysql_session_track_get_first(3)\f[R].
+.PP
+\f[C]mysql_session_track_get_next()\f[R] needs to be called repeatedly
+until a non zero return value indicates end of data.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected bys
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]type\f[R] \- type of information.
+Valid values are
+.RS 2
+.IP \[bu] 2
+\f[C]SESSION_TRACK_SYSTEM_VARIABLES\f[R]
+.IP \[bu] 2
+\f[C]SESSION_TRACK_SCHEMA\f[R]
+.IP \[bu] 2
+\f[C]SESSION_TRACK_STATE_CHANGE\f[R]
+.IP \[bu] 2
+\f[C]SESSION_TRACK_GTIDS\f[R] (unsupported)
+.RE
+.IP \[bu] 2
+\f[C]data\f[R] \- pointer to data, which must be declared as
+\f[C]const char *\f[R]
+.IP \[bu] 2
+\f[C]length\f[R] \- pointer to a \f[C]size_t\f[R] variable, which will
+contain the length of data
+.SS Return value
+.PP
+Zero for success, nonzero if an error occurred.
+.SS History
+.PP
+\f[C]mysql_session_track_get_next()\f[R] was added in Connector/C 3.0
+and MariaDB Server 10.2.
+.SS See also
+.PP
+\f[B]mysql_session_track_get_first(3)\f[R]
diff --git a/libmariadb/man/mysql_set_character_set.3 b/libmariadb/man/mysql_set_character_set.3
new file mode 100644
index 00000000..d2b8e2c2
--- /dev/null
+++ b/libmariadb/man/mysql_set_character_set.3
@@ -0,0 +1,251 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_set_character_set" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_set_character_set \- Sets the default character set for connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_set_character_set(MYSQL * mysql,
+ const char * csname);
+\f[R]
+.fi
+.SS Description
+.PP
+Sets the default
+[data\-types\-character\-sets\-and\-collations()](character set]] for
+the current connection.
+Returns zero on success, non\-zero on failure.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+mysql_init() (mysql_init) or \f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]csname\f[R] \- character set name ### Notes
+.IP \[bu] 2
+It\[cq]s strongly recommended to use mysql_set_character_set() instead
+of \f[C]SET NAMES ...\f[R] since \f[B]mysql_real_escape_string(3)\f[R]
+might fail or deliver unexpected results.
+.SS Return value
+.PP
+Zero on success, non zero if an error occured
+.SS Supported character sets
+.PP
+The client library supports the following character sets:
+.PP
+.TS
+tab(@);
+lw(35.0n) lw(35.0n).
+T{
+Character set
+T}@T{
+Description
+T}
+_
+T{
+armscii8
+T}@T{
+8 bit character set for Armenian
+T}
+T{
+ascii
+T}@T{
+US ASCII character set
+T}
+T{
+big5
+T}@T{
+2 byte character set for traditional Chinese, Hongkong, Macau and Taiwan
+T}
+T{
+binary
+T}@T{
+8 bit binary character set
+T}
+T{
+cp1250
+T}@T{
+Windows code page 1250 character set
+T}
+T{
+cp1251
+T}@T{
+Windows code page 1251 character set
+T}
+T{
+cp1256
+T}@T{
+Windows code page 1256 character set
+T}
+T{
+cp1257
+T}@T{
+Windows code page 1257 character set
+T}
+T{
+cp850
+T}@T{
+MS\-DOS Codepage 850 (Western Europe)
+T}
+T{
+cp852
+T}@T{
+MS\-DOS Codepage 852 (Middle Europe)
+T}
+T{
+cp866
+T}@T{
+MS\-DOS Codepage 866 (Russian)
+T}
+T{
+cp932
+T}@T{
+Microsoft Codepage 932 (Extension to sjis)
+T}
+T{
+dec8
+T}@T{
+DEC West European
+T}
+T{
+eucjpms
+T}@T{
+UJIS for Windows Japanese
+T}
+T{
+euckr
+T}@T{
+EUC KR\-Korean
+T}
+T{
+gb2312
+T}@T{
+GB\-2312 simplified Chinese
+T}
+T{
+gbk
+T}@T{
+GBK simplified Chinese
+T}
+T{
+geostd8
+T}@T{
+GEOSTD8 Georgian
+T}
+T{
+greek
+T}@T{
+ISO 8859\-7 Greek
+T}
+T{
+hebrew
+T}@T{
+ISO 8859\-8 Hebrew
+T}
+T{
+hp8
+T}@T{
+HP West European
+T}
+T{
+keybcs2
+T}@T{
+DOS Kamenicky Czech\-Slovak
+T}
+T{
+koi8r
+T}@T{
+KOI8\-R Relcom Russian
+T}
+T{
+koi8u
+T}@T{
+KOI8\-U Ukrainian
+T}
+T{
+latin1
+T}@T{
+CP1252 Western European
+T}
+T{
+latin2
+T}@T{
+ISO 8859\-2 Central Europe
+T}
+T{
+latin5
+T}@T{
+ISO 8859\-9 Turkish
+T}
+T{
+latin7
+T}@T{
+ISO 8859\-13 Baltic
+T}
+T{
+macce
+T}@T{
+MAC Central European
+T}
+T{
+macroman
+T}@T{
+MAC Western European
+T}
+T{
+sjis
+T}@T{
+SJIS for Windows Japanese
+T}
+T{
+swe7
+T}@T{
+7\-bit Swedish
+T}
+T{
+tis620
+T}@T{
+TIS620 Thai
+T}
+T{
+ucs2
+T}@T{
+UCS\-2 Unicode
+T}
+T{
+ujis
+T}@T{
+EUC\-JP Japanese
+T}
+T{
+utf8
+T}@T{
+UTF\-8 Unicode
+T}
+T{
+utf16
+T}@T{
+UTF\-16 Unicode
+T}
+T{
+utf32
+T}@T{
+UTF\-32 Unicode
+T}
+T{
+utf8mb4
+T}@T{
+UTF 4\-byte Unicode
+T}
+.TE
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_character_set_info(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_real_escape_string(3)\f[R]
diff --git a/libmariadb/man/mysql_set_server_option.3 b/libmariadb/man/mysql_set_server_option.3
new file mode 100644
index 00000000..915468eb
--- /dev/null
+++ b/libmariadb/man/mysql_set_server_option.3
@@ -0,0 +1,56 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_set_server_option" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_set_server_option \- Sets server option
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_set_server_option(MYSQL * mysql,
+ enum enum_mysql_set_option);
+\f[R]
+.fi
+.SS Description
+.PP
+Sets server option.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]enum_mysql_set_option\f[R] \- server option (see below) Server
+option, which can be one of the following values:
+.PP
+.TS
+tab(@);
+l l.
+T{
+Option
+T}@T{
+Description
+T}
+_
+T{
+MYSQL_OPTION_MULTI_STATEMENTS_OFF
+T}@T{
+Disables multi statement support
+T}
+T{
+MYSQL_OPTION_MULTI_STATEMENTS_ON
+T}@T{
+Enable multi statement support
+T}
+.TE
+.SS Return value
+.PP
+Returns zero on success, non\-zero on failure.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_real_connect(3)\f[R]
diff --git a/libmariadb/man/mysql_shutdown.3 b/libmariadb/man/mysql_shutdown.3
new file mode 100644
index 00000000..b91687f0
--- /dev/null
+++ b/libmariadb/man/mysql_shutdown.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_shutdown" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_shutdown \- Sends shutdown message to server
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_shutdown(MYSQL * mysql,
+ enum mysql_enum_shutdown_level);
+\f[R]
+.fi
+.SS Description
+.PP
+This function is deprecated.
+Instead please use SQL \f[C]SHUTDOWN\f[R] command.
+.PP
+Sends a shutdown message to the server.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.IP \[bu] 2
+\f[C]mysql_enum_shutdown_level\f[R] \- currently only one shutdown
+level, \f[C]SHUTDOWN_DEFAULT\f[R] is supported.
+.SS Notes
+.IP \[bu] 2
+To shutdown the database server, the user for the current connection
+must have SHUTDOWN privileges.
+.SS Return value
+.PP
+Returns zero on success, non\-zero on failure.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_kill(3)\f[R]
diff --git a/libmariadb/man/mysql_sqlstate.3 b/libmariadb/man/mysql_sqlstate.3
new file mode 100644
index 00000000..f949f746
--- /dev/null
+++ b/libmariadb/man/mysql_sqlstate.3
@@ -0,0 +1,37 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_sqlstate" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_sqlstate \- returns SQLSTATE error code
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_sqlstate(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a string containing the SQLSTATE error code for the most
+recently invoked function that can succeed or fail.
+The error code consists of five characters.
+`00000' means no error.
+The values are specified by ANSI SQL and ODBC
+.SS Parameter
+.SS Notes
+.PP
+Please note that not all client library error codes are mapped to
+SQLSTATE errors.
+Errors which can\[cq]t be mapped will returned as value HY000.
+.SS Return value
+.PP
+A string containing SQLSTATE error code.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_error(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_errno(3)\f[R]
diff --git a/libmariadb/man/mysql_ssl_set.3 b/libmariadb/man/mysql_ssl_set.3
new file mode 100644
index 00000000..bccf3774
--- /dev/null
+++ b/libmariadb/man/mysql_ssl_set.3
@@ -0,0 +1,57 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_ssl_set" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_ssl_set \- Sets TLS/SSL options
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_ssl_set(MYSQL *mysql,
+ const char *key,
+ const char *cert,
+ const char *ca,
+ const char *capath,
+ const char *cipher)
+\f[R]
+.fi
+.SS Description
+.PP
+Used for establishing a secure TLS connection.
+It must be called before attempting to use
+\f[B]mysql_real_connect(3)\f[R].
+TLS support must be enabled in the client library in order for the
+function to have any effect.
+.PP
+NULL can be used for an unused parameter.
+Always returns zero.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R].
+.IP \[bu] 2
+\f[C]key\f[R] \- path to the key file.
+.IP \[bu] 2
+\f[C]cert\f[R] \- path to the certificate file.
+.IP \[bu] 2
+\f[C]ca\f[R] \- path to the certificate authority file.
+.IP \[bu] 2
+\f[C]capath\f[R] \- path to the directory containing the trusted TLS CA
+certificates in PEM format.
+.IP \[bu] 2
+\f[C]cipher\f[R] list of permitted (SSLv3, TLSv1.0 or TLSv1.2) cipher
+suites to use for TLS encryption.
+.SS Notes
+.IP \[bu] 2
+\f[B]mysql_real_connect(3)\f[R] will return an error if attempting to
+connect and TLS is incorrectly set up.
+.IP \[bu] 2
+Even if Connector/C supports TLSv1.3 protocol, it is not possible yet to
+specify TLSv1.3 cipher suites via \f[C]cipher\f[R] parameter.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_get_ssl_cipher(3)\f[R]
diff --git a/libmariadb/man/mysql_stat.3 b/libmariadb/man/mysql_stat.3
new file mode 100644
index 00000000..a2b88565
--- /dev/null
+++ b/libmariadb/man/mysql_stat.3
@@ -0,0 +1,35 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stat" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stat \- Returns current server status
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_stat(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+mysql_stat() returns a string with the current server status for uptime,
+threads, queries, open tables, flush tables and queries per second.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected byy
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+For a complete list of other status variables, you have to use the
+[show\-status()](SHOW STATUS]] SQL command.
+.SS Return value
+.PP
+Returns a string representing current server status.
+.SS See also
+.IP \[bu] 2
+mysql_get_server_info() (mysql_get_server_info)
diff --git a/libmariadb/man/mysql_stmt_affected_rows.3 b/libmariadb/man/mysql_stmt_affected_rows.3
new file mode 100644
index 00000000..d7b2f1de
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_affected_rows.3
@@ -0,0 +1,42 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_affected_rows" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_affected_rows \- Returns the number of affected rows from
+previous executed prepared statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of affected rows by the last prepared statement
+associated with mysql, if the operation was an \[lq]upsert\[rq] (INSERT,
+UPDATE, DELETE or REPLACE) statement, or \-1 if the last prepared
+statement failed.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+[mysql_stmt_init()](mysql_stmt_init().]]
+.SS Notes
+.IP \[bu] 2
+When using \f[C]UPDATE\f[R], MariaDB will not update columns where the
+new value is the same as the old value.
+This creates the possibility that \f[C]mysql_stmt_affected_rows()\f[R]
+may not actually equal the number of rows matched, only the number of
+rows that were literally affected by the query.
+.IP \[bu] 2
+The \f[C]REPLACE\f[R] statement first deletes the record with the same
+primary key and then inserts the new record.
+This function returns the number of deleted records in addition to the
+number of inserted records.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_insert_id(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_attr_get.3 b/libmariadb/man/mysql_stmt_attr_get.3
new file mode 100644
index 00000000..2dd07a74
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_attr_get.3
@@ -0,0 +1,97 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_attr_get" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_attr_get \- Gets the current value of a statement attribute
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt,
+ enum enum_stmt_attr_type,
+ void * attr);
+\f[R]
+.fi
+.SS Description
+.PP
+Gets the current value of a statement attribute.
+Returns zero on success, non zero on failure.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]enum_stmt_attr_type\f[R] \- attribute.
+See below.
+.IP \[bu] 2
+\f[C]attr\f[R] \- pointer to a variable, which will contain the
+attribute value.
+.SS Attribute types
+.PP
+The \f[C]enum_stmt_attr_type\f[R] parameter has the following possible
+values:
+.PP
+.TS
+tab(@);
+lw(23.3n) lw(23.3n) lw(23.3n).
+T{
+Value
+T}@T{
+Type
+T}@T{
+Description
+T}
+_
+T{
+\f[C]STMT_ATTR_UPDATE_MAX_LENGTH\f[R]
+T}@T{
+\f[C]my_bool *\f[R]
+T}@T{
+Indicates if \f[B]mysql_stmt_store_result(3)\f[R] will update the
+max_length value of \f[C]MYSQL_FIELD\f[R] structures.
+T}
+T{
+\f[C]STMT_ATTR_CURSOR_TYPE\f[R]
+T}@T{
+\f[C]unsigned long *\f[R]
+T}@T{
+Possible values are \f[C]CURSOR_TYPE_READ_ONLY\f[R] or default value
+\f[C]CURSOR_TYPE_NO_CURSOR\f[R].
+T}
+T{
+\f[C]STMT_ATTR_PREFETCH_ROWS\f[R]
+T}@T{
+\f[C]unsigned long *\f[R]
+T}@T{
+Number of rows which will be prefetched.
+The default value is 1.
+T}
+T{
+\f[C]STMT_ATTR_PREBIND_PARAMS\f[R]
+T}@T{
+\f[C]unsigned int *\f[R]
+T}@T{
+Number of parameters used for \f[B]mariadb_stmt_execute_direct(3)\f[R]
+T}
+T{
+\f[C]STMT_ATTR_STATE\f[R]
+T}@T{
+\f[C]enum mysql_stmt_state *\f[R]
+T}@T{
+Status of prepared statement.
+Possible values are defined in \f[C]enum mysql_stmt_state\f[R].
+This option was added in MariaDB Connector/C 3.1.0
+T}
+.TE
+.SS Notes
+.IP \[bu] 2
+Setting the number of prefetched rows will work only for read only
+cursors.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_attr_set(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_attr_set.3 b/libmariadb/man/mysql_stmt_attr_set.3
new file mode 100644
index 00000000..5d9446a3
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_attr_set.3
@@ -0,0 +1,131 @@
+.\"t
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_attr_set" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_attr_set \- Sets attribute of a statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt,
+ enum enum_stmt_attr_type,
+ const void * attr);
+\f[R]
+.fi
+.SS Description
+.PP
+Used to modify the behavior of a prepared statement.
+This function may be called multiple times to set several attributes.
+Returns zero on success, non\-zero on failure.
+.SS Parameters
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]enum_stmt_attr_type\f[R] \- the attribute that you want to set.
+See below.
+.IP \[bu] 2
+\f[C]attr\f[R] \- the value to assign to the attribute
+.SS Attribute types
+.PP
+The \f[C]enum_stmt_attr_type\f[R] attribute can have one of the
+following values:
+.PP
+.TS
+tab(@);
+lw(23.3n) lw(23.3n) lw(23.3n).
+T{
+Value
+T}@T{
+Type
+T}@T{
+Description
+T}
+_
+T{
+\f[C]STMT_ATTR_UPDATE_MAX_LENGTH\f[R]
+T}@T{
+\f[C]my_bool *\f[R]
+T}@T{
+If set to 1, \f[B]mysql_stmt_store_result(3)\f[R] will update the
+max_length value of MYSQL_FIELD structures.
+T}
+T{
+\f[C]STMT_ATTR_CURSOR_TYPE\f[R]
+T}@T{
+\f[C]unsigned long *\f[R]
+T}@T{
+cursor type when \f[B]mysql_stmt_execute(3)\f[R] is invoked.
+Possible values are \f[C]CURSOR_TYPE_READ_ONLY\f[R] or default value
+\f[C]CURSOR_TYPE_NO_CURSOR\f[R].
+T}
+T{
+\f[C]STMT_ATTR_PREFETCH_ROWS\f[R]
+T}@T{
+\f[C]unsigned long *\f[R]
+T}@T{
+number of rows which will be prefetched.
+The default value is 1.
+T}
+T{
+\f[C]STMT_ATTR_PREBIND_PARAMS\f[R]
+T}@T{
+\f[C]unsigned int *\f[R]
+T}@T{
+number of parameter markers when using
+\f[B]mariadb_stmt_execute_direct(3)\f[R].
+If the statement handle is reused it will be reset automatically to the
+state after mysql_stmt_init().
+This option was added in Connector/C 3.0
+T}
+T{
+\f[C]STMT_ATTR_ARRAY_SIZE\f[R]
+T}@T{
+\f[C]unsigned int *\f[R]
+T}@T{
+number of array elements.
+This option was added in Connector/C 3.0 and requires MariaDB 10.2 or
+later
+T}
+T{
+\f[C]STMT_ATTR_ROW_SIZE\f[R]
+T}@T{
+\f[C]size_t *\f[R]
+T}@T{
+specifies size of a structure for row wise binding.
+This length must include space for all of the bound parameters and any
+padding of the structure or buffer to ensure that when the address of a
+bound parameter is incremented with the specified length, the result
+will point to the beginning of the same parameter in the next set of
+parameters.
+When using the sizeof operator in ANSI C, this behavior is guaranteed.
+If the value is zero column\-wise binding will be used (default).
+This option was added in Connector/C 3.0 and requires MariaDB 10.2 or
+later
+T}
+.TE
+.SS Notes
+.IP \[bu] 2
+If you use the \f[C]MYSQL_STMT_ATTR_CURSOR_TYPE\f[R] option with
+\f[C]MYSQL_CURSOR_TYPE_READ_ONLY\f[R], a cursor is opened for the
+statement when you invoke \f[B]mysql_stmt_execute(3)\f[R].
+If there is already an open cursor from a previous
+\f[B]mysql_stmt_execute(3)\f[R] call, it closes the cursor before
+opening a new one.
+\f[B]mysql_stmt_reset(3)\f[R] also closes any open cursor before
+preparing the statement for re\-execution.
+.IP \[bu] 2
+If you open a cursor for a prepared statement it is unnecessary to call
+\f[B]mysql_stmt_store_result(3)\f[R].
+.IP \[bu] 2
+\f[B]mysql_stmt_free_result(3)\f[R] closes any open cursor.
+.SS See Also
+.IP \[bu] 2
+\f[B]mariadb_stmt_execute_direct(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_attr_get(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_bind_param.3 b/libmariadb/man/mysql_stmt_bind_param.3
new file mode 100644
index 00000000..a92672ed
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_bind_param.3
@@ -0,0 +1,50 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_bind_param" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_bind_param \- Binds parameter to a prepared statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt,
+ MYSQL_BIND * bind);
+\f[R]
+.fi
+.SS Description
+.PP
+Binds variables for parameter markers in the prepared statement that was
+passed to \f[B]mysql_stmt_prepare(3)\f[R].
+Returns zero on success, non\-zero on failure.
+.SS Parameters
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]bind\f[R] \- an array of \f[C]MYSQL_BIND\f[R] structures.
+The size of this array must be equal to the number of parameters.
+.SS Notes
+.IP \[bu] 2
+The number of parameters can be obtained by
+\f[B]mysql_stmt_param_count(3)\f[R].
+.IP \[bu] 2
+If the number of parameters is unknown, for example when using
+\f[B]mariadb_stmt_execute_direct(3)\f[R], the number of parameters have
+to be specified with the \f[B]mysql_stmt_attr_set(3)\f[R] function.
+.SS See Also
+.IP \[bu] 2
+\f[B]mariadb_stmt_execute_direct(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_prepare(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_bind_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_execute(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_param_count(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_send_long_data(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_bind_result.3 b/libmariadb/man/mysql_stmt_bind_result.3
new file mode 100644
index 00000000..70ecdcbd
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_bind_result.3
@@ -0,0 +1,45 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_bind_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_bind_result \- binds result columns to variables
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt,
+ MYSQL_BIND * bind);
+\f[R]
+.fi
+.SS Description
+.PP
+Binds columns in the result set to variables.
+Returns zero on success, non\-zero on failure.
+.SS Parameters
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]bind\f[R] \- an array of [MYSQL_BIND]] structures.
+The size of this array must be equal to the number of columns in result
+set.
+.SS Notes
+.IP \[bu] 2
+To determine the number of columns in result set use
+\f[B]mysql_stmt_field_count(3)\f[R].
+.IP \[bu] 2
+A column can be bound or rebound at any time, even after a result set
+has been partially retrieved.
+The new binding takes effect the next time \f[B]mysql_stmt_fetch(3)\f[R]
+is called.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_field_count(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_execute(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_fetch(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_close.3 b/libmariadb/man/mysql_stmt_close.3
new file mode 100644
index 00000000..a7499ee8
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_close.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_close" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_close \- Closes a prepared statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_close(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Closes a prepared statement and deallocates the statement handle.
+If the current statement has pending or unread results, this function
+cancels them so that the next query can be executed.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns zero on success, nonzero on error (when communicating with the
+server).
+The statement is deallocated, regardless of the error.
+.SS Notes
+.IP \[bu] 2
+If you want to reuse the statement handle with a different SQL command,
+use \f[B]mysql_stmt_reset(3)\f[R].
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_init(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_reset(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_data_seek.3 b/libmariadb/man/mysql_stmt_data_seek.3
new file mode 100644
index 00000000..9b896f44
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_data_seek.3
@@ -0,0 +1,43 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_data_seek" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_data_seek \- Seeks to an arbitrary row in statement result
+set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_stmt_data_seek(MYSQL_STMT * stmt,
+ my_ulonglong offset);
+\f[R]
+.fi
+.SS Description
+.PP
+Seeks to an arbitrary row in statement result set obtained by a previous
+call to \f[B]mysql_stmt_store_result(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]offset\f[R] \- row offset.
+This value must between 0 and number of rows \- 1.
+.SS Return value
+.PP
+Returns void
+.SS Notes
+.IP \[bu] 2
+The number of rows can be obtained with the function
+\f[B]mysql_stmt_num_rows(3)\f[R].
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_row_tell(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_num_rows(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_errno.3 b/libmariadb/man/mysql_stmt_errno.3
new file mode 100644
index 00000000..a523b2d9
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_errno.3
@@ -0,0 +1,38 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_errno" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_errno \- Returns error code for the last statement error
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_stmt_errno(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the error code for the most recently invoked statement function
+that can succeed or fail.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns error code.
+A zero value means that no error occurred.
+.SS Notes
+.IP \[bu] 2
+Client error messages are listed in \f[C]errmsg.h\f[R] header file,
+server error messages are listed in \f[C]mysqld_error.h\f[R] header file
+of the server source distribution.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_error(3)\f[R],
+.IP \[bu] 2
+\f[B]mysql_stmt_sqlstate(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_error.3 b/libmariadb/man/mysql_stmt_error.3
new file mode 100644
index 00000000..c58d5804
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_error.3
@@ -0,0 +1,40 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_error" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_error \- Returns a string description for the last statement
+error
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_stmt_error(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a string containing the error message for the most recently
+invoked statement function that can succeed or fail.
+The string will be empty if no error occurred.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.IP \[bu] 2
+A string describing the last error or an empty string if no error
+occured.
+.SS Notes
+.IP \[bu] 2
+Client error messages are listed in the \f[C]errmsg.h\f[R] header file,
+server error messages are listed in the \f[C]mysqld_error.h\f[R] header
+file of the server source distribution.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_errno(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_sqlstate(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_execute.3 b/libmariadb/man/mysql_stmt_execute.3
new file mode 100644
index 00000000..34056f44
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_execute.3
@@ -0,0 +1,43 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_execute" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_execute \- Executes a prepared statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_stmt_execute(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Executes a prepared statement which was previously prepared by
+\f[B]mysql_stmt_prepare(3)\f[R].
+When executed any parameter markers which exist will automatically be
+replaced with the appropriate data.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- A statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns zero on success, non\-zero on failure.
+.SS Notes
+.IP \[bu] 2
+If the statement is UPDATE, REPLACE, DELETE or INSERT, the total number
+of affected rows can be determined by using the
+\f[B]mysql_stmt_affected_rows(3)\f[R] function.
+Likewise, if the query yields a result set the
+\f[B]mysql_stmt_fetch(3)\f[R] function is used.
+.SS See Also
+.IP \[bu] 2
+\f[B]mariadb_stmt_execute_direct(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_prepare(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_bind_param(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_fetch.3 b/libmariadb/man/mysql_stmt_fetch.3
new file mode 100644
index 00000000..49ab8576
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_fetch.3
@@ -0,0 +1,48 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_fetch" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_fetch \- Fetches result set row from a prepared statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_stmt_fetch(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Fetch the result from a prepared statement into the buffer bound by
+[mysql_stmt_bind_result()}(mysql_stmt_bind_result).
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns \f[C]0\f[R] for success, \f[C]MYSQL_NO_DATA\f[R] if the end of
+the result set has been reached, or \f[C]MYSQL_DATA_TRUNCATION\f[R] if
+one or more values are truncated.
+.SS Notes
+.IP \[bu] 2
+Note that all columns must be bound by the application before calling
+mysql_stmt_fetch().
+.IP \[bu] 2
+Data are transferred unbuffered without calling
+\f[B]mysql_stmt_store_result(3)\f[R] which can decrease performance (but
+reduces memory cost).
+.IP \[bu] 2
+Truncation reporting must be enabled by function
+\f[B]mysql_optionsv(3)\f[R] with option
+\f[C]MYSQL_REPORT_DATA_TRUNCATION\f[R]
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_prepare(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_bind_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_execute(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_fetch_column.3 b/libmariadb/man/mysql_stmt_fetch_column.3
new file mode 100644
index 00000000..d0c559a8
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_fetch_column.3
@@ -0,0 +1,44 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_fetch_column" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_fetch_column \- Fetches a single column into bind buffer
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_stmt_fetch_column(MYSQL_STMT * stmt,
+ MYSQL_BIND * bind_arg,
+ unsigned int column,
+ unsigned long offset);
+\f[R]
+.fi
+.SS Description
+.PP
+This function can be used to fetch large data of a single column in
+pieces.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]bind_arg\f[R] \- a pointer to a MYSQL_BIND structure.
+.IP \[bu] 2
+\f[C]column\f[R] \- number of column, first column is numbered zero.
+.IP \[bu] 2
+\f[C]offset\f[R] \- offset at which to begin retrieving data.
+.SS Return value
+.PP
+Returns zero on success, non\-zero on failure.
+.SS Notes
+.IP \[bu] 2
+The size of the buffer is specified within MYSQL_BIND structure.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_fetch(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_send_long_data(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_field_count.3 b/libmariadb/man/mysql_stmt_field_count.3
new file mode 100644
index 00000000..fa239a9c
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_field_count.3
@@ -0,0 +1,38 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_field_count" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_field_count \- Returns the number of fields in a result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of fields in a result set of a prepared statement.
+.SS Return value
+.PP
+Number of fields or zero if the prepared statement has no result set.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+The number of fields will be available after calling
+\f[B]mysql_stmt_prepare(3)\f[R]
+.IP \[bu] 2
+\f[C]mysql_stmt_field_count()\f[R] returns zero for statements which
+don\[cq]t produce a result set.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_prepare(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_param_count(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_free_result.3 b/libmariadb/man/mysql_stmt_free_result.3
new file mode 100644
index 00000000..2ca10517
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_free_result.3
@@ -0,0 +1,30 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_free_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_free_result \- Frees stored result set memory of a prepared
+statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_stmt_free_result(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Frees stored result memory of a prepared statement.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns void
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_init.3 b/libmariadb/man/mysql_stmt_init.3
new file mode 100644
index 00000000..8844aeb2
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_init.3
@@ -0,0 +1,43 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_init" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_init \- Initializes a prepared statement handle
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_STMT * mysql_stmt_init(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Initializes and allocates memory for a prepared statement.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+Returns a pointer to a \f[C]MYSQL_STMT\f[R] structure or \f[C]NULL\f[R]
+if an error occurred.
+.SS Notes
+.IP \[bu] 2
+Members of the \f[C]MYSQL_STMT\f[R] structure are not intended for
+application use.
+.IP \[bu] 2
+A statement handle which was allocated by mysql_stmt_init() needs to be
+freed with \f[B]mysql_stmt_close(3)\f[R].
+.IP \[bu] 2
+Any subsequent calls to any mysql_stmt function will fail until
+\f[B]mysql_stmt_prepare(3)\f[R] was called.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_close(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_prepare(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_insert_id.3 b/libmariadb/man/mysql_stmt_insert_id.3
new file mode 100644
index 00000000..60219704
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_insert_id.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_insert_id" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_insert_id \- Returns the auto generated id from previously
+executed prepared statement.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+The \f[C]mysql_stmt_insert_id()\f[R] function returns the ID generated
+by a prepared statement on a table with a column having the
+\f[C]AUTO_INCREMENT\f[R] attribute.
+## Parameter * \f[C]stmt\f[R] \- a statement handle, which was
+previously allocated by \f[B]mysql_stmt_init(3)\f[R].
+## Return value Returns the auto generated id from previously executed
+prepared statement.
+If the last query wasn\[cq]t an INSERT or UPDATE statement or if the
+modified table does not have a column with the AUTO_INCREMENT attribute,
+this function will return zero.
+.SS Notes
+.IP \[bu] 2
+When performing a multi insert prepared statement,
+mysql_stmt_insert_id() will return the value of the first row.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_insert_id(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_more_results.3 b/libmariadb/man/mysql_stmt_more_results.3
new file mode 100644
index 00000000..43f758dc
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_more_results.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_more_results" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_more_results \- indicates if one or more results from a
+previously executed prepared statement are available
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_more_results(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Indicates if one or more result sets are available from a previous call
+to \f[B]mysql_stmt_execute(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+mysql_stmt_init() (mysql_init) and executed by
+\f[B]mysql_stmt_execute(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+Multiple result sets can be obtained by calling a stored procedure.
+Executing concatenated statements is not supported in prepared statement
+protocol.
+.SS Return value
+.PP
+Returns 1 if more result sets are available, otherwise zero.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_stmt_next_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_next_result.3 b/libmariadb/man/mysql_stmt_next_result.3
new file mode 100644
index 00000000..b7474ef5
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_next_result.3
@@ -0,0 +1,42 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_next_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_next_result \- prepares next result set of a prepared
+statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_stmt_next_result(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Prepares next result set from a previous call to
+\f[B]mysql_stmt_execute(3)\f[R] which can be retrieved by
+\f[B]mysql_stmt_store_result(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+[mysql_stmt_init()](mysql_stmt_init().]]
+.SS Return value
+.PP
+Returns zero on success, nonzero if an error occurred.
+.SS Notes
+.IP \[bu] 2
+The function \f[B]mysql_stmt_more_results(3)\f[R] indicates if further
+result sets are available.
+.IP \[bu] 2
+If the execution of a stored procedure produced multiple result sets the
+return value of \f[B]mysql_stmt_errno(3)\f[R]/error() might change and
+there will be no result set available.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_stmt_execute(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_more_results(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_num_rows.3 b/libmariadb/man/mysql_stmt_num_rows.3
new file mode 100644
index 00000000..15312a11
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_num_rows.3
@@ -0,0 +1,37 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_num_rows" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_num_rows \- Returns number of rows in a prepared statement
+result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned long long mysql_stmt_num_rows(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of rows in the result set.
+The use of mysql_stmt_num_rows() depends on whether or not you used
+\f[B]mysql_stmt_store_result(3)\f[R] to buffer the entire result set in
+the statement handle.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Number of rows in the result set
+.SS Notes
+.IP \[bu] 2
+If you use \f[B]mysql_stmt_store_result(3)\f[R], mysql_stmt_num_rows()
+may be called immediately.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_param_count.3 b/libmariadb/man/mysql_stmt_param_count.3
new file mode 100644
index 00000000..79ab3585
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_param_count.3
@@ -0,0 +1,37 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_param_count" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_param_count \- Returns number of parameters
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned long mysql_stmt_param_count(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of parameter markers present in the prepared
+statement.
+Parameter markers are specified as \f[C]?\f[R] (question mark)
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+The number of parameter markers in prepared statement.
+.SS Notes
+.IP \[bu] 2
+This function will not deliver a valid result until
+mysql_stmt_prepare()() (mysql_stmt_prepare) was called.
+.SS See Also
+.IP \[bu] 2
+mysql_stmt_prepare()() (mysql_stmt_prepare)
+.IP \[bu] 2
+\f[B]mysql_stmt_field_count(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_param_metadata.3 b/libmariadb/man/mysql_stmt_param_metadata.3
new file mode 100644
index 00000000..8ec3eeea
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_param_metadata.3
@@ -0,0 +1,27 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_param_metadata" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_param_metadata \- This function does nothing!
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+This function does nothing, it\[cq]s not implemented now and reserved
+for future use.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Always returns \f[C]NULL\f[R].
diff --git a/libmariadb/man/mysql_stmt_prepare.3 b/libmariadb/man/mysql_stmt_prepare.3
new file mode 100644
index 00000000..2478328b
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_prepare.3
@@ -0,0 +1,58 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_prepare" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_prepare \- Prepares an SQL string
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_stmt_prepare(MYSQL_STMT * stmt,
+ const char * query,
+ unsigned long length);
+\f[R]
+.fi
+.SS Description
+.PP
+Prepares the SQL query.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]query\f[R] \- SQL statement
+.IP \[bu] 2
+\f[C]length\f[R] \- length of SQL statement
+.SS Return value
+.PP
+Zero on success, non zero on error.
+.SS Notes
+.IP \[bu] 2
+The parameter markers must be bound to application variables using
+\f[B]mysql_stmt_bind_param(3)\f[R].
+.IP \[bu] 2
+The maximum number of parameters is 65535 (0xFFFF).
+.IP \[bu] 2
+The markers are legal only in certain places in SQL statements.
+For example, they are allowed in the VALUES() list ofINSERT statement
+(to specify column values for a row), or in a comparison with a column
+in a [select()](WHERE]] clause to specify a comparison value.
+However, they are not allowed in identifiers (such as table or column
+names) in the select list that names the columns to be returned by
+SELECT statement, or to specify both operands of a binary operator such
+as the equal sign.
+The latter restriction is necessary because it would be impossible to
+determine the parameter type.
+In general, parameters are legal only in Data Manipulation Language
+(DML) statements, and not in Data Definition Language (DDL) statements.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_init(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_param_count(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_execute(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_reset.3 b/libmariadb/man/mysql_stmt_reset.3
new file mode 100644
index 00000000..84c7228e
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_reset.3
@@ -0,0 +1,44 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_reset" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_reset \- Resets a prepared statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_reset(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Resets a prepared statement on client and server to state after prepare.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+Returns zero on success, nonzero if an error occurred.
+.SS Return value
+.PP
+Returns zero on succes, 1 if an error occured.
+.SS Notes
+.IP \[bu] 2
+\f[C]mysql_stmt_reset()\f[R] resets the statement on the server,
+unbuffered result sets and errors.
+Bindings and stored result sets will not be cleared.
+The latter one will be cleared when re\-executing or closing the
+prepared statement.
+.IP \[bu] 2
+To reprepare a prepared statement with another SQL statement use
+\f[B]mysql_stmt_prepare(3)\f[R].
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_close(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_prepare(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_execute(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_result_metadata.3 b/libmariadb/man/mysql_stmt_result_metadata.3
new file mode 100644
index 00000000..2b8357f1
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_result_metadata.3
@@ -0,0 +1,50 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_result_metadata" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_result_metadata \- Returns result set metadata from a
+prepared statement.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+If a statement passed to \f[B]mysql_stmt_prepare(3)\f[R] is one that
+produces a result set, mysql_stmt_result_metadata() returns the result
+set that can be used to process the meta information such as total
+number of fields and individual field information.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns a result set that can be used to process metadata information.
+.SS Notes
+.IP \[bu] 2
+The result set returned by mysql_stmt_result_metadata() contains only
+metadata.
+It does not contain any row results.
+The rows are obtained by \f[B]mysql_stmt_fetch(3)\f[R].
+.IP \[bu] 2
+This result set pointer can be passed as an argument to any of the
+field\-based functions that process result set metadata, such as:
+\f[B]mysql_num_fields(3)\f[R], \f[B]mysql_fetch_field(3)\f[R],
+\f[B]mysql_fetch_field_direct(3)\f[R], \f[B]mysql_fetch_fields(3)\f[R],
+\f[B]mysql_field_count(3)\f[R], \f[B]mysql_field_seek(3)\f[R],
+\f[B]mysql_field_tell(3)\f[R], \f[B]mysql_free_result(3)\f[R]
+.SS See Also
+.IP \[bu] 2
+\f[B]mariadb_stmt_fetch_fields(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_free_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_prepare(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_row_seek.3 b/libmariadb/man/mysql_stmt_row_seek.3
new file mode 100644
index 00000000..f225ff74
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_row_seek.3
@@ -0,0 +1,40 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_row_seek" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_row_seek \- Positions row cursor.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt,
+ MYSQL_ROW_OFFSET offset);
+\f[R]
+.fi
+.SS Description
+.PP
+Positions the row cursor to an arbitrary row in a result set which was
+obtained by \f[B]mysql_stmt_store_result(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]offset\f[R] \- row offset.
+This value can be obtained either by mysql_stmt_row_seek() or
+\f[B]mysql_stmt_row_tell(3)\f[R].
+.SS Return value
+.PP
+Returns the previous row offset.
+.SS Notes
+.PP
+The result set must be obtained by \f[B]mysql_use_result(3)\f[R].
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_row_tell(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_row_tell.3 b/libmariadb/man/mysql_stmt_row_tell.3
new file mode 100644
index 00000000..ef754c20
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_row_tell.3
@@ -0,0 +1,37 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_row_tell" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_row_tell \- Returns position of row cursor
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the row offset of a result cursor.
+The returned offset value can be used to reposition the result cursor by
+calling \f[B]mysql_stmt_row_seek(3)\f[R].
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns the current position of the row cursor.
+.SS Notes
+.IP \[bu] 2
+This function can be used for buffered result sets only, which can be
+obtained by executing the \f[B]mysql_stmt_store_result(3)\f[R] function.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_row_seek(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_store_result(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_send_long_data.3 b/libmariadb/man/mysql_stmt_send_long_data.3
new file mode 100644
index 00000000..4955d144
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_send_long_data.3
@@ -0,0 +1,51 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_send_long_data" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_send_long_data \- Sends data in chunks
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt,
+ unsigned int,
+ const char * data,
+ unsigned long);
+\f[R]
+.fi
+.SS Description
+.PP
+Allows sending parameter data to the server in pieces (or chunks),
+e.g.\ if the size of a blob exceeds the size of max_allowed_packet size.
+This function can be called multiple times to send the parts of a
+character or binary data value for a column, which must be one of the
+\f[C]TEXT\f[R] or \f[C]BLOB\f[R] datatypes.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.IP \[bu] 2
+\f[C]param_no\f[R] \- indicates which parameter to associate the data
+with.
+Parameters are numbered beginning with 0.
+.IP \[bu] 2
+\f[C]data\f[R] \- a buffer containing the data to send.
+.IP \[bu] 2
+\f[C]long\f[R] \- size of the data buffer.
+.SS Return value
+.PP
+Returns zero on success, nonzero if an error occurred.
+.SS Notes
+.IP \[bu] 2
+\f[C]mysql_stmt_send_long_data()\f[R] must be called before
+\f[B]mysql_stmt_execute(3)\f[R].
+.IP \[bu] 2
+bound variables for this column will be ignored when calling
+\f[B]mysql_stmt_execute(3)\f[R].
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_stmt_execute(3)\f[R].
diff --git a/libmariadb/man/mysql_stmt_sqlstate.3 b/libmariadb/man/mysql_stmt_sqlstate.3
new file mode 100644
index 00000000..d46f3de3
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_sqlstate.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_sqlstate" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_sqlstate \- Returns SQLSTATE error from previous statement
+operation.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+const char * mysql_stmt_sqlstate(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a string containing the SQLSTATE error code for the most
+recently invoked prepared statement function that can succeed or fail.
+## Parameter * \f[C]stmt\f[R] \- a statement handle, which was
+previously allocated by \f[B]mysql_stmt_init(3)\f[R].
+## Return value Returns a 5 digit error code.
+`00000' means no error.
+The values are specified by ANSI SQL and ODBC.
+.SS Notes
+.PP
+Please note that not all client library error codes are mapped to
+SQLSTATE errors.
+Errors which can\[cq]t be mapped will returned as value HY000.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_errno(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_error(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_store_result.3 b/libmariadb/man/mysql_stmt_store_result.3
new file mode 100644
index 00000000..fe98e461
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_store_result.3
@@ -0,0 +1,38 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_store_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_store_result \- Transfers a result set from a prepared
+statement
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+int mysql_stmt_store_result(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+You must call mysql_stmt_store_result() for every query that
+successfully produces a result set only if you want to buffer the
+complete result set by the client, so that the subsequent
+\f[B]mysql_stmt_fetch(3)\f[R] call returns buffered data.
+.SS Parameter
+.IP \[bu] 2
+\f[C]stmt\f[R] \- a statement handle, which was previously allocated by
+\f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns zero on success, nonzero if an error occurred.
+## Notes * You can detect whether the statement produced a result set by
+checking the return value of \f[B]mysql_stmt_field_count(3)\f[R]
+function.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_stmt_field_count(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_stmt_fetch(3)\f[R]
diff --git a/libmariadb/man/mysql_stmt_warning_count.3 b/libmariadb/man/mysql_stmt_warning_count.3
new file mode 100644
index 00000000..2190719b
--- /dev/null
+++ b/libmariadb/man/mysql_stmt_warning_count.3
@@ -0,0 +1,38 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_stmt_warning_count" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_stmt_warning_count \- Returns the number of warnings from the last
+executed statement.
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_stmt_warning_count(MYSQL_STMT * stmt);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of warnings from the last executed statement, or zero
+if there are no warnings.
+## Parameter * \f[C]stmt\f[R] \- a statement handle, which was
+previously allocated by \f[B]mysql_stmt_init(3)\f[R].
+.SS Return value
+.PP
+Returns the number of warnings.
+.SS Notes
+.IP \[bu] 2
+For retrieving warning messages you should use the SQL command
+\f[C]SHOW WARNINGS\f[R].
+.IP \[bu] 2
+If SQL_MODE \f[C]TRADITIONAL\f[R] is enabled an error instead of warning
+will be returned.
+For detailed information check the server documentation.
+## History This function was added in Connector/C 3.0.
+.SS See Also
+.IP \[bu] 2
+\f[B]mysql_warning_count(3)\f[R]
diff --git a/libmariadb/man/mysql_store_result.3 b/libmariadb/man/mysql_store_result.3
new file mode 100644
index 00000000..5669063a
--- /dev/null
+++ b/libmariadb/man/mysql_store_result.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_store_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_store_result \- returns a buffered result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+MYSQL_RES * mysql_store_result(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns a buffered resultset from the last executed query.
+### Notes
+.IP \[bu] 2
+mysql_field_count() (imysql_field_count) indicates if there will be a
+result set available.
+.IP \[bu] 2
+The memory allocated by mysql_store_result() needs to be released by
+calling the function \f[B]mysql_free_result(3)\f[R].
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Return value
+.PP
+Returns a buffered result set or NULL in case an error occured or if the
+query didn\[cq]t return data (e.g.\ when executing an INSERT, UPDATE,
+DELETE or REPLACE statement).
+## See also * \f[B]mysql_free_result(3)\f[R] *
+\f[B]mysql_use_result(3)\f[R] * \f[B]mysql_real_query(3)\f[R] *
+\f[B]mysql_field_count(3)\f[R]
diff --git a/libmariadb/man/mysql_thread_end.3 b/libmariadb/man/mysql_thread_end.3
new file mode 100644
index 00000000..a7c91926
--- /dev/null
+++ b/libmariadb/man/mysql_thread_end.3
@@ -0,0 +1,36 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_thread_end" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_thread_end \- Releases thread specific memory
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+void mysql_thread_end(void );
+\f[R]
+.fi
+.SS Description
+.PP
+The mysql_thread_end() function needs to be called before a client
+thread ends.
+It will release thread specific memory, which was allocated by a
+previous \f[B]mysql_thread_init(3)\f[R] call.
+Returns void.
+.SS Notes
+.PP
+Unlike \f[B]mysql_thread_init(3)\f[R] mysql_thread_end() will not be
+invoked automatically if the thread ends.
+To avoid memory leaks mysql_thread_end() must be called explicitly.
+.SS History
+.PP
+This function is deprecated since MariaDB Connector/C 3.0.0.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_thread_init(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_thread_safe(3)\f[R]
diff --git a/libmariadb/man/mysql_thread_id.3 b/libmariadb/man/mysql_thread_id.3
new file mode 100644
index 00000000..a46fc7ca
--- /dev/null
+++ b/libmariadb/man/mysql_thread_id.3
@@ -0,0 +1,39 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_thread_id" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_thread_id \- Returns id of the current connection
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned long mysql_thread_id(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+The mysql_thread_id() function returns the thread id for the current
+connection.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+### Notes
+.IP \[bu] 2
+The current connection can be killed with \f[B]mysql_kill(3)\f[R].
+.IP \[bu] 2
+If reconnect option is enabled the thread id might change if the client
+reconnects to the server.
+.SS Return value
+.PP
+Returns the thread id of the current connection.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_kill(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_options(3)\f[R]
diff --git a/libmariadb/man/mysql_thread_init.3 b/libmariadb/man/mysql_thread_init.3
new file mode 100644
index 00000000..c382a555
--- /dev/null
+++ b/libmariadb/man/mysql_thread_init.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_thread_init" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_thread_init \- initialize thread
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+my_bool mysql_thread_init(void );
+\f[R]
+.fi
+.SS Description
+.PP
+Thread initialization for multi threaded clients.
+Multi threaded clients should call mysql_thread_init() at the beginning
+of the thread initialization to initialize thread specific client
+library variables.
+If mysql_thread_init() was not called explicitly, it will be called
+automatically by \f[B]mysql_init(3)\f[R] or
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+Before a client thread ends the \f[B]mysql_thread_end(3)\f[R] function
+must be called to release memory \- otherwise the client library will
+report an error.
+.SS Return value
+.PP
+Returns zero if successful or 1 if an error occurred.
+.SS History
+.PP
+This function is deprecated since MariaDB Connector/C 3.0.0.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_thread_end(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_thread_safe(3)\f[R]
diff --git a/libmariadb/man/mysql_use_result.3 b/libmariadb/man/mysql_use_result.3
new file mode 100644
index 00000000..a0777c29
--- /dev/null
+++ b/libmariadb/man/mysql_use_result.3
@@ -0,0 +1,46 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_use_result" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_use_result \- returns an unbuffered result set
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <nysql.h>
+
+MYSQL_RES * mysql_use_result(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Used to initiate the retrieval of a result set from the last query
+executed using the mysql_real_query() function on the database
+connection.
+Either this or the \f[B]mysql_store_result(3)\f[R] function must be
+called before the results of a query can be retrieved, and one or the
+other must be called to prevent the next query on that database
+connection from failing.
+.SS Parameters
+.IP \[bu] 2
+\f[C]mysql\f[R] is a connection identifier, which was previously
+allocated by \f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.PP
+The mysql_use_result() function does not transfer the entire result set.
+Hence several functions like \f[B]mysql_num_rows(3)\f[R] or
+\f[B]mysql_data_seek(3)\f[R] cannot be used.
+mysql_use_result() will block the current connection until all result
+sets are retrieved or result set was released by
+\f[B]mysql_free_result(3)\f[R].
+.SS Return value
+.PP
+Returns an unbuffered result set or \f[C]NULL\f[R] if an error occurred.
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_store_result(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_free_result(3)\f[R]
diff --git a/libmariadb/man/mysql_warning_count.3 b/libmariadb/man/mysql_warning_count.3
new file mode 100644
index 00000000..166bbf29
--- /dev/null
+++ b/libmariadb/man/mysql_warning_count.3
@@ -0,0 +1,41 @@
+.\" Automatically generated by Pandoc 2.5
+.\"
+.TH "mysql_warning_count" "3" "" "Version 3.3.1" "MariaDB Connector/C"
+.hy
+.SS Name
+.PP
+mysql_warning_count \- Returns the number of warnings
+.SS Synopsis
+.IP
+.nf
+\f[C]
+#include <mysql.h>
+
+unsigned int mysql_warning_count(MYSQL * mysql);
+\f[R]
+.fi
+.SS Description
+.PP
+Returns the number of warnings from the last executed query, or zero if
+there are no warnings.
+.SS Parameter
+.IP \[bu] 2
+\f[C]mysql\f[R] \- a mysql handle, which was previously allocated by
+\f[B]mysql_init(3)\f[R] and connected by
+\f[B]mysql_real_connect(3)\f[R].
+.SS Notes
+.IP \[bu] 2
+For retrieving warning messages you should use the SQL command
+\f[C]SHOW WARNINGS\f[R].
+.IP \[bu] 2
+If SQL_MODE \f[C]TRADITIONAL\f[R] is enabled an error instead of warning
+will be returned.
+For detailed information check the server documentation.
+.SS Return value
+.PP
+Returns the number of warnings
+.SS See also
+.IP \[bu] 2
+\f[B]mysql_error(3)\f[R]
+.IP \[bu] 2
+\f[B]mysql_errno(3)\f[R]
diff --git a/libmariadb/mariadb_config/CMakeLists.txt b/libmariadb/mariadb_config/CMakeLists.txt
new file mode 100644
index 00000000..0a32343d
--- /dev/null
+++ b/libmariadb/mariadb_config/CMakeLists.txt
@@ -0,0 +1,67 @@
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include)
+
+# Figure out additional libraries for use with
+
+FUNCTION(GET_LIB_NAME LIB_NAME LIB_OUT)
+ IF(APPLE)
+ STRING(FIND ${LIB_NAME} ".dylib" IS_SO)
+ ELSE()
+ STRING(FIND ${LIB_NAME} ".so" IS_SO)
+ ENDIF()
+ IF(NOT ${IS_SO} STREQUAL "-1")
+ GET_FILENAME_COMPONENT(LIB_FILE ${LIB_NAME} NAME_WE)
+ ELSE()
+ SET(LIB_FILE ${LIB_NAME})
+ ENDIF()
+
+ STRING(SUBSTRING ${LIB_NAME} 0 1 LIB_PREFIX)
+
+ IF(NOT ${LIB_PREFIX} STREQUAL "-")
+ SET(LIB_FILE "-l${LIB_FILE}")
+ STRING(REPLACE "-llib" "-l" LIB_FILE ${LIB_FILE})
+ SET(${LIB_OUT} ${LIB_FILE} PARENT_SCOPE)
+ ELSE()
+ SET(${LIB_OUT} ${LIB_NAME} PARENT_SCOPE)
+ ENDIF()
+ENDFUNCTION()
+
+LIST(LENGTH SYSTEM_LIBS rllength)
+IF(${rllength} GREATER 0)
+ LIST(REMOVE_DUPLICATES SYSTEM_LIBS)
+ENDIF()
+
+FOREACH (LIB_NAME ${SYSTEM_LIBS})
+ GET_LIB_NAME(${LIB_NAME} LIB_OUT)
+ SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${LIB_OUT}")
+ENDFOREACH()
+STRING(STRIP "${extra_dynamic_LDFLAGS}" extra_dynamic_LDFLAGS)
+LIST(REMOVE_DUPLICATES extra_dynamic_LDFLAGS)
+
+IF(UNIX AND NOT APPLE)
+ IF(ICONV_EXTERNAL)
+ GET_LIB_NAME(${ICONV_LIBRARIES} LIB_OUT)
+ SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${LIB_OUT}")
+ ENDIF()
+ENDIF()
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mariadb_config.c.in
+ ${CMAKE_CURRENT_BINARY_DIR}/mariadb_config.c @ONLY)
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libmariadb.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/libmariadb.pc @ONLY)
+
+ADD_EXECUTABLE(mariadb_config ${CMAKE_CURRENT_BINARY_DIR}/mariadb_config.c)
+
+IF(CMAKE_SYSTEM_NAME MATCHES AIX)
+ TARGET_LINK_LIBRARIES(mariadb_config compat-getopt)
+ENDIF()
+
+# Installation
+#
+INSTALL(TARGETS mariadb_config
+ DESTINATION "${INSTALL_BINDIR}"
+ COMPONENT Development)
+
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libmariadb.pc
+ DESTINATION "${INSTALL_PCDIR}"
+ COMPONENT Development)
diff --git a/libmariadb/mariadb_config/libmariadb.pc.in b/libmariadb/mariadb_config/libmariadb.pc.in
new file mode 100644
index 00000000..968181a1
--- /dev/null
+++ b/libmariadb/mariadb_config/libmariadb.pc.in
@@ -0,0 +1,20 @@
+#
+# pkg_config.pc.in
+#
+# pkg_config configuration file
+# For a detailed description of options, please visit
+# Dan Nicholson’s Guide to pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config/)
+#
+
+prefix=@CMAKE_INSTALL_PREFIX@
+includedir=${prefix}/@INSTALL_INCLUDEDIR@/@SUFFIX_INSTALL_DIR@
+libdir=${prefix}/@INSTALL_LIBDIR@/@SUFFIX_INSTALL_DIR@
+
+Name: libmariadb
+Version: @CPACK_PACKAGE_VERSION@
+Description: MariaDB Connector/C dynamic library
+Cflags: -I${includedir}
+Libs: -L${libdir} -lmariadb
+Libs.private: @extra_dynamic_LDFLAGS@
+
+
diff --git a/libmariadb/mariadb_config/mariadb_config.c.in b/libmariadb/mariadb_config/mariadb_config.c.in
new file mode 100644
index 00000000..36c01179
--- /dev/null
+++ b/libmariadb/mariadb_config/mariadb_config.c.in
@@ -0,0 +1,319 @@
+#include <ma_config.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mariadb_version.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/sysctl.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+#ifdef HAVE_LINUX_LIMITS_H
+#include <linux/limits.h>
+#endif
+#include <string.h>
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
+#endif
+
+static char *mariadb_progname;
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#define INCLUDE "-I%s/@INSTALL_INCLUDEDIR@ -I%s/@INSTALL_INCLUDEDIR@/mysql"
+#define LIBS "-L%s/@INSTALL_LIBDIR@/ -lmariadb"
+#define LIBS_SYS "@extra_dynamic_LDFLAGS@"
+#define CFLAGS INCLUDE
+#define VERSION "@MARIADB_CLIENT_VERSION@"
+#define CC_VERSION "@CPACK_PACKAGE_VERSION@"
+#define PLUGIN_DIR "%s/@INSTALL_PLUGINDIR@"
+#define SOCKET "@MARIADB_UNIX_ADDR@"
+#define PORT "@MARIADB_PORT@"
+#ifdef HAVE_TLS
+#define TLS_LIBRARY_VERSION "@TLS_LIBRARY_VERSION@"
+#else
+#define TLS_LIBRARY_VERSION ""
+#endif
+#define PKG_INCLUDEDIR "%s/@INSTALL_INCLUDEDIR@"
+#define PKG_PLUGINDIR "%s/@INSTALL_PLUGINDIR@"
+#define PKG_LIBDIR "%s/@INSTALL_LIBDIR@"
+
+#ifdef HAVE_EMBEDDED
+#define EMBEDDED_LIBS "-L@CMAKE_INSTALL_PREFIX@/@INSTALL_LIBDIR@/ -lmariadbd @extra_dynamic_LDFLAGS@"
+#endif
+
+#if defined(SOLARIS) || defined(__sun)
+#define OPT_STRING_TYPE (char *)
+#else
+#define OPT_STRING_TYPE
+#endif
+static struct option long_options[]=
+{
+ {OPT_STRING_TYPE "cflags", no_argument, 0, 'a'},
+ {OPT_STRING_TYPE "help", no_argument, 0, 'b'},
+ {OPT_STRING_TYPE "include", no_argument, 0, 'c'},
+ {OPT_STRING_TYPE "libs", no_argument, 0, 'd'},
+ {OPT_STRING_TYPE "libs_r", no_argument, 0, 'e'},
+ {OPT_STRING_TYPE "libs_sys", no_argument, 0, 'l'},
+ {OPT_STRING_TYPE "version", no_argument, 0, 'f'},
+ {OPT_STRING_TYPE "cc_version", no_argument, 0, 'g'},
+ {OPT_STRING_TYPE "socket", no_argument, 0, 'h'},
+ {OPT_STRING_TYPE "port", no_argument, 0, 'i'},
+ {OPT_STRING_TYPE "plugindir", no_argument, 0, 'j'},
+ {OPT_STRING_TYPE "tlsinfo", no_argument, 0, 'k'},
+ {OPT_STRING_TYPE "variable", 2, 0, 'm'},
+#ifdef HAVE_EMBEDDED
+ {OPT_STRING_TYPE "libmysqld-libs", no_argument, 0, 'n' },
+ {OPT_STRING_TYPE "embedded-libs", no_argument, 0, 'n' },
+ {OPT_STRING_TYPE "embedded", no_argument, 0, 'n' },
+#endif
+ {NULL, 0, 0, 0}
+};
+
+static struct {
+ const char *variable;
+ const char *value;
+} variables[] = {
+ {"pkgincludedir", PKG_INCLUDEDIR},
+ {"pkglibdir", PKG_LIBDIR},
+ {"pkgplugindir", PKG_PLUGINDIR},
+ {NULL, NULL}
+};
+
+char installation_dir[PATH_MAX];
+
+static const char *values[]=
+{
+ CFLAGS,
+ NULL,
+ INCLUDE,
+ LIBS,
+ LIBS,
+ LIBS_SYS,
+ VERSION,
+ CC_VERSION,
+ SOCKET,
+ PORT,
+ PLUGIN_DIR,
+ TLS_LIBRARY_VERSION,
+ "VAR VAR is one of:"
+#ifdef HAVE_EMBEDDED
+ ,EMBEDDED_LIBS
+#endif
+};
+
+void usage(void)
+{
+ int i=0;
+ puts("Copyright 2011-2020 MariaDB Corporation AB");
+ puts("Get compiler flags for using the MariaDB Connector/C.");
+ printf("Usage: %s [OPTIONS]\n", mariadb_progname);
+ printf("Compiler: @CMAKE_C_COMPILER_ID@ @CMAKE_C_COMPILER_VERSION@\n");
+ while (long_options[i].name)
+ {
+ if (!long_options[i].has_arg)
+ {
+ if (values[i])
+ {
+ printf(" --%-12s [", long_options[i].name);
+ printf(values[i], installation_dir, installation_dir);
+ printf("]\n");
+ }
+ } else
+ {
+ printf(" --%s=%s\n", long_options[i].name, values[i]);
+ /* Variables */
+ if (long_options[i].val == 'm')
+ {
+ int i= 0;
+ while (variables[i].variable)
+ {
+ printf(" %-14s [", variables[i].variable);
+ printf(variables[i].value, installation_dir);
+ printf("]\n");
+ i++;
+ }
+ }
+ }
+
+ i++;
+ }
+}
+
+/*
+ mariadb_get_install_location()
+ Tries to find the installation location in the following order:
+ 1) check if MARIADB_CONFIG environment variable was set
+ 2) try to determine the installation directory from executable path
+ 3) Fallback if 1 and 2 failed: use CMAKE_SYSROOT/CMAKE_INSTALL_PREFIX
+*/
+static void mariadb_get_install_location()
+{
+ char *p= NULL;
+ struct stat s;
+
+ /* Check environment variable MARIADB_CONFIG */
+ if ((p= getenv("MARIADB_CONFIG")))
+ {
+ if (!stat(p, &s) && S_ISREG(s.st_mode))
+ {
+ goto end;
+ }
+ }
+ /* Try to determine path of executable */
+ if (!(p= alloca(PATH_MAX)))
+ goto end;
+ else {
+#if defined(__APPLE__)
+ unsigned int len= PATH_MAX;
+ if (_NSGetExecutablePath(p, &len) != 0)
+ *p= 0;
+ else
+ {
+ p[len]= 0;
+ if (realpath(p, p) != 0)
+ *p= 0;
+ }
+#elif defined(__sun) || defined(SOLARIS)
+ if (realpath(getexecname(), p) == NULL)
+ *p= 0;
+#elif defined(__NetBSD__)
+ ssize_t len= readlink("/proc/curproc/exe", p, PATH_MAX);
+ if (len == -1 || len == PATH_MAX)
+ *p= 0;
+ else
+ p[len]= 0;
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+ size_t cb = PATH_MAX;
+ if (sysctl(mib, 4, p, &cb, NULL, 0) == -1)
+ *p= 0;
+ else
+ p[cb]= 0;
+#elif defined(__linux__)
+ ssize_t len= readlink("/proc/self/exe", p, PATH_MAX);
+ if (len == -1 || len == PATH_MAX)
+ *p= 0;
+ else
+ p[len]= 0;
+#else
+ *p= 0;
+#endif
+ }
+end:
+ if (p && p[0])
+ {
+ char *c, *search= alloca(6 + strlen(mariadb_progname));
+ sprintf(search, "/bin/%s", mariadb_progname);
+ c= strstr(p, search);
+ if (c)
+ {
+ strncpy(installation_dir, p, c - p);
+ }
+ else
+ *p=0;
+ }
+ if (!p || !p[0])
+ {
+ strncpy(installation_dir, "@CMAKE_SYSROOT@@CMAKE_INSTALL_PREFIX@", PATH_MAX - 1);
+ return;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ char *p = strrchr(argv[0], '/');
+ mariadb_progname= p ? p + 1 : argv[0];
+
+ mariadb_get_install_location();
+
+ if (argc <= 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while(1)
+ {
+ int option_index= 0;
+ c= getopt_long(argc, argv, "abcdefghijklmno", long_options, &option_index);
+
+ switch(c) {
+ case 'a': /* CFLAGS and Include directories */
+ printf(CFLAGS, installation_dir, installation_dir);
+ break;
+ case 'b': /* Usage */
+ usage();
+ break;
+ case 'c': /* Include directories */
+ printf(INCLUDE, installation_dir, installation_dir);
+ break;
+ case 'd': /* Library directories and names */
+ case 'e':
+ printf(LIBS, installation_dir);
+ break;
+ case 'f': /* Server version */
+ printf(VERSION);
+ break;
+ case 'g': /* Connector/C version */
+ printf(CC_VERSION);
+ break;
+ case 'h': /* Unix socket */
+ printf(SOCKET);
+ break;
+ case 'i': /* default port */
+ printf(PORT);
+ break;
+ case 'j': /* plugin directory */
+ printf(PLUGIN_DIR, installation_dir);
+ break;
+ case 'k': /* TLS version */
+ printf("%s", TLS_LIBRARY_VERSION);
+ break;
+ case 'l': /* System libraries */
+ printf(LIBS_SYS);
+ break;
+ case 'm': /* variable */
+ {
+ int i= 0;
+ while (variables[i].variable)
+ {
+ if (!strcmp(optarg, variables[i].variable))
+ {
+ printf(variables[i].value, installation_dir);
+ break;
+ }
+ i++;
+ }
+ if (!variables[i].variable)
+ {
+ printf("Unknown variable '%s'\n", optarg);
+ exit(1);
+ }
+ break;
+ }
+#ifdef HAVE_EMBEDDED
+ case 'n':
+ puts(EMBEDDED_LIBS);
+ break;
+#endif
+ default:
+ exit((c != -1));
+ }
+ printf("\n");
+ }
+
+ exit(0);
+}
+
diff --git a/libmariadb/plugins/CMakeLists.txt b/libmariadb/plugins/CMakeLists.txt
new file mode 100644
index 00000000..3b0e5e83
--- /dev/null
+++ b/libmariadb/plugins/CMakeLists.txt
@@ -0,0 +1,9 @@
+SET(PLUGIN_EXTRA_FILES ${CC_SOURCE_DIR}/libmariadb/ma_errmsg.c)
+
+
+FILE(GLOB plugin_dirs ${CC_SOURCE_DIR}/plugins/*)
+FOREACH(dir ${plugin_dirs})
+ IF (EXISTS ${dir}/CMakeLists.txt)
+ INCLUDE(${dir}/CMakeLists.txt)
+ ENDIF()
+ENDFOREACH()
diff --git a/libmariadb/plugins/auth/CMakeLists.txt b/libmariadb/plugins/auth/CMakeLists.txt
new file mode 100644
index 00000000..83e324b9
--- /dev/null
+++ b/libmariadb/plugins/auth/CMakeLists.txt
@@ -0,0 +1,142 @@
+SET(AUTH_DIR ${CC_SOURCE_DIR}/plugins/auth)
+
+INCLUDE_DIRECTORIES(${AUTH_DIR})
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include)
+
+SET(CRYPTO_PLUGIN 1)
+IF(WIN32)
+ ADD_DEFINITIONS(-DHAVE_WINCRYPT)
+ SET(CRYPT_SOURCE ${CC_SOURCE_DIR}/libmariadb/secure/win_crypt.c)
+ SET(CRYPT_LIBS crypt32 bcrypt)
+ELSEIF(WITH_SSL STREQUAL "OPENSSL")
+ SET(CRYPT_SOURCE ${CC_SOURCE_DIR}/libmariadb/secure/openssl_crypt.c)
+ SET(CRYPT_LIBS ${SSL_LIBRARIES})
+ELSEIF(WITH_SSL STREQUAL "GNUTLS")
+ SET(CRYPT_SOURCE ${CC_SOURCE_DIR}/libmariadb/secure/gnutls_crypt.c)
+ IF (NOT SSL_LIBRARIES MATCHES "^.*\\.a$")
+ SET(CRYPT_LIBS ${SSL_LIBRARIES})
+ ENDIF()
+ELSE()
+ UNSET(CRYPTO_PLUGIN)
+ENDIF()
+
+#native password
+REGISTER_PLUGIN(TARGET mysql_native_password
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS STATIC
+ DEFAULT STATIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/auth/my_auth.c)
+
+#Dialog client authentication plugin
+REGISTER_PLUGIN(TARGET dialog
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT DYNAMIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/auth/dialog.c
+ ${CC_SOURCE_DIR}/libmariadb/get_password.c)
+
+
+# Crypto plugins
+IF(CRYPTO_PLUGIN)
+
+ #ED25519 client authentication plugin
+ SET(REF10_DIR ${CC_SOURCE_DIR}/plugins/auth/ref10)
+ SET(REF10_SOURCES ${REF10_DIR}/fe_0.c ${REF10_DIR}/fe_isnegative.c ${REF10_DIR}/fe_sub.c ${REF10_DIR}/ge_p1p1_to_p2.c
+ ${REF10_DIR}/ge_p3_to_cached.c ${REF10_DIR}/open.c ${REF10_DIR}/fe_1.c ${REF10_DIR}/fe_isnonzero.c
+ ${REF10_DIR}/fe_tobytes.c ${REF10_DIR}/ge_p1p1_to_p3.c ${REF10_DIR}/ge_p3_to_p2.c ${REF10_DIR}/sc_muladd.c
+ ${REF10_DIR}/fe_add.c ${REF10_DIR}/fe_mul.c ${REF10_DIR}/ge_add.c ${REF10_DIR}/ge_p2_0.c ${REF10_DIR}/ge_precomp_0.c
+ ${REF10_DIR}/sc_reduce.c ${REF10_DIR}/fe_cmov.c ${REF10_DIR}/fe_neg.c ${REF10_DIR}/ge_double_scalarmult.c
+ ${REF10_DIR}/ge_p2_dbl.c ${REF10_DIR}/ge_scalarmult_base.c ${REF10_DIR}/sign.c ${REF10_DIR}/fe_copy.c
+ ${REF10_DIR}/fe_pow22523.c ${REF10_DIR}/ge_frombytes.c ${REF10_DIR}/ge_p3_0.c ${REF10_DIR}/ge_sub.c
+ ${REF10_DIR}/verify.c ${REF10_DIR}/fe_frombytes.c ${REF10_DIR}/fe_sq2.c ${REF10_DIR}/ge_madd.c
+ ${REF10_DIR}/ge_p3_dbl.c ${REF10_DIR}/ge_tobytes.c ${REF10_DIR}/fe_invert.c ${REF10_DIR}/fe_sq.c
+ ${REF10_DIR}/ge_msub.c ${REF10_DIR}/ge_p3_tobytes.c ${REF10_DIR}/keypair.c)
+
+ REGISTER_PLUGIN(TARGET client_ed25519
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT DYNAMIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/auth/ed25519.c
+ ${REF10_SOURCES}
+ ${CRYPT_SOURCE}
+ INCLUDES ${REF10_DIR}
+ LIBRARIES ${CRYPT_LIBS}
+ COMPILE_OPTIONS -DMYSQL_CLIENT=1)
+ IF(MSVC)
+ # Silence conversion (integer truncation) warnings from reference code
+ SET_SOURCE_FILES_PROPERTIES(${REF10_SOURCES} PROPERTY COMPILE_FLAGS "-DMYSQL_CLIENT=1 /wd4244 /wd4146")
+ ENDIF()
+
+ IF(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION LESS 11
+ AND CMAKE_C_COMPILER_VERSION GREATER 6)
+ SET_SOURCE_FILES_PROPERTIES(${REF10_SOURCES} PROPERTY COMPILE_FLAGS
+ -fno-sanitize=shift)
+ ENDIF()
+
+ # SHA256 caching plugin for MySQL 8.0 connection
+ REGISTER_PLUGIN(TARGET caching_sha2_password
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT DYNAMIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/auth/caching_sha2_pw.c
+ ${CRYPT_SOURCE}
+ LIBRARIES ${CRYPT_LIBS})
+
+ IF(WITH_SSL STREQUAL "GNUTLS" AND NOT WIN32)
+ MESSAGE1(STATUS "sha256_password not supported by GnuTLS due to missing OAEP padding")
+ ELSE()
+ REGISTER_PLUGIN(TARGET sha256_password
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT DYNAMIC
+ SOURCES ${AUTH_DIR}/sha256_pw.c
+ LIBRARIES ${CRYPT_LIBS})
+ ENDIF()
+ENDIF()
+
+#GSSAPI client authentication plugin
+IF(NOT WIN32)
+ INCLUDE(${CC_SOURCE_DIR}/cmake/FindGSSAPI.cmake)
+ IF(GSSAPI_FOUND)
+ SET(GSSAPI_SOURCES ${AUTH_DIR}/auth_gssapi_client.c ${AUTH_DIR}/gssapi_client.c ${AUTH_DIR}/gssapi_errmsg.c)
+ IF (CMAKE_VERSION VERSION_GREATER 3.18)
+ INCLUDE(CheckLinkerFlag)
+ CHECK_LINKER_FLAG(C -Wl,--as-needed have__Wl___as_needed)
+ ENDIF()
+ ENDIF()
+ SET(AUTH_GSSAPI_DEFAULT_CONFIG DYNAMIC)
+ELSE()
+ SET(GSSAPI_LIBS secur32)
+ SET(GSSAPI_SOURCES ${AUTH_DIR}/auth_gssapi_client.c ${AUTH_DIR}/sspi_client.c ${AUTH_DIR}/sspi_errmsg.c)
+ SET(AUTH_GSSAPI_DEFAULT_CONFIG STATIC)
+ENDIF()
+IF(GSSAPI_SOURCES)
+ REGISTER_PLUGIN(TARGET auth_gssapi_client
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT ${AUTH_GSSAPI_DEFAULT_CONFIG}
+ SOURCES ${GSSAPI_SOURCES}
+ INCLUDES ${CC_SOURCE_DIR}/plugins/auth ${GSSAPI_INCS}
+ LIBRARIES ${GSSAPI_LIBS})
+ IF(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ SET_SOURCE_FILES_PROPERTIES(${GSSAPI_SOURCES} PROPERTY COMPILE_FLAGS "-Wno-deprecated-declarations")
+ ENDIF()
+ IF(have__Wl___as_needed AND TARGET auth_gssapi_client)
+ SET_TARGET_PROPERTIES(auth_gssapi_client PROPERTIES LINK_FLAGS "-Wl,--as-needed")
+ ENDIF()
+ENDIF()
+
+# old_password plugin
+REGISTER_PLUGIN(TARGET mysql_old_password
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS STATIC DYNAMIC OFF
+ DEFAULT STATIC
+ SOURCES ${AUTH_DIR}/old_password.c)
+
+# Cleartext
+REGISTER_PLUGIN(TARGET mysql_clear_password
+ TYPE MARIADB_CLIENT_PLUGIN_AUTH
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT DYNAMIC
+ SOURCES ${AUTH_DIR}/mariadb_cleartext.c)
+
diff --git a/libmariadb/plugins/auth/auth_gssapi_client.c b/libmariadb/plugins/auth/auth_gssapi_client.c
new file mode 100644
index 00000000..6f6c6ceb
--- /dev/null
+++ b/libmariadb/plugins/auth/auth_gssapi_client.c
@@ -0,0 +1,121 @@
+/* Copyright (c) 2015-2016, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*/
+
+/**
+ @file
+
+ GSSAPI authentication plugin, client side
+*/
+#include <string.h>
+#include <stdarg.h>
+#include <ma_global.h>
+#include <mysql.h>
+#include <ma_server_error.h>
+#include <mysql/client_plugin.h>
+#include <mysql.h>
+#include <stdio.h>
+#include "common.h"
+
+extern int auth_client(char *principal_name,
+ char *mech,
+ MYSQL *mysql,
+ MYSQL_PLUGIN_VIO *vio);
+
+static void parse_server_packet(char *packet, size_t packet_len, char *spn, char *mech)
+{
+ size_t spn_len;
+ spn_len = strnlen(packet, packet_len);
+ strncpy(spn, packet, PRINCIPAL_NAME_MAX);
+ if (spn_len == packet_len - 1)
+ {
+ /* Mechanism not included into packet */
+ *mech = 0;
+ }
+ else
+ {
+ strncpy(mech, packet + spn_len + 1, MECH_NAME_MAX);
+ }
+}
+
+/**
+ Set client error message.
+ */
+void log_client_error(MYSQL *mysql, const char *format, ...)
+{
+ NET *net= &mysql->net;
+ va_list args;
+
+ net->last_errno= ER_UNKNOWN_ERROR;
+ va_start(args, format);
+ vsnprintf(net->last_error, sizeof(net->last_error) - 1,
+ format, args);
+ va_end(args);
+ memcpy(net->sqlstate, "HY000", sizeof(net->sqlstate));
+}
+
+/**
+ The main client function of the GSSAPI plugin.
+ */
+static int gssapi_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ int packet_len;
+ unsigned char *packet;
+ char spn[PRINCIPAL_NAME_MAX + 1];
+ char mech[MECH_NAME_MAX + 1];
+
+ /* read from server for service principal name */
+ packet_len= vio->read_packet(vio, &packet);
+ if (packet_len < 0)
+ {
+ return CR_ERROR;
+ }
+ parse_server_packet((char *)packet, (size_t)packet_len, spn, mech);
+ return auth_client(spn, mech, mysql, vio);
+}
+
+
+/* register client plugin */
+#ifndef PLUGIN_DYNAMIC
+struct st_mysql_client_plugin_AUTHENTICATION auth_gssapi_client_client_plugin=
+#else
+struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
+#endif
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "auth_gssapi_client",
+ "Shuang Qiu, Robbie Harwood, Vladislav Vaintroub, Georg Richter",
+ "GSSAPI/SSPI based authentication",
+ {0, 1, 0},
+ "BSD",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gssapi_auth_client
+};
diff --git a/libmariadb/plugins/auth/caching_sha2_pw.c b/libmariadb/plugins/auth/caching_sha2_pw.c
new file mode 100644
index 00000000..b442e477
--- /dev/null
+++ b/libmariadb/plugins/auth/caching_sha2_pw.c
@@ -0,0 +1,464 @@
+/************************************************************************************
+ Copyright (C) 2017, 2022, MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+ *************************************************************************************/
+#ifndef _WIN32
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_WINCRYPT
+#undef HAVE_OPENSSL
+#undef HAVE_GNUTLS
+#endif
+
+#if defined(HAVE_OPENSSL) || defined(HAVE_WINCRYPT) || defined(HAVE_GNUTLS)
+
+#include <ma_global.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+#include <errmsg.h>
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+#if defined(HAVE_OPENSSL)
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#elif defined(HAVE_GNUTLS)
+#include <gnutls/gnutls.h>
+#elif defined(HAVE_WINCRYPT)
+#include <windows.h>
+#include <wincrypt.h>
+#include <bcrypt.h>
+
+#endif
+
+#include <ma_crypt.h>
+
+#define MAX_PW_LEN 1024
+
+#define REQUEST_PUBLIC_KEY 2
+#define CACHED_LOGIN_SUCCEEDED 3
+#define RSA_LOGIN_REQUIRED 4
+
+/* MySQL server allows requesting public key only for non secure connections.
+ secure connections are:
+ - TLS/SSL connections
+ - unix_socket connections
+*/
+static unsigned char is_connection_secure(MYSQL *mysql)
+{
+ if (mysql->options.use_ssl ||
+ mysql->net.pvio->type != PVIO_TYPE_SOCKET)
+ return 1;
+ return 0;
+}
+
+static int ma_sha256_scramble(unsigned char *scramble, size_t scramble_len,
+ unsigned char *source, size_t source_len,
+ unsigned char *salt, size_t salt_len)
+{
+ unsigned char digest1[MA_SHA256_HASH_SIZE],
+ digest2[MA_SHA256_HASH_SIZE],
+ new_scramble[MA_SHA256_HASH_SIZE];
+
+ MA_HASH_CTX *ctx = NULL;
+ size_t i;
+
+ /* check if all specified lengths are valid */
+ if (!scramble_len || !source_len || !salt_len)
+ return 1;
+
+ /* Step1: create sha256 from source */
+ if (!(ctx= ma_hash_new(MA_HASH_SHA256)))
+ return 1;
+ ma_hash_input(ctx, source, source_len);
+ ma_hash_result(ctx, digest1);
+ ma_hash_free(ctx);
+
+
+ /* Step2: create sha256 digest from digest1 */
+ if (!(ctx= ma_hash_new(MA_HASH_SHA256)))
+ return 1;
+ ma_hash_input(ctx, digest1, MA_SHA256_HASH_SIZE);
+ ma_hash_result(ctx, digest2);
+ ma_hash_free(ctx);
+
+ /* Step3: create sha256 digest from digest2 + salt */
+ if (!(ctx= ma_hash_new(MA_HASH_SHA256)))
+ return 1;
+ ma_hash_input(ctx, digest2, MA_SHA256_HASH_SIZE);
+ ma_hash_input(ctx, salt, salt_len);
+ ma_hash_result(ctx, new_scramble);
+ ma_hash_free(ctx);
+
+ /* Step4: xor(digest1, scramble1) */
+ for (i= 0; i < scramble_len; i++)
+ scramble[i]= digest1[i] ^ new_scramble[i];
+ return 0;
+}
+
+/* function prototypes */
+static int auth_caching_sha2_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int auth_caching_sha2_deinit(void);
+static int auth_caching_sha2_init(char *unused1,
+ size_t unused2,
+ int unused3,
+ va_list);
+
+
+#ifndef PLUGIN_DYNAMIC
+struct st_mysql_client_plugin_AUTHENTICATION caching_sha2_password_client_plugin=
+#else
+struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
+#endif
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "caching_sha2_password",
+ "Georg Richter",
+ "Caching SHA2 Authentication Plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ auth_caching_sha2_init,
+ auth_caching_sha2_deinit,
+ NULL,
+ auth_caching_sha2_client
+};
+
+#ifdef HAVE_WINCRYPT
+static LPBYTE ma_load_pem(const char *buffer, DWORD *buffer_len)
+{
+ LPBYTE der_buffer= NULL;
+ DWORD der_buffer_length= 0;
+
+ if (buffer_len == NULL || *buffer_len == 0)
+ return NULL;
+ /* calculate the length of DER binary */
+ if (!CryptStringToBinaryA(buffer, *buffer_len, CRYPT_STRING_BASE64HEADER,
+ NULL, &der_buffer_length, NULL, NULL))
+ goto end;
+ /* allocate DER binary buffer */
+ if (!(der_buffer= (LPBYTE)malloc(der_buffer_length)))
+ goto end;
+ /* convert to DER binary */
+ if (!CryptStringToBinaryA(buffer, *buffer_len, CRYPT_STRING_BASE64HEADER,
+ der_buffer, &der_buffer_length, NULL, NULL))
+ goto end;
+
+ *buffer_len= der_buffer_length;
+
+ return der_buffer;
+
+end:
+ if (der_buffer)
+ free(der_buffer);
+ *buffer_len= 0;
+ return NULL;
+}
+#endif
+
+#ifndef HAVE_GNUTLS
+static char *load_pub_key_file(const char *filename, int *pub_key_size)
+{
+ FILE *fp= NULL;
+ char *buffer= NULL;
+ unsigned char error= 1;
+
+ if (!pub_key_size)
+ return NULL;
+
+ if (!(fp= fopen(filename, "r")))
+ goto end;
+
+ if (fseek(fp, 0, SEEK_END))
+ goto end;
+
+ if ((*pub_key_size= ftell(fp)) < 0)
+ goto end;
+
+ rewind(fp);
+
+ if (!(buffer= malloc(*pub_key_size + 1)))
+ goto end;
+
+ if (fread(buffer, *pub_key_size, 1, fp) != (size_t)*pub_key_size)
+ goto end;
+
+ error= 0;
+
+end:
+ if (fp)
+ fclose(fp);
+ if (error && buffer)
+ {
+ free(buffer);
+ buffer= NULL;
+ }
+ return buffer;
+}
+#endif
+
+static int auth_caching_sha2_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ unsigned char *packet;
+ int packet_length;
+ int rc= CR_ERROR;
+#if !defined(HAVE_GNUTLS)
+ char passwd[MAX_PW_LEN];
+#ifdef HAVE_OPENSSL
+ unsigned char *rsa_enc_pw= NULL;
+ size_t rsa_size;
+#else
+ unsigned char rsa_enc_pw[MAX_PW_LEN];
+ ULONG rsa_size;
+#endif
+ unsigned int pwlen, i;
+ char *filebuffer= NULL;
+#endif
+ unsigned char buf[MA_SHA256_HASH_SIZE];
+
+#if defined(HAVE_OPENSSL)
+ EVP_PKEY *pubkey= NULL;
+ EVP_PKEY_CTX *ctx= NULL;
+ BIO *bio;
+ size_t outlen;
+#elif defined(HAVE_WINCRYPT)
+ BCRYPT_KEY_HANDLE pubkey= 0;
+ BCRYPT_OAEP_PADDING_INFO paddingInfo;
+ LPBYTE der_buffer= NULL;
+ DWORD der_buffer_len= 0;
+ CERT_PUBLIC_KEY_INFO *publicKeyInfo= NULL;
+ DWORD publicKeyInfoLen;
+#endif
+
+ /* read error */
+ if ((packet_length= vio->read_packet(vio, &packet)) < 0)
+ return CR_ERROR;
+
+ if (packet_length != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ memmove(mysql->scramble_buff, packet, SCRAMBLE_LENGTH);
+ mysql->scramble_buff[SCRAMBLE_LENGTH]= 0;
+
+ /* send empty packet if no password was provided */
+ if (!mysql->passwd || !mysql->passwd[0])
+ {
+ if (vio->write_packet(vio, 0, 0))
+ return CR_ERROR;
+ return CR_OK;
+ }
+
+ /* This is the normal authentication, if the host/user key is already in server
+ cache. In case authentication will fail, we will not return an error but will
+ try to connect via RSA encryption.
+ */
+ if (ma_sha256_scramble(buf, MA_SHA256_HASH_SIZE,
+ (unsigned char *)mysql->passwd, strlen(mysql->passwd),
+ (unsigned char *)mysql->scramble_buff, SCRAMBLE_LENGTH))
+ return CR_ERROR;
+
+ if (vio->write_packet(vio, buf, MA_SHA256_HASH_SIZE))
+ return CR_ERROR;
+ if ((packet_length=vio->read_packet(vio, &packet)) == -1)
+ return CR_ERROR;
+ if (packet_length == 1)
+ {
+ switch (*packet) {
+ case CACHED_LOGIN_SUCCEEDED:
+ return CR_OK;
+ case RSA_LOGIN_REQUIRED:
+ break;
+ default:
+ return CR_ERROR;
+ }
+ }
+
+ if (!is_connection_secure(mysql))
+ {
+#if defined(HAVE_GNUTLS)
+ mysql->methods->set_error(mysql, CR_AUTH_PLUGIN_ERR, "HY000",
+ "RSA Encryption not supported - caching_sha2_password plugin was built with GnuTLS support");
+ return CR_ERROR;
+#else
+ /* read public key file (if specified) */
+ if (mysql->options.extension &&
+ mysql->options.extension->server_public_key)
+ {
+ filebuffer= load_pub_key_file(mysql->options.extension->server_public_key,
+ &packet_length);
+ }
+
+ /* if no public key file was specified or if we couldn't read the file,
+ we ask server to send public key */
+ if (!filebuffer)
+ {
+ unsigned char request= REQUEST_PUBLIC_KEY;
+ if (vio->write_packet(vio, &request, 1) ||
+ (packet_length=vio->read_packet(vio, &packet)) == -1)
+ {
+ mysql->methods->set_error(mysql, CR_AUTH_PLUGIN_ERR, "HY000", "Couldn't read RSA public key from server");
+ return CR_ERROR;
+ }
+ }
+#if defined(HAVE_OPENSSL)
+ bio= BIO_new_mem_buf(filebuffer ? (unsigned char *)filebuffer : packet,
+ packet_length);
+ if (!(pubkey= PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
+ goto error;
+ if (!(ctx= EVP_PKEY_CTX_new(pubkey, NULL)))
+ goto error;
+ if (EVP_PKEY_encrypt_init(ctx) <= 0)
+ goto error;
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
+ goto error;
+ rsa_size= EVP_PKEY_size(pubkey);
+ BIO_free(bio);
+ bio= NULL;
+ ERR_clear_error();
+#elif defined(HAVE_WINCRYPT)
+ der_buffer_len= packet_length;
+ /* Load pem and convert it to binary object. New length will be returned
+ in der_buffer_len */
+ if (!(der_buffer= ma_load_pem(filebuffer ? filebuffer : (char *)packet, &der_buffer_len)))
+ goto error;
+
+ /* Create context and load public key */
+ if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
+ der_buffer, der_buffer_len,
+ CRYPT_DECODE_ALLOC_FLAG, NULL,
+ &publicKeyInfo, &publicKeyInfoLen))
+ goto error;
+ free(der_buffer);
+
+ /* Import public key as cng key */
+ if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, publicKeyInfo,
+ CRYPT_OID_INFO_PUBKEY_ENCRYPT_KEY_FLAG,
+ NULL, &pubkey))
+ goto error;
+
+#endif
+ if (!pubkey)
+ return CR_ERROR;
+
+ pwlen= (unsigned int)strlen(mysql->passwd) + 1; /* include terminating zero */
+ if (pwlen > MAX_PW_LEN)
+ goto error;
+ memcpy(passwd, mysql->passwd, pwlen);
+
+ /* xor password with scramble */
+ for (i=0; i < pwlen; i++)
+ passwd[i]^= *(mysql->scramble_buff + i % SCRAMBLE_LENGTH);
+
+ /* encrypt scrambled password */
+#if defined(HAVE_OPENSSL)
+ if (EVP_PKEY_encrypt(ctx, NULL, &outlen, (unsigned char *)passwd, pwlen) <= 0)
+ goto error;
+ if (!(rsa_enc_pw= malloc(outlen)))
+ goto error;
+ if (EVP_PKEY_encrypt(ctx, rsa_enc_pw, &outlen, (unsigned char *)passwd, pwlen) <= 0)
+ goto error;
+#elif defined(HAVE_WINCRYPT)
+ ZeroMemory(&paddingInfo, sizeof(paddingInfo));
+ paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
+ if ((rc= BCryptEncrypt(pubkey, (PUCHAR)passwd, pwlen, &paddingInfo, NULL, 0, rsa_enc_pw,
+ MAX_PW_LEN, &rsa_size, BCRYPT_PAD_OAEP)))
+ goto error;
+
+#endif
+ if (vio->write_packet(vio, rsa_enc_pw, rsa_size))
+ goto error;
+
+ rc= CR_OK;
+#endif
+ }
+ else
+ {
+ if (vio->write_packet(vio, (unsigned char *)mysql->passwd, (int)strlen(mysql->passwd) + 1))
+ return CR_ERROR;
+ return CR_OK;
+ }
+#if !defined(HAVE_GNUTLS)
+error:
+#if defined(HAVE_OPENSSL)
+ if (pubkey)
+ EVP_PKEY_free(pubkey);
+ if (rsa_enc_pw)
+ free(rsa_enc_pw);
+ if (bio)
+ BIO_free(bio);
+ if (ctx)
+ EVP_PKEY_CTX_free(ctx);
+#elif defined(HAVE_WINCRYPT)
+ if (pubkey)
+ BCryptDestroyKey(pubkey);
+ if (publicKeyInfo)
+ LocalFree(publicKeyInfo);
+#endif
+ free(filebuffer);
+#endif
+ return rc;
+}
+/* }}} */
+
+/* {{{ static int auth_caching_sha2_init */
+/*
+ Initialization routine
+
+ SYNOPSIS
+ auth_sha256_init
+ unused1
+ unused2
+ unused3
+ unused4
+
+ DESCRIPTION
+ Init function checks if the caller provides own dialog function.
+ The function name must be mariadb_auth_dialog or
+ mysql_authentication_dialog_ask. If the function cannot be found,
+ we will use owr own simple command line input.
+
+ RETURN
+ 0 success
+ */
+static int auth_caching_sha2_init(char *unused1 __attribute__((unused)),
+ size_t unused2 __attribute__((unused)),
+ int unused3 __attribute__((unused)),
+ va_list unused4 __attribute__((unused)))
+{
+ return 0;
+}
+/* }}} */
+
+/* {{{ auth_caching_sha2_deinit */
+static int auth_caching_sha2_deinit(void)
+{
+ return 0;
+}
+/* }}} */
+
+#endif /* defined(HAVE_OPENSSL) || defined(HAVE_WINCRYPT) || defined(HAVE_GNUTLS)*/
+
diff --git a/libmariadb/plugins/auth/common.h b/libmariadb/plugins/auth/common.h
new file mode 100644
index 00000000..c04241ac
--- /dev/null
+++ b/libmariadb/plugins/auth/common.h
@@ -0,0 +1,4 @@
+/** Maximal length of the target name */
+#define PRINCIPAL_NAME_MAX 256
+/** Maximal length of the mech string */
+#define MECH_NAME_MAX 30
diff --git a/libmariadb/plugins/auth/dialog.c b/libmariadb/plugins/auth/dialog.c
new file mode 100644
index 00000000..31d7b7d8
--- /dev/null
+++ b/libmariadb/plugins/auth/dialog.c
@@ -0,0 +1,222 @@
+/************************************************************************************
+ Copyright (C) 2014-2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+#ifndef _WIN32
+#define _GNU_SOURCE 1
+#endif
+
+#include <ma_global.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+
+/* function prototypes */
+extern char *get_tty_password(char *opt_message, char *buff, int bufflen);
+static int auth_dialog_open(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int auth_dialog_init(char *unused1,
+ size_t unused2,
+ int unused3,
+ va_list);
+
+mysql_authentication_dialog_ask_t auth_dialog_func;
+
+#ifndef PLUGIN_DYNAMIC
+struct st_mysql_client_plugin_AUTHENTICATION dialog_client_plugin=
+#else
+struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
+#endif
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "dialog",
+ "Sergei Golubchik, Georg Richter",
+ "Dialog Client Authentication Plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ auth_dialog_init,
+ NULL,
+ NULL,
+ auth_dialog_open
+};
+
+
+/* {{{ static char *auth_dialog_native_prompt */
+/*
+ Native dialog prompt via stdin
+
+ SYNOPSIS
+ auth_dialog_native_prompt
+ mysql connection handle
+ type input type
+ prompt prompt
+ buffer Input buffer
+ buffer_len Input buffer length
+
+ DESCRIPTION
+
+ RETURNS
+ Input buffer
+*/
+static char *auth_dialog_native_prompt(MYSQL *mysql __attribute__((unused)),
+ int type,
+ const char *prompt,
+ char *buffer,
+ int buffer_len)
+{
+ /* display prompt */
+ fprintf(stdout, "%s", prompt);
+
+ memset(buffer, 0, buffer_len);
+
+ /* for type 2 (password) don't display input */
+ if (type != 2)
+ {
+ if (fgets(buffer, buffer_len - 1, stdin))
+ {
+ /* remove trailing line break */
+ size_t length= strlen(buffer);
+ if (length && buffer[length - 1] == '\n')
+ buffer[length - 1]= 0;
+ }
+ }
+ else
+ {
+ get_tty_password((char *)"", buffer, buffer_len - 1);
+ }
+ return buffer;
+}
+/* }}} */
+
+/* {{{ static int auth_dialog_open */
+/*
+ opens dialog
+
+ SYNOPSIS
+ vio Vio
+ mysql connection handle
+
+ DESCRIPTION
+ reads prompt from server, waits for input and sends
+ input to server.
+ Note that first byte of prompt indicates if we have a
+ password which should not be echoed to stdout.
+
+ RETURN
+ CR_ERROR if an error occurs
+ CR_OK
+ CR_OK_HANDSHAKE_COMPLETE
+*/
+static int auth_dialog_open(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ uchar *packet;
+ uchar type= 0;
+ char dialog_buffer[1024];
+ char *response;
+ int packet_length;
+ my_bool first_loop= TRUE;
+
+ do {
+ if ((packet_length= vio->read_packet(vio, &packet)) == -1)
+ /* read error */
+ return CR_ERROR;
+
+ if (packet_length > 0)
+ {
+ type= *packet;
+ packet++;
+
+ /* check for protocol packet */
+ if (!type || type == 254)
+ return CR_OK_HANDSHAKE_COMPLETE;
+
+ if ((type >> 1) == 2 &&
+ first_loop &&
+ mysql->passwd && mysql->passwd[0])
+ response= mysql->passwd;
+ else
+ response= auth_dialog_func(mysql, type >> 1,
+ (const char *)packet,
+ dialog_buffer, 1024);
+ }
+ else
+ {
+ /* in case mysql_change_user was called the client needs
+ to send packet first */
+ response= mysql->passwd;
+ }
+ if (!response ||
+ vio->write_packet(vio, (uchar *)response, (int)strlen(response) + 1))
+ return CR_ERROR;
+
+ first_loop= FALSE;
+
+ } while((type & 1) != 1);
+ return CR_OK;
+}
+/* }}} */
+
+/* {{{ static int auth_dialog_init */
+/*
+ Initialization routine
+
+ SYNOPSIS
+ auth_dialog_init
+ unused1
+ unused2
+ unused3
+ unused4
+
+ DESCRIPTION
+ Init function checks if the caller provides own dialog function.
+ The function name must be mariadb_auth_dialog or
+ mysql_authentication_dialog_ask. If the function cannot be found,
+ we will use owr own simple command line input.
+
+ RETURN
+ 0 success
+*/
+static int auth_dialog_init(char *unused1 __attribute__((unused)),
+ size_t unused2 __attribute__((unused)),
+ int unused3 __attribute__((unused)),
+ va_list unused4 __attribute__((unused)))
+{
+ void *func;
+#ifdef WIN32
+ if (!(func= GetProcAddress(GetModuleHandle(NULL), "mariadb_auth_dialog")))
+ /* for MySQL users */
+ func= GetProcAddress(GetModuleHandle(NULL), "mysql_authentication_dialog_ask");
+#else
+ if (!(func= dlsym(RTLD_DEFAULT, "mariadb_auth_dialog")))
+ /* for MySQL users */
+ func= dlsym(RTLD_DEFAULT, "mysql_authentication_dialog_ask");
+#endif
+ if (func)
+ auth_dialog_func= (mysql_authentication_dialog_ask_t)func;
+ else
+ auth_dialog_func= auth_dialog_native_prompt;
+
+ return 0;
+}
+/* }}} */
diff --git a/libmariadb/plugins/auth/ed25519.c b/libmariadb/plugins/auth/ed25519.c
new file mode 100644
index 00000000..38b896f8
--- /dev/null
+++ b/libmariadb/plugins/auth/ed25519.c
@@ -0,0 +1,137 @@
+/************************************************************************************
+ Copyright (C) 2017-2019 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+ *************************************************************************************/
+#ifndef _WIN32
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_WINCRYPT
+#undef HAVE_OPENSSL
+#undef HAVE_GNUTLS
+#endif
+
+#if defined(HAVE_OPENSSL) || defined(HAVE_WINCRYPT) || defined(HAVE_GNUTLS)
+
+#include <ma_global.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+#include <errmsg.h>
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+#if defined(HAVE_WINCRYPT)
+#include <windows.h>
+#include <wincrypt.h>
+#include <bcrypt.h>
+#elif defined(HAVE_OPENSSL)
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#elif defined(HAVE_GNUTLS)
+#include <gnutls/gnutls.h>
+#endif
+
+#include <ref10/api.h>
+#include <ed25519_common.h>
+#include <ma_crypt.h>
+
+/* function prototypes */
+static int auth_ed25519_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int auth_ed25519_deinit(void);
+static int auth_ed25519_init(char *unused1,
+ size_t unused2,
+ int unused3,
+ va_list);
+
+
+#ifndef PLUGIN_DYNAMIC
+struct st_mysql_client_plugin_AUTHENTICATION client_ed25519_client_plugin=
+#else
+struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
+#endif
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "client_ed25519",
+ "Sergei Golubchik, Georg Richter",
+ "Ed25519 Authentication Plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ auth_ed25519_init,
+ auth_ed25519_deinit,
+ NULL,
+ auth_ed25519_client
+};
+
+
+static int auth_ed25519_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ unsigned char *packet,
+ signature[CRYPTO_BYTES + NONCE_BYTES];
+ int pkt_len;
+
+ /*
+ Step 1: Server sends nonce
+ Step 2: check that packet length is equal to NONCE_BYTES (=32)
+ Step 3: Sign the nonce with password
+ Steo 4: Send the signature back to server
+ */
+
+ /* read and check nonce */
+ pkt_len= vio->read_packet(vio, &packet);
+ if (pkt_len != NONCE_BYTES)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* Sign nonce: the crypto_sign function is part of ref10 */
+ ma_crypto_sign(signature, packet, NONCE_BYTES, (unsigned char*)mysql->passwd, strlen(mysql->passwd));
+
+ /* send signature to server */
+ if (vio->write_packet(vio, signature, CRYPTO_BYTES))
+ return CR_ERROR;
+
+ return CR_OK;
+}
+/* }}} */
+
+/* {{{ static int auth_ed25519_init */
+static int auth_ed25519_init(char *unused1 __attribute__((unused)),
+ size_t unused2 __attribute__((unused)),
+ int unused3 __attribute__((unused)),
+ va_list unused4 __attribute__((unused)))
+{
+ return 0;
+}
+/* }}} */
+
+/* {{{ auth_ed25519_deinit */
+static int auth_ed25519_deinit(void)
+{
+ return 0;
+}
+/* }}} */
+
+#endif /* defined(HAVE_OPENSSL) || defined(HAVE_WINCRYPT) || defined(HAVE_GNUTLS)*/
+
diff --git a/libmariadb/plugins/auth/ed25519_common.h b/libmariadb/plugins/auth/ed25519_common.h
new file mode 100644
index 00000000..b4494f40
--- /dev/null
+++ b/libmariadb/plugins/auth/ed25519_common.h
@@ -0,0 +1,26 @@
+/************************************************************************************
+ Copyright (C) 2017-2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+
+#include <mysql.h>
+#include <string.h>
+
+#include "ref10/api.h"
+#include "ref10/crypto_sign.h"
+
+#define NONCE_BYTES 32
diff --git a/libmariadb/plugins/auth/gssapi_client.c b/libmariadb/plugins/auth/gssapi_client.c
new file mode 100644
index 00000000..b4e3e89d
--- /dev/null
+++ b/libmariadb/plugins/auth/gssapi_client.c
@@ -0,0 +1,131 @@
+/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*/
+
+#if defined(__FreeBSD__) || defined(SOLARIS) || defined(__sun)
+#include <gssapi/gssapi.h>
+#else
+#include <gssapi.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <mysql/plugin_auth.h>
+#include <ma_server_error.h>
+#include <mysql.h>
+#include "gssapi_errmsg.h"
+
+extern void log_client_error(MYSQL *mysql,const char *fmt,...);
+
+
+/* This sends the error to the client */
+static void log_error(MYSQL *mysql, OM_uint32 major, OM_uint32 minor, const char *msg)
+{
+ if (GSS_ERROR(major))
+ {
+ char sysmsg[1024];
+ gssapi_errmsg(major, minor, sysmsg, sizeof(sysmsg));
+ log_client_error(mysql,
+ "Client GSSAPI error (major %u, minor %u) : %s - %s",
+ major, minor, msg, sysmsg);
+ }
+ else
+ {
+ log_client_error(mysql, "Client GSSAPI error : %s", msg);
+ }
+}
+
+int auth_client(char *principal_name, char *mech __attribute__((unused)),
+ MYSQL *mysql, MYSQL_PLUGIN_VIO *vio)
+{
+ gss_buffer_desc input= {0,0};
+ int ret= CR_ERROR;
+ OM_uint32 major= 0, minor= 0;
+ gss_ctx_id_t ctxt= GSS_C_NO_CONTEXT;
+ gss_name_t service_name= GSS_C_NO_NAME;
+
+ if (principal_name && principal_name[0])
+ {
+ /* import principal from plain text */
+ gss_buffer_desc principal_name_buf;
+ principal_name_buf.length= strlen(principal_name);
+ principal_name_buf.value= (void *) principal_name;
+ major= gss_import_name(&minor, &principal_name_buf, GSS_C_NT_USER_NAME, &service_name);
+ if (GSS_ERROR(major))
+ {
+ log_error(mysql, major, minor, "gss_import_name");
+ return CR_ERROR;
+ }
+ }
+
+ do
+ {
+ gss_buffer_desc output= {0,0};
+ major= gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ctxt, service_name,
+ GSS_C_NO_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS,
+ &input, NULL, &output, NULL, NULL);
+ if (output.length)
+ {
+ /* send credential */
+ if(vio->write_packet(vio, (unsigned char *)output.value, output.length))
+ {
+ /* Server error packet contains detailed message. */
+ ret= CR_OK_HANDSHAKE_COMPLETE;
+ gss_release_buffer (&minor, &output);
+ goto cleanup;
+ }
+ }
+ gss_release_buffer (&minor, &output);
+
+ if (GSS_ERROR(major))
+ {
+ log_error(mysql, major, minor,"gss_init_sec_context");
+ goto cleanup;
+ }
+
+ if (major & GSS_S_CONTINUE_NEEDED)
+ {
+ int len= vio->read_packet(vio, (unsigned char **) &input.value);
+ if (len <= 0)
+ {
+ /* Server error packet contains detailed message. */
+ ret= CR_OK_HANDSHAKE_COMPLETE;
+ goto cleanup;
+ }
+ input.length= len;
+ }
+ } while (major & GSS_S_CONTINUE_NEEDED);
+
+ ret= CR_OK;
+
+cleanup:
+ if (service_name != GSS_C_NO_NAME)
+ gss_release_name(&minor, &service_name);
+ if (ctxt != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&minor, &ctxt, GSS_C_NO_BUFFER);
+
+ return ret;
+}
diff --git a/libmariadb/plugins/auth/gssapi_errmsg.c b/libmariadb/plugins/auth/gssapi_errmsg.c
new file mode 100644
index 00000000..eb914404
--- /dev/null
+++ b/libmariadb/plugins/auth/gssapi_errmsg.c
@@ -0,0 +1,79 @@
+/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*/
+
+#if defined(__FreeBSD__) || defined(SOLARIS) || defined(__sun)
+#include <gssapi/gssapi.h>
+#else
+#include <gssapi.h>
+#endif
+#include <string.h>
+void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size)
+{
+ OM_uint32 message_context;
+ OM_uint32 status_code;
+ OM_uint32 maj_status;
+ OM_uint32 min_status;
+ gss_buffer_desc status_string;
+ char *p= buf;
+ char *end= buf + size - 1;
+ int types[] = {GSS_C_GSS_CODE,GSS_C_MECH_CODE};
+ int i;
+ for(i= 0; i < 2;i++)
+ {
+ message_context= 0;
+ status_code= types[i] == GSS_C_GSS_CODE?major:minor;
+
+ if(!status_code)
+ continue;
+ do
+ {
+ maj_status = gss_display_status(
+ &min_status,
+ status_code,
+ types[i],
+ GSS_C_NO_OID,
+ &message_context,
+ &status_string);
+
+ if(maj_status)
+ break;
+
+ if(p + status_string.length + 2 < end)
+ {
+ memcpy(p,status_string.value, status_string.length);
+ p += status_string.length;
+ *p++ = '.';
+ *p++ = ' ';
+ }
+
+ gss_release_buffer(&min_status, &status_string);
+ }
+ while (message_context != 0);
+ }
+ *p= 0;
+}
diff --git a/libmariadb/plugins/auth/gssapi_errmsg.h b/libmariadb/plugins/auth/gssapi_errmsg.h
new file mode 100644
index 00000000..26db8439
--- /dev/null
+++ b/libmariadb/plugins/auth/gssapi_errmsg.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*/
+
+extern void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size);
diff --git a/libmariadb/plugins/auth/mariadb_cleartext.c b/libmariadb/plugins/auth/mariadb_cleartext.c
new file mode 100644
index 00000000..b63c1d3b
--- /dev/null
+++ b/libmariadb/plugins/auth/mariadb_cleartext.c
@@ -0,0 +1,76 @@
+/************************************************************************************
+ Copyright (C) 2014-2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+#include <ma_global.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+
+/* clear text plugin submits the password without opening a dialog.
+ This will be the case if pam-use-cleartext-plugin option is
+ enabled on server side */
+
+/* {{{ auth_send_plain_password() */
+/*
+ sends an unencrypted password to server
+
+ SYNOPSIS
+ auth_send_plain_password()
+ vio pointer to vio structure
+ mysql connection handle
+
+ DESCRIPTION
+ sends an unencrypted password (which was specified either in
+ mysql_real_connect or mysql_change_user) to server.
+
+ RETURN
+ CR_OK
+ CR_ERROR if an error occurred
+*/
+static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ if (!vio || !mysql || !mysql->passwd)
+ return CR_ERROR;
+
+ /* write password including terminating zero character */
+ return vio->write_packet(vio, (const unsigned char *) mysql->passwd, (int)strlen(mysql->passwd) + 1) ?
+ CR_ERROR : CR_OK;
+}
+/* }}} */
+
+#ifndef PLUGIN_DYNAMIC
+struct st_mysql_client_plugin_AUTHENTICATION mysql_clear_password_client_plugin=
+#else
+struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
+#endif
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "mysql_clear_password",
+ "Georg Richter",
+ "MariaDB clear password authentication plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ clear_password_auth_client
+};
+
+
diff --git a/libmariadb/plugins/auth/my_auth.c b/libmariadb/plugins/auth/my_auth.c
new file mode 100644
index 00000000..72773079
--- /dev/null
+++ b/libmariadb/plugins/auth/my_auth.c
@@ -0,0 +1,741 @@
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <errmsg.h>
+#include <string.h>
+#include <ma_common.h>
+#include <mysql/client_plugin.h>
+
+typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
+static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, size_t);
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int dummy_fallback_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql __attribute__((unused)));
+extern void read_user_name(char *name);
+extern char *ma_send_connect_attr(MYSQL *mysql, unsigned char *buffer);
+extern int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length);
+extern unsigned char *mysql_net_store_length(unsigned char *packet, ulonglong length);
+
+typedef struct {
+ int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
+ int (*write_packet)(struct st_plugin_vio *vio, const uchar *pkt, size_t pkt_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+ /* -= end of MYSQL_PLUGIN_VIO =- */
+ MYSQL *mysql;
+ auth_plugin_t *plugin; /**< what plugin we're under */
+ const char *db;
+ struct {
+ uchar *pkt; /**< pointer into NET::buff */
+ uint pkt_len;
+ } cached_server_reply;
+ uint packets_read, packets_written; /**< counters for send/received packets */
+ my_bool mysql_change_user; /**< if it's mysql_change_user() */
+ int last_read_packet_len; /**< the length of the last *read* packet */
+} MCPVIO_EXT;
+/*
+#define compile_time_assert(A) \
+do {\
+ typedef char constraint[(A) ? 1 : -1];\
+} while (0);
+*/
+
+auth_plugin_t mysql_native_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ native_password_plugin_name,
+ "R.J.Silk, Sergei Golubchik",
+ "Native MySQL authentication",
+ {1, 0, 0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ native_password_auth_client
+};
+
+
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ int pkt_len;
+ uchar *pkt;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble_buff;
+ pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memmove(mysql->scramble_buff, pkt, SCRAMBLE_LENGTH);
+ mysql->scramble_buff[SCRAMBLE_LENGTH] = 0;
+ }
+
+ if (mysql && mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH + 1];
+ memset(scrambled, 0, SCRAMBLE_LENGTH + 1);
+ ma_scramble_41((uchar *)scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
+auth_plugin_t dummy_fallback_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "dummy_fallback_auth",
+ "Sergei Golubchik",
+ "Dummy fallback plugin",
+ {1, 0, 0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ dummy_fallback_auth_client
+};
+
+
+static int dummy_fallback_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql __attribute__((unused)))
+{
+ char last_error[MYSQL_ERRMSG_SIZE];
+ unsigned int i, last_errno= ((MCPVIO_EXT *)vio)->mysql->net.last_errno;
+ if (last_errno)
+ {
+ memcpy(last_error, ((MCPVIO_EXT *)vio)->mysql->net.last_error,
+ sizeof(last_error) - 1);
+ last_error[sizeof(last_error) - 1]= 0;
+ }
+
+ /* safety-wise we only do 10 round-trips */
+ for (i=0; i < 10; i++)
+ {
+ uchar *pkt;
+ if (vio->read_packet(vio, &pkt) < 0)
+ break;
+ if (vio->write_packet(vio, 0, 0))
+ break;
+ }
+ if (last_errno)
+ {
+ MYSQL *mysql= ((MCPVIO_EXT *)vio)->mysql;
+ memcpy(mysql->net.last_error, last_error,
+ sizeof(mysql->net.last_error) - 1);
+ mysql->net.last_error[sizeof(mysql->net.last_error) - 1]= 0;
+ }
+ return CR_ERROR;
+}
+
+static int send_change_user_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ char *buff, *end;
+ int res= 1;
+ size_t conn_attr_len= (mysql->options.extension) ?
+ mysql->options.extension->connect_attrs_len : 0;
+
+ buff= malloc(USERNAME_LENGTH+1 + data_len+1 + NAME_LEN+1 + 2 + NAME_LEN+1 + 9 + conn_attr_len);
+
+ end= ma_strmake(buff, mysql->user, USERNAME_LENGTH) + 1;
+
+ if (!data_len)
+ *end++= 0;
+ else
+ {
+ if (mysql->client_flag & CLIENT_SECURE_CONNECTION)
+ {
+ DBUG_ASSERT(data_len <= 255);
+ if (data_len > 255)
+ {
+ my_set_error(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
+ goto error;
+ }
+ *end++= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1);
+ DBUG_ASSERT(data[SCRAMBLE_LENGTH_323] == 0);
+ }
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ end= ma_strmake(end, mpvio->db ? mpvio->db : "", NAME_LEN) + 1;
+
+ if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
+ {
+ int2store(end, (ushort) mysql->charset->nr);
+ end+= 2;
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= ma_strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ end= ma_send_connect_attr(mysql, (unsigned char *)end);
+
+ res= ma_simple_command(mysql, COM_CHANGE_USER,
+ buff, (ulong)(end-buff), 1, NULL);
+
+error:
+ free(buff);
+ return res;
+}
+
+static int send_client_reply_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ NET *net= &mysql->net;
+ char *buff, *end;
+ size_t conn_attr_len= (mysql->options.extension) ?
+ mysql->options.extension->connect_attrs_len : 0;
+
+ /* see end= buff+32 below, fixed size of the packet is 32 bytes */
+ buff= malloc(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9);
+ end= buff;
+
+ mysql->client_flag|= mysql->options.client_flag;
+ mysql->client_flag|= CLIENT_CAPABILITIES;
+
+ if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
+ mysql->client_flag|= CLIENT_MULTI_RESULTS;
+
+#if defined(HAVE_TLS) && !defined(EMBEDDED_LIBRARY)
+ if (mysql->options.ssl_key || mysql->options.ssl_cert ||
+ mysql->options.ssl_ca || mysql->options.ssl_capath ||
+ mysql->options.ssl_cipher || mysql->options.use_ssl ||
+ mysql->options.extension->tls_verify_server_cert)
+ mysql->options.use_ssl= 1;
+ if (mysql->options.use_ssl)
+ mysql->client_flag|= CLIENT_SSL;
+#endif /* HAVE_TLS && !EMBEDDED_LIBRARY*/
+ if (mpvio->db)
+ mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
+ else
+ /* See CONC-490: If no database was specified, we need
+ to unset CLIENT_CONNECT_WITH_DB flag */
+ mysql->client_flag&= ~CLIENT_CONNECT_WITH_DB;
+
+ /* CONC-635: For connections via named pipe or shared memory the server
+ indicates the capability for secure connections (TLS), but
+ doesn't support it. */
+ if ((mysql->server_capabilities & CLIENT_SSL) &&
+ (mysql->net.pvio->type == PVIO_TYPE_NAMEDPIPE ||
+ mysql->net.pvio->type == PVIO_TYPE_SHAREDMEM))
+ {
+ mysql->server_capabilities &= ~(CLIENT_SSL);
+ }
+
+ /* if server doesn't support SSL and verification of server certificate
+ was set to mandatory, we need to return an error */
+ if (mysql->options.use_ssl && !(mysql->server_capabilities & CLIENT_SSL))
+ {
+ if (mysql->options.extension->tls_verify_server_cert ||
+ (mysql->options.extension && (mysql->options.extension->tls_fp ||
+ mysql->options.extension->tls_fp_list)))
+ {
+ my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_SSL_CONNECTION_ERROR),
+ "SSL is required, but the server does not support it");
+ goto error;
+ }
+ }
+
+
+ /* Remove options that server doesn't support */
+ mysql->client_flag= mysql->client_flag &
+ (~(CLIENT_COMPRESS | CLIENT_ZSTD_COMPRESSION | CLIENT_SSL | CLIENT_PROTOCOL_41)
+ | mysql->server_capabilities);
+
+ /* save compress for reconnect */
+ if (mysql->client_flag & CLIENT_COMPRESS)
+ mysql->options.compress= 1;
+
+ if (mysql->options.compress && (mysql->server_capabilities & CLIENT_COMPRESS))
+ {
+ /* For MySQL 8.0 we will use zstd compression */
+ if (mysql->server_capabilities & CLIENT_ZSTD_COMPRESSION)
+ {
+ if ((compression_plugin(net) = (MARIADB_COMPRESSION_PLUGIN *)mysql_client_find_plugin(mysql,
+ _mariadb_compression_algorithm_str(COMPRESSION_ZSTD),
+ MARIADB_CLIENT_COMPRESSION_PLUGIN)))
+ {
+ mysql->client_flag|= CLIENT_ZSTD_COMPRESSION;
+ mysql->client_flag&= ~CLIENT_COMPRESS;
+ }
+ }
+ /* load zlib compression as default */
+ if (!compression_plugin(net))
+ {
+ if ((compression_plugin(net) = (MARIADB_COMPRESSION_PLUGIN *)mysql_client_find_plugin(mysql,
+ _mariadb_compression_algorithm_str(COMPRESSION_ZLIB),
+ MARIADB_CLIENT_COMPRESSION_PLUGIN)))
+ {
+ mysql->client_flag|= CLIENT_COMPRESS;
+ }
+ }
+ }
+
+ if (mysql->client_flag & CLIENT_PROTOCOL_41)
+ {
+ /* 4.1 server and 4.1 client has a 32 byte option flag */
+ if (!(mysql->server_capabilities & CLIENT_MYSQL))
+ mysql->client_flag&= ~CLIENT_MYSQL;
+ int4store(buff,mysql->client_flag);
+ int4store(buff+4, net->max_packet_size);
+ buff[8]= (char) mysql->charset->nr;
+ memset(buff + 9, 0, 32-9);
+ if (!(mysql->server_capabilities & CLIENT_MYSQL))
+ {
+ uint server_extended_cap= mysql->extension->mariadb_server_capabilities;
+ uint client_extended_cap= (uint)(MARIADB_CLIENT_SUPPORTED_FLAGS >> 32);
+ mysql->extension->mariadb_client_flag=
+ server_extended_cap & client_extended_cap;
+ int4store(buff + 28, mysql->extension->mariadb_client_flag);
+ }
+ end= buff+32;
+ }
+ else
+ {
+ int2store(buff, mysql->client_flag);
+ int3store(buff+2, net->max_packet_size);
+ end= buff+5;
+ }
+#ifdef HAVE_TLS
+ if (mysql->options.ssl_key ||
+ mysql->options.ssl_cert ||
+ mysql->options.ssl_ca ||
+ mysql->options.ssl_capath ||
+ mysql->options.ssl_cipher
+#ifdef CRL_IMPLEMENTED
+ || (mysql->options.extension &&
+ (mysql->options.extension->ssl_crl ||
+ mysql->options.extension->ssl_crlpath))
+#endif
+ )
+ mysql->options.use_ssl= 1;
+ if (mysql->options.use_ssl &&
+ (mysql->client_flag & CLIENT_SSL))
+ {
+ /*
+ Send mysql->client_flag, max_packet_size - unencrypted otherwise
+ the server does not know we want to do SSL
+ */
+ if (ma_net_write(net, (unsigned char *)buff, (size_t) (end-buff)) || ma_net_flush(net))
+ {
+ my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending connection information to server",
+ errno);
+ goto error;
+ }
+ if (ma_pvio_start_ssl(mysql->net.pvio))
+ goto error;
+ }
+#endif /* HAVE_TLS */
+
+ /* This needs to be changed as it's not useful with big packets */
+ if (mysql->user && mysql->user[0])
+ ma_strmake(end, mysql->user, USERNAME_LENGTH);
+ else
+ read_user_name(end);
+
+ /* We have to handle different version of handshake here */
+ end+= strlen(end) + 1;
+ if (data_len)
+ {
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA)
+ {
+ end= (char *)mysql_net_store_length((uchar *)end, data_len);
+ }
+ else {
+ /* Without CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA capability password
+ length is limited up to 255 chars */
+ if (data_len > 0xFF)
+ goto error;
+ *end++= data_len;
+ }
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ }
+ else
+ *end++= 0;
+
+ /* Add database if needed */
+ if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
+ {
+ end= ma_strmake(end, mpvio->db, NAME_LEN) + 1;
+ mysql->db= strdup(mpvio->db);
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= ma_strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ end= ma_send_connect_attr(mysql, (unsigned char *)end);
+
+ /* MySQL 8.0:
+ If zstd compresson was specified, the server expects
+ 1 byte for compression level
+ */
+ if (mysql->client_flag & CLIENT_ZSTD_COMPRESSION)
+ {
+ int4store(end, (unsigned int)3);
+ end+= 4;
+ }
+
+ /* Write authentication package */
+ if (ma_net_write(net, (unsigned char *)buff, (size_t) (end-buff)) || ma_net_flush(net))
+ {
+ my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ goto error;
+ }
+ free(buff);
+ return 0;
+
+error:
+ free(buff);
+ return 1;
+}
+
+/**
+ vio->read_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to read data from the server.
+*/
+
+static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+ MYSQL *mysql= mpvio->mysql;
+ ulong pkt_len;
+
+ /* there are cached data left, feed it to a plugin */
+ if (mpvio->cached_server_reply.pkt)
+ {
+ *buf= mpvio->cached_server_reply.pkt;
+ mpvio->cached_server_reply.pkt= 0;
+ mpvio->packets_read++;
+ return mpvio->cached_server_reply.pkt_len;
+ }
+
+ if (mpvio->packets_read == 0)
+ {
+ /*
+ the server handshake packet came from the wrong plugin,
+ or it's mysql_change_user(). Either way, there is no data
+ for a plugin to read. send a dummy packet to the server
+ to initiate a dialog.
+ */
+ if (client_mpvio_write_packet(mpv, 0, 0))
+ return (int)packet_error;
+ }
+
+ /* otherwise read the data */
+ if ((pkt_len= ma_net_safe_read(mysql)) == packet_error)
+ return (int)packet_error;
+
+ mpvio->last_read_packet_len= pkt_len;
+ *buf= mysql->net.read_pos;
+
+ /* was it a request to change plugins ? */
+ if (pkt_len && **buf == 254)
+ return (int)packet_error; /* if yes, this plugin shan't continue */
+
+ /*
+ the server sends \1\255 or \1\254 instead of just \255 or \254 -
+ for us to not confuse it with an error or "change plugin" packets.
+ We remove this escaping \1 here.
+
+ See also server_mpvio_write_packet() where the escaping is done.
+ */
+ if (pkt_len && **buf == 1)
+ {
+ (*buf)++;
+ pkt_len--;
+ }
+ mpvio->packets_read++;
+ return pkt_len;
+}
+
+/**
+ vio->write_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to send data to the server.
+
+ It transparently wraps the data into a change user or authentication
+ handshake packet, if necessary.
+*/
+
+static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
+ const uchar *pkt, size_t pkt_len)
+{
+ int res;
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+
+ if (mpvio->packets_written == 0)
+ {
+ if (mpvio->mysql_change_user)
+ res= send_change_user_packet(mpvio, pkt, (int)pkt_len);
+ else
+ res= send_client_reply_packet(mpvio, pkt, (int)pkt_len);
+ }
+ else
+ {
+ NET *net= &mpvio->mysql->net;
+ if (mpvio->mysql->thd)
+ res= 1; /* no chit-chat in embedded */
+ else
+ res= ma_net_write(net, (unsigned char *)pkt, pkt_len) || ma_net_flush(net);
+ }
+
+ if (res)
+ {
+ /* don't overwrite errors */
+ if (!mysql_errno(mpvio->mysql))
+ my_set_error(mpvio->mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ }
+ mpvio->packets_written++;
+ return res;
+}
+
+/**
+ fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
+ connection
+*/
+
+void mpvio_info(MARIADB_PVIO *pvio, MYSQL_PLUGIN_VIO_INFO *info)
+{
+ memset(info, 0, sizeof(*info));
+ switch (pvio->type) {
+ case PVIO_TYPE_SOCKET:
+ info->protocol= MYSQL_VIO_TCP;
+ ma_pvio_get_handle(pvio, &info->socket);
+ return;
+ case PVIO_TYPE_UNIXSOCKET:
+ info->protocol= MYSQL_VIO_SOCKET;
+ ma_pvio_get_handle(pvio, &info->socket);
+ return;
+ /*
+ case VIO_TYPE_SSL:
+ {
+ struct sockaddr addr;
+ SOCKET_SIZE_TYPE addrlen= sizeof(addr);
+ if (getsockname(vio->sd, &addr, &addrlen))
+ return;
+ info->protocol= addr.sa_family == AF_UNIX ?
+ MYSQL_VIO_SOCKET : MYSQL_VIO_TCP;
+ info->socket= vio->sd;
+ return;
+ }
+ */
+#ifdef _WIN32
+ /*
+ case VIO_TYPE_NAMEDPIPE:
+ info->protocol= MYSQL_VIO_PIPE;
+ info->handle= vio->hPipe;
+ return;
+ */
+/* not supported yet
+ case VIO_TYPE_SHARED_MEMORY:
+ info->protocol= MYSQL_VIO_MEMORY;
+ info->handle= vio->handle_file_map;
+ return;
+*/
+#endif
+ default: DBUG_ASSERT(0);
+ }
+}
+
+static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_PLUGIN_VIO_INFO *info)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)vio;
+ mpvio_info(mpvio->mysql->net.pvio, info);
+}
+
+/**
+ Client side of the plugin driver authentication.
+
+ @note this is used by both the mysql_real_connect and mysql_change_user
+
+ @param mysql mysql
+ @param data pointer to the plugin auth data (scramble) in the
+ handshake packet
+ @param data_len the length of the data
+ @param data_plugin a plugin that data were prepared for
+ or 0 if it's mysql_change_user()
+ @param db initial db to use, can be 0
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ const char *data_plugin, const char *db)
+{
+ const char *auth_plugin_name= NULL;
+ auth_plugin_t *auth_plugin;
+ MCPVIO_EXT mpvio;
+ ulong pkt_length;
+ int res;
+
+
+ /* determine the default/initial plugin to use */
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ if (mysql->options.extension && mysql->options.extension->default_auth)
+ auth_plugin_name= mysql->options.extension->default_auth;
+ else if (data_plugin)
+ auth_plugin_name= data_plugin;
+ }
+ if (!auth_plugin_name)
+ {
+ if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
+ auth_plugin_name= native_password_plugin_name;
+ else
+ auth_plugin_name= "mysql_old_password";
+ }
+ if (!(auth_plugin= (auth_plugin_t*) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ auth_plugin= &dummy_fallback_client_plugin;
+
+ mysql->net.last_errno= 0; /* just in case */
+
+ if (data_plugin && strcmp(data_plugin, auth_plugin_name))
+ {
+ /* data was prepared for a different plugin, so we don't
+ send any data */
+ data= 0;
+ data_len= 0;
+ }
+
+ mpvio.mysql_change_user= data_plugin == 0;
+ mpvio.cached_server_reply.pkt= (uchar*)data;
+ mpvio.cached_server_reply.pkt_len= data_len;
+ mpvio.read_packet= client_mpvio_read_packet;
+ mpvio.write_packet= client_mpvio_write_packet;
+ mpvio.info= client_mpvio_info;
+ mpvio.mysql= mysql;
+ mpvio.packets_read= mpvio.packets_written= 0;
+ mpvio.db= db;
+
+retry:
+ mpvio.plugin= auth_plugin;
+
+ if (auth_plugin_name &&
+ mysql->options.extension &&
+ mysql->options.extension->restricted_auth)
+ {
+ if (!strstr(mysql->options.extension->restricted_auth, auth_plugin_name))
+ {
+ my_set_error(mysql, CR_PLUGIN_NOT_ALLOWED, SQLSTATE_UNKNOWN, 0, data_plugin);
+ return 1;
+ }
+ }
+
+ mysql->net.read_pos[0]= 0;
+ res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+
+ if ((res == CR_ERROR && !mysql->net.buff) ||
+ (res > CR_OK && mysql->net.read_pos[0] != 254))
+ {
+ /*
+ the plugin returned an error. write it down in mysql,
+ unless the error code is CR_ERROR and mysql->net.last_errno
+ is already set (the plugin has done it)
+ */
+ if (res > CR_ERROR)
+ my_set_error(mysql, res, SQLSTATE_UNKNOWN, 0);
+ else
+ if (!mysql->net.last_errno) {
+ my_set_error(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
+ }
+ return 1;
+ }
+
+ /* read the OK packet (or use the cached value in mysql->net.read_pos */
+ if (res == CR_OK)
+ pkt_length= ma_net_safe_read(mysql);
+ else /* res == CR_OK_HANDSHAKE_COMPLETE or an error */
+ pkt_length= mpvio.last_read_packet_len;
+
+ if (pkt_length == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading authorization packet",
+ errno);
+ return 1;
+ }
+ if (mysql->net.read_pos[0] == 254)
+ {
+ /* The server asked to use a different authentication plugin */
+ if (pkt_length == 1)
+ {
+ /* old "use short scramble" packet */
+ auth_plugin_name= old_password_plugin_name;
+ mpvio.cached_server_reply.pkt= (uchar*)mysql->scramble_buff;
+ mpvio.cached_server_reply.pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* new "use different plugin" packet */
+ uint len;
+ auth_plugin_name= (char*)mysql->net.read_pos + 1;
+ len= (uint)strlen(auth_plugin_name); /* safe as ma_net_read always appends \0 */
+ mpvio.cached_server_reply.pkt_len= pkt_length - len - 2;
+ mpvio.cached_server_reply.pkt= mysql->net.read_pos + len + 2;
+ }
+ if (!(auth_plugin= (auth_plugin_t *) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ auth_plugin= &dummy_fallback_client_plugin;
+
+ goto retry;
+
+ }
+ /*
+ net->read_pos[0] should always be 0 here if the server implements
+ the protocol correctly
+ */
+ if (mysql->net.read_pos[0] == 0)
+ return ma_read_ok_packet(mysql, mysql->net.read_pos + 1, pkt_length);
+ return 1;
+}
+
diff --git a/libmariadb/plugins/auth/old_password.c b/libmariadb/plugins/auth/old_password.c
new file mode 100644
index 00000000..07756e92
--- /dev/null
+++ b/libmariadb/plugins/auth/old_password.c
@@ -0,0 +1,117 @@
+/************************************************************************************
+ Copyright (C) 2014,2015,2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+#include <ma_global.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+#include <errmsg.h>
+
+
+/* function prototypes */
+static int auth_old_password(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+
+typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
+
+typedef struct {
+ int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
+ int (*write_packet)(struct st_plugin_vio *vio, const uchar *pkt, size_t pkt_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+ /* -= end of MYSQL_PLUGIN_VIO =- */
+ MYSQL *mysql;
+ auth_plugin_t *plugin; /**< what plugin we're under */
+ const char *db;
+ struct {
+ uchar *pkt; /**< pointer into NET::buff */
+ uint pkt_len;
+ } cached_server_reply;
+ uint packets_read, packets_written; /**< counters for send/received packets */
+ my_bool mysql_change_user; /**< if it's mysql_change_user() */
+ int last_read_packet_len; /**< the length of the last *read* packet */
+} MCPVIO_EXT;
+
+#ifndef PLUGIN_DYNAMIC
+struct st_mysql_client_plugin_AUTHENTICATION mysql_old_password_client_plugin=
+#else
+struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
+#endif
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "mysql_old_password",
+ "Sergei Golubchik, R.J. Silk, Georg Richter",
+ "Old (pre 4.1) authentication plugin",
+ {1,0,0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ auth_old_password
+};
+
+/**
+ client authentication plugin that does old MySQL authentication
+ using an 8-byte (4.0-) scramble
+*/
+
+static int auth_old_password(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ uchar *pkt;
+ int pkt_len;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble_buff;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH_323 + 1 &&
+ pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memmove(mysql->scramble_buff, pkt, pkt_len - 1);
+ mysql->scramble_buff[pkt_len - 1] = 0;
+ }
+
+ if (mysql && mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH_323 + 1];
+ ma_scramble_323(scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH_323 + 1))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
+
+
diff --git a/libmariadb/plugins/auth/ref10/api.h b/libmariadb/plugins/auth/ref10/api.h
new file mode 100644
index 00000000..9f1db7e5
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/api.h
@@ -0,0 +1,3 @@
+#define CRYPTO_PUBLICKEYBYTES 32
+#define CRYPTO_BYTES 64
+#define CRYPTO_DETERMINISTIC 1
diff --git a/libmariadb/plugins/auth/ref10/base.h b/libmariadb/plugins/auth/ref10/base.h
new file mode 100644
index 00000000..573bd8a0
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/base.h
@@ -0,0 +1,1344 @@
+{
+ {
+ { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
+ { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
+ { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
+ },
+ {
+ { -12815894,-12976347,-21581243,11784320,-25355658,-2750717,-11717903,-3814571,-358445,-10211303 },
+ { -21703237,6903825,27185491,6451973,-29577724,-9554005,-15616551,11189268,-26829678,-5319081 },
+ { 26966642,11152617,32442495,15396054,14353839,-12752335,-3128826,-9541118,-15472047,-4166697 },
+ },
+ {
+ { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
+ { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
+ { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
+ },
+ {
+ { -17036878,13921892,10945806,-6033431,27105052,-16084379,-28926210,15006023,3284568,-6276540 },
+ { 23599295,-8306047,-11193664,-7687416,13236774,10506355,7464579,9656445,13059162,10374397 },
+ { 7798556,16710257,3033922,2874086,28997861,2835604,32406664,-3839045,-641708,-101325 },
+ },
+ {
+ { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
+ { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
+ { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
+ },
+ {
+ { -15371964,-12862754,32573250,4720197,-26436522,5875511,-19188627,-15224819,-9818940,-12085777 },
+ { -8549212,109983,15149363,2178705,22900618,4543417,3044240,-15689887,1762328,14866737 },
+ { -18199695,-15951423,-10473290,1707278,-17185920,3916101,-28236412,3959421,27914454,4383652 },
+ },
+ {
+ { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
+ { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
+ { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
+ },
+ {
+ { 14499471,-2729599,-33191113,-4254652,28494862,14271267,30290735,10876454,-33154098,2381726 },
+ { -7195431,-2655363,-14730155,462251,-27724326,3941372,-6236617,3696005,-32300832,15351955 },
+ { 27431194,8222322,16448760,-3907995,-18707002,11938355,-32961401,-2970515,29551813,10109425 },
+ },
+},
+{
+ {
+ { -13657040,-13155431,-31283750,11777098,21447386,6519384,-2378284,-1627556,10092783,-4764171 },
+ { 27939166,14210322,4677035,16277044,-22964462,-12398139,-32508754,12005538,-17810127,12803510 },
+ { 17228999,-15661624,-1233527,300140,-1224870,-11714777,30364213,-9038194,18016357,4397660 },
+ },
+ {
+ { -10958843,-7690207,4776341,-14954238,27850028,-15602212,-26619106,14544525,-17477504,982639 },
+ { 29253598,15796703,-2863982,-9908884,10057023,3163536,7332899,-4120128,-21047696,9934963 },
+ { 5793303,16271923,-24131614,-10116404,29188560,1206517,-14747930,4559895,-30123922,-10897950 },
+ },
+ {
+ { -27643952,-11493006,16282657,-11036493,28414021,-15012264,24191034,4541697,-13338309,5500568 },
+ { 12650548,-1497113,9052871,11355358,-17680037,-8400164,-17430592,12264343,10874051,13524335 },
+ { 25556948,-3045990,714651,2510400,23394682,-10415330,33119038,5080568,-22528059,5376628 },
+ },
+ {
+ { -26088264,-4011052,-17013699,-3537628,-6726793,1920897,-22321305,-9447443,4535768,1569007 },
+ { -2255422,14606630,-21692440,-8039818,28430649,8775819,-30494562,3044290,31848280,12543772 },
+ { -22028579,2943893,-31857513,6777306,13784462,-4292203,-27377195,-2062731,7718482,14474653 },
+ },
+ {
+ { 2385315,2454213,-22631320,46603,-4437935,-15680415,656965,-7236665,24316168,-5253567 },
+ { 13741529,10911568,-33233417,-8603737,-20177830,-1033297,33040651,-13424532,-20729456,8321686 },
+ { 21060490,-2212744,15712757,-4336099,1639040,10656336,23845965,-11874838,-9984458,608372 },
+ },
+ {
+ { -13672732,-15087586,-10889693,-7557059,-6036909,11305547,1123968,-6780577,27229399,23887 },
+ { -23244140,-294205,-11744728,14712571,-29465699,-2029617,12797024,-6440308,-1633405,16678954 },
+ { -29500620,4770662,-16054387,14001338,7830047,9564805,-1508144,-4795045,-17169265,4904953 },
+ },
+ {
+ { 24059557,14617003,19037157,-15039908,19766093,-14906429,5169211,16191880,2128236,-4326833 },
+ { -16981152,4124966,-8540610,-10653797,30336522,-14105247,-29806336,916033,-6882542,-2986532 },
+ { -22630907,12419372,-7134229,-7473371,-16478904,16739175,285431,2763829,15736322,4143876 },
+ },
+ {
+ { 2379352,11839345,-4110402,-5988665,11274298,794957,212801,-14594663,23527084,-16458268 },
+ { 33431127,-11130478,-17838966,-15626900,8909499,8376530,-32625340,4087881,-15188911,-14416214 },
+ { 1767683,7197987,-13205226,-2022635,-13091350,448826,5799055,4357868,-4774191,-16323038 },
+ },
+},
+{
+ {
+ { 6721966,13833823,-23523388,-1551314,26354293,-11863321,23365147,-3949732,7390890,2759800 },
+ { 4409041,2052381,23373853,10530217,7676779,-12885954,21302353,-4264057,1244380,-12919645 },
+ { -4421239,7169619,4982368,-2957590,30256825,-2777540,14086413,9208236,15886429,16489664 },
+ },
+ {
+ { 1996075,10375649,14346367,13311202,-6874135,-16438411,-13693198,398369,-30606455,-712933 },
+ { -25307465,9795880,-2777414,14878809,-33531835,14780363,13348553,12076947,-30836462,5113182 },
+ { -17770784,11797796,31950843,13929123,-25888302,12288344,-30341101,-7336386,13847711,5387222 },
+ },
+ {
+ { -18582163,-3416217,17824843,-2340966,22744343,-10442611,8763061,3617786,-19600662,10370991 },
+ { 20246567,-14369378,22358229,-543712,18507283,-10413996,14554437,-8746092,32232924,16763880 },
+ { 9648505,10094563,26416693,14745928,-30374318,-6472621,11094161,15689506,3140038,-16510092 },
+ },
+ {
+ { -16160072,5472695,31895588,4744994,8823515,10365685,-27224800,9448613,-28774454,366295 },
+ { 19153450,11523972,-11096490,-6503142,-24647631,5420647,28344573,8041113,719605,11671788 },
+ { 8678025,2694440,-6808014,2517372,4964326,11152271,-15432916,-15266516,27000813,-10195553 },
+ },
+ {
+ { -15157904,7134312,8639287,-2814877,-7235688,10421742,564065,5336097,6750977,-14521026 },
+ { 11836410,-3979488,26297894,16080799,23455045,15735944,1695823,-8819122,8169720,16220347 },
+ { -18115838,8653647,17578566,-6092619,-8025777,-16012763,-11144307,-2627664,-5990708,-14166033 },
+ },
+ {
+ { -23308498,-10968312,15213228,-10081214,-30853605,-11050004,27884329,2847284,2655861,1738395 },
+ { -27537433,-14253021,-25336301,-8002780,-9370762,8129821,21651608,-3239336,-19087449,-11005278 },
+ { 1533110,3437855,23735889,459276,29970501,11335377,26030092,5821408,10478196,8544890 },
+ },
+ {
+ { 32173121,-16129311,24896207,3921497,22579056,-3410854,19270449,12217473,17789017,-3395995 },
+ { -30552961,-2228401,-15578829,-10147201,13243889,517024,15479401,-3853233,30460520,1052596 },
+ { -11614875,13323618,32618793,8175907,-15230173,12596687,27491595,-4612359,3179268,-9478891 },
+ },
+ {
+ { 31947069,-14366651,-4640583,-15339921,-15125977,-6039709,-14756777,-16411740,19072640,-9511060 },
+ { 11685058,11822410,3158003,-13952594,33402194,-4165066,5977896,-5215017,473099,5040608 },
+ { -20290863,8198642,-27410132,11602123,1290375,-2799760,28326862,1721092,-19558642,-3131606 },
+ },
+},
+{
+ {
+ { 7881532,10687937,7578723,7738378,-18951012,-2553952,21820786,8076149,-27868496,11538389 },
+ { -19935666,3899861,18283497,-6801568,-15728660,-11249211,8754525,7446702,-5676054,5797016 },
+ { -11295600,-3793569,-15782110,-7964573,12708869,-8456199,2014099,-9050574,-2369172,-5877341 },
+ },
+ {
+ { -22472376,-11568741,-27682020,1146375,18956691,16640559,1192730,-3714199,15123619,10811505 },
+ { 14352098,-3419715,-18942044,10822655,32750596,4699007,-70363,15776356,-28886779,-11974553 },
+ { -28241164,-8072475,-4978962,-5315317,29416931,1847569,-20654173,-16484855,4714547,-9600655 },
+ },
+ {
+ { 15200332,8368572,19679101,15970074,-31872674,1959451,24611599,-4543832,-11745876,12340220 },
+ { 12876937,-10480056,33134381,6590940,-6307776,14872440,9613953,8241152,15370987,9608631 },
+ { -4143277,-12014408,8446281,-391603,4407738,13629032,-7724868,15866074,-28210621,-8814099 },
+ },
+ {
+ { 26660628,-15677655,8393734,358047,-7401291,992988,-23904233,858697,20571223,8420556 },
+ { 14620715,13067227,-15447274,8264467,14106269,15080814,33531827,12516406,-21574435,-12476749 },
+ { 236881,10476226,57258,-14677024,6472998,2466984,17258519,7256740,8791136,15069930 },
+ },
+ {
+ { 1276410,-9371918,22949635,-16322807,-23493039,-5702186,14711875,4874229,-30663140,-2331391 },
+ { 5855666,4990204,-13711848,7294284,-7804282,1924647,-1423175,-7912378,-33069337,9234253 },
+ { 20590503,-9018988,31529744,-7352666,-2706834,10650548,31559055,-11609587,18979186,13396066 },
+ },
+ {
+ { 24474287,4968103,22267082,4407354,24063882,-8325180,-18816887,13594782,33514650,7021958 },
+ { -11566906,-6565505,-21365085,15928892,-26158305,4315421,-25948728,-3916677,-21480480,12868082 },
+ { -28635013,13504661,19988037,-2132761,21078225,6443208,-21446107,2244500,-12455797,-8089383 },
+ },
+ {
+ { -30595528,13793479,-5852820,319136,-25723172,-6263899,33086546,8957937,-15233648,5540521 },
+ { -11630176,-11503902,-8119500,-7643073,2620056,1022908,-23710744,-1568984,-16128528,-14962807 },
+ { 23152971,775386,27395463,14006635,-9701118,4649512,1689819,892185,-11513277,-15205948 },
+ },
+ {
+ { 9770129,9586738,26496094,4324120,1556511,-3550024,27453819,4763127,-19179614,5867134 },
+ { -32765025,1927590,31726409,-4753295,23962434,-16019500,27846559,5931263,-29749703,-16108455 },
+ { 27461885,-2977536,22380810,1815854,-23033753,-3031938,7283490,-15148073,-19526700,7734629 },
+ },
+},
+{
+ {
+ { -8010264,-9590817,-11120403,6196038,29344158,-13430885,7585295,-3176626,18549497,15302069 },
+ { -32658337,-6171222,-7672793,-11051681,6258878,13504381,10458790,-6418461,-8872242,8424746 },
+ { 24687205,8613276,-30667046,-3233545,1863892,-1830544,19206234,7134917,-11284482,-828919 },
+ },
+ {
+ { 11334899,-9218022,8025293,12707519,17523892,-10476071,10243738,-14685461,-5066034,16498837 },
+ { 8911542,6887158,-9584260,-6958590,11145641,-9543680,17303925,-14124238,6536641,10543906 },
+ { -28946384,15479763,-17466835,568876,-1497683,11223454,-2669190,-16625574,-27235709,8876771 },
+ },
+ {
+ { -25742899,-12566864,-15649966,-846607,-33026686,-796288,-33481822,15824474,-604426,-9039817 },
+ { 10330056,70051,7957388,-9002667,9764902,15609756,27698697,-4890037,1657394,3084098 },
+ { 10477963,-7470260,12119566,-13250805,29016247,-5365589,31280319,14396151,-30233575,15272409 },
+ },
+ {
+ { -12288309,3169463,28813183,16658753,25116432,-5630466,-25173957,-12636138,-25014757,1950504 },
+ { -26180358,9489187,11053416,-14746161,-31053720,5825630,-8384306,-8767532,15341279,8373727 },
+ { 28685821,7759505,-14378516,-12002860,-31971820,4079242,298136,-10232602,-2878207,15190420 },
+ },
+ {
+ { -32932876,13806336,-14337485,-15794431,-24004620,10940928,8669718,2742393,-26033313,-6875003 },
+ { -1580388,-11729417,-25979658,-11445023,-17411874,-10912854,9291594,-16247779,-12154742,6048605 },
+ { -30305315,14843444,1539301,11864366,20201677,1900163,13934231,5128323,11213262,9168384 },
+ },
+ {
+ { -26280513,11007847,19408960,-940758,-18592965,-4328580,-5088060,-11105150,20470157,-16398701 },
+ { -23136053,9282192,14855179,-15390078,-7362815,-14408560,-22783952,14461608,14042978,5230683 },
+ { 29969567,-2741594,-16711867,-8552442,9175486,-2468974,21556951,3506042,-5933891,-12449708 },
+ },
+ {
+ { -3144746,8744661,19704003,4581278,-20430686,6830683,-21284170,8971513,-28539189,15326563 },
+ { -19464629,10110288,-17262528,-3503892,-23500387,1355669,-15523050,15300988,-20514118,9168260 },
+ { -5353335,4488613,-23803248,16314347,7780487,-15638939,-28948358,9601605,33087103,-9011387 },
+ },
+ {
+ { -19443170,-15512900,-20797467,-12445323,-29824447,10229461,-27444329,-15000531,-5996870,15664672 },
+ { 23294591,-16632613,-22650781,-8470978,27844204,11461195,13099750,-2460356,18151676,13417686 },
+ { -24722913,-4176517,-31150679,5988919,-26858785,6685065,1661597,-12551441,15271676,-15452665 },
+ },
+},
+{
+ {
+ { 11433042,-13228665,8239631,-5279517,-1985436,-725718,-18698764,2167544,-6921301,-13440182 },
+ { -31436171,15575146,30436815,12192228,-22463353,9395379,-9917708,-8638997,12215110,12028277 },
+ { 14098400,6555944,23007258,5757252,-15427832,-12950502,30123440,4617780,-16900089,-655628 },
+ },
+ {
+ { -4026201,-15240835,11893168,13718664,-14809462,1847385,-15819999,10154009,23973261,-12684474 },
+ { -26531820,-3695990,-1908898,2534301,-31870557,-16550355,18341390,-11419951,32013174,-10103539 },
+ { -25479301,10876443,-11771086,-14625140,-12369567,1838104,21911214,6354752,4425632,-837822 },
+ },
+ {
+ { -10433389,-14612966,22229858,-3091047,-13191166,776729,-17415375,-12020462,4725005,14044970 },
+ { 19268650,-7304421,1555349,8692754,-21474059,-9910664,6347390,-1411784,-19522291,-16109756 },
+ { -24864089,12986008,-10898878,-5558584,-11312371,-148526,19541418,8180106,9282262,10282508 },
+ },
+ {
+ { -26205082,4428547,-8661196,-13194263,4098402,-14165257,15522535,8372215,5542595,-10702683 },
+ { -10562541,14895633,26814552,-16673850,-17480754,-2489360,-2781891,6993761,-18093885,10114655 },
+ { -20107055,-929418,31422704,10427861,-7110749,6150669,-29091755,-11529146,25953725,-106158 },
+ },
+ {
+ { -4234397,-8039292,-9119125,3046000,2101609,-12607294,19390020,6094296,-3315279,12831125 },
+ { -15998678,7578152,5310217,14408357,-33548620,-224739,31575954,6326196,7381791,-2421839 },
+ { -20902779,3296811,24736065,-16328389,18374254,7318640,6295303,8082724,-15362489,12339664 },
+ },
+ {
+ { 27724736,2291157,6088201,-14184798,1792727,5857634,13848414,15768922,25091167,14856294 },
+ { -18866652,8331043,24373479,8541013,-701998,-9269457,12927300,-12695493,-22182473,-9012899 },
+ { -11423429,-5421590,11632845,3405020,30536730,-11674039,-27260765,13866390,30146206,9142070 },
+ },
+ {
+ { 3924129,-15307516,-13817122,-10054960,12291820,-668366,-27702774,9326384,-8237858,4171294 },
+ { -15921940,16037937,6713787,16606682,-21612135,2790944,26396185,3731949,345228,-5462949 },
+ { -21327538,13448259,25284571,1143661,20614966,-8849387,2031539,-12391231,-16253183,-13582083 },
+ },
+ {
+ { 31016211,-16722429,26371392,-14451233,-5027349,14854137,17477601,3842657,28012650,-16405420 },
+ { -5075835,9368966,-8562079,-4600902,-15249953,6970560,-9189873,16292057,-8867157,3507940 },
+ { 29439664,3537914,23333589,6997794,-17555561,-11018068,-15209202,-15051267,-9164929,6580396 },
+ },
+},
+{
+ {
+ { -12185861,-7679788,16438269,10826160,-8696817,-6235611,17860444,-9273846,-2095802,9304567 },
+ { 20714564,-4336911,29088195,7406487,11426967,-5095705,14792667,-14608617,5289421,-477127 },
+ { -16665533,-10650790,-6160345,-13305760,9192020,-1802462,17271490,12349094,26939669,-3752294 },
+ },
+ {
+ { -12889898,9373458,31595848,16374215,21471720,13221525,-27283495,-12348559,-3698806,117887 },
+ { 22263325,-6560050,3984570,-11174646,-15114008,-566785,28311253,5358056,-23319780,541964 },
+ { 16259219,3261970,2309254,-15534474,-16885711,-4581916,24134070,-16705829,-13337066,-13552195 },
+ },
+ {
+ { 9378160,-13140186,-22845982,-12745264,28198281,-7244098,-2399684,-717351,690426,14876244 },
+ { 24977353,-314384,-8223969,-13465086,28432343,-1176353,-13068804,-12297348,-22380984,6618999 },
+ { -1538174,11685646,12944378,13682314,-24389511,-14413193,8044829,-13817328,32239829,-5652762 },
+ },
+ {
+ { -18603066,4762990,-926250,8885304,-28412480,-3187315,9781647,-10350059,32779359,5095274 },
+ { -33008130,-5214506,-32264887,-3685216,9460461,-9327423,-24601656,14506724,21639561,-2630236 },
+ { -16400943,-13112215,25239338,15531969,3987758,-4499318,-1289502,-6863535,17874574,558605 },
+ },
+ {
+ { -13600129,10240081,9171883,16131053,-20869254,9599700,33499487,5080151,2085892,5119761 },
+ { -22205145,-2519528,-16381601,414691,-25019550,2170430,30634760,-8363614,-31999993,-5759884 },
+ { -6845704,15791202,8550074,-1312654,29928809,-12092256,27534430,-7192145,-22351378,12961482 },
+ },
+ {
+ { -24492060,-9570771,10368194,11582341,-23397293,-2245287,16533930,8206996,-30194652,-5159638 },
+ { -11121496,-3382234,2307366,6362031,-135455,8868177,-16835630,7031275,7589640,8945490 },
+ { -32152748,8917967,6661220,-11677616,-1192060,-15793393,7251489,-11182180,24099109,-14456170 },
+ },
+ {
+ { 5019558,-7907470,4244127,-14714356,-26933272,6453165,-19118182,-13289025,-6231896,-10280736 },
+ { 10853594,10721687,26480089,5861829,-22995819,1972175,-1866647,-10557898,-3363451,-6441124 },
+ { -17002408,5906790,221599,-6563147,7828208,-13248918,24362661,-2008168,-13866408,7421392 },
+ },
+ {
+ { 8139927,-6546497,32257646,-5890546,30375719,1886181,-21175108,15441252,28826358,-4123029 },
+ { 6267086,9695052,7709135,-16603597,-32869068,-1886135,14795160,-7840124,13746021,-1742048 },
+ { 28584902,7787108,-6732942,-15050729,22846041,-7571236,-3181936,-363524,4771362,-8419958 },
+ },
+},
+{
+ {
+ { 24949256,6376279,-27466481,-8174608,-18646154,-9930606,33543569,-12141695,3569627,11342593 },
+ { 26514989,4740088,27912651,3697550,19331575,-11472339,6809886,4608608,7325975,-14801071 },
+ { -11618399,-14554430,-24321212,7655128,-1369274,5214312,-27400540,10258390,-17646694,-8186692 },
+ },
+ {
+ { 11431204,15823007,26570245,14329124,18029990,4796082,-31446179,15580664,9280358,-3973687 },
+ { -160783,-10326257,-22855316,-4304997,-20861367,-13621002,-32810901,-11181622,-15545091,4387441 },
+ { -20799378,12194512,3937617,-5805892,-27154820,9340370,-24513992,8548137,20617071,-7482001 },
+ },
+ {
+ { -938825,-3930586,-8714311,16124718,24603125,-6225393,-13775352,-11875822,24345683,10325460 },
+ { -19855277,-1568885,-22202708,8714034,14007766,6928528,16318175,-1010689,4766743,3552007 },
+ { -21751364,-16730916,1351763,-803421,-4009670,3950935,3217514,14481909,10988822,-3994762 },
+ },
+ {
+ { 15564307,-14311570,3101243,5684148,30446780,-8051356,12677127,-6505343,-8295852,13296005 },
+ { -9442290,6624296,-30298964,-11913677,-4670981,-2057379,31521204,9614054,-30000824,12074674 },
+ { 4771191,-135239,14290749,-13089852,27992298,14998318,-1413936,-1556716,29832613,-16391035 },
+ },
+ {
+ { 7064884,-7541174,-19161962,-5067537,-18891269,-2912736,25825242,5293297,-27122660,13101590 },
+ { -2298563,2439670,-7466610,1719965,-27267541,-16328445,32512469,-5317593,-30356070,-4190957 },
+ { -30006540,10162316,-33180176,3981723,-16482138,-13070044,14413974,9515896,19568978,9628812 },
+ },
+ {
+ { 33053803,199357,15894591,1583059,27380243,-4580435,-17838894,-6106839,-6291786,3437740 },
+ { -18978877,3884493,19469877,12726490,15913552,13614290,-22961733,70104,7463304,4176122 },
+ { -27124001,10659917,11482427,-16070381,12771467,-6635117,-32719404,-5322751,24216882,5944158 },
+ },
+ {
+ { 8894125,7450974,-2664149,-9765752,-28080517,-12389115,19345746,14680796,11632993,5847885 },
+ { 26942781,-2315317,9129564,-4906607,26024105,11769399,-11518837,6367194,-9727230,4782140 },
+ { 19916461,-4828410,-22910704,-11414391,25606324,-5972441,33253853,8220911,6358847,-1873857 },
+ },
+ {
+ { 801428,-2081702,16569428,11065167,29875704,96627,7908388,-4480480,-13538503,1387155 },
+ { 19646058,5720633,-11416706,12814209,11607948,12749789,14147075,15156355,-21866831,11835260 },
+ { 19299512,1155910,28703737,14890794,2925026,7269399,26121523,15467869,-26560550,5052483 },
+ },
+},
+{
+ {
+ { -3017432,10058206,1980837,3964243,22160966,12322533,-6431123,-12618185,12228557,-7003677 },
+ { 32944382,14922211,-22844894,5188528,21913450,-8719943,4001465,13238564,-6114803,8653815 },
+ { 22865569,-4652735,27603668,-12545395,14348958,8234005,24808405,5719875,28483275,2841751 },
+ },
+ {
+ { -16420968,-1113305,-327719,-12107856,21886282,-15552774,-1887966,-315658,19932058,-12739203 },
+ { -11656086,10087521,-8864888,-5536143,-19278573,-3055912,3999228,13239134,-4777469,-13910208 },
+ { 1382174,-11694719,17266790,9194690,-13324356,9720081,20403944,11284705,-14013818,3093230 },
+ },
+ {
+ { 16650921,-11037932,-1064178,1570629,-8329746,7352753,-302424,16271225,-24049421,-6691850 },
+ { -21911077,-5927941,-4611316,-5560156,-31744103,-10785293,24123614,15193618,-21652117,-16739389 },
+ { -9935934,-4289447,-25279823,4372842,2087473,10399484,31870908,14690798,17361620,11864968 },
+ },
+ {
+ { -11307610,6210372,13206574,5806320,-29017692,-13967200,-12331205,-7486601,-25578460,-16240689 },
+ { 14668462,-12270235,26039039,15305210,25515617,4542480,10453892,6577524,9145645,-6443880 },
+ { 5974874,3053895,-9433049,-10385191,-31865124,3225009,-7972642,3936128,-5652273,-3050304 },
+ },
+ {
+ { 30625386,-4729400,-25555961,-12792866,-20484575,7695099,17097188,-16303496,-27999779,1803632 },
+ { -3553091,9865099,-5228566,4272701,-5673832,-16689700,14911344,12196514,-21405489,7047412 },
+ { 20093277,9920966,-11138194,-5343857,13161587,12044805,-32856851,4124601,-32343828,-10257566 },
+ },
+ {
+ { -20788824,14084654,-13531713,7842147,19119038,-13822605,4752377,-8714640,-21679658,2288038 },
+ { -26819236,-3283715,29965059,3039786,-14473765,2540457,29457502,14625692,-24819617,12570232 },
+ { -1063558,-11551823,16920318,12494842,1278292,-5869109,-21159943,-3498680,-11974704,4724943 },
+ },
+ {
+ { 17960970,-11775534,-4140968,-9702530,-8876562,-1410617,-12907383,-8659932,-29576300,1903856 },
+ { 23134274,-14279132,-10681997,-1611936,20684485,15770816,-12989750,3190296,26955097,14109738 },
+ { 15308788,5320727,-30113809,-14318877,22902008,7767164,29425325,-11277562,31960942,11934971 },
+ },
+ {
+ { -27395711,8435796,4109644,12222639,-24627868,14818669,20638173,4875028,10491392,1379718 },
+ { -13159415,9197841,3875503,-8936108,-1383712,-5879801,33518459,16176658,21432314,12180697 },
+ { -11787308,11500838,13787581,-13832590,-22430679,10140205,1465425,12689540,-10301319,-13872883 },
+ },
+},
+{
+ {
+ { 5414091,-15386041,-21007664,9643570,12834970,1186149,-2622916,-1342231,26128231,6032912 },
+ { -26337395,-13766162,32496025,-13653919,17847801,-12669156,3604025,8316894,-25875034,-10437358 },
+ { 3296484,6223048,24680646,-12246460,-23052020,5903205,-8862297,-4639164,12376617,3188849 },
+ },
+ {
+ { 29190488,-14659046,27549113,-1183516,3520066,-10697301,32049515,-7309113,-16109234,-9852307 },
+ { -14744486,-9309156,735818,-598978,-20407687,-5057904,25246078,-15795669,18640741,-960977 },
+ { -6928835,-16430795,10361374,5642961,4910474,12345252,-31638386,-494430,10530747,1053335 },
+ },
+ {
+ { -29265967,-14186805,-13538216,-12117373,-19457059,-10655384,-31462369,-2948985,24018831,15026644 },
+ { -22592535,-3145277,-2289276,5953843,-13440189,9425631,25310643,13003497,-2314791,-15145616 },
+ { -27419985,-603321,-8043984,-1669117,-26092265,13987819,-27297622,187899,-23166419,-2531735 },
+ },
+ {
+ { -21744398,-13810475,1844840,5021428,-10434399,-15911473,9716667,16266922,-5070217,726099 },
+ { 29370922,-6053998,7334071,-15342259,9385287,2247707,-13661962,-4839461,30007388,-15823341 },
+ { -936379,16086691,23751945,-543318,-1167538,-5189036,9137109,730663,9835848,4555336 },
+ },
+ {
+ { -23376435,1410446,-22253753,-12899614,30867635,15826977,17693930,544696,-11985298,12422646 },
+ { 31117226,-12215734,-13502838,6561947,-9876867,-12757670,-5118685,-4096706,29120153,13924425 },
+ { -17400879,-14233209,19675799,-2734756,-11006962,-5858820,-9383939,-11317700,7240931,-237388 },
+ },
+ {
+ { -31361739,-11346780,-15007447,-5856218,-22453340,-12152771,1222336,4389483,3293637,-15551743 },
+ { -16684801,-14444245,11038544,11054958,-13801175,-3338533,-24319580,7733547,12796905,-6335822 },
+ { -8759414,-10817836,-25418864,10783769,-30615557,-9746811,-28253339,3647836,3222231,-11160462 },
+ },
+ {
+ { 18606113,1693100,-25448386,-15170272,4112353,10045021,23603893,-2048234,-7550776,2484985 },
+ { 9255317,-3131197,-12156162,-1004256,13098013,-9214866,16377220,-2102812,-19802075,-3034702 },
+ { -22729289,7496160,-5742199,11329249,19991973,-3347502,-31718148,9936966,-30097688,-10618797 },
+ },
+ {
+ { 21878590,-5001297,4338336,13643897,-3036865,13160960,19708896,5415497,-7360503,-4109293 },
+ { 27736861,10103576,12500508,8502413,-3413016,-9633558,10436918,-1550276,-23659143,-8132100 },
+ { 19492550,-12104365,-29681976,-852630,-3208171,12403437,30066266,8367329,13243957,8709688 },
+ },
+},
+{
+ {
+ { 12015105,2801261,28198131,10151021,24818120,-4743133,-11194191,-5645734,5150968,7274186 },
+ { 2831366,-12492146,1478975,6122054,23825128,-12733586,31097299,6083058,31021603,-9793610 },
+ { -2529932,-2229646,445613,10720828,-13849527,-11505937,-23507731,16354465,15067285,-14147707 },
+ },
+ {
+ { 7840942,14037873,-33364863,15934016,-728213,-3642706,21403988,1057586,-19379462,-12403220 },
+ { 915865,-16469274,15608285,-8789130,-24357026,6060030,-17371319,8410997,-7220461,16527025 },
+ { 32922597,-556987,20336074,-16184568,10903705,-5384487,16957574,52992,23834301,6588044 },
+ },
+ {
+ { 32752030,11232950,3381995,-8714866,22652988,-10744103,17159699,16689107,-20314580,-1305992 },
+ { -4689649,9166776,-25710296,-10847306,11576752,12733943,7924251,-2752281,1976123,-7249027 },
+ { 21251222,16309901,-2983015,-6783122,30810597,12967303,156041,-3371252,12331345,-8237197 },
+ },
+ {
+ { 8651614,-4477032,-16085636,-4996994,13002507,2950805,29054427,-5106970,10008136,-4667901 },
+ { 31486080,15114593,-14261250,12951354,14369431,-7387845,16347321,-13662089,8684155,-10532952 },
+ { 19443825,11385320,24468943,-9659068,-23919258,2187569,-26263207,-6086921,31316348,14219878 },
+ },
+ {
+ { -28594490,1193785,32245219,11392485,31092169,15722801,27146014,6992409,29126555,9207390 },
+ { 32382935,1110093,18477781,11028262,-27411763,-7548111,-4980517,10843782,-7957600,-14435730 },
+ { 2814918,7836403,27519878,-7868156,-20894015,-11553689,-21494559,8550130,28346258,1994730 },
+ },
+ {
+ { -19578299,8085545,-14000519,-3948622,2785838,-16231307,-19516951,7174894,22628102,8115180 },
+ { -30405132,955511,-11133838,-15078069,-32447087,-13278079,-25651578,3317160,-9943017,930272 },
+ { -15303681,-6833769,28856490,1357446,23421993,1057177,24091212,-1388970,-22765376,-10650715 },
+ },
+ {
+ { -22751231,-5303997,-12907607,-12768866,-15811511,-7797053,-14839018,-16554220,-1867018,8398970 },
+ { -31969310,2106403,-4736360,1362501,12813763,16200670,22981545,-6291273,18009408,-15772772 },
+ { -17220923,-9545221,-27784654,14166835,29815394,7444469,29551787,-3727419,19288549,1325865 },
+ },
+ {
+ { 15100157,-15835752,-23923978,-1005098,-26450192,15509408,12376730,-3479146,33166107,-8042750 },
+ { 20909231,13023121,-9209752,16251778,-5778415,-8094914,12412151,10018715,2213263,-13878373 },
+ { 32529814,-11074689,30361439,-16689753,-9135940,1513226,22922121,6382134,-5766928,8371348 },
+ },
+},
+{
+ {
+ { 9923462,11271500,12616794,3544722,-29998368,-1721626,12891687,-8193132,-26442943,10486144 },
+ { -22597207,-7012665,8587003,-8257861,4084309,-12970062,361726,2610596,-23921530,-11455195 },
+ { 5408411,-1136691,-4969122,10561668,24145918,14240566,31319731,-4235541,19985175,-3436086 },
+ },
+ {
+ { -13994457,16616821,14549246,3341099,32155958,13648976,-17577068,8849297,65030,8370684 },
+ { -8320926,-12049626,31204563,5839400,-20627288,-1057277,-19442942,6922164,12743482,-9800518 },
+ { -2361371,12678785,28815050,4759974,-23893047,4884717,23783145,11038569,18800704,255233 },
+ },
+ {
+ { -5269658,-1773886,13957886,7990715,23132995,728773,13393847,9066957,19258688,-14753793 },
+ { -2936654,-10827535,-10432089,14516793,-3640786,4372541,-31934921,2209390,-1524053,2055794 },
+ { 580882,16705327,5468415,-2683018,-30926419,-14696000,-7203346,-8994389,-30021019,7394435 },
+ },
+ {
+ { 23838809,1822728,-15738443,15242727,8318092,-3733104,-21672180,-3492205,-4821741,14799921 },
+ { 13345610,9759151,3371034,-16137791,16353039,8577942,31129804,13496856,-9056018,7402518 },
+ { 2286874,-4435931,-20042458,-2008336,-13696227,5038122,11006906,-15760352,8205061,1607563 },
+ },
+ {
+ { 14414086,-8002132,3331830,-3208217,22249151,-5594188,18364661,-2906958,30019587,-9029278 },
+ { -27688051,1585953,-10775053,931069,-29120221,-11002319,-14410829,12029093,9944378,8024 },
+ { 4368715,-3709630,29874200,-15022983,-20230386,-11410704,-16114594,-999085,-8142388,5640030 },
+ },
+ {
+ { 10299610,13746483,11661824,16234854,7630238,5998374,9809887,-16694564,15219798,-14327783 },
+ { 27425505,-5719081,3055006,10660664,23458024,595578,-15398605,-1173195,-18342183,9742717 },
+ { 6744077,2427284,26042789,2720740,-847906,1118974,32324614,7406442,12420155,1994844 },
+ },
+ {
+ { 14012521,-5024720,-18384453,-9578469,-26485342,-3936439,-13033478,-10909803,24319929,-6446333 },
+ { 16412690,-4507367,10772641,15929391,-17068788,-4658621,10555945,-10484049,-30102368,-4739048 },
+ { 22397382,-7767684,-9293161,-12792868,17166287,-9755136,-27333065,6199366,21880021,-12250760 },
+ },
+ {
+ { -4283307,5368523,-31117018,8163389,-30323063,3209128,16557151,8890729,8840445,4957760 },
+ { -15447727,709327,-6919446,-10870178,-29777922,6522332,-21720181,12130072,-14796503,5005757 },
+ { -2114751,-14308128,23019042,15765735,-25269683,6002752,10183197,-13239326,-16395286,-2176112 },
+ },
+},
+{
+ {
+ { -19025756,1632005,13466291,-7995100,-23640451,16573537,-32013908,-3057104,22208662,2000468 },
+ { 3065073,-1412761,-25598674,-361432,-17683065,-5703415,-8164212,11248527,-3691214,-7414184 },
+ { 10379208,-6045554,8877319,1473647,-29291284,-12507580,16690915,2553332,-3132688,16400289 },
+ },
+ {
+ { 15716668,1254266,-18472690,7446274,-8448918,6344164,-22097271,-7285580,26894937,9132066 },
+ { 24158887,12938817,11085297,-8177598,-28063478,-4457083,-30576463,64452,-6817084,-2692882 },
+ { 13488534,7794716,22236231,5989356,25426474,-12578208,2350710,-3418511,-4688006,2364226 },
+ },
+ {
+ { 16335052,9132434,25640582,6678888,1725628,8517937,-11807024,-11697457,15445875,-7798101 },
+ { 29004207,-7867081,28661402,-640412,-12794003,-7943086,31863255,-4135540,-278050,-15759279 },
+ { -6122061,-14866665,-28614905,14569919,-10857999,-3591829,10343412,-6976290,-29828287,-10815811 },
+ },
+ {
+ { 27081650,3463984,14099042,-4517604,1616303,-6205604,29542636,15372179,17293797,960709 },
+ { 20263915,11434237,-5765435,11236810,13505955,-10857102,-16111345,6493122,-19384511,7639714 },
+ { -2830798,-14839232,25403038,-8215196,-8317012,-16173699,18006287,-16043750,29994677,-15808121 },
+ },
+ {
+ { 9769828,5202651,-24157398,-13631392,-28051003,-11561624,-24613141,-13860782,-31184575,709464 },
+ { 12286395,13076066,-21775189,-1176622,-25003198,4057652,-32018128,-8890874,16102007,13205847 },
+ { 13733362,5599946,10557076,3195751,-5557991,8536970,-25540170,8525972,10151379,10394400 },
+ },
+ {
+ { 4024660,-16137551,22436262,12276534,-9099015,-2686099,19698229,11743039,-33302334,8934414 },
+ { -15879800,-4525240,-8580747,-2934061,14634845,-698278,-9449077,3137094,-11536886,11721158 },
+ { 17555939,-5013938,8268606,2331751,-22738815,9761013,9319229,8835153,-9205489,-1280045 },
+ },
+ {
+ { -461409,-7830014,20614118,16688288,-7514766,-4807119,22300304,505429,6108462,-6183415 },
+ { -5070281,12367917,-30663534,3234473,32617080,-8422642,29880583,-13483331,-26898490,-7867459 },
+ { -31975283,5726539,26934134,10237677,-3173717,-605053,24199304,3795095,7592688,-14992079 },
+ },
+ {
+ { 21594432,-14964228,17466408,-4077222,32537084,2739898,6407723,12018833,-28256052,4298412 },
+ { -20650503,-11961496,-27236275,570498,3767144,-1717540,13891942,-1569194,13717174,10805743 },
+ { -14676630,-15644296,15287174,11927123,24177847,-8175568,-796431,14860609,-26938930,-5863836 },
+ },
+},
+{
+ {
+ { 12962541,5311799,-10060768,11658280,18855286,-7954201,13286263,-12808704,-4381056,9882022 },
+ { 18512079,11319350,-20123124,15090309,18818594,5271736,-22727904,3666879,-23967430,-3299429 },
+ { -6789020,-3146043,16192429,13241070,15898607,-14206114,-10084880,-6661110,-2403099,5276065 },
+ },
+ {
+ { 30169808,-5317648,26306206,-11750859,27814964,7069267,7152851,3684982,1449224,13082861 },
+ { 10342826,3098505,2119311,193222,25702612,12233820,23697382,15056736,-21016438,-8202000 },
+ { -33150110,3261608,22745853,7948688,19370557,-15177665,-26171976,6482814,-10300080,-11060101 },
+ },
+ {
+ { 32869458,-5408545,25609743,15678670,-10687769,-15471071,26112421,2521008,-22664288,6904815 },
+ { 29506923,4457497,3377935,-9796444,-30510046,12935080,1561737,3841096,-29003639,-6657642 },
+ { 10340844,-6630377,-18656632,-2278430,12621151,-13339055,30878497,-11824370,-25584551,5181966 },
+ },
+ {
+ { 25940115,-12658025,17324188,-10307374,-8671468,15029094,24396252,-16450922,-2322852,-12388574 },
+ { -21765684,9916823,-1300409,4079498,-1028346,11909559,1782390,12641087,20603771,-6561742 },
+ { -18882287,-11673380,24849422,11501709,13161720,-4768874,1925523,11914390,4662781,7820689 },
+ },
+ {
+ { 12241050,-425982,8132691,9393934,32846760,-1599620,29749456,12172924,16136752,15264020 },
+ { -10349955,-14680563,-8211979,2330220,-17662549,-14545780,10658213,6671822,19012087,3772772 },
+ { 3753511,-3421066,10617074,2028709,14841030,-6721664,28718732,-15762884,20527771,12988982 },
+ },
+ {
+ { -14822485,-5797269,-3707987,12689773,-898983,-10914866,-24183046,-10564943,3299665,-12424953 },
+ { -16777703,-15253301,-9642417,4978983,3308785,8755439,6943197,6461331,-25583147,8991218 },
+ { -17226263,1816362,-1673288,-6086439,31783888,-8175991,-32948145,7417950,-30242287,1507265 },
+ },
+ {
+ { 29692663,6829891,-10498800,4334896,20945975,-11906496,-28887608,8209391,14606362,-10647073 },
+ { -3481570,8707081,32188102,5672294,22096700,1711240,-33020695,9761487,4170404,-2085325 },
+ { -11587470,14855945,-4127778,-1531857,-26649089,15084046,22186522,16002000,-14276837,-8400798 },
+ },
+ {
+ { -4811456,13761029,-31703877,-2483919,-3312471,7869047,-7113572,-9620092,13240845,10965870 },
+ { -7742563,-8256762,-14768334,-13656260,-23232383,12387166,4498947,14147411,29514390,4302863 },
+ { -13413405,-12407859,20757302,-13801832,14785143,8976368,-5061276,-2144373,17846988,-13971927 },
+ },
+},
+{
+ {
+ { -2244452,-754728,-4597030,-1066309,-6247172,1455299,-21647728,-9214789,-5222701,12650267 },
+ { -9906797,-16070310,21134160,12198166,-27064575,708126,387813,13770293,-19134326,10958663 },
+ { 22470984,12369526,23446014,-5441109,-21520802,-9698723,-11772496,-11574455,-25083830,4271862 },
+ },
+ {
+ { -25169565,-10053642,-19909332,15361595,-5984358,2159192,75375,-4278529,-32526221,8469673 },
+ { 15854970,4148314,-8893890,7259002,11666551,13824734,-30531198,2697372,24154791,-9460943 },
+ { 15446137,-15806644,29759747,14019369,30811221,-9610191,-31582008,12840104,24913809,9815020 },
+ },
+ {
+ { -4709286,-5614269,-31841498,-12288893,-14443537,10799414,-9103676,13438769,18735128,9466238 },
+ { 11933045,9281483,5081055,-5183824,-2628162,-4905629,-7727821,-10896103,-22728655,16199064 },
+ { 14576810,379472,-26786533,-8317236,-29426508,-10812974,-102766,1876699,30801119,2164795 },
+ },
+ {
+ { 15995086,3199873,13672555,13712240,-19378835,-4647646,-13081610,-15496269,-13492807,1268052 },
+ { -10290614,-3659039,-3286592,10948818,23037027,3794475,-3470338,-12600221,-17055369,3565904 },
+ { 29210088,-9419337,-5919792,-4952785,10834811,-13327726,-16512102,-10820713,-27162222,-14030531 },
+ },
+ {
+ { -13161890,15508588,16663704,-8156150,-28349942,9019123,-29183421,-3769423,2244111,-14001979 },
+ { -5152875,-3800936,-9306475,-6071583,16243069,14684434,-25673088,-16180800,13491506,4641841 },
+ { 10813417,643330,-19188515,-728916,30292062,-16600078,27548447,-7721242,14476989,-12767431 },
+ },
+ {
+ { 10292079,9984945,6481436,8279905,-7251514,7032743,27282937,-1644259,-27912810,12651324 },
+ { -31185513,-813383,22271204,11835308,10201545,15351028,17099662,3988035,21721536,-3148940 },
+ { 10202177,-6545839,-31373232,-9574638,-32150642,-8119683,-12906320,3852694,13216206,14842320 },
+ },
+ {
+ { -15815640,-10601066,-6538952,-7258995,-6984659,-6581778,-31500847,13765824,-27434397,9900184 },
+ { 14465505,-13833331,-32133984,-14738873,-27443187,12990492,33046193,15796406,-7051866,-8040114 },
+ { 30924417,-8279620,6359016,-12816335,16508377,9071735,-25488601,15413635,9524356,-7018878 },
+ },
+ {
+ { 12274201,-13175547,32627641,-1785326,6736625,13267305,5237659,-5109483,15663516,4035784 },
+ { -2951309,8903985,17349946,601635,-16432815,-4612556,-13732739,-15889334,-22258478,4659091 },
+ { -16916263,-4952973,-30393711,-15158821,20774812,15897498,5736189,15026997,-2178256,-13455585 },
+ },
+},
+{
+ {
+ { -8858980,-2219056,28571666,-10155518,-474467,-10105698,-3801496,278095,23440562,-290208 },
+ { 10226241,-5928702,15139956,120818,-14867693,5218603,32937275,11551483,-16571960,-7442864 },
+ { 17932739,-12437276,-24039557,10749060,11316803,7535897,22503767,5561594,-3646624,3898661 },
+ },
+ {
+ { 7749907,-969567,-16339731,-16464,-25018111,15122143,-1573531,7152530,21831162,1245233 },
+ { 26958459,-14658026,4314586,8346991,-5677764,11960072,-32589295,-620035,-30402091,-16716212 },
+ { -12165896,9166947,33491384,13673479,29787085,13096535,6280834,14587357,-22338025,13987525 },
+ },
+ {
+ { -24349909,7778775,21116000,15572597,-4833266,-5357778,-4300898,-5124639,-7469781,-2858068 },
+ { 9681908,-6737123,-31951644,13591838,-6883821,386950,31622781,6439245,-14581012,4091397 },
+ { -8426427,1470727,-28109679,-1596990,3978627,-5123623,-19622683,12092163,29077877,-14741988 },
+ },
+ {
+ { 5269168,-6859726,-13230211,-8020715,25932563,1763552,-5606110,-5505881,-20017847,2357889 },
+ { 32264008,-15407652,-5387735,-1160093,-2091322,-3946900,23104804,-12869908,5727338,189038 },
+ { 14609123,-8954470,-6000566,-16622781,-14577387,-7743898,-26745169,10942115,-25888931,-14884697 },
+ },
+ {
+ { 20513500,5557931,-15604613,7829531,26413943,-2019404,-21378968,7471781,13913677,-5137875 },
+ { -25574376,11967826,29233242,12948236,-6754465,4713227,-8940970,14059180,12878652,8511905 },
+ { -25656801,3393631,-2955415,-7075526,-2250709,9366908,-30223418,6812974,5568676,-3127656 },
+ },
+ {
+ { 11630004,12144454,2116339,13606037,27378885,15676917,-17408753,-13504373,-14395196,8070818 },
+ { 27117696,-10007378,-31282771,-5570088,1127282,12772488,-29845906,10483306,-11552749,-1028714 },
+ { 10637467,-5688064,5674781,1072708,-26343588,-6982302,-1683975,9177853,-27493162,15431203 },
+ },
+ {
+ { 20525145,10892566,-12742472,12779443,-29493034,16150075,-28240519,14943142,-15056790,-7935931 },
+ { -30024462,5626926,-551567,-9981087,753598,11981191,25244767,-3239766,-3356550,9594024 },
+ { -23752644,2636870,-5163910,-10103818,585134,7877383,11345683,-6492290,13352335,-10977084 },
+ },
+ {
+ { -1931799,-5407458,3304649,-12884869,17015806,-4877091,-29783850,-7752482,-13215537,-319204 },
+ { 20239939,6607058,6203985,3483793,-18386976,-779229,-20723742,15077870,-22750759,14523817 },
+ { 27406042,-6041657,27423596,-4497394,4996214,10002360,-28842031,-4545494,-30172742,-4805667 },
+ },
+},
+{
+ {
+ { 11374242,12660715,17861383,-12540833,10935568,1099227,-13886076,-9091740,-27727044,11358504 },
+ { -12730809,10311867,1510375,10778093,-2119455,-9145702,32676003,11149336,-26123651,4985768 },
+ { -19096303,341147,-6197485,-239033,15756973,-8796662,-983043,13794114,-19414307,-15621255 },
+ },
+ {
+ { 6490081,11940286,25495923,-7726360,8668373,-8751316,3367603,6970005,-1691065,-9004790 },
+ { 1656497,13457317,15370807,6364910,13605745,8362338,-19174622,-5475723,-16796596,-5031438 },
+ { -22273315,-13524424,-64685,-4334223,-18605636,-10921968,-20571065,-7007978,-99853,-10237333 },
+ },
+ {
+ { 17747465,10039260,19368299,-4050591,-20630635,-16041286,31992683,-15857976,-29260363,-5511971 },
+ { 31932027,-4986141,-19612382,16366580,22023614,88450,11371999,-3744247,4882242,-10626905 },
+ { 29796507,37186,19818052,10115756,-11829032,3352736,18551198,3272828,-5190932,-4162409 },
+ },
+ {
+ { 12501286,4044383,-8612957,-13392385,-32430052,5136599,-19230378,-3529697,330070,-3659409 },
+ { 6384877,2899513,17807477,7663917,-2358888,12363165,25366522,-8573892,-271295,12071499 },
+ { -8365515,-4042521,25133448,-4517355,-6211027,2265927,-32769618,1936675,-5159697,3829363 },
+ },
+ {
+ { 28425966,-5835433,-577090,-4697198,-14217555,6870930,7921550,-6567787,26333140,14267664 },
+ { -11067219,11871231,27385719,-10559544,-4585914,-11189312,10004786,-8709488,-21761224,8930324 },
+ { -21197785,-16396035,25654216,-1725397,12282012,11008919,1541940,4757911,-26491501,-16408940 },
+ },
+ {
+ { 13537262,-7759490,-20604840,10961927,-5922820,-13218065,-13156584,6217254,-15943699,13814990 },
+ { -17422573,15157790,18705543,29619,24409717,-260476,27361681,9257833,-1956526,-1776914 },
+ { -25045300,-10191966,15366585,15166509,-13105086,8423556,-29171540,12361135,-18685978,4578290 },
+ },
+ {
+ { 24579768,3711570,1342322,-11180126,-27005135,14124956,-22544529,14074919,21964432,8235257 },
+ { -6528613,-2411497,9442966,-5925588,12025640,-1487420,-2981514,-1669206,13006806,2355433 },
+ { -16304899,-13605259,-6632427,-5142349,16974359,-10911083,27202044,1719366,1141648,-12796236 },
+ },
+ {
+ { -12863944,-13219986,-8318266,-11018091,-6810145,-4843894,13475066,-3133972,32674895,13715045 },
+ { 11423335,-5468059,32344216,8962751,24989809,9241752,-13265253,16086212,-28740881,-15642093 },
+ { -1409668,12530728,-6368726,10847387,19531186,-14132160,-11709148,7791794,-27245943,4383347 },
+ },
+},
+{
+ {
+ { -28970898,5271447,-1266009,-9736989,-12455236,16732599,-4862407,-4906449,27193557,6245191 },
+ { -15193956,5362278,-1783893,2695834,4960227,12840725,23061898,3260492,22510453,8577507 },
+ { -12632451,11257346,-32692994,13548177,-721004,10879011,31168030,13952092,-29571492,-3635906 },
+ },
+ {
+ { 3877321,-9572739,32416692,5405324,-11004407,-13656635,3759769,11935320,5611860,8164018 },
+ { -16275802,14667797,15906460,12155291,-22111149,-9039718,32003002,-8832289,5773085,-8422109 },
+ { -23788118,-8254300,1950875,8937633,18686727,16459170,-905725,12376320,31632953,190926 },
+ },
+ {
+ { -24593607,-16138885,-8423991,13378746,14162407,6901328,-8288749,4508564,-25341555,-3627528 },
+ { 8884438,-5884009,6023974,10104341,-6881569,-4941533,18722941,-14786005,-1672488,827625 },
+ { -32720583,-16289296,-32503547,7101210,13354605,2659080,-1800575,-14108036,-24878478,1541286 },
+ },
+ {
+ { 2901347,-1117687,3880376,-10059388,-17620940,-3612781,-21802117,-3567481,20456845,-1885033 },
+ { 27019610,12299467,-13658288,-1603234,-12861660,-4861471,-19540150,-5016058,29439641,15138866 },
+ { 21536104,-6626420,-32447818,-10690208,-22408077,5175814,-5420040,-16361163,7779328,109896 },
+ },
+ {
+ { 30279744,14648750,-8044871,6425558,13639621,-743509,28698390,12180118,23177719,-554075 },
+ { 26572847,3405927,-31701700,12890905,-19265668,5335866,-6493768,2378492,4439158,-13279347 },
+ { -22716706,3489070,-9225266,-332753,18875722,-1140095,14819434,-12731527,-17717757,-5461437 },
+ },
+ {
+ { -5056483,16566551,15953661,3767752,-10436499,15627060,-820954,2177225,8550082,-15114165 },
+ { -18473302,16596775,-381660,15663611,22860960,15585581,-27844109,-3582739,-23260460,-8428588 },
+ { -32480551,15707275,-8205912,-5652081,29464558,2713815,-22725137,15860482,-21902570,1494193 },
+ },
+ {
+ { -19562091,-14087393,-25583872,-9299552,13127842,759709,21923482,16529112,8742704,12967017 },
+ { -28464899,1553205,32536856,-10473729,-24691605,-406174,-8914625,-2933896,-29903758,15553883 },
+ { 21877909,3230008,9881174,10539357,-4797115,2841332,11543572,14513274,19375923,-12647961 },
+ },
+ {
+ { 8832269,-14495485,13253511,5137575,5037871,4078777,24880818,-6222716,2862653,9455043 },
+ { 29306751,5123106,20245049,-14149889,9592566,8447059,-2077124,-2990080,15511449,4789663 },
+ { -20679756,7004547,8824831,-9434977,-4045704,-3750736,-5754762,108893,23513200,16652362 },
+ },
+},
+{
+ {
+ { -33256173,4144782,-4476029,-6579123,10770039,-7155542,-6650416,-12936300,-18319198,10212860 },
+ { 2756081,8598110,7383731,-6859892,22312759,-1105012,21179801,2600940,-9988298,-12506466 },
+ { -24645692,13317462,-30449259,-15653928,21365574,-10869657,11344424,864440,-2499677,-16710063 },
+ },
+ {
+ { -26432803,6148329,-17184412,-14474154,18782929,-275997,-22561534,211300,2719757,4940997 },
+ { -1323882,3911313,-6948744,14759765,-30027150,7851207,21690126,8518463,26699843,5276295 },
+ { -13149873,-6429067,9396249,365013,24703301,-10488939,1321586,149635,-15452774,7159369 },
+ },
+ {
+ { 9987780,-3404759,17507962,9505530,9731535,-2165514,22356009,8312176,22477218,-8403385 },
+ { 18155857,-16504990,19744716,9006923,15154154,-10538976,24256460,-4864995,-22548173,9334109 },
+ { 2986088,-4911893,10776628,-3473844,10620590,-7083203,-21413845,14253545,-22587149,536906 },
+ },
+ {
+ { 4377756,8115836,24567078,15495314,11625074,13064599,7390551,10589625,10838060,-15420424 },
+ { -19342404,867880,9277171,-3218459,-14431572,-1986443,19295826,-15796950,6378260,699185 },
+ { 7895026,4057113,-7081772,-13077756,-17886831,-323126,-716039,15693155,-5045064,-13373962 },
+ },
+ {
+ { -7737563,-5869402,-14566319,-7406919,11385654,13201616,31730678,-10962840,-3918636,-9669325 },
+ { 10188286,-15770834,-7336361,13427543,22223443,14896287,30743455,7116568,-21786507,5427593 },
+ { 696102,13206899,27047647,-10632082,15285305,-9853179,10798490,-4578720,19236243,12477404 },
+ },
+ {
+ { -11229439,11243796,-17054270,-8040865,-788228,-8167967,-3897669,11180504,-23169516,7733644 },
+ { 17800790,-14036179,-27000429,-11766671,23887827,3149671,23466177,-10538171,10322027,15313801 },
+ { 26246234,11968874,32263343,-5468728,6830755,-13323031,-15794704,-101982,-24449242,10890804 },
+ },
+ {
+ { -31365647,10271363,-12660625,-6267268,16690207,-13062544,-14982212,16484931,25180797,-5334884 },
+ { -586574,10376444,-32586414,-11286356,19801893,10997610,2276632,9482883,316878,13820577 },
+ { -9882808,-4510367,-2115506,16457136,-11100081,11674996,30756178,-7515054,30696930,-3712849 },
+ },
+ {
+ { 32988917,-9603412,12499366,7910787,-10617257,-11931514,-7342816,-9985397,-32349517,7392473 },
+ { -8855661,15927861,9866406,-3649411,-2396914,-16655781,-30409476,-9134995,25112947,-2926644 },
+ { -2504044,-436966,25621774,-5678772,15085042,-5479877,-24884878,-13526194,5537438,-13914319 },
+ },
+},
+{
+ {
+ { -11225584,2320285,-9584280,10149187,-33444663,5808648,-14876251,-1729667,31234590,6090599 },
+ { -9633316,116426,26083934,2897444,-6364437,-2688086,609721,15878753,-6970405,-9034768 },
+ { -27757857,247744,-15194774,-9002551,23288161,-10011936,-23869595,6503646,20650474,1804084 },
+ },
+ {
+ { -27589786,15456424,8972517,8469608,15640622,4439847,3121995,-10329713,27842616,-202328 },
+ { -15306973,2839644,22530074,10026331,4602058,5048462,28248656,5031932,-11375082,12714369 },
+ { 20807691,-7270825,29286141,11421711,-27876523,-13868230,-21227475,1035546,-19733229,12796920 },
+ },
+ {
+ { 12076899,-14301286,-8785001,-11848922,-25012791,16400684,-17591495,-12899438,3480665,-15182815 },
+ { -32361549,5457597,28548107,7833186,7303070,-11953545,-24363064,-15921875,-33374054,2771025 },
+ { -21389266,421932,26597266,6860826,22486084,-6737172,-17137485,-4210226,-24552282,15673397 },
+ },
+ {
+ { -20184622,2338216,19788685,-9620956,-4001265,-8740893,-20271184,4733254,3727144,-12934448 },
+ { 6120119,814863,-11794402,-622716,6812205,-15747771,2019594,7975683,31123697,-10958981 },
+ { 30069250,-11435332,30434654,2958439,18399564,-976289,12296869,9204260,-16432438,9648165 },
+ },
+ {
+ { 32705432,-1550977,30705658,7451065,-11805606,9631813,3305266,5248604,-26008332,-11377501 },
+ { 17219865,2375039,-31570947,-5575615,-19459679,9219903,294711,15298639,2662509,-16297073 },
+ { -1172927,-7558695,-4366770,-4287744,-21346413,-8434326,32087529,-1222777,32247248,-14389861 },
+ },
+ {
+ { 14312628,1221556,17395390,-8700143,-4945741,-8684635,-28197744,-9637817,-16027623,-13378845 },
+ { -1428825,-9678990,-9235681,6549687,-7383069,-468664,23046502,9803137,17597934,2346211 },
+ { 18510800,15337574,26171504,981392,-22241552,7827556,-23491134,-11323352,3059833,-11782870 },
+ },
+ {
+ { 10141598,6082907,17829293,-1947643,9830092,13613136,-25556636,-5544586,-33502212,3592096 },
+ { 33114168,-15889352,-26525686,-13343397,33076705,8716171,1151462,1521897,-982665,-6837803 },
+ { -32939165,-4255815,23947181,-324178,-33072974,-12305637,-16637686,3891704,26353178,693168 },
+ },
+ {
+ { 30374239,1595580,-16884039,13186931,4600344,406904,9585294,-400668,31375464,14369965 },
+ { -14370654,-7772529,1510301,6434173,-18784789,-6262728,32732230,-13108839,17901441,16011505 },
+ { 18171223,-11934626,-12500402,15197122,-11038147,-15230035,-19172240,-16046376,8764035,12309598 },
+ },
+},
+{
+ {
+ { 5975908,-5243188,-19459362,-9681747,-11541277,14015782,-23665757,1228319,17544096,-10593782 },
+ { 5811932,-1715293,3442887,-2269310,-18367348,-8359541,-18044043,-15410127,-5565381,12348900 },
+ { -31399660,11407555,25755363,6891399,-3256938,14872274,-24849353,8141295,-10632534,-585479 },
+ },
+ {
+ { -12675304,694026,-5076145,13300344,14015258,-14451394,-9698672,-11329050,30944593,1130208 },
+ { 8247766,-6710942,-26562381,-7709309,-14401939,-14648910,4652152,2488540,23550156,-271232 },
+ { 17294316,-3788438,7026748,15626851,22990044,113481,2267737,-5908146,-408818,-137719 },
+ },
+ {
+ { 16091085,-16253926,18599252,7340678,2137637,-1221657,-3364161,14550936,3260525,-7166271 },
+ { -4910104,-13332887,18550887,10864893,-16459325,-7291596,-23028869,-13204905,-12748722,2701326 },
+ { -8574695,16099415,4629974,-16340524,-20786213,-6005432,-10018363,9276971,11329923,1862132 },
+ },
+ {
+ { 14763076,-15903608,-30918270,3689867,3511892,10313526,-21951088,12219231,-9037963,-940300 },
+ { 8894987,-3446094,6150753,3013931,301220,15693451,-31981216,-2909717,-15438168,11595570 },
+ { 15214962,3537601,-26238722,-14058872,4418657,-15230761,13947276,10730794,-13489462,-4363670 },
+ },
+ {
+ { -2538306,7682793,32759013,263109,-29984731,-7955452,-22332124,-10188635,977108,699994 },
+ { -12466472,4195084,-9211532,550904,-15565337,12917920,19118110,-439841,-30534533,-14337913 },
+ { 31788461,-14507657,4799989,7372237,8808585,-14747943,9408237,-10051775,12493932,-5409317 },
+ },
+ {
+ { -25680606,5260744,-19235809,-6284470,-3695942,16566087,27218280,2607121,29375955,6024730 },
+ { 842132,-2794693,-4763381,-8722815,26332018,-12405641,11831880,6985184,-9940361,2854096 },
+ { -4847262,-7969331,2516242,-5847713,9695691,-7221186,16512645,960770,12121869,16648078 },
+ },
+ {
+ { -15218652,14667096,-13336229,2013717,30598287,-464137,-31504922,-7882064,20237806,2838411 },
+ { -19288047,4453152,15298546,-16178388,22115043,-15972604,12544294,-13470457,1068881,-12499905 },
+ { -9558883,-16518835,33238498,13506958,30505848,-1114596,-8486907,-2630053,12521378,4845654 },
+ },
+ {
+ { -28198521,10744108,-2958380,10199664,7759311,-13088600,3409348,-873400,-6482306,-12885870 },
+ { -23561822,6230156,-20382013,10655314,-24040585,-11621172,10477734,-1240216,-3113227,13974498 },
+ { 12966261,15550616,-32038948,-1615346,21025980,-629444,5642325,7188737,18895762,12629579 },
+ },
+},
+{
+ {
+ { 14741879,-14946887,22177208,-11721237,1279741,8058600,11758140,789443,32195181,3895677 },
+ { 10758205,15755439,-4509950,9243698,-4879422,6879879,-2204575,-3566119,-8982069,4429647 },
+ { -2453894,15725973,-20436342,-10410672,-5803908,-11040220,-7135870,-11642895,18047436,-15281743 },
+ },
+ {
+ { -25173001,-11307165,29759956,11776784,-22262383,-15820455,10993114,-12850837,-17620701,-9408468 },
+ { 21987233,700364,-24505048,14972008,-7774265,-5718395,32155026,2581431,-29958985,8773375 },
+ { -25568350,454463,-13211935,16126715,25240068,8594567,20656846,12017935,-7874389,-13920155 },
+ },
+ {
+ { 6028182,6263078,-31011806,-11301710,-818919,2461772,-31841174,-5468042,-1721788,-2776725 },
+ { -12278994,16624277,987579,-5922598,32908203,1248608,7719845,-4166698,28408820,6816612 },
+ { -10358094,-8237829,19549651,-12169222,22082623,16147817,20613181,13982702,-10339570,5067943 },
+ },
+ {
+ { -30505967,-3821767,12074681,13582412,-19877972,2443951,-19719286,12746132,5331210,-10105944 },
+ { 30528811,3601899,-1957090,4619785,-27361822,-15436388,24180793,-12570394,27679908,-1648928 },
+ { 9402404,-13957065,32834043,10838634,-26580150,-13237195,26653274,-8685565,22611444,-12715406 },
+ },
+ {
+ { 22190590,1118029,22736441,15130463,-30460692,-5991321,19189625,-4648942,4854859,6622139 },
+ { -8310738,-2953450,-8262579,-3388049,-10401731,-271929,13424426,-3567227,26404409,13001963 },
+ { -31241838,-15415700,-2994250,8939346,11562230,-12840670,-26064365,-11621720,-15405155,11020693 },
+ },
+ {
+ { 1866042,-7949489,-7898649,-10301010,12483315,13477547,3175636,-12424163,28761762,1406734 },
+ { -448555,-1777666,13018551,3194501,-9580420,-11161737,24760585,-4347088,25577411,-13378680 },
+ { -24290378,4759345,-690653,-1852816,2066747,10693769,-29595790,9884936,-9368926,4745410 },
+ },
+ {
+ { -9141284,6049714,-19531061,-4341411,-31260798,9944276,-15462008,-11311852,10931924,-11931931 },
+ { -16561513,14112680,-8012645,4817318,-8040464,-11414606,-22853429,10856641,-20470770,13434654 },
+ { 22759489,-10073434,-16766264,-1871422,13637442,-10168091,1765144,-12654326,28445307,-5364710 },
+ },
+ {
+ { 29875063,12493613,2795536,-3786330,1710620,15181182,-10195717,-8788675,9074234,1167180 },
+ { -26205683,11014233,-9842651,-2635485,-26908120,7532294,-18716888,-9535498,3843903,9367684 },
+ { -10969595,-6403711,9591134,9582310,11349256,108879,16235123,8601684,-139197,4242895 },
+ },
+},
+{
+ {
+ { 22092954,-13191123,-2042793,-11968512,32186753,-11517388,-6574341,2470660,-27417366,16625501 },
+ { -11057722,3042016,13770083,-9257922,584236,-544855,-7770857,2602725,-27351616,14247413 },
+ { 6314175,-10264892,-32772502,15957557,-10157730,168750,-8618807,14290061,27108877,-1180880 },
+ },
+ {
+ { -8586597,-7170966,13241782,10960156,-32991015,-13794596,33547976,-11058889,-27148451,981874 },
+ { 22833440,9293594,-32649448,-13618667,-9136966,14756819,-22928859,-13970780,-10479804,-16197962 },
+ { -7768587,3326786,-28111797,10783824,19178761,14905060,22680049,13906969,-15933690,3797899 },
+ },
+ {
+ { 21721356,-4212746,-12206123,9310182,-3882239,-13653110,23740224,-2709232,20491983,-8042152 },
+ { 9209270,-15135055,-13256557,-6167798,-731016,15289673,25947805,15286587,30997318,-6703063 },
+ { 7392032,16618386,23946583,-8039892,-13265164,-1533858,-14197445,-2321576,17649998,-250080 },
+ },
+ {
+ { -9301088,-14193827,30609526,-3049543,-25175069,-1283752,-15241566,-9525724,-2233253,7662146 },
+ { -17558673,1763594,-33114336,15908610,-30040870,-12174295,7335080,-8472199,-3174674,3440183 },
+ { -19889700,-5977008,-24111293,-9688870,10799743,-16571957,40450,-4431835,4862400,1133 },
+ },
+ {
+ { -32856209,-7873957,-5422389,14860950,-16319031,7956142,7258061,311861,-30594991,-7379421 },
+ { -3773428,-1565936,28985340,7499440,24445838,9325937,29727763,16527196,18278453,15405622 },
+ { -4381906,8508652,-19898366,-3674424,-5984453,15149970,-13313598,843523,-21875062,13626197 },
+ },
+ {
+ { 2281448,-13487055,-10915418,-2609910,1879358,16164207,-10783882,3953792,13340839,15928663 },
+ { 31727126,-7179855,-18437503,-8283652,2875793,-16390330,-25269894,-7014826,-23452306,5964753 },
+ { 4100420,-5959452,-17179337,6017714,-18705837,12227141,-26684835,11344144,2538215,-7570755 },
+ },
+ {
+ { -9433605,6123113,11159803,-2156608,30016280,14966241,-20474983,1485421,-629256,-15958862 },
+ { -26804558,4260919,11851389,9658551,-32017107,16367492,-20205425,-13191288,11659922,-11115118 },
+ { 26180396,10015009,-30844224,-8581293,5418197,9480663,2231568,-10170080,33100372,-1306171 },
+ },
+ {
+ { 15121113,-5201871,-10389905,15427821,-27509937,-15992507,21670947,4486675,-5931810,-14466380 },
+ { 16166486,-9483733,-11104130,6023908,-31926798,-1364923,2340060,-16254968,-10735770,-10039824 },
+ { 28042865,-3557089,-12126526,12259706,-3717498,-6945899,6766453,-8689599,18036436,5803270 },
+ },
+},
+{
+ {
+ { -817581,6763912,11803561,1585585,10958447,-2671165,23855391,4598332,-6159431,-14117438 },
+ { -31031306,-14256194,17332029,-2383520,31312682,-5967183,696309,50292,-20095739,11763584 },
+ { -594563,-2514283,-32234153,12643980,12650761,14811489,665117,-12613632,-19773211,-10713562 },
+ },
+ {
+ { 30464590,-11262872,-4127476,-12734478,19835327,-7105613,-24396175,2075773,-17020157,992471 },
+ { 18357185,-6994433,7766382,16342475,-29324918,411174,14578841,8080033,-11574335,-10601610 },
+ { 19598397,10334610,12555054,2555664,18821899,-10339780,21873263,16014234,26224780,16452269 },
+ },
+ {
+ { -30223925,5145196,5944548,16385966,3976735,2009897,-11377804,-7618186,-20533829,3698650 },
+ { 14187449,3448569,-10636236,-10810935,-22663880,-3433596,7268410,-10890444,27394301,12015369 },
+ { 19695761,16087646,28032085,12999827,6817792,11427614,20244189,-1312777,-13259127,-3402461 },
+ },
+ {
+ { 30860103,12735208,-1888245,-4699734,-16974906,2256940,-8166013,12298312,-8550524,-10393462 },
+ { -5719826,-11245325,-1910649,15569035,26642876,-7587760,-5789354,-15118654,-4976164,12651793 },
+ { -2848395,9953421,11531313,-5282879,26895123,-12697089,-13118820,-16517902,9768698,-2533218 },
+ },
+ {
+ { -24719459,1894651,-287698,-4704085,15348719,-8156530,32767513,12765450,4940095,10678226 },
+ { 18860224,15980149,-18987240,-1562570,-26233012,-11071856,-7843882,13944024,-24372348,16582019 },
+ { -15504260,4970268,-29893044,4175593,-20993212,-2199756,-11704054,15444560,-11003761,7989037 },
+ },
+ {
+ { 31490452,5568061,-2412803,2182383,-32336847,4531686,-32078269,6200206,-19686113,-14800171 },
+ { -17308668,-15879940,-31522777,-2831,-32887382,16375549,8680158,-16371713,28550068,-6857132 },
+ { -28126887,-5688091,16837845,-1820458,-6850681,12700016,-30039981,4364038,1155602,5988841 },
+ },
+ {
+ { 21890435,-13272907,-12624011,12154349,-7831873,15300496,23148983,-4470481,24618407,8283181 },
+ { -33136107,-10512751,9975416,6841041,-31559793,16356536,3070187,-7025928,1466169,10740210 },
+ { -1509399,-15488185,-13503385,-10655916,32799044,909394,-13938903,-5779719,-32164649,-15327040 },
+ },
+ {
+ { 3960823,-14267803,-28026090,-15918051,-19404858,13146868,15567327,951507,-3260321,-573935 },
+ { 24740841,5052253,-30094131,8961361,25877428,6165135,-24368180,14397372,-7380369,-6144105 },
+ { -28888365,3510803,-28103278,-1158478,-11238128,-10631454,-15441463,-14453128,-1625486,-6494814 },
+ },
+},
+{
+ {
+ { 793299,-9230478,8836302,-6235707,-27360908,-2369593,33152843,-4885251,-9906200,-621852 },
+ { 5666233,525582,20782575,-8038419,-24538499,14657740,16099374,1468826,-6171428,-15186581 },
+ { -4859255,-3779343,-2917758,-6748019,7778750,11688288,-30404353,-9871238,-1558923,-9863646 },
+ },
+ {
+ { 10896332,-7719704,824275,472601,-19460308,3009587,25248958,14783338,-30581476,-15757844 },
+ { 10566929,12612572,-31944212,11118703,-12633376,12362879,21752402,8822496,24003793,14264025 },
+ { 27713862,-7355973,-11008240,9227530,27050101,2504721,23886875,-13117525,13958495,-5732453 },
+ },
+ {
+ { -23481610,4867226,-27247128,3900521,29838369,-8212291,-31889399,-10041781,7340521,-15410068 },
+ { 4646514,-8011124,-22766023,-11532654,23184553,8566613,31366726,-1381061,-15066784,-10375192 },
+ { -17270517,12723032,-16993061,14878794,21619651,-6197576,27584817,3093888,-8843694,3849921 },
+ },
+ {
+ { -9064912,2103172,25561640,-15125738,-5239824,9582958,32477045,-9017955,5002294,-15550259 },
+ { -12057553,-11177906,21115585,-13365155,8808712,-12030708,16489530,13378448,-25845716,12741426 },
+ { -5946367,10645103,-30911586,15390284,-3286982,-7118677,24306472,15852464,28834118,-7646072 },
+ },
+ {
+ { -17335748,-9107057,-24531279,9434953,-8472084,-583362,-13090771,455841,20461858,5491305 },
+ { 13669248,-16095482,-12481974,-10203039,-14569770,-11893198,-24995986,11293807,-28588204,-9421832 },
+ { 28497928,6272777,-33022994,14470570,8906179,-1225630,18504674,-14165166,29867745,-8795943 },
+ },
+ {
+ { -16207023,13517196,-27799630,-13697798,24009064,-6373891,-6367600,-13175392,22853429,-4012011 },
+ { 24191378,16712145,-13931797,15217831,14542237,1646131,18603514,-11037887,12876623,-2112447 },
+ { 17902668,4518229,-411702,-2829247,26878217,5258055,-12860753,608397,16031844,3723494 },
+ },
+ {
+ { -28632773,12763728,-20446446,7577504,33001348,-13017745,17558842,-7872890,23896954,-4314245 },
+ { -20005381,-12011952,31520464,605201,2543521,5991821,-2945064,7229064,-9919646,-8826859 },
+ { 28816045,298879,-28165016,-15920938,19000928,-1665890,-12680833,-2949325,-18051778,-2082915 },
+ },
+ {
+ { 16000882,-344896,3493092,-11447198,-29504595,-13159789,12577740,16041268,-19715240,7847707 },
+ { 10151868,10572098,27312476,7922682,14825339,4723128,-32855931,-6519018,-10020567,3852848 },
+ { -11430470,15697596,-21121557,-4420647,5386314,15063598,16514493,-15932110,29330899,-15076224 },
+ },
+},
+{
+ {
+ { -25499735,-4378794,-15222908,-6901211,16615731,2051784,3303702,15490,-27548796,12314391 },
+ { 15683520,-6003043,18109120,-9980648,15337968,-5997823,-16717435,15921866,16103996,-3731215 },
+ { -23169824,-10781249,13588192,-1628807,-3798557,-1074929,-19273607,5402699,-29815713,-9841101 },
+ },
+ {
+ { 23190676,2384583,-32714340,3462154,-29903655,-1529132,-11266856,8911517,-25205859,2739713 },
+ { 21374101,-3554250,-33524649,9874411,15377179,11831242,-33529904,6134907,4931255,11987849 },
+ { -7732,-2978858,-16223486,7277597,105524,-322051,-31480539,13861388,-30076310,10117930 },
+ },
+ {
+ { -29501170,-10744872,-26163768,13051539,-25625564,5089643,-6325503,6704079,12890019,15728940 },
+ { -21972360,-11771379,-951059,-4418840,14704840,2695116,903376,-10428139,12885167,8311031 },
+ { -17516482,5352194,10384213,-13811658,7506451,13453191,26423267,4384730,1888765,-5435404 },
+ },
+ {
+ { -25817338,-3107312,-13494599,-3182506,30896459,-13921729,-32251644,-12707869,-19464434,-3340243 },
+ { -23607977,-2665774,-526091,4651136,5765089,4618330,6092245,14845197,17151279,-9854116 },
+ { -24830458,-12733720,-15165978,10367250,-29530908,-265356,22825805,-7087279,-16866484,16176525 },
+ },
+ {
+ { -23583256,6564961,20063689,3798228,-4740178,7359225,2006182,-10363426,-28746253,-10197509 },
+ { -10626600,-4486402,-13320562,-5125317,3432136,-6393229,23632037,-1940610,32808310,1099883 },
+ { 15030977,5768825,-27451236,-2887299,-6427378,-15361371,-15277896,-6809350,2051441,-15225865 },
+ },
+ {
+ { -3362323,-7239372,7517890,9824992,23555850,295369,5148398,-14154188,-22686354,16633660 },
+ { 4577086,-16752288,13249841,-15304328,19958763,-14537274,18559670,-10759549,8402478,-9864273 },
+ { -28406330,-1051581,-26790155,-907698,-17212414,-11030789,9453451,-14980072,17983010,9967138 },
+ },
+ {
+ { -25762494,6524722,26585488,9969270,24709298,1220360,-1677990,7806337,17507396,3651560 },
+ { -10420457,-4118111,14584639,15971087,-15768321,8861010,26556809,-5574557,-18553322,-11357135 },
+ { 2839101,14284142,4029895,3472686,14402957,12689363,-26642121,8459447,-5605463,-7621941 },
+ },
+ {
+ { -4839289,-3535444,9744961,2871048,25113978,3187018,-25110813,-849066,17258084,-7977739 },
+ { 18164541,-10595176,-17154882,-1542417,19237078,-9745295,23357533,-15217008,26908270,12150756 },
+ { -30264870,-7647865,5112249,-7036672,-1499807,-6974257,43168,-5537701,-32302074,16215819 },
+ },
+},
+{
+ {
+ { -6898905,9824394,-12304779,-4401089,-31397141,-6276835,32574489,12532905,-7503072,-8675347 },
+ { -27343522,-16515468,-27151524,-10722951,946346,16291093,254968,7168080,21676107,-1943028 },
+ { 21260961,-8424752,-16831886,-11920822,-23677961,3968121,-3651949,-6215466,-3556191,-7913075 },
+ },
+ {
+ { 16544754,13250366,-16804428,15546242,-4583003,12757258,-2462308,-8680336,-18907032,-9662799 },
+ { -2415239,-15577728,18312303,4964443,-15272530,-12653564,26820651,16690659,25459437,-4564609 },
+ { -25144690,11425020,28423002,-11020557,-6144921,-15826224,9142795,-2391602,-6432418,-1644817 },
+ },
+ {
+ { -23104652,6253476,16964147,-3768872,-25113972,-12296437,-27457225,-16344658,6335692,7249989 },
+ { -30333227,13979675,7503222,-12368314,-11956721,-4621693,-30272269,2682242,25993170,-12478523 },
+ { 4364628,5930691,32304656,-10044554,-8054781,15091131,22857016,-10598955,31820368,15075278 },
+ },
+ {
+ { 31879134,-8918693,17258761,90626,-8041836,-4917709,24162788,-9650886,-17970238,12833045 },
+ { 19073683,14851414,-24403169,-11860168,7625278,11091125,-19619190,2074449,-9413939,14905377 },
+ { 24483667,-11935567,-2518866,-11547418,-1553130,15355506,-25282080,9253129,27628530,-7555480 },
+ },
+ {
+ { 17597607,8340603,19355617,552187,26198470,-3176583,4593324,-9157582,-14110875,15297016 },
+ { 510886,14337390,-31785257,16638632,6328095,2713355,-20217417,-11864220,8683221,2921426 },
+ { 18606791,11874196,27155355,-5281482,-24031742,6265446,-25178240,-1278924,4674690,13890525 },
+ },
+ {
+ { 13609624,13069022,-27372361,-13055908,24360586,9592974,14977157,9835105,4389687,288396 },
+ { 9922506,-519394,13613107,5883594,-18758345,-434263,-12304062,8317628,23388070,16052080 },
+ { 12720016,11937594,-31970060,-5028689,26900120,8561328,-20155687,-11632979,-14754271,-10812892 },
+ },
+ {
+ { 15961858,14150409,26716931,-665832,-22794328,13603569,11829573,7467844,-28822128,929275 },
+ { 11038231,-11582396,-27310482,-7316562,-10498527,-16307831,-23479533,-9371869,-21393143,2465074 },
+ { 20017163,-4323226,27915242,1529148,12396362,15675764,13817261,-9658066,2463391,-4622140 },
+ },
+ {
+ { -16358878,-12663911,-12065183,4996454,-1256422,1073572,9583558,12851107,4003896,12673717 },
+ { -1731589,-15155870,-3262930,16143082,19294135,13385325,14741514,-9103726,7903886,2348101 },
+ { 24536016,-16515207,12715592,-3862155,1511293,10047386,-3842346,-7129159,-28377538,10048127 },
+ },
+},
+{
+ {
+ { -12622226,-6204820,30718825,2591312,-10617028,12192840,18873298,-7297090,-32297756,15221632 },
+ { -26478122,-11103864,11546244,-1852483,9180880,7656409,-21343950,2095755,29769758,6593415 },
+ { -31994208,-2907461,4176912,3264766,12538965,-868111,26312345,-6118678,30958054,8292160 },
+ },
+ {
+ { 31429822,-13959116,29173532,15632448,12174511,-2760094,32808831,3977186,26143136,-3148876 },
+ { 22648901,1402143,-22799984,13746059,7936347,365344,-8668633,-1674433,-3758243,-2304625 },
+ { -15491917,8012313,-2514730,-12702462,-23965846,-10254029,-1612713,-1535569,-16664475,8194478 },
+ },
+ {
+ { 27338066,-7507420,-7414224,10140405,-19026427,-6589889,27277191,8855376,28572286,3005164 },
+ { 26287124,4821776,25476601,-4145903,-3764513,-15788984,-18008582,1182479,-26094821,-13079595 },
+ { -7171154,3178080,23970071,6201893,-17195577,-4489192,-21876275,-13982627,32208683,-1198248 },
+ },
+ {
+ { -16657702,2817643,-10286362,14811298,6024667,13349505,-27315504,-10497842,-27672585,-11539858 },
+ { 15941029,-9405932,-21367050,8062055,31876073,-238629,-15278393,-1444429,15397331,-4130193 },
+ { 8934485,-13485467,-23286397,-13423241,-32446090,14047986,31170398,-1441021,-27505566,15087184 },
+ },
+ {
+ { -18357243,-2156491,24524913,-16677868,15520427,-6360776,-15502406,11461896,16788528,-5868942 },
+ { -1947386,16013773,21750665,3714552,-17401782,-16055433,-3770287,-10323320,31322514,-11615635 },
+ { 21426655,-5650218,-13648287,-5347537,-28812189,-4920970,-18275391,-14621414,13040862,-12112948 },
+ },
+ {
+ { 11293895,12478086,-27136401,15083750,-29307421,14748872,14555558,-13417103,1613711,4896935 },
+ { -25894883,15323294,-8489791,-8057900,25967126,-13425460,2825960,-4897045,-23971776,-11267415 },
+ { -15924766,-5229880,-17443532,6410664,3622847,10243618,20615400,12405433,-23753030,-8436416 },
+ },
+ {
+ { -7091295,12556208,-20191352,9025187,-17072479,4333801,4378436,2432030,23097949,-566018 },
+ { 4565804,-16025654,20084412,-7842817,1724999,189254,24767264,10103221,-18512313,2424778 },
+ { 366633,-11976806,8173090,-6890119,30788634,5745705,-7168678,1344109,-3642553,12412659 },
+ },
+ {
+ { -24001791,7690286,14929416,-168257,-32210835,-13412986,24162697,-15326504,-3141501,11179385 },
+ { 18289522,-14724954,8056945,16430056,-21729724,7842514,-6001441,-1486897,-18684645,-11443503 },
+ { 476239,6601091,-6152790,-9723375,17503545,-4863900,27672959,13403813,11052904,5219329 },
+ },
+},
+{
+ {
+ { 20678546,-8375738,-32671898,8849123,-5009758,14574752,31186971,-3973730,9014762,-8579056 },
+ { -13644050,-10350239,-15962508,5075808,-1514661,-11534600,-33102500,9160280,8473550,-3256838 },
+ { 24900749,14435722,17209120,-15292541,-22592275,9878983,-7689309,-16335821,-24568481,11788948 },
+ },
+ {
+ { -3118155,-11395194,-13802089,14797441,9652448,-6845904,-20037437,10410733,-24568470,-1458691 },
+ { -15659161,16736706,-22467150,10215878,-9097177,7563911,11871841,-12505194,-18513325,8464118 },
+ { -23400612,8348507,-14585951,-861714,-3950205,-6373419,14325289,8628612,33313881,-8370517 },
+ },
+ {
+ { -20186973,-4967935,22367356,5271547,-1097117,-4788838,-24805667,-10236854,-8940735,-5818269 },
+ { -6948785,-1795212,-32625683,-16021179,32635414,-7374245,15989197,-12838188,28358192,-4253904 },
+ { -23561781,-2799059,-32351682,-1661963,-9147719,10429267,-16637684,4072016,-5351664,5596589 },
+ },
+ {
+ { -28236598,-3390048,12312896,6213178,3117142,16078565,29266239,2557221,1768301,15373193 },
+ { -7243358,-3246960,-4593467,-7553353,-127927,-912245,-1090902,-4504991,-24660491,3442910 },
+ { -30210571,5124043,14181784,8197961,18964734,-11939093,22597931,7176455,-18585478,13365930 },
+ },
+ {
+ { -7877390,-1499958,8324673,4690079,6261860,890446,24538107,-8570186,-9689599,-3031667 },
+ { 25008904,-10771599,-4305031,-9638010,16265036,15721635,683793,-11823784,15723479,-15163481 },
+ { -9660625,12374379,-27006999,-7026148,-7724114,-12314514,11879682,5400171,519526,-1235876 },
+ },
+ {
+ { 22258397,-16332233,-7869817,14613016,-22520255,-2950923,-20353881,7315967,16648397,7605640 },
+ { -8081308,-8464597,-8223311,9719710,19259459,-15348212,23994942,-5281555,-9468848,4763278 },
+ { -21699244,9220969,-15730624,1084137,-25476107,-2852390,31088447,-7764523,-11356529,728112 },
+ },
+ {
+ { 26047220,-11751471,-6900323,-16521798,24092068,9158119,-4273545,-12555558,-29365436,-5498272 },
+ { 17510331,-322857,5854289,8403524,17133918,-3112612,-28111007,12327945,10750447,10014012 },
+ { -10312768,3936952,9156313,-8897683,16498692,-994647,-27481051,-666732,3424691,7540221 },
+ },
+ {
+ { 30322361,-6964110,11361005,-4143317,7433304,4989748,-7071422,-16317219,-9244265,15258046 },
+ { 13054562,-2779497,19155474,469045,-12482797,4566042,5631406,2711395,1062915,-5136345 },
+ { -19240248,-11254599,-29509029,-7499965,-5835763,13005411,-6066489,12194497,32960380,1459310 },
+ },
+},
+{
+ {
+ { 19852034,7027924,23669353,10020366,8586503,-6657907,394197,-6101885,18638003,-11174937 },
+ { 31395534,15098109,26581030,8030562,-16527914,-5007134,9012486,-7584354,-6643087,-5442636 },
+ { -9192165,-2347377,-1997099,4529534,25766844,607986,-13222,9677543,-32294889,-6456008 },
+ },
+ {
+ { -2444496,-149937,29348902,8186665,1873760,12489863,-30934579,-7839692,-7852844,-8138429 },
+ { -15236356,-15433509,7766470,746860,26346930,-10221762,-27333451,10754588,-9431476,5203576 },
+ { 31834314,14135496,-770007,5159118,20917671,-16768096,-7467973,-7337524,31809243,7347066 },
+ },
+ {
+ { -9606723,-11874240,20414459,13033986,13716524,-11691881,19797970,-12211255,15192876,-2087490 },
+ { -12663563,-2181719,1168162,-3804809,26747877,-14138091,10609330,12694420,33473243,-13382104 },
+ { 33184999,11180355,15832085,-11385430,-1633671,225884,15089336,-11023903,-6135662,14480053 },
+ },
+ {
+ { 31308717,-5619998,31030840,-1897099,15674547,-6582883,5496208,13685227,27595050,8737275 },
+ { -20318852,-15150239,10933843,-16178022,8335352,-7546022,-31008351,-12610604,26498114,66511 },
+ { 22644454,-8761729,-16671776,4884562,-3105614,-13559366,30540766,-4286747,-13327787,-7515095 },
+ },
+ {
+ { -28017847,9834845,18617207,-2681312,-3401956,-13307506,8205540,13585437,-17127465,15115439 },
+ { 23711543,-672915,31206561,-8362711,6164647,-9709987,-33535882,-1426096,8236921,16492939 },
+ { -23910559,-13515526,-26299483,-4503841,25005590,-7687270,19574902,10071562,6708380,-6222424 },
+ },
+ {
+ { 2101391,-4930054,19702731,2367575,-15427167,1047675,5301017,9328700,29955601,-11678310 },
+ { 3096359,9271816,-21620864,-15521844,-14847996,-7592937,-25892142,-12635595,-9917575,6216608 },
+ { -32615849,338663,-25195611,2510422,-29213566,-13820213,24822830,-6146567,-26767480,7525079 },
+ },
+ {
+ { -23066649,-13985623,16133487,-7896178,-3389565,778788,-910336,-2782495,-19386633,11994101 },
+ { 21691500,-13624626,-641331,-14367021,3285881,-3483596,-25064666,9718258,-7477437,13381418 },
+ { 18445390,-4202236,14979846,11622458,-1727110,-3582980,23111648,-6375247,28535282,15779576 },
+ },
+ {
+ { 30098053,3089662,-9234387,16662135,-21306940,11308411,-14068454,12021730,9955285,-16303356 },
+ { 9734894,-14576830,-7473633,-9138735,2060392,11313496,-18426029,9924399,20194861,13380996 },
+ { -26378102,-7965207,-22167821,15789297,-18055342,-6168792,-1984914,15707771,26342023,10146099 },
+ },
+},
+{
+ {
+ { -26016874,-219943,21339191,-41388,19745256,-2878700,-29637280,2227040,21612326,-545728 },
+ { -13077387,1184228,23562814,-5970442,-20351244,-6348714,25764461,12243797,-20856566,11649658 },
+ { -10031494,11262626,27384172,2271902,26947504,-15997771,39944,6114064,33514190,2333242 },
+ },
+ {
+ { -21433588,-12421821,8119782,7219913,-21830522,-9016134,-6679750,-12670638,24350578,-13450001 },
+ { -4116307,-11271533,-23886186,4843615,-30088339,690623,-31536088,-10406836,8317860,12352766 },
+ { 18200138,-14475911,-33087759,-2696619,-23702521,-9102511,-23552096,-2287550,20712163,6719373 },
+ },
+ {
+ { 26656208,6075253,-7858556,1886072,-28344043,4262326,11117530,-3763210,26224235,-3297458 },
+ { -17168938,-14854097,-3395676,-16369877,-19954045,14050420,21728352,9493610,18620611,-16428628 },
+ { -13323321,13325349,11432106,5964811,18609221,6062965,-5269471,-9725556,-30701573,-16479657 },
+ },
+ {
+ { -23860538,-11233159,26961357,1640861,-32413112,-16737940,12248509,-5240639,13735342,1934062 },
+ { 25089769,6742589,17081145,-13406266,21909293,-16067981,-15136294,-3765346,-21277997,5473616 },
+ { 31883677,-7961101,1083432,-11572403,22828471,13290673,-7125085,12469656,29111212,-5451014 },
+ },
+ {
+ { 24244947,-15050407,-26262976,2791540,-14997599,16666678,24367466,6388839,-10295587,452383 },
+ { -25640782,-3417841,5217916,16224624,19987036,-4082269,-24236251,-5915248,15766062,8407814 },
+ { -20406999,13990231,15495425,16395525,5377168,15166495,-8917023,-4388953,-8067909,2276718 },
+ },
+ {
+ { 30157918,12924066,-17712050,9245753,19895028,3368142,-23827587,5096219,22740376,-7303417 },
+ { 2041139,-14256350,7783687,13876377,-25946985,-13352459,24051124,13742383,-15637599,13295222 },
+ { 33338237,-8505733,12532113,7977527,9106186,-1715251,-17720195,-4612972,-4451357,-14669444 },
+ },
+ {
+ { -20045281,5454097,-14346548,6447146,28862071,1883651,-2469266,-4141880,7770569,9620597 },
+ { 23208068,7979712,33071466,8149229,1758231,-10834995,30945528,-1694323,-33502340,-14767970 },
+ { 1439958,-16270480,-1079989,-793782,4625402,10647766,-5043801,1220118,30494170,-11440799 },
+ },
+ {
+ { -5037580,-13028295,-2970559,-3061767,15640974,-6701666,-26739026,926050,-1684339,-13333647 },
+ { 13908495,-3549272,30919928,-6273825,-21521863,7989039,9021034,9078865,3353509,4033511 },
+ { -29663431,-15113610,32259991,-344482,24295849,-12912123,23161163,8839127,27485041,7356032 },
+ },
+},
+{
+ {
+ { 9661027,705443,11980065,-5370154,-1628543,14661173,-6346142,2625015,28431036,-16771834 },
+ { -23839233,-8311415,-25945511,7480958,-17681669,-8354183,-22545972,14150565,15970762,4099461 },
+ { 29262576,16756590,26350592,-8793563,8529671,-11208050,13617293,-9937143,11465739,8317062 },
+ },
+ {
+ { -25493081,-6962928,32500200,-9419051,-23038724,-2302222,14898637,3848455,20969334,-5157516 },
+ { -20384450,-14347713,-18336405,13884722,-33039454,2842114,-21610826,-3649888,11177095,14989547 },
+ { -24496721,-11716016,16959896,2278463,12066309,10137771,13515641,2581286,-28487508,9930240 },
+ },
+ {
+ { -17751622,-2097826,16544300,-13009300,-15914807,-14949081,18345767,-13403753,16291481,-5314038 },
+ { -33229194,2553288,32678213,9875984,8534129,6889387,-9676774,6957617,4368891,9788741 },
+ { 16660756,7281060,-10830758,12911820,20108584,-8101676,-21722536,-8613148,16250552,-11111103 },
+ },
+ {
+ { -19765507,2390526,-16551031,14161980,1905286,6414907,4689584,10604807,-30190403,4782747 },
+ { -1354539,14736941,-7367442,-13292886,7710542,-14155590,-9981571,4383045,22546403,437323 },
+ { 31665577,-12180464,-16186830,1491339,-18368625,3294682,27343084,2786261,-30633590,-14097016 },
+ },
+ {
+ { -14467279,-683715,-33374107,7448552,19294360,14334329,-19690631,2355319,-19284671,-6114373 },
+ { 15121312,-15796162,6377020,-6031361,-10798111,-12957845,18952177,15496498,-29380133,11754228 },
+ { -2637277,-13483075,8488727,-14303896,12728761,-1622493,7141596,11724556,22761615,-10134141 },
+ },
+ {
+ { 16918416,11729663,-18083579,3022987,-31015732,-13339659,-28741185,-12227393,32851222,11717399 },
+ { 11166634,7338049,-6722523,4531520,-29468672,-7302055,31474879,3483633,-1193175,-4030831 },
+ { -185635,9921305,31456609,-13536438,-12013818,13348923,33142652,6546660,-19985279,-3948376 },
+ },
+ {
+ { -32460596,11266712,-11197107,-7899103,31703694,3855903,-8537131,-12833048,-30772034,-15486313 },
+ { -18006477,12709068,3991746,-6479188,-21491523,-10550425,-31135347,-16049879,10928917,3011958 },
+ { -6957757,-15594337,31696059,334240,29576716,14796075,-30831056,-12805180,18008031,10258577 },
+ },
+ {
+ { -22448644,15655569,7018479,-4410003,-30314266,-1201591,-1853465,1367120,25127874,6671743 },
+ { 29701166,-14373934,-10878120,9279288,-17568,13127210,21382910,11042292,25838796,4642684 },
+ { -20430234,14955537,-24126347,8124619,-5369288,-5990470,30468147,-13900640,18423289,4177476 },
+ },
+},
diff --git a/libmariadb/plugins/auth/ref10/base2.h b/libmariadb/plugins/auth/ref10/base2.h
new file mode 100644
index 00000000..8c538440
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/base2.h
@@ -0,0 +1,40 @@
+ {
+ { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
+ { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
+ { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
+ },
+ {
+ { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
+ { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
+ { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
+ },
+ {
+ { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
+ { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
+ { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
+ },
+ {
+ { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
+ { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
+ { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
+ },
+ {
+ { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 },
+ { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 },
+ { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 },
+ },
+ {
+ { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 },
+ { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 },
+ { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 },
+ },
+ {
+ { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 },
+ { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 },
+ { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 },
+ },
+ {
+ { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 },
+ { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 },
+ { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 },
+ },
diff --git a/libmariadb/plugins/auth/ref10/crypto_hash_sha512.h b/libmariadb/plugins/auth/ref10/crypto_hash_sha512.h
new file mode 100644
index 00000000..c023f30f
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_hash_sha512.h
@@ -0,0 +1,7 @@
+#if defined(MYSQL_CLIENT) || defined(LIBMARIADB)
+#include <ma_crypt.h>
+#define crypto_hash_sha512(DST,SRC,SLEN) ma_hash(MA_HASH_SHA512, SRC, SLEN, DST)
+#else
+#include <mysql/service_sha2.h>
+#define crypto_hash_sha512(DST,SRC,SLEN) my_sha512(DST,(char*)(SRC),SLEN)
+#endif
diff --git a/libmariadb/plugins/auth/ref10/crypto_int32.h b/libmariadb/plugins/auth/ref10/crypto_int32.h
new file mode 100644
index 00000000..642fca05
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_int32.h
@@ -0,0 +1,5 @@
+#include <stdint.h>
+#include <sys/types.h>
+typedef int32_t crypto_int32;
+
+#define select ed25519_select
diff --git a/libmariadb/plugins/auth/ref10/crypto_int64.h b/libmariadb/plugins/auth/ref10/crypto_int64.h
new file mode 100644
index 00000000..a308e406
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_int64.h
@@ -0,0 +1,5 @@
+#include <stdint.h>
+#include <sys/types.h>
+typedef int64_t crypto_int64;
+
+#define select ed25519_select
diff --git a/libmariadb/plugins/auth/ref10/crypto_sign.h b/libmariadb/plugins/auth/ref10/crypto_sign.h
new file mode 100644
index 00000000..5f9b3437
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_sign.h
@@ -0,0 +1,13 @@
+int crypto_sign_keypair(
+ unsigned char *pk,
+ unsigned char *pw, unsigned long long pwlen
+);
+int ma_crypto_sign(
+ unsigned char *sm,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *pw, unsigned long long pwlen
+);
+int crypto_sign_open(
+ unsigned char *sm, unsigned long long smlen,
+ const unsigned char *pk
+);
diff --git a/libmariadb/plugins/auth/ref10/crypto_uint32.h b/libmariadb/plugins/auth/ref10/crypto_uint32.h
new file mode 100644
index 00000000..ab2977ca
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_uint32.h
@@ -0,0 +1,5 @@
+#include <stdint.h>
+#include <sys/types.h>
+typedef uint32_t crypto_uint32;
+
+#define select ed25519_select
diff --git a/libmariadb/plugins/auth/ref10/crypto_uint64.h b/libmariadb/plugins/auth/ref10/crypto_uint64.h
new file mode 100644
index 00000000..029c6819
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_uint64.h
@@ -0,0 +1,5 @@
+#include <stdint.h>
+#include <sys/types.h>
+typedef uint64_t crypto_uint64;
+
+#define select ed25519_select
diff --git a/libmariadb/plugins/auth/ref10/crypto_verify.h b/libmariadb/plugins/auth/ref10/crypto_verify.h
new file mode 100644
index 00000000..33e11b1e
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_verify.h
@@ -0,0 +1 @@
+int crypto_verify(const unsigned char *x,const unsigned char *y);
diff --git a/libmariadb/plugins/auth/ref10/crypto_verify_32.h b/libmariadb/plugins/auth/ref10/crypto_verify_32.h
new file mode 100644
index 00000000..d8235b75
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/crypto_verify_32.h
@@ -0,0 +1,2 @@
+#define crypto_verify_32 crypto_verify
+int crypto_verify(const unsigned char *x,const unsigned char *y);
diff --git a/libmariadb/plugins/auth/ref10/d.h b/libmariadb/plugins/auth/ref10/d.h
new file mode 100644
index 00000000..e25f5783
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/d.h
@@ -0,0 +1 @@
+-10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116
diff --git a/libmariadb/plugins/auth/ref10/d2.h b/libmariadb/plugins/auth/ref10/d2.h
new file mode 100644
index 00000000..01aaec75
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/d2.h
@@ -0,0 +1 @@
+-21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199
diff --git a/libmariadb/plugins/auth/ref10/fe.h b/libmariadb/plugins/auth/ref10/fe.h
new file mode 100644
index 00000000..60c308ba
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe.h
@@ -0,0 +1,56 @@
+#ifndef FE_H
+#define FE_H
+
+#include "crypto_int32.h"
+
+typedef crypto_int32 fe[10];
+
+/*
+fe means field element.
+Here the field is \Z/(2^255-19).
+An element t, entries t[0]...t[9], represents the integer
+t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
+Bounds on each t[i] vary depending on context.
+*/
+
+#define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes
+#define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes
+#define fe_copy crypto_sign_ed25519_ref10_fe_copy
+#define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero
+#define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative
+#define fe_0 crypto_sign_ed25519_ref10_fe_0
+#define fe_1 crypto_sign_ed25519_ref10_fe_1
+#define fe_cswap crypto_sign_ed25519_ref10_fe_cswap
+#define fe_cmov crypto_sign_ed25519_ref10_fe_cmov
+#define fe_add crypto_sign_ed25519_ref10_fe_add
+#define fe_sub crypto_sign_ed25519_ref10_fe_sub
+#define fe_neg crypto_sign_ed25519_ref10_fe_neg
+#define fe_mul crypto_sign_ed25519_ref10_fe_mul
+#define fe_sq crypto_sign_ed25519_ref10_fe_sq
+#define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2
+#define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666
+#define fe_invert crypto_sign_ed25519_ref10_fe_invert
+#define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523
+
+extern void fe_frombytes(fe,const unsigned char *);
+extern void fe_tobytes(unsigned char *,const fe);
+
+extern void fe_copy(fe,const fe);
+extern int fe_isnonzero(const fe);
+extern int fe_isnegative(const fe);
+extern void fe_0(fe);
+extern void fe_1(fe);
+extern void fe_cswap(fe,fe,unsigned int);
+extern void fe_cmov(fe,const fe,unsigned int);
+
+extern void fe_add(fe,const fe,const fe);
+extern void fe_sub(fe,const fe,const fe);
+extern void fe_neg(fe,const fe);
+extern void fe_mul(fe,const fe,const fe);
+extern void fe_sq(fe,const fe);
+extern void fe_sq2(fe,const fe);
+extern void fe_mul121666(fe,const fe);
+extern void fe_invert(fe,const fe);
+extern void fe_pow22523(fe,const fe);
+
+#endif
diff --git a/libmariadb/plugins/auth/ref10/fe_0.c b/libmariadb/plugins/auth/ref10/fe_0.c
new file mode 100644
index 00000000..ec879d73
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_0.c
@@ -0,0 +1,19 @@
+#include "fe.h"
+
+/*
+h = 0
+*/
+
+void fe_0(fe h)
+{
+ h[0] = 0;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+ h[4] = 0;
+ h[5] = 0;
+ h[6] = 0;
+ h[7] = 0;
+ h[8] = 0;
+ h[9] = 0;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_1.c b/libmariadb/plugins/auth/ref10/fe_1.c
new file mode 100644
index 00000000..8cf77848
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_1.c
@@ -0,0 +1,19 @@
+#include "fe.h"
+
+/*
+h = 1
+*/
+
+void fe_1(fe h)
+{
+ h[0] = 1;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+ h[4] = 0;
+ h[5] = 0;
+ h[6] = 0;
+ h[7] = 0;
+ h[8] = 0;
+ h[9] = 0;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_add.c b/libmariadb/plugins/auth/ref10/fe_add.c
new file mode 100644
index 00000000..e6a81da2
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_add.c
@@ -0,0 +1,57 @@
+#include "fe.h"
+
+/*
+h = f + g
+Can overlap h with f or g.
+
+Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+
+Postconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+void fe_add(fe h,const fe f,const fe g)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 h0 = f0 + g0;
+ crypto_int32 h1 = f1 + g1;
+ crypto_int32 h2 = f2 + g2;
+ crypto_int32 h3 = f3 + g3;
+ crypto_int32 h4 = f4 + g4;
+ crypto_int32 h5 = f5 + g5;
+ crypto_int32 h6 = f6 + g6;
+ crypto_int32 h7 = f7 + g7;
+ crypto_int32 h8 = f8 + g8;
+ crypto_int32 h9 = f9 + g9;
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_cmov.c b/libmariadb/plugins/auth/ref10/fe_cmov.c
new file mode 100644
index 00000000..8ca584fb
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_cmov.c
@@ -0,0 +1,63 @@
+#include "fe.h"
+
+/*
+Replace (f,g) with (g,g) if b == 1;
+replace (f,g) with (f,g) if b == 0.
+
+Preconditions: b in {0,1}.
+*/
+
+void fe_cmov(fe f,const fe g,unsigned int b)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 x0 = f0 ^ g0;
+ crypto_int32 x1 = f1 ^ g1;
+ crypto_int32 x2 = f2 ^ g2;
+ crypto_int32 x3 = f3 ^ g3;
+ crypto_int32 x4 = f4 ^ g4;
+ crypto_int32 x5 = f5 ^ g5;
+ crypto_int32 x6 = f6 ^ g6;
+ crypto_int32 x7 = f7 ^ g7;
+ crypto_int32 x8 = f8 ^ g8;
+ crypto_int32 x9 = f9 ^ g9;
+ b = -b;
+ x0 &= b;
+ x1 &= b;
+ x2 &= b;
+ x3 &= b;
+ x4 &= b;
+ x5 &= b;
+ x6 &= b;
+ x7 &= b;
+ x8 &= b;
+ x9 &= b;
+ f[0] = f0 ^ x0;
+ f[1] = f1 ^ x1;
+ f[2] = f2 ^ x2;
+ f[3] = f3 ^ x3;
+ f[4] = f4 ^ x4;
+ f[5] = f5 ^ x5;
+ f[6] = f6 ^ x6;
+ f[7] = f7 ^ x7;
+ f[8] = f8 ^ x8;
+ f[9] = f9 ^ x9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_copy.c b/libmariadb/plugins/auth/ref10/fe_copy.c
new file mode 100644
index 00000000..9c5bf865
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_copy.c
@@ -0,0 +1,29 @@
+#include "fe.h"
+
+/*
+h = f
+*/
+
+void fe_copy(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ h[0] = f0;
+ h[1] = f1;
+ h[2] = f2;
+ h[3] = f3;
+ h[4] = f4;
+ h[5] = f5;
+ h[6] = f6;
+ h[7] = f7;
+ h[8] = f8;
+ h[9] = f9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_frombytes.c b/libmariadb/plugins/auth/ref10/fe_frombytes.c
new file mode 100644
index 00000000..5c179174
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_frombytes.c
@@ -0,0 +1,73 @@
+#include "fe.h"
+#include "crypto_int64.h"
+#include "crypto_uint64.h"
+
+static crypto_uint64 load_3(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ return result;
+}
+
+static crypto_uint64 load_4(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ result |= ((crypto_uint64) in[3]) << 24;
+ return result;
+}
+
+/*
+Ignores top bit of h.
+*/
+
+void fe_frombytes(fe h,const unsigned char *s)
+{
+ crypto_int64 h0 = load_4(s);
+ crypto_int64 h1 = load_3(s + 4) << 6;
+ crypto_int64 h2 = load_3(s + 7) << 5;
+ crypto_int64 h3 = load_3(s + 10) << 3;
+ crypto_int64 h4 = load_3(s + 13) << 2;
+ crypto_int64 h5 = load_4(s + 16);
+ crypto_int64 h6 = load_3(s + 20) << 7;
+ crypto_int64 h7 = load_3(s + 23) << 5;
+ crypto_int64 h8 = load_3(s + 26) << 4;
+ crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_invert.c b/libmariadb/plugins/auth/ref10/fe_invert.c
new file mode 100644
index 00000000..bcfdb8ff
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_invert.c
@@ -0,0 +1,14 @@
+#include "fe.h"
+
+void fe_invert(fe out,const fe z)
+{
+ fe t0;
+ fe t1;
+ fe t2;
+ fe t3;
+ int i;
+
+#include "pow225521.h"
+
+ return;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_isnegative.c b/libmariadb/plugins/auth/ref10/fe_isnegative.c
new file mode 100644
index 00000000..3b2c8b8d
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_isnegative.c
@@ -0,0 +1,16 @@
+#include "fe.h"
+
+/*
+return 1 if f is in {1,3,5,...,q-2}
+return 0 if f is in {0,2,4,...,q-1}
+
+Preconditions:
+ |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+int fe_isnegative(const fe f)
+{
+ unsigned char s[32];
+ fe_tobytes(s,f);
+ return s[0] & 1;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_isnonzero.c b/libmariadb/plugins/auth/ref10/fe_isnonzero.c
new file mode 100644
index 00000000..47568001
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_isnonzero.c
@@ -0,0 +1,19 @@
+#include "fe.h"
+#include "crypto_verify_32.h"
+
+/*
+return 1 if f == 0
+return 0 if f != 0
+
+Preconditions:
+ |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+static const unsigned char zero[32];
+
+int fe_isnonzero(const fe f)
+{
+ unsigned char s[32];
+ fe_tobytes(s,f);
+ return crypto_verify_32(s,zero);
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_mul.c b/libmariadb/plugins/auth/ref10/fe_mul.c
new file mode 100644
index 00000000..26ca8b36
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_mul.c
@@ -0,0 +1,253 @@
+#include "fe.h"
+#include "crypto_int64.h"
+
+/*
+h = f * g
+Can overlap h with f or g.
+
+Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+
+Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+*/
+
+/*
+Notes on implementation strategy:
+
+Using schoolbook multiplication.
+Karatsuba would save a little in some cost models.
+
+Most multiplications by 2 and 19 are 32-bit precomputations;
+cheaper than 64-bit postcomputations.
+
+There is one remaining multiplication by 19 in the carry chain;
+one *19 precomputation can be merged into this,
+but the resulting data flow is considerably less clean.
+
+There are 12 carries below.
+10 of them are 2-way parallelizable and vectorizable.
+Can get away with 11 carries, but then data flow is much deeper.
+
+With tighter constraints on inputs can squeeze carries into int32.
+*/
+
+void fe_mul(fe h,const fe f,const fe g)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 g1_19 = 19 * g1; /* 1.959375*2^29 */
+ crypto_int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
+ crypto_int32 g3_19 = 19 * g3;
+ crypto_int32 g4_19 = 19 * g4;
+ crypto_int32 g5_19 = 19 * g5;
+ crypto_int32 g6_19 = 19 * g6;
+ crypto_int32 g7_19 = 19 * g7;
+ crypto_int32 g8_19 = 19 * g8;
+ crypto_int32 g9_19 = 19 * g9;
+ crypto_int32 f1_2 = 2 * f1;
+ crypto_int32 f3_2 = 2 * f3;
+ crypto_int32 f5_2 = 2 * f5;
+ crypto_int32 f7_2 = 2 * f7;
+ crypto_int32 f9_2 = 2 * f9;
+ crypto_int64 f0g0 = f0 * (crypto_int64) g0;
+ crypto_int64 f0g1 = f0 * (crypto_int64) g1;
+ crypto_int64 f0g2 = f0 * (crypto_int64) g2;
+ crypto_int64 f0g3 = f0 * (crypto_int64) g3;
+ crypto_int64 f0g4 = f0 * (crypto_int64) g4;
+ crypto_int64 f0g5 = f0 * (crypto_int64) g5;
+ crypto_int64 f0g6 = f0 * (crypto_int64) g6;
+ crypto_int64 f0g7 = f0 * (crypto_int64) g7;
+ crypto_int64 f0g8 = f0 * (crypto_int64) g8;
+ crypto_int64 f0g9 = f0 * (crypto_int64) g9;
+ crypto_int64 f1g0 = f1 * (crypto_int64) g0;
+ crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1;
+ crypto_int64 f1g2 = f1 * (crypto_int64) g2;
+ crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3;
+ crypto_int64 f1g4 = f1 * (crypto_int64) g4;
+ crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5;
+ crypto_int64 f1g6 = f1 * (crypto_int64) g6;
+ crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7;
+ crypto_int64 f1g8 = f1 * (crypto_int64) g8;
+ crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19;
+ crypto_int64 f2g0 = f2 * (crypto_int64) g0;
+ crypto_int64 f2g1 = f2 * (crypto_int64) g1;
+ crypto_int64 f2g2 = f2 * (crypto_int64) g2;
+ crypto_int64 f2g3 = f2 * (crypto_int64) g3;
+ crypto_int64 f2g4 = f2 * (crypto_int64) g4;
+ crypto_int64 f2g5 = f2 * (crypto_int64) g5;
+ crypto_int64 f2g6 = f2 * (crypto_int64) g6;
+ crypto_int64 f2g7 = f2 * (crypto_int64) g7;
+ crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19;
+ crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19;
+ crypto_int64 f3g0 = f3 * (crypto_int64) g0;
+ crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1;
+ crypto_int64 f3g2 = f3 * (crypto_int64) g2;
+ crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3;
+ crypto_int64 f3g4 = f3 * (crypto_int64) g4;
+ crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5;
+ crypto_int64 f3g6 = f3 * (crypto_int64) g6;
+ crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19;
+ crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19;
+ crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19;
+ crypto_int64 f4g0 = f4 * (crypto_int64) g0;
+ crypto_int64 f4g1 = f4 * (crypto_int64) g1;
+ crypto_int64 f4g2 = f4 * (crypto_int64) g2;
+ crypto_int64 f4g3 = f4 * (crypto_int64) g3;
+ crypto_int64 f4g4 = f4 * (crypto_int64) g4;
+ crypto_int64 f4g5 = f4 * (crypto_int64) g5;
+ crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19;
+ crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19;
+ crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19;
+ crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19;
+ crypto_int64 f5g0 = f5 * (crypto_int64) g0;
+ crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1;
+ crypto_int64 f5g2 = f5 * (crypto_int64) g2;
+ crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3;
+ crypto_int64 f5g4 = f5 * (crypto_int64) g4;
+ crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19;
+ crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19;
+ crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19;
+ crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19;
+ crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19;
+ crypto_int64 f6g0 = f6 * (crypto_int64) g0;
+ crypto_int64 f6g1 = f6 * (crypto_int64) g1;
+ crypto_int64 f6g2 = f6 * (crypto_int64) g2;
+ crypto_int64 f6g3 = f6 * (crypto_int64) g3;
+ crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19;
+ crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19;
+ crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19;
+ crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19;
+ crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19;
+ crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19;
+ crypto_int64 f7g0 = f7 * (crypto_int64) g0;
+ crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1;
+ crypto_int64 f7g2 = f7 * (crypto_int64) g2;
+ crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19;
+ crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19;
+ crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19;
+ crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19;
+ crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19;
+ crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19;
+ crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19;
+ crypto_int64 f8g0 = f8 * (crypto_int64) g0;
+ crypto_int64 f8g1 = f8 * (crypto_int64) g1;
+ crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19;
+ crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19;
+ crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19;
+ crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19;
+ crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19;
+ crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19;
+ crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19;
+ crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19;
+ crypto_int64 f9g0 = f9 * (crypto_int64) g0;
+ crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19;
+ crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19;
+ crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19;
+ crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19;
+ crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19;
+ crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19;
+ crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19;
+ crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19;
+ crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19;
+ crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
+ crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
+ crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
+ crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
+ crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
+ crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
+ crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38;
+ crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19;
+ crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38;
+ crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ /*
+ |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
+ i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
+ |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
+ i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
+ */
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ /* |h0| <= 2^25 */
+ /* |h4| <= 2^25 */
+ /* |h1| <= 1.71*2^59 */
+ /* |h5| <= 1.71*2^59 */
+
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+ /* |h1| <= 2^24; from now on fits into int32 */
+ /* |h5| <= 2^24; from now on fits into int32 */
+ /* |h2| <= 1.41*2^60 */
+ /* |h6| <= 1.41*2^60 */
+
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+ /* |h2| <= 2^25; from now on fits into int32 unchanged */
+ /* |h6| <= 2^25; from now on fits into int32 unchanged */
+ /* |h3| <= 1.71*2^59 */
+ /* |h7| <= 1.71*2^59 */
+
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+ /* |h3| <= 2^24; from now on fits into int32 unchanged */
+ /* |h7| <= 2^24; from now on fits into int32 unchanged */
+ /* |h4| <= 1.72*2^34 */
+ /* |h8| <= 1.41*2^60 */
+
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+ /* |h4| <= 2^25; from now on fits into int32 unchanged */
+ /* |h8| <= 2^25; from now on fits into int32 unchanged */
+ /* |h5| <= 1.01*2^24 */
+ /* |h9| <= 1.71*2^59 */
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+ /* |h9| <= 2^24; from now on fits into int32 unchanged */
+ /* |h0| <= 1.1*2^39 */
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ /* |h0| <= 2^25; from now on fits into int32 unchanged */
+ /* |h1| <= 1.01*2^24 */
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_neg.c b/libmariadb/plugins/auth/ref10/fe_neg.c
new file mode 100644
index 00000000..2078ce52
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_neg.c
@@ -0,0 +1,45 @@
+#include "fe.h"
+
+/*
+h = -f
+
+Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+
+Postconditions:
+ |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+*/
+
+void fe_neg(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 h0 = -f0;
+ crypto_int32 h1 = -f1;
+ crypto_int32 h2 = -f2;
+ crypto_int32 h3 = -f3;
+ crypto_int32 h4 = -f4;
+ crypto_int32 h5 = -f5;
+ crypto_int32 h6 = -f6;
+ crypto_int32 h7 = -f7;
+ crypto_int32 h8 = -f8;
+ crypto_int32 h9 = -f9;
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_pow22523.c b/libmariadb/plugins/auth/ref10/fe_pow22523.c
new file mode 100644
index 00000000..56675a59
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_pow22523.c
@@ -0,0 +1,13 @@
+#include "fe.h"
+
+void fe_pow22523(fe out,const fe z)
+{
+ fe t0;
+ fe t1;
+ fe t2;
+ int i;
+
+#include "pow22523.h"
+
+ return;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_sq.c b/libmariadb/plugins/auth/ref10/fe_sq.c
new file mode 100644
index 00000000..8dd11984
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_sq.c
@@ -0,0 +1,149 @@
+#include "fe.h"
+#include "crypto_int64.h"
+
+/*
+h = f * f
+Can overlap h with f.
+
+Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+
+Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+*/
+
+/*
+See fe_mul.c for discussion of implementation strategy.
+*/
+
+void fe_sq(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 f0_2 = 2 * f0;
+ crypto_int32 f1_2 = 2 * f1;
+ crypto_int32 f2_2 = 2 * f2;
+ crypto_int32 f3_2 = 2 * f3;
+ crypto_int32 f4_2 = 2 * f4;
+ crypto_int32 f5_2 = 2 * f5;
+ crypto_int32 f6_2 = 2 * f6;
+ crypto_int32 f7_2 = 2 * f7;
+ crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
+ crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
+ crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
+ crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
+ crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
+ crypto_int64 f0f0 = f0 * (crypto_int64) f0;
+ crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1;
+ crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2;
+ crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3;
+ crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4;
+ crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5;
+ crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6;
+ crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7;
+ crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8;
+ crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9;
+ crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1;
+ crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2;
+ crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2;
+ crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4;
+ crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2;
+ crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6;
+ crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2;
+ crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8;
+ crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38;
+ crypto_int64 f2f2 = f2 * (crypto_int64) f2;
+ crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3;
+ crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4;
+ crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5;
+ crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6;
+ crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7;
+ crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19;
+ crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38;
+ crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3;
+ crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4;
+ crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2;
+ crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6;
+ crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38;
+ crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19;
+ crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38;
+ crypto_int64 f4f4 = f4 * (crypto_int64) f4;
+ crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5;
+ crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19;
+ crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38;
+ crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19;
+ crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38;
+ crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38;
+ crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19;
+ crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38;
+ crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19;
+ crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38;
+ crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19;
+ crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38;
+ crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19;
+ crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38;
+ crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38;
+ crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19;
+ crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38;
+ crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19;
+ crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38;
+ crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38;
+ crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
+ crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
+ crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
+ crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
+ crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38;
+ crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
+ crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
+ crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
+ crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38;
+ crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_sq2.c b/libmariadb/plugins/auth/ref10/fe_sq2.c
new file mode 100644
index 00000000..026ed3aa
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_sq2.c
@@ -0,0 +1,160 @@
+#include "fe.h"
+#include "crypto_int64.h"
+
+/*
+h = 2 * f * f
+Can overlap h with f.
+
+Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+
+Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+*/
+
+/*
+See fe_mul.c for discussion of implementation strategy.
+*/
+
+void fe_sq2(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 f0_2 = 2 * f0;
+ crypto_int32 f1_2 = 2 * f1;
+ crypto_int32 f2_2 = 2 * f2;
+ crypto_int32 f3_2 = 2 * f3;
+ crypto_int32 f4_2 = 2 * f4;
+ crypto_int32 f5_2 = 2 * f5;
+ crypto_int32 f6_2 = 2 * f6;
+ crypto_int32 f7_2 = 2 * f7;
+ crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
+ crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
+ crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
+ crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
+ crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
+ crypto_int64 f0f0 = f0 * (crypto_int64) f0;
+ crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1;
+ crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2;
+ crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3;
+ crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4;
+ crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5;
+ crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6;
+ crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7;
+ crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8;
+ crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9;
+ crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1;
+ crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2;
+ crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2;
+ crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4;
+ crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2;
+ crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6;
+ crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2;
+ crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8;
+ crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38;
+ crypto_int64 f2f2 = f2 * (crypto_int64) f2;
+ crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3;
+ crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4;
+ crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5;
+ crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6;
+ crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7;
+ crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19;
+ crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38;
+ crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3;
+ crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4;
+ crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2;
+ crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6;
+ crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38;
+ crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19;
+ crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38;
+ crypto_int64 f4f4 = f4 * (crypto_int64) f4;
+ crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5;
+ crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19;
+ crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38;
+ crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19;
+ crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38;
+ crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38;
+ crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19;
+ crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38;
+ crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19;
+ crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38;
+ crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19;
+ crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38;
+ crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19;
+ crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38;
+ crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38;
+ crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19;
+ crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38;
+ crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19;
+ crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38;
+ crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38;
+ crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
+ crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
+ crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
+ crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
+ crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38;
+ crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
+ crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
+ crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
+ crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38;
+ crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ h0 += h0;
+ h1 += h1;
+ h2 += h2;
+ h3 += h3;
+ h4 += h4;
+ h5 += h5;
+ h6 += h6;
+ h7 += h7;
+ h8 += h8;
+ h9 += h9;
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_sub.c b/libmariadb/plugins/auth/ref10/fe_sub.c
new file mode 100644
index 00000000..6e26b7df
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_sub.c
@@ -0,0 +1,57 @@
+#include "fe.h"
+
+/*
+h = f - g
+Can overlap h with f or g.
+
+Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+
+Postconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+void fe_sub(fe h,const fe f,const fe g)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 h0 = f0 - g0;
+ crypto_int32 h1 = f1 - g1;
+ crypto_int32 h2 = f2 - g2;
+ crypto_int32 h3 = f3 - g3;
+ crypto_int32 h4 = f4 - g4;
+ crypto_int32 h5 = f5 - g5;
+ crypto_int32 h6 = f6 - g6;
+ crypto_int32 h7 = f7 - g7;
+ crypto_int32 h8 = f8 - g8;
+ crypto_int32 h9 = f9 - g9;
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/libmariadb/plugins/auth/ref10/fe_tobytes.c b/libmariadb/plugins/auth/ref10/fe_tobytes.c
new file mode 100644
index 00000000..0a63baf9
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/fe_tobytes.c
@@ -0,0 +1,119 @@
+#include "fe.h"
+
+/*
+Preconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+
+Write p=2^255-19; q=floor(h/p).
+Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+
+Proof:
+ Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+ Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
+
+ Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+ Then 0<y<1.
+
+ Write r=h-pq.
+ Have 0<=r<=p-1=2^255-20.
+ Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+
+ Write x=r+19(2^-255)r+y.
+ Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+
+ Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+ so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+*/
+
+void fe_tobytes(unsigned char *s,const fe h)
+{
+ crypto_int32 h0 = h[0];
+ crypto_int32 h1 = h[1];
+ crypto_int32 h2 = h[2];
+ crypto_int32 h3 = h[3];
+ crypto_int32 h4 = h[4];
+ crypto_int32 h5 = h[5];
+ crypto_int32 h6 = h[6];
+ crypto_int32 h7 = h[7];
+ crypto_int32 h8 = h[8];
+ crypto_int32 h9 = h[9];
+ crypto_int32 q;
+ crypto_int32 carry0;
+ crypto_int32 carry1;
+ crypto_int32 carry2;
+ crypto_int32 carry3;
+ crypto_int32 carry4;
+ crypto_int32 carry5;
+ crypto_int32 carry6;
+ crypto_int32 carry7;
+ crypto_int32 carry8;
+ crypto_int32 carry9;
+
+ q = (19 * h9 + (((crypto_int32) 1) << 24)) >> 25;
+ q = (h0 + q) >> 26;
+ q = (h1 + q) >> 25;
+ q = (h2 + q) >> 26;
+ q = (h3 + q) >> 25;
+ q = (h4 + q) >> 26;
+ q = (h5 + q) >> 25;
+ q = (h6 + q) >> 26;
+ q = (h7 + q) >> 25;
+ q = (h8 + q) >> 26;
+ q = (h9 + q) >> 25;
+
+ /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
+ h0 += 19 * q;
+ /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
+
+ carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
+ carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
+ carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
+ carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
+ carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
+ carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
+ carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
+ carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
+ carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
+ carry9 = h9 >> 25; h9 -= carry9 << 25;
+ /* h10 = carry9 */
+
+ /*
+ Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ Have h0+...+2^230 h9 between 0 and 2^255-1;
+ evidently 2^255 h10-2^255 q = 0.
+ Goal: Output h0+...+2^230 h9.
+ */
+
+ s[0] = h0 >> 0;
+ s[1] = h0 >> 8;
+ s[2] = h0 >> 16;
+ s[3] = (h0 >> 24) | (h1 << 2);
+ s[4] = h1 >> 6;
+ s[5] = h1 >> 14;
+ s[6] = (h1 >> 22) | (h2 << 3);
+ s[7] = h2 >> 5;
+ s[8] = h2 >> 13;
+ s[9] = (h2 >> 21) | (h3 << 5);
+ s[10] = h3 >> 3;
+ s[11] = h3 >> 11;
+ s[12] = (h3 >> 19) | (h4 << 6);
+ s[13] = h4 >> 2;
+ s[14] = h4 >> 10;
+ s[15] = h4 >> 18;
+ s[16] = h5 >> 0;
+ s[17] = h5 >> 8;
+ s[18] = h5 >> 16;
+ s[19] = (h5 >> 24) | (h6 << 1);
+ s[20] = h6 >> 7;
+ s[21] = h6 >> 15;
+ s[22] = (h6 >> 23) | (h7 << 3);
+ s[23] = h7 >> 5;
+ s[24] = h7 >> 13;
+ s[25] = (h7 >> 21) | (h8 << 4);
+ s[26] = h8 >> 4;
+ s[27] = h8 >> 12;
+ s[28] = (h8 >> 20) | (h9 << 6);
+ s[29] = h9 >> 2;
+ s[30] = h9 >> 10;
+ s[31] = h9 >> 18;
+}
diff --git a/libmariadb/plugins/auth/ref10/ge.h b/libmariadb/plugins/auth/ref10/ge.h
new file mode 100644
index 00000000..55e95f95
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge.h
@@ -0,0 +1,95 @@
+#ifndef GE_H
+#define GE_H
+
+/*
+ge means group element.
+
+Here the group is the set of pairs (x,y) of field elements (see fe.h)
+satisfying -x^2 + y^2 = 1 + d x^2y^2
+where d = -121665/121666.
+
+Representations:
+ ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
+ ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+ ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+ ge_precomp (Duif): (y+x,y-x,2dxy)
+*/
+
+#include "fe.h"
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+} ge_p2;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p3;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p1p1;
+
+typedef struct {
+ fe yplusx;
+ fe yminusx;
+ fe xy2d;
+} ge_precomp;
+
+typedef struct {
+ fe YplusX;
+ fe YminusX;
+ fe Z;
+ fe T2d;
+} ge_cached;
+
+#define ge_frombytes_negate_vartime crypto_sign_ed25519_ref10_ge_frombytes_negate_vartime
+#define ge_tobytes crypto_sign_ed25519_ref10_ge_tobytes
+#define ge_p3_tobytes crypto_sign_ed25519_ref10_ge_p3_tobytes
+
+#define ge_p2_0 crypto_sign_ed25519_ref10_ge_p2_0
+#define ge_p3_0 crypto_sign_ed25519_ref10_ge_p3_0
+#define ge_precomp_0 crypto_sign_ed25519_ref10_ge_precomp_0
+#define ge_p3_to_p2 crypto_sign_ed25519_ref10_ge_p3_to_p2
+#define ge_p3_to_cached crypto_sign_ed25519_ref10_ge_p3_to_cached
+#define ge_p1p1_to_p2 crypto_sign_ed25519_ref10_ge_p1p1_to_p2
+#define ge_p1p1_to_p3 crypto_sign_ed25519_ref10_ge_p1p1_to_p3
+#define ge_p2_dbl crypto_sign_ed25519_ref10_ge_p2_dbl
+#define ge_p3_dbl crypto_sign_ed25519_ref10_ge_p3_dbl
+
+#define ge_madd crypto_sign_ed25519_ref10_ge_madd
+#define ge_msub crypto_sign_ed25519_ref10_ge_msub
+#define ge_add crypto_sign_ed25519_ref10_ge_add
+#define ge_sub crypto_sign_ed25519_ref10_ge_sub
+#define ge_scalarmult_base crypto_sign_ed25519_ref10_ge_scalarmult_base
+#define ge_double_scalarmult_vartime crypto_sign_ed25519_ref10_ge_double_scalarmult_vartime
+
+extern void ge_tobytes(unsigned char *,const ge_p2 *);
+extern void ge_p3_tobytes(unsigned char *,const ge_p3 *);
+extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *);
+
+extern void ge_p2_0(ge_p2 *);
+extern void ge_p3_0(ge_p3 *);
+extern void ge_precomp_0(ge_precomp *);
+extern void ge_p3_to_p2(ge_p2 *,const ge_p3 *);
+extern void ge_p3_to_cached(ge_cached *,const ge_p3 *);
+extern void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *);
+extern void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *);
+extern void ge_p2_dbl(ge_p1p1 *,const ge_p2 *);
+extern void ge_p3_dbl(ge_p1p1 *,const ge_p3 *);
+
+extern void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
+extern void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
+extern void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *);
+extern void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *);
+extern void ge_scalarmult_base(ge_p3 *,const unsigned char *);
+extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *);
+
+#endif
diff --git a/libmariadb/plugins/auth/ref10/ge_add.c b/libmariadb/plugins/auth/ref10/ge_add.c
new file mode 100644
index 00000000..da7ff5d2
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_add.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p + q
+*/
+
+void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
+{
+ fe t0;
+#include "ge_add.h"
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_add.h b/libmariadb/plugins/auth/ref10/ge_add.h
new file mode 100644
index 00000000..7481f8ff
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_add.h
@@ -0,0 +1,97 @@
+
+/* qhasm: enter ge_add */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe Z2 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ZZ */
+
+/* qhasm: fe YpX2 */
+
+/* qhasm: fe YmX2 */
+
+/* qhasm: fe T2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*YpX2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<YpX2=fe#15); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<YpX2=q->YplusX); */
+fe_mul(r->Z,r->X,q->YplusX);
+
+/* qhasm: B = YmX1*YmX2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<YmX2=fe#16); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<YmX2=q->YminusX); */
+fe_mul(r->Y,r->Y,q->YminusX);
+
+/* qhasm: C = T2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<T2d2=fe#18,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<T2d2=q->T2d,<T1=p->T); */
+fe_mul(r->T,q->T2d,p->T);
+
+/* qhasm: ZZ = Z1*Z2 */
+/* asm 1: fe_mul(>ZZ=fe#1,<Z1=fe#13,<Z2=fe#17); */
+/* asm 2: fe_mul(>ZZ=r->X,<Z1=p->Z,<Z2=q->Z); */
+fe_mul(r->X,p->Z,q->Z);
+
+/* qhasm: D = 2*ZZ */
+/* asm 1: fe_add(>D=fe#5,<ZZ=fe#1,<ZZ=fe#1); */
+/* asm 2: fe_add(>D=t0,<ZZ=r->X,<ZZ=r->X); */
+fe_add(t0,r->X,r->X);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D+C */
+/* asm 1: fe_add(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_add(r->Z,t0,r->T);
+
+/* qhasm: T3 = D-C */
+/* asm 1: fe_sub(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>T3=r->T,<D=t0,<C=r->T); */
+fe_sub(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/libmariadb/plugins/auth/ref10/ge_double_scalarmult.c b/libmariadb/plugins/auth/ref10/ge_double_scalarmult.c
new file mode 100644
index 00000000..f8bf4bf7
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_double_scalarmult.c
@@ -0,0 +1,96 @@
+#include "ge.h"
+
+static void slide(signed char *r,const unsigned char *a)
+{
+ int i;
+ int b;
+ int k;
+
+ for (i = 0;i < 256;++i)
+ r[i] = 1 & (a[i >> 3] >> (i & 7));
+
+ for (i = 0;i < 256;++i)
+ if (r[i]) {
+ for (b = 1;b <= 6 && i + b < 256;++b) {
+ if (r[i + b]) {
+ if (r[i] + (r[i + b] << b) <= 15) {
+ r[i] += r[i + b] << b; r[i + b] = 0;
+ } else if (r[i] - (r[i + b] << b) >= -15) {
+ r[i] -= r[i + b] << b;
+ for (k = i + b;k < 256;++k) {
+ if (!r[k]) {
+ r[k] = 1;
+ break;
+ }
+ r[k] = 0;
+ }
+ } else
+ break;
+ }
+ }
+ }
+
+}
+
+static ge_precomp Bi[8] = {
+#include "base2.h"
+} ;
+
+/*
+r = a * A + b * B
+where a = a[0]+256*a[1]+...+256^31 a[31].
+and b = b[0]+256*b[1]+...+256^31 b[31].
+B is the Ed25519 base point (x,4/5) with x positive.
+*/
+
+void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b)
+{
+ signed char aslide[256];
+ signed char bslide[256];
+ ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
+ ge_p1p1 t;
+ ge_p3 u;
+ ge_p3 A2;
+ int i;
+
+ slide(aslide,a);
+ slide(bslide,b);
+
+ ge_p3_to_cached(&Ai[0],A);
+ ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
+ ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
+ ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
+ ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
+ ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
+ ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
+ ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
+ ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
+
+ ge_p2_0(r);
+
+ for (i = 255;i >= 0;--i) {
+ if (aslide[i] || bslide[i]) break;
+ }
+
+ for (;i >= 0;--i) {
+ ge_p2_dbl(&t,r);
+
+ if (aslide[i] > 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_add(&t,&u,&Ai[aslide[i]/2]);
+ } else if (aslide[i] < 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
+ }
+
+ if (bslide[i] > 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_madd(&t,&u,&Bi[bslide[i]/2]);
+ } else if (bslide[i] < 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
+ }
+
+ ge_p1p1_to_p2(r,&t);
+ }
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_frombytes.c b/libmariadb/plugins/auth/ref10/ge_frombytes.c
new file mode 100644
index 00000000..1a059ee9
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_frombytes.c
@@ -0,0 +1,50 @@
+#include "ge.h"
+
+static const fe d = {
+#include "d.h"
+} ;
+
+static const fe sqrtm1 = {
+#include "sqrtm1.h"
+} ;
+
+int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s)
+{
+ fe u;
+ fe v;
+ fe v3;
+ fe vxx;
+ fe check;
+
+ fe_frombytes(h->Y,s);
+ fe_1(h->Z);
+ fe_sq(u,h->Y);
+ fe_mul(v,u,d);
+ fe_sub(u,u,h->Z); /* u = y^2-1 */
+ fe_add(v,v,h->Z); /* v = dy^2+1 */
+
+ fe_sq(v3,v);
+ fe_mul(v3,v3,v); /* v3 = v^3 */
+ fe_sq(h->X,v3);
+ fe_mul(h->X,h->X,v);
+ fe_mul(h->X,h->X,u); /* x = uv^7 */
+
+ fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
+ fe_mul(h->X,h->X,v3);
+ fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+ fe_sq(vxx,h->X);
+ fe_mul(vxx,vxx,v);
+ fe_sub(check,vxx,u); /* vx^2-u */
+ if (fe_isnonzero(check)) {
+ fe_add(check,vxx,u); /* vx^2+u */
+ if (fe_isnonzero(check)) return -1;
+ fe_mul(h->X,h->X,sqrtm1);
+ }
+
+ if (fe_isnegative(h->X) == (s[31] >> 7))
+ fe_neg(h->X,h->X);
+
+ fe_mul(h->T,h->X,h->Y);
+ return 0;
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_madd.c b/libmariadb/plugins/auth/ref10/ge_madd.c
new file mode 100644
index 00000000..62257177
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_madd.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p + q
+*/
+
+void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
+{
+ fe t0;
+#include "ge_madd.h"
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_madd.h b/libmariadb/plugins/auth/ref10/ge_madd.h
new file mode 100644
index 00000000..ecae8495
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_madd.h
@@ -0,0 +1,88 @@
+
+/* qhasm: enter ge_madd */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ypx2 */
+
+/* qhasm: fe ymx2 */
+
+/* qhasm: fe xy2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*ypx2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<ypx2=fe#15); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<ypx2=q->yplusx); */
+fe_mul(r->Z,r->X,q->yplusx);
+
+/* qhasm: B = YmX1*ymx2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<ymx2=fe#16); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<ymx2=q->yminusx); */
+fe_mul(r->Y,r->Y,q->yminusx);
+
+/* qhasm: C = xy2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<xy2d2=fe#17,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<xy2d2=q->xy2d,<T1=p->T); */
+fe_mul(r->T,q->xy2d,p->T);
+
+/* qhasm: D = 2*Z1 */
+/* asm 1: fe_add(>D=fe#5,<Z1=fe#13,<Z1=fe#13); */
+/* asm 2: fe_add(>D=t0,<Z1=p->Z,<Z1=p->Z); */
+fe_add(t0,p->Z,p->Z);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D+C */
+/* asm 1: fe_add(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_add(r->Z,t0,r->T);
+
+/* qhasm: T3 = D-C */
+/* asm 1: fe_sub(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>T3=r->T,<D=t0,<C=r->T); */
+fe_sub(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/libmariadb/plugins/auth/ref10/ge_msub.c b/libmariadb/plugins/auth/ref10/ge_msub.c
new file mode 100644
index 00000000..741ecbf1
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_msub.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p - q
+*/
+
+void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
+{
+ fe t0;
+#include "ge_msub.h"
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_msub.h b/libmariadb/plugins/auth/ref10/ge_msub.h
new file mode 100644
index 00000000..500f986b
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_msub.h
@@ -0,0 +1,88 @@
+
+/* qhasm: enter ge_msub */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ypx2 */
+
+/* qhasm: fe ymx2 */
+
+/* qhasm: fe xy2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*ymx2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<ymx2=fe#16); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<ymx2=q->yminusx); */
+fe_mul(r->Z,r->X,q->yminusx);
+
+/* qhasm: B = YmX1*ypx2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<ypx2=fe#15); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<ypx2=q->yplusx); */
+fe_mul(r->Y,r->Y,q->yplusx);
+
+/* qhasm: C = xy2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<xy2d2=fe#17,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<xy2d2=q->xy2d,<T1=p->T); */
+fe_mul(r->T,q->xy2d,p->T);
+
+/* qhasm: D = 2*Z1 */
+/* asm 1: fe_add(>D=fe#5,<Z1=fe#13,<Z1=fe#13); */
+/* asm 2: fe_add(>D=t0,<Z1=p->Z,<Z1=p->Z); */
+fe_add(t0,p->Z,p->Z);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D-C */
+/* asm 1: fe_sub(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_sub(r->Z,t0,r->T);
+
+/* qhasm: T3 = D+C */
+/* asm 1: fe_add(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>T3=r->T,<D=t0,<C=r->T); */
+fe_add(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/libmariadb/plugins/auth/ref10/ge_p1p1_to_p2.c b/libmariadb/plugins/auth/ref10/ge_p1p1_to_p2.c
new file mode 100644
index 00000000..9bb5013d
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p1p1_to_p2.c
@@ -0,0 +1,12 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p)
+{
+ fe_mul(r->X,p->X,p->T);
+ fe_mul(r->Y,p->Y,p->Z);
+ fe_mul(r->Z,p->Z,p->T);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p1p1_to_p3.c b/libmariadb/plugins/auth/ref10/ge_p1p1_to_p3.c
new file mode 100644
index 00000000..2f57b109
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p1p1_to_p3.c
@@ -0,0 +1,13 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p)
+{
+ fe_mul(r->X,p->X,p->T);
+ fe_mul(r->Y,p->Y,p->Z);
+ fe_mul(r->Z,p->Z,p->T);
+ fe_mul(r->T,p->X,p->Y);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p2_0.c b/libmariadb/plugins/auth/ref10/ge_p2_0.c
new file mode 100644
index 00000000..6191d1e6
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p2_0.c
@@ -0,0 +1,8 @@
+#include "ge.h"
+
+void ge_p2_0(ge_p2 *h)
+{
+ fe_0(h->X);
+ fe_1(h->Y);
+ fe_1(h->Z);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p2_dbl.c b/libmariadb/plugins/auth/ref10/ge_p2_dbl.c
new file mode 100644
index 00000000..2e332b5c
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p2_dbl.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = 2 * p
+*/
+
+void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p)
+{
+ fe t0;
+#include "ge_p2_dbl.h"
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p2_dbl.h b/libmariadb/plugins/auth/ref10/ge_p2_dbl.h
new file mode 100644
index 00000000..128efed9
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p2_dbl.h
@@ -0,0 +1,73 @@
+
+/* qhasm: enter ge_p2_dbl */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe AA */
+
+/* qhasm: fe XX */
+
+/* qhasm: fe YY */
+
+/* qhasm: fe B */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: XX=X1^2 */
+/* asm 1: fe_sq(>XX=fe#1,<X1=fe#11); */
+/* asm 2: fe_sq(>XX=r->X,<X1=p->X); */
+fe_sq(r->X,p->X);
+
+/* qhasm: YY=Y1^2 */
+/* asm 1: fe_sq(>YY=fe#3,<Y1=fe#12); */
+/* asm 2: fe_sq(>YY=r->Z,<Y1=p->Y); */
+fe_sq(r->Z,p->Y);
+
+/* qhasm: B=2*Z1^2 */
+/* asm 1: fe_sq2(>B=fe#4,<Z1=fe#13); */
+/* asm 2: fe_sq2(>B=r->T,<Z1=p->Z); */
+fe_sq2(r->T,p->Z);
+
+/* qhasm: A=X1+Y1 */
+/* asm 1: fe_add(>A=fe#2,<X1=fe#11,<Y1=fe#12); */
+/* asm 2: fe_add(>A=r->Y,<X1=p->X,<Y1=p->Y); */
+fe_add(r->Y,p->X,p->Y);
+
+/* qhasm: AA=A^2 */
+/* asm 1: fe_sq(>AA=fe#5,<A=fe#2); */
+/* asm 2: fe_sq(>AA=t0,<A=r->Y); */
+fe_sq(t0,r->Y);
+
+/* qhasm: Y3=YY+XX */
+/* asm 1: fe_add(>Y3=fe#2,<YY=fe#3,<XX=fe#1); */
+/* asm 2: fe_add(>Y3=r->Y,<YY=r->Z,<XX=r->X); */
+fe_add(r->Y,r->Z,r->X);
+
+/* qhasm: Z3=YY-XX */
+/* asm 1: fe_sub(>Z3=fe#3,<YY=fe#3,<XX=fe#1); */
+/* asm 2: fe_sub(>Z3=r->Z,<YY=r->Z,<XX=r->X); */
+fe_sub(r->Z,r->Z,r->X);
+
+/* qhasm: X3=AA-Y3 */
+/* asm 1: fe_sub(>X3=fe#1,<AA=fe#5,<Y3=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<AA=t0,<Y3=r->Y); */
+fe_sub(r->X,t0,r->Y);
+
+/* qhasm: T3=B-Z3 */
+/* asm 1: fe_sub(>T3=fe#4,<B=fe#4,<Z3=fe#3); */
+/* asm 2: fe_sub(>T3=r->T,<B=r->T,<Z3=r->Z); */
+fe_sub(r->T,r->T,r->Z);
+
+/* qhasm: return */
diff --git a/libmariadb/plugins/auth/ref10/ge_p3_0.c b/libmariadb/plugins/auth/ref10/ge_p3_0.c
new file mode 100644
index 00000000..401b2935
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p3_0.c
@@ -0,0 +1,9 @@
+#include "ge.h"
+
+void ge_p3_0(ge_p3 *h)
+{
+ fe_0(h->X);
+ fe_1(h->Y);
+ fe_1(h->Z);
+ fe_0(h->T);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p3_dbl.c b/libmariadb/plugins/auth/ref10/ge_p3_dbl.c
new file mode 100644
index 00000000..0d8a0591
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p3_dbl.c
@@ -0,0 +1,12 @@
+#include "ge.h"
+
+/*
+r = 2 * p
+*/
+
+void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p)
+{
+ ge_p2 q;
+ ge_p3_to_p2(&q,p);
+ ge_p2_dbl(r,&q);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p3_to_cached.c b/libmariadb/plugins/auth/ref10/ge_p3_to_cached.c
new file mode 100644
index 00000000..bde64228
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p3_to_cached.c
@@ -0,0 +1,17 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+static const fe d2 = {
+#include "d2.h"
+} ;
+
+extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p)
+{
+ fe_add(r->YplusX,p->Y,p->X);
+ fe_sub(r->YminusX,p->Y,p->X);
+ fe_copy(r->Z,p->Z);
+ fe_mul(r->T2d,p->T,d2);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p3_to_p2.c b/libmariadb/plugins/auth/ref10/ge_p3_to_p2.c
new file mode 100644
index 00000000..e532a9e4
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p3_to_p2.c
@@ -0,0 +1,12 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p)
+{
+ fe_copy(r->X,p->X);
+ fe_copy(r->Y,p->Y);
+ fe_copy(r->Z,p->Z);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_p3_tobytes.c b/libmariadb/plugins/auth/ref10/ge_p3_tobytes.c
new file mode 100644
index 00000000..21cb2fc6
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_p3_tobytes.c
@@ -0,0 +1,14 @@
+#include "ge.h"
+
+void ge_p3_tobytes(unsigned char *s,const ge_p3 *h)
+{
+ fe recip;
+ fe x;
+ fe y;
+
+ fe_invert(recip,h->Z);
+ fe_mul(x,h->X,recip);
+ fe_mul(y,h->Y,recip);
+ fe_tobytes(s,y);
+ s[31] ^= fe_isnegative(x) << 7;
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_precomp_0.c b/libmariadb/plugins/auth/ref10/ge_precomp_0.c
new file mode 100644
index 00000000..2e218861
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_precomp_0.c
@@ -0,0 +1,8 @@
+#include "ge.h"
+
+void ge_precomp_0(ge_precomp *h)
+{
+ fe_1(h->yplusx);
+ fe_1(h->yminusx);
+ fe_0(h->xy2d);
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_scalarmult_base.c b/libmariadb/plugins/auth/ref10/ge_scalarmult_base.c
new file mode 100644
index 00000000..421e4fa0
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_scalarmult_base.c
@@ -0,0 +1,105 @@
+#include "ge.h"
+#include "crypto_uint32.h"
+
+static unsigned char equal(signed char b,signed char c)
+{
+ unsigned char ub = b;
+ unsigned char uc = c;
+ unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
+ crypto_uint32 y = x; /* 0: yes; 1..255: no */
+ y -= 1; /* 4294967295: yes; 0..254: no */
+ y >>= 31; /* 1: yes; 0: no */
+ return y;
+}
+
+static unsigned char negative(signed char b)
+{
+ unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
+ x >>= 63; /* 1: yes; 0: no */
+ return x;
+}
+
+static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b)
+{
+ fe_cmov(t->yplusx,u->yplusx,b);
+ fe_cmov(t->yminusx,u->yminusx,b);
+ fe_cmov(t->xy2d,u->xy2d,b);
+}
+
+/* base[i][j] = (j+1)*256^i*B */
+static ge_precomp base[32][8] = {
+#include "base.h"
+} ;
+
+static void select(ge_precomp *t,int pos,signed char b)
+{
+ ge_precomp minust;
+ unsigned char bnegative = negative(b);
+ unsigned char babs = b - (((-bnegative) & b) << 1);
+
+ ge_precomp_0(t);
+ cmov(t,&base[pos][0],equal(babs,1));
+ cmov(t,&base[pos][1],equal(babs,2));
+ cmov(t,&base[pos][2],equal(babs,3));
+ cmov(t,&base[pos][3],equal(babs,4));
+ cmov(t,&base[pos][4],equal(babs,5));
+ cmov(t,&base[pos][5],equal(babs,6));
+ cmov(t,&base[pos][6],equal(babs,7));
+ cmov(t,&base[pos][7],equal(babs,8));
+ fe_copy(minust.yplusx,t->yminusx);
+ fe_copy(minust.yminusx,t->yplusx);
+ fe_neg(minust.xy2d,t->xy2d);
+ cmov(t,&minust,bnegative);
+}
+
+/*
+h = a * B
+where a = a[0]+256*a[1]+...+256^31 a[31]
+B is the Ed25519 base point (x,4/5) with x positive.
+
+Preconditions:
+ a[31] <= 127
+*/
+
+void ge_scalarmult_base(ge_p3 *h,const unsigned char *a)
+{
+ signed char e[64];
+ signed char carry;
+ ge_p1p1 r;
+ ge_p2 s;
+ ge_precomp t;
+ int i;
+
+ for (i = 0;i < 32;++i) {
+ e[2 * i + 0] = (a[i] >> 0) & 15;
+ e[2 * i + 1] = (a[i] >> 4) & 15;
+ }
+ /* each e[i] is between 0 and 15 */
+ /* e[63] is between 0 and 7 */
+
+ carry = 0;
+ for (i = 0;i < 63;++i) {
+ e[i] += carry;
+ carry = e[i] + 8;
+ carry >>= 4;
+ e[i] -= carry << 4;
+ }
+ e[63] += carry;
+ /* each e[i] is between -8 and 8 */
+
+ ge_p3_0(h);
+ for (i = 1;i < 64;i += 2) {
+ select(&t,i / 2,e[i]);
+ ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
+ }
+
+ ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r);
+ ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
+ ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
+ ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r);
+
+ for (i = 0;i < 64;i += 2) {
+ select(&t,i / 2,e[i]);
+ ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
+ }
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_sub.c b/libmariadb/plugins/auth/ref10/ge_sub.c
new file mode 100644
index 00000000..69f3d540
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_sub.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p - q
+*/
+
+void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
+{
+ fe t0;
+#include "ge_sub.h"
+}
diff --git a/libmariadb/plugins/auth/ref10/ge_sub.h b/libmariadb/plugins/auth/ref10/ge_sub.h
new file mode 100644
index 00000000..b4ef1f5d
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_sub.h
@@ -0,0 +1,97 @@
+
+/* qhasm: enter ge_sub */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe Z2 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ZZ */
+
+/* qhasm: fe YpX2 */
+
+/* qhasm: fe YmX2 */
+
+/* qhasm: fe T2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*YmX2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<YmX2=fe#16); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<YmX2=q->YminusX); */
+fe_mul(r->Z,r->X,q->YminusX);
+
+/* qhasm: B = YmX1*YpX2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<YpX2=fe#15); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<YpX2=q->YplusX); */
+fe_mul(r->Y,r->Y,q->YplusX);
+
+/* qhasm: C = T2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<T2d2=fe#18,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<T2d2=q->T2d,<T1=p->T); */
+fe_mul(r->T,q->T2d,p->T);
+
+/* qhasm: ZZ = Z1*Z2 */
+/* asm 1: fe_mul(>ZZ=fe#1,<Z1=fe#13,<Z2=fe#17); */
+/* asm 2: fe_mul(>ZZ=r->X,<Z1=p->Z,<Z2=q->Z); */
+fe_mul(r->X,p->Z,q->Z);
+
+/* qhasm: D = 2*ZZ */
+/* asm 1: fe_add(>D=fe#5,<ZZ=fe#1,<ZZ=fe#1); */
+/* asm 2: fe_add(>D=t0,<ZZ=r->X,<ZZ=r->X); */
+fe_add(t0,r->X,r->X);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D-C */
+/* asm 1: fe_sub(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_sub(r->Z,t0,r->T);
+
+/* qhasm: T3 = D+C */
+/* asm 1: fe_add(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>T3=r->T,<D=t0,<C=r->T); */
+fe_add(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/libmariadb/plugins/auth/ref10/ge_tobytes.c b/libmariadb/plugins/auth/ref10/ge_tobytes.c
new file mode 100644
index 00000000..31b3d33e
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/ge_tobytes.c
@@ -0,0 +1,14 @@
+#include "ge.h"
+
+void ge_tobytes(unsigned char *s,const ge_p2 *h)
+{
+ fe recip;
+ fe x;
+ fe y;
+
+ fe_invert(recip,h->Z);
+ fe_mul(x,h->X,recip);
+ fe_mul(y,h->Y,recip);
+ fe_tobytes(s,y);
+ s[31] ^= fe_isnegative(x) << 7;
+}
diff --git a/libmariadb/plugins/auth/ref10/keypair.c b/libmariadb/plugins/auth/ref10/keypair.c
new file mode 100644
index 00000000..64000838
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/keypair.c
@@ -0,0 +1,23 @@
+#include <string.h>
+#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"
+#include "ge.h"
+
+int crypto_sign_keypair(
+ unsigned char *pk,
+ unsigned char *pw, unsigned long long pwlen
+)
+{
+ unsigned char az[64];
+ ge_p3 A;
+
+ crypto_hash_sha512(az,pw,pwlen);
+ az[0] &= 248;
+ az[31] &= 63;
+ az[31] |= 64;
+
+ ge_scalarmult_base(&A,az);
+ ge_p3_tobytes(pk,&A);
+
+ return 0;
+}
diff --git a/libmariadb/plugins/auth/ref10/open.c b/libmariadb/plugins/auth/ref10/open.c
new file mode 100644
index 00000000..7362b681
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/open.c
@@ -0,0 +1,36 @@
+#include <string.h>
+#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_32.h"
+#include "ge.h"
+#include "sc.h"
+
+int crypto_sign_open(
+ unsigned char *sm, unsigned long long smlen,
+ const unsigned char *pk
+)
+{
+ unsigned char scopy[32];
+ unsigned char h[64];
+ unsigned char rcheck[32];
+ ge_p3 A;
+ ge_p2 R;
+
+ if (smlen < 64) goto badsig;
+ if (sm[63] & 224) goto badsig;
+ if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig;
+
+ memmove(scopy,sm + 32,32);
+
+ memmove(sm + 32,pk,32);
+ crypto_hash_sha512(h,sm,smlen);
+ sc_reduce(h);
+
+ ge_double_scalarmult_vartime(&R,h,&A,scopy);
+ ge_tobytes(rcheck,&R);
+ if (crypto_verify_32(rcheck,sm) == 0)
+ return 0;
+
+badsig:
+ return -1;
+}
diff --git a/libmariadb/plugins/auth/ref10/pow22523.h b/libmariadb/plugins/auth/ref10/pow22523.h
new file mode 100644
index 00000000..d476ed14
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/pow22523.h
@@ -0,0 +1,168 @@
+
+/* qhasm: fe z1 */
+
+/* qhasm: fe z2 */
+
+/* qhasm: fe z8 */
+
+/* qhasm: fe z9 */
+
+/* qhasm: fe z11 */
+
+/* qhasm: fe z22 */
+
+/* qhasm: fe z_5_0 */
+
+/* qhasm: fe z_10_5 */
+
+/* qhasm: fe z_10_0 */
+
+/* qhasm: fe z_20_10 */
+
+/* qhasm: fe z_20_0 */
+
+/* qhasm: fe z_40_20 */
+
+/* qhasm: fe z_40_0 */
+
+/* qhasm: fe z_50_10 */
+
+/* qhasm: fe z_50_0 */
+
+/* qhasm: fe z_100_50 */
+
+/* qhasm: fe z_100_0 */
+
+/* qhasm: fe z_200_100 */
+
+/* qhasm: fe z_200_0 */
+
+/* qhasm: fe z_250_50 */
+
+/* qhasm: fe z_250_0 */
+
+/* qhasm: fe z_252_2 */
+
+/* qhasm: fe z_252_3 */
+
+/* qhasm: enter pow22523 */
+
+/* qhasm: z2 = z1^2^1 */
+/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */
+/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */
+fe_sq(t0,z);
+
+/* covscan CWE-561 dead code: variable i can't be < 1
+for (i = 1;i < 1;++i) fe_sq(t0,t0);
+*/
+
+/* qhasm: z8 = z2^2^2 */
+/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */
+/* asm 2: fe_sq(>z8=t1,<z2=t0); for (i = 1;i < 2;++i) fe_sq(>z8=t1,>z8=t1); */
+fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
+
+/* qhasm: z9 = z1*z8 */
+/* asm 1: fe_mul(>z9=fe#2,<z1=fe#11,<z8=fe#2); */
+/* asm 2: fe_mul(>z9=t1,<z1=z,<z8=t1); */
+fe_mul(t1,z,t1);
+
+/* qhasm: z11 = z2*z9 */
+/* asm 1: fe_mul(>z11=fe#1,<z2=fe#1,<z9=fe#2); */
+/* asm 2: fe_mul(>z11=t0,<z2=t0,<z9=t1); */
+fe_mul(t0,t0,t1);
+
+/* qhasm: z22 = z11^2^1 */
+/* asm 1: fe_sq(>z22=fe#1,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#1,>z22=fe#1); */
+/* asm 2: fe_sq(>z22=t0,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t0,>z22=t0); */
+fe_sq(t0,t0);
+
+/* covscan CWE-561 dead code: variable i can't be < 1
+for (i = 1;i < 1;++i) fe_sq(t0,t0);
+*/
+
+/* qhasm: z_5_0 = z9*z22 */
+/* asm 1: fe_mul(>z_5_0=fe#1,<z9=fe#2,<z22=fe#1); */
+/* asm 2: fe_mul(>z_5_0=t0,<z9=t1,<z22=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_10_5 = z_5_0^2^5 */
+/* asm 1: fe_sq(>z_10_5=fe#2,<z_5_0=fe#1); for (i = 1;i < 5;++i) fe_sq(>z_10_5=fe#2,>z_10_5=fe#2); */
+/* asm 2: fe_sq(>z_10_5=t1,<z_5_0=t0); for (i = 1;i < 5;++i) fe_sq(>z_10_5=t1,>z_10_5=t1); */
+fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1);
+
+/* qhasm: z_10_0 = z_10_5*z_5_0 */
+/* asm 1: fe_mul(>z_10_0=fe#1,<z_10_5=fe#2,<z_5_0=fe#1); */
+/* asm 2: fe_mul(>z_10_0=t0,<z_10_5=t1,<z_5_0=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_20_10 = z_10_0^2^10 */
+/* asm 1: fe_sq(>z_20_10=fe#2,<z_10_0=fe#1); for (i = 1;i < 10;++i) fe_sq(>z_20_10=fe#2,>z_20_10=fe#2); */
+/* asm 2: fe_sq(>z_20_10=t1,<z_10_0=t0); for (i = 1;i < 10;++i) fe_sq(>z_20_10=t1,>z_20_10=t1); */
+fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1);
+
+/* qhasm: z_20_0 = z_20_10*z_10_0 */
+/* asm 1: fe_mul(>z_20_0=fe#2,<z_20_10=fe#2,<z_10_0=fe#1); */
+/* asm 2: fe_mul(>z_20_0=t1,<z_20_10=t1,<z_10_0=t0); */
+fe_mul(t1,t1,t0);
+
+/* qhasm: z_40_20 = z_20_0^2^20 */
+/* asm 1: fe_sq(>z_40_20=fe#3,<z_20_0=fe#2); for (i = 1;i < 20;++i) fe_sq(>z_40_20=fe#3,>z_40_20=fe#3); */
+/* asm 2: fe_sq(>z_40_20=t2,<z_20_0=t1); for (i = 1;i < 20;++i) fe_sq(>z_40_20=t2,>z_40_20=t2); */
+fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2);
+
+/* qhasm: z_40_0 = z_40_20*z_20_0 */
+/* asm 1: fe_mul(>z_40_0=fe#2,<z_40_20=fe#3,<z_20_0=fe#2); */
+/* asm 2: fe_mul(>z_40_0=t1,<z_40_20=t2,<z_20_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_50_10 = z_40_0^2^10 */
+/* asm 1: fe_sq(>z_50_10=fe#2,<z_40_0=fe#2); for (i = 1;i < 10;++i) fe_sq(>z_50_10=fe#2,>z_50_10=fe#2); */
+/* asm 2: fe_sq(>z_50_10=t1,<z_40_0=t1); for (i = 1;i < 10;++i) fe_sq(>z_50_10=t1,>z_50_10=t1); */
+fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1);
+
+/* qhasm: z_50_0 = z_50_10*z_10_0 */
+/* asm 1: fe_mul(>z_50_0=fe#1,<z_50_10=fe#2,<z_10_0=fe#1); */
+/* asm 2: fe_mul(>z_50_0=t0,<z_50_10=t1,<z_10_0=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_100_50 = z_50_0^2^50 */
+/* asm 1: fe_sq(>z_100_50=fe#2,<z_50_0=fe#1); for (i = 1;i < 50;++i) fe_sq(>z_100_50=fe#2,>z_100_50=fe#2); */
+/* asm 2: fe_sq(>z_100_50=t1,<z_50_0=t0); for (i = 1;i < 50;++i) fe_sq(>z_100_50=t1,>z_100_50=t1); */
+fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1);
+
+/* qhasm: z_100_0 = z_100_50*z_50_0 */
+/* asm 1: fe_mul(>z_100_0=fe#2,<z_100_50=fe#2,<z_50_0=fe#1); */
+/* asm 2: fe_mul(>z_100_0=t1,<z_100_50=t1,<z_50_0=t0); */
+fe_mul(t1,t1,t0);
+
+/* qhasm: z_200_100 = z_100_0^2^100 */
+/* asm 1: fe_sq(>z_200_100=fe#3,<z_100_0=fe#2); for (i = 1;i < 100;++i) fe_sq(>z_200_100=fe#3,>z_200_100=fe#3); */
+/* asm 2: fe_sq(>z_200_100=t2,<z_100_0=t1); for (i = 1;i < 100;++i) fe_sq(>z_200_100=t2,>z_200_100=t2); */
+fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2);
+
+/* qhasm: z_200_0 = z_200_100*z_100_0 */
+/* asm 1: fe_mul(>z_200_0=fe#2,<z_200_100=fe#3,<z_100_0=fe#2); */
+/* asm 2: fe_mul(>z_200_0=t1,<z_200_100=t2,<z_100_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_250_50 = z_200_0^2^50 */
+/* asm 1: fe_sq(>z_250_50=fe#2,<z_200_0=fe#2); for (i = 1;i < 50;++i) fe_sq(>z_250_50=fe#2,>z_250_50=fe#2); */
+/* asm 2: fe_sq(>z_250_50=t1,<z_200_0=t1); for (i = 1;i < 50;++i) fe_sq(>z_250_50=t1,>z_250_50=t1); */
+fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1);
+
+/* qhasm: z_250_0 = z_250_50*z_50_0 */
+/* asm 1: fe_mul(>z_250_0=fe#1,<z_250_50=fe#2,<z_50_0=fe#1); */
+/* asm 2: fe_mul(>z_250_0=t0,<z_250_50=t1,<z_50_0=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_252_2 = z_250_0^2^2 */
+/* asm 1: fe_sq(>z_252_2=fe#1,<z_250_0=fe#1); for (i = 1;i < 2;++i) fe_sq(>z_252_2=fe#1,>z_252_2=fe#1); */
+/* asm 2: fe_sq(>z_252_2=t0,<z_250_0=t0); for (i = 1;i < 2;++i) fe_sq(>z_252_2=t0,>z_252_2=t0); */
+fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0);
+
+/* qhasm: z_252_3 = z_252_2*z1 */
+/* asm 1: fe_mul(>z_252_3=fe#12,<z_252_2=fe#1,<z1=fe#11); */
+/* asm 2: fe_mul(>z_252_3=out,<z_252_2=t0,<z1=z); */
+fe_mul(out,t0,z);
+
+/* qhasm: return */
diff --git a/libmariadb/plugins/auth/ref10/pow225521.h b/libmariadb/plugins/auth/ref10/pow225521.h
new file mode 100644
index 00000000..cb889bc9
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/pow225521.h
@@ -0,0 +1,166 @@
+
+/* qhasm: fe z1 */
+
+/* qhasm: fe z2 */
+
+/* qhasm: fe z8 */
+
+/* qhasm: fe z9 */
+
+/* qhasm: fe z11 */
+
+/* qhasm: fe z22 */
+
+/* qhasm: fe z_5_0 */
+
+/* qhasm: fe z_10_5 */
+
+/* qhasm: fe z_10_0 */
+
+/* qhasm: fe z_20_10 */
+
+/* qhasm: fe z_20_0 */
+
+/* qhasm: fe z_40_20 */
+
+/* qhasm: fe z_40_0 */
+
+/* qhasm: fe z_50_10 */
+
+/* qhasm: fe z_50_0 */
+
+/* qhasm: fe z_100_50 */
+
+/* qhasm: fe z_100_0 */
+
+/* qhasm: fe z_200_100 */
+
+/* qhasm: fe z_200_0 */
+
+/* qhasm: fe z_250_50 */
+
+/* qhasm: fe z_250_0 */
+
+/* qhasm: fe z_255_5 */
+
+/* qhasm: fe z_255_21 */
+
+/* qhasm: enter pow225521 */
+
+/* qhasm: z2 = z1^2^1 */
+/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */
+/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */
+fe_sq(t0,z);
+/* covscan CWE-561 dead code: variable i can't be < 1
+for (i = 1;i < 1;++i) fe_sq(t0,t0);
+*/
+
+/* qhasm: z8 = z2^2^2 */
+/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */
+/* asm 2: fe_sq(>z8=t1,<z2=t0); for (i = 1;i < 2;++i) fe_sq(>z8=t1,>z8=t1); */
+fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
+
+/* qhasm: z9 = z1*z8 */
+/* asm 1: fe_mul(>z9=fe#2,<z1=fe#11,<z8=fe#2); */
+/* asm 2: fe_mul(>z9=t1,<z1=z,<z8=t1); */
+fe_mul(t1,z,t1);
+
+/* qhasm: z11 = z2*z9 */
+/* asm 1: fe_mul(>z11=fe#1,<z2=fe#1,<z9=fe#2); */
+/* asm 2: fe_mul(>z11=t0,<z2=t0,<z9=t1); */
+fe_mul(t0,t0,t1);
+
+/* qhasm: z22 = z11^2^1 */
+/* asm 1: fe_sq(>z22=fe#3,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#3,>z22=fe#3); */
+/* asm 2: fe_sq(>z22=t2,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t2,>z22=t2); */
+fe_sq(t2,t0);
+/* covscan CWE-561 dead code: variable i can't be < 1
+for (i = 1;i < 1;++i) fe_sq(t2,t2);
+*/
+
+/* qhasm: z_5_0 = z9*z22 */
+/* asm 1: fe_mul(>z_5_0=fe#2,<z9=fe#2,<z22=fe#3); */
+/* asm 2: fe_mul(>z_5_0=t1,<z9=t1,<z22=t2); */
+fe_mul(t1,t1,t2);
+
+/* qhasm: z_10_5 = z_5_0^2^5 */
+/* asm 1: fe_sq(>z_10_5=fe#3,<z_5_0=fe#2); for (i = 1;i < 5;++i) fe_sq(>z_10_5=fe#3,>z_10_5=fe#3); */
+/* asm 2: fe_sq(>z_10_5=t2,<z_5_0=t1); for (i = 1;i < 5;++i) fe_sq(>z_10_5=t2,>z_10_5=t2); */
+fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2);
+
+/* qhasm: z_10_0 = z_10_5*z_5_0 */
+/* asm 1: fe_mul(>z_10_0=fe#2,<z_10_5=fe#3,<z_5_0=fe#2); */
+/* asm 2: fe_mul(>z_10_0=t1,<z_10_5=t2,<z_5_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_20_10 = z_10_0^2^10 */
+/* asm 1: fe_sq(>z_20_10=fe#3,<z_10_0=fe#2); for (i = 1;i < 10;++i) fe_sq(>z_20_10=fe#3,>z_20_10=fe#3); */
+/* asm 2: fe_sq(>z_20_10=t2,<z_10_0=t1); for (i = 1;i < 10;++i) fe_sq(>z_20_10=t2,>z_20_10=t2); */
+fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2);
+
+/* qhasm: z_20_0 = z_20_10*z_10_0 */
+/* asm 1: fe_mul(>z_20_0=fe#3,<z_20_10=fe#3,<z_10_0=fe#2); */
+/* asm 2: fe_mul(>z_20_0=t2,<z_20_10=t2,<z_10_0=t1); */
+fe_mul(t2,t2,t1);
+
+/* qhasm: z_40_20 = z_20_0^2^20 */
+/* asm 1: fe_sq(>z_40_20=fe#4,<z_20_0=fe#3); for (i = 1;i < 20;++i) fe_sq(>z_40_20=fe#4,>z_40_20=fe#4); */
+/* asm 2: fe_sq(>z_40_20=t3,<z_20_0=t2); for (i = 1;i < 20;++i) fe_sq(>z_40_20=t3,>z_40_20=t3); */
+fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3);
+
+/* qhasm: z_40_0 = z_40_20*z_20_0 */
+/* asm 1: fe_mul(>z_40_0=fe#3,<z_40_20=fe#4,<z_20_0=fe#3); */
+/* asm 2: fe_mul(>z_40_0=t2,<z_40_20=t3,<z_20_0=t2); */
+fe_mul(t2,t3,t2);
+
+/* qhasm: z_50_10 = z_40_0^2^10 */
+/* asm 1: fe_sq(>z_50_10=fe#3,<z_40_0=fe#3); for (i = 1;i < 10;++i) fe_sq(>z_50_10=fe#3,>z_50_10=fe#3); */
+/* asm 2: fe_sq(>z_50_10=t2,<z_40_0=t2); for (i = 1;i < 10;++i) fe_sq(>z_50_10=t2,>z_50_10=t2); */
+fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2);
+
+/* qhasm: z_50_0 = z_50_10*z_10_0 */
+/* asm 1: fe_mul(>z_50_0=fe#2,<z_50_10=fe#3,<z_10_0=fe#2); */
+/* asm 2: fe_mul(>z_50_0=t1,<z_50_10=t2,<z_10_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_100_50 = z_50_0^2^50 */
+/* asm 1: fe_sq(>z_100_50=fe#3,<z_50_0=fe#2); for (i = 1;i < 50;++i) fe_sq(>z_100_50=fe#3,>z_100_50=fe#3); */
+/* asm 2: fe_sq(>z_100_50=t2,<z_50_0=t1); for (i = 1;i < 50;++i) fe_sq(>z_100_50=t2,>z_100_50=t2); */
+fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2);
+
+/* qhasm: z_100_0 = z_100_50*z_50_0 */
+/* asm 1: fe_mul(>z_100_0=fe#3,<z_100_50=fe#3,<z_50_0=fe#2); */
+/* asm 2: fe_mul(>z_100_0=t2,<z_100_50=t2,<z_50_0=t1); */
+fe_mul(t2,t2,t1);
+
+/* qhasm: z_200_100 = z_100_0^2^100 */
+/* asm 1: fe_sq(>z_200_100=fe#4,<z_100_0=fe#3); for (i = 1;i < 100;++i) fe_sq(>z_200_100=fe#4,>z_200_100=fe#4); */
+/* asm 2: fe_sq(>z_200_100=t3,<z_100_0=t2); for (i = 1;i < 100;++i) fe_sq(>z_200_100=t3,>z_200_100=t3); */
+fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3);
+
+/* qhasm: z_200_0 = z_200_100*z_100_0 */
+/* asm 1: fe_mul(>z_200_0=fe#3,<z_200_100=fe#4,<z_100_0=fe#3); */
+/* asm 2: fe_mul(>z_200_0=t2,<z_200_100=t3,<z_100_0=t2); */
+fe_mul(t2,t3,t2);
+
+/* qhasm: z_250_50 = z_200_0^2^50 */
+/* asm 1: fe_sq(>z_250_50=fe#3,<z_200_0=fe#3); for (i = 1;i < 50;++i) fe_sq(>z_250_50=fe#3,>z_250_50=fe#3); */
+/* asm 2: fe_sq(>z_250_50=t2,<z_200_0=t2); for (i = 1;i < 50;++i) fe_sq(>z_250_50=t2,>z_250_50=t2); */
+fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2);
+
+/* qhasm: z_250_0 = z_250_50*z_50_0 */
+/* asm 1: fe_mul(>z_250_0=fe#2,<z_250_50=fe#3,<z_50_0=fe#2); */
+/* asm 2: fe_mul(>z_250_0=t1,<z_250_50=t2,<z_50_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_255_5 = z_250_0^2^5 */
+/* asm 1: fe_sq(>z_255_5=fe#2,<z_250_0=fe#2); for (i = 1;i < 5;++i) fe_sq(>z_255_5=fe#2,>z_255_5=fe#2); */
+/* asm 2: fe_sq(>z_255_5=t1,<z_250_0=t1); for (i = 1;i < 5;++i) fe_sq(>z_255_5=t1,>z_255_5=t1); */
+fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1);
+
+/* qhasm: z_255_21 = z_255_5*z11 */
+/* asm 1: fe_mul(>z_255_21=fe#12,<z_255_5=fe#2,<z11=fe#1); */
+/* asm 2: fe_mul(>z_255_21=out,<z_255_5=t1,<z11=t0); */
+fe_mul(out,t1,t0);
+
+/* qhasm: return */
diff --git a/libmariadb/plugins/auth/ref10/sc.h b/libmariadb/plugins/auth/ref10/sc.h
new file mode 100644
index 00000000..d32ed2e8
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/sc.h
@@ -0,0 +1,15 @@
+#ifndef SC_H
+#define SC_H
+
+/*
+The set of scalars is \Z/l
+where l = 2^252 + 27742317777372353535851937790883648493.
+*/
+
+#define sc_reduce crypto_sign_ed25519_ref10_sc_reduce
+#define sc_muladd crypto_sign_ed25519_ref10_sc_muladd
+
+extern void sc_reduce(unsigned char *);
+extern void sc_muladd(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
+
+#endif
diff --git a/libmariadb/plugins/auth/ref10/sc_muladd.c b/libmariadb/plugins/auth/ref10/sc_muladd.c
new file mode 100644
index 00000000..6f1e9d02
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/sc_muladd.c
@@ -0,0 +1,368 @@
+#include "sc.h"
+#include "crypto_int64.h"
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+
+static crypto_uint64 load_3(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ return result;
+}
+
+static crypto_uint64 load_4(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ result |= ((crypto_uint64) in[3]) << 24;
+ return result;
+}
+
+/*
+Input:
+ a[0]+256*a[1]+...+256^31*a[31] = a
+ b[0]+256*b[1]+...+256^31*b[31] = b
+ c[0]+256*c[1]+...+256^31*c[31] = c
+
+Output:
+ s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+*/
+
+void sc_muladd(unsigned char *s,const unsigned char *a,const unsigned char *b,const unsigned char *c)
+{
+ crypto_int64 a0 = 2097151 & load_3(a);
+ crypto_int64 a1 = 2097151 & (load_4(a + 2) >> 5);
+ crypto_int64 a2 = 2097151 & (load_3(a + 5) >> 2);
+ crypto_int64 a3 = 2097151 & (load_4(a + 7) >> 7);
+ crypto_int64 a4 = 2097151 & (load_4(a + 10) >> 4);
+ crypto_int64 a5 = 2097151 & (load_3(a + 13) >> 1);
+ crypto_int64 a6 = 2097151 & (load_4(a + 15) >> 6);
+ crypto_int64 a7 = 2097151 & (load_3(a + 18) >> 3);
+ crypto_int64 a8 = 2097151 & load_3(a + 21);
+ crypto_int64 a9 = 2097151 & (load_4(a + 23) >> 5);
+ crypto_int64 a10 = 2097151 & (load_3(a + 26) >> 2);
+ crypto_int64 a11 = (load_4(a + 28) >> 7);
+ crypto_int64 b0 = 2097151 & load_3(b);
+ crypto_int64 b1 = 2097151 & (load_4(b + 2) >> 5);
+ crypto_int64 b2 = 2097151 & (load_3(b + 5) >> 2);
+ crypto_int64 b3 = 2097151 & (load_4(b + 7) >> 7);
+ crypto_int64 b4 = 2097151 & (load_4(b + 10) >> 4);
+ crypto_int64 b5 = 2097151 & (load_3(b + 13) >> 1);
+ crypto_int64 b6 = 2097151 & (load_4(b + 15) >> 6);
+ crypto_int64 b7 = 2097151 & (load_3(b + 18) >> 3);
+ crypto_int64 b8 = 2097151 & load_3(b + 21);
+ crypto_int64 b9 = 2097151 & (load_4(b + 23) >> 5);
+ crypto_int64 b10 = 2097151 & (load_3(b + 26) >> 2);
+ crypto_int64 b11 = (load_4(b + 28) >> 7);
+ crypto_int64 c0 = 2097151 & load_3(c);
+ crypto_int64 c1 = 2097151 & (load_4(c + 2) >> 5);
+ crypto_int64 c2 = 2097151 & (load_3(c + 5) >> 2);
+ crypto_int64 c3 = 2097151 & (load_4(c + 7) >> 7);
+ crypto_int64 c4 = 2097151 & (load_4(c + 10) >> 4);
+ crypto_int64 c5 = 2097151 & (load_3(c + 13) >> 1);
+ crypto_int64 c6 = 2097151 & (load_4(c + 15) >> 6);
+ crypto_int64 c7 = 2097151 & (load_3(c + 18) >> 3);
+ crypto_int64 c8 = 2097151 & load_3(c + 21);
+ crypto_int64 c9 = 2097151 & (load_4(c + 23) >> 5);
+ crypto_int64 c10 = 2097151 & (load_3(c + 26) >> 2);
+ crypto_int64 c11 = (load_4(c + 28) >> 7);
+ crypto_int64 s0;
+ crypto_int64 s1;
+ crypto_int64 s2;
+ crypto_int64 s3;
+ crypto_int64 s4;
+ crypto_int64 s5;
+ crypto_int64 s6;
+ crypto_int64 s7;
+ crypto_int64 s8;
+ crypto_int64 s9;
+ crypto_int64 s10;
+ crypto_int64 s11;
+ crypto_int64 s12;
+ crypto_int64 s13;
+ crypto_int64 s14;
+ crypto_int64 s15;
+ crypto_int64 s16;
+ crypto_int64 s17;
+ crypto_int64 s18;
+ crypto_int64 s19;
+ crypto_int64 s20;
+ crypto_int64 s21;
+ crypto_int64 s22;
+ crypto_int64 s23;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+ crypto_int64 carry10;
+ crypto_int64 carry11;
+ crypto_int64 carry12;
+ crypto_int64 carry13;
+ crypto_int64 carry14;
+ crypto_int64 carry15;
+ crypto_int64 carry16;
+ crypto_int64 carry17;
+ crypto_int64 carry18;
+ crypto_int64 carry19;
+ crypto_int64 carry20;
+ crypto_int64 carry21;
+ crypto_int64 carry22;
+
+ s0 = c0 + a0*b0;
+ s1 = c1 + a0*b1 + a1*b0;
+ s2 = c2 + a0*b2 + a1*b1 + a2*b0;
+ s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0;
+ s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0;
+ s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0;
+ s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0;
+ s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0;
+ s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0;
+ s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0;
+ s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0;
+ s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0;
+ s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1;
+ s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2;
+ s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3;
+ s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4;
+ s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5;
+ s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6;
+ s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7;
+ s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8;
+ s20 = a9*b11 + a10*b10 + a11*b9;
+ s21 = a10*b11 + a11*b10;
+ s22 = a11*b11;
+ s23 = 0;
+
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
+ carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21;
+ carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21;
+ carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21;
+
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
+ carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21;
+ carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21;
+ carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21;
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+ s23 = 0;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+ s22 = 0;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+ s21 = 0;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+ s20 = 0;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+ s19 = 0;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+ s18 = 0;
+
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
+
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+ s17 = 0;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+ s16 = 0;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+ s15 = 0;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+ s14 = 0;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+ s13 = 0;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
+
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
+ carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
+
+ s[0] = s0 >> 0;
+ s[1] = s0 >> 8;
+ s[2] = (s0 >> 16) | (s1 << 5);
+ s[3] = s1 >> 3;
+ s[4] = s1 >> 11;
+ s[5] = (s1 >> 19) | (s2 << 2);
+ s[6] = s2 >> 6;
+ s[7] = (s2 >> 14) | (s3 << 7);
+ s[8] = s3 >> 1;
+ s[9] = s3 >> 9;
+ s[10] = (s3 >> 17) | (s4 << 4);
+ s[11] = s4 >> 4;
+ s[12] = s4 >> 12;
+ s[13] = (s4 >> 20) | (s5 << 1);
+ s[14] = s5 >> 7;
+ s[15] = (s5 >> 15) | (s6 << 6);
+ s[16] = s6 >> 2;
+ s[17] = s6 >> 10;
+ s[18] = (s6 >> 18) | (s7 << 3);
+ s[19] = s7 >> 5;
+ s[20] = s7 >> 13;
+ s[21] = s8 >> 0;
+ s[22] = s8 >> 8;
+ s[23] = (s8 >> 16) | (s9 << 5);
+ s[24] = s9 >> 3;
+ s[25] = s9 >> 11;
+ s[26] = (s9 >> 19) | (s10 << 2);
+ s[27] = s10 >> 6;
+ s[28] = (s10 >> 14) | (s11 << 7);
+ s[29] = s11 >> 1;
+ s[30] = s11 >> 9;
+ s[31] = s11 >> 17;
+}
diff --git a/libmariadb/plugins/auth/ref10/sc_reduce.c b/libmariadb/plugins/auth/ref10/sc_reduce.c
new file mode 100644
index 00000000..d01f5a57
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/sc_reduce.c
@@ -0,0 +1,275 @@
+#include "sc.h"
+#include "crypto_int64.h"
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+
+static crypto_uint64 load_3(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ return result;
+}
+
+static crypto_uint64 load_4(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ result |= ((crypto_uint64) in[3]) << 24;
+ return result;
+}
+
+/*
+Input:
+ s[0]+256*s[1]+...+256^63*s[63] = s
+
+Output:
+ s[0]+256*s[1]+...+256^31*s[31] = s mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ Overwrites s in place.
+*/
+
+void sc_reduce(unsigned char *s)
+{
+ crypto_int64 s0 = 2097151 & load_3(s);
+ crypto_int64 s1 = 2097151 & (load_4(s + 2) >> 5);
+ crypto_int64 s2 = 2097151 & (load_3(s + 5) >> 2);
+ crypto_int64 s3 = 2097151 & (load_4(s + 7) >> 7);
+ crypto_int64 s4 = 2097151 & (load_4(s + 10) >> 4);
+ crypto_int64 s5 = 2097151 & (load_3(s + 13) >> 1);
+ crypto_int64 s6 = 2097151 & (load_4(s + 15) >> 6);
+ crypto_int64 s7 = 2097151 & (load_3(s + 18) >> 3);
+ crypto_int64 s8 = 2097151 & load_3(s + 21);
+ crypto_int64 s9 = 2097151 & (load_4(s + 23) >> 5);
+ crypto_int64 s10 = 2097151 & (load_3(s + 26) >> 2);
+ crypto_int64 s11 = 2097151 & (load_4(s + 28) >> 7);
+ crypto_int64 s12 = 2097151 & (load_4(s + 31) >> 4);
+ crypto_int64 s13 = 2097151 & (load_3(s + 34) >> 1);
+ crypto_int64 s14 = 2097151 & (load_4(s + 36) >> 6);
+ crypto_int64 s15 = 2097151 & (load_3(s + 39) >> 3);
+ crypto_int64 s16 = 2097151 & load_3(s + 42);
+ crypto_int64 s17 = 2097151 & (load_4(s + 44) >> 5);
+ crypto_int64 s18 = 2097151 & (load_3(s + 47) >> 2);
+ crypto_int64 s19 = 2097151 & (load_4(s + 49) >> 7);
+ crypto_int64 s20 = 2097151 & (load_4(s + 52) >> 4);
+ crypto_int64 s21 = 2097151 & (load_3(s + 55) >> 1);
+ crypto_int64 s22 = 2097151 & (load_4(s + 57) >> 6);
+ crypto_int64 s23 = (load_4(s + 60) >> 3);
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+ crypto_int64 carry10;
+ crypto_int64 carry11;
+ crypto_int64 carry12;
+ crypto_int64 carry13;
+ crypto_int64 carry14;
+ crypto_int64 carry15;
+ crypto_int64 carry16;
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+ s23 = 0;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+ s22 = 0;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+ s21 = 0;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+ s20 = 0;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+ s19 = 0;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+ s18 = 0;
+
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
+
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+ s17 = 0;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+ s16 = 0;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+ s15 = 0;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+ s14 = 0;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+ s13 = 0;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
+
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
+ carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
+
+ s[0] = s0 >> 0;
+ s[1] = s0 >> 8;
+ s[2] = (s0 >> 16) | (s1 << 5);
+ s[3] = s1 >> 3;
+ s[4] = s1 >> 11;
+ s[5] = (s1 >> 19) | (s2 << 2);
+ s[6] = s2 >> 6;
+ s[7] = (s2 >> 14) | (s3 << 7);
+ s[8] = s3 >> 1;
+ s[9] = s3 >> 9;
+ s[10] = (s3 >> 17) | (s4 << 4);
+ s[11] = s4 >> 4;
+ s[12] = s4 >> 12;
+ s[13] = (s4 >> 20) | (s5 << 1);
+ s[14] = s5 >> 7;
+ s[15] = (s5 >> 15) | (s6 << 6);
+ s[16] = s6 >> 2;
+ s[17] = s6 >> 10;
+ s[18] = (s6 >> 18) | (s7 << 3);
+ s[19] = s7 >> 5;
+ s[20] = s7 >> 13;
+ s[21] = s8 >> 0;
+ s[22] = s8 >> 8;
+ s[23] = (s8 >> 16) | (s9 << 5);
+ s[24] = s9 >> 3;
+ s[25] = s9 >> 11;
+ s[26] = (s9 >> 19) | (s10 << 2);
+ s[27] = s10 >> 6;
+ s[28] = (s10 >> 14) | (s11 << 7);
+ s[29] = s11 >> 1;
+ s[30] = s11 >> 9;
+ s[31] = s11 >> 17;
+}
diff --git a/libmariadb/plugins/auth/ref10/sign.c b/libmariadb/plugins/auth/ref10/sign.c
new file mode 100644
index 00000000..b4153201
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/sign.c
@@ -0,0 +1,39 @@
+#include <string.h>
+#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"
+#include "ge.h"
+#include "sc.h"
+
+int ma_crypto_sign(
+ unsigned char *sm,
+ const unsigned char *m,unsigned long long mlen,
+ const unsigned char *pw,unsigned long long pwlen
+)
+{
+ unsigned char az[64];
+ unsigned char nonce[64];
+ unsigned char hram[64];
+ ge_p3 A, R;
+
+ crypto_hash_sha512(az,pw,pwlen);
+ az[0] &= 248;
+ az[31] &= 63;
+ az[31] |= 64;
+
+ memmove(sm + 64,m,mlen);
+ memmove(sm + 32,az + 32,32);
+ crypto_hash_sha512(nonce,sm + 32,mlen + 32);
+
+ ge_scalarmult_base(&A,az);
+ ge_p3_tobytes(sm + 32,&A);
+
+ sc_reduce(nonce);
+ ge_scalarmult_base(&R,nonce);
+ ge_p3_tobytes(sm,&R);
+
+ crypto_hash_sha512(hram,sm,mlen + 64);
+ sc_reduce(hram);
+ sc_muladd(sm + 32,hram,az,nonce);
+
+ return 0;
+}
diff --git a/libmariadb/plugins/auth/ref10/sqrtm1.h b/libmariadb/plugins/auth/ref10/sqrtm1.h
new file mode 100644
index 00000000..d8caa23b
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/sqrtm1.h
@@ -0,0 +1 @@
+-32595792,-7943725,9377950,3500415,12389472,-272473,-25146209,-2005654,326686,11406482
diff --git a/libmariadb/plugins/auth/ref10/verify.c b/libmariadb/plugins/auth/ref10/verify.c
new file mode 100644
index 00000000..a0e23afe
--- /dev/null
+++ b/libmariadb/plugins/auth/ref10/verify.c
@@ -0,0 +1,40 @@
+#include "crypto_verify.h"
+
+int crypto_verify(const unsigned char *x,const unsigned char *y)
+{
+ unsigned int differentbits = 0;
+#define F(i) differentbits |= x[i] ^ y[i];
+ F(0)
+ F(1)
+ F(2)
+ F(3)
+ F(4)
+ F(5)
+ F(6)
+ F(7)
+ F(8)
+ F(9)
+ F(10)
+ F(11)
+ F(12)
+ F(13)
+ F(14)
+ F(15)
+ F(16)
+ F(17)
+ F(18)
+ F(19)
+ F(20)
+ F(21)
+ F(22)
+ F(23)
+ F(24)
+ F(25)
+ F(26)
+ F(27)
+ F(28)
+ F(29)
+ F(30)
+ F(31)
+ return (1 & ((differentbits - 1) >> 8)) - 1;
+}
diff --git a/libmariadb/plugins/auth/server_plugin.h b/libmariadb/plugins/auth/server_plugin.h
new file mode 100644
index 00000000..1348835e
--- /dev/null
+++ b/libmariadb/plugins/auth/server_plugin.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*/
+
+/* Plugin variables*/
+#include <mysql/plugin_auth.h>
+typedef enum
+{
+ PLUGIN_MECH_KERBEROS = 0,
+ PLUGIN_MECH_SPNEGO = 1,
+ PLUGIN_MECH_DEFAULT = 2
+}PLUGIN_MECH;
+
+extern unsigned long srv_mech;
+extern char *srv_principal_name;
+extern char *srv_mech_name;
+extern char *srv_keytab_path;
+/*
+ Check, with GSSAPI/SSPI username of logged on user.
+
+ Depending on use_full_name parameter, compare either full name
+ (principal name like user@real), or local name (first component)
+*/
+int plugin_init();
+int plugin_deinit();
+
+int auth_server(MYSQL_PLUGIN_VIO *vio, const char *username, size_t username_len, int use_full_name);
diff --git a/libmariadb/plugins/auth/sha256_pw.c b/libmariadb/plugins/auth/sha256_pw.c
new file mode 100644
index 00000000..79febf1a
--- /dev/null
+++ b/libmariadb/plugins/auth/sha256_pw.c
@@ -0,0 +1,356 @@
+/************************************************************************************
+ Copyright (C) 2017, 2022, MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+ *************************************************************************************/
+#ifndef _WIN32
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_WINCRYPT
+#undef HAVE_GNUTLS
+#undef HAVE_OPENSSL
+#endif
+
+#if defined(HAVE_OPENSSL) || defined(HAVE_WINCRYPT)
+
+#include <ma_global.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+#include <errmsg.h>
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <ma_common.h>
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+#if defined(HAVE_WINCRYPT)
+#include <wincrypt.h>
+#elif defined(HAVE_OPENSSL)
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#endif
+
+#define MAX_PW_LEN 1024
+
+/* function prototypes */
+static int auth_sha256_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int auth_sha256_init(char *unused1,
+ size_t unused2,
+ int unused3,
+ va_list);
+
+
+#ifndef PLUGIN_DYNAMIC
+struct st_mysql_client_plugin_AUTHENTICATION sha256_password_client_plugin=
+#else
+struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
+#endif
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ "sha256_password",
+ "Georg Richter",
+ "SHA256 Authentication Plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ auth_sha256_init,
+ NULL,
+ NULL,
+ auth_sha256_client
+};
+
+#ifdef HAVE_WINCRYPT
+static LPBYTE ma_load_pem(const char *buffer, DWORD *buffer_len)
+{
+ LPBYTE der_buffer= NULL;
+ DWORD der_buffer_length= 0;
+
+ if (buffer_len == NULL || *buffer_len == 0)
+ return NULL;
+ /* calculate the length of DER binary */
+ if (!CryptStringToBinaryA(buffer, *buffer_len, CRYPT_STRING_BASE64HEADER,
+ NULL, &der_buffer_length, NULL, NULL))
+ goto end;
+ /* allocate DER binary buffer */
+ if (!(der_buffer= (LPBYTE)LocalAlloc(0, der_buffer_length)))
+ goto end;
+ /* convert to DER binary */
+ if (!CryptStringToBinaryA(buffer, *buffer_len, CRYPT_STRING_BASE64HEADER,
+ der_buffer, &der_buffer_length, NULL, NULL))
+ goto end;
+
+ *buffer_len= der_buffer_length;
+
+ return der_buffer;
+
+end:
+ if (der_buffer)
+ LocalFree(der_buffer);
+ *buffer_len= 0;
+ return NULL;
+}
+#endif
+
+static char *load_pub_key_file(const char *filename, int *pub_key_size)
+{
+ FILE *fp= NULL;
+ char *buffer= NULL;
+ unsigned char error= 1;
+ size_t bytes_read= 0;
+ long fsize= 0;
+
+ if (!pub_key_size)
+ return NULL;
+
+ if (!(fp= fopen(filename, "r")))
+ goto end;
+
+ if (fseek(fp, 0, SEEK_END))
+ goto end;
+
+ fsize= ftell(fp);
+ if (fsize < 0)
+ goto end;
+
+ rewind(fp);
+
+ if (!(buffer= malloc(fsize + 1)))
+ goto end;
+
+ bytes_read= fread(buffer, 1, (size_t)fsize, fp);
+ if (bytes_read < (size_t)fsize)
+ goto end;
+
+ *pub_key_size= (int)bytes_read;
+
+ error= 0;
+
+end:
+ if (fp)
+ fclose(fp);
+ if (error && buffer)
+ {
+ free(buffer);
+ buffer= NULL;
+ }
+ return buffer;
+}
+
+
+static int auth_sha256_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ unsigned char *packet;
+ int packet_length;
+ int rc= CR_ERROR;
+ char passwd[MAX_PW_LEN];
+ unsigned int rsa_size;
+ unsigned int pwlen, i;
+
+#if defined(HAVE_OPENSSL)
+ EVP_PKEY *pubkey= NULL;
+ EVP_PKEY_CTX *ctx= NULL;
+ size_t outlen= 0;
+ unsigned char *rsa_enc_pw= NULL;
+ BIO *bio;
+#elif defined(HAVE_WINCRYPT)
+ unsigned char rsa_enc_pw[MAX_PW_LEN];
+ HCRYPTKEY pubkey= 0;
+ HCRYPTPROV hProv= 0;
+ LPBYTE der_buffer= NULL;
+ DWORD der_buffer_len= 0;
+ CERT_PUBLIC_KEY_INFO *publicKeyInfo= NULL;
+ DWORD ParamSize= sizeof(DWORD);
+ int publicKeyInfoLen= 0;
+#endif
+ char *filebuffer= NULL;
+
+ /* read error */
+ if ((packet_length= vio->read_packet(vio, &packet)) < 0)
+ return CR_ERROR;
+
+ if (packet_length != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ memmove(mysql->scramble_buff, packet, SCRAMBLE_LENGTH);
+ mysql->scramble_buff[SCRAMBLE_LENGTH]= 0;
+
+ /* if a tls session is active we need to send plain password */
+ if (mysql->client_flag & CLIENT_SSL)
+ {
+ if (vio->write_packet(vio, (unsigned char *)mysql->passwd, (int)strlen(mysql->passwd) + 1))
+ return CR_ERROR;
+ return CR_OK;
+ }
+
+ /* send empty packet if no password was provided */
+ if (!mysql->passwd || !mysql->passwd[0])
+ {
+ if (vio->write_packet(vio, 0, 0))
+ return CR_ERROR;
+ return CR_OK;
+ }
+
+ /* read public key file (if specified) */
+ if (mysql->options.extension &&
+ mysql->options.extension->server_public_key)
+ {
+ filebuffer= load_pub_key_file(mysql->options.extension->server_public_key,
+ &packet_length);
+ }
+
+ /* if no public key file was specified or if we couldn't read the file,
+ we ask server to send public key */
+ if (!filebuffer)
+ {
+ unsigned char buf= 1;
+ if (vio->write_packet(vio, &buf, 1))
+ return CR_ERROR;
+ if ((packet_length=vio->read_packet(vio, &packet)) == -1)
+ return CR_ERROR;
+ }
+#if defined(HAVE_OPENSSL)
+ bio= BIO_new_mem_buf(filebuffer ? (unsigned char *)filebuffer : packet,
+ packet_length);
+ if (!(pubkey= PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
+ goto error;
+ if (!(ctx= EVP_PKEY_CTX_new(pubkey, NULL)))
+ goto error;
+ if (EVP_PKEY_encrypt_init(ctx) <= 0)
+ goto error;
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
+ goto error;
+ rsa_size= EVP_PKEY_size(pubkey);
+ BIO_free(bio);
+ bio= NULL;
+ ERR_clear_error();
+#elif defined(HAVE_WINCRYPT)
+ der_buffer_len= packet_length;
+ /* Load pem and convert it to binary object. New length will be returned
+ in der_buffer_len */
+ if (!(der_buffer= ma_load_pem(filebuffer ? filebuffer : (char *)packet, &der_buffer_len)))
+ goto error;
+
+ /* Create context and load public key */
+ if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
+ der_buffer, der_buffer_len,
+ CRYPT_DECODE_ALLOC_FLAG, NULL,
+ &publicKeyInfo, (DWORD *)&publicKeyInfoLen))
+ goto error;
+ LocalFree(der_buffer);
+
+ if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ goto error;
+ if (!CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING,
+ publicKeyInfo, &pubkey))
+ goto error;
+
+ /* Get rsa_size */
+ CryptGetKeyParam(pubkey, KP_KEYLEN, (BYTE *)&rsa_size, &ParamSize, 0);
+ rsa_size /= 8;
+#endif
+ if (!pubkey)
+ return CR_ERROR;
+
+ pwlen= (unsigned int)strlen(mysql->passwd) + 1; /* include terminating zero */
+ if (pwlen > MAX_PW_LEN)
+ goto error;
+ memcpy(passwd, mysql->passwd, pwlen);
+
+ /* xor password with scramble */
+ for (i=0; i < pwlen; i++)
+ passwd[i]^= *(mysql->scramble_buff + i % SCRAMBLE_LENGTH);
+
+ /* encrypt scrambled password */
+#if defined(HAVE_OPENSSL)
+ if (EVP_PKEY_encrypt(ctx, NULL, &outlen, (unsigned char *)passwd, pwlen) <= 0)
+ goto error;
+ if (!(rsa_enc_pw= malloc(outlen)))
+ goto error;
+ if (EVP_PKEY_encrypt(ctx, rsa_enc_pw, &outlen, (unsigned char *)passwd, pwlen) <= 0)
+ goto error;
+#elif defined(HAVE_WINCRYPT)
+ if (!CryptEncrypt(pubkey, 0, TRUE, CRYPT_OAEP, (BYTE *)passwd, (DWORD *)&pwlen, MAX_PW_LEN))
+ goto error;
+ /* Windows encrypts as little-endian, while server (openssl) expects
+ big-endian, so we have to revert the string */
+ for (i= 0; i < rsa_size / 2; i++)
+ {
+ rsa_enc_pw[i]= passwd[rsa_size - 1 - i];
+ rsa_enc_pw[rsa_size - 1 - i]= passwd[i];
+ }
+#endif
+ if (vio->write_packet(vio, rsa_enc_pw, rsa_size))
+ goto error;
+
+ rc= CR_OK;
+error:
+#if defined(HAVE_OPENSSL)
+ if (pubkey)
+ EVP_PKEY_free(pubkey);
+ if (bio)
+ BIO_free(bio);
+ if (ctx)
+ EVP_PKEY_CTX_free(ctx);
+ if (rsa_enc_pw)
+ free(rsa_enc_pw);
+#elif defined(HAVE_WINCRYPT)
+ CryptReleaseContext(hProv, 0);
+ if (publicKeyInfo)
+ LocalFree(publicKeyInfo);
+#endif
+ free(filebuffer);
+ return rc;
+}
+/* }}} */
+
+/* {{{ static int auth_sha256_init */
+/*
+ Initialization routine
+
+ SYNOPSIS
+ auth_sha256_init
+ unused1
+ unused2
+ unused3
+ unused4
+
+ DESCRIPTION
+ Init function checks if the caller provides own dialog function.
+ The function name must be mariadb_auth_dialog or
+ mysql_authentication_dialog_ask. If the function cannot be found,
+ we will use owr own simple command line input.
+
+ RETURN
+ 0 success
+ */
+static int auth_sha256_init(char *unused1 __attribute__((unused)),
+ size_t unused2 __attribute__((unused)),
+ int unused3 __attribute__((unused)),
+ va_list unused4 __attribute__((unused)))
+{
+ return 0;
+}
+/* }}} */
+
+#endif /* defined(HAVE_OPENSSL) || defined(HAVE_WINCRYPT) */
diff --git a/libmariadb/plugins/auth/sspi_client.c b/libmariadb/plugins/auth/sspi_client.c
new file mode 100644
index 00000000..e257cd9d
--- /dev/null
+++ b/libmariadb/plugins/auth/sspi_client.c
@@ -0,0 +1,184 @@
+/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*/
+
+#define SECURITY_WIN32
+#include <windows.h>
+#include <sspi.h>
+#include <secext.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mysql/plugin_auth.h>
+#include <mysql.h>
+#include <ma_server_error.h>
+
+#include "sspi_common.h"
+
+extern void log_client_error(MYSQL *mysql, const char *fmt, ...);
+static void log_error(MYSQL *mysql, SECURITY_STATUS err, const char *msg)
+{
+ if (err)
+ {
+ char buf[1024];
+ sspi_errmsg(err, buf, sizeof(buf));
+ log_client_error(mysql, "SSPI client error 0x%x - %s - %s", err, msg, buf);
+ }
+ else
+ {
+ log_client_error(mysql, "SSPI client error %s", msg);
+ }
+}
+
+
+/** Client side authentication*/
+int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio)
+{
+
+ int ret;
+ CredHandle cred;
+ CtxtHandle ctxt;
+ ULONG attribs = 0;
+ TimeStamp lifetime;
+ SECURITY_STATUS sspi_err;
+
+ SecBufferDesc inbuf_desc;
+ SecBuffer inbuf;
+ SecBufferDesc outbuf_desc;
+ SecBuffer outbuf;
+ PBYTE out = NULL;
+
+ ret= CR_ERROR;
+ SecInvalidateHandle(&ctxt);
+ SecInvalidateHandle(&cred);
+
+ if (!mech || strcmp(mech, "Negotiate") != 0)
+ {
+ mech= (char *)"Kerberos";
+ }
+
+ sspi_err = AcquireCredentialsHandle(
+ NULL,
+ mech,
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &cred,
+ &lifetime);
+
+ if (SEC_ERROR(sspi_err))
+ {
+ log_error(mysql, sspi_err, "AcquireCredentialsHandle");
+ return CR_ERROR;
+ }
+
+ out = (PBYTE)malloc(SSPI_MAX_TOKEN_SIZE);
+ if (!out)
+ {
+ log_error(mysql, SEC_E_OK, "memory allocation error");
+ goto cleanup;
+ }
+
+ /* Prepare buffers */
+ inbuf_desc.ulVersion = SECBUFFER_VERSION;
+ inbuf_desc.cBuffers = 1;
+ inbuf_desc.pBuffers = &inbuf;
+ inbuf.BufferType = SECBUFFER_TOKEN;
+ inbuf.cbBuffer = 0;
+ inbuf.pvBuffer = NULL;
+
+ outbuf_desc.ulVersion = SECBUFFER_VERSION;
+ outbuf_desc.cBuffers = 1;
+ outbuf_desc.pBuffers = &outbuf;
+ outbuf.BufferType = SECBUFFER_TOKEN;
+ outbuf.pvBuffer = out;
+
+ do
+ {
+ outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE;
+ sspi_err= InitializeSecurityContext(
+ &cred,
+ SecIsValidHandle(&ctxt) ? &ctxt : NULL,
+ principal_name,
+ 0,
+ 0,
+ SECURITY_NATIVE_DREP,
+ inbuf.cbBuffer ? &inbuf_desc : NULL,
+ 0,
+ &ctxt,
+ &outbuf_desc,
+ &attribs,
+ &lifetime);
+ if (SEC_ERROR(sspi_err))
+ {
+ log_error(mysql, sspi_err, "InitializeSecurityContext");
+ goto cleanup;
+ }
+ if (sspi_err != SEC_E_OK && sspi_err != SEC_I_CONTINUE_NEEDED)
+ {
+ log_error(mysql, sspi_err, "Unexpected response from InitializeSecurityContext");
+ goto cleanup;
+ }
+
+ if (outbuf.cbBuffer)
+ {
+ /* send credential to server */
+ if (vio->write_packet(vio, (unsigned char *)outbuf.pvBuffer, outbuf.cbBuffer))
+ {
+ /* Server error packet contains detailed message. */
+ ret= CR_OK_HANDSHAKE_COMPLETE;
+ goto cleanup;
+ }
+ }
+
+ if (sspi_err == SEC_I_CONTINUE_NEEDED)
+ {
+ int len= vio->read_packet(vio, (unsigned char **)&inbuf.pvBuffer);
+ if (len <= 0)
+ {
+ /* Server side error is in the last server packet. */
+ ret= CR_OK_HANDSHAKE_COMPLETE;
+ goto cleanup;
+ }
+ inbuf.cbBuffer= len;
+ }
+ } while (sspi_err == SEC_I_CONTINUE_NEEDED);
+
+ ret= CR_OK;
+
+cleanup:
+
+ if (SecIsValidHandle(&ctxt))
+ DeleteSecurityContext(&ctxt);
+ if (SecIsValidHandle(&cred))
+ FreeCredentialsHandle(&cred);
+ free(out);
+ return ret;
+}
diff --git a/libmariadb/plugins/auth/sspi_common.h b/libmariadb/plugins/auth/sspi_common.h
new file mode 100644
index 00000000..da9159eb
--- /dev/null
+++ b/libmariadb/plugins/auth/sspi_common.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+*/
+
+#define SECURITY_WIN32
+#include <windows.h>
+#include <sspi.h>
+#include <secext.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#define SSPI_MAX_TOKEN_SIZE 50000
+#define SEC_ERROR(err) ((err) < 0)
+extern void sspi_errmsg(int err, char *buf, size_t size);
diff --git a/libmariadb/plugins/auth/sspi_errmsg.c b/libmariadb/plugins/auth/sspi_errmsg.c
new file mode 100644
index 00000000..15cb2582
--- /dev/null
+++ b/libmariadb/plugins/auth/sspi_errmsg.c
@@ -0,0 +1,169 @@
+/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
+Vladislav Vaintroub & MariaDB Corporation
+
+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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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 <windows.h>
+#include <stdio.h>
+
+#ifndef SEC_E_INVALID_PARAMETER
+#define SEC_E_INVALID_PARAMETER _HRESULT_TYPEDEF_(0x8009035D)
+#endif
+#ifndef SEC_E_DELEGATION_POLICY
+#define SEC_E_DELEGATION_POLICY _HRESULT_TYPEDEF_(0x8009035E)
+#endif
+#ifndef SEC_E_POLICY_NLTM_ONLY
+#define SEC_E_POLICY_NLTM_ONLY _HRESULT_TYPEDEF_(0x8009035F)
+#endif
+#ifndef SEC_E_NO_CONTEXT
+#define SEC_E_NO_CONTEXT _HRESULT_TYPEDEF_(0x80090361)
+#endif
+#ifndef SEC_E_PKU2U_CERT_FAILURE
+#define SEC_E_PKU2U_CERT_FAILURE _HRESULT_TYPEDEF_(0x80090362)
+#endif
+#ifndef SEC_E_MUTUAL_AUTH_FAILED
+#define SEC_E_MUTUAL_AUTH_FAILED _HRESULT_TYPEDEF_(0x80090363)
+#endif
+
+#define ERRSYM(x) {x, #x}
+static struct {
+ int error;
+ const char *sym;
+} error_symbols[] =
+{
+ ERRSYM(SEC_E_OK),
+ ERRSYM(SEC_E_INSUFFICIENT_MEMORY),
+ ERRSYM(SEC_E_INVALID_HANDLE),
+ ERRSYM(SEC_E_UNSUPPORTED_FUNCTION),
+ ERRSYM(SEC_E_TARGET_UNKNOWN),
+ ERRSYM(SEC_E_INTERNAL_ERROR),
+ ERRSYM(SEC_E_SECPKG_NOT_FOUND),
+ ERRSYM(SEC_E_NOT_OWNER),
+ ERRSYM(SEC_E_CANNOT_INSTALL),
+ ERRSYM(SEC_E_INVALID_TOKEN),
+ ERRSYM(SEC_E_CANNOT_PACK),
+ ERRSYM(SEC_E_QOP_NOT_SUPPORTED),
+ ERRSYM(SEC_E_NO_IMPERSONATION),
+ ERRSYM(SEC_E_LOGON_DENIED),
+ ERRSYM(SEC_E_UNKNOWN_CREDENTIALS),
+ ERRSYM(SEC_E_NO_CREDENTIALS),
+ ERRSYM(SEC_E_MESSAGE_ALTERED),
+ ERRSYM(SEC_E_OUT_OF_SEQUENCE),
+ ERRSYM(SEC_E_NO_AUTHENTICATING_AUTHORITY),
+ ERRSYM(SEC_E_BAD_PKGID),
+ ERRSYM(SEC_E_CONTEXT_EXPIRED),
+ ERRSYM(SEC_E_INCOMPLETE_MESSAGE),
+ ERRSYM(SEC_E_INCOMPLETE_CREDENTIALS),
+ ERRSYM(SEC_E_BUFFER_TOO_SMALL),
+ ERRSYM(SEC_E_WRONG_PRINCIPAL),
+ ERRSYM(SEC_E_TIME_SKEW),
+ ERRSYM(SEC_E_UNTRUSTED_ROOT),
+ ERRSYM(SEC_E_ILLEGAL_MESSAGE),
+ ERRSYM(SEC_E_CERT_UNKNOWN),
+ ERRSYM(SEC_E_CERT_EXPIRED),
+ ERRSYM(SEC_E_ENCRYPT_FAILURE),
+ ERRSYM(SEC_E_DECRYPT_FAILURE),
+ ERRSYM(SEC_E_ALGORITHM_MISMATCH),
+ ERRSYM(SEC_E_SECURITY_QOS_FAILED),
+ ERRSYM(SEC_E_UNFINISHED_CONTEXT_DELETED),
+ ERRSYM(SEC_E_NO_TGT_REPLY),
+ ERRSYM(SEC_E_NO_IP_ADDRESSES),
+ ERRSYM(SEC_E_WRONG_CREDENTIAL_HANDLE),
+ ERRSYM(SEC_E_CRYPTO_SYSTEM_INVALID),
+ ERRSYM(SEC_E_MAX_REFERRALS_EXCEEDED),
+ ERRSYM(SEC_E_MUST_BE_KDC),
+ ERRSYM(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED),
+ ERRSYM(SEC_E_TOO_MANY_PRINCIPALS),
+ ERRSYM(SEC_E_NO_PA_DATA),
+ ERRSYM(SEC_E_PKINIT_NAME_MISMATCH),
+ ERRSYM(SEC_E_SMARTCARD_LOGON_REQUIRED),
+ ERRSYM(SEC_E_SHUTDOWN_IN_PROGRESS),
+ ERRSYM(SEC_E_KDC_INVALID_REQUEST),
+ ERRSYM(SEC_E_KDC_UNABLE_TO_REFER),
+ ERRSYM(SEC_E_KDC_UNKNOWN_ETYPE),
+ ERRSYM(SEC_E_UNSUPPORTED_PREAUTH),
+ ERRSYM(SEC_E_DELEGATION_REQUIRED),
+ ERRSYM(SEC_E_BAD_BINDINGS),
+ ERRSYM(SEC_E_MULTIPLE_ACCOUNTS),
+ ERRSYM(SEC_E_NO_KERB_KEY),
+ ERRSYM(SEC_E_CERT_WRONG_USAGE),
+ ERRSYM(SEC_E_DOWNGRADE_DETECTED),
+ ERRSYM(SEC_E_SMARTCARD_CERT_REVOKED),
+ ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED),
+ ERRSYM(SEC_E_REVOCATION_OFFLINE_C),
+ ERRSYM(SEC_E_PKINIT_CLIENT_FAILURE),
+ ERRSYM(SEC_E_SMARTCARD_CERT_EXPIRED),
+ ERRSYM(SEC_E_NO_S4U_PROT_SUPPORT),
+ ERRSYM(SEC_E_CROSSREALM_DELEGATION_FAILURE),
+ ERRSYM(SEC_E_REVOCATION_OFFLINE_KDC),
+ ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED_KDC),
+ ERRSYM(SEC_E_KDC_CERT_EXPIRED),
+ ERRSYM(SEC_E_KDC_CERT_REVOKED),
+ ERRSYM(SEC_E_INVALID_PARAMETER),
+ ERRSYM(SEC_E_DELEGATION_POLICY),
+ ERRSYM(SEC_E_POLICY_NLTM_ONLY),
+ ERRSYM(SEC_E_NO_CONTEXT),
+ ERRSYM(SEC_E_PKU2U_CERT_FAILURE),
+ ERRSYM(SEC_E_MUTUAL_AUTH_FAILED),
+ ERRSYM(SEC_E_NO_SPM),
+ ERRSYM(SEC_E_NOT_SUPPORTED),
+ {0,0}
+};
+
+void sspi_errmsg(int err, char *buf, size_t size)
+{
+ size_t len,i;
+
+ buf[size - 1] = 0;
+ for (i= 0; error_symbols[i].sym; i++)
+ {
+ if (error_symbols[i].error == err)
+ {
+ size_t len= strlen(error_symbols[i].sym);
+ if (len + 2 < size)
+ {
+ memcpy(buf, error_symbols[i].sym, len);
+ buf[len]= ' ';
+ buf += len + 1;
+ size-= len + 1;
+ }
+ break;
+ }
+ }
+
+ len = FormatMessageA(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
+ err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ buf, (DWORD)size, NULL);
+
+ if(len > 0)
+ {
+ /* Trim trailing \n\r*/
+ char *p;
+ for(p= buf + len;p > buf && (*p == '\n' || *p=='\r' || *p == 0);p--)
+ *p= 0;
+ }
+}
diff --git a/libmariadb/plugins/compress/CMakeLists.txt b/libmariadb/plugins/compress/CMakeLists.txt
new file mode 100644
index 00000000..f6dab85d
--- /dev/null
+++ b/libmariadb/plugins/compress/CMakeLists.txt
@@ -0,0 +1,23 @@
+SET(COMPRESS_PLUGIN_DIR ${CC_SOURCE_DIR}/plugins/compress)
+
+INCLUDE_DIRECTORIES(${COMPRESS_PLUGIN_DIR})
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include)
+
+#zlib compression
+
+REGISTER_PLUGIN(TARGET zlib
+ TYPE MARIADB_CLIENT_COMPRESSION_PLUGIN
+ CONFIGURATIONS STATIC
+ DEFAULT STATIC
+ SOURCES ${COMPRESS_PLUGIN_DIR}/c_zlib.c)
+
+#zstd compression
+IF(${ZSTD_FOUND})
+ INCLUDE_DIRECTORIES(${ZSTD_INCLUDE_DIRS})
+ REGISTER_PLUGIN(TARGET zstd
+ TYPE MARIADB_CLIENT_COMPRESSION_PLUGIN
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT DYNAMIC
+ SOURCES ${COMPRESS_PLUGIN_DIR}/c_zstd.c
+ LIBRARIES ${ZSTD_LIBRARIES})
+ENDIF()
diff --git a/libmariadb/plugins/compress/c_zlib.c b/libmariadb/plugins/compress/c_zlib.c
new file mode 100644
index 00000000..a031841d
--- /dev/null
+++ b/libmariadb/plugins/compress/c_zlib.c
@@ -0,0 +1,99 @@
+/************************************************************************************
+ Copyright (C) 2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+*************************************************************************************/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <zlib.h>
+
+static ma_compress_ctx *ma_zlib_ctx_init(int compression_level)
+{
+ ma_compress_ctx *ctx;
+
+ if (!(ctx = (ma_compress_ctx *)calloc(1, sizeof(ma_compress_ctx))))
+ return NULL;
+
+ ctx->compression_level= (compression_level == COMPRESSION_LEVEL_DEFAULT) ?
+ Z_DEFAULT_COMPRESSION : compression_level;
+ return ctx;
+}
+
+static void ma_zlib_ctx_deinit(ma_compress_ctx *ctx)
+{
+ free(ctx);
+}
+
+my_bool ma_zlib_compress(ma_compress_ctx *ctx, void *dst,
+ size_t *dst_len, void *source, size_t source_len)
+{
+ int rc;
+ if (!ctx)
+ return 1;
+
+ if ((rc= compress2((Bytef *)dst, (uLongf *)dst_len, (Bytef *)source, (uLong)source_len,
+ ctx->compression_level)) != Z_OK)
+ return 1;
+ return 0;
+}
+
+my_bool ma_zlib_decompress(ma_compress_ctx *ctx, void *dst, size_t *dst_len,
+ void *source, size_t *source_len)
+{
+ int rc;
+ if (!ctx)
+ return 1;
+
+ rc= uncompress((Bytef*) dst, (uLongf *)dst_len, (Bytef*) source, (uLongf)*source_len);
+
+ if (rc != Z_OK)
+ return 1;
+
+ return 0;
+}
+
+#ifndef PLUGIN_DYNAMIC
+MARIADB_COMPRESSION_PLUGIN zlib_client_plugin=
+#else
+MARIADB_COMPRESSION_PLUGIN _mysql_client_plugin_declaration_ =
+#endif
+{
+ MARIADB_CLIENT_COMPRESSION_PLUGIN,
+ MARIADB_CLIENT_COMPRESSION_PLUGIN_INTERFACE_VERSION,
+ "zlib",
+ "Georg Richter",
+ "zlib compresson plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ma_zlib_ctx_init,
+ ma_zlib_ctx_deinit,
+ ma_zlib_compress,
+ ma_zlib_decompress,
+mysql_end_client_plugin;
+
diff --git a/libmariadb/plugins/compress/c_zstd.c b/libmariadb/plugins/compress/c_zstd.c
new file mode 100644
index 00000000..9a725f7f
--- /dev/null
+++ b/libmariadb/plugins/compress/c_zstd.c
@@ -0,0 +1,128 @@
+/************************************************************************************
+ Copyright (C) 2022 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+*************************************************************************************/
+
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <zstd.h>
+
+#ifndef ZSTD_CLEVEL_DEFAULT
+#define ZSTD_CLEVEL_DEFAULT 3
+#endif
+
+static void ma_free_ctx(ma_compress_ctx *ctx)
+{
+ if (ctx)
+ {
+ if (ctx->compress_ctx)
+ ZSTD_freeCCtx(ctx->compress_ctx);
+ if (ctx->decompress_ctx)
+ ZSTD_freeDCtx(ctx->decompress_ctx);
+ free(ctx);
+ }
+}
+
+static ma_compress_ctx *ma_zstd_ctx_init(int compression_level)
+{
+ ma_compress_ctx *ctx;
+
+ if (!(ctx = (ma_compress_ctx *)calloc(1, sizeof(ma_compress_ctx))))
+ return NULL;
+
+ ctx->compression_level= (compression_level == COMPRESSION_LEVEL_DEFAULT) ?
+ ZSTD_CLEVEL_DEFAULT : compression_level;
+
+ if (!(ctx->compress_ctx= (void *)ZSTD_createCCtx()) ||
+ !(ctx->decompress_ctx= (void *)ZSTD_createDCtx()))
+ goto end;
+
+ return ctx;
+end:
+ ma_free_ctx(ctx);
+ return NULL;
+}
+
+static void ma_zstd_ctx_deinit(ma_compress_ctx *ctx)
+{
+ ma_free_ctx(ctx);
+}
+
+my_bool ma_zstd_compress(ma_compress_ctx *ctx, void *dst,
+ size_t *dst_len, void *source, size_t source_len)
+{
+ size_t rc;
+ if (!ctx)
+ return 1;
+
+ rc= ZSTD_compressCCtx(ctx->compress_ctx, dst, *dst_len, source, source_len, ctx->compression_level);
+ if (ZSTD_isError(rc))
+ return 1;
+ *dst_len= rc;
+ return 0;
+}
+
+my_bool ma_zstd_decompress(ma_compress_ctx *ctx, void *dst, size_t *dst_len,
+ void *source, size_t *source_len)
+{
+ size_t rc;
+ if (!ctx)
+ return 1;
+
+ rc= ZSTD_decompressDCtx(ctx->decompress_ctx, dst, *dst_len, source, *source_len);
+ if (ZSTD_isError(rc))
+ {
+ return 1;
+ }
+
+ *dst_len= rc;
+
+ return 0;
+}
+
+#ifndef PLUGIN_DYNAMIC
+MARIADB_COMPRESSION_PLUGIN zstd_client_plugin=
+#else
+MARIADB_COMPRESSION_PLUGIN _mysql_client_plugin_declaration_ =
+#endif
+{
+ MARIADB_CLIENT_COMPRESSION_PLUGIN,
+ MARIADB_CLIENT_COMPRESSION_PLUGIN_INTERFACE_VERSION,
+ "zstd",
+ "Georg Richter",
+ "ZStandard compresson plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ma_zstd_ctx_init,
+ ma_zstd_ctx_deinit,
+ ma_zstd_compress,
+ ma_zstd_decompress,
+mysql_end_client_plugin;
+
diff --git a/libmariadb/plugins/connection/CMakeLists.txt b/libmariadb/plugins/connection/CMakeLists.txt
new file mode 100644
index 00000000..743cf2b0
--- /dev/null
+++ b/libmariadb/plugins/connection/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Replication
+REGISTER_PLUGIN(TARGET replication
+ TYPE MARIADB_CLIENT_PLUGIN_CONNECTION
+ CONFIGURATIONS STATIC DYNAMIC OFF
+ DEFAULT OFF
+ SOURCES ${CC_SOURCE_DIR}/plugins/connection/replication.c)
diff --git a/libmariadb/plugins/connection/replication.c b/libmariadb/plugins/connection/replication.c
new file mode 100644
index 00000000..0e7a18b7
--- /dev/null
+++ b/libmariadb/plugins/connection/replication.c
@@ -0,0 +1,357 @@
+/************************************************************************************
+ Copyright (C) 2015-2018 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+ Part of this code includes code from the PHP project which
+ is freely available from http://www.php.net
+*************************************************************************************/
+
+/* MariaDB Connection plugin for load balancing */
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <errmsg.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <ma_string.h>
+#include <ma_common.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
+/* function prototypes */
+MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
+ const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
+void repl_close(MYSQL *mysql);
+int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ size_t length, my_bool skipp_check, void *opt_arg);
+int repl_set_optionsv(MYSQL *mysql, unsigned int option, ...);
+
+#define MARIADB_MASTER 0
+#define MARIADB_SLAVE 1
+
+static struct st_mariadb_api *libmariadb_api= NULL;
+
+#ifndef PLUGIN_DYNAMIC
+MARIADB_CONNECTION_PLUGIN replication_client_plugin =
+#else
+MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
+#endif
+{
+ MARIADB_CLIENT_CONNECTION_PLUGIN,
+ MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION,
+ "replication",
+ "Georg Richter",
+ "MariaDB connection plugin for load balancing",
+ {1, 0, 0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ repl_connect,
+ repl_close,
+ repl_set_optionsv,
+ repl_command,
+ NULL,
+ NULL
+};
+
+typedef struct st_conn_repl {
+ MARIADB_PVIO *pvio[2];
+ MYSQL *slave_mysql;
+ my_bool read_only;
+ my_bool round_robin;
+ char *url;
+ char *host[2];
+ unsigned int port[2];
+ unsigned int current_type;
+} REPL_DATA;
+
+#define SET_SLAVE(mysql, data)\
+do {\
+ mysql->net.pvio= data->pvio[MARIADB_SLAVE]; \
+ data->current_type= MARIADB_SLAVE;\
+} while(0)
+
+#define SET_MASTER(mysql, data)\
+do {\
+ mysql->net.pvio= data->pvio[MARIADB_MASTER];\
+ data->current_type= MARIADB_MASTER;\
+} while(0)
+
+
+/* parse url
+ * Url has the following format:
+ * master[:port],slave1[:port],slave2[:port],..,slaven[:port]
+ *
+ */
+
+my_bool repl_parse_url(const char *url, REPL_DATA *data)
+{
+ char *p;
+ char *slaves[64];
+ int port[64], i,num_slaves= 0;
+
+ if (!url || url[0] == 0)
+ return 1;
+
+ memset(slaves, 0, 64 * sizeof(char *));
+ memset(&port, 0, 64 * sizeof(int));
+
+ memset(data->host, 0, 2 * sizeof(char *));
+ memset(data->port, 0, 2 * sizeof(int));
+
+ if (!data->url)
+ data->url= strdup(url);
+ data->host[MARIADB_MASTER]= p= data->url;
+
+ /* get slaves */
+ while((p && (p= strchr(p, ','))))
+ {
+ *p= '\0';
+ p++;
+ if (*p)
+ {
+ slaves[num_slaves]= p;
+ num_slaves++;
+ }
+ }
+
+ if (!num_slaves)
+ return 0;
+ if (num_slaves == 1)
+ data->host[MARIADB_SLAVE]= slaves[0];
+ else
+ {
+ int random_nr;
+#ifndef WIN32
+ struct timeval tp;
+ gettimeofday(&tp,NULL);
+ srand(tp.tv_usec / 1000 + tp.tv_sec * 1000);
+#else
+ srand(GetTickCount());
+#endif
+
+ random_nr= rand() % num_slaves;
+ data->host[MARIADB_SLAVE]= slaves[random_nr];
+ }
+
+ /* check ports */
+ for (i=0; i < 2 && data->host[i]; i++)
+ {
+ /* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2
+ hostnames have to be enclosed in square brackets if a port is given */
+ if (data->host[i][0]== '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']')))
+ {
+ /* ignore first square bracket */
+ memmove(data->host[i], data->host[i]+1, strlen(data->host[i]) - 1);
+ p= strchr(data->host[i],']');
+ *p= 0;
+ p++;
+ }
+ else
+ p= data->host[i];
+ if (p && (p= strchr(p, ':')))
+ {
+ *p= '\0';
+ p++;
+ data->port[i]= atoi(p);
+ }
+ }
+
+ return 0;
+}
+
+MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
+ const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag)
+{
+ REPL_DATA *data= NULL;
+ MA_CONNECTION_HANDLER *hdlr= mysql->extension->conn_hdlr;
+
+ if (!libmariadb_api)
+ libmariadb_api= mysql->methods->api;
+
+ if ((data= (REPL_DATA *)hdlr->data))
+ {
+ data->pvio[MARIADB_MASTER]->methods->close(data->pvio[MARIADB_MASTER]);
+ data->pvio[MARIADB_MASTER]= 0;
+ repl_close(mysql);
+ }
+
+ if (!(data= calloc(1, sizeof(REPL_DATA))))
+ {
+ mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, "HY000", 0);
+ return NULL;
+ }
+ memset(data->pvio, 0, 2 * sizeof(MARIADB_PVIO *));
+
+ if (repl_parse_url(host, data))
+ goto error;
+
+ /* try to connect to master */
+ if (!(libmariadb_api->mysql_real_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db,
+ data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag)))
+ goto error;
+
+ data->pvio[MARIADB_MASTER]= mysql->net.pvio;
+ hdlr->data= data;
+ SET_MASTER(mysql, data);
+
+ /* to allow immediate access without connection delay, we will start
+ * connecting to slave(s) in background */
+
+ /* if slave connection will fail, we will not return error but use master instead */
+ if (!(data->slave_mysql= libmariadb_api->mysql_init(NULL)) ||
+ !(mysql->methods->db_connect(data->slave_mysql, data->host[MARIADB_SLAVE], user, passwd, db,
+ data->port[MARIADB_SLAVE] ? data->port[MARIADB_SLAVE] : port, unix_socket, clientflag)))
+ {
+ if (data->slave_mysql)
+ libmariadb_api->mysql_close(data->slave_mysql);
+ data->pvio[MARIADB_SLAVE]= NULL;
+ }
+ else
+ {
+ data->pvio[MARIADB_SLAVE]= data->slave_mysql->net.pvio;
+ data->slave_mysql->net.pvio->mysql= mysql;
+ }
+ return mysql;
+error:
+ if (data)
+ {
+ if (data->url)
+ free(data->url);
+ free(data);
+ }
+ return NULL;
+}
+
+void repl_close(MYSQL *mysql)
+{
+ MA_CONNECTION_HANDLER *hdlr= mysql->extension->conn_hdlr;
+ REPL_DATA *data= (REPL_DATA *)hdlr->data;
+
+ /* restore master */
+ SET_MASTER(mysql, data);
+
+ /* free slave information and close connection */
+ if (data->pvio[MARIADB_SLAVE])
+ {
+ /* restore mysql */
+ data->pvio[MARIADB_SLAVE]->mysql= data->slave_mysql;
+ libmariadb_api->mysql_close(data->slave_mysql);
+ data->pvio[MARIADB_SLAVE]= NULL;
+ data->slave_mysql= NULL;
+ }
+
+ /* free masrwe information and close connection */
+ free(data->url);
+ free(data);
+ mysql->extension->conn_hdlr->data= NULL;
+}
+
+static my_bool is_slave_command(const char *buffer, size_t buffer_len)
+{
+ const char *buffer_end= buffer + buffer_len;
+
+ for (; buffer < buffer_end; ++buffer)
+ {
+ char c;
+ if (isalpha(c=*buffer))
+ {
+ if (tolower(c) == 's')
+ return 1;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static my_bool is_slave_stmt(MYSQL *mysql, const char *buffer)
+{
+ unsigned long stmt_id= uint4korr(buffer);
+ LIST *stmt_list= mysql->stmts;
+
+ for (; stmt_list; stmt_list= stmt_list->next)
+ {
+ MYSQL_STMT *stmt= (MYSQL_STMT *)stmt_list->data;
+ if (stmt->stmt_id == stmt_id)
+ return 1;
+ }
+ return 0;
+}
+
+
+int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
+ size_t length,
+ my_bool skipp_check __attribute__((unused)),
+ void *opt_arg __attribute__((unused)))
+{
+ REPL_DATA *data= (REPL_DATA *)mysql->extension->conn_hdlr->data;
+
+ /* if we don't have slave or slave became unavailable root traffic to master */
+ if (!data->pvio[MARIADB_SLAVE] || !data->read_only)
+ {
+ SET_MASTER(mysql, data);
+ return 0;
+ }
+ switch(command) {
+ case COM_QUERY:
+ case COM_STMT_PREPARE:
+ if (is_slave_command(arg, length))
+ SET_SLAVE(mysql, data)
+ else
+ SET_MASTER(mysql,data)
+ break;
+ case COM_STMT_EXECUTE:
+ case COM_STMT_FETCH:
+ if (data->pvio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->pvio[MARIADB_SLAVE]->mysql, arg))
+ SET_SLAVE(mysql, data)
+ else
+ SET_MASTER(mysql,data)
+ break;
+
+ default:
+ SET_MASTER(mysql,data)
+ break;
+ }
+ return 0;
+}
+
+int repl_set_optionsv(MYSQL *mysql, unsigned int option, ...)
+{
+ REPL_DATA *data= (REPL_DATA *)mysql->extension->conn_hdlr->data;
+ va_list ap;
+ void *arg1;
+ int rc= 0;
+
+ va_start(ap, option);
+ arg1= va_arg(ap, void *);
+
+ switch(option) {
+ case MARIADB_OPT_CONNECTION_READ_ONLY:
+ data->read_only= *(my_bool *)arg1;
+ break;
+ default:
+ rc= -1;
+ break;
+ }
+ va_end(ap);
+ return(rc);
+}
diff --git a/libmariadb/plugins/io/CMakeLists.txt b/libmariadb/plugins/io/CMakeLists.txt
new file mode 100644
index 00000000..8c304c99
--- /dev/null
+++ b/libmariadb/plugins/io/CMakeLists.txt
@@ -0,0 +1,15 @@
+IF (WITH_CURL)
+ INCLUDE(FindCURL)
+ IF(CURL_FOUND)
+
+ ADD_DEFINITIONS(-DHAVE_REMOTEIO=1)
+ #remote io plugin
+ REGISTER_PLUGIN(TARGET remote_io
+ TYPE MARIADB_CLIENT_PLUGIN_IO
+ CONFIGURATIONS DYNAMIC STATIC OFF
+ DEFAULT DYNAMIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/io/remote_io.c
+ INCLUDES ${CURL_INCLUDE_DIR}
+ LIBRARIES ${CURL_LIBRARIES})
+ ENDIF()
+ENDIF()
diff --git a/libmariadb/plugins/io/remote_io.c b/libmariadb/plugins/io/remote_io.c
new file mode 100644
index 00000000..c06ecacd
--- /dev/null
+++ b/libmariadb/plugins/io/remote_io.c
@@ -0,0 +1,453 @@
+/************************************************************************************
+ * Copyright (C) 2015 - 2018 MariaDB Corporation AB
+ * Copyright (c) 2003 Simtec Electronics
+ *
+ * Re-implemented by Vincent Sanders <vince@kyllikki.org> with extensive
+ * reference to original curl example code
+ *
+ * Rewritten for MariaDB Connector/C by Georg Richter <georg@mariadb.com>
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *************************************************************************************/
+
+/*
+ This is a plugin for remote file access via libcurl.
+
+ The following URL types are supported:
+
+ http://
+ https://
+ ftp://
+ sftp://
+ ldap://
+ smb://
+*/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+
+#include <stdio.h>
+#include <string.h>
+#ifndef WIN32
+#include <sys/time.h>
+#else
+#pragma comment(lib, "Ws2_32.lib")
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <mariadb/ma_io.h>
+
+/* Internal file structure */
+
+MA_FILE *ma_rio_open(const char *url,const char *operation);
+int ma_rio_close(MA_FILE *file);
+int ma_rio_feof(MA_FILE *file);
+size_t ma_rio_read(void *ptr, size_t size, size_t nmemb, MA_FILE *file);
+char * ma_rio_gets(char *ptr, size_t size, MA_FILE *file);
+
+int ma_rio_init(char *, size_t, int, va_list);
+int ma_rio_deinit(void);
+
+struct st_rio_methods ma_rio_methods= {
+ ma_rio_open,
+ ma_rio_close,
+ ma_rio_feof,
+ ma_rio_read,
+ ma_rio_gets
+};
+
+typedef struct
+{
+ CURL *curl;
+ size_t length,
+ offset;
+ uchar *buffer;
+ int in_progress;
+} MA_REMOTE_FILE;
+
+CURLM *multi_handle= NULL;
+
+#ifndef PLUGIN_DYNAMIC
+MARIADB_REMOTEIO_PLUGIN remote_io_client_plugin=
+#else
+MARIADB_REMOTEIO_PLUGIN _mysql_client_plugin_declaration_ =
+#endif
+{
+ MARIADB_CLIENT_REMOTEIO_PLUGIN,
+ MARIADB_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION,
+ "remote_io",
+ "Georg Richter",
+ "Remote IO plugin",
+ {0,1,0},
+ "LGPL",
+ NULL,
+ ma_rio_init,
+ ma_rio_deinit,
+ NULL,
+ &ma_rio_methods
+mysql_end_client_plugin;
+
+/* {{{ ma_rio_init - Plugin initialization */
+int ma_rio_init(char *unused1 __attribute__((unused)),
+ size_t unused2 __attribute__((unused)),
+ int unused3 __attribute__((unused)),
+ va_list unused4 __attribute__((unused)))
+{
+ curl_global_init(CURL_GLOBAL_ALL);
+ if (!multi_handle)
+ multi_handle = curl_multi_init();
+ return 0;
+}
+/* }}} */
+
+/* {{{ ma_rio_deinit - Plugin deinitialization */
+int ma_rio_deinit(void)
+{
+ if (multi_handle)
+ {
+ curl_multi_cleanup(multi_handle);
+ multi_handle= NULL;
+ }
+ curl_global_cleanup();
+ return 0;
+}
+/* }}} */
+
+/* {{{ curl_write_callback */
+static size_t rio_write_callback(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *ptr)
+{
+ size_t free_bytes;
+ char *tmp;
+
+ MA_FILE *file= (MA_FILE *)ptr;
+ MA_REMOTE_FILE *curl_file = (MA_REMOTE_FILE *)file->ptr;
+ size *= nitems;
+
+ free_bytes= curl_file->length - curl_file->offset;
+
+ /* check if we need to allocate more memory */
+ if (size > free_bytes) {
+ tmp= (char *)realloc((gptr)curl_file->buffer, curl_file->length + (size - free_bytes));
+ if (!tmp)
+ size= free_bytes;
+ else {
+ curl_file->length+= size - free_bytes;
+ curl_file->buffer= (unsigned char *)tmp;
+ }
+ }
+
+ /* copy buffer into MA_FILE structure */
+ memcpy((char *)curl_file->buffer + curl_file->offset, buffer, size);
+ curl_file->offset+= size;
+
+ return size;
+}
+/* }}} */
+
+/* use to attempt to fill the read buffer up to requested number of bytes */
+static int fill_buffer(MA_FILE *file, size_t want)
+{
+ fd_set fdread;
+ fd_set fdwrite;
+ fd_set fdexcep;
+ struct timeval timeout;
+ int rc;
+ CURLMcode mc; /* curl_multi_fdset() return code */
+ MA_REMOTE_FILE *rf= (MA_REMOTE_FILE *)file->ptr;
+
+ /* only attempt to fill buffer if transactions still running and buffer
+ doesn't exceed required size already */
+ if (!rf->in_progress || (rf->offset > want))
+ return 0;
+
+ /* try to fill buffer */
+ do {
+ int maxfd = -1;
+ long curl_timeo = -1;
+
+ FD_ZERO(&fdread);
+ FD_ZERO(&fdwrite);
+ FD_ZERO(&fdexcep);
+
+ /* set a suitable timeout to fail on */
+ timeout.tv_sec = 20; /* 20 seconds */
+ timeout.tv_usec = 0;
+
+ curl_multi_timeout(multi_handle, &curl_timeo);
+ if(curl_timeo >= 0) {
+ timeout.tv_sec = curl_timeo / 1000;
+ if(timeout.tv_sec > 1)
+ timeout.tv_sec = 1;
+ else
+ timeout.tv_usec = (curl_timeo % 1000) * 1000;
+ }
+
+ /* get file descriptors from the transfers */
+ mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+ if(mc != CURLM_OK)
+ {
+ /* todo: error handling */
+ break;
+ }
+
+ /* On success the value of maxfd is guaranteed to be >= -1. We call
+ select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
+ no fds ready yet so we call select(0, ...) */
+
+ if(maxfd == -1) {
+ struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
+ rc = select(0, NULL, NULL, NULL, &wait);
+ }
+ else {
+ rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+ }
+
+ switch(rc) {
+ case -1:
+ /* select error */
+ break;
+
+ case 0:
+ default:
+ /* timeout or readable/writable sockets */
+ curl_multi_perform(multi_handle, &rf->in_progress);
+ break;
+ }
+ } while(rf->in_progress && (rf->offset < want));
+ return 1;
+}
+
+/* use to remove want bytes from the front of a files buffer */
+static int use_buffer(MA_FILE *file,int want)
+{
+ MA_REMOTE_FILE *rf= (MA_REMOTE_FILE *)file->ptr;
+ /* sort out buffer */
+ if((rf->offset - want) <=0) {
+ /* ditch buffer - write will recreate */
+ if (rf->buffer)
+ free(rf->buffer);
+
+ rf->buffer=NULL;
+ rf->offset=0;
+ rf->length=0;
+ }
+ else {
+ /* move rest down make it available for later */
+ memmove(rf->buffer,
+ &rf->buffer[want],
+ (rf->offset - want));
+
+ rf->offset -= want;
+ }
+ return 0;
+}
+
+MA_FILE *ma_rio_open(const char *url,const char *operation)
+{
+ /* this code could check for URLs or types in the 'url' and
+ basically use the real fopen() for standard files */
+
+ MA_FILE *file;
+ MA_REMOTE_FILE *rf;
+ (void)operation;
+
+ if (!(file = (MA_FILE *)calloc(sizeof(MA_FILE), 1)))
+ return NULL;
+
+ file->type= MA_FILE_REMOTE;
+ if (!(file->ptr= rf= (MA_REMOTE_FILE *)calloc(sizeof(MA_REMOTE_FILE), 1)))
+ {
+ free(file);
+ return NULL;
+ }
+ rf->curl = curl_easy_init();
+
+ if (curl_easy_setopt(rf->curl, CURLOPT_URL, url) ||
+ curl_easy_setopt(rf->curl, CURLOPT_WRITEDATA, file) ||
+ curl_easy_setopt(rf->curl, CURLOPT_VERBOSE, 0L) ||
+ curl_easy_setopt(rf->curl, CURLOPT_WRITEFUNCTION, rio_write_callback))
+ {
+ free(file);
+ free(rf);
+ return NULL;
+ }
+
+ curl_multi_add_handle(multi_handle, rf->curl);
+
+ /* lets start the fetch */
+ curl_multi_perform(multi_handle, &rf->in_progress);
+
+ if((rf->offset == 0) && (!rf->in_progress)) {
+ /* if in_progress is 0 now, we should return NULL */
+
+ /* make sure the easy handle is not in the multi handle anymore */
+ curl_multi_remove_handle(multi_handle, rf->curl);
+
+ /* cleanup */
+ curl_easy_cleanup(rf->curl);
+
+ free(file);
+
+ file = NULL;
+ }
+ return file;
+}
+
+int ma_rio_close(MA_FILE *file)
+{
+ int ret=0;/* default is good return */
+ MA_REMOTE_FILE *rf= (MA_REMOTE_FILE *)file->ptr;
+
+ switch(file->type) {
+ case MA_FILE_REMOTE:
+ curl_multi_remove_handle(multi_handle, rf->curl);
+
+ /* cleanup */
+ curl_easy_cleanup(rf->curl);
+ break;
+
+ default: /* unknown or supported type - oh dear */
+ ret=EOF;
+ errno=EBADF;
+ break;
+ }
+
+ if(rf->buffer)
+ free(rf->buffer);/* free any allocated buffer space */
+
+ free(rf);
+ free(file);
+
+ return ret;
+}
+
+int ma_rio_feof(MA_FILE *file)
+{
+ int ret=0;
+ MA_REMOTE_FILE *rf= (MA_REMOTE_FILE *)file->ptr;
+
+ switch(file->type) {
+ case MA_FILE_REMOTE:
+ if((rf->offset == 0) && (!rf->in_progress))
+ ret = 1;
+ break;
+
+ default: /* unknown or supported type - oh dear */
+ ret=-1;
+ errno=EBADF;
+ break;
+ }
+ return ret;
+}
+
+size_t ma_rio_read(void *ptr, size_t size, size_t nmemb, MA_FILE *file)
+{
+ size_t want;
+ MA_REMOTE_FILE *rf= (MA_REMOTE_FILE *)file->ptr;
+
+ switch(file->type) {
+ case MA_FILE_REMOTE:
+ want = nmemb * size;
+
+ fill_buffer(file,want);
+
+ /* check if there's data in the buffer - if not fill_buffer()
+ * either errored or EOF */
+ if(!rf->offset)
+ return 0;
+
+ /* ensure only available data is considered */
+ if(rf->offset < want)
+ want = rf->offset;
+
+ /* xfer data to caller */
+ memcpy(ptr, rf->buffer, want);
+
+ use_buffer(file,want);
+
+ want = want / size; /* number of items */
+ break;
+
+ default: /* unknown or supported type - oh dear */
+ want=0;
+ errno=EBADF;
+ break;
+
+ }
+ return want;
+}
+
+char *ma_rio_gets(char *ptr, size_t size, MA_FILE *file)
+{
+ size_t want = size - 1;/* always need to leave room for zero termination */
+ size_t loop;
+
+ switch(file->type) {
+ case MA_FILE_REMOTE:
+ {
+ MA_REMOTE_FILE *rf= (MA_REMOTE_FILE *)file->ptr;
+ fill_buffer(file,want);
+
+ /* check if there's data in the buffer - if not fill either errored or
+ * EOF */
+ if(!rf->offset)
+ return NULL;
+
+ /* ensure only available data is considered */
+ if(rf->offset < want)
+ want = rf->offset;
+
+ /*buffer contains data */
+ /* look for newline or eof */
+ for(loop=0;loop < want;loop++) {
+ if(rf->buffer[loop] == '\n') {
+ want=loop+1;/* include newline */
+ break;
+ }
+ }
+
+ /* xfer data to caller */
+ memcpy(ptr, rf->buffer, want);
+ ptr[want]=0;/* always null terminate */
+
+ use_buffer(file,want);
+
+ break;
+ }
+
+ default: /* unknown or supported type - oh dear */
+ ptr=NULL;
+ errno=EBADF;
+ break;
+ }
+
+ return ptr;/*success */
+}
diff --git a/libmariadb/plugins/plugin.def b/libmariadb/plugins/plugin.def
new file mode 100644
index 00000000..70af9256
--- /dev/null
+++ b/libmariadb/plugins/plugin.def
@@ -0,0 +1,2 @@
+EXPORTS
+ _mysql_client_plugin_declaration_ DATA
diff --git a/libmariadb/plugins/pvio/CMakeLists.txt b/libmariadb/plugins/pvio/CMakeLists.txt
new file mode 100644
index 00000000..b74407a6
--- /dev/null
+++ b/libmariadb/plugins/pvio/CMakeLists.txt
@@ -0,0 +1,27 @@
+SET(PVIO_DIR ${CC_SOURCE_DIR}/plugins/pvio)
+
+INCLUDE_DIRECTORIES(${PVIO_DIR})
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include)
+
+#native password
+REGISTER_PLUGIN(TARGET pvio_socket
+ TYPE MARIADB_CLIENT_PLUGIN_PVIO
+ CONFIGURATIONS STATIC DYNAMIC DEFAULT
+ DEFAULT STATIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_socket.c)
+
+IF(WIN32)
+ # named pipe
+ REGISTER_PLUGIN(TARGET pvio_npipe
+ TYPE MARIADB_CLIENT_PLUGIN_PVIO
+ CONFIGURATIONS STATIC DYNAMIC DEFAULT
+ DEFAULT STATIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_npipe.c)
+
+ # shared memory
+ REGISTER_PLUGIN(TARGET pvio_shmem
+ TYPE MARIADB_CLIENT_PLUGIN_PVIO
+ CONFIGURATIONS STATIC DYNAMIC DEFAULT
+ DEFAULT DYNAMIC
+ SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_shmem.c)
+ENDIF()
diff --git a/libmariadb/plugins/pvio/pvio_npipe.c b/libmariadb/plugins/pvio/pvio_npipe.c
new file mode 100644
index 00000000..17c59cef
--- /dev/null
+++ b/libmariadb/plugins/pvio/pvio_npipe.c
@@ -0,0 +1,359 @@
+/************************************************************************************
+ Copyright (C) 2015 Georg Richter and MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+*************************************************************************************/
+
+/* MariaDB virtual IO plugin for Windows named pipe communication */
+
+#ifdef _WIN32
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <errmsg.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <ma_string.h>
+
+/* Function prototypes */
+my_bool pvio_npipe_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
+int pvio_npipe_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
+ssize_t pvio_npipe_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ssize_t pvio_npipe_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
+
+my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
+my_bool pvio_npipe_close(MARIADB_PVIO *pvio);
+int pvio_npipe_fast_send(MARIADB_PVIO *pvio);
+int pvio_npipe_keepalive(MARIADB_PVIO *pvio);
+my_bool pvio_npipe_get_handle(MARIADB_PVIO *pvio, void *handle);
+my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio);
+int pvio_npipe_shutdown(MARIADB_PVIO *pvio);
+my_bool pvio_npipe_is_alive(MARIADB_PVIO *pvio);
+
+struct st_ma_pvio_methods pvio_npipe_methods= {
+ pvio_npipe_set_timeout,
+ pvio_npipe_get_timeout,
+ pvio_npipe_read,
+ NULL,
+ pvio_npipe_write,
+ NULL,
+ NULL,
+ NULL,
+ pvio_npipe_connect,
+ pvio_npipe_close,
+ pvio_npipe_fast_send,
+ pvio_npipe_keepalive,
+ pvio_npipe_get_handle,
+ pvio_npipe_is_blocking,
+ pvio_npipe_is_alive,
+ NULL,
+ pvio_npipe_shutdown
+};
+
+#ifndef PLUGIN_DYNAMIC
+MARIADB_PVIO_PLUGIN pvio_npipe_client_plugin =
+#else
+MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_ =
+#endif
+{
+ MARIADB_CLIENT_PVIO_PLUGIN,
+ MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
+ "pvio_npipe",
+ "Georg Richter",
+ "MariaDB virtual IO plugin for named pipe connection",
+ {1, 0, 0},
+ "LGPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &pvio_npipe_methods
+};
+
+struct st_pvio_npipe {
+ HANDLE pipe;
+ OVERLAPPED overlapped;
+ MYSQL *mysql;
+};
+
+my_bool pvio_npipe_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
+{
+ int timeout_ms;
+
+ if (!pvio)
+ return 1;
+ if (timeout > INT_MAX/1000)
+ timeout_ms= -1;
+ else if (timeout <=0)
+ timeout_ms= -1;
+ else
+ timeout_ms = timeout*1000;
+
+ pvio->timeout[type]= timeout_ms;
+ return 0;
+}
+
+int pvio_npipe_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
+{
+ if (!pvio)
+ return -1;
+ return pvio->timeout[type] / 1000;
+}
+
+static BOOL complete_io(HANDLE file, OVERLAPPED *ov, BOOL ret, DWORD timeout, DWORD *size)
+{
+ if (ret)
+ timeout = 0; /* IO completed successfully, do not WaitForSingleObject */
+ else
+ {
+ assert(timeout);
+ if (GetLastError() != ERROR_IO_PENDING)
+ return FALSE;
+ }
+
+ if (timeout)
+ {
+ HANDLE wait_handle= ov->hEvent;
+ assert(wait_handle && (wait_handle != INVALID_HANDLE_VALUE));
+
+ DWORD wait_ret= WaitForSingleObject(wait_handle, timeout);
+ switch (wait_ret)
+ {
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_TIMEOUT:
+ CancelIoEx(file, ov);
+ SetLastError(ERROR_TIMEOUT);
+ return FALSE;
+ default:
+ /* WAIT_ABANDONED or WAIT_FAILED unexpected. */
+ assert(0);
+ return FALSE;
+ }
+ }
+
+ return GetOverlappedResult(file, ov, size, FALSE);
+}
+
+ssize_t pvio_npipe_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
+{
+ BOOL ret;
+ ssize_t r= -1;
+ struct st_pvio_npipe *cpipe= NULL;
+ DWORD size;
+
+ if (!pvio || !pvio->data)
+ return -1;
+
+ cpipe= (struct st_pvio_npipe *)pvio->data;
+
+ ret= ReadFile(cpipe->pipe, buffer, (DWORD)length, NULL, &cpipe->overlapped);
+ ret= complete_io(cpipe->pipe, &cpipe->overlapped, ret, pvio->timeout[PVIO_READ_TIMEOUT], &size);
+ r= ret? (ssize_t) size:-1;
+
+ return r;
+}
+
+ssize_t pvio_npipe_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ ssize_t r= -1;
+ struct st_pvio_npipe *cpipe= NULL;
+ BOOL ret;
+ DWORD size;
+
+ if (!pvio || !pvio->data)
+ return -1;
+
+ cpipe= (struct st_pvio_npipe *)pvio->data;
+
+ ret= WriteFile(cpipe->pipe, buffer, (DWORD)length, NULL , &cpipe->overlapped);
+ ret= complete_io(cpipe->pipe, &cpipe->overlapped, ret, pvio->timeout[PVIO_WRITE_TIMEOUT], &size);
+ r= ret ? (ssize_t)size : -1;
+ return r;
+}
+
+
+int pvio_npipe_keepalive(MARIADB_PVIO *pvio)
+{
+ /* keep alive is used for TCP/IP connections only */
+ return 0;
+}
+
+int pvio_npipe_fast_send(MARIADB_PVIO *pvio)
+{
+ /* not supported */
+ return 0;
+}
+my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
+{
+ struct st_pvio_npipe *cpipe= NULL;
+
+ if (!pvio || !cinfo)
+ return 1;
+
+ /* if connect timeout is set, we will overwrite read/write timeout */
+ if (pvio->timeout[PVIO_CONNECT_TIMEOUT])
+ {
+ pvio->timeout[PVIO_READ_TIMEOUT]= pvio->timeout[PVIO_WRITE_TIMEOUT]= pvio->timeout[PVIO_CONNECT_TIMEOUT];
+ }
+
+ if (!(cpipe= (struct st_pvio_npipe *)LocalAlloc(LMEM_ZEROINIT, sizeof(struct st_pvio_npipe))))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, "HY000", 0, "");
+ return 1;
+ }
+ pvio->data= (void *)cpipe;
+ cpipe->pipe= INVALID_HANDLE_VALUE;
+ pvio->mysql= cinfo->mysql;
+ pvio->type= cinfo->type;
+
+ if (cinfo->type == PVIO_TYPE_NAMEDPIPE)
+ {
+ char szPipeName[MAX_PATH];
+ ULONGLONG deadline;
+ LONGLONG wait_ms;
+ DWORD backoff= 0; /* Avoid busy wait if ERROR_PIPE_BUSY.*/
+ if ( ! cinfo->unix_socket || (cinfo->unix_socket)[0] == 0x00)
+ cinfo->unix_socket = MARIADB_NAMEDPIPE;
+ if (!cinfo->host || !strcmp(cinfo->host,LOCAL_HOST))
+ cinfo->host=LOCAL_HOST_NAMEDPIPE;
+
+ szPipeName[MAX_PATH - 1]= 0;
+ snprintf(szPipeName, MAX_PATH - 1, "\\\\%s\\pipe\\%s", cinfo->host, cinfo->unix_socket);
+
+ if (pvio->timeout[PVIO_CONNECT_TIMEOUT] > 0)
+ deadline = GetTickCount64() + pvio->timeout[PVIO_CONNECT_TIMEOUT];
+ else
+ deadline = INFINITE;
+
+ while (1)
+ {
+ if ((cpipe->pipe = CreateFile(szPipeName,
+ GENERIC_READ |
+ GENERIC_WRITE,
+ 0, /* no sharing */
+ NULL, /* default security attributes */
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL)) != INVALID_HANDLE_VALUE)
+ break;
+
+ if (GetLastError() != ERROR_PIPE_BUSY)
+ {
+ pvio->set_error(pvio->mysql, CR_NAMEDPIPEOPEN_ERROR, "HY000", 0,
+ cinfo->host, cinfo->unix_socket, GetLastError());
+ goto end;
+ }
+
+ Sleep(backoff);
+ if (!backoff)
+ backoff = 1;
+
+ wait_ms = deadline - GetTickCount64();
+ if (wait_ms > INFINITE)
+ wait_ms = INFINITE;
+
+ if ((wait_ms <= 0) || !WaitNamedPipe(szPipeName, (DWORD)wait_ms))
+ {
+ pvio->set_error(pvio->mysql, CR_NAMEDPIPEWAIT_ERROR, "HY000", 0,
+ cinfo->host, cinfo->unix_socket, ERROR_TIMEOUT);
+ goto end;
+ }
+ }
+
+
+ if (!(cpipe->overlapped.hEvent= CreateEvent(NULL, FALSE, FALSE, NULL)))
+ {
+ pvio->set_error(pvio->mysql, CR_EVENT_CREATE_FAILED, "HY000", 0,
+ GetLastError());
+ goto end;
+ }
+ return 0;
+ }
+end:
+ if (cpipe)
+ {
+ if (cpipe->pipe != INVALID_HANDLE_VALUE)
+ CloseHandle(cpipe->pipe);
+ LocalFree(cpipe);
+ pvio->data= NULL;
+ }
+ return 1;
+}
+
+my_bool pvio_npipe_close(MARIADB_PVIO *pvio)
+{
+ struct st_pvio_npipe *cpipe= NULL;
+ int r= 0;
+
+ if (!pvio)
+ return 1;
+
+ if (pvio->data)
+ {
+ cpipe= (struct st_pvio_npipe *)pvio->data;
+ CloseHandle(cpipe->overlapped.hEvent);
+ if (cpipe->pipe != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(cpipe->pipe);
+ cpipe->pipe= INVALID_HANDLE_VALUE;
+ }
+ LocalFree(pvio->data);
+ pvio->data= NULL;
+ }
+ return r;
+}
+
+my_bool pvio_npipe_get_handle(MARIADB_PVIO *pvio, void *handle)
+{
+ if (pvio && pvio->data)
+ {
+ *(HANDLE *)handle= ((struct st_pvio_npipe *)pvio->data)->pipe;
+ return 0;
+ }
+ return 1;
+}
+
+my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio)
+{
+ return 1;
+}
+
+int pvio_npipe_shutdown(MARIADB_PVIO *pvio)
+{
+ HANDLE h;
+ if (pvio_npipe_get_handle(pvio, &h) == 0)
+ {
+ return(CancelIoEx(h, NULL) ? 0 : 1);
+ }
+ return 1;
+}
+
+my_bool pvio_npipe_is_alive(MARIADB_PVIO *pvio)
+{
+ HANDLE handle;
+ if (!pvio || !pvio->data)
+ return FALSE;
+
+ handle= ((struct st_pvio_npipe *)pvio->data)->pipe;
+ /* Copy data from named pipe without removing it */
+ if (PeekNamedPipe(handle, NULL, 0, NULL, NULL, NULL))
+ return TRUE;
+ return test(GetLastError() != ERROR_BROKEN_PIPE);
+}
+#endif
diff --git a/libmariadb/plugins/pvio/pvio_plugin.def b/libmariadb/plugins/pvio/pvio_plugin.def
new file mode 100644
index 00000000..70af9256
--- /dev/null
+++ b/libmariadb/plugins/pvio/pvio_plugin.def
@@ -0,0 +1,2 @@
+EXPORTS
+ _mysql_client_plugin_declaration_ DATA
diff --git a/libmariadb/plugins/pvio/pvio_shmem.c b/libmariadb/plugins/pvio/pvio_shmem.c
new file mode 100644
index 00000000..f412393b
--- /dev/null
+++ b/libmariadb/plugins/pvio/pvio_shmem.c
@@ -0,0 +1,469 @@
+/************************************************************************************
+ Copyright (C) 2015 Georg Richter and MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+
+*************************************************************************************/
+/* MariaDB virtual IO plugin for Windows shared memory communication */
+
+#ifdef _WIN32
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <errmsg.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <ma_string.h>
+
+#define PVIO_SHM_BUFFER_SIZE (16000 + 4)
+
+my_bool pvio_shm_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
+int pvio_shm_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
+ssize_t pvio_shm_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ssize_t pvio_shm_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
+int pvio_shm_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
+int pvio_shm_blocking(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value);
+my_bool pvio_shm_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
+my_bool pvio_shm_close(MARIADB_PVIO *pvio);
+int pvio_shm_shutdown(MARIADB_PVIO *pvio);
+my_bool pvio_shm_is_alive(MARIADB_PVIO *pvio);
+my_bool pvio_shm_get_handle(MARIADB_PVIO *pvio, void *handle);
+
+struct st_ma_pvio_methods pvio_shm_methods= {
+ pvio_shm_set_timeout,
+ pvio_shm_get_timeout,
+ pvio_shm_read,
+ NULL,
+ pvio_shm_write,
+ NULL,
+ pvio_shm_wait_io_or_timeout,
+ pvio_shm_blocking,
+ pvio_shm_connect,
+ pvio_shm_close,
+ NULL,
+ NULL,
+ pvio_shm_get_handle,
+ NULL,
+ pvio_shm_is_alive,
+ NULL,
+ pvio_shm_shutdown
+};
+
+#ifndef PLUGIN_DYNAMIC
+MARIADB_PVIO_PLUGIN pvio_shmem_client_plugin=
+#else
+MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_=
+#endif
+{
+ MARIADB_CLIENT_PVIO_PLUGIN,
+ MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
+ "pvio_shmem",
+ "Georg Richter",
+ "MariaDB virtual IO plugin for Windows shared memory communication",
+ {1, 0, 0},
+ "LGPPL",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &pvio_shm_methods,
+
+};
+
+enum enum_shm_events
+{
+ PVIO_SHM_SERVER_WROTE= 0,
+ PVIO_SHM_SERVER_READ,
+ PVIO_SHM_CLIENT_WROTE,
+ PVIO_SHM_CLIENT_READ,
+ PVIO_SHM_CONNECTION_CLOSED
+};
+
+typedef struct {
+ HANDLE event[5];
+ HANDLE file_map;
+ LPVOID *map;
+ char *read_pos;
+ size_t buffer_size;
+} PVIO_SHM;
+
+const char *StrEvent[]= {"SERVER_WROTE", "SERVER_READ", "CLIENT_WROTE", "CLIENT_READ", "CONNECTION_CLOSED"};
+
+struct st_pvio_shm {
+ char *shm_name;
+};
+
+my_bool pvio_shm_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
+{
+ if (!pvio)
+ return 1;
+ pvio->timeout[type]= (timeout > 0) ? timeout * 1000 : INFINITE;
+ return 0;
+}
+
+int pvio_shm_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
+{
+ if (!pvio)
+ return -1;
+ return pvio->timeout[type] / 1000;
+}
+
+ssize_t pvio_shm_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
+{
+ PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
+ size_t copy_size= length;
+ HANDLE events[2];
+
+ if (!pvio_shm)
+ return -1;
+
+ /* we need to wait for write and close events */
+ if (!pvio_shm->buffer_size)
+ {
+ events[0]= pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED];
+ events[1]= pvio_shm->event[PVIO_SHM_SERVER_WROTE];
+
+ switch(WaitForMultipleObjects(2, events, 0, pvio->timeout[PVIO_READ_TIMEOUT]))
+ {
+ case WAIT_OBJECT_0: /* server closed connection */
+ SetLastError(ERROR_GRACEFUL_DISCONNECT);
+ return -1;
+ case WAIT_OBJECT_0 +1: /* server_wrote event */
+ break;
+ case WAIT_TIMEOUT:
+ SetLastError(ETIMEDOUT);
+ default:
+ return -1;
+ }
+ /* server sent data */
+ pvio_shm->read_pos= (char *)pvio_shm->map;
+ pvio_shm->buffer_size= uint4korr(pvio_shm->read_pos);
+ pvio_shm->read_pos+= 4;
+ }
+
+ if (pvio_shm->buffer_size < copy_size)
+ copy_size= pvio_shm->buffer_size;
+
+ if (copy_size)
+ {
+ memcpy(buffer, (uchar *)pvio_shm->read_pos, pvio_shm->buffer_size);
+ pvio_shm->read_pos+= copy_size;
+ pvio_shm->buffer_size-= copy_size;
+ }
+
+ /* we need to read again */
+ if (!pvio_shm->buffer_size)
+ if (!SetEvent(pvio_shm->event[PVIO_SHM_CLIENT_READ]))
+ return -1;
+
+ return (ssize_t)copy_size;
+}
+
+ssize_t pvio_shm_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ HANDLE events[2];
+ PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
+ size_t bytes_to_write= length;
+ uchar *buffer_pos= (uchar *)buffer;
+
+ if (!pvio_shm)
+ return -1;
+
+ events[0]= pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED];
+ events[1]= pvio_shm->event[PVIO_SHM_SERVER_READ];
+
+ while (bytes_to_write)
+ {
+ size_t pkt_length;
+ switch (WaitForMultipleObjects(2, events, 0, pvio->timeout[PVIO_WRITE_TIMEOUT])) {
+ case WAIT_OBJECT_0: /* connection closed */
+ SetLastError(ERROR_GRACEFUL_DISCONNECT);
+ return -1;
+ case WAIT_OBJECT_0 + 1: /* server_read */
+ break;
+ case WAIT_TIMEOUT:
+ SetLastError(ETIMEDOUT);
+ default:
+ return -1;
+ }
+ pkt_length= MIN(PVIO_SHM_BUFFER_SIZE, length);
+ int4store(pvio_shm->map, pkt_length);
+ memcpy((uchar *)pvio_shm->map + 4, buffer_pos, length);
+ buffer_pos+= length;
+ bytes_to_write-= length;
+
+ if (!SetEvent(pvio_shm->event[PVIO_SHM_CLIENT_WROTE]))
+ return -1;
+ }
+ return (ssize_t)length;
+}
+
+
+int pvio_shm_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
+{
+ return 0;
+}
+
+int pvio_shm_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
+{
+ /* not supported */
+ return 0;
+}
+
+int pvio_shm_keepalive(MARIADB_PVIO *pvio)
+{
+ /* not supported */
+ return 0;
+}
+
+int pvio_shm_fast_send(MARIADB_PVIO *pvio)
+{
+ /* not supported */
+ return 0;
+}
+
+my_bool pvio_shm_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
+{
+ const char *base_memory_name;
+ char *prefixes[]= {"", "Global\\", NULL};
+ char *shm_name, *shm_suffix, *shm_prefix;
+ uchar i= 0;
+ int len;
+ int cid;
+ DWORD dwDesiredAccess= EVENT_MODIFY_STATE | SYNCHRONIZE;
+ HANDLE hdlConnectRequest= NULL,
+ hdlConnectRequestAnswer= NULL,
+ file_map= NULL;
+ LPVOID map= NULL;
+ PVIO_SHM *pvio_shm= (PVIO_SHM*)LocalAlloc(LMEM_ZEROINIT, sizeof(PVIO_SHM));
+
+ if (!pvio_shm)
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, "HY000", 0, "");
+ return 0;
+ }
+
+ /* MariaDB server constructs the event name as follows:
+ "Global\\base_memory_name" or
+ "\\base_memory_name"
+ */
+
+
+ base_memory_name= (cinfo->host) ? cinfo->host : SHM_DEFAULT_NAME;
+
+ if (!(shm_name= (char *)LocalAlloc(LMEM_ZEROINIT, strlen(base_memory_name) + 40)))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, "HY000", 0, "");
+ goto error;
+ }
+
+ /* iterate through prefixes */
+ while (prefixes[i])
+ {
+ len= sprintf(shm_name, "%s%s_", prefixes[i], base_memory_name);
+ shm_suffix= shm_name + len;
+ strcpy(shm_suffix, "CONNECT_REQUEST");
+ if ((hdlConnectRequest= OpenEvent(dwDesiredAccess, 0, shm_name)))
+ {
+ /* save prefix to prevent further loop */
+ shm_prefix= prefixes[i];
+ break;
+ }
+ i++;
+ }
+ if (!hdlConnectRequest)
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Opening CONNECT_REQUEST event failed", GetLastError());
+ goto error;
+ }
+
+ strcpy(shm_suffix, "CONNECT_ANSWER");
+ if (!(hdlConnectRequestAnswer= OpenEvent(dwDesiredAccess, 0, shm_name)))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Opening CONNECT_ANSWER event failed", GetLastError());
+ goto error;
+ }
+
+ /* get connection id, so we can build the filename used for connection */
+ strcpy(shm_suffix, "CONNECT_DATA");
+ if (!(file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name)))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "OpenFileMapping failed", GetLastError());
+ goto error;
+ }
+
+ /* try to get first 4 bytes, which represents connection_id */
+ if (!(map= MapViewOfFile(file_map, FILE_MAP_WRITE, 0, 0, sizeof(cid))))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Reading connection_id failed", GetLastError());
+ goto error;
+ }
+
+ /* notify server */
+ if (!SetEvent(hdlConnectRequest))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Failed sending connection request", GetLastError());
+ goto error;
+ }
+
+ /* Wait for server answer */
+ switch(WaitForSingleObject(hdlConnectRequestAnswer, pvio->timeout[PVIO_CONNECT_TIMEOUT])) {
+ case WAIT_ABANDONED:
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Mutex was not released in time", GetLastError());
+ goto error;
+ break;
+ case WAIT_FAILED:
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Operation wait failed", GetLastError());
+ goto error;
+ break;
+ case WAIT_TIMEOUT:
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Operation timed out", GetLastError());
+ goto error;
+ break;
+ case WAIT_OBJECT_0:
+ break;
+ default:
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Wait for server failed", GetLastError());
+ break;
+ }
+
+ cid= uint4korr(map);
+
+ len= sprintf(shm_name, "%s%s_%d_", shm_prefix, base_memory_name, cid);
+ shm_suffix= shm_name + len;
+
+ strcpy(shm_suffix, "DATA");
+ pvio_shm->file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name);
+ if (pvio_shm->file_map == NULL)
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "OpenFileMapping failed", GetLastError());
+ goto error;
+ }
+ if (!(pvio_shm->map= MapViewOfFile(pvio_shm->file_map, FILE_MAP_WRITE, 0, 0, PVIO_SHM_BUFFER_SIZE)))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "MapViewOfFile failed", GetLastError());
+ goto error;
+ }
+
+ for (i=0; i < 5; i++)
+ {
+ strcpy(shm_suffix, StrEvent[i]);
+ if (!(pvio_shm->event[i]= OpenEvent(dwDesiredAccess, 0, shm_name)))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Couldn't create event", GetLastError());
+ goto error;
+ }
+ }
+ /* we will first read from server */
+ SetEvent(pvio_shm->event[PVIO_SHM_SERVER_READ]);
+
+error:
+ if (hdlConnectRequest)
+ CloseHandle(hdlConnectRequest);
+ if (hdlConnectRequestAnswer)
+ CloseHandle(hdlConnectRequestAnswer);
+ if (shm_name)
+ LocalFree(shm_name);
+ if (map)
+ UnmapViewOfFile(map);
+ if (file_map)
+ CloseHandle(file_map);
+ if (pvio_shm)
+ {
+ /* check if all events are set */
+ if (pvio_shm->event[4])
+ {
+ pvio->data= (void *)pvio_shm;
+ pvio->mysql= cinfo->mysql;
+ pvio->type= cinfo->type;
+ pvio_shm->read_pos= (char *)pvio_shm->map;
+ pvio->mysql->net.pvio= pvio;
+ return 0;
+ }
+ for (i=0;i < 5; i++)
+ if (pvio_shm->event[i])
+ CloseHandle(pvio_shm->event[i]);
+ if (pvio_shm->map)
+ UnmapViewOfFile(pvio_shm->map);
+ if (pvio_shm->file_map)
+ CloseHandle(pvio_shm->file_map);
+ LocalFree(pvio_shm);
+ }
+ return 1;
+
+}
+
+my_bool pvio_shm_close(MARIADB_PVIO *pvio)
+{
+ PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
+ int i;
+
+ if (!pvio_shm)
+ return 1;
+
+ /* notify server */
+ SetEvent(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED]);
+
+ UnmapViewOfFile(pvio_shm->map);
+ CloseHandle(pvio_shm->file_map);
+
+ for (i=0; i < 5; i++)
+ CloseHandle(pvio_shm->event[i]);
+
+ LocalFree(pvio_shm);
+ pvio->data= NULL;
+ return 0;
+}
+
+my_bool pvio_shm_get_socket(MARIADB_PVIO *pvio, void *handle)
+{
+ return 1;
+}
+
+my_bool pvio_shm_is_blocking(MARIADB_PVIO *pvio)
+{
+ return 1;
+}
+
+int pvio_shm_shutdown(MARIADB_PVIO *pvio)
+{
+ PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
+ if (pvio_shm)
+ return (SetEvent(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED]) ? 0 : 1);
+ return 1;
+}
+
+my_bool pvio_shm_is_alive(MARIADB_PVIO *pvio)
+{
+ PVIO_SHM *pvio_shm;
+ if (!pvio || !pvio->data)
+ return FALSE;
+ pvio_shm= (PVIO_SHM *)pvio->data;
+ return WaitForSingleObject(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED], 0)!=WAIT_OBJECT_0;
+}
+
+my_bool pvio_shm_get_handle(MARIADB_PVIO *pvio, void *handle)
+{
+
+ *(HANDLE **)handle= 0;
+ if (!pvio || !pvio->data)
+ return FALSE;
+ *(HANDLE **)handle= ((PVIO_SHM*)pvio->data)->event;
+ return TRUE;
+}
+#endif
+
diff --git a/libmariadb/plugins/pvio/pvio_socket.c b/libmariadb/plugins/pvio/pvio_socket.c
new file mode 100644
index 00000000..550fb831
--- /dev/null
+++ b/libmariadb/plugins/pvio/pvio_socket.c
@@ -0,0 +1,1165 @@
+/************************************************************************************
+ Copyright (C) 2015,2016 MariaDB Corporation AB,
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+
+/*
+ MariaDB virtual IO plugin for socket communication:
+
+ The plugin handles connections via unix and network sockets. it is enabled by
+ default and compiled into Connector/C.
+*/
+
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <errmsg.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <ma_context.h>
+#include <mariadb_async.h>
+#include <ma_common.h>
+#include <string.h>
+#include <time.h>
+#ifndef _WIN32
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_POLL
+#include <sys/poll.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#define IS_SOCKET_EINTR(err) ((err) == SOCKET_EINTR)
+#else
+#include <ws2tcpip.h>
+#define O_NONBLOCK 1
+#define MSG_DONTWAIT 0
+#define IS_SOCKET_EINTR(err) 0
+#endif
+
+#ifndef SOCKET_ERROR
+#define SOCKET_ERROR -1
+#endif
+
+#ifndef INVALID_SOCKET
+#define INVALID_SOCKET -1
+#endif
+
+#define DNS_TIMEOUT 30
+
+#ifndef O_NONBLOCK
+#if defined(O_NDELAY)
+#define O_NONBLOCK O_NODELAY
+#elif defined (O_FNDELAY)
+#define O_NONBLOCK O_FNDELAY
+#else
+#error socket blocking is not supported on this platform
+#endif
+#endif
+
+#if SOCKET_EAGAIN != SOCKET_EWOULDBLOCK
+#define HAVE_SOCKET_EWOULDBLOCK 1
+#endif
+
+#ifdef _AIX
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+#endif
+
+/* Function prototypes */
+my_bool pvio_socket_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
+int pvio_socket_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
+ssize_t pvio_socket_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ssize_t pvio_socket_async_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
+ssize_t pvio_socket_async_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
+ssize_t pvio_socket_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
+int pvio_socket_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
+int pvio_socket_blocking(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value);
+my_bool pvio_socket_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
+my_bool pvio_socket_close(MARIADB_PVIO *pvio);
+int pvio_socket_fast_send(MARIADB_PVIO *pvio);
+int pvio_socket_keepalive(MARIADB_PVIO *pvio);
+my_bool pvio_socket_get_handle(MARIADB_PVIO *pvio, void *handle);
+my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio);
+my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio);
+my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len);
+int pvio_socket_shutdown(MARIADB_PVIO *pvio);
+
+static int pvio_socket_init(char *unused1,
+ size_t unused2,
+ int unused3,
+ va_list);
+static int pvio_socket_end(void);
+static ssize_t ma_send(my_socket socket, const uchar *buffer, size_t length, int flags);
+static ssize_t ma_recv(my_socket socket, uchar *buffer, size_t length, int flags);
+
+struct st_ma_pvio_methods pvio_socket_methods= {
+ pvio_socket_set_timeout,
+ pvio_socket_get_timeout,
+ pvio_socket_read,
+ pvio_socket_async_read,
+ pvio_socket_write,
+ pvio_socket_async_write,
+ pvio_socket_wait_io_or_timeout,
+ pvio_socket_blocking,
+ pvio_socket_connect,
+ pvio_socket_close,
+ pvio_socket_fast_send,
+ pvio_socket_keepalive,
+ pvio_socket_get_handle,
+ pvio_socket_is_blocking,
+ pvio_socket_is_alive,
+ pvio_socket_has_data,
+ pvio_socket_shutdown
+};
+
+#ifndef PLUGIN_DYNAMIC
+MARIADB_PVIO_PLUGIN pvio_socket_client_plugin=
+#else
+MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_=
+#endif
+{
+ MARIADB_CLIENT_PVIO_PLUGIN,
+ MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
+ "pvio_socket",
+ "Georg Richter",
+ "MariaDB virtual IO plugin for socket communication",
+ {1, 0, 0},
+ "LGPL",
+ NULL,
+ &pvio_socket_init,
+ &pvio_socket_end,
+ NULL,
+ &pvio_socket_methods
+};
+
+struct st_pvio_socket {
+ my_socket socket;
+ int fcntl_mode;
+ MYSQL *mysql;
+};
+
+static my_bool pvio_socket_initialized= FALSE;
+
+static int pvio_socket_init(char *errmsg __attribute__((unused)),
+ size_t errmsg_length __attribute__((unused)),
+ int unused __attribute__((unused)),
+ va_list va __attribute__((unused)))
+{
+ pvio_socket_initialized= TRUE;
+ return 0;
+}
+
+static int pvio_socket_end(void)
+{
+ if (!pvio_socket_initialized)
+ return 1;
+ return 0;
+}
+
+my_bool pvio_socket_change_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
+{
+ struct timeval tm= {0};
+ int rc= 0;
+ struct st_pvio_socket *csock= NULL;
+ if (!pvio)
+ return 1;
+ if (!(csock= (struct st_pvio_socket *)pvio->data))
+ return 1;
+ tm.tv_sec= timeout / 1000;
+ tm.tv_usec= (timeout % 1000) * 1000;
+ switch(type)
+ {
+ case PVIO_WRITE_TIMEOUT:
+#ifndef _WIN32
+ rc= setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tm, sizeof(tm));
+#else
+ rc= setsockopt(csock->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(int));
+#endif
+ break;
+ case PVIO_READ_TIMEOUT:
+#ifndef _WIN32
+ rc= setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tm, sizeof(tm));
+#else
+ rc= setsockopt(csock->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(int));
+#endif
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
+
+/* {{{ pvio_socket_set_timeout */
+/*
+ set timeout value
+
+ SYNOPSIS
+ pvio_socket_set_timeout
+ pvio PVIO
+ type timeout type (connect, read, write)
+ timeout timeout in seconds
+
+ DESCRIPTION
+ Sets timeout values for connection-, read or write time out.
+ PVIO internally stores all timeout values in milliseconds, but
+ accepts and returns all time values in seconds (like api does).
+
+ RETURNS
+ 0 Success
+ 1 Error
+*/
+my_bool pvio_socket_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
+{
+ struct st_pvio_socket *csock= NULL;
+ if (!pvio)
+ return 1;
+ csock= (struct st_pvio_socket *)pvio->data;
+ pvio->timeout[type]= (timeout > 0) ? timeout * 1000 : -1;
+ if (csock)
+ return pvio_socket_change_timeout(pvio, type, timeout * 1000);
+ return 0;
+}
+/* }}} */
+
+/* {{{ pvio_socket_get_timeout */
+/*
+ get timeout value
+
+ SYNOPSIS
+ pvio_socket_get_timeout
+ pvio PVIO
+ type timeout type (connect, read, write)
+
+ DESCRIPTION
+ Returns timeout values for connection-, read or write time out.
+ PVIO internally stores all timeout values in milliseconds, but
+ accepts and returns all time values in seconds (like api does).
+
+ RETURNS
+ 0...n time out value
+ -1 error
+*/
+int pvio_socket_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
+{
+ if (!pvio)
+ return -1;
+ return pvio->timeout[type] / 1000;
+}
+/* }}} */
+
+/* {{{ pvio_socket_read */
+/*
+ read from socket
+
+ SYNOPSIS
+ pvio_socket_read()
+ pvio PVIO
+ buffer read buffer
+ length buffer length
+
+ DESCRIPTION
+ reads up to length bytes into specified buffer. In the event of an
+ error erno is set to indicate it.
+
+ RETURNS
+ 1..n number of bytes read
+ 0 peer has performed shutdown
+ -1 on error
+
+*/
+ssize_t pvio_socket_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
+{
+ ssize_t r;
+ int read_flags= MSG_DONTWAIT;
+ struct st_pvio_socket *csock;
+ int timeout;
+
+ if (!pvio || !pvio->data)
+ return -1;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+ timeout = pvio->timeout[PVIO_READ_TIMEOUT];
+
+ while ((r = ma_recv(csock->socket, (void *)buffer, length, read_flags)) == -1)
+ {
+ int err = socket_errno;
+ if ((err != SOCKET_EAGAIN
+#ifdef HAVE_SOCKET_EWOULDBLOCK
+ && err != SOCKET_EWOULDBLOCK
+#endif
+ ) || timeout == 0)
+ return r;
+
+ if (pvio_socket_wait_io_or_timeout(pvio, TRUE, timeout) < 1)
+ return -1;
+ }
+ return r;
+}
+/* }}} */
+
+/* {{{ pvio_socket_async_read */
+/*
+ read from socket
+
+ SYNOPSIS
+ pvio_socket_async_read()
+ pvio PVIO
+ buffer read buffer
+ length buffer length
+
+ DESCRIPTION
+ reads up to length bytes into specified buffer. In the event of an
+ error erno is set to indicate it.
+
+ RETURNS
+ 1..n number of bytes read
+ 0 peer has performed shutdown
+ -1 on error
+
+*/
+ssize_t pvio_socket_async_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
+{
+ ssize_t r= -1;
+#ifndef _WIN32
+ int read_flags= MSG_DONTWAIT;
+#endif
+ struct st_pvio_socket *csock= NULL;
+
+ if (!pvio || !pvio->data)
+ return -1;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+
+#ifndef _WIN32
+ r= recv(csock->socket,(void *)buffer, length, read_flags);
+#else
+ /* Windows doesn't support MSG_DONTWAIT, so we need to set
+ socket to non blocking */
+ pvio_socket_blocking(pvio, 0, 0);
+ r= recv(csock->socket, (char *)buffer, (int)length, 0);
+#endif
+ return r;
+}
+/* }}} */
+
+static ssize_t ma_send(my_socket socket, const uchar *buffer, size_t length, int flags)
+{
+ ssize_t r;
+#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE) && !defined(_WIN32)
+ struct sigaction act, oldact;
+ act.sa_handler= SIG_IGN;
+ sigaction(SIGPIPE, &act, &oldact);
+#endif
+ do {
+ r = send(socket, (const char *)buffer, IF_WIN((int)length,length), flags);
+ }
+ while (r == -1 && IS_SOCKET_EINTR(socket_errno));
+#if !defined(MSG_NOSIGNAL) && !defined(SO_NOSIGPIPE) && !defined(_WIN32)
+ sigaction(SIGPIPE, &oldact, NULL);
+#endif
+ return r;
+}
+
+static ssize_t ma_recv(my_socket socket, uchar *buffer, size_t length, int flags)
+{
+ ssize_t r;
+ do {
+ r = recv(socket, (char*) buffer, IF_WIN((int)length, length), flags);
+ }
+ while (r == -1 && IS_SOCKET_EINTR(socket_errno));
+ return r;
+}
+
+/* {{{ pvio_socket_async_write */
+/*
+ write to socket
+
+ SYNOPSIS
+ pvio_socket_async_write()
+ pvio PVIO
+ buffer read buffer
+ length buffer length
+
+ DESCRIPTION
+ writes up to length bytes to socket. In the event of an
+ error erno is set to indicate it.
+
+ RETURNS
+ 1..n number of bytes read
+ 0 peer has performed shutdown
+ -1 on error
+
+*/
+ssize_t pvio_socket_async_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ ssize_t r= -1;
+ struct st_pvio_socket *csock= NULL;
+#ifndef _WIN32
+ int write_flags= MSG_DONTWAIT;
+#ifdef MSG_NOSIGNAL
+ write_flags|= MSG_NOSIGNAL;
+#endif
+#endif
+
+ if (!pvio || !pvio->data)
+ return -1;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+
+#ifndef WIN32
+ r= ma_send(csock->socket, buffer, length, write_flags);
+#else
+ /* Windows doesn't support MSG_DONTWAIT, so we need to set
+ socket to non blocking */
+ pvio_socket_blocking(pvio, 0, 0);
+ r= send(csock->socket, (const char *)buffer, (int)length, 0);
+#endif
+
+ return r;
+}
+/* }}} */
+
+/* {{{ pvio_socket_write */
+/*
+ write to socket
+
+ SYNOPSIS
+ pvio_socket_write()
+ pvio PVIO
+ buffer read buffer
+ length buffer length
+
+ DESCRIPTION
+ writes up to length bytes to socket. In the event of an
+ error erno is set to indicate it.
+
+ RETURNS
+ 1..n number of bytes read
+ 0 peer has performed shutdown
+ -1 on error
+
+*/
+ssize_t pvio_socket_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
+{
+ ssize_t r;
+ struct st_pvio_socket *csock;
+ int timeout;
+ int send_flags= MSG_DONTWAIT;
+#ifdef MSG_NOSIGNAL
+ send_flags|= MSG_NOSIGNAL;
+#endif
+ if (!pvio || !pvio->data)
+ return -1;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+ timeout = pvio->timeout[PVIO_WRITE_TIMEOUT];
+
+ while ((r = ma_send(csock->socket, (void *)buffer, length,send_flags)) == -1)
+ {
+ int err = socket_errno;
+ if ((err != SOCKET_EAGAIN
+#ifdef HAVE_SOCKET_EWOULDBLOCK
+ && err != SOCKET_EWOULDBLOCK
+#endif
+ )|| timeout == 0)
+ return r;
+ if (pvio_socket_wait_io_or_timeout(pvio, FALSE, timeout) < 1)
+ return -1;
+ }
+ return r;
+}
+/* }}} */
+
+int pvio_socket_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
+{
+ int rc;
+ struct st_pvio_socket *csock= NULL;
+
+#ifndef _WIN32
+ struct pollfd p_fd;
+#else
+ struct timeval tv= {0,0};
+ fd_set fds, exc_fds;
+#endif
+
+ if (!pvio || !pvio->data)
+ return 0;
+
+ if (pvio->mysql->options.extension &&
+ pvio->mysql->options.extension->io_wait != NULL) {
+ my_socket handle;
+ if (pvio_socket_get_handle(pvio, &handle))
+ return 0;
+ return pvio->mysql->options.extension->io_wait(handle, is_read, timeout);
+ }
+
+ csock= (struct st_pvio_socket *)pvio->data;
+ {
+#ifndef _WIN32
+ memset(&p_fd, 0, sizeof(p_fd));
+ p_fd.fd= csock->socket;
+ p_fd.events= (is_read) ? POLLIN : POLLOUT;
+
+ if (!timeout)
+ timeout= -1;
+
+ do {
+ rc= poll(&p_fd, 1, timeout);
+ } while (rc == -1 && errno == EINTR);
+
+ if (rc == 0)
+ errno= ETIMEDOUT;
+#else
+ FD_ZERO(&fds);
+ FD_ZERO(&exc_fds);
+
+ FD_SET(csock->socket, &fds);
+ FD_SET(csock->socket, &exc_fds);
+
+ if (timeout >= 0)
+ {
+ tv.tv_sec= timeout / 1000;
+ tv.tv_usec= (timeout % 1000) * 1000;
+ }
+
+ rc= select(0, (is_read) ? &fds : NULL,
+ (is_read) ? NULL : &fds,
+ &exc_fds,
+ (timeout >= 0) ? &tv : NULL);
+
+ if (rc == SOCKET_ERROR)
+ {
+ errno= WSAGetLastError();
+ }
+ else if (rc == 0)
+ {
+ rc= SOCKET_ERROR;
+ WSASetLastError(WSAETIMEDOUT);
+ errno= ETIMEDOUT;
+ }
+ else if (FD_ISSET(csock->socket, &exc_fds))
+ {
+ int err;
+ int len = sizeof(int);
+ if (getsockopt(csock->socket, SOL_SOCKET, SO_ERROR, (char *)&err, &len) != SOCKET_ERROR)
+ {
+ WSASetLastError(err);
+ errno= err;
+ }
+ rc= SOCKET_ERROR;
+ }
+
+#endif
+ }
+ return rc;
+}
+
+int pvio_socket_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
+{
+ my_bool is_blocking;
+ struct st_pvio_socket *csock;
+ int new_fcntl_mode;
+
+ if (!pvio || !pvio->data)
+ return 1;
+
+ csock = (struct st_pvio_socket *)pvio->data;
+
+ is_blocking = !(csock->fcntl_mode & O_NONBLOCK);
+ if (previous_mode)
+ *previous_mode = is_blocking;
+
+ if (is_blocking == block)
+ return 0;
+
+ if (block)
+ new_fcntl_mode = csock->fcntl_mode & ~O_NONBLOCK;
+ else
+ new_fcntl_mode = csock->fcntl_mode | O_NONBLOCK;
+
+#ifdef _WIN32
+ {
+ ulong arg = block ? 0 : 1;
+ if (ioctlsocket(csock->socket, FIONBIO, (void *)&arg))
+ {
+ return(WSAGetLastError());
+ }
+ }
+#else
+ if (fcntl(csock->socket, F_SETFL, new_fcntl_mode) == -1)
+ {
+ return errno;
+ }
+#endif
+ csock->fcntl_mode = new_fcntl_mode;
+ return 0;
+}
+
+static int pvio_socket_internal_connect(MARIADB_PVIO *pvio,
+ const struct sockaddr *name,
+ size_t namelen)
+{
+ int rc= 0;
+ struct st_pvio_socket *csock= NULL;
+ int timeout;
+#ifndef _WIN32
+ unsigned int wait_conn= 1;
+ time_t start_t= time(NULL);
+#endif
+
+ if (!pvio || !pvio->data)
+ return 1;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+ timeout= pvio->timeout[PVIO_CONNECT_TIMEOUT];
+
+ /* set non blocking */
+ pvio_socket_blocking(pvio, 0, 0);
+
+#ifndef _WIN32
+ do {
+ int save_errno;
+ rc= connect(csock->socket, (struct sockaddr*) name, (int)namelen);
+
+ if (time(NULL) - start_t > (time_t)timeout/1000)
+ break;
+
+ /* CONC-612: Since usleep may fail and will set errno (On MacOSX usleep
+ always sets errno=ETIMEDOUT), we need to save and restore errno */
+ save_errno= errno;
+ usleep(wait_conn);
+ errno= save_errno;
+
+ wait_conn= wait_conn >= 1000000 ? 1000000 : wait_conn * 2;
+
+ } while (rc == -1 && (errno == EINTR || errno == EAGAIN));
+ /* in case a timeout values was set we need to check error values
+ EINPROGRESS */
+ if (timeout != 0 && rc == -1 && errno == EINPROGRESS)
+ {
+ rc= pvio_socket_wait_io_or_timeout(pvio, FALSE, timeout);
+ if (rc < 1)
+ return -1;
+ {
+ int error;
+ socklen_t error_len= sizeof(error);
+ if ((rc = getsockopt(csock->socket, SOL_SOCKET, SO_ERROR,
+ (char *)&error, &error_len)) < 0)
+ return errno;
+ else if (error)
+ return error;
+ }
+ }
+#ifdef __APPLE__
+ if (csock->socket)
+ {
+ int val= 1;
+ setsockopt(csock->socket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&val, sizeof(int));
+ }
+#endif
+#else
+ rc= connect(csock->socket, (struct sockaddr*) name, (int)namelen);
+ if (rc == SOCKET_ERROR)
+ {
+ if (WSAGetLastError() == WSAEWOULDBLOCK)
+ {
+ if (pvio_socket_wait_io_or_timeout(pvio, FALSE, timeout) < 0)
+ return -1;
+ rc= 0;
+ }
+ }
+#endif
+ return rc;
+}
+
+int pvio_socket_keepalive(MARIADB_PVIO *pvio)
+{
+ int opt= 1;
+ struct st_pvio_socket *csock= NULL;
+
+ if (!pvio || !pvio->data)
+ return 1;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+
+ return setsockopt(csock->socket, SOL_SOCKET, SO_KEEPALIVE,
+#ifndef _WIN32
+ (const void *)&opt, sizeof(opt));
+#else
+ (char *)&opt, (int)sizeof(opt));
+#endif
+}
+
+int pvio_socket_fast_send(MARIADB_PVIO *pvio)
+{
+ int r= 0;
+ struct st_pvio_socket *csock= NULL;
+
+ if (!pvio || !pvio->data)
+ return 1;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+
+/* Setting IP_TOS is not recommended on Windows. See
+ http://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx
+*/
+#if !defined(_WIN32) && defined(IPTOS_THROUGHPUT)
+ {
+ int tos = IPTOS_THROUGHPUT;
+ r= setsockopt(csock->socket, IPPROTO_IP, IP_TOS,
+ (const void *)&tos, sizeof(tos));
+ }
+#endif /* !_WIN32 && IPTOS_THROUGHPUT */
+ if (!r)
+ {
+ int opt = 1;
+ /* turn off nagle algorithm */
+ r= setsockopt(csock->socket, IPPROTO_TCP, TCP_NODELAY,
+#ifdef _WIN32
+ (const char *)&opt, (int)sizeof(opt));
+#else
+ (const void *)&opt, sizeof(opt));
+#endif
+ }
+ return r;
+}
+
+static int
+pvio_socket_connect_async(MARIADB_PVIO *pvio,
+ const struct sockaddr *name, uint namelen)
+{
+ MYSQL *mysql= pvio->mysql;
+ mysql->options.extension->async_context->pvio= pvio;
+ pvio_socket_blocking(pvio, 0, 0);
+ return my_connect_async(pvio, name, namelen, pvio->timeout[PVIO_CONNECT_TIMEOUT]);
+}
+
+static int
+pvio_socket_connect_sync_or_async(MARIADB_PVIO *pvio,
+ const struct sockaddr *name, uint namelen)
+{
+ MYSQL *mysql= pvio->mysql;
+ if (mysql->options.extension && mysql->options.extension->async_context &&
+ mysql->options.extension->async_context->active)
+ {
+ /* even if we are not connected yet, application needs to check socket
+ * via mysql_get_socket api call, so we need to assign pvio */
+ return pvio_socket_connect_async(pvio, name, namelen);
+ }
+
+ return pvio_socket_internal_connect(pvio, name, namelen);
+}
+
+my_bool pvio_socket_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
+{
+ struct st_pvio_socket *csock= NULL;
+ MYSQL *mysql;
+
+ if (!pvio || !cinfo)
+ return 1;
+
+ if (!(csock= (struct st_pvio_socket *)calloc(1, sizeof(struct st_pvio_socket))))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0, "");
+ return 1;
+ }
+ pvio->data= (void *)csock;
+ csock->socket= INVALID_SOCKET;
+ mysql= pvio->mysql= cinfo->mysql;
+ pvio->type= cinfo->type;
+
+ if (cinfo->type == PVIO_TYPE_UNIXSOCKET)
+ {
+#ifndef _WIN32
+#ifdef HAVE_SYS_UN_H
+ size_t port_length;
+ struct sockaddr_un UNIXaddr;
+ if ((csock->socket = socket(AF_UNIX,SOCK_STREAM,0)) == INVALID_SOCKET ||
+ (port_length=strlen(cinfo->unix_socket)) >= (sizeof(UNIXaddr.sun_path)))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_SOCKET_CREATE_ERROR, unknown_sqlstate, 0, errno);
+ goto error;
+ }
+ memset((char*) &UNIXaddr, 0, sizeof(UNIXaddr));
+ UNIXaddr.sun_family = AF_UNIX;
+#if defined(__linux__)
+ /* Abstract socket */
+ if (cinfo->unix_socket[0] == '@')
+ {
+ strncpy(UNIXaddr.sun_path + 1, cinfo->unix_socket + 1, 106);
+ port_length+= offsetof(struct sockaddr_un, sun_path);
+ }
+ else
+#endif
+ {
+ size_t sun_path_size = sizeof(UNIXaddr.sun_path);
+ strncpy(UNIXaddr.sun_path, cinfo->unix_socket, sun_path_size - 1);
+ if (sun_path_size == strlen(UNIXaddr.sun_path) + 1 && UNIXaddr.sun_path[sun_path_size - 1] != '\0')
+ {
+ /* Making the string null-terminated */
+ UNIXaddr.sun_path[sun_path_size - 1] = '\0';
+ }
+ port_length= sizeof(UNIXaddr);
+ }
+ if (pvio_socket_connect_sync_or_async(pvio, (struct sockaddr *) &UNIXaddr, port_length))
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_CONNECTION_ERROR), cinfo->unix_socket, socket_errno);
+ goto error;
+ }
+ if (pvio_socket_blocking(pvio, 1, 0) == SOCKET_ERROR)
+ {
+ goto error;
+ }
+#else
+/* todo: error, not supported */
+#endif
+#endif
+ } else if (cinfo->type == PVIO_TYPE_SOCKET)
+ {
+ struct addrinfo hints, *save_res= 0, *bind_res= 0, *res= 0, *bres= 0;
+ char server_port[NI_MAXSERV];
+ int gai_rc;
+ int rc= 0;
+ time_t start_t= time(NULL);
+#ifdef _WIN32
+ DWORD wait_gai;
+#else
+ unsigned int wait_gai;
+#endif
+
+ memset(&server_port, 0, NI_MAXSERV);
+ snprintf(server_port, NI_MAXSERV, "%d", cinfo->port);
+
+ /* set hints for getaddrinfo */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_protocol= IPPROTO_TCP; /* TCP connections only */
+ hints.ai_family= AF_UNSPEC; /* includes: IPv4, IPv6 or hostname */
+ hints.ai_socktype= SOCK_STREAM;
+
+ /* if client has multiple interfaces, we will bind socket to given
+ * bind_address */
+ if (cinfo->mysql->options.bind_address)
+ {
+ wait_gai= 1;
+ while ((gai_rc= getaddrinfo(cinfo->mysql->options.bind_address, 0,
+ &hints, &bind_res)) == EAI_AGAIN)
+ {
+ unsigned int timeout= mysql->options.connect_timeout ?
+ mysql->options.connect_timeout : DNS_TIMEOUT;
+ if (time(NULL) - start_t > (time_t)timeout)
+ break;
+#ifndef _WIN32
+ usleep(wait_gai);
+#else
+ Sleep(wait_gai);
+#endif
+ wait_gai*= 2;
+ }
+ if (gai_rc != 0 || !bind_res)
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_BIND_ADDR_FAILED, SQLSTATE_UNKNOWN,
+ CER(CR_BIND_ADDR_FAILED), cinfo->mysql->options.bind_address, gai_rc);
+ goto error;
+ }
+ }
+ /* Get the address information for the server using getaddrinfo() */
+ wait_gai= 1;
+ while ((gai_rc= getaddrinfo(cinfo->host, server_port,
+ &hints, &res)) == EAI_AGAIN)
+ {
+ unsigned int timeout= mysql->options.connect_timeout ?
+ mysql->options.connect_timeout : DNS_TIMEOUT;
+ if (time(NULL) - start_t > (time_t)timeout)
+ break;
+#ifndef _WIN32
+ usleep(wait_gai);
+#else
+ Sleep(wait_gai);
+#endif
+ wait_gai*= 2;
+ }
+ if (gai_rc != 0 || !res)
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_UNKNOWN_HOST, SQLSTATE_UNKNOWN,
+ ER(CR_UNKNOWN_HOST), cinfo->host, gai_rc);
+ if (bind_res)
+ freeaddrinfo(bind_res);
+ goto error;
+ }
+
+ /* res is a linked list of addresses for the given hostname. We loop until
+ we are able to connect to one address or all connect attempts failed */
+ for (save_res= res; save_res; save_res= save_res->ai_next)
+ {
+ /* CONC-364: Avoid leak of open sockets */
+ if (csock->socket != INVALID_SOCKET)
+ closesocket(csock->socket);
+ csock->socket= socket(save_res->ai_family, save_res->ai_socktype,
+ save_res->ai_protocol);
+ if (csock->socket == INVALID_SOCKET)
+ /* Errors will be handled after loop finished */
+ continue;
+
+ if (bind_res)
+ {
+ for (bres= bind_res; bres; bres= bres->ai_next)
+ {
+ if (!(rc= bind(csock->socket, bres->ai_addr, (int)bres->ai_addrlen)))
+ break;
+ }
+ if (rc)
+ {
+ closesocket(csock->socket);
+ csock->socket= INVALID_SOCKET;
+ continue;
+ }
+ }
+
+ if (mysql->options.extension && mysql->options.extension->async_context &&
+ mysql->options.extension->async_context->active)
+ {
+ mysql->options.extension->async_context->pending_gai_res = res;
+ rc= pvio_socket_connect_async(pvio, save_res->ai_addr, (uint)save_res->ai_addrlen);
+ mysql->options.extension->async_context->pending_gai_res = NULL;
+ }
+ else
+ {
+ rc= pvio_socket_connect_sync_or_async(pvio, save_res->ai_addr, (uint)save_res->ai_addrlen);
+ }
+
+ if (!rc)
+ {
+ MYSQL *mysql= pvio->mysql;
+ if (mysql->options.extension && mysql->options.extension->async_context &&
+ mysql->options.extension->async_context->active)
+ break;
+ if (pvio_socket_blocking(pvio, 0, 0) == SOCKET_ERROR)
+ {
+ closesocket(csock->socket);
+ csock->socket= INVALID_SOCKET;
+ continue;
+ }
+ break; /* success! */
+ }
+ }
+
+ freeaddrinfo(res);
+ if (bind_res)
+ freeaddrinfo(bind_res);
+
+ if (csock->socket == INVALID_SOCKET)
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_IPSOCK_ERROR, SQLSTATE_UNKNOWN, ER(CR_IPSOCK_ERROR),
+ socket_errno);
+ goto error;
+ }
+
+ /* last call to connect 2 failed */
+ if (rc)
+ {
+ PVIO_SET_ERROR(cinfo->mysql, CR_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
+ ER(CR_CONN_HOST_ERROR), cinfo->host,
+#ifdef _WIN32
+ errno);
+#else
+ socket_errno);
+#endif
+ goto error;
+ }
+ if (pvio_socket_blocking(pvio, 1, 0) == SOCKET_ERROR)
+ goto error;
+ }
+ /* apply timeouts */
+ if (pvio->timeout[PVIO_CONNECT_TIMEOUT] > 0)
+ {
+ if (pvio_socket_change_timeout(pvio, PVIO_READ_TIMEOUT, pvio->timeout[PVIO_CONNECT_TIMEOUT]) ||
+ pvio_socket_change_timeout(pvio, PVIO_WRITE_TIMEOUT, pvio->timeout[PVIO_CONNECT_TIMEOUT]))
+ goto error;
+ }
+ else
+ {
+ if (pvio->timeout[PVIO_WRITE_TIMEOUT] > 0)
+ if (pvio_socket_change_timeout(pvio, PVIO_WRITE_TIMEOUT, pvio->timeout[PVIO_WRITE_TIMEOUT]))
+ goto error;
+ if (pvio->timeout[PVIO_READ_TIMEOUT] > 0)
+ if (pvio_socket_change_timeout(pvio, PVIO_READ_TIMEOUT, pvio->timeout[PVIO_READ_TIMEOUT]))
+ goto error;
+ }
+ return 0;
+error:
+ /* close socket: MDEV-10891 */
+ if (csock->socket != INVALID_SOCKET)
+ {
+ closesocket(csock->socket);
+ csock->socket= INVALID_SOCKET;
+ }
+ if (pvio->data)
+ {
+ free((gptr)pvio->data);
+ pvio->data= NULL;
+ }
+ return 1;
+}
+
+/* {{{ my_bool pvio_socket_close() */
+my_bool pvio_socket_close(MARIADB_PVIO *pvio)
+{
+ struct st_pvio_socket *csock= NULL;
+ int r= 0;
+
+ if (!pvio)
+ return 1;
+
+ if (pvio->data)
+ {
+ csock= (struct st_pvio_socket *)pvio->data;
+ if (csock && csock->socket != INVALID_SOCKET)
+ {
+ r= closesocket(csock->socket);
+ csock->socket= INVALID_SOCKET;
+ }
+ free((gptr)pvio->data);
+ pvio->data= NULL;
+ }
+ return r;
+}
+/* }}} */
+
+/* {{{ my_socket pvio_socket_get_handle */
+my_bool pvio_socket_get_handle(MARIADB_PVIO *pvio, void *handle)
+{
+ if (pvio && pvio->data && handle)
+ {
+ *(my_socket *)handle= ((struct st_pvio_socket *)pvio->data)->socket;
+ return 0;
+ }
+ return 1;
+}
+/* }}} */
+
+/* {{{ my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio) */
+my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio)
+{
+ struct st_pvio_socket *csock= NULL;
+ my_bool r;
+
+ if (!pvio || !pvio->data)
+ return 0;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+ r = !(csock->fcntl_mode & O_NONBLOCK);
+ return r;
+}
+/* }}} */
+
+/* {{{ my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio) */
+my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio)
+{
+ struct st_pvio_socket *csock= NULL;
+ #ifndef _WIN32
+ struct pollfd poll_fd;
+#else
+ FD_SET sfds;
+ struct timeval tv= {0,0};
+#endif
+ int res;
+
+ if (!pvio || !pvio->data)
+ return 0;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+#ifndef _WIN32
+ memset(&poll_fd, 0, sizeof(struct pollfd));
+ poll_fd.events= POLLPRI | POLLIN;
+ poll_fd.fd= csock->socket;
+
+ res= poll(&poll_fd, 1, 0);
+ if (res <= 0) /* timeout or error */
+ return FALSE;
+ if (!(poll_fd.revents & (POLLIN | POLLPRI)))
+ return FALSE;
+ return TRUE;
+#else
+ /* We can't use the WSAPoll function, it's broken :-(
+ (see Windows 8 Bugs 309411 - WSAPoll does not report failed connections)
+ Instead we need to use select function:
+ If TIMEVAL is initialized to {0, 0}, select will return immediately;
+ this is used to poll the state of the selected sockets.
+ */
+ FD_ZERO(&sfds);
+ FD_SET(csock->socket, &sfds);
+
+ res= select((int)csock->socket + 1, &sfds, NULL, NULL, &tv);
+ if (res > 0 && FD_ISSET(csock->socket, &sfds))
+ return TRUE;
+ return FALSE;
+#endif
+}
+/* }}} */
+
+/* {{{ my_boool pvio_socket_has_data */
+my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
+{
+ struct st_pvio_socket *csock= NULL;
+ char tmp_buf;
+ ssize_t len;
+ my_bool mode;
+
+ if (!pvio || !pvio->data)
+ return 0;
+
+ csock= (struct st_pvio_socket *)pvio->data;
+ /* MSG_PEEK: Peeks at the incoming data. The data is copied into the buffer,
+ but is not removed from the input queue.
+ */
+ pvio_socket_blocking(pvio, 0, &mode);
+ len= recv(csock->socket, &tmp_buf, sizeof(tmp_buf), MSG_PEEK);
+ pvio_socket_blocking(pvio, mode, 0);
+ if (len < 0)
+ return 1;
+ *data_len= len;
+ return 0;
+}
+/* }}} */
+
+int pvio_socket_shutdown(MARIADB_PVIO *pvio)
+{
+ if (pvio && pvio->data)
+ {
+ my_socket s = ((struct st_pvio_socket *)pvio->data)->socket;
+#ifdef _WIN32
+ shutdown(s, SD_BOTH);
+ CancelIoEx((HANDLE)s, NULL);
+#else
+ shutdown(s, SHUT_RDWR);
+#endif
+ }
+ return -1;
+}
+
diff --git a/libmariadb/plugins/trace/trace_example.c b/libmariadb/plugins/trace/trace_example.c
new file mode 100644
index 00000000..1060542c
--- /dev/null
+++ b/libmariadb/plugins/trace/trace_example.c
@@ -0,0 +1,458 @@
+/************************************************************************************
+ Copyright (C) 2015 MariaDB Corporation AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+*************************************************************************************/
+#ifndef _WIN32
+#define _GNU_SOURCE 1
+#endif
+
+#include <ma_global.h>
+#include <mysql.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <memory.h>
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+#define READ 0
+#define WRITE 1
+
+/* function prototypes */
+static int trace_init(char *errormsg,
+ size_t errormsg_size,
+ int unused __attribute__((unused)),
+ va_list unused1 __attribute__((unused)));
+static int trace_deinit(void);
+
+int (*register_callback)(my_bool register_callback,
+ void (*callback_function)(int mode, MYSQL *mysql, const uchar *buffer, size_t length));
+void trace_callback(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
+
+#ifndef HAVE_TRACE_EXAMPLE_PLUGIN_DYNAMIC
+struct st_mysql_client_plugin trace_example_plugin=
+#else
+struct st_mysql_client_plugin _mysql_client_plugin_declaration_ =
+#endif
+{
+ MARIADB_CLIENT_TRACE_PLUGIN,
+ MARIADB_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION,
+ "trace_example",
+ "Georg Richter",
+ "Trace example plugin",
+ {1,0,0},
+ "LGPL",
+ NULL,
+ &trace_init,
+ &trace_deinit,
+ NULL
+};
+
+static const char *commands[]= {
+ "COM_SLEEP",
+ "COM_QUIT",
+ "COM_INIT_DB",
+ "COM_QUERY",
+ "COM_FIELD_LIST",
+ "COM_CREATE_DB",
+ "COM_DROP_DB",
+ "COM_REFRESH",
+ "COM_SHUTDOWN",
+ "COM_STATISTICS",
+ "COM_PROCESS_INFO",
+ "COM_CONNECT",
+ "COM_PROCESS_KILL",
+ "COM_DEBUG",
+ "COM_PING",
+ "COM_TIME",
+ "COM_DELAYED_INSERT",
+ "COM_CHANGE_USER",
+ "COM_BINLOG_DUMP",
+ "COM_TABLE_DUMP",
+ "COM_CONNECT_OUT",
+ "COM_REGISTER_SLAVE",
+ "COM_STMT_PREPARE",
+ "COM_STMT_EXECUTE",
+ "COM_STMT_SEND_LONG_DATA",
+ "COM_STMT_CLOSE",
+ "COM_STMT_RESET",
+ "COM_SET_OPTION",
+ "COM_STMT_FETCH",
+ "COM_DAEMON",
+ "COM_END"
+};
+
+typedef struct {
+ unsigned long thread_id;
+ int last_command; /* COM_* values, -1 for handshake */
+ unsigned int max_packet_size;
+ unsigned int num_commands;
+ size_t total_size[2];
+ unsigned int client_flags;
+ char *username;
+ char *db;
+ char *command;
+ char *filename;
+ unsigned long refid; /* stmt_id, thread_id for kill */
+ uchar charset;
+ void *next;
+ int local_infile;
+ unsigned long pkt_length;
+} TRACE_INFO;
+
+#define TRACE_STATUS(a) ((!a) ? "ok" : "error")
+
+TRACE_INFO *trace_info= NULL;
+
+static TRACE_INFO *get_trace_info(unsigned long thread_id)
+{
+ TRACE_INFO *info= trace_info;
+
+ /* search connection */
+ while (info)
+ {
+ if (info->thread_id == thread_id)
+ return info;
+ else
+ info= (TRACE_INFO *)info->next;
+ }
+
+ if (!(info= (TRACE_INFO *)calloc(sizeof(TRACE_INFO), 1)))
+ return NULL;
+ info->thread_id= thread_id;
+ info->next= trace_info;
+ trace_info= info;
+ return info;
+}
+
+static void delete_trace_info(unsigned long thread_id)
+{
+ TRACE_INFO *last= NULL, *current;
+ current= trace_info;
+
+ while (current)
+ {
+ if (current->thread_id == thread_id)
+ {
+ printf("deleting thread %lu\n", thread_id);
+
+ if (last)
+ last->next= current->next;
+ else
+ trace_info= (TRACE_INFO *)current->next;
+ if (current->command)
+ free(current->command);
+ if (current->db)
+ free(current->db);
+ if (current->username)
+ free(current->username);
+ if (current->filename)
+ free(current->filename);
+ free(current);
+ }
+ last= current;
+ current= (TRACE_INFO *)current->next;
+ }
+
+}
+
+
+/* {{{ static int trace_init */
+/*
+ Initialization routine
+
+ SYNOPSIS
+ trace_init
+ unused1
+ unused2
+ unused3
+ unused4
+
+ DESCRIPTION
+ Init function registers a callback handler for PVIO interface.
+
+ RETURN
+ 0 success
+*/
+static int trace_init(char *errormsg,
+ size_t errormsg_size,
+ int unused1 __attribute__((unused)),
+ va_list unused2 __attribute__((unused)))
+{
+ void *func;
+
+#ifdef WIN32
+ if (!(func= GetProcAddress(GetModuleHandle(NULL), "ma_pvio_register_callback")))
+#else
+ if (!(func= dlsym(RTLD_DEFAULT, "ma_pvio_register_callback")))
+#endif
+ {
+ strncpy(errormsg, "Can't find ma_pvio_register_callback function", errormsg_size);
+ return 1;
+ }
+ register_callback= func;
+ register_callback(TRUE, trace_callback);
+
+ return 0;
+}
+/* }}} */
+
+static int trace_deinit(void)
+{
+ /* unregister plugin */
+ while(trace_info)
+ {
+ printf("Warning: Connection for thread %lu not properly closed\n", trace_info->thread_id);
+ trace_info= (TRACE_INFO *)trace_info->next;
+ }
+ register_callback(FALSE, trace_callback);
+ return 0;
+}
+
+static void trace_set_command(TRACE_INFO *info, char *buffer, size_t size)
+{
+ if (info->command)
+ free(info->command);
+
+ info->command= calloc(1, size + 1);
+ memcpy(info->command, buffer, size);
+}
+
+void dump_buffer(uchar *buffer, size_t len)
+{
+ uchar *p= buffer;
+ while (p < buffer + len)
+ {
+ printf("%02x ", *p);
+ p++;
+ }
+ printf("\n");
+}
+
+static void dump_simple(TRACE_INFO *info, my_bool is_error)
+{
+ printf("%8lu: %s %s\n", info->thread_id, commands[info->last_command], TRACE_STATUS(is_error));
+}
+
+static void dump_reference(TRACE_INFO *info, my_bool is_error)
+{
+ printf("%8lu: %s(%lu) %s\n", info->thread_id, commands[info->last_command], (long)info->refid, TRACE_STATUS(is_error));
+}
+
+static void dump_command(TRACE_INFO *info, my_bool is_error)
+{
+ size_t i;
+ printf("%8lu: %s(", info->thread_id, commands[info->last_command]);
+ for (i= 0; info->command && i < strlen(info->command); i++)
+ if (info->command[i] == '\n')
+ printf("\\n");
+ else if (info->command[i] == '\r')
+ printf("\\r");
+ else if (info->command[i] == '\t')
+ printf("\\t");
+ else
+ printf("%c", info->command[i]);
+ printf(") %s\n", TRACE_STATUS(is_error));
+}
+
+void trace_callback(int mode, MYSQL *mysql, const uchar *buffer, size_t length)
+{
+ unsigned long thread_id= mysql->thread_id;
+ TRACE_INFO *info;
+
+ /* check if package is server greeting package,
+ * and set thread_id */
+ if (!thread_id && mode == READ)
+ {
+ char *p= (char *)buffer;
+ p+= 4; /* packet length */
+ if ((uchar)*p != 0xFF) /* protocol version 0xFF indicates error */
+ {
+ p+= strlen(p + 1) + 2;
+ thread_id= uint4korr(p);
+ }
+ info= get_trace_info(thread_id);
+ info->last_command= -1;
+ }
+ else
+ {
+ char *p= (char *)buffer;
+ info= get_trace_info(thread_id);
+
+ if (info->last_command == -1)
+ {
+ if (mode == WRITE)
+ {
+ /* client authentication reply packet:
+ *
+ * ofs description length
+ * ------------------------
+ * 0 length 3
+ * 3 packet_no 1
+ * 4 client capab. 4
+ * 8 max_packet_size 4
+ * 12 character set 1
+ * 13 reserved 23
+ * ------------------------
+ * 36 username (zero terminated)
+ * len (1 byte) + password or
+ */
+
+ p+= 4;
+ info->client_flags= uint4korr(p);
+ p+= 4;
+ info->max_packet_size= uint4korr(p);
+ p+= 4;
+ info->charset= *p;
+ p+= 24;
+ info->username= strdup(p);
+ p+= strlen(p) + 1;
+ if (*p) /* we are not interested in authentication data */
+ p+= *p;
+ p++;
+ if (info->client_flags & CLIENT_CONNECT_WITH_DB)
+ info->db= strdup(p);
+ }
+ else
+ {
+ p++;
+ if ((uchar)*p == 0xFF)
+ printf("%8lu: CONNECT_ERROR(%d)\n", info->thread_id, uint4korr(p+1));
+ else
+ printf("%8lu: CONNECT_SUCCESS(host=%s,user=%s,db=%s)\n", info->thread_id,
+ mysql->host, info->username, info->db ? info->db : "'none'");
+ info->last_command= COM_SLEEP;
+ }
+ }
+ else {
+ char *p= (char *)buffer;
+ int len;
+
+ if (mode == WRITE)
+ {
+ if (info->pkt_length > 0)
+ {
+ info->pkt_length-= length;
+ return;
+ }
+ len= uint3korr(p);
+ info->pkt_length= len + 4 - length;
+ p+= 4;
+ info->last_command= *p;
+ p++;
+
+ switch (info->last_command) {
+ case COM_INIT_DB:
+ case COM_DROP_DB:
+ case COM_CREATE_DB:
+ case COM_DEBUG:
+ case COM_QUERY:
+ case COM_STMT_PREPARE:
+ trace_set_command(info, p, len - 1);
+ break;
+ case COM_PROCESS_KILL:
+ info->refid= uint4korr(p);
+ break;
+ case COM_QUIT:
+ printf("%8lu: COM_QUIT\n", info->thread_id);
+ delete_trace_info(info->thread_id);
+ break;
+ case COM_PING:
+ printf("%8lu: COM_PING\n", info->thread_id);
+ break;
+ case COM_STMT_EXECUTE:
+ case COM_STMT_RESET:
+ case COM_STMT_CLOSE:
+ info->refid= uint4korr(p);
+ break;
+ case COM_CHANGE_USER:
+ break;
+ default:
+ if (info->local_infile == 1)
+ {
+ printf("%8lu: SEND_LOCAL_INFILE(%s) ", info->thread_id, info->filename);
+ if (len)
+ printf("sent %d bytes\n", len);
+ else
+ printf("- error\n");
+ info->local_infile= 2;
+ }
+ else
+ printf("%8lu: UNKNOWN_COMMAND: %d\n", info->thread_id, info->last_command);
+ break;
+ }
+ }
+ else
+ {
+ my_bool is_error;
+
+ len= uint3korr(p);
+ p+= 4;
+
+ is_error= (len == -1);
+
+ switch(info->last_command) {
+ case COM_STMT_EXECUTE:
+ case COM_STMT_RESET:
+ case COM_STMT_CLOSE:
+ case COM_PROCESS_KILL:
+ dump_reference(info, is_error);
+ info->refid= 0;
+ info->last_command= 0;
+ break;
+ case COM_QUIT:
+ dump_simple(info, is_error);
+ break;
+ case COM_QUERY:
+ case COM_INIT_DB:
+ case COM_DROP_DB:
+ case COM_CREATE_DB:
+ case COM_DEBUG:
+ case COM_CHANGE_USER:
+ if (info->last_command == COM_QUERY && (uchar)*p == 251)
+ {
+ info->local_infile= 1;
+ p++;
+ info->filename= (char *)malloc(len);
+ strncpy(info->filename, (char *)p, len);
+ dump_command(info, is_error);
+ break;
+ }
+ dump_command(info, is_error);
+ if (info->local_infile != 1)
+ {
+ free(info->command);
+ info->command= NULL;
+ }
+ break;
+ case COM_STMT_PREPARE:
+ printf("%8lu: COM_STMT_PREPARE(%s) ", info->thread_id, info->command);
+ if (!*p)
+ {
+ unsigned long stmt_id= uint4korr(p+1);
+ printf("-> stmt_id(%lu)\n", stmt_id);
+ }
+ else
+ printf("error\n");
+ break;
+ }
+ }
+ }
+ }
+ info->total_size[mode]+= length;
+}
diff --git a/libmariadb/scripts/create_man b/libmariadb/scripts/create_man
new file mode 100755
index 00000000..4ff118b0
--- /dev/null
+++ b/libmariadb/scripts/create_man
@@ -0,0 +1,54 @@
+#!/usr/bin/python3
+
+import re
+import os
+import argparse
+
+def read_content(file):
+ try:
+ f=open(file, "r")
+ content= f.read()
+ f.close()
+ except:
+ raise
+ return content
+
+def header(function, version):
+ hdr= "%% %s(3) Version %s | MariaDB Connector/C\n" % (function, version)
+ return hdr
+
+def replace_links(content):
+ links= list(re.compile(r'\[([^\]]+)\]\(([^)]+)\)').findall(content))
+ for l in links:
+ search= "[%s()](%s)" % (l[1], l[1])
+ replace= "**%s(3)**" % l[1]
+ content= content.replace(search, replace)
+ return content
+
+parser= argparse.ArgumentParser(prog="create_man.py",
+ description="Create man pages for MariaDB Connector/C")
+parser.add_argument('--docs', type=str, metavar='docs', help='Directory of MariaDB Connector/C documentation')
+parser.add_argument('--funcs', type=str, metavar='funcs', help='File which contains exported functions.')
+parser.add_argument('--version', type=str, metavar='version', help='Connector/C version')
+args= parser.parse_args()
+print(args)
+
+func_list= read_content(args.funcs)
+funcs= func_list.split(";")
+
+for function in funcs:
+
+ try:
+ print("%s/%s.md" % (args.docs, function))
+ content= read_content("%s/%s.md" % (args.docs, function))
+
+ except:
+ print("warning: No documentation for function %s found" % function)
+ continue
+
+ f= open("%s.3.md" % function, "w")
+ f.write(header(function, args.version))
+ f.write(replace_links(content))
+ f.close()
+ ret= os.system("pandoc --standalone --to man %s.3.md -o man/%s.3" % (function, function))
+ os.unlink("%s.3.md" % function)
diff --git a/libmariadb/travis.sh b/libmariadb/travis.sh
new file mode 100755
index 00000000..c316dec2
--- /dev/null
+++ b/libmariadb/travis.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+
+set -e
+
+if [ -n "$BENCH" ] ; then
+ sudo benchmark/build.sh
+ cd benchmark
+ sudo ./installation.sh
+ sudo ./launch.sh
+ exit
+fi
+
+export CC_DIR=/home/travis/build/mariadb-corporation/mariadb-connector-c
+if [ -n "$server_branch" ] ; then
+
+ ###################################################################################################################
+ # run server test suite
+ ###################################################################################################################
+ echo "run server test suite"
+
+ # change travis localhost to use only 127.0.0.1
+ sudo sed -i 's/127\.0\.1\.1 localhost/127.0.0.1 localhost/' /etc/hosts
+ sudo tail /etc/hosts
+
+ # get latest server
+ git clone -b ${server_branch} https://github.com/mariadb/server ../workdir-server --depth=1
+
+ cd ../workdir-server
+ export SERVER_DIR=$PWD
+
+ # don't pull in submodules. We want the latest C/C as libmariadb
+ # build latest server with latest C/C as libmariadb
+ # skip to build some storage engines to speed up the build
+
+ mkdir bld
+ cd bld
+ cmake .. -DPLUGIN_MROONGA=NO -DPLUGIN_ROCKSDB=NO -DPLUGIN_SPIDER=NO -DPLUGIN_TOKUDB=NO
+ echo "PR:${TRAVIS_PULL_REQUEST} TRAVIS_COMMIT:${TRAVIS_COMMIT}"
+ if [ -n "$TRAVIS_PULL_REQUEST" ] && [ "$TRAVIS_PULL_REQUEST" != "false" ] ; then
+ # fetching pull request
+ echo "fetching PR"
+ else
+ echo "checkout commit"
+ fi
+
+ cp $CC_DIR/* $SERVER_DIR/libmariadb -r
+ cd $SERVER_DIR
+ git add libmariadb
+
+ cd $SERVER_DIR/bld
+ make -j9
+
+ cd mysql-test/
+ ./mysql-test-run.pl --suite=main ${TEST_OPTION} --parallel=auto --skip-test=session_tracker_last_gtid
+
+else
+
+ ###################################################################################################################
+ # run connector test suite
+ ###################################################################################################################
+ echo "run connector test suite"
+
+ mkdir bld
+ cd bld
+ cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCERT_PATH=${SSLCERT}
+
+ if [ "$TRAVIS_OS_NAME" = "windows" ] ; then
+ echo "build from windows"
+ set MARIADB_CC_TEST=1
+ set MYSQL_TEST_DB=testc
+ set MYSQL_TEST_TLS=%TEST_REQUIRE_TLS%
+ set MYSQL_TEST_USER=%TEST_DB_USER%
+ set MYSQL_TEST_HOST=%TEST_DB_HOST%
+ set MYSQL_TEST_PASSWD=%TEST_DB_PASSWORD%
+ set MYSQL_TEST_PORT=%TEST_DB_PORT%
+ set MYSQL_TEST_TLS=%TEST_REQUIRE_TLS%
+ cmake --build . --config RelWithDebInfo
+ else
+ echo "build from linux"
+ export MARIADB_CC_TEST=1
+ export MYSQL_TEST_USER=$TEST_DB_USER
+ export MYSQL_TEST_HOST=$TEST_DB_HOST
+ export MYSQL_TEST_PASSWD=$TEST_DB_PASSWORD
+ export MYSQL_TEST_PORT=$TEST_DB_PORT
+ export MYSQL_TEST_DB=testc
+ export MYSQL_TEST_TLS=$TEST_REQUIRE_TLS
+ export SSLCERT=$TEST_DB_SERVER_CERT
+ export MARIADB_PLUGIN_DIR=$PWD
+
+ echo "MYSQL_TEST_PLUGINDIR=$MYSQL_TEST_PLUGINDIR"
+ if [ -n "$MYSQL_TEST_SSL_PORT" ] ; then
+ export MYSQL_TEST_SSL_PORT=$MYSQL_TEST_SSL_PORT
+ fi
+ export MYSQL_TEST_TLS=$TEST_REQUIRE_TLS
+ export SSLCERT=$TEST_DB_SERVER_CERT
+ if [ -n "$TEST_MAXSCALE_TLS_PORT" ] ; then
+ export MYSQL_TEST_SSL_PORT=$TEST_MAXSCALE_TLS_PORT
+ fi
+ make
+ fi
+
+ ls -lrt
+
+ openssl ciphers -v
+ cd unittest/libmariadb
+ ctest -V
+fi
diff --git a/libmariadb/unittest/libmariadb/CMakeLists.txt b/libmariadb/unittest/libmariadb/CMakeLists.txt
new file mode 100644
index 00000000..876e5cfc
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/CMakeLists.txt
@@ -0,0 +1,67 @@
+# Copyright (C) 2008 Sun Microsystems, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+IF(SKIP_TESTS)
+ RETURN()
+ENDIF()
+
+ENABLE_TESTING()
+
+
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
+ ${CC_BINARY_DIR}/include
+ ${CC_SOURCE_DIR}/unittest/mytap
+ ${CC_SOURCE_DIR}/unittest/libmariadb)
+ADD_DEFINITIONS(-DLIBMARIADB)
+
+SET(API_TESTS "conc336" "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "thread" "features-10_2")
+IF(WITH_DYNCOL)
+ SET(API_TESTS ${API_TESTS} "dyncol")
+ENDIF()
+
+SET(API_TESTS ${API_TESTS} "async")
+
+#exclude following tests from ctests, since we need to run them manually with different credentials
+SET(MANUAL_TESTS "t_conc173" "rpl_api")
+# Get finger print from server certificate
+IF(WITH_SSL)
+ IF(CERT_PATH AND NOT DEFINED ENV{TRAVIS})
+ SET(API_TESTS ${API_TESTS} "ssl")
+ IF(WIN32)
+ STRING(REPLACE "\\" "\\\\" CERT_PATH ${CERT_PATH})
+ ENDIF()
+ ADD_DEFINITIONS(-DCERT_PATH="${CERT_PATH}")
+ ENDIF()
+ENDIF()
+
+ADD_LIBRARY(ma_getopt ma_getopt.c)
+
+FOREACH(API_TEST ${API_TESTS})
+ IF (NOT TARGET ${API_TEST})
+ ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c)
+ ENDIF()
+ TARGET_LINK_LIBRARIES(${API_TEST} cctap ma_getopt mariadbclient)
+ ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST})
+ IF(${API_TEST} STREQUAL "cursor" OR ${API_TEST} STREQUAL "ps_new")
+ SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 360)
+ ELSE()
+ SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 180)
+ ENDIF()
+ENDFOREACH(API_TEST)
+
+FOREACH(API_TEST ${MANUAL_TESTS})
+ ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c)
+ TARGET_LINK_LIBRARIES(${API_TEST} cctap ma_getopt mariadbclient)
+ENDFOREACH()
diff --git a/libmariadb/unittest/libmariadb/async.c b/libmariadb/unittest/libmariadb/async.c
new file mode 100644
index 00000000..bc6beaff
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/async.c
@@ -0,0 +1,321 @@
+/*
+ Copyright 2011 Kristian Nielsen and Monty Program Ab.
+
+ This file is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "my_test.h"
+#include "ma_common.h"
+
+
+#ifndef _WIN32
+#include <poll.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <mysql.h>
+
+my_bool skip_async= 0;
+
+static int test_async(MYSQL *mysql)
+{
+ int type;
+ mariadb_get_info(mysql, MARIADB_CONNECTION_PVIO_TYPE, &type);
+ if (type > MARIADB_CONNECTION_TCP)
+ {
+ skip_async= 1;
+ diag("Async IO not supported");
+ }
+ return OK;
+}
+
+static int
+wait_for_mysql(MYSQL *mysql, int status)
+{
+#ifdef _WIN32
+ fd_set rs, ws, es;
+ int res;
+ struct timeval tv, *timeout;
+ my_socket s= mysql_get_socket(mysql);
+ FD_ZERO(&rs);
+ FD_ZERO(&ws);
+ FD_ZERO(&es);
+ if (status & MYSQL_WAIT_READ)
+ FD_SET(s, &rs);
+ if (status & MYSQL_WAIT_WRITE)
+ FD_SET(s, &ws);
+ if (status & MYSQL_WAIT_EXCEPT)
+ FD_SET(s, &es);
+ if (status & MYSQL_WAIT_TIMEOUT)
+ {
+ tv.tv_sec= mysql_get_timeout_value(mysql);
+ tv.tv_usec= 0;
+ timeout= &tv;
+ }
+ else
+ timeout= NULL;
+ res= select(1, &rs, &ws, &es, timeout);
+ if (res == 0)
+ return MYSQL_WAIT_TIMEOUT;
+ else if (res == SOCKET_ERROR)
+ {
+ /*
+ In a real event framework, we should handle errors and re-try the select.
+ */
+ return MYSQL_WAIT_TIMEOUT;
+ }
+ else
+ {
+ int status= 0;
+ if (FD_ISSET(s, &rs))
+ status|= MYSQL_WAIT_READ;
+ if (FD_ISSET(s, &ws))
+ status|= MYSQL_WAIT_WRITE;
+ if (FD_ISSET(s, &es))
+ status|= MYSQL_WAIT_EXCEPT;
+ return status;
+ }
+#else
+ struct pollfd pfd;
+ int timeout;
+ int res= -1;
+
+ pfd.fd= mysql_get_socket(mysql);
+ pfd.events=
+ (status & MYSQL_WAIT_READ ? POLLIN : 0) |
+ (status & MYSQL_WAIT_WRITE ? POLLOUT : 0) |
+ (status & MYSQL_WAIT_EXCEPT ? POLLPRI : 0);
+ if (status & MYSQL_WAIT_TIMEOUT)
+ {
+ timeout= mysql_get_timeout_value_ms(mysql);
+ }
+ else
+ timeout= -1;
+ do {
+ res= poll(&pfd, 1, timeout);
+ } while (res == -1 && errno == EINTR);
+ if (res == 0)
+ return MYSQL_WAIT_TIMEOUT;
+ else if (res < 0)
+ {
+ /*
+ In a real event framework, we should handle EINTR and re-try the poll.
+ */
+ return MYSQL_WAIT_TIMEOUT;
+ }
+ else
+ {
+ int status= 0;
+ if (pfd.revents & POLLIN)
+ status|= MYSQL_WAIT_READ;
+ if (pfd.revents & POLLOUT)
+ status|= MYSQL_WAIT_WRITE;
+ if (pfd.revents & POLLPRI)
+ status|= MYSQL_WAIT_EXCEPT;
+ return status;
+ }
+#endif
+}
+
+static int async1(MYSQL *unused __attribute__((unused)))
+{
+ int err= 0, rc;
+ MYSQL mysql, *ret;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int status;
+ uint default_timeout;
+ int i;
+
+ if (skip_async)
+ return SKIP;
+
+ for (i=0; i < 100; i++)
+ {
+
+ mysql_init(&mysql);
+ rc= mysql_options(&mysql, MYSQL_OPT_NONBLOCK, 0);
+ check_mysql_rc(rc, (MYSQL *)&mysql);
+
+ /* set timeouts to 300 microseconds */
+ default_timeout= 3;
+ mysql_options(&mysql, MYSQL_OPT_READ_TIMEOUT, &default_timeout);
+ mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &default_timeout);
+ mysql_options(&mysql, MYSQL_OPT_WRITE_TIMEOUT, &default_timeout);
+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "myapp");
+ if (force_tls)
+ mysql_ssl_set(&mysql, NULL, NULL, NULL, NULL,NULL);
+
+ /* Returns 0 when done, else flag for what to wait for when need to block. */
+ status= mysql_real_connect_start(&ret, &mysql, hostname, username, password, schema, port, socketname, 0);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_real_connect_cont(&ret, &mysql, status);
+ }
+ if (!ret)
+ {
+ diag("Error: %s", mysql_error(&mysql));
+ FAIL_IF(!ret, "Failed to mysql_real_connect()");
+ }
+
+ if (force_tls && !mysql_get_ssl_cipher(&mysql))
+ {
+ diag("Error: No tls connection");
+ return FAIL;
+ }
+
+ status= mysql_real_query_start(&err, &mysql, SL("SHOW STATUS"));
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_real_query_cont(&err, &mysql, status);
+ }
+ FAIL_IF(err, "mysql_real_query() returns error");
+
+ /* This method cannot block. */
+ res= mysql_use_result(&mysql);
+ FAIL_IF(!res, "mysql_use_result() returns error");
+
+ for (;;)
+ {
+ status= mysql_fetch_row_start(&row, res);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_fetch_row_cont(&row, res, status);
+ }
+ if (!row)
+ break;
+ }
+ FAIL_IF(mysql_errno(&mysql), "Got error while retrieving rows");
+ mysql_free_result(res);
+
+ /*
+ mysql_close() sends a COM_QUIT packet, and so in principle could block
+ waiting for the socket to accept the data.
+ In practise, for many applications it will probably be fine to use the
+ blocking mysql_close().
+ */
+ status= mysql_close_start(&mysql);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_close_cont(&mysql, status);
+ }
+ }
+ return OK;
+}
+
+static int test_conc131(MYSQL *unused __attribute__((unused)))
+{
+ int rc;
+ /* this test needs to run under valgrind */
+ MYSQL *mysql;
+
+ if (skip_async)
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ rc= mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0);
+ check_mysql_rc(rc, mysql);
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc129(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (skip_async)
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(mysql_close_start(mysql), "No error expected");
+ return OK;
+}
+
+static int test_conc622(MYSQL *my __attribute__((unused)))
+{
+ int rc;
+ MYSQL mysql, *ret;
+ int status;
+ uint default_timeout;
+ int i;
+ const char *invalid_host= "1.0.0.0";
+
+ if (skip_async)
+ return SKIP;
+
+ for (i=0; i < 5; i++)
+ {
+ mysql_init(&mysql);
+ rc= mysql_options(&mysql, MYSQL_OPT_NONBLOCK, 0);
+ check_mysql_rc(rc, (MYSQL *)&mysql);
+
+ /* set timeouts to 300 microseconds */
+ default_timeout= 3;
+ mysql_options(&mysql, MYSQL_OPT_READ_TIMEOUT, &default_timeout);
+ mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &default_timeout);
+ mysql_options(&mysql, MYSQL_OPT_WRITE_TIMEOUT, &default_timeout);
+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "myapp");
+
+ /* Returns 0 when done, else flag for what to wait for when need to block. */
+ status= mysql_real_connect_start(&ret, &mysql, invalid_host, username, password, schema, port, socketname, 0);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_real_connect_cont(&ret, &mysql, status);
+ }
+ if (!ret)
+ {
+ status= mysql_close_start(&mysql);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_close_cont(&mysql, status);
+ }
+ } else {
+ diag("Expected error when connecting to host '%s'", invalid_host);
+ diag("Connected to %s", mysql_get_server_info(&mysql));
+ return FAIL;
+ }
+ }
+ return OK;
+}
+
+
+struct my_tests_st my_tests[] = {
+ {"test_async", test_async, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"async1", async1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc131", test_conc131, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc129", test_conc129, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc622", test_conc622, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/basic-t.c b/libmariadb/unittest/libmariadb/basic-t.c
new file mode 100644
index 00000000..40a44962
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/basic-t.c
@@ -0,0 +1,885 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+/**
+ Some basic tests of the client API.
+*/
+
+#include "my_test.h"
+#include "ma_common.h"
+
+static int test_conc75(MYSQL *my)
+{
+ int rc;
+ MYSQL *mysql;
+ int i;
+ my_bool reconnect= 1;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+ SKIP_XPAND;
+
+ mysql= mysql_init(NULL);
+
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE a (a varchar(200))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_set_character_set(mysql, "utf8");
+ check_mysql_rc(rc, mysql);
+
+ for (i=0; i < 10; i++)
+ {
+ ulong thread_id= mysql_thread_id(mysql);
+ /* force reconnect */
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ diag("killing connection");
+ mysql_kill(my, thread_id);
+ mysql_ping(mysql);
+ rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)");
+ FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct");
+ diag("thread1: %ld %ld", thread_id, mysql_thread_id(mysql));
+ FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected");
+ //diag("cs: %s", mysql->charset->csname);
+ //FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set");
+ }
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
+ check_mysql_rc(rc, mysql);
+ mysql_close(mysql);
+ return OK;
+}
+
+
+static int test_conc74(MYSQL *unused __attribute__((unused)))
+{
+ int rc;
+ MYSQL *mysql;
+
+ mysql= mysql_init(NULL);
+
+
+ if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE a (a varchar(200))");
+ check_mysql_rc(rc, mysql);
+
+ mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
+
+ rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)");
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
+ check_mysql_rc(rc, mysql);
+
+ mysql_close(mysql);
+ return OK;
+}
+
+
+static int test_conc71(MYSQL *my)
+{
+ int rc;
+ MYSQL *mysql;
+
+ /* uncomment if you want to test manually */
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+
+
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8");
+ mysql_options(mysql, MYSQL_OPT_COMPRESS, 0);
+ mysql_options(mysql, MYSQL_INIT_COMMAND, "/*!40101 SET SQL_MODE='' */");
+ mysql_options(mysql, MYSQL_INIT_COMMAND, "/*!40101 set @@session.wait_timeout=28800 */");
+
+ FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ diag("kill server");
+
+ rc= mysql_query(mysql, "SELECT 'foo' FROM DUAL");
+ check_mysql_rc(rc, mysql);
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc70(MYSQL *my)
+{
+ int rc;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL *mysql;
+
+ SKIP_CONNECTION_HANDLER;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ mysql= mysql_init(NULL);
+
+ rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
+ check_mysql_rc(rc, my);
+
+ mysql_query(my, "SET global max_allowed_packet=1024*1024*22");
+ check_mysql_rc(rc, my);
+
+ mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1);
+ FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a LONGBLOB) engine=MyISAM");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
+ check_mysql_rc(rc, mysql);
+
+ if (mysql_warning_count(mysql))
+ {
+ diag("server doesn't accept package size");
+ return SKIP;
+ }
+
+
+ rc= mysql_query(mysql, "SELECT a FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ if (!(res= mysql_store_result(mysql)))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+
+ row= mysql_fetch_row(res);
+ diag("Length: %ld", (long)strlen(row[0]));
+ FAIL_IF(strlen(row[0]) != 1024 * 1024 * 20, "Wrong length");
+
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ mysql_close(mysql);
+
+ rc= mysql_query(my, "SET global max_allowed_packet=@a");
+ check_mysql_rc(rc, my);
+
+ return OK;
+}
+
+static int test_conc68(MYSQL *my)
+{
+ int rc;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL *mysql;
+
+ SKIP_CONNECTION_HANDLER;
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ mysql= mysql_init(NULL);
+
+ rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
+ check_mysql_rc(rc, my);
+
+ mysql_query(my, "SET global max_allowed_packet=1024*1024*22");
+
+ FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a LONGBLOB) ENGINE=MyISAM");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
+ check_mysql_rc(rc, mysql);
+ if (mysql_warning_count(mysql))
+ {
+ diag("server doesn't accept package size");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "SELECT a FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ if (!(res= mysql_store_result(mysql)))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+
+ row= mysql_fetch_row(res);
+ diag("Length: %ld", (long)strlen(row[0]));
+ FAIL_IF(strlen(row[0]) != 1024 * 1024 * 20, "Wrong length");
+
+ mysql_free_result(res);
+ mysql_close(mysql);
+
+ rc= mysql_query(my, "SET global max_allowed_packet=@a");
+ check_mysql_rc(rc, my);
+
+ return OK;
+}
+
+
+static int basic_connect(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+ MYSQL_FIELD *field;
+ int rc;
+ MYSQL *my;
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ rc= mysql_query(my, "SELECT @@version");
+ check_mysql_rc(rc, my);
+
+ res= mysql_store_result(my);
+ FAIL_IF(!res, mysql_error(my));
+ field= mysql_fetch_fields(res);
+ FAIL_IF(!field, "couldn't fetch field");
+ while ((row= mysql_fetch_row(res)) != NULL)
+ {
+ FAIL_IF(mysql_num_fields(res) != 1, "Got the wrong number of fields");
+ }
+ FAIL_IF(mysql_errno(my), mysql_error(my));
+
+ mysql_free_result(res);
+ mysql_close(my);
+
+ return OK;
+}
+
+
+static int use_utf8(MYSQL *my)
+{
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+ int rc;
+
+ /* Make sure that we actually ended up with utf8. */
+ rc= mysql_query(my, "SELECT @@character_set_connection");
+ check_mysql_rc(rc, my);
+
+ res= mysql_store_result(my);
+ FAIL_IF(!res, mysql_error(my));
+
+ while ((row= mysql_fetch_row(res)) != NULL)
+ {
+ FAIL_IF(strncmp(row[0], "utf8", 4), "wrong character set");
+ }
+ FAIL_IF(mysql_errno(my), mysql_error(my));
+ mysql_free_result(res);
+
+ return OK;
+}
+
+int client_query(MYSQL *mysql) {
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1("
+ "id int primary key auto_increment, "
+ "name varchar(20))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1(id int, name varchar(20))");
+ FAIL_IF(!rc, "Error expected");
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('mysql')");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('monty')");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('venu')");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "UPDATE t1 SET name= 'updated' "
+ "WHERE name= 'deleted'");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "UPDATE t1 SET id= 3 WHERE name= 'updated'");
+ FAIL_IF(!rc, "Error expected");
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug12001(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ const char *query= "DROP TABLE IF EXISTS test_table;"
+ "CREATE TABLE test_table(id INT);"
+ "INSERT INTO test_table VALUES(10);"
+ "UPDATE test_table SET id=20 WHERE id=10;"
+ "SELECT * FROM test_table;"
+ "INSERT INTO non_existent_table VALUES(11);";
+ int rc, res;
+
+
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ do
+ {
+ if (mysql_field_count(mysql) &&
+ (result= mysql_use_result(mysql)))
+ {
+ mysql_free_result(result);
+ }
+ }
+ while (!(res= mysql_next_result(mysql)));
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_table");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_UNLESS(res==1, "res != 1");
+
+ return OK;
+}
+
+
+/* connection options */
+struct my_option_st opt_utf8[] = {
+ {MYSQL_SET_CHARSET_NAME, (char *)"utf8"},
+ {0, NULL}
+};
+
+static int test_bad_union(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *query= "SELECT 1, 2 union SELECT 1";
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_UNLESS(rc && mysql_errno(mysql) == 1222, "Error expected");
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+/*
+ Test that mysql_insert_id() behaves as documented in our manual
+*/
+static int test_mysql_insert_id(MYSQL *mysql)
+{
+ unsigned long long res;
+ int rc;
+
+ if (mysql_get_server_version(mysql) < 50100) {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "drop table if exists t2");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "drop table if exists t3");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "drop table if exists t4");
+ check_mysql_rc(rc, mysql);
+ /* table without auto_increment column */
+ rc= mysql_query(mysql, "create table t1 (f1 int, f2 varchar(255), key(f1))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t3 (f1 int not null primary key auto_increment, f2 varchar(255)) engine=MyISAM");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t4 (f1 int not null primary key "
+ "auto_increment, f2 varchar(200), unique (f2)) engine=MyISAM");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "START TRANSACTION");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values (1,'a')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "insert into t1 values (null,'b')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "insert into t1 select 5,'c'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+
+ /*
+ Test for bug #34889: mysql_client_test::test_mysql_insert_id test fails
+ sporadically
+ */
+ rc= mysql_query(mysql, "insert into t2 values (null,'b')");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 select 5,'c'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "insert into t1 select null,'d'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "insert into t1 values (null,last_insert_id(300))");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 300, "");
+ rc= mysql_query(mysql, "insert into t1 select null,last_insert_id(400)");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ /*
+ Behaviour change: old code used to return 0; but 400 is consistent
+ with INSERT VALUES, and the manual's section of mysql_insert_id() does not
+ say INSERT SELECT should be different.
+ */
+ FAIL_UNLESS(res == 400, "");
+
+ /* table with auto_increment column */
+ rc= mysql_query(mysql, "insert into t3 values (1,'a')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 1, "");
+ /* this should not influence next INSERT if it doesn't have auto_inc */
+ rc= mysql_query(mysql, "insert into t1 values (10,'e')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+
+ rc= mysql_query(mysql, "insert into t3 values (null,'b')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 2, "");
+ rc= mysql_query(mysql, "insert into t3 select 5,'c'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ /*
+ Manual says that for multirow insert this should have been 5, but does not
+ say for INSERT SELECT. This is a behaviour change: old code used to return
+ 0. We try to be consistent with INSERT VALUES.
+ */
+ FAIL_UNLESS(res == 5, "");
+ rc= mysql_query(mysql, "insert into t3 select null,'d'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 6, "");
+ /* with more than one row */
+ rc= mysql_query(mysql, "insert into t3 values (10,'a'),(11,'b')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 11, "");
+ rc= mysql_query(mysql, "insert into t3 select 12,'a' union select 13,'b'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ /*
+ Manual says that for multirow insert this should have been 13, but does
+ not say for INSERT SELECT. This is a behaviour change: old code used to
+ return 0. We try to be consistent with INSERT VALUES.
+ */
+ FAIL_UNLESS(res == 13, "");
+ rc= mysql_query(mysql, "insert into t3 values (null,'a'),(null,'b')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 14, "");
+ rc= mysql_query(mysql, "insert into t3 select null,'a' union select null,'b'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 16, "");
+ rc= mysql_query(mysql, "insert into t3 select 12,'a' union select 13,'b'");
+ FAIL_IF(!rc, "Error expected");
+ rc= mysql_query(mysql, "insert ignore into t3 select 12,'a' union select 13,'b'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "insert into t3 values (12,'a'),(13,'b')");
+ FAIL_IF(!rc, "Error expected");
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "insert ignore into t3 values (12,'a'),(13,'b')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ /* mixing autogenerated and explicit values */
+ rc= mysql_query(mysql, "insert into t3 values (null,'e'),(12,'a'),(13,'b')");
+ FAIL_IF(!rc, "Error expected");
+ rc= mysql_query(mysql, "insert into t3 values (null,'e'),(12,'a'),(13,'b'),(25,'g')");
+ FAIL_IF(!rc, "Error expected");
+ rc= mysql_query(mysql, "insert into t3 values (null,last_insert_id(300))");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ /*
+ according to the manual, this might be 20 or 300, but it looks like
+ auto_increment column takes priority over last_insert_id().
+ */
+ diag("res: %lld", res);
+ FAIL_UNLESS(res == 20, "");
+ /* If first autogenerated number fails and 2nd works: */
+ rc= mysql_query(mysql, "insert into t4 values (null,'e')");
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 1, "");
+ rc= mysql_query(mysql, "insert ignore into t4 values (null,'e'),(null,'a'),(null,'e')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 2, "");
+ /* If autogenerated fails and explicit works: */
+ rc= mysql_query(mysql, "insert ignore into t4 values (null,'e'),(12,'c'),(null,'d')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ /*
+ Behaviour change: old code returned 3 (first autogenerated, even if it
+ fails); we now return first successful autogenerated.
+ */
+ FAIL_UNLESS(res == 13, "");
+ /* UPDATE may update mysql_insert_id() if it uses LAST_INSERT_ID(#) */
+ rc= mysql_query(mysql, "update t4 set f1=14 where f1=12");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "update t4 set f1=0 where f1=14");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ rc= mysql_query(mysql, "update t4 set f2=last_insert_id(372) where f1=0");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 372, "");
+ /* check that LAST_INSERT_ID() does not update mysql_insert_id(): */
+ rc= mysql_query(mysql, "insert into t4 values (null,'g')");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 15, "");
+ rc= mysql_query(mysql, "update t4 set f2=(@li:=last_insert_id()) where f1=15");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+ /*
+ Behaviour change: now if ON DUPLICATE KEY UPDATE updates a row,
+ mysql_insert_id() returns the id of the row, instead of not being
+ affected.
+ */
+ rc= mysql_query(mysql, "insert into t4 values (null,@li) on duplicate key "
+ "update f2=concat('we updated ',f2)");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 15, "");
+
+ rc= mysql_query(mysql, "drop table t1,t2,t3,t4");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test simple select to debug */
+
+static int test_select_direct(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id int, id1 tinyint, "
+ " id2 float, "
+ " id3 double, "
+ " name varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* insert a row and commit the transaction */
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 5, 2.3, 4.5, 'venu')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT * FROM test_select");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ Ensure we execute the status code while testing
+*/
+
+static int test_status(MYSQL *mysql)
+{
+ mysql_stat(mysql);
+ check_mysql_rc(mysql_errno(mysql), mysql);
+ return OK;
+}
+
+static int bug_conc1(MYSQL *mysql)
+{
+ my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0);
+ diag("errno: %d", mysql_errno(mysql));
+ FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED,
+ "Expected errno=CR_ALREADY_CONNECTED");
+ return OK;
+}
+
+static int test_options_initcmd(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL_RES *res;
+ int rc;
+
+ mysql_options(mysql, MYSQL_INIT_COMMAND, "DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a int)");
+ mysql_options(mysql, MYSQL_INIT_COMMAND, "INSERT INTO t1 VALUES (1),(2),(3)");
+ FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname,
+ CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
+
+ rc= mysql_query(mysql, "SELECT a FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_IF(mysql_num_rows(res) != 3, "Expected 3 rows");
+
+ mysql_free_result(res);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_extended_init_values(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+
+ mysql_options(mysql, MYSQL_DEFAULT_AUTH, "unknown");
+ FAIL_IF(strcmp(mysql->options.extension->default_auth, "unknown"), "option not set");
+
+ mysql_options(mysql, MYSQL_PLUGIN_DIR, "/tmp/foo");
+ FAIL_IF(strcmp(mysql->options.extension->plugin_dir, "/tmp/foo"), "option not set");
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_reconnect_maxpackage(MYSQL *unused __attribute__((unused)))
+{
+ int rc;
+ ulong max_packet= 0;
+ MYSQL *mysql;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char *query;
+ my_bool reconnect= 1;
+
+ SKIP_CONNECTION_HANDLER;
+
+ mysql= mysql_init(NULL);
+
+ FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname,
+ CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+
+ rc= mysql_query(mysql, "SELECT @@max_allowed_packet");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ max_packet= atol(row[0]);
+ diag("max_allowed_packet=%lu", max_packet);
+ mysql_free_result(res);
+
+ query= (char *)malloc(max_packet + 30);
+ memset(query, 0, max_packet + 30);
+
+ strcpy(query, "SELECT '");
+ memset(query + 8, 'A', max_packet);
+ strcat(query, "' FROM DUAL");
+
+ rc= mysql_query(mysql, query);
+ free(query);
+ if (!rc)
+ {
+ diag("expected error");
+ mysql_close(mysql);
+ return FAIL;
+ }
+ else
+ diag("Error (expected): %s", mysql_error(mysql));
+
+ rc= mysql_ping(mysql);
+ /* if the server is under load, poll might not report closed
+ socket since FIN packet came too late */
+ if (rc)
+ rc= mysql_ping(mysql);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "SELECT @@max_allowed_packet");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ max_packet= atol(row[0]);
+ diag("max_allowed_packet=%lu", max_packet);
+ mysql_free_result(res);
+
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_compressed(MYSQL *unused __attribute__((unused)))
+{
+ int rc;
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL_RES *res;
+ my_bool reconnect= 1;
+
+ mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1);
+ FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname,
+ CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+
+ rc= mysql_query(mysql, "SHOW VARIABLES");
+ check_mysql_rc(rc, mysql);
+
+ if ((res= mysql_store_result(mysql)))
+ mysql_free_result(res);
+
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_conc624(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ char errmsg[MYSQL_ERRMSG_SIZE];
+
+ stmt_set_error(stmt, 9000, SQLSTATE_UNKNOWN, 0);
+ snprintf(errmsg, MYSQL_ERRMSG_SIZE, ER_UNKNOWN_ERROR_CODE, 9000);
+ diag("stmt_error: %s", mysql_stmt_error(stmt));
+ FAIL_IF(strcmp(mysql_stmt_error(stmt), errmsg), "expected undefined error 9000");
+
+ stmt_set_error(stmt, 0, SQLSTATE_UNKNOWN, 0);
+ snprintf(errmsg, MYSQL_ERRMSG_SIZE, ER_UNKNOWN_ERROR_CODE, 0);
+ FAIL_IF(strcmp(mysql_stmt_error(stmt), errmsg), "expected undefined error 0");
+
+ stmt_set_error(stmt, 4999, SQLSTATE_UNKNOWN, 0);
+ snprintf(errmsg, MYSQL_ERRMSG_SIZE, ER_UNKNOWN_ERROR_CODE, 4999);
+ FAIL_IF(strcmp(mysql_stmt_error(stmt), errmsg), "expected undefined error 4999");
+
+ my_set_error(mysql, 4999, SQLSTATE_UNKNOWN, 0);
+ snprintf(errmsg, MYSQL_ERRMSG_SIZE, ER_UNKNOWN_ERROR_CODE, 4999);
+ FAIL_IF(strcmp(mysql_error(mysql), errmsg), "expected undefined error 4999");
+
+ my_set_error(mysql, 0, SQLSTATE_UNKNOWN, 0);
+ snprintf(errmsg, MYSQL_ERRMSG_SIZE, ER_UNKNOWN_ERROR_CODE, 0);
+ FAIL_IF(strcmp(mysql_error(mysql), errmsg), "expected undefined error 0");
+
+ my_set_error(mysql, 9000, SQLSTATE_UNKNOWN, 0);
+ snprintf(errmsg, MYSQL_ERRMSG_SIZE, ER_UNKNOWN_ERROR_CODE, 9000);
+ FAIL_IF(strcmp(mysql_error(mysql), errmsg), "expected undefined error 9000");
+
+ /* test if stmt_set_error works with variadic arguments */
+ stmt_set_error(stmt, CR_STMT_CLOSED, SQLSTATE_UNKNOWN, 0, "foobar");
+ snprintf(errmsg, MYSQL_ERRMSG_SIZE, ER(CR_STMT_CLOSED), "foobar");
+ FAIL_IF(strcmp(mysql_stmt_error(stmt), errmsg), "error when passing variadic arguments to prepared stmt error function");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc624", test_conc624, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc75", test_conc75, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc74", test_conc74, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc71", test_conc71, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc70", test_conc70, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc68", test_conc68, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_compressed", test_compressed, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_reconnect_maxpackage", test_reconnect_maxpackage, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"basic_connect", basic_connect, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"use_utf8", use_utf8, TEST_CONNECTION_NEW, 0, opt_utf8, NULL},
+ {"client_query", client_query, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bad_union", test_bad_union, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_select_direct", test_select_direct, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_mysql_insert_id", test_mysql_insert_id, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug12001", test_bug12001, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL, NULL},
+ {"test_status", test_status, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL, NULL},
+ {"bug_conc1", bug_conc1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_options_initcmd", test_options_initcmd, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_extended_init_values", test_extended_init_values, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ diag("user: %s", username);
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/bulk1.c b/libmariadb/unittest/libmariadb/bulk1.c
new file mode 100644
index 00000000..e1c31eaa
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/bulk1.c
@@ -0,0 +1,1099 @@
+/*
+ Copyright 2011 Kristian Nielsen and Monty Program Ab.
+
+ This file is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "my_test.h"
+#include "ma_common.h"
+
+#define TEST_ARRAY_SIZE 1024
+
+static my_bool bulk_enabled= 0;
+
+char *rand_str(size_t length) {
+ const char charset[] = "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ char *dest= (char *)malloc(length+1);
+ char *p= dest;
+ while (length-- > 0) {
+ *dest++ = charset[rand() % sizeof(charset)];
+ }
+ *dest = '\0';
+ return p;
+}
+
+static int check_bulk(MYSQL *mysql)
+{
+ bulk_enabled= (!(mysql->server_capabilities & CLIENT_MYSQL) &&
+ (mysql->extension->mariadb_server_capabilities &
+ (MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32)));
+ diag("bulk %ssupported", bulk_enabled ? "" : "not ");
+ return OK;
+}
+
+static int bulk1(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ const char *stmt_str= "INSERT INTO bulk1 VALUES (?,?)";
+ unsigned int array_size= TEST_ARRAY_SIZE;
+ int rc;
+ unsigned int i;
+ char **buffer;
+ unsigned long *lengths;
+ unsigned int *vals;
+ MYSQL_BIND bind[2];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ unsigned int intval;
+
+ if (!bulk_enabled)
+ return SKIP;
+
+ rc= mysql_select_db(mysql, "testc");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk1 (a int , b VARCHAR(255))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_str));
+ check_stmt_rc(rc, stmt);
+
+ /* allocate memory */
+ buffer= calloc(TEST_ARRAY_SIZE, sizeof(char *));
+ lengths= (unsigned long *)calloc(sizeof(long), TEST_ARRAY_SIZE);
+ vals= (unsigned int *)calloc(sizeof(int), TEST_ARRAY_SIZE);
+
+ for (i=0; i < TEST_ARRAY_SIZE; i++)
+ {
+ buffer[i]= rand_str(254);
+ lengths[i]= -1;
+ vals[i]= i;
+ }
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 2);
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= vals;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (void *)buffer;
+ bind[1].length= (unsigned long *)lengths;
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ for (i=0; i < 100; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != TEST_ARRAY_SIZE, "affected_rows != TEST_ARRAY_SIZE");
+ }
+
+ for (i=0; i < array_size; i++)
+ free(buffer[i]);
+
+ free(buffer);
+ free(lengths);
+ free(vals);
+
+ rc= mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT COUNT(*) FROM bulk1");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ intval= atoi(row[0]);
+ mysql_free_result(res);
+ FAIL_IF(intval != array_size * 100, "Expected 102400 rows");
+
+ rc= mysql_query(mysql, "SELECT MAX(a) FROM bulk1");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ intval= atoi(row[0]);
+ mysql_free_result(res);
+ FAIL_IF(intval != array_size - 1, "Expected max value 1024");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int bulk2(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+ MYSQL_BIND bind[2];
+ unsigned int i;
+ unsigned int array_size=1024;
+ char indicator[1024];
+ long lval[1024];
+
+ if (!bulk_enabled)
+ return SKIP;
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk2 (a int default 4, b int default 2)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk2 VALUES (?,1)"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+
+ for (i=0; i < array_size; i++)
+ {
+ indicator[i]= STMT_INDICATOR_DEFAULT;
+ lval[i]= i;
+ }
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].u.indicator= indicator;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= &lval;
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int bulk3(MYSQL *mysql)
+{
+ struct st_bulk3 {
+ char char_value[20];
+ unsigned long length;
+ int int_value;
+ };
+
+ struct st_bulk3 val[3]= {{"Row 1", 5, 1},
+ {"Row 02", 6, 2},
+ {"Row 003", 7, 3}};
+ int rc;
+ MYSQL_BIND bind[2];
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ size_t row_size= sizeof(struct st_bulk3);
+ int array_size= 3;
+
+ if (!bulk_enabled)
+ return SKIP;
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk3");
+ check_mysql_rc(rc,mysql);
+ rc= mysql_query(mysql, "CREATE TABLE bulk3 (name varchar(20), row int)");
+ check_mysql_rc(rc,mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk3 VALUES (?,?)"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND)*2);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size);
+ check_stmt_rc(rc, stmt);
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= &val[0].char_value;
+ bind[0].length= &val[0].length;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= &val[0].int_value;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk3");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int bulk4(MYSQL *mysql)
+{
+ struct st_bulk4 {
+ char char_value[20];
+ char indicator1;
+ int int_value;
+ char indicator2;
+ };
+
+ struct st_bulk4 val[]= {{"Row 1", STMT_INDICATOR_NTS, 0, STMT_INDICATOR_DEFAULT},
+ {"Row 2", STMT_INDICATOR_NTS, 0, STMT_INDICATOR_DEFAULT},
+ {"Row 3", STMT_INDICATOR_NTS, 0, STMT_INDICATOR_DEFAULT}};
+ int rc;
+ MYSQL_BIND bind[2];
+ MYSQL_RES *res;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ size_t row_size= sizeof(struct st_bulk4);
+ int array_size= 3;
+ unsigned long lengths[3]= {-1, -1, -1};
+
+ if (!bulk_enabled)
+ return SKIP;
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk4");
+ check_mysql_rc(rc,mysql);
+ rc= mysql_query(mysql, "CREATE TABLE bulk4 (name varchar(20), row int not null default 3)");
+ check_mysql_rc(rc,mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk4 VALUES (?,?)"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND)*2);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size);
+ check_stmt_rc(rc, stmt);
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].u.indicator= &val[0].indicator1;
+ bind[0].buffer= &val[0].char_value;
+ bind[0].length= lengths;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].u.indicator= &val[0].indicator2;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk4 WHERE row=3");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(res);
+ mysql_free_result(res);
+ FAIL_IF(rc != 3, "expected 3 rows");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk4");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int bulk_null(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+ MYSQL_BIND bind[2];
+ unsigned int param_count= 2;
+ unsigned int array_size= 2;
+ unsigned long lengths[2]= {-1, -1};
+ char **buf= calloc(1, 2 * sizeof(char *));
+
+ if (!bulk_enabled)
+ {
+ free(buf);
+ return SKIP;
+ }
+
+ buf[0]= strdup("foo");
+ buf[1]= strdup("foobar");
+
+ rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS bulk_null", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE bulk_null (a int not null auto_increment primary key, b varchar(20))", -1);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+ bind[0].buffer_type= MYSQL_TYPE_NULL;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= buf;
+ bind[1].length= lengths;
+
+ mysql_stmt_close(stmt);
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &param_count);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO bulk_null VALUES (?, ?)", -1);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ free(buf[0]);
+ free(buf[1]);
+ free(buf);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_null");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int bulk5(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_BIND bind[3];
+ MYSQL_RES *res;
+ unsigned long rows;
+ unsigned int array_size= 5;
+ int rc;
+ int intval[]= {12,13,14,15,16};
+ int id[]= {1,2,3,4,5};
+
+ if (!bulk_enabled)
+ return SKIP;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk5");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk5 (a int, b int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO bulk5 VALUES (1,1), (2,2), (3,3), (4,4), (5,5)");
+ check_mysql_rc(rc, mysql);
+
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+
+ rc= mysql_stmt_prepare(stmt, SL("UPDATE bulk5 SET a=? WHERE a=?"));
+ check_stmt_rc(rc, stmt);
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= &intval;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= &id;
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk5 WHERE a=b+11");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ rows= (unsigned long)mysql_num_rows(res);
+ diag("rows: %lu", rows);
+ mysql_free_result(res);
+
+ FAIL_IF(rows != 5, "expected 5 rows");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk5");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int bulk6(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_BIND bind[3];
+ MYSQL_RES *res;
+ unsigned long rows;
+ unsigned int array_size= 5;
+ int rc;
+ int intval[]= {12,13,14,15,16};
+ int id[]= {1,2,3,4,5};
+ char indicator[5];
+
+ if (!bulk_enabled)
+ return SKIP;
+ memset(indicator, STMT_INDICATOR_IGNORE, 5);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk6");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk6 (a int, b int default 4)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO bulk6 VALUES (1,1), (2,2), (3,3), (4,4), (5,5)");
+ check_mysql_rc(rc, mysql);
+
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+
+ /* 1st case: UPDATE */
+ rc= mysql_stmt_prepare(stmt, SL("UPDATE bulk6 SET a=?, b=? WHERE a=?"));
+ check_stmt_rc(rc, stmt);
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= &intval;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= &intval;
+ bind[1].u.indicator= indicator;
+ bind[2].buffer_type= MYSQL_TYPE_LONG;
+ bind[2].buffer= &id;
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk6 WHERE a=b+11");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ rows= (unsigned long)mysql_num_rows(res);
+ mysql_free_result(res);
+
+ FAIL_IF(rows != 5, "expected 5 rows");
+
+ /* 2nd case: INSERT - ignore indicator should be same as default */
+ rc= mysql_query(mysql, "DELETE FROM bulk6");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk6 VALUES (?,?)"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ /* this should insert 5 default values (=4) */
+ memset(indicator, STMT_INDICATOR_DEFAULT, 5);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* this should insert 5 default values (=4) */
+ memset(indicator, STMT_INDICATOR_IGNORE, 5);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk6 WHERE b=4");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ rows= (unsigned long)mysql_num_rows(res);
+ mysql_free_result(res);
+
+ FAIL_IF(rows != 10, "expected 10 rows");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk6");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc243(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[3];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ struct st_data {
+ unsigned long id;
+ char id_ind;
+ char forename[30];
+ char forename_ind;
+ char surname[30];
+ char surname_ind;
+ };
+
+ struct st_data data[]= {
+ {0, STMT_INDICATOR_NULL, "Monty", STMT_INDICATOR_NTS, "Widenius", STMT_INDICATOR_NTS},
+ {0, STMT_INDICATOR_NULL, "David", STMT_INDICATOR_NTS, "Axmark", STMT_INDICATOR_NTS},
+ {0, STMT_INDICATOR_NULL, "default", STMT_INDICATOR_DEFAULT, "N.N.", STMT_INDICATOR_NTS},
+ };
+
+ unsigned int array_size= 1;
+ size_t row_size= sizeof(struct st_data);
+ int rc;
+
+ if (!bulk_enabled)
+ return SKIP;
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_example2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk_example2 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"\
+ "forename CHAR(30) NOT NULL DEFAULT 'unknown', surname CHAR(30))");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk_example2 VALUES (?,?,?)"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+
+ /* We autogenerate id's, so all indicators are STMT_INDICATOR_NULL */
+ bind[0].u.indicator= &data[0].id_ind;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+
+ bind[1].buffer= &data[0].forename;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].u.indicator= &data[0].forename_ind;
+
+ bind[2].buffer_type= MYSQL_TYPE_STRING;
+ bind[2].buffer= &data[0].surname;
+ bind[2].u.indicator= &data[0].surname_ind;
+
+ /* set array size */
+ mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+
+ /* set row size */
+ mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size);
+
+ /* bind parameter */
+ mysql_stmt_bind_param(stmt, bind);
+
+ /* execute */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT forename, surname FROM bulk_example2");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result || !mysql_num_rows(result), "Invalid resultset");
+ row = mysql_fetch_row(result);
+ if (strcmp(row[0], "Monty") || strcmp(row[1], "Widenius"))
+ {
+ mysql_free_result(result);
+ diag("Wrong values");
+ return FAIL;
+ }
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE bulk_example2");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+static int bulk7(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+ int array_size= 5;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("UPDATE t1 SET a=a+1"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+
+ FAIL_IF(!rc, "Error expected: Bulk operation without parameters is not supported");
+ diag("%s", mysql_stmt_error(stmt));
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_char_conv1(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind_in, bind_out;
+ char buffer[100];
+ char outbuffer[100];
+
+ if (!bulk_enabled)
+ return SKIP;
+ stmt= mysql_stmt_init(mysql);
+ strcpy (buffer, "\xC3\x82\xC3\x83\xC3\x84\x00");
+
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS char_conv");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE char_conv (a varchar(20)) CHARSET=latin1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO char_conv VALUES (?)"));
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind_in, 0, sizeof(MYSQL_BIND));
+ bind_in.buffer_type= MYSQL_TYPE_STRING;
+ bind_in.buffer_length= -1;
+ bind_in.buffer= &buffer;
+
+ rc= mysql_stmt_bind_param(stmt, &bind_in);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT a from char_conv"));
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind_out, 0, sizeof(MYSQL_BIND));
+ bind_out.buffer_type= MYSQL_TYPE_STRING;
+ bind_out.buffer_length= 100;
+ bind_out.buffer= outbuffer;
+
+ rc= mysql_stmt_bind_result(stmt, &bind_out);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc == MYSQL_NO_DATA, "Error");
+
+ mysql_stmt_close(stmt);
+
+
+ if (strcmp(buffer, outbuffer))
+ {
+ diag("Error: Expected '%s' instead of '%s'", buffer, outbuffer);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE char_conv");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int test_char_conv2(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int array_size= 1;
+ MYSQL_BIND bind_in, bind_out;
+ char *buffer[1];
+ char outbuffer[100];
+
+ if (!bulk_enabled)
+ return SKIP;
+
+ stmt= mysql_stmt_init(mysql);
+ buffer[0]= calloc(1, 7);
+ strcpy (buffer[0], "\xC3\x82\xC3\x83\xC3\x84\x00");
+
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS char_conv");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE char_conv (a varchar(20)) CHARSET=latin1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO char_conv VALUES (?)"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind_in, 0, sizeof(MYSQL_BIND));
+ bind_in.buffer_type= MYSQL_TYPE_STRING;
+ bind_in.buffer_length= -1;
+ bind_in.buffer= &buffer;
+
+ rc= mysql_stmt_bind_param(stmt, &bind_in);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT a from char_conv"));
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind_out, 0, sizeof(MYSQL_BIND));
+ bind_out.buffer_type= MYSQL_TYPE_STRING;
+ bind_out.buffer_length= 100;
+ bind_out.buffer= outbuffer;
+
+ rc= mysql_stmt_bind_result(stmt, &bind_out);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc == MYSQL_NO_DATA, "Error");
+
+ mysql_stmt_close(stmt);
+
+
+ if (strcmp(buffer[0], outbuffer))
+ {
+ diag("Error: Expected '%s' instead of '%s'", buffer[0], outbuffer);
+ return FAIL;
+ }
+ free(buffer[0]);
+
+ rc= mysql_query(mysql, "DROP TABLE char_conv");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int bulk_skip_row(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[3];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ struct st_data {
+ unsigned long id;
+ char id_ind;
+ char forename[30];
+ char forename_ind;
+ char surname[30];
+ char surname_ind;
+ };
+
+ struct st_data data[]={
+ { 0, STMT_INDICATOR_NULL, "Monty", STMT_INDICATOR_NTS, "Widenius", STMT_INDICATOR_IGNORE_ROW },
+ { 0, STMT_INDICATOR_IGNORE_ROW, "David", STMT_INDICATOR_NTS, "Axmark", STMT_INDICATOR_NTS },
+ { 0, STMT_INDICATOR_NULL, "default", STMT_INDICATOR_DEFAULT, "N.N.", STMT_INDICATOR_NTS },
+ };
+
+ unsigned int array_size= 3;
+ size_t row_size= sizeof(struct st_data);
+ int rc;
+
+ if (!bulk_enabled)
+ return SKIP;
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_example2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bulk_example2 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"\
+ "forename CHAR(30) NOT NULL DEFAULT 'unknown', surname CHAR(30))");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk_example2 VALUES (?,?,?)"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+
+ /* We autogenerate id's, so all indicators are STMT_INDICATOR_NULL */
+ bind[0].u.indicator= &data[0].id_ind;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+
+ bind[1].buffer= &data[0].forename;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].u.indicator= &data[0].forename_ind;
+
+ bind[2].buffer_type= MYSQL_TYPE_STRING;
+ bind[2].buffer= &data[0].surname;
+ bind[2].u.indicator= &data[0].surname_ind;
+
+ /* set array size */
+ mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+
+ /* set row size */
+ mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size);
+
+ /* bind parameter */
+ mysql_stmt_bind_param(stmt, bind);
+
+ /* execute */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT forename, surname FROM bulk_example2");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result || mysql_num_rows(result) != 1, "Invalid resultset");
+
+ row = mysql_fetch_row(result);
+ if (strcmp(row[0], "unknown") || strcmp(row[1], "N.N."))
+ {
+ mysql_free_result(result);
+ diag("Wrong values");
+ return FAIL;
+ }
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE bulk_example2");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int bulk_null_null(MYSQL *mysql)
+{
+ struct st_bulk4 {
+ char char_value[20];
+ char indicator1;
+ int int_value;
+ char indicator2;
+ double double_value;
+ char indicator3;
+ char time_value[20];
+ char indicator4;
+ char decimal_value[4];
+ char indicator5;
+ };
+
+ struct st_bulk4 val[]= {{"3", STMT_INDICATOR_NTS,
+ 3, STMT_INDICATOR_NONE,
+ 3.0, STMT_INDICATOR_NONE,
+ "00:00:00", STMT_INDICATOR_NTS,
+ "3.0", STMT_INDICATOR_NTS},
+ {"3", STMT_INDICATOR_NULL,
+ 3, STMT_INDICATOR_NULL,
+ 3.0, STMT_INDICATOR_NULL,
+ "00:00:00", STMT_INDICATOR_NULL,
+ "3.0", STMT_INDICATOR_NULL},
+ {"3", STMT_INDICATOR_NTS,
+ 3, STMT_INDICATOR_NONE,
+ 3.0, STMT_INDICATOR_NONE,
+ "00:00:00", STMT_INDICATOR_NTS,
+ "3.0", STMT_INDICATOR_NTS}};
+ int rc;
+ MYSQL_BIND bind[5];
+ MYSQL_RES *res;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ size_t row_size= sizeof(struct st_bulk4);
+ int array_size= 3;
+ unsigned long server_version= mysql_get_server_version(mysql);
+ unsigned long lengths[3]= {-1, -1, -1};
+
+ if (!bulk_enabled)
+ return SKIP;
+
+ if (server_version > 100300 &&
+ server_version < 100305)
+ return SKIP;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_null");
+ check_mysql_rc(rc,mysql);
+ rc= mysql_query(mysql, "CREATE TABLE bulk_null "
+ "(s varchar(20), "
+ " i int, "
+ " d double, "
+ " t time, "
+ " c decimal(3,1))");
+ check_mysql_rc(rc,mysql);
+
+ rc= mysql_stmt_prepare(stmt, "INSERT INTO bulk_null VALUES (?,?,?,?,?)", -1);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND)*5);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size);
+ check_stmt_rc(rc, stmt);
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].u.indicator= &val[0].indicator1;
+ bind[0].buffer= &val[0].char_value;
+ bind[0].length= lengths;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= &val[0].int_value;
+ bind[1].u.indicator= &val[0].indicator2;
+ bind[2].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind[2].buffer= &val[0].double_value;
+ bind[2].u.indicator= &val[0].indicator3;
+ bind[3].buffer_type= MYSQL_TYPE_STRING;
+ bind[3].u.indicator= &val[0].indicator4;
+ bind[3].buffer= &val[0].time_value;
+ bind[3].length= lengths;
+ bind[4].buffer_type= MYSQL_TYPE_NEWDECIMAL;
+ bind[4].u.indicator= &val[0].indicator5;
+ bind[4].buffer= &val[0].decimal_value;
+ bind[4].length= lengths;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE s='3'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(res);
+ mysql_free_result(res);
+ FAIL_IF(rc != 2, "expected 2 rows");
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE i=3");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(res);
+ mysql_free_result(res);
+ FAIL_IF(rc != 2, "expected 2 rows");
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE d=3.0");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(res);
+ mysql_free_result(res);
+ FAIL_IF(rc != 2, "expected 2 rows");
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE t='00:00:00'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(res);
+ mysql_free_result(res);
+ FAIL_IF(rc != 2, "expected 2 rows");
+
+ rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE c=3.0");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(res);
+ mysql_free_result(res);
+ FAIL_IF(rc != 2, "expected 2 rows");
+
+ rc= mysql_query(mysql, "DROP TABLE bulk_null");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_mdev16593(MYSQL *mysql)
+{
+ int i;
+ int rc;
+ MYSQL_BIND bind[2];
+ unsigned int array_size= 2;
+ int val_a[2]= {1,2};
+ char indicators[2]= {STMT_INDICATOR_NULL, STMT_INDICATOR_NULL};
+ const char *testcase[]= {"MYSQL_TYPE_LONG", "MYSQL_TYPE_NULL", "STMT_INDICATOR_NULL"};
+
+ diag("waiting for server fix");
+ return SKIP;
+
+ memset(&bind, 0, 2 * sizeof(MYSQL_BIND));
+ for (i=0; i < 3; i++)
+ {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ rc= mysql_query(mysql, "CREATE OR REPLACE TABLE t1 (a int not null auto_increment primary key, b int)");
+ check_mysql_rc(rc, mysql);
+ switch (i) {
+ case 0:
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ break;
+ case 1:
+ bind[0].buffer_type= MYSQL_TYPE_NULL;
+ break;
+ case 2:
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].u.indicator= indicators;
+ break;
+ }
+ bind[0].buffer= val_a;
+ bind[1].buffer_type= MYSQL_TYPE_LONG;
+ bind[1].buffer= val_a;
+
+ rc= mysql_stmt_prepare(stmt, SL("insert into t1 values(?,?)"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "COMMIT");
+ check_mysql_rc(rc, mysql);
+
+ diag("Insert id with buffer_type %s: %lld",
+ testcase[i],
+ mysql_stmt_insert_id(stmt));
+
+ rc= mysql_query(mysql, "SELECT max(a) FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ diag("Max value for t1.a=%s", row[0]);
+ mysql_free_result(res);
+
+ mysql_stmt_close(stmt);
+ }
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"check_bulk", check_bulk, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_mdev16593", test_mdev16593, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"bulk_null_null", bulk_null_null, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_char_conv1", test_char_conv1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_char_conv2", test_char_conv2, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc243", test_conc243, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"update_no_param", bulk7, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk5", bulk5, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk6", bulk6, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk1", bulk1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk2", bulk2, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk3", bulk3, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk4", bulk4, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk_null", bulk_null, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bulk_skip_row", bulk_skip_row, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/charset.c b/libmariadb/unittest/libmariadb/charset.c
new file mode 100644
index 00000000..b438f8d9
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/charset.c
@@ -0,0 +1,881 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "my_test.h"
+
+/*
+ test gbk charset escaping
+
+ The important part is that 0x27 (') is the second-byte in a invalid
+ two-byte GBK character here. But 0xbf5c is a valid GBK character, so
+ it needs to be escaped as 0x5cbf27
+
+*/
+#define TEST_BUG8378_IN "\xef\xbb\xbf\x27\xbf\x10"
+#define TEST_BUG8378_OUT "\xef\xbb\x5c\xbf\x5c\x27\x5c\xbf\x10"
+
+/* set connection options */
+struct my_option_st opt_bug8378[] = {
+ {MYSQL_SET_CHARSET_NAME, (char *) "gbk"},
+ {0, NULL}
+};
+
+int bug_8378(MYSQL *mysql) {
+ int rc, len;
+ char out[9], buf[256];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ len= mysql_real_escape_string(mysql, out, TEST_BUG8378_IN, 4);
+ FAIL_IF(memcmp(out, TEST_BUG8378_OUT, len), "wrong result");
+
+ sprintf(buf, "SELECT '%s' FROM DUAL", TEST_BUG8378_OUT);
+
+ rc= mysql_query(mysql, buf);
+ check_mysql_rc(rc, mysql);
+
+ if ((res= mysql_store_result(mysql))) {
+ row= mysql_fetch_row(res);
+ if (memcmp(row[0], TEST_BUG8378_IN, 4)) {
+ mysql_free_result(res);
+ return FAIL;
+ }
+ mysql_free_result(res);
+ } else
+ return FAIL;
+
+ return OK;
+}
+
+int test_client_character_set(MYSQL *mysql)
+{
+ MY_CHARSET_INFO cs;
+ char *csname= (char*) "latin2";
+ char *csdefault= (char*)mysql_character_set_name(mysql);
+
+
+ FAIL_IF(mysql_set_character_set(mysql, csname), mysql_error(mysql));
+
+ mysql_get_character_set_info(mysql, &cs);
+
+ FAIL_IF(strcmp(cs.csname, "latin2") || strcmp(cs.name, "latin2_general_ci"),
+ "Character set != latin2");
+ FAIL_IF(mysql_set_character_set(mysql, csdefault), mysql_error(mysql));
+
+ return OK;
+}
+
+/*
+ * Regression test for bug #10214
+ *
+ * Test escaping with NO_BACKSLASH_ESCAPES
+ *
+ */
+int bug_10214(MYSQL *mysql)
+{
+ int len, rc;
+ char out[8];
+
+ /* reset sql_mode */
+ rc= mysql_query(mysql, "SET sql_mode=''");
+ check_mysql_rc(rc, mysql);
+
+ len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
+ FAIL_IF(memcmp(out, "a\\'b\\\\c", len), "wrong result");
+
+ rc= mysql_query(mysql, "set sql_mode='NO_BACKSLASH_ESCAPES'");
+ check_mysql_rc(rc, mysql);
+ FAIL_IF(!(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES),
+ "wrong server status: NO_BACKSLASH_ESCAPES not set");
+
+ len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
+ FAIL_IF(memcmp(out, "a''b\\c", len), "wrong result");
+
+ return OK;
+}
+
+/*
+ * simple escaping of special chars
+ */
+int test_escaping(MYSQL *mysql)
+{
+ int i= 0, rc, len;
+ char out[20];
+ const char *escape_chars[] = {"'", "\x0", "\n", "\r", "\\", "\0", NULL};
+
+ /* reset sql_mode, mysql_change_user call doesn't reset it */
+ rc= mysql_query(mysql, "SET sql_mode=''");
+ check_mysql_rc(rc, mysql);
+
+ while (escape_chars[i]) {
+ len= mysql_real_escape_string(mysql, out, escape_chars[i], 1);
+ FAIL_IF(len < 2, "Len < 2");
+ i++;
+ }
+
+ return OK;
+}
+
+/*
+ * server doesn't reset sql_mode after COM_CHANGE_USER
+ */
+int bug_41785(MYSQL *mysql)
+{
+ char out[10];
+ int rc, len;
+
+ len= mysql_real_escape_string(mysql, out, "\\", 1);
+ FAIL_IF(len != 2, "len != 2");
+
+ rc= mysql_query(mysql, "SET SQL_MODE=NO_BACKSLASH_ESCAPES");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "SET sql_mode=''");
+ check_mysql_rc(rc, mysql);
+
+ mysql_change_user(mysql, "root", "", "test");
+
+ len= mysql_real_escape_string(mysql, out, "\\", 1);
+ FAIL_IF(len != 2, "len != 2");
+
+ return OK;
+}
+
+static int test_conversion(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ MYSQL_BIND my_bind[1];
+ uchar buff[4];
+ ulong length;
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "CREATE TABLE t1 (a TEXT) DEFAULT CHARSET latin1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "SET character_set_connection=utf8, character_set_client=utf8, "
+ " character_set_results=latin1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ stmt_text= "INSERT INTO t1 (a) VALUES (?)";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer= (char*) buff;
+ my_bind[0].length= &length;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+
+ mysql_stmt_bind_param(stmt, my_bind);
+
+ buff[0]= (uchar) 0xC3;
+ buff[1]= (uchar) 0xA0;
+ length= 2;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ stmt_text= "SELECT a FROM t1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ my_bind[0].buffer_length= sizeof(buff);
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(length == 1, "length != 1");
+ FAIL_UNLESS(buff[0] == 0xE0, "buff[0] != 0xE0");
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ stmt_text= "DROP TABLE t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "SET NAMES DEFAULT";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug27876(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+
+ uchar utf8_func[] =
+ {
+ 0xd1, 0x84, 0xd1, 0x83, 0xd0, 0xbd, 0xd0, 0xba,
+ 0xd1, 0x86, 0xd0, 0xb8, 0xd0, 0xb9, 0xd0, 0xba,
+ 0xd0, 0xb0,
+ 0x00
+ };
+
+ uchar utf8_param[] =
+ {
+ 0xd0, 0xbf, 0xd0, 0xb0, 0xd1, 0x80, 0xd0, 0xb0,
+ 0xd0, 0xbc, 0xd0, 0xb5, 0xd1, 0x82, 0xd1, 0x8a,
+ 0xd1, 0x80, 0x5f, 0xd0, 0xb2, 0xd0, 0xb5, 0xd1,
+ 0x80, 0xd1, 0x81, 0xd0, 0xb8, 0xd1, 0x8f,
+ 0x00
+ };
+
+ char query[500];
+
+ rc= mysql_query(mysql, "set names utf8");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "select version()");
+ check_mysql_rc(rc, mysql);
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+ mysql_free_result(result);
+
+ sprintf(query, "DROP FUNCTION IF EXISTS %s", (char*) utf8_func);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query,
+ "CREATE FUNCTION %s( %s VARCHAR(25))"
+ " RETURNS VARCHAR(25) DETERMINISTIC RETURN %s",
+ (char*) utf8_func, (char*) utf8_param, (char*) utf8_param);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+ sprintf(query, "SELECT %s(VERSION())", (char*) utf8_func);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+ mysql_free_result(result);
+
+ sprintf(query, "DROP FUNCTION %s", (char*) utf8_func);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "set names default");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_ps_i18n(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+ MYSQL_BIND bind_array[2];
+
+ /* Represented as numbers to keep UTF8 tools from clobbering them. */
+ const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
+ const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
+ char buf1[16], buf2[16];
+ ulong buf1_len, buf2_len;
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ /*
+ Create table with binary columns, set session character set to cp1251,
+ client character set to koi8, and make sure that there is conversion
+ on insert and no conversion on select
+ */
+
+ stmt_text= "CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "SET CHARACTER_SET_CLIENT=koi8r, "
+ "CHARACTER_SET_CONNECTION=cp1251, "
+ "CHARACTER_SET_RESULTS=koi8r";
+
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ memset(bind_array, '\0', sizeof(bind_array));
+ bind_array[0].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[0].buffer= (void *) koi8;
+ bind_array[0].buffer_length= (unsigned long)strlen(koi8);
+
+ bind_array[1].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[1].buffer= (void *) koi8;
+ bind_array[1].buffer_length= (unsigned long)strlen(koi8);
+
+ stmt= mysql_stmt_init(mysql);
+ check_stmt_rc(rc, stmt);
+
+ stmt_text= "INSERT INTO t1 (c1, c2) VALUES (?, ?)";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_bind_param(stmt, bind_array);
+ check_stmt_rc(rc, stmt);
+
+// mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ stmt_text= "SELECT c1, c2 FROM t1";
+
+ /* c1 and c2 are binary so no conversion will be done on select */
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ bind_array[0].buffer= buf1;
+ bind_array[0].buffer_length= sizeof(buf1);
+ bind_array[0].length= &buf1_len;
+
+ bind_array[1].buffer= buf2;
+ bind_array[1].buffer_length= sizeof(buf2);
+ bind_array[1].length= &buf2_len;
+
+ mysql_stmt_bind_result(stmt, bind_array);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(buf1_len == strlen(cp1251), "buf1_len != strlen(cp1251)");
+ FAIL_UNLESS(buf2_len == strlen(cp1251), "buf2_len != strlen(cp1251)");
+ FAIL_UNLESS(!memcmp(buf1, cp1251, buf1_len), "buf1 != cp1251");
+ FAIL_UNLESS(!memcmp(buf2, cp1251, buf1_len), "buf2 != cp1251");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ /*
+ Now create table with two cp1251 columns, set client character
+ set to koi8 and supply columns of one row as string and another as
+ binary data. Binary data must not be converted on insert, and both
+ columns must be converted to client character set on select.
+ */
+
+ stmt_text= "CREATE TABLE t1 (c1 VARCHAR(255) CHARACTER SET cp1251, "
+ "c2 VARCHAR(255) CHARACTER SET cp1251)";
+
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "INSERT INTO t1 (c1, c2) VALUES (?, ?)";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ /* this data must be converted */
+ bind_array[0].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[0].buffer= (void *) koi8;
+ bind_array[0].buffer_length= (unsigned long)strlen(koi8);
+
+ bind_array[1].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[1].buffer= (void *) koi8;
+ bind_array[1].buffer_length= (unsigned long)strlen(koi8);
+
+ mysql_stmt_bind_param(stmt, bind_array);
+
+// mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ /* this data must not be converted */
+ bind_array[0].buffer_type= MYSQL_TYPE_BLOB;
+ bind_array[0].buffer= (void *) cp1251;
+ bind_array[0].buffer_length= (unsigned long)strlen(cp1251);
+
+ bind_array[1].buffer_type= MYSQL_TYPE_BLOB;
+ bind_array[1].buffer= (void *) cp1251;
+ bind_array[1].buffer_length= (unsigned long)strlen(cp1251);
+
+ mysql_stmt_bind_param(stmt, bind_array);
+
+// mysql_stmt_send_long_data(stmt, 0, cp1251, strlen(cp1251));
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ /* Fetch data and verify that rows are in koi8 */
+
+ stmt_text= "SELECT c1, c2 FROM t1";
+
+ /* c1 and c2 are binary so no conversion will be done on select */
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ bind_array[0].buffer= buf1;
+ bind_array[0].buffer_length= sizeof(buf1);
+ bind_array[0].length= &buf1_len;
+
+ bind_array[1].buffer= buf2;
+ bind_array[1].buffer_length= sizeof(buf2);
+ bind_array[1].length= &buf2_len;
+
+ mysql_stmt_bind_result(stmt, bind_array);
+
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ {
+ FAIL_UNLESS(buf1_len == strlen(koi8), "buf1_len != strlen(koi8)");
+ FAIL_UNLESS(buf2_len == strlen(koi8), "buf2_len != strlen(koi8)");
+ FAIL_UNLESS(!memcmp(buf1, koi8, buf1_len), "buf1 != koi8");
+ FAIL_UNLESS(!memcmp(buf2, koi8, buf1_len), "buf2 != koi8");
+ }
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ mysql_stmt_close(stmt);
+
+ stmt_text= "DROP TABLE t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "SET NAMES DEFAULT";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ Bug#30472: libmysql doesn't reset charset, insert_id after succ.
+ mysql_change_user() call row insertions.
+*/
+
+static int bug30472_retrieve_charset_info(MYSQL *con,
+ char *character_set_name,
+ char *character_set_client,
+ char *character_set_results,
+ char *collation_connection)
+{
+ MYSQL_RES *rs;
+ MYSQL_ROW row;
+ int rc;
+
+ /* Get the cached client character set name. */
+
+ strcpy(character_set_name, mysql_character_set_name(con));
+
+ /* Retrieve server character set information. */
+
+ rc= mysql_query(con, "SHOW VARIABLES LIKE 'character_set_client'");
+ check_mysql_rc(rc, con);
+
+ rs= mysql_store_result(con);
+ FAIL_IF(!rs, "Invalid result set");
+ row= mysql_fetch_row(rs);
+ FAIL_IF(!row, "Couldn't fetch row");
+ strcpy(character_set_client, row[1]);
+ mysql_free_result(rs);
+
+ rc= mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'");
+ check_mysql_rc(rc, con);
+ rs= mysql_store_result(con);
+ FAIL_IF(!rs, "Invalid result set");
+ row= mysql_fetch_row(rs);
+ FAIL_IF(!row, "Couldn't fetch row");
+ strcpy(character_set_results, row[1]);
+ mysql_free_result(rs);
+
+ rc= mysql_query(con, "SHOW VARIABLES LIKE 'collation_connection'");
+ check_mysql_rc(rc, con);
+ rs= mysql_store_result(con);
+ FAIL_IF(!rs, "Invalid result set");
+ row= mysql_fetch_row(rs);
+ FAIL_IF(!row, "Couldn't fetch row");
+ strcpy(collation_connection, row[1]);
+ mysql_free_result(rs);
+ return OK;
+}
+
+#define MY_CS_NAME_SIZE 32
+
+static int test_bug30472(MYSQL *mysql)
+{
+ int rc;
+
+ char character_set_name_1[MY_CS_NAME_SIZE];
+ char character_set_client_1[MY_CS_NAME_SIZE];
+ char character_set_results_1[MY_CS_NAME_SIZE];
+ char collation_connnection_1[MY_CS_NAME_SIZE];
+
+ char character_set_name_2[MY_CS_NAME_SIZE];
+ char character_set_client_2[MY_CS_NAME_SIZE];
+ char character_set_results_2[MY_CS_NAME_SIZE];
+ char collation_connnection_2[MY_CS_NAME_SIZE];
+
+ char character_set_name_3[MY_CS_NAME_SIZE];
+ char character_set_client_3[MY_CS_NAME_SIZE];
+ char character_set_results_3[MY_CS_NAME_SIZE];
+ char collation_connnection_3[MY_CS_NAME_SIZE];
+
+ char character_set_name_4[MY_CS_NAME_SIZE];
+ char character_set_client_4[MY_CS_NAME_SIZE];
+ char character_set_results_4[MY_CS_NAME_SIZE];
+ char collation_connnection_4[MY_CS_NAME_SIZE];
+
+ SKIP_MAXSCALE;
+
+ if (mysql_get_server_version(mysql) < 50100 || !is_mariadb)
+ {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+ /* Retrieve character set information. */
+
+ mysql_set_character_set(mysql, "latin1");
+ bug30472_retrieve_charset_info(mysql,
+ character_set_name_1,
+ character_set_client_1,
+ character_set_results_1,
+ collation_connnection_1);
+
+ /* Switch client character set. */
+
+ FAIL_IF(mysql_set_character_set(mysql, "ascii"),
+ "Setting cs to ascii failed");
+
+ /* Retrieve character set information. */
+
+ bug30472_retrieve_charset_info(mysql,
+ character_set_name_2,
+ character_set_client_2,
+ character_set_results_2,
+ collation_connnection_2);
+
+ /*
+ Check that
+ 1) character set has been switched and
+ 2) new character set is different from the original one.
+ */
+
+ FAIL_UNLESS(strcmp(character_set_name_2, "ascii") == 0, "cs_name != ascii");
+ FAIL_UNLESS(strcmp(character_set_client_2, "ascii") == 0, "cs_client != ascii");
+ FAIL_UNLESS(strcmp(character_set_results_2, "ascii") == 0, "cs_result != ascii");
+ FAIL_UNLESS(strcmp(collation_connnection_2, "ascii_general_ci") == 0,
+ "collation != ascii_general_ci");
+
+ diag("%s %s", character_set_name_1, character_set_name_2);
+ FAIL_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0, "cs_name1 = cs_name2");
+ FAIL_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0, "cs_client1 = cs_client2");
+ FAIL_UNLESS(strcmp(character_set_results_1, character_set_results_2) != 0, "cs_result1 = cs_result2");
+ FAIL_UNLESS(strcmp(collation_connnection_1, collation_connnection_2) != 0, "collation1 = collation2");
+
+ /* Call mysql_change_user() with the same username, password, database. */
+
+ rc= mysql_change_user(mysql, username, password, (schema) ? schema : "test");
+ mysql_set_character_set(mysql, "latin1");
+ check_mysql_rc(rc, mysql);
+
+ /* Retrieve character set information. */
+
+ bug30472_retrieve_charset_info(mysql,
+ character_set_name_3,
+ character_set_client_3,
+ character_set_results_3,
+ collation_connnection_3);
+
+ /* Check that character set information has been reset. */
+
+ FAIL_UNLESS(strcmp(character_set_name_1, character_set_name_3) == 0, "cs_name1 != cs_name3");
+ FAIL_UNLESS(strcmp(character_set_client_1, character_set_client_3) == 0, "cs_client1 != cs_client3");
+ FAIL_UNLESS(strcmp(character_set_results_1, character_set_results_3) == 0, "cs_result1 != cs_result3");
+ FAIL_UNLESS(strcmp(collation_connnection_1, collation_connnection_3) == 0, "collation1 != collation3");
+
+ /* Change connection-default character set in the client. */
+
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "latin2");
+
+ /*
+ Call mysql_change_user() in order to check that new connection will
+ have UTF8 character set on the client and on the server.
+ */
+
+ rc= mysql_change_user(mysql, username, password, (schema) ? schema : "test");
+ check_mysql_rc(rc, mysql);
+
+ /* Retrieve character set information. */
+
+ bug30472_retrieve_charset_info(mysql,
+ character_set_name_4,
+ character_set_client_4,
+ character_set_results_4,
+ collation_connnection_4);
+
+ /* Check that we have UTF8 on the server and on the client. */
+
+ FAIL_UNLESS(strcmp(character_set_name_4, "latin2") == 0, "cs_name != latin2");
+ FAIL_UNLESS(strcmp(character_set_client_4, "latin2") == 0, "cs_client != latin2");
+ FAIL_UNLESS(strcmp(character_set_results_4, "latin2") == 0, "cs_result != latin2");
+ FAIL_UNLESS(strcmp(collation_connnection_4, "latin2_general_ci") == 0,
+ "collation_connection != latin2_general_ci");
+
+ /* That's it. Cleanup. */
+
+ return OK;
+}
+
+static int test_bug_54100(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc;
+
+ rc= mysql_query(mysql, "SHOW CHARACTER SET");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+
+ while ((row= mysql_fetch_row(result)))
+ {
+ /* ignore ucs2 */
+ if (strcmp(row[0], "ucs2")
+ && strcmp(row[0], "utf16le")
+ && (strcmp(row[0], "utf8mb4") && mariadb_connection(mysql) && mysql_get_server_version(mysql) < 100600)
+ && (strcmp(row[0], "utf8") && mariadb_connection(mysql) && mysql_get_server_version(mysql) >= 100600)
+ && strcmp(row[0], "utf16")
+ && strcmp(row[0], "utf32")) {
+ rc= mysql_set_character_set(mysql, row[0]);
+ check_mysql_rc(rc, mysql);
+ }
+ }
+ mysql_free_result(result);
+
+ return OK;
+}
+
+
+/* We need this internal function for the test */
+
+static int test_utf16_utf32_noboms(MYSQL *mysql __attribute__((unused)))
+{
+#ifndef HAVE_ICONV
+ diag("MariaDB Connector/C was built without iconv support");
+ return SKIP;
+#else
+ const char *csname[]= {"utf16", "utf16le", "utf32", "utf8"};
+ MARIADB_CHARSET_INFO *csinfo[sizeof(csname)/sizeof(char*)];
+
+ const int UTF8= sizeof(csname)/sizeof(char*) - 1;
+
+ unsigned char in_string[][8]= {"\xd8\x02\xdc\x60\0", /* utf16(be) */
+ "\x02\xd8\x60\xdc\0", /* utf16le */
+ "\x00\x01\x08\x60\0\0\0", /* utf32(be) */
+ "\xF0\x90\xA1\xA0" }; /* utf8 */
+ size_t in_oct_len[]= {6, 6, 8, 5};
+
+ char buffer[8], as_hex[16];
+ int i, error;
+ size_t rc, in_len, out_len;
+
+ for (i= 0; i < (int)(sizeof(csname)/sizeof(char*)); ++i)
+ {
+ csinfo[i]= mariadb_get_charset_by_name(csname[i]);
+
+ if (csinfo[i] == NULL)
+ {
+ diag("Could not get cs info for %s", csname[i]);
+ return FAIL;
+ }
+ }
+
+ for (i= 0; i < UTF8; ++i)
+ {
+ in_len= in_oct_len[i];
+ out_len= sizeof(buffer);
+
+ diag("Converting %s->%s", csname[i], csname[UTF8]);
+ rc= mariadb_convert_string((char *)in_string[i], &in_len, csinfo[i], buffer, &out_len, csinfo[UTF8], &error);
+
+ FAIL_IF(rc == (size_t)-1, "Conversion failed");
+ FAIL_IF(rc != in_oct_len[UTF8], "Incorrect number of written bytes");
+
+ if (memcmp(buffer, in_string[UTF8], rc) != 0)
+ {
+ mysql_hex_string(as_hex, buffer, (unsigned long)rc);
+ diag("Converted string(%s) does not match the expected one", as_hex);
+ return FAIL;
+ }
+
+ in_len= in_oct_len[UTF8];
+ out_len= sizeof(buffer);
+
+ diag("Converting %s->%s", csname[UTF8], csname[i]);
+ rc= mariadb_convert_string((char *)in_string[UTF8], &in_len, csinfo[UTF8], buffer, &out_len, csinfo[i], &error);
+
+ FAIL_IF(rc == (size_t)-1, "Conversion failed");
+ diag("rc=%lu oct_len: %lu", (unsigned long)rc, (unsigned long)in_oct_len[i]);
+ FAIL_IF(rc != in_oct_len[i], "Incorrect number of written bytes");
+
+ if (memcmp(buffer, in_string[i], rc) != 0)
+ {
+ mysql_hex_string(as_hex, buffer, (unsigned long)rc);
+ diag("Converted string(%s) does not match the expected one", as_hex);
+ return FAIL;
+ }
+ }
+
+ return OK;
+#endif
+}
+
+static int charset_auto(MYSQL *my __attribute__((unused)))
+{
+ const char *csname1, *csname2;
+ const char *osname;
+ MYSQL *mysql= mysql_init(NULL);
+ int rc;
+
+ osname= madb_get_os_character_set();
+
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "auto");
+
+ FAIL_IF(!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0),
+ mysql_error(mysql));
+
+ csname1= mysql_character_set_name(mysql);
+ diag("Character set: %s os charset: %s", csname1, osname);
+
+ FAIL_IF(!strcasecmp(osname,"utf8") ? strncmp(osname, csname1, 4) :
+ strcmp(osname, csname1),
+ "character set is not os character set");
+ if (strcmp(osname, "utf8"))
+ {
+ rc= mysql_set_character_set(mysql, "utf8");
+ check_mysql_rc(rc, mysql);
+
+ csname2= mysql_character_set_name(mysql);
+ diag("Character set: %s", csname2);
+ FAIL_IF(!strcmp(csname2, csname1), "Wrong charset: expected utf8");
+
+ rc= mysql_set_character_set(mysql, "auto");
+ check_mysql_rc(rc, mysql);
+
+ csname2= mysql_character_set_name(mysql);
+ diag("Character set: %s", csname2);
+ FAIL_IF(strcmp(csname2, osname), "Wrong charset: expected os charset");
+ }
+ mysql_close(mysql);
+ return OK;
+}
+
+/* check if all server character sets are supported */
+static int test_conc223(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int found= 0;
+ int mdev27266= 0;
+
+ SKIP_MYSQL(mysql);
+
+ /*
+ Test if we're running against an MDEV-27266 server.
+ It can be detected by the presense of the FULL_COLLATION_NAME
+ column in I_S.COLLATION_CHARACTER_SET_APPLICABILITY.
+ */
+ rc= mysql_query(mysql,
+ "SELECT COUNT(*) "
+ "FROM INFORMATION_SCHEMA.COLUMNS "
+ "WHERE COLUMN_NAME='FULL_COLLATION_NAME' "
+ " AND TABLE_NAME='COLLATION_CHARACTER_SET_APPLICABILITY'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ if ((row= mysql_fetch_row(res)))
+ mdev27266= atoi(row[0]);
+ mysql_free_result(res);
+ diag("MDEV-27266 aware server: %d", mdev27266);
+
+ /*
+ Now get the list of collations either from I_S.COLLATIONS
+ or I_S.COLLATION_CHARACTER_SET_APPLICABILITY,
+ depending on the MDEV-27266 server awareness.
+ */
+ if (mdev27266)
+ rc= mysql_query(mysql,
+ "SELECT ID, CHARACTER_SET_NAME, FULL_COLLATION_NAME "
+ "FROM INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY");
+ else
+ rc= mysql_query(mysql,
+ "SELECT ID, CHARACTER_SET_NAME, COLLATION_NAME "
+ "FROM INFORMATION_SCHEMA.COLLATIONS");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ while ((row = mysql_fetch_row(res)))
+ {
+ int id;
+
+ if (row[0])
+ {
+ id= atoi(row[0]);
+ if (!mariadb_get_charset_by_nr(id))
+ {
+ diag("%04d %s %s", id, row[1], row[2]);
+ found++;
+ }
+ }
+ }
+ mysql_free_result(res);
+ if (found)
+ {
+ diag("%d character sets/collations not found", found);
+ return FAIL;
+ }
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc223", test_conc223, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"charset_auto", charset_auto, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bug_8378: mysql_real_escape with gbk", bug_8378, TEST_CONNECTION_NEW, 0, opt_bug8378, NULL},
+ {"test_client_character_set", test_client_character_set, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bug_10214: mysql_real_escape with NO_BACKSLASH_ESCAPES", bug_10214, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_escaping", test_escaping, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conversion", test_conversion, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"bug_41785", bug_41785, TEST_CONNECTION_DEFAULT, 0, NULL, "not fixed yet"},
+ {"test_bug27876", test_bug27876, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug30472", test_bug30472, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_ps_i18n", test_ps_i18n, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug_54100", test_bug_54100, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_utf16_utf32_noboms", test_utf16_utf32_noboms, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, 0}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/conc336.c b/libmariadb/unittest/libmariadb/conc336.c
new file mode 100644
index 00000000..3d1f47b5
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/conc336.c
@@ -0,0 +1,59 @@
+#include "my_test.h"
+
+#define MAX_COUNT 2000
+
+int main(int argc, char *argv[]) {
+
+ MYSQL *mysql;
+ int i;
+
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ if (IS_XPAND())
+ SKIP_XPAND;
+
+ if (IS_SKYSQL(hostname))
+ return 0;
+
+ if (IS_XPAND())
+ SKIP_XPAND;
+
+ diag("hostname: %s", hostname);
+
+ for (i = 0; i < MAX_COUNT; ++i) {
+
+ if (mysql_library_init(-1, NULL, NULL) != 0) {
+ diag("mysql_library_init failed");
+ return 1;
+ }
+
+ mysql = mysql_init(NULL);
+ if (!mysql) {
+ diag("mysql_init failed");
+ return 1;
+ }
+
+ if (force_tls)
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &force_tls);
+
+ if (!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0)) {
+ diag("mysql_real_connect failed: %s", mysql_error(mysql));
+ return 1;
+ }
+
+ if (mysql_query(mysql, "SELECT NULL LIMIT 0") != 0) {
+ diag("mysql_query failed: %s", mysql_error(mysql));
+ return 1;
+ }
+
+ mysql_close(mysql);
+ mysql_library_end();
+
+ }
+
+ return 0;
+
+}
diff --git a/libmariadb/unittest/libmariadb/connection.c b/libmariadb/unittest/libmariadb/connection.c
new file mode 100644
index 00000000..517bc538
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/connection.c
@@ -0,0 +1,2365 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ Some basic tests of the client API.
+*/
+
+#include "my_test.h"
+
+static int test_conc66(MYSQL *my)
+{
+ MYSQL *mysql= mysql_init(NULL);
+ int rc;
+ FILE *fp;
+ char query[1024];
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ if (!(fp= fopen("./my-conc66-test.cnf", "w")))
+ return FAIL;
+
+ fprintf(fp, "[notmygroup]\n");
+ fprintf(fp, "user=foo\n");
+ fprintf(fp, "[conc-66]\n");
+ fprintf(fp, "user=conc66\n");
+ fprintf(fp, "port=3306\n");
+ fprintf(fp, "enable-local-infile\n");
+ fprintf(fp, "server_plugin=file_key_management:file_key_management_algorithm=AES_CTR;file_key_management_key=secret\n");
+ fprintf(fp, "password='test@A1\\\";#test'\n");
+
+ fclose(fp);
+
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "conc-66");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my-conc66-test.cnf");
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "GRANT ALL ON %s.* TO 'conc66'@'%s' IDENTIFIED BY 'test@A1\";#test'", schema, this_host ? this_host : "localhost");
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+ rc= mysql_query(my, "FLUSH PRIVILEGES");
+ check_mysql_rc(rc, my);
+ if (!my_test_connect(mysql, hostname, NULL,
+ NULL, schema, port, socketname, 0))
+ {
+ diag("user: %s", mysql->options.user);
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+ diag("user: %s", mysql->options.user);
+
+ sprintf(query, "DROP user 'conc66'@'%s'", this_host ? this_host : "localhost");
+ rc= mysql_query(my, query);
+
+ check_mysql_rc(rc, my);
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_bug20023(MYSQL *mysql)
+{
+ int sql_big_selects_orig;
+ int max_join_size_orig;
+
+ int sql_big_selects_2;
+ int sql_big_selects_3;
+ int sql_big_selects_4;
+ int sql_big_selects_5;
+ int rc;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ if (mysql_get_server_version(mysql) < 50100) {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+
+ /***********************************************************************
+ Remember original SQL_BIG_SELECTS, MAX_JOIN_SIZE values.
+ ***********************************************************************/
+
+ query_int_variable(mysql,
+ "@@session.sql_big_selects",
+ &sql_big_selects_orig);
+
+ query_int_variable(mysql,
+ "@@global.max_join_size",
+ &max_join_size_orig);
+
+ /***********************************************************************
+ Test that COM_CHANGE_USER resets the SQL_BIG_SELECTS to the initial value.
+ ***********************************************************************/
+
+ /* Issue COM_CHANGE_USER. */
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ /* Query SQL_BIG_SELECTS. */
+
+ query_int_variable(mysql,
+ "@@session.sql_big_selects",
+ &sql_big_selects_2);
+
+ /* Check that SQL_BIG_SELECTS is reset properly. */
+
+ FAIL_UNLESS(sql_big_selects_orig == sql_big_selects_2, "Different value for sql_big_select");
+
+ /***********************************************************************
+ Test that if MAX_JOIN_SIZE set to non-default value,
+ SQL_BIG_SELECTS will be 0.
+ ***********************************************************************/
+
+ /* Set MAX_JOIN_SIZE to some non-default value. */
+
+ rc= mysql_query(mysql, "SET @@global.max_join_size = 10000");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "SET @@session.max_join_size = default");
+ check_mysql_rc(rc, mysql);
+
+ /* Issue COM_CHANGE_USER. */
+
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ /* Query SQL_BIG_SELECTS. */
+
+ query_int_variable(mysql,
+ "@@session.sql_big_selects",
+ &sql_big_selects_3);
+
+ /* Check that SQL_BIG_SELECTS is 0. */
+
+ FAIL_UNLESS(sql_big_selects_3 == 0, "big_selects != 0");
+
+ /***********************************************************************
+ Test that if MAX_JOIN_SIZE set to default value,
+ SQL_BIG_SELECTS will be 1.
+ ***********************************************************************/
+
+ /* Set MAX_JOIN_SIZE to the default value (-1). */
+
+ rc= mysql_query(mysql, "SET @@global.max_join_size = cast(-1 as unsigned int)");
+ rc= mysql_query(mysql, "SET @@session.max_join_size = default");
+
+ /* Issue COM_CHANGE_USER. */
+
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ /* Query SQL_BIG_SELECTS. */
+
+ query_int_variable(mysql,
+ "@@session.sql_big_selects",
+ &sql_big_selects_4);
+
+ /* Check that SQL_BIG_SELECTS is 1. */
+
+ FAIL_UNLESS(sql_big_selects_4 == 1, "sql_big_select != 1");
+
+ /***********************************************************************
+ Restore MAX_JOIN_SIZE.
+ Check that SQL_BIG_SELECTS will be the original one.
+ ***********************************************************************/
+
+ rc= mysql_query(mysql, "SET @@global.max_join_size = cast(-1 as unsigned int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SET @@session.max_join_size = default");
+ check_mysql_rc(rc, mysql);
+
+ /* Issue COM_CHANGE_USER. */
+
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ /* Query SQL_BIG_SELECTS. */
+
+ query_int_variable(mysql,
+ "@@session.sql_big_selects",
+ &sql_big_selects_5);
+
+ /* Check that SQL_BIG_SELECTS is 1. */
+
+ FAIL_UNLESS(sql_big_selects_5 == sql_big_selects_orig, "big_select != 1");
+
+ /***********************************************************************
+ That's it. Cleanup.
+ ***********************************************************************/
+
+ return OK;
+}
+
+static int test_change_user(MYSQL *mysql)
+{
+ char buff[256];
+ const char *user_pw= "mysqltest_pw";
+ const char *user_no_pw= "mysqltest_no_pw";
+ const char *pw= "password";
+ const char *db= "mysqltest_user_test_database";
+ int rc;
+
+ diag("Due to mysql_change_user security fix this test will not work anymore.");
+ return(SKIP);
+
+ /* Prepare environment */
+ sprintf(buff, "drop database if exists %s", db);
+ rc= mysql_query(mysql, buff);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(buff, "create database %s", db);
+ rc= mysql_query(mysql, buff);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(buff,
+ "grant select on %s.* to %s@'%%' identified by '%s'",
+ db,
+ user_pw,
+ pw);
+ rc= mysql_query(mysql, buff);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(buff,
+ "grant select on %s.* to %s@'%%'",
+ db,
+ user_no_pw);
+ rc= mysql_query(mysql, buff);
+ check_mysql_rc(rc, mysql);
+
+
+ /* Try some combinations */
+ rc= mysql_change_user(mysql, NULL, NULL, NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+
+ rc= mysql_change_user(mysql, "", NULL, NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, "", "", NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, "", "", "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, NULL, "", "");
+ FAIL_UNLESS(rc, "Error expected");
+
+
+ rc= mysql_change_user(mysql, NULL, NULL, "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, "", NULL, "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_pw, NULL, "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_pw, "", "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_pw, "", NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_pw, NULL, NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_pw, "", db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_pw, NULL, db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_pw, pw, db);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, user_pw, pw, NULL);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, user_pw, pw, "");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, user_no_pw, pw, db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_no_pw, pw, "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_no_pw, pw, NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user_no_pw, "", NULL);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, user_no_pw, "", "");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, user_no_pw, "", db);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, user_no_pw, NULL, db);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, "", pw, db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, "", pw, "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, "", pw, NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, NULL, pw, NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, NULL, NULL, db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, NULL, "", db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, "", "", db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ /* Cleanup the environment */
+
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(buff, "drop database %s", db);
+ rc= mysql_query(mysql, buff);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(buff, "drop user %s@'%%'", user_pw);
+ rc= mysql_query(mysql, buff);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(buff, "drop user %s@'%%'", user_no_pw);
+ rc= mysql_query(mysql, buff);
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/**
+ Bug#31669 Buffer overflow in mysql_change_user()
+*/
+
+#define LARGE_BUFFER_SIZE 2048
+
+static int test_bug31669(MYSQL *mysql)
+{
+ int rc;
+ static char buff[LARGE_BUFFER_SIZE+1];
+ static char user[USERNAME_CHAR_LENGTH+1];
+ static char db[NAME_CHAR_LEN+1];
+ static char query[LARGE_BUFFER_SIZE*2];
+
+ diag("Due to mysql_change_user security fix this test will not work anymore.");
+ return(SKIP);
+
+ rc= mysql_change_user(mysql, NULL, NULL, NULL);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc= mysql_change_user(mysql, "", "", "");
+ FAIL_UNLESS(rc, "Error expected");
+
+ memset(buff, 'a', sizeof(buff));
+
+ rc= mysql_change_user(mysql, buff, buff, buff);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc = mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ memset(db, 'a', sizeof(db));
+ db[NAME_CHAR_LEN]= 0;
+ sprintf(query, "CREATE DATABASE IF NOT EXISTS %s", db);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ memset(user, 'b', sizeof(user));
+ user[USERNAME_CHAR_LENGTH]= 0;
+ memset(buff, 'c', sizeof(buff));
+ buff[LARGE_BUFFER_SIZE]= 0;
+ sprintf(query, "GRANT ALL PRIVILEGES ON *.* TO '%s'@'%%' IDENTIFIED BY '%s' WITH GRANT OPTION", user, buff);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH PRIVILEGES");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_change_user(mysql, user, buff, db);
+ check_mysql_rc(rc, mysql);
+
+ user[USERNAME_CHAR_LENGTH-1]= 'a';
+ rc= mysql_change_user(mysql, user, buff, db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ user[USERNAME_CHAR_LENGTH-1]= 'b';
+ buff[LARGE_BUFFER_SIZE-1]= 'd';
+ rc= mysql_change_user(mysql, user, buff, db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ buff[LARGE_BUFFER_SIZE-1]= 'c';
+ db[NAME_CHAR_LEN-1]= 'e';
+ rc= mysql_change_user(mysql, user, buff, db);
+ FAIL_UNLESS(rc, "Error expected");
+
+ db[NAME_CHAR_LEN-1]= 'a';
+ rc= mysql_change_user(mysql, user, buff, db);
+ FAIL_UNLESS(!rc, "Error expected");
+
+ rc= mysql_change_user(mysql, user + 1, buff + 1, db + 1);
+ FAIL_UNLESS(rc, "Error expected");
+
+ rc = mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "DROP DATABASE %s", db);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "DELETE FROM mysql.user WHERE User='%s'", user);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+ FAIL_UNLESS(mysql_affected_rows(mysql) == 1, "");
+
+ return OK;
+}
+
+/**
+ Bug# 33831 my_test_connect() should fail if
+ given an already connected MYSQL handle.
+*/
+
+static int test_bug33831(MYSQL *mysql)
+{
+ FAIL_IF(my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0),
+ "Error expected");
+
+ return OK;
+}
+
+/* Test MYSQL_OPT_RECONNECT, Bug#15719 */
+
+static int test_opt_reconnect(MYSQL *mysql)
+{
+ my_bool my_true= TRUE;
+ int rc;
+ my_bool reconnect;
+
+ printf("true: %d\n", TRUE);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "not enough memory");
+
+ mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 0, "reconnect != 0");
+
+ rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true);
+ check_mysql_rc(rc, mysql);
+
+ mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 1, "reconnect != 1");
+
+ if (!(my_test_connect(mysql, hostname, username,
+ password, schema, port,
+ socketname, 0)))
+ {
+ diag("connection failed");
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 1, "reconnect != 1");
+
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "not enough memory");
+
+ mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 0, "reconnect != 0");
+
+ if (!(my_test_connect(mysql, hostname, username,
+ password, schema, port,
+ socketname, 0)))
+ {
+ diag("connection failed");
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 0, "reconnect != 0");
+
+ mysql_close(mysql);
+ return OK;
+}
+
+
+static int test_compress(MYSQL *mysql)
+{
+ // maxscale doesn't support compression
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+ SKIP_MAXSCALE;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "not enough memory");
+
+ /* use compressed protocol */
+ rc= mysql_options(mysql, MYSQL_OPT_COMPRESS, NULL);
+
+ if (!(my_test_connect(mysql, hostname, username,
+ password, schema, port,
+ socketname, 0)))
+ {
+ diag("connection failed");
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "SHOW STATUS LIKE 'compression'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ FAIL_UNLESS(strcmp(row[1], "ON") == 0, "Compression off");
+ mysql_free_result(res);
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_reconnect(MYSQL *mysql)
+{
+ my_bool my_true= TRUE;
+ MYSQL *mysql1;
+ int rc;
+ my_bool reconnect;
+ SKIP_MAXSCALE;
+
+ mysql1= mysql_init(NULL);
+ FAIL_IF(!mysql1, "not enough memory");
+
+ mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 0, "reconnect != 0");
+
+ rc= mysql_options(mysql1, MYSQL_OPT_RECONNECT, &my_true);
+ check_mysql_rc(rc, mysql1);
+
+ mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 1, "reconnect != 1");
+
+ if (!(my_test_connect(mysql1, hostname, username,
+ password, schema, port,
+ socketname, 0)))
+ {
+ diag("connection failed");
+ return FAIL;
+ }
+
+ mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 1, "reconnect != 1");
+
+ diag("Thread_id before kill: %lu", mysql_thread_id(mysql1));
+ mysql_kill(mysql, mysql_thread_id(mysql1));
+
+ mysql_ping(mysql1);
+
+ rc= mysql_query(mysql1, "SELECT 1 FROM DUAL LIMIT 0");
+ check_mysql_rc(rc, mysql1);
+ diag("Thread_id after kill: %lu", mysql_thread_id(mysql1));
+
+ mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_UNLESS(reconnect == 1, "reconnect != 1");
+ mysql_close(mysql1);
+ return OK;
+}
+
+int test_conc21(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *res= NULL;
+ MYSQL_ROW row;
+ char tmp[256];
+ unsigned int check_server_version= 0;
+ int major=0, minor= 0, patch=0;
+ SKIP_MAXSCALE;
+
+ if (strlen(mysql_get_server_info(mysql)) > 63)
+ {
+ diag("server name is too long - skip until rpl hack was removed");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "SELECT @@version");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_IF(res == NULL, "invalid result set");
+
+ row= mysql_fetch_row(res);
+ strcpy(tmp, row[0]);
+ mysql_free_result(res);
+
+ sscanf(tmp, "%d.%d.%d", &major, &minor, &patch);
+
+ check_server_version= major * 10000 + minor * 100 + patch;
+
+ FAIL_IF(mysql_get_server_version(mysql) != check_server_version, "Numeric server version mismatch");
+ FAIL_IF(strcmp(mysql_get_server_info(mysql), tmp) != 0, "String server version mismatch");
+ return OK;
+}
+
+int test_conc26(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "ascii");
+
+ FAIL_IF(my_test_connect(mysql, hostname, "notexistinguser", "password", schema, port, socketname, CLIENT_REMEMBER_OPTIONS),
+ "Error expected");
+ FAIL_IF(!mysql->options.charset_name || strcmp(mysql->options.charset_name, "ascii") != 0,
+ "expected charsetname=ascii");
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(my_test_connect(mysql, hostname, "notexistinguser", "password", schema, port, socketname, 0),
+ "Error expected");
+ FAIL_IF(mysql->options.charset_name, "Error: options not freed");
+ mysql_close(mysql);
+
+ return OK;
+}
+
+int test_connection_timeout(MYSQL *unused __attribute__((unused)))
+{
+ unsigned int timeout= 5;
+ time_t start, elapsed;
+ MYSQL *mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
+ start= time(NULL);
+ if (my_test_connect(mysql, "192.168.1.101", "notexistinguser", "password", schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Error expected - maybe you have to change hostname");
+ return FAIL;
+ }
+ elapsed= time(NULL) - start;
+ diag("elapsed: %lu", (unsigned long)elapsed);
+ mysql_close(mysql);
+ FAIL_IF((unsigned int)elapsed > 2 * timeout, "timeout ignored");
+ return OK;
+}
+
+int test_connection_timeout2(MYSQL *unused __attribute__((unused)))
+{
+ unsigned int timeout= 5;
+ time_t start, elapsed;
+ MYSQL *mysql;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+ SKIP_TLS;
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
+ mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(7)");
+ start= time(NULL);
+ if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ elapsed= time(NULL) - start;
+ diag("elapsed: %lu", (unsigned long)elapsed);
+ diag("timeout error expected");
+ return FAIL;
+ }
+ elapsed= time(NULL) - start;
+ diag("elapsed: %lu", (unsigned long)elapsed);
+ mysql_close(mysql);
+ FAIL_IF((unsigned int)elapsed > 2 * timeout, "timeout ignored");
+ return OK;
+}
+
+int test_connection_timeout3(MYSQL *unused __attribute__((unused)))
+{
+ unsigned int timeout= 5;
+ unsigned int read_write_timeout= 10;
+ int rc;
+ time_t start, elapsed;
+ MYSQL *mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
+ mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (unsigned int *)&read_write_timeout);
+ mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (unsigned int *)&read_write_timeout);
+ mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(6)");
+ start= time(NULL);
+ if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("timeout error expected");
+ elapsed= time(NULL) - start;
+ diag("elapsed: %lu", (unsigned long)elapsed);
+ return FAIL;
+ }
+ elapsed= time(NULL) - start;
+ diag("elapsed: %lu", (unsigned long)elapsed);
+ FAIL_IF((unsigned int)elapsed > timeout + 1, "timeout ignored");
+
+ mysql_close(mysql);
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
+ mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (unsigned int *)&read_write_timeout);
+ mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (unsigned int *)&read_write_timeout);
+
+ if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+
+ start= time(NULL);
+ rc= mysql_query(mysql, "SET @a:=SLEEP(12)");
+ elapsed= time(NULL) - start;
+ diag("elapsed: %lu", (unsigned long)elapsed);
+ FAIL_IF(!rc, "timeout expected");
+ mysql_close(mysql);
+ return OK;
+}
+
+
+/* test should run with valgrind */
+static int test_conc118(MYSQL *mysql)
+{
+ int rc;
+ my_bool reconnect= 1;
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+
+ mysql->options.unused_1= 1;
+
+ rc= mysql_kill(mysql, mysql_thread_id(mysql));
+
+ mysql_ping(mysql);
+
+ rc= mysql_query(mysql, "SET @a:=1");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql->options.unused_1 != 1, "options got lost");
+
+ rc= mysql_kill(mysql, mysql_thread_id(mysql));
+
+ mysql_ping(mysql);
+ rc= mysql_query(mysql, "SET @a:=1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_wrong_bind_address(MYSQL *unused __attribute__((unused)))
+{
+ const char *bind_addr= "100.188.111.112";
+ MYSQL *mysql;
+
+ if (!hostname || !strcmp(hostname, "localhost"))
+ {
+ diag("test doesn't work with unix sockets");
+ return SKIP;
+ }
+
+ mysql= mysql_init(NULL);
+
+ mysql_options(mysql, MYSQL_OPT_BIND, bind_addr);
+ if (my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error expected");
+ mysql_close(mysql);
+ return FAIL;
+ }
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_bind_address(MYSQL *my)
+{
+ MYSQL *mysql;
+ char *bind_addr= getenv("MYSQL_TEST_BINDADDR");
+ char query[128];
+ int rc;
+
+ SKIP_SKYSQL;
+
+ if (!hostname || !strcmp(hostname, "localhost"))
+ {
+ diag("test doesn't work with unix sockets");
+ return SKIP;
+ }
+
+ sprintf(query, "DROP USER '%s'@'%s'", username, bind_addr);
+ rc= mysql_query(my, query);
+
+ sprintf(query, "CREATE USER '%s'@'%s' IDENTIFIED BY '%s'", username, bind_addr, password);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ sprintf(query, "GRANT ALL ON %s.* TO '%s'@'%s'", schema, username, bind_addr);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ if (!bind_addr)
+ {
+ diag("No bind address specified");
+ return SKIP;
+ }
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_BIND, bind_addr);
+
+ if (!my_test_connect(mysql, bind_addr, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s\n", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+ diag("%s", mysql_get_host_info(mysql));
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_get_options(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_LOCAL_INFILE,
+ MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0};
+ my_bool options_bool[]= {MYSQL_OPT_RECONNECT, MYSQL_REPORT_DATA_TRUNCATION,
+ MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH,
+#ifdef _WIN32
+ MYSQL_OPT_NAMED_PIPE,
+#endif
+ 0};
+ int options_char[]= {MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, MYSQL_SET_CHARSET_NAME,
+ MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CERT, MYSQL_OPT_SSL_CAPATH,
+ MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_BIND, MARIADB_OPT_SSL_FP, MARIADB_OPT_SSL_FP_LIST,
+ MARIADB_OPT_TLS_PASSPHRASE, 0};
+
+ const char *init_command[3]= {"SET @a:=1", "SET @b:=2", "SET @c:=3"};
+ int elements= 0;
+ char **command;
+
+
+ int intval[2]= {1, 0};
+ my_bool boolval[2]= {1, 0};
+ const char *char1= "test";
+ char *char2;
+ int i;
+ MYSQL *userdata;
+ const char *attr_key[] = {"foo1", "foo2", "foo3"};
+ const char *attr_val[] = {"bar1", "bar2", "bar3"};
+ char **key, **val;
+
+ for (i=0; i < (int)(sizeof(options_int)/sizeof(int)); i++)
+ {
+ mysql_options(mysql, options_int[i], &intval[0]);
+ intval[1]= 0;
+ mysql_get_optionv(mysql, options_int[i], &intval[1]);
+ FAIL_IF(intval[0] != intval[1], "mysql_get_optionv (int) failed");
+ }
+ for (i=0; options_bool[i]; i++)
+ {
+ mysql_options(mysql, options_bool[i], &boolval[0]);
+ intval[1]= 0;
+ mysql_get_optionv(mysql, options_bool[i], &boolval[1]);
+ FAIL_IF(boolval[0] != boolval[1], "mysql_get_optionv (my_bool) failed");
+ }
+ for (i=0; options_char[i]; i++)
+ {
+ mysql_options(mysql, options_char[i], char1);
+ char2= NULL;
+ mysql_get_optionv(mysql, options_char[i], (void *)&char2);
+ if (options_char[i] != MYSQL_SET_CHARSET_NAME)
+ FAIL_IF(strcmp(char1, char2), "mysql_get_optionv (char) failed");
+ }
+
+ for (i=0; i < 3; i++)
+ mysql_options(mysql, MYSQL_INIT_COMMAND, init_command[i]);
+
+ mysql_get_optionv(mysql, MYSQL_INIT_COMMAND, &command, &elements);
+ FAIL_IF(elements != 3, "expected 3 elements");
+ for (i=0; i < 3; i++)
+ FAIL_IF(strcmp(init_command[i], command[i]), "wrong init command");
+ for (i=0; i < 3; i++)
+ mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, attr_key[i], attr_val[i]);
+
+ mysql_get_optionv(mysql, MYSQL_OPT_CONNECT_ATTRS, NULL, NULL, &elements);
+ FAIL_IF(elements != 3, "expected 3 connection attributes");
+
+ key= (char **)malloc(sizeof(char *) * elements);
+ val= (char **)malloc(sizeof(char *) * elements);
+
+ mysql_get_optionv(mysql, MYSQL_OPT_CONNECT_ATTRS, &key, &val, &elements);
+ for (i=0; i < elements; i++)
+ {
+ diag("%s => %s", key[i], val[i]);
+ }
+
+ free(key);
+ free(val);
+
+ mysql_optionsv(mysql, MARIADB_OPT_USERDATA, "my_app", (void *)mysql);
+ mysql_get_optionv(mysql, MARIADB_OPT_USERDATA, (char *)"my_app", &userdata);
+
+ FAIL_IF(mysql != userdata, "wrong userdata");
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_sess_track_db(MYSQL *mysql)
+{
+ int rc;
+ const char *data;
+ size_t len;
+ char tmp_str[512];
+
+
+ if (!(mysql->server_capabilities & CLIENT_SESSION_TRACKING))
+ {
+ diag("Server doesn't support session tracking (cap=%lu)", mysql->server_capabilities);
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "USE mysql");
+ check_mysql_rc(rc, mysql);
+ FAIL_IF(strcmp(mysql->db, "mysql"), "Expected new schema 'mysql'");
+
+ FAIL_IF(mysql_session_track_get_first(mysql, SESSION_TRACK_SCHEMA, &data, &len),
+ "session_track_get_first failed");
+ FAIL_IF(strncmp(data, "mysql", len), "Expected new schema 'mysql'");
+
+ sprintf(tmp_str, "USE %s", schema);
+ rc= mysql_query(mysql, tmp_str);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(tmp_str, "Expected new schema '%s'.", schema);
+
+ FAIL_IF(strcmp(mysql->db, schema), tmp_str);
+
+ FAIL_IF(mysql_session_track_get_first(mysql, SESSION_TRACK_SCHEMA, &data, &len),
+ "session_track_get_first failed");
+ FAIL_IF(strncmp(data, schema, len), tmp_str);
+
+ if (mysql_get_server_version(mysql) >= 100300)
+ {
+ diag("charset: %s", mysql->charset->csname);
+ rc= mysql_query(mysql, "SET NAMES ascii");
+ check_mysql_rc(rc, mysql);
+ if (!mysql_session_track_get_first(mysql, SESSION_TRACK_SYSTEM_VARIABLES, &data, &len))
+ do {
+ printf("# SESSION_TRACK_VARIABLES: %*.*s\n", (int)len, (int)len, data);
+ } while (!mysql_session_track_get_next(mysql, SESSION_TRACK_SYSTEM_VARIABLES, &data, &len));
+ diag("charset: %s", mysql->charset->csname);
+ FAIL_IF(strcmp(mysql->charset->csname, "ascii"),
+ "Expected charset 'ascii'");
+
+ rc= mysql_query(mysql, "SET NAMES latin1");
+ check_mysql_rc(rc, mysql);
+ FAIL_IF(strcmp(mysql->charset->csname, "latin1"), "Expected charset 'latin1'");
+ }
+ rc= mysql_query(mysql, "CREATE PROCEDURE p1() "
+ "BEGIN "
+ "SET @@autocommit=0; "
+ "SET NAMES utf8; "
+ "SET session auto_increment_increment=2; "
+ "END ");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CALL p1()");
+ check_mysql_rc(rc, mysql);
+
+ if (!mysql_session_track_get_first(mysql, SESSION_TRACK_SYSTEM_VARIABLES, &data, &len))
+ do {
+ printf("# SESSION_TRACK_VARIABLES: %*.*s\n", (int)len, (int)len, data);
+ } while (!mysql_session_track_get_next(mysql, SESSION_TRACK_SYSTEM_VARIABLES, &data, &len));
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc496(MYSQL *mysql)
+{
+ int rc;
+ const char *data;
+ size_t len;
+
+ rc= mysql_query(mysql, "set @@session.session_track_transaction_info=STATE");
+
+ if (rc && mysql_errno(mysql) == ER_UNKNOWN_SYSTEM_VARIABLE)
+ {
+ diag("session_track_transaction_info not supported");
+ return SKIP;
+ }
+
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "BEGIN");
+ check_mysql_rc(rc, mysql);
+ if (!mysql_session_track_get_first(mysql, SESSION_TRACK_TRANSACTION_STATE, &data, &len))
+ do {
+ FAIL_IF(len != 8, "expected 8 bytes");
+ FAIL_IF(data[0] != 'T', "expected transaction");
+ } while (!mysql_session_track_get_next(mysql, SESSION_TRACK_TRANSACTION_STATE, &data, &len));
+
+ rc= mysql_query(mysql, "CREATE TEMPORARY TABLE t1(a int) ENGINE=InnoDB");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "COMMIT");
+
+ check_mysql_rc(rc, mysql);
+
+ if (!mysql_session_track_get_first(mysql, SESSION_TRACK_TRANSACTION_STATE, &data, &len))
+ do {
+ FAIL_IF(len != 8, "expected 8 bytes");
+ FAIL_IF(data[0] != '_', "expected underscore");
+ } while (!mysql_session_track_get_next(mysql, SESSION_TRACK_TRANSACTION_STATE, &data, &len));
+
+ return OK;
+}
+
+
+static int test_unix_socket_close(MYSQL *unused __attribute__((unused)))
+{
+#ifdef _WIN32
+ diag("test does not run on Windows");
+ return SKIP;
+#else
+ MYSQL *mysql= mysql_init(NULL);
+ FILE *fp;
+ int i;
+
+ SKIP_SKYSQL;
+ SKIP_TRAVIS();
+
+ if (!(fp= fopen("./dummy_sock", "w")))
+ {
+ diag("couldn't create dummy socket");
+ return FAIL;
+ }
+ fclose(fp);
+
+ for (i=0; i < 10000; i++)
+ {
+ my_test_connect(mysql, "localhost", "user", "passwd", NULL, 0, "./dummy_sock", 0);
+ /* check if we run out of sockets */
+ if (mysql_errno(mysql) == 2001)
+ {
+ diag("out of sockets after %d attempts", i);
+ mysql_close(mysql);
+ return FAIL;
+ }
+ }
+ mysql_close(mysql);
+ return OK;
+#endif
+}
+
+
+static int test_reset(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *res;
+
+ if (mysql_get_server_version(mysql) < 100200)
+ return SKIP;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1),(2),(3)");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_affected_rows(mysql) != 3, "Expected 3 rows");
+
+ rc= mysql_reset_connection(mysql);
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_affected_rows(mysql) != ~(my_ulonglong)0, "Expected 0 rows");
+
+ rc= mysql_query(mysql, "SELECT a FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT 1 FROM DUAL");
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_reset_connection(mysql);
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_IF(res, "expected no result");
+
+ rc= mysql_query(mysql, "SELECT a FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_use_result(mysql);
+ FAIL_IF(!res, "expected result");
+
+ rc= mysql_reset_connection(mysql);
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_fetch_row(res), "expected error");
+
+ mysql_free_result(res);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_auth256(MYSQL *my)
+{
+ MYSQL *mysql= mysql_init(NULL);
+ int rc;
+ MYSQL_RES *res;
+ my_ulonglong num_rows= 0;
+ char query[1024];
+ SKIP_MAXSCALE;
+
+ if (IS_SKYSQL(hostname))
+ return SKIP;
+
+ // xpand doesn't have information_schema.plugins
+ SKIP_XPAND;
+
+ if (!mysql_client_find_plugin(mysql, "sha256_password", MYSQL_CLIENT_AUTHENTICATION_PLUGIN))
+ {
+ diag("sha256_password plugin not available");
+ mysql_close(mysql);
+ return SKIP;
+ }
+
+ rc= mysql_query(my, "SELECT * FROM information_schema.plugins where plugin_name='sha256_password'");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(my);
+ num_rows= mysql_num_rows(res);
+ mysql_free_result(res);
+
+ if (!num_rows)
+ {
+ diag("server doesn't support sha256 authentication");
+ mysql_close(mysql);
+ return SKIP;
+ }
+
+ rc= mysql_query(my, "DROP USER IF EXISTS sha256user@localhost");
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "CREATE user 'sha256user'@'%s' identified with sha256_password by 'foo'", this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ if (!my_test_connect(mysql, hostname, "sha256user", "foo", NULL, port, socketname, 0))
+ {
+ diag("error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_SERVER_PUBLIC_KEY, "rsa_public_key.pem");
+ if (!my_test_connect(mysql, hostname, "sha256user", "foo", NULL, port, socketname, 0))
+ {
+ diag("error: %s", mysql_error(mysql));
+ diag("host: %s", this_host);
+ mysql_close(mysql);
+ return FAIL;
+ }
+ mysql_close(mysql);
+ sprintf(query, "DROP USER 'sha256user'@'%s'", this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_mdev13100(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ int rc;
+ FILE *fp;
+
+ if (!(fp= fopen("./mdev13100.cnf", "w")))
+ return FAIL;
+
+ /* [client] group only */
+ fprintf(fp, "[client]\n");
+ fprintf(fp, "default-character-set=latin2\n");
+
+ fclose(fp);
+
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./mdev13100.cnf");
+ check_mysql_rc(rc, mysql);
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+ FAIL_IF(strcmp("latin2", mysql_character_set_name(mysql)), "Expected charset latin2");
+ mysql_close(mysql);
+
+ /* value from client-mariadb group */
+ mysql= mysql_init(NULL);
+ if (!(fp= fopen("./mdev13100.cnf", "w")))
+ return FAIL;
+
+ fprintf(fp, "[client]\n");
+ fprintf(fp, "default-character-set=latin1\n");
+ fprintf(fp, "[client-server]\n");
+ fprintf(fp, "default-character-set=latin2\n");
+
+ fclose(fp);
+
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./mdev13100.cnf");
+ check_mysql_rc(rc, mysql);
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+ FAIL_IF(strcmp("latin2", mysql_character_set_name(mysql)), "Expected charset latin2");
+ mysql_close(mysql);
+
+/* values from client-mariadb group */
+ mysql= mysql_init(NULL);
+
+if (!(fp= fopen("./mdev13100.cnf", "w")))
+ return FAIL;
+
+ fprintf(fp, "[client]\n");
+ fprintf(fp, "default-character-set=latin1\n");
+ fprintf(fp, "[client-server]\n");
+ fprintf(fp, "default-character-set=utf8\n");
+ fprintf(fp, "[client-mariadb]\n");
+ fprintf(fp, "default-character-set=latin2\n");
+
+ fclose(fp);
+
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./mdev13100.cnf");
+ check_mysql_rc(rc, mysql);
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+ FAIL_IF(strcmp("latin2", mysql_character_set_name(mysql)), "Expected charset latin2");
+ mysql_close(mysql);
+
+/* values from mdev-13100 group */
+ mysql= mysql_init(NULL);
+ if (!(fp= fopen("./mdev13100.cnf", "w")))
+ return FAIL;
+
+ fprintf(fp, "[client]\n");
+ fprintf(fp, "default-character-set=latin1\n");
+ fprintf(fp, "[client-server]\n");
+ fprintf(fp, "default-character-set=latin1\n");
+ fprintf(fp, "[client-mariadb]\n");
+ fprintf(fp, "default-character-set=utf8\n");
+ fprintf(fp, "[mdev13100]\n");
+ fprintf(fp, "default-character-set=latin2\n");
+
+ fclose(fp);
+
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./mdev13100.cnf");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "mdev13100");
+ check_mysql_rc(rc, mysql);
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+ FAIL_IF(strcmp("latin2", mysql_character_set_name(mysql)), "Expected charset latin2");
+ mysql_close(mysql);
+
+/* values from [programname] group */
+ mysql= mysql_init(NULL);
+ if (!(fp= fopen("./mdev13100.cnf", "w")))
+ return FAIL;
+
+ fprintf(fp, "[client]\n");
+ fprintf(fp, "default-character-set=utf8\n");
+ fprintf(fp, "[client-server]\n");
+ fprintf(fp, "default-character-set=utf8\n");
+ fprintf(fp, "[client-mariadb]\n");
+ fprintf(fp, "default-character-set=latin2\n");
+
+ fclose(fp);
+
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./mdev13100.cnf");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
+ check_mysql_rc(rc, mysql);
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+ diag("character set: %s", mysql_character_set_name(mysql));
+ FAIL_IF(strcmp("latin2", mysql_character_set_name(mysql)), "Expected charset latin2");
+ mysql_close(mysql);
+
+ remove("./mdev13100.cnf");
+
+ return OK;
+}
+
+static int test_conc276(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ int rc;
+ my_bool val= 1;
+
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &val);
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &val);
+
+ if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0))
+ {
+ diag("Connection failed. Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+ diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
+
+ rc= mariadb_reconnect(mysql);
+ check_mysql_rc(rc, mysql);
+
+ diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
+ /* this shouldn't crash anymore */
+ rc= mysql_query(mysql, "SET @a:=1");
+ check_mysql_rc(rc, mysql);
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_expired_pw(MYSQL *my)
+{
+ MYSQL *mysql;
+ int rc;
+ char query[512];
+ unsigned char expire= 1;
+
+ if (mariadb_connection(my) ||
+ !(my->server_capabilities & CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS))
+ {
+ diag("Server doesn't support password expiration");
+ return SKIP;
+ }
+ sprintf(query, "DROP USER 'foo'@'%s'", this_host);
+ rc= mysql_query(my, query);
+
+ sprintf(query, "CREATE USER 'foo'@'%s' IDENTIFIED BY 'foo'", this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ sprintf(query, "GRANT ALL ON *.* TO 'foo'@'%s'", this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ sprintf(query, "ALTER USER 'foo'@'%s' PASSWORD EXPIRE", this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ mysql= mysql_init(NULL);
+
+ my_test_connect(mysql, hostname, "foo", "foo", schema,
+ port, socketname, 0);
+
+ FAIL_IF(!mysql_errno(mysql), "Error expected");
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ mysql_optionsv(mysql, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, &expire);
+
+ my_test_connect(mysql, hostname, "foo", "foo", schema,
+ port, socketname, 0);
+
+ /* we should be in sandbox mode now, only set commands should be allowed */
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ FAIL_IF(!rc, "Error expected (we are in sandbox mode");
+
+ diag("error: %d %s", mysql_errno(mysql), mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql) != ER_MUST_CHANGE_PASSWORD &&
+ mysql_errno(mysql) != ER_MUST_CHANGE_PASSWORD_LOGIN, "Error 1820/1862 expected");
+
+ mysql_close(mysql);
+
+ sprintf(query, "DROP USER 'foo'@'%s'", this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ return OK;
+}
+
+static int test_conc315(MYSQL *mysql)
+{
+ int rc;
+ const char *csname;
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ mysql_get_optionv(mysql, MYSQL_SET_CHARSET_NAME, (void *)&csname);
+ diag("csname=%s", csname);
+ FAIL_UNLESS(strcmp(csname, MARIADB_DEFAULT_CHARSET) == 0, "Wrong default character set");
+
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+ mysql_get_optionv(mysql, MYSQL_SET_CHARSET_NAME, (void *)&csname);
+ FAIL_UNLESS(strcmp(csname, MARIADB_DEFAULT_CHARSET) == 0, "Wrong default character set");
+ return OK;
+}
+#ifndef WIN32
+static int test_conc317(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+ my_bool reconnect = 0;
+ FILE *fp= NULL;
+ const char *env= getenv("MYSQL_TMP_DIR");
+ char cnf_file1[FN_REFLEN + 1];
+
+ SKIP_SKYSQL;
+
+ if (travis_test)
+ return SKIP;
+
+ if (!env)
+ env= "/tmp";
+
+ setenv("HOME", env, 1);
+
+ snprintf(cnf_file1, FN_REFLEN, "%s%c.my.cnf", env, FN_LIBCHAR);
+
+ FAIL_IF(!access(cnf_file1, R_OK), "access");
+
+ mysql= mysql_init(NULL);
+ fp= fopen(cnf_file1, "w");
+ FAIL_IF(!fp, "fopen");
+
+ fprintf(fp, "[client]\ndefault-character-set = latin2\nreconnect= 1\n");
+ fclose(fp);
+
+ mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
+ my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, 0);
+
+ remove(cnf_file1);
+
+ FAIL_IF(strcmp(mysql_character_set_name(mysql), "latin2"), "expected charset latin2");
+ mysql_get_optionv(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_IF(reconnect != 1, "expected reconnect=1");
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc327(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+ my_bool reconnect = 0;
+ FILE *fp1= NULL, *fp2= NULL;
+ const char *env= getenv("MYSQL_TMP_DIR");
+ char cnf_file1[FN_REFLEN + 1];
+ char cnf_file2[FN_REFLEN + 1];
+
+ SKIP_SKYSQL;
+
+ if (travis_test)
+ return SKIP;
+
+ if (!env)
+ env= "/tmp";
+
+ setenv("HOME", env, 1);
+
+ snprintf(cnf_file1, FN_REFLEN, "%s%c.my.cnf", env, FN_LIBCHAR);
+ snprintf(cnf_file2, FN_REFLEN, "%s%c.my.tmp", env, FN_LIBCHAR);
+
+ FAIL_IF(!access(cnf_file1, R_OK), "access");
+
+ fp1= fopen(cnf_file1, "w");
+ fp2= fopen(cnf_file2, "w");
+ FAIL_IF(!fp1 || !fp2, "fopen failed");
+
+ fprintf(fp1, "!include %s\n", cnf_file2);
+
+ fprintf(fp2, "[client]\ndefault-character-set = latin2\nreconnect= 1\n");
+ fclose(fp1);
+ fclose(fp2);
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
+ my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, 0);
+
+ remove(cnf_file1);
+ remove(cnf_file2);
+
+ diag("new charset: %s", mysql->options.charset_name);
+ FAIL_IF(strcmp(mysql_character_set_name(mysql), "latin2"), "expected charset latin2");
+ mysql_get_optionv(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_IF(reconnect != 1, "expected reconnect=1");
+ mysql_close(mysql);
+
+ snprintf(cnf_file1, FN_REFLEN, "%s%cmy.cnf", env, FN_LIBCHAR);
+ fp1= fopen(cnf_file1, "w");
+ fp2= fopen(cnf_file2, "w");
+ FAIL_IF(!fp1 || !fp2, "fopen failed");
+
+ fprintf(fp2, "!includedir %s\n", env);
+
+ fprintf(fp1, "[client]\ndefault-character-set = latin2\nreconnect= 1\n");
+ fclose(fp1);
+ fclose(fp2);
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, cnf_file2);
+ my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, 0);
+
+ remove(cnf_file1);
+ remove(cnf_file2);
+
+ FAIL_IF(strcmp(mysql_character_set_name(mysql), "latin2"), "expected charset latin2");
+ mysql_get_optionv(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_IF(reconnect != 1, "expected reconnect=1");
+ mysql_close(mysql);
+
+ return OK;
+}
+#endif
+
+static int test_conc332(MYSQL *unused __attribute__((unused)))
+{
+ int rc;
+ MYSQL *mysql= mysql_init(NULL);
+ int server_status1, server_status2;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4");
+
+ my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0);
+
+ FAIL_IF(mysql_errno(mysql), "Error during connect");
+
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_STATUS, &server_status1);
+ diag("server_status: %d", server_status1);
+
+ if (server_status1 & SERVER_STATUS_AUTOCOMMIT)
+ rc= mysql_query(mysql, "SET autocommit= 0");
+ else
+ rc= mysql_query(mysql, "SET autocommit= 1");
+ check_mysql_rc(rc, mysql);
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_STATUS, &server_status2);
+ diag("server_status after changing autocommit: %d", server_status2);
+
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_STATUS, &server_status2);
+ diag("server_status after mysql_change_user: %d", server_status2);
+ if (server_status1 != server_status2)
+ {
+ diag("Expected server_status %d instead of %d", server_status1, server_status2);
+ mysql_close(mysql);
+ return FAIL;
+ }
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc351(MYSQL *unused __attribute__((unused)))
+{
+ int rc;
+ const char *data;
+ size_t len;
+ MYSQL *mysql= mysql_init(NULL);
+ ulong capabilities= 0;
+
+ my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0);
+
+ FAIL_IF(mysql_errno(mysql), "Error during connect");
+
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_CAPABILITIES, &capabilities);
+ if (!(capabilities & CLIENT_SESSION_TRACKING))
+ {
+ mysql_close(mysql);
+ diag("Server doesn't support session tracking (cap=%lu)", mysql->server_capabilities);
+ return SKIP;
+ }
+ rc= mysql_query(mysql, "USE mysql");
+ check_mysql_rc(rc, mysql);
+ FAIL_IF(strcmp(mysql->db, "mysql"), "Expected new schema 'mysql'");
+
+ FAIL_IF(mysql_session_track_get_first(mysql, SESSION_TRACK_SCHEMA, &data, &len), "expected session track schema");
+
+ rc= mysql_query(mysql, "SET @a:=1");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(!mysql_session_track_get_first(mysql, SESSION_TRACK_SCHEMA, &data, &len), "expected no schema tracking information");
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc312(MYSQL *my)
+{
+ int rc;
+ char query[1024];
+ MYSQL *mysql;
+
+ sprintf(query, "DROP USER 'foo'@'%s'", this_host);
+ rc= mysql_query(my, query);
+
+ sprintf(query, "CREATE USER 'foo'@'%s' IDENTIFIED WITH caching_sha2_password BY 'foo'", this_host);
+ rc= mysql_query(my, query);
+
+ if (rc)
+ {
+ diag("Error: %s", mysql_error(my));
+ diag("caching_sha256_password not supported");
+ return SKIP;
+ }
+
+ sprintf(query, "GRANT ALL ON %s.* TO 'foo'@'%s'", schema, this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, my);
+
+ mysql= mysql_init(NULL);
+ if (!my_test_connect(mysql, hostname, "foo", "foo", schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ return FAIL;
+ }
+
+ mysql_close(mysql);
+
+ sprintf(query, "DROP USER 'foo'@'%s'", this_host);
+ rc= mysql_query(my, query);
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc366(MYSQL *mysql)
+{
+ char query[1024];
+ int rc;
+ MYSQL *my;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ {
+ diag("feature not supported by MySQL server");
+ return SKIP;
+ }
+
+ /* check if ed25519 plugin is available */
+ if (!mysql_client_find_plugin(mysql, "client_ed25519", MYSQL_CLIENT_AUTHENTICATION_PLUGIN))
+ {
+ diag("client_ed25519 plugin not available");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "INSTALL SONAME 'auth_ed25519'");
+ if (rc)
+ {
+ diag("feature not supported, ed25519 plugin not available");
+ return SKIP;
+ }
+
+ if (mysql_get_server_version(mysql) < 100400) {
+ sprintf(query, "CREATE OR REPLACE USER 'ede'@'%s' IDENTIFIED VIA ed25519 USING '6aW9C7ENlasUfymtfMvMZZtnkCVlcb1ssxOLJ0kj/AA'", this_host);
+ } else {
+ sprintf(query, "CREATE OR REPLACE USER 'ede'@'%s' IDENTIFIED VIA ed25519 USING PASSWORD('MySup8%%rPassw@ord')", this_host);
+ }
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "GRANT ALL ON %s.* TO 'ede'@'%s'", schema, this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ my= mysql_init(NULL);
+ if (plugindir)
+ mysql_options(my, MYSQL_PLUGIN_DIR, plugindir);
+ if (!my_test_connect(my, hostname, "ede", "MySup8%rPassw@ord", schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(my));
+ return FAIL;
+ }
+ mysql_close(my);
+
+ sprintf(query, "DROP USER 'ede'@'%s'", this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "UNINSTALL SONAME 'auth_ed25519'");
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc392(MYSQL *mysql)
+{
+ int rc;
+ const char *data;
+ size_t len;
+ ulong capabilities= 0;
+
+ SKIP_MYSQL(mysql);
+
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_CAPABILITIES, &capabilities);
+ if (!(capabilities & CLIENT_SESSION_TRACKING))
+ {
+ diag("Server doesn't support session tracking (cap=%lu)", mysql->server_capabilities);
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "set session_track_state_change=1");
+ check_mysql_rc(rc, mysql);
+
+ if (mysql_session_track_get_first(mysql, SESSION_TRACK_STATE_CHANGE, &data, &len))
+ {
+ diag("session_track_get_first failed");
+ return FAIL;
+ }
+
+ FAIL_IF(len != 1, "Expected length 1");
+ return OK;
+}
+
+static int test_conc443(MYSQL *my __attribute__((unused)))
+{
+ my_bool x= 1;
+ unsigned long thread_id= 0;
+ char query[128];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc;
+
+ MYSQL *mysql= mysql_init(NULL);
+
+ SKIP_MAXSCALE;
+
+ mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=3");
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &x);
+
+ if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Connection failed. Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ }
+
+ thread_id= mysql_thread_id(mysql);
+
+ sprintf(query, "KILL %lu", thread_id);
+ rc= mysql_query(mysql, query);
+
+ sleep(3);
+
+ rc= mysql_ping(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT @a");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_thread_id(mysql) == thread_id, "Expected different thread id");
+
+ result= mysql_store_result(mysql);
+ if (!result)
+ return FAIL;
+ row= mysql_fetch_row(result);
+ FAIL_IF(strcmp(row[0],"3"), "Wrong result");
+
+ mysql_free_result(result);
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_default_auth(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_DEFAULT_AUTH, "mysql_clear_password");
+
+ if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Connection failed. Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_DEFAULT_AUTH, "caching_sha2_password");
+
+ if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Connection failed. Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+
+ }
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_gtid(MYSQL *mysql)
+{
+ int rc;
+ const char *data;
+ size_t len;
+
+ if (is_mariadb)
+ return SKIP;
+ // https://jira.mariadb.org/browse/XPT-182
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "SET @@session.session_track_state_change=1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SET @@session.session_track_gtids=OWN_GTID");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "BEGIN");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ if (!mysql_session_track_get_first(mysql, SESSION_TRACK_GTIDS, &data, &len))
+ do {
+ printf("# SESSION_TRACK_GTIDS: %*.*s\n", (int)len, (int)len, data);
+ } while (!mysql_session_track_get_next(mysql, SESSION_TRACK_GTIDS, &data, &len));
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ if (!mysql_session_track_get_first(mysql, SESSION_TRACK_GTIDS, &data, &len))
+ do {
+ printf("# SESSION_TRACK_GTIDS: %*.*s\n", (int)len, (int)len, data);
+ } while (!mysql_session_track_get_next(mysql, SESSION_TRACK_GTIDS, &data, &len));
+
+ rc= mysql_query(mysql, "COMMIT");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc490(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, NULL, port, socketname, CLIENT_CONNECT_WITH_DB))
+ {
+ diag("error: %s\n", mysql_error(mysql));
+ return FAIL;
+ }
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc544(MYSQL *mysql)
+{
+ int rc;
+ MYSQL *my= mysql_init(NULL);
+ char query[1024];
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!mysql_client_find_plugin(mysql, "client_ed25519", MYSQL_CLIENT_AUTHENTICATION_PLUGIN))
+ {
+ diag("client_ed25519 plugin not available");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "INSTALL SONAME 'auth_ed25519'");
+ if (rc)
+ {
+ diag("feature not supported, ed25519 plugin not available");
+ return SKIP;
+ }
+
+ rc= mysql_optionsv(my, MARIADB_OPT_RESTRICTED_AUTH, "client_ed25519");
+ check_mysql_rc(rc, mysql);
+
+ if (my_test_connect(my, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("error expected (restricted auth)");
+ return FAIL;
+ }
+ mysql_close(my);
+
+ if (mysql_get_server_version(mysql) < 100400) {
+ sprintf(query, "CREATE OR REPLACE USER 'ede'@'%s' IDENTIFIED VIA ed25519 USING '6aW9C7ENlasUfymtfMvMZZtnkCVlcb1ssxOLJ0kj/AA'", this_host);
+ } else {
+ sprintf(query, "CREATE OR REPLACE USER 'ede'@'%s' IDENTIFIED VIA ed25519 USING PASSWORD('MySup8%%rPassw@ord')", this_host);
+ }
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "GRANT ALL ON %s.* TO 'ede'@'%s'", schema, this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ my= mysql_init(NULL);
+ if (plugindir)
+ mysql_optionsv(my, MYSQL_PLUGIN_DIR, plugindir);
+ mysql_optionsv(my, MARIADB_OPT_RESTRICTED_AUTH, "client_ed25519, mysql_native_password");
+ if (!my_test_connect(my, hostname, "ede", "MySup8%rPassw@ord", schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(my));
+ return FAIL;
+ }
+ mysql_close(my);
+
+ sprintf(query, "DROP USER 'ede'@'%s'", this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ sprintf(query, "UNINSTALL SONAME 'auth_ed25519'");
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conn_str(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ char conn_str[1024];
+ int rc=OK;
+
+ snprintf(conn_str, sizeof(conn_str)-1, "host=%s;user=%s;password={%s};port=%d;socket=%s",
+ hostname ? hostname : "localhost", username ? username : "",
+ password ? password : "",
+ port, socketname ? socketname : "");
+
+ /* SkySQL requires secure connection */
+ if (IS_SKYSQL(hostname))
+ {
+ strcat(conn_str, ";ssl_enforce=1");
+ }
+
+ if (mariadb_connect(mysql, conn_str))
+ {
+ diag("host: %s", mysql->host);
+ diag("user: %s", mysql->user);
+ diag("cipher: %s", mysql_get_ssl_cipher(mysql));
+ } else
+ {
+ diag("error: %s", mysql_error(mysql));
+ rc= FAIL;
+ }
+ mysql_close(mysql);
+ return rc;
+}
+
+static int test_conn_str_1(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql;
+ FILE *fp;
+ int rc;
+ char conn_str[1024];
+ mysql= mysql_init(NULL);
+
+ if (!(fp= fopen("./conc274.cnf", "w")))
+ return FAIL;
+
+ sprintf(conn_str, "connection=host=%s;user=%s;password=%s;port=%d;ssl_enforce=1;socket=%s",
+ hostname ? hostname : "localhost", username ? username : "",
+ password ? password : "", ssl_port, socketname ? socketname : "");
+
+ fprintf(fp, "[client]\n");
+ fprintf(fp, "%s\n", conn_str);
+
+ fclose(fp);
+
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./conc274.cnf");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
+ check_mysql_rc(rc, mysql);
+
+ if (!my_test_connect(mysql, NULL, NULL, NULL, NULL, 0, NULL, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ remove("./conc274.cnf");
+ return FAIL;
+ }
+ remove("./conc274.cnf");
+
+ if (!mysql_get_ssl_cipher(mysql))
+ {
+ diag("Error: No TLS connection");
+ return FAIL;
+ }
+ diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc365(MYSQL *my __attribute__((unused)))
+{
+ int rc= OK;
+ MYSQL *mysql= mysql_init(NULL);
+ char tmp[1024];
+
+ snprintf(tmp, sizeof(tmp) - 1,
+ "host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s",
+ hostname ? hostname : "localhost", username ? username : "", password ? password : "",
+ port, socketname ? socketname : "");
+
+ if (IS_SKYSQL(hostname))
+ strcat(tmp, ";ssl_enforce=1");
+
+ if (!mariadb_connect(mysql, tmp))
+ rc= FAIL;
+
+ mysql_close(mysql);
+
+ if (rc)
+ return rc;
+
+ mysql= mysql_init(NULL);
+ snprintf(tmp, sizeof(tmp) -1, "127.0.0.1:3300,%s:%d", hostname ? hostname : "localhost", port);
+ if (!my_test_connect(mysql, tmp, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ rc= FAIL;
+ }
+
+ mysql_close(mysql);
+
+ if (rc)
+ return rc;
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MARIADB_OPT_HOST, tmp);
+ if (!my_test_connect(mysql, NULL, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ rc= FAIL;
+ }
+
+ mysql_close(mysql);
+ return rc;
+}
+
+static int test_conc365_reconnect(MYSQL *my)
+{
+ int rc= OK;
+ MYSQL *mysql= mysql_init(NULL);
+ char tmp[1024];
+ my_bool reconnect= 1;
+ SKIP_MAXSCALE;
+
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+
+ if (IS_SKYSQL(hostname))
+ {
+ snprintf(tmp, sizeof(tmp) - 1,
+ "host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s;ssl_enforce=1",
+ hostname ? hostname : "localhost", username ? username : "", password ? password : "",
+ ssl_port, socketname ? socketname : "");
+ } else {
+ snprintf(tmp, sizeof(tmp) - 1,
+ "host=127.0.0.1:3300,%s;user=%s;password=%s;port=%d;socket=%s",
+ hostname ? hostname : "localhost", username ? username : "", password ? password : "",
+ port, socketname ? socketname : "");
+ }
+
+ if (!my_test_connect(mysql, tmp, username,
+ password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ rc= FAIL;
+ }
+
+ sprintf(tmp, "KILL %ld", mysql_thread_id(mysql));
+
+ rc= mysql_query(my, tmp);
+ check_mysql_rc(rc, my);
+
+ sleep(3);
+ rc= mysql_ping(mysql);
+ check_mysql_rc(rc, my);
+
+ mysql_close(mysql);
+ return rc;
+}
+
+struct st_callback {
+ char autocommit;
+ char database[64];
+ char charset[64];
+};
+
+void my_status_callback(void *ptr, enum enum_mariadb_status_info type, ...)
+{
+ va_list ap;
+ struct st_callback *data= (struct st_callback *)ptr;
+ va_start(ap, type);
+
+ switch(type) {
+ case STATUS_TYPE:
+ {
+ int status= va_arg(ap, int);
+ data->autocommit= status & SERVER_STATUS_AUTOCOMMIT;
+ }
+ break;
+ case SESSION_TRACK_TYPE:
+ {
+ enum enum_session_state_type track_type= va_arg(ap, enum enum_session_state_type);
+ switch (track_type) {
+ case SESSION_TRACK_SCHEMA:
+ {
+ MARIADB_CONST_STRING *str= va_arg(ap, MARIADB_CONST_STRING *);
+ strncpy(data->database, str->str, str->length);
+ }
+ break;
+ case SESSION_TRACK_SYSTEM_VARIABLES:
+ {
+ MARIADB_CONST_STRING *key= va_arg(ap, MARIADB_CONST_STRING *);
+ MARIADB_CONST_STRING *val= va_arg(ap, MARIADB_CONST_STRING *);
+
+ if (!strncmp(key->str, "character_set_client", key->length))
+ {
+ strncpy(data->charset, val->str, val->length);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ default:
+ break;
+ }
+ va_end(ap);
+}
+
+static int test_status_callback(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ char tmp[64];
+ int rc;
+ struct st_callback data= {0,"", ""};
+
+ rc= mysql_optionsv(mysql, MARIADB_OPT_STATUS_CALLBACK, my_status_callback, &data);
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, NULL, port, socketname, 0))
+ {
+ diag("error1: %s", mysql_error(mysql));
+ return FAIL;
+ }
+
+ rc= mysql_autocommit(mysql, 0);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_autocommit(mysql, 1);
+ check_mysql_rc(rc, mysql);
+
+ if (!data.autocommit)
+ {
+ diag("autocommit not set");
+ return FAIL;
+ }
+ diag("-------------------------");
+
+ sprintf(tmp, "USE %s", schema);
+ rc= mysql_query(mysql, tmp);
+ check_mysql_rc(rc, mysql);
+
+ if (strcmp(data.database, schema))
+ {
+ diag("Expected database: %s instead of %s", schema, data.database);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "SET NAMES latin1");
+ check_mysql_rc(rc, mysql);
+
+ if (strcmp(data.charset, "latin1"))
+ {
+ diag("Expected charset latin1 instead of %s", data.charset);
+ return FAIL;
+ }
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc632(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ int rc;
+
+ if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
+ {
+ diag("Connection failed. Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "DROP PROCEDURE conc632");
+
+ rc= mysql_query(mysql, "CREATE PROCEDURE conc632() "
+ "BEGIN "
+ " SELECT 1;"
+ " SELECT 2;"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CALL conc632()");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_reset_connection(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_ping(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE conc632");
+ check_mysql_rc(rc, mysql);
+
+ mysql_close(mysql);
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc632", test_conc632, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_status_callback", test_status_callback, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc365", test_conc365, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc365_reconnect", test_conc365_reconnect, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conn_str", test_conn_str, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conn_str_1", test_conn_str_1, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc544", test_conc544, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc490", test_conc490, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_gtid", test_gtid, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc496", test_conc496, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_default_auth", test_default_auth, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc443", test_conc443, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc366", test_conc366, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc392", test_conc392, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc312", test_conc312, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc351", test_conc351, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc332", test_conc332, TEST_CONNECTION_NONE, 0, NULL, NULL},
+#ifndef WIN32
+ {"test_conc327", test_conc327, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc317", test_conc317, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+#endif
+ {"test_conc315", test_conc315, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_expired_pw", test_expired_pw, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc276", test_conc276, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_mdev13100", test_mdev13100, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_auth256", test_auth256, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_reset", test_reset, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_unix_socket_close", test_unix_socket_close, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_sess_track_db", test_sess_track_db, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_get_options", test_get_options, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_wrong_bind_address", test_wrong_bind_address, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bind_address", test_bind_address, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc118", test_conc118, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc66", test_conc66, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug20023", test_bug20023, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_bug31669", test_bug31669, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_bug33831", test_bug33831, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_change_user", test_change_user, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_opt_reconnect", test_opt_reconnect, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_compress", test_compress, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_reconnect", test_reconnect, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc21", test_conc21, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc26", test_conc26, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_connection_timeout", test_connection_timeout, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_connection_timeout2", test_connection_timeout2, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_connection_timeout3", test_connection_timeout3, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/cursor.c b/libmariadb/unittest/libmariadb/cursor.c
new file mode 100644
index 00000000..9cdda475
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/cursor.c
@@ -0,0 +1,1852 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+
+/* helper functions */
+enum { MAX_COLUMN_LENGTH= 255 };
+
+typedef struct st_stmt_fetch
+{
+ const char *query;
+ unsigned stmt_no;
+ MYSQL_STMT *handle;
+ my_bool is_open;
+ MYSQL_BIND *bind_array;
+ char **out_data;
+ unsigned long *out_data_length;
+ unsigned column_count;
+ unsigned row_count;
+} Stmt_fetch;
+
+MYSQL_STMT *open_cursor(MYSQL *mysql, const char *query)
+{
+ int rc;
+ const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
+
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ if (rc) {
+ diag("Error: %s", mysql_stmt_error(stmt));
+ return NULL;
+ }
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ return stmt;
+}
+
+/*
+ Create statement handle, prepare it with statement, execute and allocate
+ fetch buffers.
+*/
+
+int stmt_fetch_init(MYSQL *mysql, Stmt_fetch *fetch, unsigned int stmt_no_arg,
+ const char *query_arg)
+{
+ unsigned long type= CURSOR_TYPE_READ_ONLY;
+ int rc;
+ unsigned int i;
+ MYSQL_RES *metadata;
+
+ /* Save query and statement number for error messages */
+ fetch->stmt_no= stmt_no_arg;
+ fetch->query= query_arg;
+
+ fetch->handle= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(fetch->handle, SL(fetch->query));
+ FAIL_IF(rc, mysql_stmt_error(fetch->handle));
+
+ /*
+ The attribute is sent to server on execute and asks to open read-only
+ for result set
+ */
+ mysql_stmt_attr_set(fetch->handle, STMT_ATTR_CURSOR_TYPE,
+ (const void*) &type);
+
+ rc= mysql_stmt_execute(fetch->handle);
+ FAIL_IF(rc, mysql_stmt_error(fetch->handle));
+
+ /* Find out total number of columns in result set */
+ metadata= mysql_stmt_result_metadata(fetch->handle);
+ fetch->column_count= mysql_num_fields(metadata);
+ mysql_free_result(metadata);
+
+ /*
+ Now allocate bind handles and buffers for output data:
+ calloc memory to reduce number of MYSQL_BIND members we need to
+ set up.
+ */
+
+ fetch->bind_array= (MYSQL_BIND *) calloc(1, sizeof(MYSQL_BIND) *
+ fetch->column_count);
+ fetch->out_data= (char**) calloc(1, sizeof(char*) * fetch->column_count);
+ fetch->out_data_length= (ulong*) calloc(1, sizeof(ulong) *
+ fetch->column_count);
+ for (i= 0; i < fetch->column_count; ++i)
+ {
+ fetch->out_data[i]= (char*) calloc(1, MAX_COLUMN_LENGTH);
+ fetch->bind_array[i].buffer_type= MYSQL_TYPE_STRING;
+ fetch->bind_array[i].buffer= fetch->out_data[i];
+ fetch->bind_array[i].buffer_length= MAX_COLUMN_LENGTH;
+ fetch->bind_array[i].length= fetch->out_data_length + i;
+ }
+
+ mysql_stmt_bind_result(fetch->handle, fetch->bind_array);
+
+ fetch->row_count= 0;
+ fetch->is_open= TRUE;
+
+ /* Ready for reading rows */
+ return OK;
+}
+
+
+int fill_tables(MYSQL *mysql, const char **query_list, unsigned query_count)
+{
+ int rc;
+ const char **query;
+ for (query= query_list; query < query_list + query_count;
+ ++query)
+ {
+ rc= mysql_query(mysql, *query);
+ check_mysql_rc(rc, mysql);
+ }
+ return OK;
+}
+
+int stmt_fetch_fetch_row(Stmt_fetch *fetch)
+{
+ int rc;
+ unsigned i;
+
+ if ((rc= mysql_stmt_fetch(fetch->handle)) == 0)
+ {
+ ++fetch->row_count;
+ for (i= 0; i < fetch->column_count; ++i)
+ {
+ fetch->out_data[i][fetch->out_data_length[i]]= '\0';
+ }
+ }
+ else
+ fetch->is_open= FALSE;
+
+ return rc;
+}
+
+void stmt_fetch_close(Stmt_fetch *fetch)
+{
+ unsigned i;
+
+ for (i= 0; i < fetch->column_count; ++i)
+ free(fetch->out_data[i]);
+ free(fetch->out_data);
+ free(fetch->out_data_length);
+ free(fetch->bind_array);
+ mysql_stmt_close(fetch->handle);
+}
+
+
+
+enum fetch_type { USE_ROW_BY_ROW_FETCH= 0, USE_STORE_RESULT= 1 };
+
+int fetch_n(MYSQL *mysql, const char **query_list, unsigned query_count,
+ enum fetch_type fetch_type)
+{
+ unsigned open_statements= query_count;
+ int rc, error_count= 0;
+ Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) *
+ query_count);
+ Stmt_fetch *fetch;
+
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ if (stmt_fetch_init(mysql, fetch, (unsigned int)(fetch - fetch_array),
+ query_list[fetch - fetch_array]))
+ return FAIL;
+ }
+
+ if (fetch_type == USE_STORE_RESULT)
+ {
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ rc= mysql_stmt_store_result(fetch->handle);
+ FAIL_IF(rc, mysql_stmt_error(fetch->handle));
+ }
+ }
+
+ while (open_statements)
+ {
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ {
+ if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch)))
+ {
+ open_statements--;
+ /*
+ We try to fetch from the rest of the statements in case of
+ error
+ */
+ if (rc != MYSQL_NO_DATA)
+ error_count++;
+ }
+ }
+ }
+ for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+ stmt_fetch_close(fetch);
+ free(fetch_array);
+
+ return (error_count) ? FAIL:OK;
+}
+
+static int test_basic_cursors(MYSQL *mysql)
+{
+ const char *basic_tables[]=
+ {
+ "DROP TABLE IF EXISTS t1, t2",
+
+ "CREATE TABLE t1 "
+ "(id INTEGER NOT NULL PRIMARY KEY, "
+ " name VARCHAR(20) NOT NULL)",
+
+ "INSERT INTO t1 (id, name) VALUES "
+ " (2, 'Ja'), (3, 'Ede'), "
+ " (4, 'Haag'), (5, 'Kabul'), "
+ " (6, 'Almere'), (7, 'Utrecht'), "
+ " (8, 'Qandahar'), (9, 'Amsterdam'), "
+ " (10, 'Amersfoort'), (11, 'Constantine')",
+
+ "CREATE TABLE t2 "
+ "(id INTEGER NOT NULL PRIMARY KEY, "
+ " name VARCHAR(20) NOT NULL)",
+
+ "INSERT INTO t2 (id, name) VALUES "
+ " (4, 'Guam'), (5, 'Aruba'), "
+ " (6, 'Angola'), (7, 'Albania'), "
+ " (8, 'Anguilla'), (9, 'Argentina'), "
+ " (10, 'Azerbaijan'), (11, 'Afghanistan'), "
+ " (12, 'Burkina Faso'), (13, 'Faroe Islands')"
+ };
+
+ const char *queries[]=
+ {
+ "SELECT * FROM t1",
+ "SELECT * FROM t2"
+ };
+
+
+ FAIL_IF(fill_tables(mysql, basic_tables, sizeof(basic_tables)/sizeof(*basic_tables)), "fill_tables failed");
+
+ FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH), "fetch_n failed");
+ FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT), "fetch_n failed");
+ return OK;
+}
+
+
+static int test_cursors_with_union(MYSQL *mysql)
+{
+ const char *queries[]=
+ {
+ "SELECT t1.name FROM t1 UNION SELECT t2.name FROM t2",
+ "SELECT t1.id FROM t1 WHERE t1.id < 5"
+ };
+ FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH), "fetch_n failed");
+ FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT), "fetch_n failed");
+
+ return OK;
+}
+
+
+static int test_cursors_with_procedure(MYSQL *mysql)
+{
+ const char *queries[]=
+ {
+ "SELECT * FROM t1 procedure analyse()"
+ };
+ SKIP_MYSQL(mysql);
+ FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH), "fetch_n failed");
+ FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT), "fetch_n failed");
+
+ return OK;
+}
+
+/*
+ Bug#21206: memory corruption when too many cursors are opened at once
+
+ Memory corruption happens when more than 1024 cursors are open
+ simultaneously.
+*/
+static int test_bug21206(MYSQL *mysql)
+{
+ int retcode= OK;
+
+ const size_t cursor_count= 1025;
+
+ const char *create_table[]=
+ {
+ "DROP TABLE IF EXISTS t1",
+ "CREATE TABLE t1 (i INT)",
+ "INSERT INTO t1 VALUES (1), (2), (3)"
+ };
+ const char *query= "SELECT * FROM t1";
+
+ Stmt_fetch *fetch_array=
+ (Stmt_fetch*) calloc(cursor_count, sizeof(Stmt_fetch));
+
+ Stmt_fetch *fetch;
+
+ FAIL_IF(fill_tables(mysql, create_table, sizeof(create_table) / sizeof(*create_table)), "fill_tables failed");
+
+ for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
+ {
+ if ((retcode= stmt_fetch_init(mysql, fetch, (unsigned int)(fetch - fetch_array), query)))
+ break;
+ }
+
+ for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
+ stmt_fetch_close(fetch);
+
+ free(fetch_array);
+
+ return retcode;
+}
+
+static int test_bug10729(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ char a[21];
+ int rc;
+ const char *stmt_text;
+ int i= 0;
+ const char *name_array[3]= { "aaa", "bbb", "ccc" };
+ ulong type;
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "name VARCHAR(20) NOT NULL)");
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_stmt_rc(rc, stmt);
+ stmt_text= "select name from t1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void*) a;
+ my_bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ for (i= 0; i < 3; i++)
+ {
+ int row_no= 0;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ {
+ FAIL_UNLESS(strcmp(a, name_array[row_no]) == 0, "a != name_array[row_no]");
+ ++row_no;
+ }
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ }
+ rc= mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#10736: cursors and subqueries, memroot management */
+
+static int test_bug10736(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ char a[21];
+ int rc;
+ const char *stmt_text;
+ int i= 0;
+ ulong type;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "name VARCHAR(20) NOT NULL)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_stmt_rc(rc, stmt);
+ stmt_text= "select name from t1 where name=(select name from t1 where id=2)";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void*) a;
+ my_bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ }
+ rc= mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#10794: cursors, packets out of order */
+
+static int test_bug10794(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt, *stmt1;
+ MYSQL_BIND my_bind[2];
+ char a[21];
+ int id_val;
+ ulong a_len;
+ int rc;
+ const char *stmt_text;
+ int i= 0;
+ ulong type;
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "name varchar(20) not null)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "insert into t1 (id, name) values (?, ?)";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void*) &id_val;
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void*) a;
+ my_bind[1].length= &a_len;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ for (i= 0; i < 42; i++)
+ {
+ id_val= (i+1)*10;
+ sprintf(a, "a%d", i);
+ a_len= (unsigned long)strlen(a); /* safety against broken sprintf */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ stmt_text= "select name from t1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ stmt1= mysql_stmt_init(mysql);
+ mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void*) a;
+ my_bind[0].buffer_length= sizeof(a);
+ my_bind[0].length= &a_len;
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ /* Don't optimize: an attribute of the original test case */
+ mysql_stmt_free_result(stmt);
+ mysql_stmt_reset(stmt);
+ stmt_text= "select name from t1 where id=10";
+ rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_bind_result(stmt1, my_bind);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+ while (1)
+ {
+ rc= mysql_stmt_fetch(stmt1);
+ if (rc == MYSQL_NO_DATA)
+ {
+ break;
+ }
+ check_stmt_rc(rc, stmt1);
+ }
+ mysql_stmt_close(stmt);
+ mysql_stmt_close(stmt1);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#10760: cursors, crash in a fetch after rollback. */
+
+static int test_bug10760(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ int rc;
+ const char *stmt_text;
+ char id_buf[20];
+ ulong id_len;
+ int i= 0;
+ ulong type;
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ /* create tables */
+ rc= mysql_query(mysql, "create table t1 (id integer not null primary key)"
+ " engine=MyISAM");
+ check_mysql_rc(rc, mysql);;
+ for (; i < 42; ++i)
+ {
+ char buf[100];
+ sprintf(buf, "insert into t1 (id) values (%d)", i+1);
+ rc= mysql_query(mysql, buf);
+ check_mysql_rc(rc, mysql);;
+ }
+ mysql_autocommit(mysql, FALSE);
+ /* create statement */
+ stmt= mysql_stmt_init(mysql);
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ /*
+ 1: check that a deadlock within the same connection
+ is resolved and an error is returned. The deadlock is modelled
+ as follows:
+ con1: open cursor for select * from t1;
+ con1: insert into t1 (id) values (1)
+ */
+ stmt_text= "select id from t1 order by 1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);;
+ rc= mysql_query(mysql, "update t1 set id=id+100");
+ /*
+ If cursors are not materialized, the update will return an error;
+ we mainly test that it won't deadlock.
+ */
+ /* FAIL_IF(!rc, "Error expected"); */
+ /*
+ 2: check that MyISAM tables used in cursors survive
+ COMMIT/ROLLBACK.
+ */
+ rc= mysql_rollback(mysql); /* should not close the cursor */
+ check_mysql_rc(rc, mysql);;
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);;
+
+ /*
+ 3: check that cursors to InnoDB tables are closed (for now) by
+ COMMIT/ROLLBACK.
+ */
+ if (check_variable(mysql, "@@have_innodb", "YES"))
+ {
+ stmt_text= "select id from t1 order by 1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);;
+
+ rc= mysql_query(mysql, "alter table t1 engine=InnoDB");
+ check_mysql_rc(rc, mysql);;
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void*) id_buf;
+ my_bind[0].buffer_length= sizeof(id_buf);
+ my_bind[0].length= &id_len;
+ check_stmt_rc(rc, stmt);;
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_execute(stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+ rc= mysql_rollback(mysql); /* should close the cursor */
+ }
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_autocommit(mysql, TRUE); /* restore default */
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#11172: cursors, crash on a fetch from a datetime column */
+
+static int test_bug11172(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind_in[1], bind_out[2];
+ MYSQL_TIME hired;
+ int rc;
+ const char *stmt_text;
+ int i= 0, id;
+ ulong type;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (id integer not null primary key,"
+ "hired date not null)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "insert into t1 (id, hired) values (1, '1933-08-24'), "
+ "(2, '1965-01-01'), (3, '1949-08-17'), (4, '1945-07-07'), "
+ "(5, '1941-05-15'), (6, '1978-09-15'), (7, '1936-03-28')");
+ check_mysql_rc(rc, mysql);
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ stmt_text= "SELECT id, hired FROM t1 WHERE hired=?";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ memset(bind_in, '\0', sizeof(bind_in));
+ memset(bind_out, '\0', sizeof(bind_out));
+ memset(&hired, '\0', sizeof(hired));
+ hired.year= 1965;
+ hired.month= 1;
+ hired.day= 1;
+ bind_in[0].buffer_type= MYSQL_TYPE_DATE;
+ bind_in[0].buffer= (void*) &hired;
+ bind_in[0].buffer_length= sizeof(hired);
+ bind_out[0].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[0].buffer= (void*) &id;
+ bind_out[1]= bind_in[0];
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_bind_param(stmt, bind_in);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_result(stmt, bind_out);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ if (!mysql_stmt_free_result(stmt))
+ mysql_stmt_reset(stmt);
+ }
+ mysql_stmt_close(stmt);
+ mysql_rollback(mysql);
+ mysql_rollback(mysql);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#11656: cursors, crash on a fetch from a query with distinct. */
+
+static int test_bug11656(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ int rc;
+ const char *stmt_text;
+ char buf[2][20];
+ int i= 0;
+ ulong type;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 ("
+ "server varchar(40) not null, "
+ "test_kind varchar(1) not null, "
+ "test_id varchar(30) not null , "
+ "primary key (server,test_kind,test_id))");
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "select distinct test_kind, test_id from t1 "
+ "where server in (?, ?)";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ strcpy(buf[0], "pcint502_MY2");
+ strcpy(buf[1], "*");
+ for (i=0; i < 2; i++)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[i].buffer= (uchar* *)&buf[i];
+ my_bind[i].buffer_length= (unsigned long)strlen(buf[i]);
+ }
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Cursors: opening a cursor to a complicated query with ORDER BY */
+
+static int test_bug11901(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ int rc;
+ char workdept[20];
+ ulong workdept_len;
+ uint32 empno;
+ const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
+ const char *stmt_text;
+
+
+ stmt_text= "drop table if exists t1, t2";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "create table t1 ("
+ " empno int(11) not null, firstname varchar(20) not null,"
+ " midinit varchar(20) not null, lastname varchar(20) not null,"
+ " workdept varchar(6) not null, salary double not null,"
+ " bonus float not null, primary key (empno), "
+ " unique key (workdept, empno) "
+ ") default charset=latin1 collate=latin1_bin";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "insert into t1 values "
+ "(10, 'CHRISTINE', 'I', 'HAAS', 'A00', 52750, 1000),"
+ "(20, 'MICHAEL', 'L', 'THOMPSON', 'B01', 41250, 800), "
+ "(30, 'SALLY', 'A', 'KWAN', 'C01', 38250, 800), "
+ "(50, 'JOHN', 'B', 'GEYER', 'E01', 40175, 800), "
+ "(60, 'IRVING', 'F', 'STERN', 'D11', 32250, 500), "
+ "(70, 'EVA', 'D', 'PULASKI', 'D21', 36170, 700), "
+ "(90, 'EILEEN', 'W', 'HENDERSON', 'E11', 29750, 600), "
+ "(100, 'THEODORE', 'Q', 'SPENSER', 'E21', 26150, 500), "
+ "(110, 'VINCENZO', 'G', 'LUCCHESSI', 'A00', 46500, 900), "
+ "(120, 'SEAN', '', 'O\\'CONNELL', 'A00', 29250, 600), "
+ "(130, 'DOLORES', 'M', 'QUINTANA', 'C01', 23800, 500), "
+ "(140, 'HEATHER', 'A', 'NICHOLLS', 'C01', 28420, 600), "
+ "(150, 'BRUCE', '', 'ADAMSON', 'D11', 25280, 500), "
+ "(160, 'ELIZABETH', 'R', 'PIANKA', 'D11', 22250, 400), "
+ "(170, 'MASATOSHI', 'J', 'YOSHIMURA', 'D11', 24680, 500), "
+ "(180, 'MARILYN', 'S', 'SCOUTTEN', 'D11', 21340, 500), "
+ "(190, 'JAMES', 'H', 'WALKER', 'D11', 20450, 400), "
+ "(200, 'DAVID', '', 'BROWN', 'D11', 27740, 600), "
+ "(210, 'WILLIAM', 'T', 'JONES', 'D11', 18270, 400), "
+ "(220, 'JENNIFER', 'K', 'LUTZ', 'D11', 29840, 600), "
+ "(230, 'JAMES', 'J', 'JEFFERSON', 'D21', 22180, 400), "
+ "(240, 'SALVATORE', 'M', 'MARINO', 'D21', 28760, 600), "
+ "(250, 'DANIEL', 'S', 'SMITH', 'D21', 19180, 400), "
+ "(260, 'SYBIL', 'P', 'JOHNSON', 'D21', 17250, 300), "
+ "(270, 'MARIA', 'L', 'PEREZ', 'D21', 27380, 500), "
+ "(280, 'ETHEL', 'R', 'SCHNEIDER', 'E11', 26250, 500), "
+ "(290, 'JOHN', 'R', 'PARKER', 'E11', 15340, 300), "
+ "(300, 'PHILIP', 'X', 'SMITH', 'E11', 17750, 400), "
+ "(310, 'MAUDE', 'F', 'SETRIGHT', 'E11', 15900, 300), "
+ "(320, 'RAMLAL', 'V', 'MEHTA', 'E21', 19950, 400), "
+ "(330, 'WING', '', 'LEE', 'E21', 25370, 500), "
+ "(340, 'JASON', 'R', 'GOUNOT', 'E21', 23840, 500)";
+
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "create table t2 ("
+ " deptno varchar(6) not null, deptname varchar(20) not null,"
+ " mgrno int(11) not null, location varchar(20) not null,"
+ " admrdept varchar(6) not null, refcntd int(11) not null,"
+ " refcntu int(11) not null, primary key (deptno)"
+ ") default charset=latin1 collate=latin1_bin";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "insert into t2 values "
+ "('A00', 'SPIFFY COMPUTER SERV', 10, '', 'A00', 0, 0), "
+ "('B01', 'PLANNING', 20, '', 'A00', 0, 0), "
+ "('C01', 'INFORMATION CENTER', 30, '', 'A00', 0, 0), "
+ "('D01', 'DEVELOPMENT CENTER', 0, '', 'A00', 0, 0),"
+ "('D11', 'MANUFACTURING SYSTEM', 60, '', 'D01', 0, 0), "
+ "('D21', 'ADMINISTRATION SYSTE', 70, '', 'D01', 0, 0), "
+ "('E01', 'SUPPORT SERVICES', 50, '', 'A00', 0, 0), "
+ "('E11', 'OPERATIONS', 90, '', 'E01', 0, 0), "
+ "('E21', 'SOFTWARE SUPPORT', 100,'', 'E01', 0, 0)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "select t1.empno, t1.workdept "
+ "from (t1 left join t2 on t2.deptno = t1.workdept) "
+ "where t2.deptno in "
+ " (select t2.deptno "
+ " from (t1 left join t2 on t2.deptno = t1.workdept) "
+ " where t1.empno = ?) "
+ "order by 1";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_stmt_rc(rc, stmt);
+
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= &empno;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ my_bind[1].buffer= (void*) workdept;
+ my_bind[1].buffer_length= sizeof(workdept);
+ my_bind[1].length= &workdept_len;
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ empno= 10;
+
+ /* ERROR: next statement causes a server crash */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#11904: mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY grouping wrong result */
+
+static int test_bug11904(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt1;
+ int rc;
+ const char *stmt_text;
+ const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
+ MYSQL_BIND my_bind[2];
+ int country_id=0;
+ char row_data[11]= {0};
+
+ /* create tables */
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug11904b");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE bug11904b (id int, name char(10), primary key(id, name))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO bug11904b VALUES (1, 'sofia'), (1,'plovdiv'),"
+ " (1,'varna'), (2,'LA'), (2,'new york'), (3,'heidelberg'),"
+ " (3,'berlin'), (3, 'frankfurt')");
+
+ check_mysql_rc(rc, mysql);
+ mysql_commit(mysql);
+ /* create statement */
+ stmt1= mysql_stmt_init(mysql);
+ mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ stmt_text= "SELECT id, MIN(name) FROM bug11904b GROUP BY id ORDER BY id";
+
+ rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
+ check_stmt_rc(rc, stmt1);
+
+ memset(my_bind, 0, sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer=& country_id;
+ my_bind[0].buffer_length= 0;
+ my_bind[0].length= 0;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer=& row_data;
+ my_bind[1].buffer_length= sizeof(row_data) - 1;
+ my_bind[1].length= 0;
+
+ rc= mysql_stmt_bind_result(stmt1, my_bind);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+ FAIL_UNLESS(country_id == 1, "country_id != 1");
+ FAIL_UNLESS(memcmp(row_data, "plovdiv", 7) == 0, "row_data != 'plovdiv'");
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+ FAIL_UNLESS(country_id == 2, "country_id != 2");
+ FAIL_UNLESS(memcmp(row_data, "LA", 2) == 0, "row_data != 'LA'");
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+ FAIL_UNLESS(country_id == 3, "country_id != 3");
+ FAIL_UNLESS(memcmp(row_data, "berlin", 6) == 0, "row_data != 'Berlin'");
+
+ rc= mysql_stmt_close(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_query(mysql, "drop table bug11904b");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/* Bug#12243: multiple cursors, crash in a fetch after commit. */
+
+static int test_bug12243(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt1, *stmt2;
+ int rc;
+ const char *stmt_text;
+ ulong type;
+
+ if (!check_variable(mysql, "@@have_innodb", "YES"))
+ {
+ diag("Skip -> Test required InnoDB");
+ return SKIP;
+ }
+
+ /* create tables */
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (a int) engine=InnoDB");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 (a) values (1), (2)");
+ check_mysql_rc(rc, mysql);
+ mysql_autocommit(mysql, FALSE);
+ /* create statement */
+ stmt1= mysql_stmt_init(mysql);
+ stmt2= mysql_stmt_init(mysql);
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ check_stmt_rc(rc, stmt1);
+
+ stmt_text= "select a from t1";
+
+ rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_prepare(stmt2, SL(stmt_text));
+ check_stmt_rc(rc, stmt2);
+ rc= mysql_stmt_execute(stmt2);
+ check_stmt_rc(rc, stmt2);
+ rc= mysql_stmt_fetch(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ rc= mysql_stmt_close(stmt1);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_stmt_fetch(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ mysql_stmt_close(stmt2);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ mysql_autocommit(mysql, TRUE); /* restore default */
+
+ return OK;
+}
+
+/* Bug#11909: wrong metadata if fetching from two cursors */
+
+static int test_bug11909(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt1, *stmt2;
+ MYSQL_BIND my_bind[7];
+ int rc;
+ char firstname[20], midinit[20], lastname[20], workdept[20];
+ ulong firstname_len, midinit_len, lastname_len, workdept_len;
+ uint32 empno;
+ double salary;
+ float bonus;
+ const char *stmt_text;
+ const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
+
+
+ stmt_text= "drop table if exists t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "create table t1 ("
+ " empno int(11) not null, firstname varchar(20) not null,"
+ " midinit varchar(20) not null, lastname varchar(20) not null,"
+ " workdept varchar(6) not null, salary double not null,"
+ " bonus float not null, primary key (empno)"
+ ") default charset=latin1 collate=latin1_bin";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "insert into t1 values "
+ "(10, 'CHRISTINE', 'I', 'HAAS', 'A00', 52750, 1000), "
+ "(20, 'MICHAEL', 'L', 'THOMPSON', 'B01', 41250, 800),"
+ "(30, 'SALLY', 'A', 'KWAN', 'C01', 38250, 800),"
+ "(50, 'JOHN', 'B', 'GEYER', 'E01', 40175, 800), "
+ "(60, 'IRVING', 'F', 'STERN', 'D11', 32250, 500)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ /* ****** Begin of trace ****** */
+
+ stmt_text= "SELECT empno, firstname, midinit, lastname,"
+ "workdept, salary, bonus FROM t1 ORDER BY empno";
+ stmt1= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt1, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
+ check_stmt_rc(rc, stmt1);
+ mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE,
+ (const void*) &type);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void*) &empno;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ my_bind[1].buffer= (void*) firstname;
+ my_bind[1].buffer_length= sizeof(firstname);
+ my_bind[1].length= &firstname_len;
+
+ my_bind[2].buffer_type= MYSQL_TYPE_VAR_STRING;
+ my_bind[2].buffer= (void*) midinit;
+ my_bind[2].buffer_length= sizeof(midinit);
+ my_bind[2].length= &midinit_len;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_VAR_STRING;
+ my_bind[3].buffer= (void*) lastname;
+ my_bind[3].buffer_length= sizeof(lastname);
+ my_bind[3].length= &lastname_len;
+
+ my_bind[4].buffer_type= MYSQL_TYPE_VAR_STRING;
+ my_bind[4].buffer= (void*) workdept;
+ my_bind[4].buffer_length= sizeof(workdept);
+ my_bind[4].length= &workdept_len;
+
+ my_bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[5].buffer= (void*) &salary;
+
+ my_bind[6].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[6].buffer= (void*) &bonus;
+ rc= mysql_stmt_bind_result(stmt1, my_bind);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+ FAIL_UNLESS(empno == 10, "empno != 10");
+ FAIL_UNLESS(strcmp(firstname, "CHRISTINE""") == 0, "firstname != 'Christine'");
+ FAIL_UNLESS(strcmp(midinit, "I""") == 0, "");
+ FAIL_UNLESS(strcmp(lastname, "HAAS""") == 0, "lastname != 'HAAS'");
+ FAIL_UNLESS(strcmp(workdept, "A00""") == 0, "workdept != 'A00'");
+ FAIL_UNLESS(salary == (double) 52750.0, "salary != 52750");
+ FAIL_UNLESS(bonus == (float) 1000.0, "bonus =! 1000");
+
+ stmt_text = "SELECT empno, firstname FROM t1";
+ stmt2= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt2, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt2, SL(stmt_text));
+ check_stmt_rc(rc, stmt2);
+ mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE,
+ (const void*) &type);
+ rc= mysql_stmt_bind_result(stmt2, my_bind);
+ check_stmt_rc(rc, stmt2);
+
+ rc= mysql_stmt_execute(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ rc= mysql_stmt_fetch(stmt2);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+
+ FAIL_UNLESS(empno == 10, "empno != 10");
+ FAIL_UNLESS(strcmp(firstname, "CHRISTINE""") == 0, "firstname != 'Christine'");
+
+ rc= mysql_stmt_reset(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ /* ERROR: next statement should return 0 */
+
+ rc= mysql_stmt_fetch(stmt1);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+
+ mysql_stmt_close(stmt1);
+ mysql_stmt_close(stmt2);
+ rc= mysql_rollback(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#13488: wrong column metadata when fetching from cursor */
+
+static int test_bug13488(MYSQL *mysql)
+{
+ MYSQL_BIND my_bind[3];
+ MYSQL_STMT *stmt1;
+ int rc, f1, f2, f3, i;
+ const ulong type= CURSOR_TYPE_READ_ONLY;
+ const char *query= "select f1, f2, f3 from t1 left join t2 on f1=f2 where f1=1";
+
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (f1 int not null primary key)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t2 (f2 int not null primary key, "
+ "f3 int not null)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values (1), (2)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t2 values (1,2), (2,4)");
+ check_mysql_rc(rc, mysql);
+
+ memset(my_bind, 0, sizeof(my_bind));
+ for (i= 0; i < 3; i++)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].buffer_length= 4;
+ my_bind[i].length= 0;
+ }
+ my_bind[0].buffer=&f1;
+ my_bind[1].buffer=&f2;
+ my_bind[2].buffer=&f3;
+
+ stmt1= mysql_stmt_init(mysql);
+ rc= mysql_stmt_attr_set(stmt1,STMT_ATTR_CURSOR_TYPE, (const void *)&type);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_prepare(stmt1, SL(query));
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_bind_result(stmt1, my_bind);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_free_result(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_reset(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_close(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ FAIL_UNLESS(f1 == 1, "f1 != 1");
+ FAIL_UNLESS(f2 == 1, "f2 != 1");
+ FAIL_UNLESS(f3 == 2, "f3 != 2");
+ rc= mysql_query(mysql, "drop table t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ Bug#13524: warnings of a previous command are not reset when fetching
+ from a cursor.
+*/
+
+static int test_bug13524(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ unsigned int warning_count;
+ const ulong type= CURSOR_TYPE_READ_ONLY;
+ const char *query= "select * from t1";
+
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (a int not null primary key)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ warning_count= mysql_warning_count(mysql);
+ FAIL_UNLESS(warning_count == 0, "warning_count != 0");
+
+ /* Check that DROP TABLE produced a warning (no such table) */
+ rc= mysql_query(mysql, "drop table if exists t2");
+ check_mysql_rc(rc, mysql);
+ warning_count= mysql_warning_count(mysql);
+ FAIL_UNLESS(warning_count == 1, "warning_count != 1");
+
+ /*
+ Check that fetch from a cursor cleared the warning from the previous
+ command.
+ */
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ warning_count= mysql_warning_count(mysql);
+ FAIL_UNLESS(warning_count == 0, "warning_count != 0");
+
+ /* Cleanup */
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ Bug#14845 "mysql_stmt_fetch returns MYSQL_NO_DATA when COUNT(*) is 0"
+*/
+
+static int test_bug14845(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const ulong type= CURSOR_TYPE_READ_ONLY;
+ const char *query= "select count(*) from t1 where 1 = 0";
+
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (id int(11) default null, "
+ "name varchar(20) default null)"
+ "engine=MyISAM DEFAULT CHARSET=utf8");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values (1,'abc'),(2,'def')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 0, "");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "");
+
+ /* Cleanup */
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ Bug#14210 "Simple query with > operator on large table gives server
+ crash"
+*/
+
+static int test_bug14210(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *stmt_text;
+ ulong type;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ /*
+ To trigger the problem the table must be InnoDB, although the problem
+ itself is not InnoDB related. In case the table is MyISAM this test
+ is harmless.
+ */
+ rc= mysql_query(mysql, "create table t1 (a varchar(255)) engine=InnoDB");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 (a) values (repeat('a', 256))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "set @@session.max_heap_table_size=16384");
+
+ /* Create a big enough table (more than max_heap_table_size) */
+ for (i= 0; i < 8; i++)
+ {
+ rc= mysql_query(mysql, "insert into t1 (a) select a from t1");
+ check_mysql_rc(rc, mysql);
+ }
+ /* create statement */
+ stmt= mysql_stmt_init(mysql);
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+
+ stmt_text= "select a from t1";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ while ((rc= mysql_stmt_fetch(stmt)) == 0);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ rc= mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "set @@session.max_heap_table_size=default");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ Bug#24179 "select b into $var" fails with --cursor_protocol"
+ The failure is correct, check that the returned message is meaningful.
+*/
+
+static int test_bug24179(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+
+ // works with xpand
+ SKIP_XPAND;
+
+ stmt= open_cursor(mysql, "select 1 into @a");
+ rc= mysql_stmt_execute(stmt);
+ FAIL_UNLESS(rc, "Error expected");
+ FAIL_UNLESS(mysql_stmt_errno(stmt) == 1323, "stmt_errno != 1323");
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+/**
+ Bug#32265 Server returns different metadata if prepared statement is used
+*/
+
+static int test_bug32265(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_FIELD *field;
+ MYSQL_RES *metadata;
+
+ if (mysql_get_server_version(mysql) < 50100) {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1");
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a INTEGER)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT * FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ stmt= open_cursor(mysql, "SELECT * FROM t1");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ metadata= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_field(metadata);
+ FAIL_UNLESS(field, "couldn't fetch field");
+ FAIL_UNLESS(strcmp(field->table, "t1") == 0, "table != t1");
+ FAIL_UNLESS(strcmp(field->org_table, "t1") == 0, "org_table != t1");
+ FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
+ mysql_free_result(metadata);
+ mysql_stmt_close(stmt);
+
+ stmt= open_cursor(mysql, "SELECT a '' FROM t1 ``");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ metadata= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_field(metadata);
+ FAIL_UNLESS(strcmp(field->table, "") == 0, "field != ''");
+ FAIL_UNLESS(strcmp(field->org_table, "t1") == 0, "org_table != t1");
+ FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
+ mysql_free_result(metadata);
+ mysql_stmt_close(stmt);
+
+ stmt= open_cursor(mysql, "SELECT a '' FROM t1 ``");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ metadata= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_field(metadata);
+ FAIL_UNLESS(strcmp(field->table, "") == 0, "table != ''");
+ FAIL_UNLESS(strcmp(field->org_table, "t1") == 0, "org_table != t1");
+ FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
+ mysql_free_result(metadata);
+ mysql_stmt_close(stmt);
+
+ stmt= open_cursor(mysql, "SELECT * FROM v1");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ metadata= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_field(metadata);
+ FAIL_UNLESS(strcmp(field->table, "v1") == 0, "table != v1");
+ FAIL_UNLESS(strcmp(field->org_table, "v1") == 0, "org_table != v1");
+ FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
+ mysql_free_result(metadata);
+ mysql_stmt_close(stmt);
+
+ stmt= open_cursor(mysql, "SELECT * FROM v1 /* SIC */ GROUP BY 1");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ metadata= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_field(metadata);
+ FAIL_UNLESS(strcmp(field->table, "v1") == 0, "table != v1");
+ FAIL_UNLESS(strcmp(field->org_table, "v1") == 0, "org_table != v1");
+ FAIL_UNLESS(strcmp(field->db, schema) == 0, "schema != db");
+ mysql_free_result(metadata);
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/**
+ Bug#38486 Crash when using cursor protocol
+*/
+
+static int test_bug38486(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ unsigned long type= CURSOR_TYPE_READ_ONLY;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t10");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t10 (a INT)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
+ check_stmt_rc(rc, stmt);
+ stmt_text= "INSERT INTO t10 VALUES (1)";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t10");
+ check_mysql_rc(rc, mysql);
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_bug8880(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt_list[2], **stmt;
+ MYSQL_STMT **stmt_list_end= (MYSQL_STMT**) stmt_list + 2;
+ int rc;
+
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values (1,1)");
+ check_mysql_rc(rc, mysql);
+ /*
+ when inserting 2 rows everything works well
+ mysql_query(mysql, "INSERT INTO t1 VALUES (1,1),(2,2)");
+ */
+ for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
+ *stmt= open_cursor(mysql, "select a from t1");
+ for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
+ {
+ rc= mysql_stmt_execute(*stmt);
+ check_stmt_rc(rc, *stmt);
+ }
+ for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
+ mysql_stmt_close(*stmt);
+ return OK;
+}
+
+static int test_bug9159(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text= "select a, b from t1";
+ const unsigned long type= CURSOR_TYPE_READ_ONLY;
+
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
+ rc= mysql_query(mysql, "insert into t1 values (1,1)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ mysql_stmt_prepare(stmt, SL(stmt_text));
+ mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void *)&type);
+
+ mysql_stmt_execute(stmt);
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ We can't have more than one cursor open for a prepared statement.
+ Test re-executions of a PS with cursor; mysql_stmt_reset must close
+ the cursor attached to the statement, if there is one.
+*/
+
+static int test_bug9478(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ char a[6];
+ ulong a_len;
+ int rc, i;
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key, "
+ " name varchar(20) not null)");
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ " (1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= open_cursor(mysql, "select name from t1 where id=2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (char*) a;
+ my_bind[0].buffer_length= sizeof(a);
+ my_bind[0].length= &a_len;
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ for (i= 0; i < 5; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /*
+ The query above is a one-row result set. Therefore, there is no
+ cursor associated with it, as the server won't bother with opening
+ a cursor for a one-row result set. The first row was read from the
+ server in the fetch above. But there is eof packet pending in the
+ network. mysql_stmt_execute will flush the packet and successfully
+ execute the statement.
+ */
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ {
+ char buff[8];
+ /* Fill in the fetch packet */
+ int4store(buff, stmt->stmt_id);
+ buff[4]= 1; /* prefetch rows */
+/* rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
+ (uchar*) buff,
+ sizeof(buff), 0,0,1,NULL) ||
+ (*mysql->methods->read_query_result)(mysql)); */
+ FAIL_UNLESS(rc, "error expected");
+ }
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+
+ /* mariadb client supports GEOMETRY, so no error will
+ be returned
+ FAIL_UNLESS(rc && mysql_stmt_errno(stmt), "Error expected");
+ */
+ }
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* Test the case with a server side cursor */
+ stmt= open_cursor(mysql, "select name from t1");
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ for (i= 0; i < 5; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ while (! (rc= mysql_stmt_fetch(stmt)));
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc && mysql_stmt_errno(stmt), "Error expected");
+ }
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Crash when opening a cursor to a query with DISTINCT and no key */
+
+static int test_bug9520(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ char a[6];
+ ulong a_len;
+ int rc, row_count= 0;
+
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (a char(5), b char(5), c char(5),"
+ " primary key (a, b, c))");
+ rc= mysql_query(mysql, "insert into t1 values ('x', 'y', 'z'), "
+ " ('a', 'b', 'c'), ('k', 'l', 'm')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= open_cursor(mysql, "select distinct b from t1");
+
+ /*
+ Not crashes with:
+ stmt= open_cursor(mysql, "select distinct a from t1");
+ */
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (char*) a;
+ my_bind[0].buffer_length= sizeof(a);
+ my_bind[0].length= &a_len;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ while (!(rc= mysql_stmt_fetch(stmt)))
+ row_count++;
+
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ FAIL_UNLESS(row_count == 3, "row_count != 3");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ Error message is returned for unsupported features.
+ Test also cursors with non-default PREFETCH_ROWS
+*/
+
+static int test_bug9643(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ int32 a;
+ int rc;
+ const char *stmt_text;
+ int num_rows= 0;
+ ulong type;
+ ulong prefetch_rows= 5;
+
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key)");
+ rc= mysql_query(mysql, "insert into t1 (id) values "
+ " (1), (2), (3), (4), (5), (6), (7), (8), (9)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ /* Not implemented in 5.0 */
+ type= (ulong) CURSOR_TYPE_SCROLLABLE;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ FAIL_UNLESS(rc, "Error expected");
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS,
+ (void*) &prefetch_rows);
+ check_stmt_rc(rc, stmt);
+ stmt_text= "select * from t1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void*) &a;
+ my_bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ while ((rc= mysql_stmt_fetch(stmt)) == 0)
+ ++num_rows;
+ FAIL_UNLESS(num_rows == 9, "num_rows != 9");
+
+ rc= mysql_stmt_close(stmt);
+ FAIL_UNLESS(rc == 0, "");
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+
+struct my_tests_st my_tests[] = {
+ {"test_basic_cursors", test_basic_cursors, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_cursors_with_union", test_cursors_with_union, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_cursors_with_procedure", test_cursors_with_procedure, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug21206", test_bug21206, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug10729", test_bug10729, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug10736", test_bug10736, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug10794", test_bug10794, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug10760", test_bug10760, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11172", test_bug11172, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11656", test_bug11656, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11901", test_bug11901, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11904", test_bug11904, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug12243", test_bug12243, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11909", test_bug11909, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug13488", test_bug13488, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug13524", test_bug13524, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug14845", test_bug14845, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug14210", test_bug14210, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug24179", test_bug24179, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug32265", test_bug32265, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug38486", test_bug38486, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug8880", test_bug8880, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug9159", test_bug9159, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug9478", test_bug9478, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug9520", test_bug9520, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug9643", test_bug9643, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/data.csv b/libmariadb/unittest/libmariadb/data.csv
new file mode 100644
index 00000000..07471374
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/data.csv
@@ -0,0 +1,100 @@
+00000100,1,60000.000000
+00000101,2,60000.000000
+00000102,3,60000.000000
+00000103,1,60000.000000
+00000104,2,60000.000000
+00000105,3,60000.000000
+00000106,1,60000.000000
+00000107,2,60000.000000
+00000108,3,60000.000000
+00000109,1,60000.000000
+00000110,2,60000.000000
+00000111,3,60000.000000
+00000112,1,60000.000000
+00000113,2,60000.000000
+00000114,3,60000.000000
+00000115,1,60000.000000
+00000116,2,60000.000000
+00000117,3,60000.000000
+00000118,1,60000.000000
+00000119,2,60000.000000
+00000120,3,60000.000000
+00000121,1,60000.000000
+00000122,2,60000.000000
+00000123,3,60000.000000
+00000124,1,60000.000000
+00000125,2,60000.000000
+00000126,3,60000.000000
+00000127,1,60000.000000
+00000128,2,60000.000000
+00000129,3,60000.000000
+00000130,1,60000.000000
+00000131,2,60000.000000
+00000132,3,60000.000000
+00000133,1,60000.000000
+00000134,2,60000.000000
+00000135,3,60000.000000
+00000136,1,60000.000000
+00000137,2,60000.000000
+00000138,3,60000.000000
+00000139,1,60000.000000
+00000140,2,60000.000000
+00000141,3,60000.000000
+00000142,1,60000.000000
+00000143,2,60000.000000
+00000144,3,60000.000000
+00000145,1,60000.000000
+00000146,2,60000.000000
+00000147,3,60000.000000
+00000148,1,60000.000000
+00000149,2,60000.000000
+00000150,3,60000.000000
+00000151,1,60000.000000
+00000152,2,60000.000000
+00000153,3,60000.000000
+00000154,1,60000.000000
+00000155,2,60000.000000
+00000156,3,60000.000000
+00000157,1,60000.000000
+00000158,2,60000.000000
+00000159,3,60000.000000
+00000160,1,60000.000000
+00000161,2,60000.000000
+00000162,3,60000.000000
+00000163,1,60000.000000
+00000164,2,60000.000000
+00000165,3,60000.000000
+00000166,1,60000.000000
+00000167,2,60000.000000
+00000168,3,60000.000000
+00000169,1,60000.000000
+00000170,2,60000.000000
+00000171,3,60000.000000
+00000172,1,60000.000000
+00000173,2,60000.000000
+00000174,3,60000.000000
+00000175,1,60000.000000
+00000176,2,60000.000000
+00000177,3,60000.000000
+00000178,1,60000.000000
+00000179,2,60000.000000
+00000180,3,60000.000000
+00000181,1,60000.000000
+00000182,2,60000.000000
+00000183,3,60000.000000
+00000184,1,60000.000000
+00000185,2,60000.000000
+00000186,3,60000.000000
+00000187,1,60000.000000
+00000188,2,60000.000000
+00000189,3,60000.000000
+00000190,1,60000.000000
+00000191,2,60000.000000
+00000192,3,60000.000000
+00000193,1,60000.000000
+00000194,2,60000.000000
+00000195,3,60000.000000
+00000196,1,60000.000000
+00000197,2,60000.000000
+00000198,3,60000.000000
+00000199,1,60000.000000
diff --git a/libmariadb/unittest/libmariadb/dyncol.c b/libmariadb/unittest/libmariadb/dyncol.c
new file mode 100644
index 00000000..8edb20a8
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/dyncol.c
@@ -0,0 +1,323 @@
+/*
+Copyright (c) 2013 Monty Program AB. All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "my_test.h"
+#include "mariadb_dyncol.h"
+
+static int create_dyncol_named(MYSQL *mysql)
+{
+ DYNAMIC_COLUMN dyncol;
+ DYNAMIC_COLUMN_VALUE *vals;
+ uint i, column_count= 6;
+ int rc;
+ const char *strval[]= {"Val1", "Val2", "Val3", "Val4", "Val5", "Val6"};
+ MYSQL_LEX_STRING keys1[]= {{(char *)"key1", 4}, {(char *)"key2", 4},
+ {(char *)"key3", 4}, {(char *)"key4", 4},
+ {(char *)"key5", 4}, {(char *)"key6", 4}},
+
+ keys2[]= {{(char *)"key1", 4}, {(char *)"key1", 4},
+ {(char *)"key3", 4}, {(char *)"key4", 4},
+ {(char *)"key5", 4}, {(char *)"key6", 4}},
+
+ keys3[]= {{(char *)"\x70\x61\x72\x61\x00\x30", 6},
+ {(char *)"\x70\x61\x72\x61\x00\x31", 6},
+ {(char *)"\x70\x61\x72\x61\x00\x32", 6},
+ {(char *)"\x70\x61\x72\x61\x00\x33", 6},
+ {(char *)"\x70\x61\x72\x61\x00\x34", 6},
+ {(char *)"\x70\x61\x72\x61\x00\x35", 6}};
+ MYSQL_LEX_STRING *my_keys;
+ uint my_count;
+
+ vals= (DYNAMIC_COLUMN_VALUE *)malloc(column_count * sizeof(DYNAMIC_COLUMN_VALUE));
+
+ for (i=0; i < column_count; i++)
+ {
+ vals[i].type= DYN_COL_STRING;
+ vals[i].x.string.value.str= (char *)strval[i];
+ vals[i].x.string.value.length= strlen(strval[i]);
+ vals[i].x.string.charset= (MARIADB_CHARSET_INFO *)mysql->charset;
+ diag("%s", keys3[i].str);
+ }
+
+ mariadb_dyncol_init(&dyncol);
+ rc= mariadb_dyncol_create_many_named(&dyncol, column_count, keys1, vals, 0);
+ mariadb_dyncol_free(&dyncol);
+ FAIL_IF(mariadb_dyncol_create_many_named(&dyncol, column_count, keys1, vals, 1) < 0, "Error");
+ column_count= 0;
+ FAIL_IF(mariadb_dyncol_column_count(&dyncol, &column_count) < 0, "Error");
+
+ FAIL_IF(column_count != 6, "6 columns expected");
+ mariadb_dyncol_free(&dyncol);
+
+ rc= mariadb_dyncol_create_many_named(&dyncol, column_count, keys3, vals, 1);
+ if (rc < 0) {
+ diag("Error!!: %d", rc);
+ return FAIL;
+ }
+ column_count= 0;
+ FAIL_IF(mariadb_dyncol_column_count(&dyncol, &column_count) < 0, "Error");
+
+ FAIL_IF(column_count != 6, "6 columns expected");
+
+ mariadb_dyncol_free(&dyncol);
+
+ /* Now try to add a duplicate key */
+
+ FAIL_IF(mariadb_dyncol_create_many_named(&dyncol, column_count, keys2, vals, 1) >=0, "Error expected");
+ mariadb_dyncol_free(&dyncol);
+
+ /* binary keys */
+ rc= mariadb_dyncol_create_many_named(&dyncol, column_count, keys3, vals, 1);
+ FAIL_IF(rc < 0, "binary keys failed");
+
+ /* get keys*/
+ rc= mariadb_dyncol_list_named(&dyncol, &my_count, &my_keys);
+ FAIL_IF(rc < 0, "list named failed");
+
+ for (i=0; i < my_count; i++)
+ {
+ if (memcmp(my_keys[i].str, keys3[i].str, keys3[i].length) != 0)
+ diag("error key %d", i);
+ vals[i].type=DYN_COL_NULL;
+ }
+ rc= mariadb_dyncol_update_many_named(&dyncol, column_count, keys3, vals);
+ FAIL_IF(rc < 0, "update failed");
+ mariadb_dyncol_free(&dyncol);
+
+ keys3[0].str= (char *)"test";
+ for (i=0; i < column_count; i++)
+ diag("%s", my_keys[i].str);
+
+ free(vals);
+ free(my_keys);
+ return OK;
+}
+
+static int mdev_4994(MYSQL *unused __attribute__((unused)))
+{
+ DYNAMIC_COLUMN dyncol;
+ uint key= 1;
+ DYNAMIC_COLUMN_VALUE val;
+ int rc;
+
+
+ val.type= DYN_COL_NULL;
+
+ mariadb_dyncol_init(&dyncol);
+ rc= mariadb_dyncol_create_many_num(&dyncol, 1, &key, &val, 0);
+ FAIL_IF(rc < 0, "Unexpected error");
+ mariadb_dyncol_free(&dyncol);
+ return OK;
+}
+
+static int create_dyncol_num(MYSQL *mysql)
+{
+ DYNAMIC_COLUMN dyncol;
+ DYNAMIC_COLUMN_VALUE vals[5];
+ uint i, column_count= 5;
+ uint my_count;
+ MYSQL_LEX_STRING *my_keys;
+ DYNAMIC_COLUMN_VALUE *my_vals;
+ int rc;
+ const char *strval[]= {"Val1", "Val2", "Val3", "Val4", "Val5"};
+
+ uint keys1[5]= {1,2,3,4,5},
+ keys2[5]= {1,2,2,4,5};
+ MYSQL_LEX_STRING key1= {(char *)"1",1};
+
+ for (i=0; i < column_count; i++)
+ {
+ vals[i].type= DYN_COL_STRING;
+ vals[i].x.string.value.str= (char *)strval[i];
+ vals[i].x.string.value.length= strlen(strval[i]);
+ vals[i].x.string.charset= (MARIADB_CHARSET_INFO *)mysql->charset;
+ }
+ FAIL_IF(mariadb_dyncol_create_many_num(&dyncol, column_count, keys1, vals, 1) <0, "Error (keys1)");
+
+ vals[0].x.string.value.str= (char *)strval[1];
+ rc= mariadb_dyncol_update_many_named(&dyncol,1, &key1, vals);
+ diag("update: %d", rc);
+
+ rc= mariadb_dyncol_unpack(&dyncol, &my_count, &my_keys, &my_vals);
+ diag("unpack: %d %d", rc, my_count);
+
+ free(my_keys);
+ free(my_vals);
+
+ FAIL_IF(mariadb_dyncol_column_count(&dyncol, &column_count) < 0, "Error");
+ FAIL_IF(column_count != 5, "5 columns expected");
+ mariadb_dyncol_free(&dyncol);
+ FAIL_IF(mariadb_dyncol_create_many_num(&dyncol, column_count, keys2, vals, 1) >=0, "Error expected (keys2)");
+ mariadb_dyncol_free(&dyncol);
+ return OK;
+}
+
+static int mdev_x1(MYSQL *mysql)
+{
+ int rc;
+ uint i;
+ uint num_keys[5]= {1,2,3,4,5};
+ const char *strval[]= {"Val1", "Val2", "Val3", "Val4", "Val5"};
+ DYNAMIC_COLUMN_VALUE vals[5];
+ DYNAMIC_COLUMN dynstr;
+ MYSQL_LEX_STRING my_key= {(char *)"1", 2};
+ uint unpack_columns;
+ MYSQL_LEX_STRING *unpack_keys;
+ DYNAMIC_COLUMN_VALUE *unpack_vals;
+
+ for (i=0; i < 5; i++)
+ {
+ vals[i].type= DYN_COL_STRING;
+ vals[i].x.string.value.str= (char *)strval[i];
+ vals[i].x.string.value.length= strlen(strval[i]);
+ vals[i].x.string.charset= (MARIADB_CHARSET_INFO *)mysql->charset;
+ }
+
+ mariadb_dyncol_init(&dynstr);
+
+ /* create numeric */
+ rc= mariadb_dyncol_create_many_num(&dynstr, 5, num_keys, vals, 1);
+ if (rc < 0)
+ {
+ diag("Error: %d", rc);
+ return FAIL;
+ }
+
+ /* unpack and print values */
+ rc= mariadb_dyncol_unpack(&dynstr, &unpack_columns, &unpack_keys, &unpack_vals);
+ if (rc < 0)
+ {
+ diag("Error: %d", rc);
+ return FAIL;
+ }
+
+ for (i=0; i < unpack_columns; i++)
+ if (memcmp(unpack_vals[i].x.string.value.str, vals[i].x.string.value.str, vals[i].x.string.value.length))
+ diag("Error1: key: %1s val: %s %s", unpack_keys[i].str, unpack_vals[i].x.string.value.str, vals[i].x.string.value.str);
+
+ free(unpack_keys);
+ free(unpack_vals);
+
+ /* change one value and update with named key */
+/* vals[0].x.string.value.str= strval[1]; */
+ rc= mariadb_dyncol_update_many_named(&dynstr, 1, &my_key, vals);
+ if (rc < 0)
+ {
+ diag("Error: %d", rc);
+ return FAIL;
+ }
+
+ /* unpack and print values */
+ rc= mariadb_dyncol_unpack(&dynstr, &unpack_columns, &unpack_keys, &unpack_vals);
+ if (rc < 0)
+ {
+ diag("Error: %d", rc);
+ return FAIL;
+ }
+ diag("Columns: %d", unpack_columns);
+
+ for (i=0; i < unpack_columns; i++)
+ diag("Key: %s Len: %lu", unpack_keys[i].str, (unsigned long)unpack_keys[i].length);
+
+
+ free(unpack_keys);
+ free(unpack_vals);
+
+ mariadb_dyncol_free(&dynstr);
+ return OK;
+}
+
+static int dyncol_column_count(MYSQL *unused __attribute__((unused)))
+{
+ DYNAMIC_COLUMN dyncol;
+ uint column_count= 5;
+ int rc;
+
+ mariadb_dyncol_init(&dyncol); /* memset(&dyncol, 0, sizeof(DYNAMIC_COLUMN)) */
+ rc= mariadb_dyncol_column_count(&dyncol, &column_count);
+ diag("rc=%d", rc);
+ FAIL_IF(rc < 0, "unexpected error");
+ FAIL_IF(column_count > 0, "Expected column_count=0");
+ return OK;
+}
+
+static int dyncol_nested(MYSQL *mysql __attribute__((unused)))
+{
+ DYNAMIC_COLUMN col1, col2;
+ DYNAMIC_COLUMN_VALUE value[2];
+ MYSQL_LEX_STRING cols[2]= {{(char *)"0",1},{(char *)"1",1}};
+ DYNAMIC_STRING s;
+
+ mariadb_dyncol_init(&col1);
+ mariadb_dyncol_init(&col2);
+
+ memset(&value, 0, sizeof(DYNAMIC_COLUMN_VALUE));
+
+ value[0].type= DYN_COL_UINT;
+ value[0].x.ulong_value = 17;
+
+ mariadb_dyncol_create_many_named(&col1, 1, cols, value, 0);
+ if (mariadb_dyncol_check(&col1) != ER_DYNCOL_OK)
+ {
+ diag("Error while creating col1");
+ return FAIL;
+ }
+
+ value[1].type= DYN_COL_DYNCOL;
+ value[1].x.string.value.str= col1.str;
+ value[1].x.string.value.length= col1.length;
+
+ mariadb_dyncol_create_many_named(&col2, 2, cols, value, 0);
+ if (mariadb_dyncol_check(&col2) != ER_DYNCOL_OK)
+ {
+ diag("Error while creating col1");
+ return FAIL;
+ }
+ mariadb_dyncol_json(&col2, &s);
+ if (strcmp(s.str, "{\"0\":17,\"1\":{\"0\":17}}") != 0)
+ {
+ diag("%s != %s", s.str, "{\"0\":17,\"1\":{\"0\":17}}");
+ return FAIL;
+ }
+ ma_dynstr_free(&s);
+ mariadb_dyncol_free(&col1);
+ mariadb_dyncol_free(&col2);
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"mdev_x1", mdev_x1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"mdev_4994", mdev_4994, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"create_dyncol_named", create_dyncol_named, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"create_dyncol_num", create_dyncol_num, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"dyncol_column_count", dyncol_column_count, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"dyncol_nested", dyncol_nested, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, 0}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/errors.c b/libmariadb/unittest/libmariadb/errors.c
new file mode 100644
index 00000000..b0914782
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/errors.c
@@ -0,0 +1,299 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+
+/* Test warnings */
+
+static int test_client_warnings(MYSQL *mysql)
+{
+ int rc;
+
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(!mysql_warning_count(mysql), "Warning expected");
+
+ return OK;
+}
+
+
+static int test_ps_client_warnings(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ const char *query= "DROP TABLE IF EXISTS test_non_exists";
+
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(rc, mysql_stmt_error(stmt));
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(rc, mysql_stmt_error(stmt));
+
+ FAIL_IF(!mysql_warning_count(mysql), "Warning expected");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_server_warnings(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SHOW WARNINGS");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, mysql_error(mysql));
+ FAIL_IF(!mysql_num_rows(result), "Empty resultset");
+
+ mysql_free_result(result);
+
+ return OK;
+}
+
+
+/* Test errors */
+
+static int test_client_errors(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE test_non_exists");
+ FAIL_IF(!rc, "Error expected");
+
+ FAIL_IF(!mysql_errno(mysql), "Error expected");
+ FAIL_IF(!strlen(mysql_error(mysql)), "Empty errormsg");
+ FAIL_IF(strcmp(mysql_sqlstate(mysql), "00000") == 0, "Invalid SQLstate");
+
+ return OK;
+}
+
+static int test_ps_client_errors(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ const char *query= "DROP TABLE test_non_exists";
+
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(rc, mysql_stmt_error(stmt));
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, mysql_stmt_error(stmt));
+
+ FAIL_IF(!mysql_stmt_errno(stmt), "Error expected");
+ FAIL_IF(!strlen(mysql_stmt_error(stmt)), "Empty errormsg");
+ FAIL_IF(strcmp(mysql_stmt_sqlstate(stmt), "00000") == 0, "Invalid SQLstate");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_server_errors(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+
+ rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE test_non_exists");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SHOW ERRORS");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, mysql_error(mysql));
+ FAIL_IF(!mysql_num_rows(result), "Empty resultset");
+ mysql_free_result(result);
+
+ return OK;
+}
+
+/* Bug #16143: mysql_stmt_sqlstate returns an empty string instead of '00000' */
+
+static int test_bug16143(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ /* Check mysql_stmt_sqlstate return "no error" */
+ FAIL_UNLESS(strcmp(mysql_stmt_sqlstate(stmt), "00000") == 0, "Expected SQLstate 000000");
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+/* Test warnings for cuted rows */
+
+static int test_cuted_rows(MYSQL *mysql)
+{
+ int rc, count;
+ MYSQL_RES *result;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ rc= mysql_query(mysql, "DROP TABLE if exists t1");
+ check_mysql_rc(rc, mysql);
+ mysql_query(mysql, "DROP TABLE if exists t2");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1(c1 tinyint)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t2(c1 int not null)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "START TRANSACTION");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 values(10), (NULL), (NULL)");
+ check_mysql_rc(rc, mysql);
+
+ count= mysql_warning_count(mysql);
+ FAIL_UNLESS(count == 0, "warnings != 0");
+
+ rc= mysql_query(mysql, "INSERT INTO t2 SELECT * FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ count= mysql_warning_count(mysql);
+ FAIL_UNLESS(count == 2, "warnings != 2");
+
+ rc= mysql_query(mysql, "SHOW WARNINGS");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 2, "rowcount != 2");
+ mysql_free_result(result);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES('junk'), (876789)");
+ check_mysql_rc(rc, mysql);
+
+ count= mysql_warning_count(mysql);
+ FAIL_UNLESS(count == 2, "warnings != 2");
+
+ rc= mysql_query(mysql, "SHOW WARNINGS");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 2, "rowcount != 2");
+ mysql_free_result(result);
+
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_parse_error_and_bad_length(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char stmt_str[128];
+
+ /* check that we get 4 syntax errors over the 4 calls */
+
+ rc= mysql_query(mysql, "SHOW DATABAAAA");
+ FAIL_UNLESS(rc, "Error expected");
+ rc= mysql_real_query(mysql, SL_BIN("SHOW DATABASES\0AAA"));
+ FAIL_UNLESS(rc, "Error expected");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SHOW DATABAAAA"));
+ FAIL_IF(!rc, "Error expected");
+ mysql_stmt_close(stmt);
+ stmt= mysql_stmt_init(mysql);
+ FAIL_UNLESS(stmt, "");
+ memset(stmt_str, 0, 100);
+
+ SKIP_XPAND;
+
+ strcpy(stmt_str, "SHOW DATABASES");
+ rc= mysql_stmt_prepare(stmt, stmt_str, 99);
+ FAIL_IF(!rc, "Error expected");
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+
+struct my_tests_st my_tests[] = {
+ {"test_client_warnings", test_client_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_ps_client_warnings", test_ps_client_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_server_warnings", test_server_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_client_errors", test_client_errors, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_ps_client_errors", test_ps_client_errors, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_server_errors", test_server_errors, TEST_CONNECTION_DEFAULT, 0, NULL , "Open bug: #42364"},
+ {"test_bug16143", test_bug16143, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_cuted_rows", test_cuted_rows, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_parse_error_and_bad_length", test_parse_error_and_bad_length, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/features-10_2.c b/libmariadb/unittest/libmariadb/features-10_2.c
new file mode 100644
index 00000000..6e5064dc
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/features-10_2.c
@@ -0,0 +1,255 @@
+/*
+*/
+
+#include "my_test.h"
+
+static int execute_direct(MYSQL *mysql)
+{
+ int rc= 0;
+ long i= 0;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind;
+ unsigned int param_count= 1;
+ MYSQL_RES *res= NULL;
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS t1", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1);
+ check_stmt_rc(rc, stmt);
+
+ while (!mysql_stmt_fetch(stmt));
+
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE t1 (a int)", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+
+ bind.buffer= &i;
+ bind.buffer_type= MYSQL_TYPE_LONG;
+ bind.buffer_length= sizeof(long);
+
+ mysql_stmt_close(stmt);
+ stmt= mysql_stmt_init(mysql);
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &param_count);
+
+ rc= mysql_stmt_bind_param(stmt, &bind);
+ check_stmt_rc(rc, stmt);
+ rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO t1 VALUES (?)", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "START TRANSACTION");
+ check_mysql_rc(rc, mysql);
+
+ for (i=1; i < 1000; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+ rc= mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT * FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_IF(mysql_num_rows(res) != 1000, "Expected 1000 rows");
+
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "COMMIT");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int execute_direct_example(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_BIND bind[2];
+ int intval= 1;
+ int param_count= 2;
+ int rc;
+ const char *strval= "execute_direct_example1";
+
+ /* Direct execution without parameters */
+ rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS execute_direct", -1);
+ check_stmt_rc(rc, stmt);
+ rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE execute_direct (a int, b varchar(20))", -1);
+ rc= mysql_stmt_close(stmt);
+ stmt= mysql_stmt_init(mysql);
+ check_stmt_rc(rc, stmt);
+ memset(bind, 0, sizeof(MYSQL_BIND) * 2);
+ bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ bind[0].buffer= &intval;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= (char *)strval;
+ bind[1].buffer_length= (unsigned long)strlen(strval);
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ /* set number of parameters */
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &param_count);
+ check_stmt_rc(rc, stmt);
+
+ /* bind parameters */
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO execute_direct VALUES (?,?)", -1);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE execute_direct");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int conc_213(MYSQL *mysql)
+{
+ MYSQL_BIND bind;
+ unsigned int param_count= 1;
+ long id= 1234;
+ MYSQL_STMT *stmt;
+
+ stmt = mysql_stmt_init(mysql);
+
+ memset(&bind, '\0', sizeof(bind));
+
+ bind.buffer_type = MYSQL_TYPE_LONG;
+ bind.buffer = (void *)&id;
+ bind.buffer_length = sizeof(long);
+/* bind.is_null = &is_null;
+ bind.length = &length;
+ bind.error = &error; */
+
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &param_count);
+ check_stmt_rc(mysql_stmt_bind_param(stmt, &bind), stmt);
+ check_stmt_rc(mariadb_stmt_execute_direct(stmt, "SELECT ?", -1), stmt);
+ check_stmt_rc(mysql_stmt_store_result(stmt), stmt);
+ check_stmt_rc(mysql_stmt_free_result(stmt), stmt);
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int conc_212(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1, 2", -1);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_store_result(stmt);
+ mysql_stmt_free_result(stmt);
+
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1, 2", -1);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_store_result(stmt);
+ mysql_stmt_free_result(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc,mysql);
+
+
+ rc= mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int conc_218(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_BIND bind[2];
+ int id=1;
+ my_bool is_null= 0, error= 0;
+ unsigned int param_count= 1;
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+ bind[0].buffer_type = MYSQL_TYPE_LONG;
+ bind[0].buffer = (void *)&id;
+ bind[0].buffer_length = 4;
+ bind[0].is_null = &is_null;
+ bind[0].error = &error;
+
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &param_count);
+ check_stmt_rc(mysql_stmt_bind_param(stmt, bind), stmt);
+ check_stmt_rc(mariadb_stmt_execute_direct(stmt, "SELECT ?", -1), stmt);
+ check_stmt_rc(mysql_stmt_store_result(stmt), stmt);
+
+ check_stmt_rc(mysql_stmt_free_result(stmt), stmt);
+
+ param_count= 1;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &param_count);
+ check_stmt_rc(mysql_stmt_bind_param(stmt, bind), stmt);
+ check_stmt_rc(mariadb_stmt_execute_direct(stmt, "SELECT ?", -1), stmt);
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_cursor(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ unsigned long prefetch_rows= 1;
+ unsigned long cursor_type= CURSOR_TYPE_READ_ONLY;
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, &prefetch_rows);
+ check_stmt_rc(rc, stmt);
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL", -1);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL", -1);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+
+struct my_tests_st my_tests[] = {
+ {"test_cursor", test_cursor, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"conc_218", conc_218, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"conc_212", conc_212, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"conc_213", conc_213, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"execute_direct", execute_direct, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"execute_direct_example", execute_direct_example, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+
+ mysql_library_init(0,0,NULL);
+
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ mysql_server_end();
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/fetch.c b/libmariadb/unittest/libmariadb/fetch.c
new file mode 100644
index 00000000..55b1314a
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/fetch.c
@@ -0,0 +1,1003 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+
+/* Generalized fetch conversion routine for all basic types */
+
+static int bind_fetch(MYSQL *mysql, int row_count)
+{
+ MYSQL_STMT *stmt;
+ int rc, i, count= row_count;
+ int32 data[10];
+ int8 i8_data;
+ int16 i16_data;
+ int i32_data;
+ longlong i64_data;
+ float f_data;
+ double d_data;
+ char s_data[10];
+ ulong length[10];
+ MYSQL_BIND my_bind[7];
+ my_bool is_null[7];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ strcpy(query, "INSERT INTO test_bind_fetch VALUES (?, ?, ?, ?, ?, ?, ?)");
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc,stmt);
+
+ FAIL_UNLESS(mysql_stmt_param_count(stmt) == 7, "ParamCount != 7");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].buffer= (void *) &data[i];
+ }
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc,stmt);
+
+ while (count--)
+ {
+ rc= 10+count;
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ data[i]= rc+i;
+ rc+= 12;
+ }
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc,stmt);
+ }
+
+ rc= mysql_commit(mysql);
+ check_stmt_rc(rc,stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= my_stmt_result(mysql, "SELECT * FROM test_bind_fetch");
+ FAIL_UNLESS(row_count == rc, "Wrong number of rows");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ strcpy(query, "SELECT * FROM test_bind_fetch");
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc,stmt);
+
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].buffer= (void *) &data[i];
+ my_bind[i].length= &length[i];
+ my_bind[i].is_null= &is_null[i];
+ }
+
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&i8_data;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[1].buffer= (void *)&i16_data;
+
+ my_bind[2].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[2].buffer= (void *)&i32_data;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[3].buffer= (void *)&i64_data;
+
+ my_bind[4].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[4].buffer= (void *)&f_data;
+
+ my_bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[5].buffer= (void *)&d_data;
+
+ my_bind[6].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[6].buffer= (void *)&s_data;
+ my_bind[6].buffer_length= sizeof(s_data);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc,stmt);
+
+ while (row_count--)
+ {
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= 10+row_count;
+
+ /* TINY */
+ FAIL_UNLESS((int) i8_data == rc, "Invalid value for i8_data");
+ FAIL_UNLESS(length[0] == 1, "Invalid length");
+ rc+= 13;
+
+ /* SHORT */
+ FAIL_UNLESS((int) i16_data == rc, "Invalid value for i16_data");
+ FAIL_UNLESS(length[1] == 2, "Invalid length");
+ rc+= 13;
+
+ /* LONG */
+ FAIL_UNLESS((int) i32_data == rc, "Invalid value for i32_data");
+ FAIL_UNLESS(length[2] == 4, "Invalid length");
+ rc+= 13;
+
+ /* LONGLONG */
+ FAIL_UNLESS((int) i64_data == rc, "Invalid value for i64_data");
+ FAIL_UNLESS(length[3] == 8, "Invalid length");
+ rc+= 13;
+
+ /* FLOAT */
+ FAIL_UNLESS((int)f_data == rc, "Invalid value for f_data");
+ FAIL_UNLESS(length[4] == 4, "Invalid length");
+ rc+= 13;
+
+ /* DOUBLE */
+ FAIL_UNLESS((int)d_data == rc, "Invalid value for d_data");
+ FAIL_UNLESS(length[5] == 8, "Invalid length");
+ rc+= 13;
+
+ /* CHAR */
+ {
+ char buff[20];
+ long len= sprintf(buff, "%d", rc);
+ FAIL_UNLESS(strcmp(s_data, buff) == 0, "Invalid value for s_data");
+ FAIL_UNLESS(length[6] == (ulong) len, "Invalid length");
+ }
+ }
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "Expected MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+
+static int test_fetch_seek(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[3];
+ MYSQL_ROW_OFFSET row;
+ int rc;
+ int32 c1;
+ char c2[11], c3[20];
+ const char *query = "SELECT * FROM t1";
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10), c3 timestamp)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1(c2) values('venu'), ('mysql'), ('open'), ('source')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc,stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&c1;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)c2;
+ my_bind[1].buffer_length= sizeof(c2);
+
+ my_bind[2]= my_bind[1];
+ my_bind[2].buffer= (void *)c3;
+ my_bind[2].buffer_length= sizeof(c3);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc,stmt);
+
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ row= mysql_stmt_row_tell(stmt);
+
+ row= mysql_stmt_row_seek(stmt, row);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ row= mysql_stmt_row_seek(stmt, row);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ mysql_stmt_data_seek(stmt, 0);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc != MYSQL_NO_DATA, "Expected MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Test mysql_stmt_fetch_column() with offset */
+
+static int test_fetch_offset(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ char data[11], chunk[5];
+ ulong length[2];
+ int rc;
+ my_bool is_null[2];
+ const char *query = "SELECT * FROM t1";
+
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1(a char(10), b mediumblob)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values('abcdefghij', 'klmnopqrstzy'), (null, null)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc,stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)data;
+ my_bind[0].buffer_length= 11;
+ my_bind[0].is_null= &is_null[0];
+ my_bind[0].length= &length[0];
+
+ my_bind[1].buffer_type= MYSQL_TYPE_MEDIUM_BLOB;
+ my_bind[1].buffer= NULL;
+ my_bind[1].buffer_length= 0;
+ my_bind[1].is_null= &is_null[1];
+ my_bind[1].length= &length[1];
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc,stmt);
+diag("truncation: %d", mysql->options.report_data_truncation);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_DATA_TRUNCATED, "rc != MYSQL_DATA_TRUNCATED");
+
+ data[0]= '\0';
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[0], 0, 0);
+ check_stmt_rc(rc,stmt);
+
+
+ FAIL_IF(!(strncmp(data, "abcdefghij", 11) == 0 && length[0] == 10), "Wrong value");
+ FAIL_IF(my_bind[0].error_value, "No truncation, but error is set");
+
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[0], 0, 5);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strncmp(data, "fghij", 6) == 0 && length[0] == 10), "Wrong value");
+ FAIL_IF(my_bind[0].error_value, "No truncation, but error is set");
+
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[0], 0, 9);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strncmp(data, "j", 2) == 0 && length[0] == 10), "Wrong value");
+ FAIL_IF(my_bind[0].error_value, "No truncation, but error is set");
+
+ /* Now blob field */
+ my_bind[1].buffer= chunk;
+ my_bind[1].buffer_length= sizeof(chunk);
+
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[1], 1, 0);
+ check_stmt_rc(rc,stmt);
+
+ FAIL_IF(!(strncmp(chunk, "klmno", 5) == 0 && length[1] == 12), "Wrong value");
+ FAIL_IF(my_bind[1].error_value == '\0', "Truncation, but error is not set");
+
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[1], 1, 5);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strncmp(chunk, "pqrst", 5) == 0 && length[1] == 12), "Wrong value");
+ FAIL_IF(my_bind[1].error_value == '\0', "Truncation, but error is not set");
+
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[1], 1, 10);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strncmp(chunk, "zy", 2) == 0 && length[1] == 12), "Wrong value");
+ FAIL_IF(my_bind[1].error_value, "No truncation, but error is set");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ memset(is_null, 0, sizeof(is_null));
+
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[0], 0, 0);
+ check_stmt_rc(rc,stmt);
+
+ FAIL_IF(is_null[0] != 1, "Null flag not set");
+
+ rc= mysql_stmt_fetch_column(stmt, &my_bind[1], 1, 0);
+ check_stmt_rc(rc,stmt);
+
+ FAIL_IF(is_null[1] != 1, "Null flag not set");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc != MYSQL_NO_DATA, "Expected MYSQL_NO_DATA");
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Test mysql_stmt_fetch_column() */
+
+static int test_fetch_column(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ char c2[20], bc2[20];
+ ulong l1, l2, bl1, bl2;
+ int rc, c1, bc1;
+ const char *query= "SELECT * FROM t1 ORDER BY c2 DESC";
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1(c2) values('venu'), ('mysql')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc,stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&bc1;
+ my_bind[0].buffer_length= 0;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &bl1;
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)bc2;
+ my_bind[1].buffer_length= 7;
+ my_bind[1].is_null= 0;
+ my_bind[1].length= &bl2;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc,stmt);
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0); /* No-op at this point */
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ c2[0]= '\0'; l2= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)c2;
+ my_bind[0].buffer_length= 7;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l2;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strncmp(c2, "venu", 4) == 0 && l2 == 4), "Expected c2='venu'");
+
+ c2[0]= '\0'; l2= 0;
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strcmp(c2, "venu") == 0 && l2 == 4), "Expected c2='venu'");
+
+ c1= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&c1;
+ my_bind[0].buffer_length= 0;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l1;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(c1 == 1 && l1 == 4), "Expected c1=1");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+
+ c2[0]= '\0'; l2= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)c2;
+ my_bind[0].buffer_length= 7;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l2;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strncmp(c2, "mysq", 4) == 0 && l2 == 5), "Expected c2='mysql'");
+
+ c2[0]= '\0'; l2= 0;
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(strcmp(c2, "mysql") == 0 && l2 == 5), "Expected c2='mysql'");
+
+ c1= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&c1;
+ my_bind[0].buffer_length= 0;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l1;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
+ check_stmt_rc(rc,stmt);
+ FAIL_IF(!(c1 == 2 && l1 == 4), "Expected c2=2");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc!=MYSQL_NO_DATA, "Expected MYSQL_NO_DATA");
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Test fetch without prior bound buffers */
+
+static int test_fetch_nobuffs(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[4];
+ char str[4][50];
+ int rc;
+ const char *query = "SELECT DATABASE(), CURRENT_USER(), \
+ CURRENT_DATE(), CURRENT_TIME()";
+
+ stmt = mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+
+ FAIL_IF(rc != 1, "Expected 1 row");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)str[0];
+ my_bind[0].buffer_length= sizeof(str[0]);
+ my_bind[1]= my_bind[2]= my_bind[3]= my_bind[0];
+ my_bind[1].buffer= (void *)str[1];
+ my_bind[2].buffer= (void *)str[2];
+ my_bind[3].buffer= (void *)str[3];
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ rc++;
+ }
+ FAIL_IF(rc != 1, "Expected 1 row");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+/* Test fetch null */
+
+static int test_fetch_null(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int i;
+ int nData= 0;
+ MYSQL_BIND my_bind[11];
+ ulong length[11];
+ my_bool is_null[11];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_fetch_null");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_fetch_null("
+ " col1 tinyint, col2 smallint, "
+ " col3 int, col4 bigint, "
+ " col5 float, col6 double, "
+ " col7 date, col8 time, "
+ " col9 varbinary(10), "
+ " col10 varchar(50), "
+ " col11 char(20))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_fetch_null (col11) "
+ "VALUES (1000), (88), (389789)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ FAIL_IF(rc, mysql_error(mysql));
+
+ /* fetch */
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].is_null= &is_null[i];
+ my_bind[i].length= &length[i];
+ }
+ my_bind[i-1].buffer= (void *)&nData; /* Last column is not null */
+
+ strcpy((char *)query , "SELECT * FROM test_fetch_null");
+
+ rc= my_stmt_result(mysql, query);
+ FAIL_UNLESS(rc == 3, "Expected 3 rows");
+
+ stmt = mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ rc++;
+ for (i= 0; i < 10; i++)
+ {
+ FAIL_IF(!is_null[i], "Expected is_null");
+ }
+ FAIL_UNLESS(nData == 1000 || nData == 88 || nData == 389789, "Wrong value for nData");
+ FAIL_UNLESS(is_null[i] == 0, "Expected !is_null");
+ FAIL_UNLESS(length[i] == 4, "Expected length=4");
+ }
+ FAIL_UNLESS(rc == 3, "Expected 3 rows");
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE test_fetch_null");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Test fetching of date, time and ts */
+
+static int test_fetch_date(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ uint i;
+ int rc;
+ long year;
+ char date[25], my_time[25], ts[25], ts_4[25], ts_6[20], dt[20];
+ ulong d_length, t_length, ts_length, ts4_length, ts6_length,
+ dt_length, y_length;
+ MYSQL_BIND my_bind[8];
+ my_bool is_null[8];
+ ulong length[8];
+ const char *query= "SELECT * FROM test_bind_result";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 date, c2 time, \
+ c3 timestamp, \
+ c4 year, \
+ c5 datetime, \
+ c6 timestamp, \
+ c7 timestamp)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SET SQL_MODE=''");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES('2002-01-02', \
+ '12:49:00', \
+ '2002-01-02 17:46:59', \
+ 2010, \
+ '2010-07-10', \
+ '2020', '1999-12-29')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ FAIL_IF(rc, mysql_error(mysql));
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i= 0; i < array_elements(my_bind); i++)
+ {
+ my_bind[i].is_null= &is_null[i];
+ my_bind[i].length= &length[i];
+ }
+
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1]= my_bind[2]= my_bind[0];
+
+ my_bind[0].buffer= (void *)&date;
+ my_bind[0].buffer_length= sizeof(date);
+ my_bind[0].length= &d_length;
+
+ my_bind[1].buffer= (void *)&my_time;
+ my_bind[1].buffer_length= sizeof(my_time);
+ my_bind[1].length= &t_length;
+
+ my_bind[2].buffer= (void *)&ts;
+ my_bind[2].buffer_length= sizeof(ts);
+ my_bind[2].length= &ts_length;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[3].buffer= (void *)&year;
+ my_bind[3].length= &y_length;
+
+ my_bind[4].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[4].buffer= (void *)&dt;
+ my_bind[4].buffer_length= sizeof(dt);
+ my_bind[4].length= &dt_length;
+
+ my_bind[5].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[5].buffer= (void *)&ts_4;
+ my_bind[5].buffer_length= sizeof(ts_4);
+ my_bind[5].length= &ts4_length;
+
+ my_bind[6].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[6].buffer= (void *)&ts_6;
+ my_bind[6].buffer_length= sizeof(ts_6);
+ my_bind[6].length= &ts6_length;
+
+ rc= my_stmt_result(mysql, "SELECT * FROM test_bind_result");
+ FAIL_UNLESS(rc == 1, "Expected 1 row");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ ts_4[0]= '\0';
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(strcmp(date, "2002-01-02") == 0, "date != '2002-01-02'");
+ FAIL_UNLESS(d_length == 10, "d_length != 10");
+
+ FAIL_UNLESS(strcmp(my_time, "12:49:00") == 0, "mytime != '12:49:00'");
+ FAIL_UNLESS(t_length == 8, "t_length != 8");
+
+ FAIL_UNLESS(strcmp(ts, "2002-01-02 17:46:59") == 0, "ts != '2002-01-02 17:46:59'");
+ FAIL_UNLESS(ts_length == 19, "ts_length != 19");
+
+ FAIL_UNLESS(strcmp(dt, "2010-07-10 00:00:00") == 0, "dt != 2010-07-10 00:00:00");
+ FAIL_UNLESS(dt_length == 19, "dt_length != 19");
+
+ FAIL_UNLESS(strcmp(ts_4, "0000-00-00 00:00:00") == 0, "ts4 != '0000-00-00 00:00:00'");
+ FAIL_UNLESS(ts4_length == strlen("0000-00-00 00:00:00"), "ts4_length != 19");
+
+ FAIL_UNLESS(strcmp(ts_6, "1999-12-29 00:00:00") == 0, "ts_6 != '1999-12-29 00:00:00'");
+ FAIL_UNLESS(ts6_length == 19, "ts6_length != 19");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Test fetching of str to all types */
+
+static int test_fetch_str(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 char(10), \
+ c2 char(10), \
+ c3 char(20), \
+ c4 char(20), \
+ c5 char(30), \
+ c6 char(40), \
+ c7 char(20))");
+ check_mysql_rc(rc, mysql);
+
+ rc= bind_fetch(mysql, 3);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ return rc;
+}
+
+/* Test fetching of long to all types */
+
+static int test_fetch_long(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 int unsigned, \
+ c2 int unsigned, \
+ c3 int, \
+ c4 int, \
+ c5 int, \
+ c6 int unsigned, \
+ c7 int)");
+ check_mysql_rc(rc, mysql);
+ rc= bind_fetch(mysql, 4);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ return rc;
+}
+
+
+/* Test fetching of short to all types */
+
+static int test_fetch_short(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 smallint unsigned, \
+ c2 smallint, \
+ c3 smallint unsigned, \
+ c4 smallint, \
+ c5 smallint, \
+ c6 smallint, \
+ c7 smallint unsigned)");
+ check_mysql_rc(rc, mysql);
+ rc= bind_fetch(mysql, 5);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ return rc;
+}
+
+
+/* Test fetching of tiny to all types */
+
+static int test_fetch_tiny(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 tinyint unsigned, \
+ c2 tinyint, \
+ c3 tinyint unsigned, \
+ c4 tinyint, \
+ c5 tinyint, \
+ c6 tinyint, \
+ c7 tinyint unsigned)");
+ check_mysql_rc(rc, mysql);
+ rc= bind_fetch(mysql, 3);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ return rc;
+}
+
+
+/* Test fetching of longlong to all types */
+
+static int test_fetch_bigint(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 bigint, \
+ c2 bigint, \
+ c3 bigint unsigned, \
+ c4 bigint unsigned, \
+ c5 bigint unsigned, \
+ c6 bigint unsigned, \
+ c7 bigint unsigned)");
+ check_mysql_rc(rc, mysql);
+ rc= bind_fetch(mysql, 2);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ return rc;
+}
+
+
+/* Test fetching of float to all types */
+
+static int test_fetch_float(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 float(3), \
+ c2 float, \
+ c3 float unsigned, \
+ c4 float, \
+ c5 float, \
+ c6 float, \
+ c7 float(10) unsigned)");
+ check_mysql_rc(rc, mysql);
+
+ rc= bind_fetch(mysql, 2);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ return rc;
+}
+
+
+/* Test fetching of double to all types */
+
+static int test_fetch_double(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 double(5, 2), "
+ "c2 double unsigned, c3 double unsigned, "
+ "c4 double unsigned, c5 double unsigned, "
+ "c6 double unsigned, c7 double unsigned)");
+ check_mysql_rc(rc, mysql);
+ rc= bind_fetch(mysql, 3);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
+ return rc;
+}
+
+static int test_conc281(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_BIND bind[2];
+ unsigned long length= 0;
+ char buffer[2048];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc282");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE conc282 (a blob, b varchar(1000), c int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO conc282 VALUES (REPEAT('A',2000), REPEAT('B', 999),3)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, "SELECT a, b FROM conc282", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 2);
+
+ bind[0].buffer_type= MYSQL_TYPE_BLOB;
+ bind[0].buffer= buffer;
+ bind[0].buffer_length= 2048;
+ bind[0].length= &length;
+
+ rc= mysql_stmt_fetch_column(stmt, &bind[0], 0, 0);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(length != 2000, "Expected length= 2000");
+ FAIL_IF(buffer[0] != 'A' || buffer[1999] != 'A', "Wrong result");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE conc282");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc281", test_conc281, 1, 0, NULL, NULL},
+ {"test_fetch_seek", test_fetch_seek, 1, 0, NULL , NULL},
+ {"test_fetch_offset", test_fetch_offset, 1, 0, NULL , NULL},
+ {"test_fetch_column", test_fetch_column, 1, 0, NULL , NULL},
+ {"test_fetch_nobuffs", test_fetch_nobuffs, 1, 0, NULL , NULL},
+ {"test_fetch_null", test_fetch_null, 1, 0, NULL , NULL},
+ {"test_fetch_date", test_fetch_date, 1, 0, NULL , NULL},
+ {"test_fetch_str", test_fetch_str, 1, 0, NULL , NULL},
+ {"test_fetch_long", test_fetch_long, 1, 0, NULL , NULL},
+ {"test_fetch_short", test_fetch_short, 1, 0, NULL , NULL},
+ {"test_fetch_tiny", test_fetch_tiny, 1, 0, NULL , NULL},
+ {"test_fetch_bigint", test_fetch_bigint, 1, 0, NULL , NULL},
+ {"test_fetch_float", test_fetch_float, 1, 0, NULL , NULL},
+ {"test_fetch_double", test_fetch_double, 1, 0, NULL , NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/fingerprint.list.in b/libmariadb/unittest/libmariadb/fingerprint.list.in
new file mode 100644
index 00000000..06f2be28
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/fingerprint.list.in
@@ -0,0 +1,4 @@
+86DD6D764C0CA47C5014E1E7802674BFDB674ED3
+@SSL_CERT_FINGER_PRINT@
+73F1FEC1FE041473563BFF2D624B88F6CFCFE626
+
diff --git a/libmariadb/unittest/libmariadb/getopt.c b/libmariadb/unittest/libmariadb/getopt.c
new file mode 100644
index 00000000..50debeff
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/getopt.c
@@ -0,0 +1,742 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+ Free Software Foundation, Inc.
+
+Changes by monty:
+- Added include of string.h when necessary.
+- Removed two warnings from gcc.
+
+This file is part of the GNU C Library. Its master source is NOT part of
+the C library, however. The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if (!defined (__STDC__) || !__STDC__) && !defined(MSDOS) && !defined(OS2)
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <ma_global.h> /* Changes for mysys */
+#include <ma_string.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "ma_getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+static char *
+my_index (const char *str, int chr)
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (char **argv)
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (const char *optstring)
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only)
+{
+ optarg = NULL;
+
+ if (optind == 0)
+ optstring = _getopt_initialize (optstring);
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound=0; /* Keep gcc happy */
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((size_t) (nameend - nextchar) == (size_t) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+ else
+ fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/libmariadb/unittest/libmariadb/logs.c b/libmariadb/unittest/libmariadb/logs.c
new file mode 100644
index 00000000..60554a06
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/logs.c
@@ -0,0 +1,223 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+
+#ifdef ENABLE_IF_IN_USE
+static int enable_general_log(MYSQL *mysql, int truncate)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "set @save_global_general_log=@@global.general_log");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "set @@global.general_log=on");
+ check_mysql_rc(rc, mysql);
+
+ if (truncate)
+ {
+ rc= mysql_query(mysql, "truncate mysql.general_log");
+ check_mysql_rc(rc, mysql);
+ }
+
+ return OK;
+}
+
+
+static int restore_general_log(MYSQL *mysql)
+{
+ int rc;
+ rc= mysql_query(mysql, "set @@global.general_log=@save_global_general_log");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+#endif
+
+/* Test update/binary logs */
+
+static int test_logs(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ char data[255];
+ size_t length;
+ int rc;
+ short id;
+
+ rc= mysql_query(mysql, "SET session sql_mode=''");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_logs");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_logs(id smallint, name varchar(20))");
+ check_mysql_rc(rc, mysql);
+
+ strcpy((char *)data, "INSERT INTO test_logs VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(data));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[0].buffer= (void *)&id;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)&data;
+ my_bind[1].buffer_length= 255;
+ my_bind[1].length= (unsigned long *)&length;
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ id= 9876;
+ strcpy((char *)data, "MySQL - Open Source Database");
+ length= strlen(data);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ strcpy((char *)data, "'");
+ length= 1;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ strcpy((char *)data, "\"");
+ length= 1;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ strcpy((char *)data, "my\'sql\'");
+ length= strlen(data);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ strcpy((char *)data, "my\"sql\"");
+ length= strlen(data);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ strcpy((char *)data, "INSERT INTO test_logs VALUES(20, 'mysql')");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(data));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ strcpy((char *)data, "SELECT * FROM test_logs WHERE id=?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(data));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ my_bind[1].buffer_length= 255;
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(id == 9876, "id != 9876");
+ FAIL_UNLESS(length == 19 || length == 20, "Invalid Length"); /* Due to VARCHAR(20) */
+ FAIL_UNLESS(strncmp(data, "MySQL - Open Source", 19) == 0, "data != 'MySQL - Open Source'");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(length == 1, "length != 1");
+ FAIL_UNLESS(strcmp(data, "'") == 0, "data != '''");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(length == 1, "length != 1");
+ FAIL_UNLESS(strcmp(data, "\"") == 0, "data != '\"'");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(length == 7, "length != 7");
+ FAIL_UNLESS(strcmp(data, "my\'sql\'") == 0, "data != my'sql'");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(length == 7, "length != 7");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE test_logs");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+struct my_tests_st my_tests[] = {
+ {"test_logs", test_logs, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/ma_getopt.c b/libmariadb/unittest/libmariadb/ma_getopt.c
new file mode 100644
index 00000000..186cdcd5
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/ma_getopt.c
@@ -0,0 +1,741 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+ Free Software Foundation, Inc.
+
+Changes by monty:
+- Added include of string.h when necessary.
+- Removed two warnings from gcc.
+
+This file is part of the GNU C Library. Its master source is NOT part of
+the C library, however. The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if (!defined (__STDC__) || !__STDC__) && !defined(MSDOS) && !defined(OS2)
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "ma_getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+static char *
+my_index (const char *str, int chr)
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (char **argv)
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (const char *optstring)
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only)
+{
+ optarg = NULL;
+
+ if (optind == 0)
+ optstring = _getopt_initialize (optstring);
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound=0; /* Keep gcc happy */
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((size_t) (nameend - nextchar) == (size_t) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+ else
+ fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/libmariadb/unittest/libmariadb/ma_getopt.h b/libmariadb/unittest/libmariadb/ma_getopt.h
new file mode 100644
index 00000000..e169e829
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/ma_getopt.h
@@ -0,0 +1,131 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+This file is part of the GNU C Library. Its master source is NOT part of
+the C library, however. The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__ || defined(__cplusplus)
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if ( defined (__STDC__) && __STDC__ ) || defined(__cplusplus) || defined(MSDOS)
+#ifdef __EMX__
+int getopt (int, char **, __const__ char *);
+#elif defined( __GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt (int argc, char *const *argv, const char *optstring);
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt (int argc, char *const *argv, const char *optstring);
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/libmariadb/unittest/libmariadb/misc.c b/libmariadb/unittest/libmariadb/misc.c
new file mode 100644
index 00000000..f67d1366
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/misc.c
@@ -0,0 +1,1689 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+#include "ma_common.h"
+
+#include <mysql/client_plugin.h>
+
+
+/*
+ Bug#28075 "COM_DEBUG crashes mysqld"
+*/
+#ifdef _WIN32
+#define R_OK 4
+#endif
+
+static int test_bug28075(MYSQL *mysql)
+{
+ int rc;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+ SKIP_XPAND;
+
+ rc= mysql_dump_debug_info(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_ping(mysql);
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ Bug#28505: mysql_affected_rows() returns wrong value if CLIENT_FOUND_ROWS
+ flag is set.
+*/
+
+static int test_bug28505(MYSQL *mysql)
+{
+ unsigned long long res;
+ int rc;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1(f1 int primary key)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values(1)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values(1) on duplicate key update f1=1");
+ check_mysql_rc(rc, mysql);
+ res= mysql_affected_rows(mysql);
+ FAIL_UNLESS(!res, "res != 0");
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ Bug #29692 Single row inserts can incorrectly report a huge number of
+ row insertions
+*/
+
+static int test_bug29692(MYSQL *mysql)
+{
+ int rc;
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1(f1 int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values(1)");
+ check_mysql_rc(rc, mysql);
+ FAIL_UNLESS(1 == mysql_affected_rows(mysql), "affected_rows != 1");
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int bug31418_impl()
+{
+ my_bool is_null;
+ MYSQL *mysql;
+ int rc;
+
+
+ /* Create a new connection. */
+
+ mysql= test_connect(NULL);
+ if (!mysql)
+ return FAIL;
+
+ /***********************************************************************
+ Check that lock is free:
+ - IS_FREE_LOCK() should return 1;
+ - IS_USED_LOCK() should return NULL;
+ ***********************************************************************/
+
+ is_null= query_int_variable(mysql,
+ "IS_FREE_LOCK('bug31418')",
+ &rc);
+ FAIL_UNLESS(!is_null && rc, "rc = 0");
+
+ is_null= query_int_variable(mysql,
+ "IS_USED_LOCK('bug31418')",
+ &rc);
+ FAIL_UNLESS(is_null, "rc = 0");
+
+ /***********************************************************************
+ Acquire lock and check the lock status (the lock must be in use):
+ - IS_FREE_LOCK() should return 0;
+ - IS_USED_LOCK() should return non-zero thread id;
+ ***********************************************************************/
+
+ query_int_variable(mysql, "GET_LOCK('bug31418', 1)", &rc);
+ FAIL_UNLESS(rc, "rc = 0");
+
+ is_null= query_int_variable(mysql,
+ "IS_FREE_LOCK('bug31418')",
+ &rc);
+ FAIL_UNLESS(!is_null && !rc, "rc = 0");
+
+ is_null= query_int_variable(mysql,
+ "IS_USED_LOCK('bug31418')",
+ &rc);
+ FAIL_UNLESS(!is_null && rc, "rc = 0");
+
+ /***********************************************************************
+ Issue COM_CHANGE_USER command and check the lock status
+ (the lock must be free):
+ - IS_FREE_LOCK() should return 1;
+ - IS_USED_LOCK() should return NULL;
+ **********************************************************************/
+
+ rc= mysql_change_user(mysql, username, password, schema ? schema : "test");
+ check_mysql_rc(rc, mysql);
+
+ is_null= query_int_variable(mysql,
+ "IS_FREE_LOCK('bug31418')",
+ &rc);
+ FAIL_UNLESS(!is_null && rc, "rc = 0");
+
+ is_null= query_int_variable(mysql,
+ "IS_USED_LOCK('bug31418')",
+ &rc);
+ FAIL_UNLESS(is_null, "rc = 0");
+
+ /***********************************************************************
+ That's it. Cleanup.
+ ***********************************************************************/
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_bug31418(MYSQL *unused __attribute__((unused)))
+{
+ int i;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+ /* Run test case for BUG#31418 for three different connections. */
+
+ for (i=0; i < 3; i++)
+ if (bug31418_impl())
+ return FAIL;
+
+ return OK;
+}
+
+/* Query processing */
+
+static int test_debug_example(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_debug_example");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_debug_example("
+ "id INT PRIMARY KEY AUTO_INCREMENT, "
+ "name VARCHAR(20), xxx INT)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_debug_example (name) "
+ "VALUES ('mysql')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "UPDATE test_debug_example SET name='updated' "
+ "WHERE name='deleted'");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT * FROM test_debug_example where name='mysql'");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_use_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ while (mysql_fetch_row(result));
+ mysql_free_result(result);
+
+ rc= mysql_query(mysql, "DROP TABLE test_debug_example");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ Test a crash when invalid/corrupted .frm is used in the
+ SHOW TABLE STATUS
+ bug #93 (reported by serg@mysql.com).
+*/
+
+static int test_frm_bug(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ FILE *test_file;
+ char data_dir[FN_REFLEN];
+ char test_frm[1024];
+ int rc;
+
+ SKIP_MYSQL(mysql);
+ SKIP_XPAND;
+
+ mysql_autocommit(mysql, TRUE);
+
+ rc= mysql_query(mysql, "drop table if exists test_frm_bug");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "flush tables");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("show variables like 'datadir'"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= data_dir;
+ my_bind[0].buffer_length= FN_REFLEN;
+ my_bind[1]= my_bind[0];
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ snprintf(test_frm, sizeof(test_frm)-1, "%s/%s/test_frm_bug.frm", data_dir, schema);
+
+ if (!(test_file= fopen(test_frm, "w")))
+ {
+ mysql_stmt_close(stmt);
+ diag("Can't write to file %s -> SKIP", test_frm);
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "SHOW TABLE STATUS like 'test_frm_bug'");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");/* It can't be NULL */
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ mysql_data_seek(result, 0);
+
+ row= mysql_fetch_row(result);
+ FAIL_IF(!row, "couldn't fetch row");
+
+ FAIL_UNLESS(row[17] != 0, "row[17] != 0");
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ fclose(test_file);
+ mysql_query(mysql, "drop table if exists test_frm_bug");
+ unlink(test_frm);
+ return OK;
+}
+
+static int test_wl4166_1(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int int_data;
+ char str_data[50];
+ char tiny_data;
+ short small_data;
+ longlong big_data;
+ float real_data;
+ double double_data;
+ ulong length[7];
+ my_bool is_null[7];
+ MYSQL_BIND my_bind[7];
+ const char *query;
+ int rc;
+ int i;
+
+ if (mysql_get_server_version(mysql) < 50100) {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS table_4166");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE table_4166(col1 tinyint NOT NULL, "
+ "col2 varchar(15), col3 int, "
+ "col4 smallint, col5 bigint, "
+ "col6 float, col7 double, "
+ "colX varchar(10) default NULL)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ query= "INSERT INTO table_4166(col1, col2, col3, col4, col5, col6, col7) "
+ "VALUES(?, ?, ?, ?, ?, ?, ?)";
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 7, "param_count != 7");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ /* tinyint */
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&tiny_data;
+ /* string */
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)str_data;
+ my_bind[1].buffer_length= 1000; /* Max string length */
+ /* integer */
+ my_bind[2].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[2].buffer= (void *)&int_data;
+ /* short */
+ my_bind[3].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[3].buffer= (void *)&small_data;
+ /* bigint */
+ my_bind[4].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[4].buffer= (void *)&big_data;
+ /* float */
+ my_bind[5].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[5].buffer= (void *)&real_data;
+ /* double */
+ my_bind[6].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[6].buffer= (void *)&double_data;
+
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].length= &length[i];
+ my_bind[i].is_null= &is_null[i];
+ is_null[i]= 0;
+ }
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ int_data= 320;
+ small_data= 1867;
+ big_data= 1000;
+ real_data= 2;
+ double_data= 6578.001;
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (tiny_data= 0; tiny_data < 10; tiny_data++)
+ {
+ length[1]= sprintf(str_data, "MySQL%d", int_data);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ int_data += 25;
+ small_data += 10;
+ big_data += 100;
+ real_data += 1;
+ double_data += 10.09;
+ }
+
+ /* force a re-prepare with some DDL */
+
+ rc= mysql_query(mysql,
+ "ALTER TABLE table_4166 change colX colX varchar(20) default NULL");
+ check_mysql_rc(rc, mysql);
+
+ /*
+ execute the prepared statement again,
+ without changing the types of parameters already bound.
+ */
+
+ for (tiny_data= 50; tiny_data < 60; tiny_data++)
+ {
+ length[1]= sprintf(str_data, "MySQL%d", int_data);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ int_data += 25;
+ small_data += 10;
+ big_data += 100;
+ real_data += 1;
+ double_data += 10.09;
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE table_4166");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+
+static int test_wl4166_2(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int c_int;
+ MYSQL_TIME d_date;
+ MYSQL_BIND bind_out[2];
+ int rc;
+
+ if (mysql_get_server_version(mysql) < 50100) {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (c_int int, d_date date)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "insert into t1 (c_int, d_date) values (42, '1948-05-15')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("select * from t1"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind_out, '\0', sizeof(bind_out));
+ bind_out[0].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[0].buffer= (void*) &c_int;
+
+ bind_out[1].buffer_type= MYSQL_TYPE_DATE;
+ bind_out[1].buffer= (void*) &d_date;
+
+ rc= mysql_stmt_bind_result(stmt, bind_out);
+ check_stmt_rc(rc, stmt);
+
+ /* int -> varchar transition */
+
+ rc= mysql_query(mysql,
+ "alter table t1 change column c_int c_int varchar(11)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(c_int == 42, "c_int != 42");
+ FAIL_UNLESS(d_date.year == 1948, "y!=1948");
+ FAIL_UNLESS(d_date.month == 5, "m != 5");
+ FAIL_UNLESS(d_date.day == 15, "d != 15");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ /* varchar to int retrieval with truncation */
+
+ rc= mysql_query(mysql, "update t1 set c_int='abcde'");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ FAIL_UNLESS(c_int == 0, "c != 0");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ /* alter table and increase the number of columns */
+ rc= mysql_query(mysql, "alter table t1 add column d_int int");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* decrease the number of columns */
+ rc= mysql_query(mysql, "alter table t1 drop d_date, drop d_int");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_stmt_execute(stmt);
+ diag("rc=%d error: %d\n", rc, mysql_stmt_errno(stmt));
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/**
+ Test how warnings generated during assignment of parameters
+ are (currently not) preserve in case of reprepare.
+*/
+
+static int test_wl4166_3(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ MYSQL_TIME tm[1];
+
+ if (mysql_get_server_version(mysql) < 50100) {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (year datetime)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("insert into t1 (year) values (?)"));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "param_count != 1");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_DATETIME;
+ my_bind[0].buffer= &tm[0];
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ tm[0].year= 2014;
+ tm[0].month= 1; tm[0].day= 1;
+ tm[0].hour= 1; tm[0].minute= 1; tm[0].second= 1;
+ tm[0].second_part= 0; tm[0].neg= 0;
+
+ /* Cause a statement reprepare */
+ rc= mysql_query(mysql, "alter table t1 add column c int");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ diag("rc=%d %s", rc, mysql_stmt_error(stmt));
+ check_stmt_rc(rc, stmt);
+
+ if (verify_col_data(mysql, "t1", "year", "2014-01-01 01:01:01")) {
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ return FAIL;
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+
+/**
+ Test that long data parameters, as well as parameters
+ that were originally in a different character set, are
+ preserved in case of reprepare.
+*/
+
+static int test_wl4166_4(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+ MYSQL_BIND bind_array[2];
+
+ /* Represented as numbers to keep UTF8 tools from clobbering them. */
+ const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
+ const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
+ char buf1[16], buf2[16];
+ ulong buf1_len, buf2_len;
+
+ SKIP_XPAND;
+
+ if (mysql_get_server_version(mysql) < 50100) {
+ diag("Test requires MySQL Server version 5.1 or above");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ /*
+ Create table with binary columns, set session character set to cp1251,
+ client character set to koi8, and make sure that there is conversion
+ on insert and no conversion on select
+ */
+ rc= mysql_query(mysql,
+ "create table t1 (c1 varbinary(255), c2 varbinary(255))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "set character_set_client=koi8r, "
+ "character_set_connection=cp1251, "
+ "character_set_results=koi8r");
+ check_mysql_rc(rc, mysql);
+
+ memset(bind_array, '\0', sizeof(bind_array));
+
+ bind_array[0].buffer_type= MYSQL_TYPE_STRING;
+
+ bind_array[1].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[1].buffer= (void *) koi8;
+ bind_array[1].buffer_length= (unsigned long)strlen(koi8);
+
+ stmt= mysql_stmt_init(mysql);
+ check_stmt_rc(rc, stmt);
+
+ stmt_text= "insert into t1 (c1, c2) values (?, ?)";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_bind_param(stmt, bind_array);
+
+ mysql_stmt_send_long_data(stmt, 0, koi8, (unsigned long)strlen(koi8));
+
+ /* Cause a reprepare at statement execute */
+ rc= mysql_query(mysql, "alter table t1 add column d int");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ stmt_text= "select c1, c2 from t1";
+
+ /* c1 and c2 are binary so no conversion will be done on select */
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ bind_array[0].buffer= buf1;
+ bind_array[0].buffer_length= sizeof(buf1);
+ bind_array[0].length= &buf1_len;
+
+ bind_array[1].buffer= buf2;
+ bind_array[1].buffer_length= sizeof(buf2);
+ bind_array[1].length= &buf2_len;
+
+ mysql_stmt_bind_result(stmt, bind_array);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(buf1_len == strlen(cp1251), "");
+ FAIL_UNLESS(buf2_len == strlen(cp1251), "");
+ FAIL_UNLESS(!memcmp(buf1, cp1251, buf1_len), "");
+ FAIL_UNLESS(!memcmp(buf2, cp1251, buf1_len), "");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "set names default");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/**
+ Test that COM_REFRESH issues a implicit commit.
+*/
+
+static int test_wl4284_1(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_ROW row;
+ MYSQL_RES *result;
+
+ diag("Test temporarily disabled");
+ return SKIP;
+
+ if (mysql_get_server_version(mysql) < 60000) {
+ diag("Test requires MySQL Server version 6.0 or above");
+ return SKIP;
+ }
+
+ /* set AUTOCOMMIT to OFF */
+ rc= mysql_autocommit(mysql, FALSE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS trans");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE trans (a INT) ENGINE=InnoDB");
+
+ if (mysql_errno(mysql) == ER_UNKNOWN_STORAGE_ENGINE)
+ {
+ diag("InnoDB not configured or available");
+ return SKIP;
+ }
+
+ check_mysql_rc(rc, mysql);
+
+
+ rc= mysql_query(mysql, "INSERT INTO trans VALUES(1)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_refresh(mysql, REFRESH_GRANT | REFRESH_TABLES);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_rollback(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT * FROM trans");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_use_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ row= mysql_fetch_row(result);
+ FAIL_IF(!row, "Can't fetch row");
+
+ mysql_free_result(result);
+
+ /* set AUTOCOMMIT to OFF */
+ rc= mysql_autocommit(mysql, FALSE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE trans");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug49694(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int i;
+ FILE *fp;
+
+ diag("Load local infile server : %ld", (mysql->server_capabilities & CLIENT_LOCAL_FILES));
+ diag("Load local infile client : %ld", (mysql->client_flag & CLIENT_LOCAL_FILES));
+
+ SKIP_LOAD_INFILE_DISABLE;
+ SKIP_SKYSQL;
+
+ /* XPT-600: local_infile variable not supported */
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "select @@LOCAL_INFILE");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ if (atol(row[0]) == 0) {
+ diag("Load local infile disable");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS enclist");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE `enclist` ("
+ " `pat_id` int(11) NOT NULL,"
+ " `episode_id` int(11) NOT NULL,"
+ " `enc_id` double NOT NULL,"
+ " PRIMARY KEY (`pat_id`,`episode_id`,`enc_id`)"
+ ") ENGINE=MyISAM DEFAULT CHARSET=latin1");
+ check_mysql_rc(rc, mysql);
+
+ fp= fopen("data.csv", "w");
+ FAIL_IF(!fp, "Can't open data.csv");
+
+ for (i=0; i < 100; i++)
+ fprintf (fp, "%.08d,%d,%f\r\n", 100 + i, i % 3 + 1, 60000.0 + i/100);
+ fclose(fp);
+
+ rc= mysql_query(mysql, "LOAD DATA LOCAL INFILE 'data.csv' INTO TABLE enclist "
+ "FIELDS TERMINATED BY '.' LINES TERMINATED BY '\r\n'");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DELETE FROM enclist");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_affected_rows(mysql) != 100, "Import failure. Expected 2 imported rows");
+
+ rc= mysql_query(mysql, "DROP TABLE enclist");
+ check_mysql_rc(rc, mysql);
+ mysql_free_result(res);
+ return OK;
+}
+
+static int test_conc49(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ int i;
+ FILE *fp;
+
+ SKIP_LOAD_INFILE_DISABLE;
+ SKIP_SKYSQL;
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "select @@LOCAL_INFILE");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+
+ i= !atol(row[0]);
+ if (i) {
+ diag("Load local infile disable");
+ mysql_free_result(res);
+ return SKIP;
+ }
+ mysql_free_result(res);
+
+ fp= fopen("./sample.csv", "w");
+ for (i=1; i < 4; i++)
+ fprintf(fp, "\"%d\", \"%d\", \"%d\"\r\n", i, i, i);
+ fclose(fp);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc49");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE conc49 (a int, b int, c int) Engine=InnoDB DEFAULT CHARSET=latin1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "LOAD DATA LOCAL INFILE './sample.csv' INTO TABLE conc49 FIELDS ESCAPED BY ' ' TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\r\n'");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT a FROM conc49");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(res);
+ mysql_free_result(res);
+ FAIL_IF(rc != 3, "3 rows expected");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc49");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_ldi_path(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+
+#ifdef _WIN32
+ rc= mysql_query(mysql, "LOAD DATA LOCAL INFILE 'X:/non_existing_path/data.csv' INTO TABLE t1 "
+ "FIELDS TERMINATED BY '.' LINES TERMINATED BY '\r\n'");
+#else
+ rc= mysql_query(mysql, "LOAD DATA LOCAL INFILE '/non_existing_path/data.csv' INTO TABLE t1 "
+ "FIELDS TERMINATED BY '.' LINES TERMINATED BY '\r\n'");
+#endif
+ FAIL_IF(rc== 0, "Error expected");
+ diag("Error: %d", mysql_errno(mysql));
+ FAIL_IF(mysql_errno(mysql) == 0, "Error expected");
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+#if _WIN32
+static int test_conc44(MYSQL *mysql)
+{
+ char query[1024];
+ char *a_filename= "æøå.csv";
+ int rc;
+ int i;
+ FILE *fp;
+
+ rc= mysql_set_character_set(mysql, "latin1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS enclist");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE `enclist` ("
+ " `pat_id` int(11) NOT NULL,"
+ " `episode_id` int(11) NOT NULL,"
+ " `enc_id` double NOT NULL,"
+ " PRIMARY KEY (`pat_id`,`episode_id`,`enc_id`)"
+ ") ENGINE=MyISAM DEFAULT CHARSET=latin1");
+ check_mysql_rc(rc, mysql);
+
+ fp= fopen(a_filename, "w");
+ FAIL_IF(!fp, "Can't open file");
+
+ for (i=0; i < 100; i++)
+ fprintf (fp, "%.08d,%d,%f\r\n", 100 + i, i % 3 + 1, 60000.0 + i/100);
+ fclose(fp);
+
+ sprintf(query, "LOAD DATA LOCAL INFILE '%s' INTO TABLE enclist "
+ "FIELDS TERMINATED BY '.' LINES TERMINATED BY '\r\n'", a_filename);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DELETE FROM enclist");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_affected_rows(mysql) != 100, "Import failure. Expected 2 imported rows");
+
+ rc= mysql_query(mysql, "DROP TABLE enclist");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+#endif
+
+static int test_connect_attrs(MYSQL *my)
+{
+ MYSQL *mysql;
+ MYSQL_RES *result;
+ int rc, len;
+
+ rc= mysql_query(my, "SELECT * FROM performance_schema.session_connect_attrs LIMIT 1");
+ if (rc != 0)
+ {
+ diag("Server doesn't support connection attributes");
+ return SKIP;
+ }
+
+ result= mysql_store_result(my);
+ /* MariaDB Connector/C already sent connection attrs after handshake. So if the table is
+ empty, it indicates that the performance schema is disabled */
+ if (!mysql_num_rows(result))
+ {
+ diag("skip: performance_schema not enabled");
+ mysql_free_result(result);
+ return SKIP;
+ }
+ mysql_free_result(result);
+
+ mysql= mysql_init(NULL);
+
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo0", "bar0");
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo1", "bar1");
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo2", "bar2");
+
+ FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ if (!(mysql->server_capabilities & CLIENT_CONNECT_ATTRS))
+ {
+ diag("Server doesn't support connection attributes");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "SELECT * FROM performance_schema.session_connect_attrs where attr_name like 'foo%'");
+ check_mysql_rc(rc, mysql);
+ result= mysql_store_result(mysql);
+ rc= (int)mysql_num_rows(result);
+ mysql_free_result(result);
+
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, NULL);
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo0", "bar0");
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo1", "bar1");
+ mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo2", "bar2");
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "foo0");
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "foo1");
+ mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "foo2");
+
+ len= (int)mysql->options.extension->connect_attrs_len;
+
+ mysql_close(mysql);
+
+ FAIL_IF(rc < 3, "Expected 3 or more rows");
+ FAIL_IF(len != 0, "Expected connection_attr_len=0");
+
+ return OK;
+}
+
+static int test_conc_114(MYSQL *mysql)
+{
+ if (mysql_client_find_plugin(mysql, "foo", 0))
+ {
+ diag("Null pointer expected");
+ return FAIL;
+ }
+ diag("Error: %s", mysql_error(mysql));
+ return OK;
+}
+
+/* run with valgrind */
+static int test_conc117(MYSQL *unused __attribute__((unused)))
+{
+ my_bool reconnect= 1;
+ MYSQL *my= mysql_init(NULL);
+ SKIP_MAXSCALE;
+ FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ mysql_kill(my, mysql_thread_id(my));
+
+ mysql_options(my, MYSQL_OPT_RECONNECT, &reconnect);
+
+ mysql_query(my, "SET @a:=1");
+ mysql_close(my);
+
+ return OK;
+}
+
+static int test_read_timeout(MYSQL *unused __attribute__((unused)))
+{
+ int timeout= 5, rc;
+ MYSQL *my= mysql_init(NULL);
+ SKIP_MAXSCALE;
+ mysql_options(my, MYSQL_OPT_READ_TIMEOUT, &timeout);
+ FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ rc= mysql_query(my, "SELECT SLEEP(50)");
+
+ FAIL_IF(rc == 0, "error expected");
+ diag("error: %s", mysql_error(my));
+
+ mysql_close(my);
+
+ return OK;
+}
+
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+#if !__has_feature(memory_sanitizer)
+#ifdef HAVE_REMOTEIO
+void *remote_plugin;
+static int test_remote1(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ SKIP_SKYSQL;
+ SKIP_XPAND;
+
+ remote_plugin= (void *)mysql_client_find_plugin(mysql, "remote_io", MARIADB_CLIENT_REMOTEIO_PLUGIN);
+ if (!remote_plugin)
+ {
+ diag("skip - no remote io plugin available");
+ diag("error: %s", mysql_error(mysql));
+ return SKIP;
+ }
+
+ SKIP_LOAD_INFILE_DISABLE;
+
+ rc= mysql_query(mysql, "select @@LOCAL_INFILE");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ if (atol(row[0]) == 0) {
+ diag("Load local infile disable");
+ return SKIP;
+ }
+ mysql_free_result(res);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a text)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "LOAD DATA LOCAL INFILE 'http://www.example.com' INTO TABLE t1");
+ if (rc && mysql_errno(mysql) == 2058)
+ {
+ diag("remote_io plugin not available");
+ return SKIP;
+ }
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_remote2(MYSQL *my)
+{
+ MYSQL *mysql;
+
+ if (!remote_plugin)
+ {
+ diag("skip - no remote io plugin available");
+ return SKIP;
+ }
+ mysql= mysql_init(NULL);
+
+ mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "http://localhost/test.cnf");
+ mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "test");
+ my_test_connect(mysql, hostname, username, password, schema,
+ 0, socketname, 0), mysql_error(my);
+ diag("port: %d", mysql->port);
+ mysql_close(mysql);
+ return OK;
+}
+#endif
+#endif
+
+#ifndef _WIN32
+static int test_mdev12965(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+ my_bool reconnect = 0;
+ FILE *fp= NULL;
+ const char *env= getenv("MYSQL_TMP_DIR");
+ char cnf_file1[FN_REFLEN + 1];
+
+ SKIP_SKYSQL;
+ if (travis_test)
+ return SKIP;
+
+ if (!env)
+ env= "/tmp";
+
+ setenv("HOME", env, 1);
+
+ snprintf(cnf_file1, FN_REFLEN, "%s%c.my.cnf", env, FN_LIBCHAR);
+
+ diag("Config file: %s", cnf_file1);
+
+ FAIL_IF(!access(cnf_file1, R_OK), "access");
+
+ mysql= mysql_init(NULL);
+ fp= fopen(cnf_file1, "w");
+ FAIL_IF(!fp, "fopen");
+
+ fprintf(fp, "[client]\ndefault-character-set=latin2\nreconnect=1\n");
+ fclose(fp);
+
+ mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
+ my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, 0);
+
+ remove(cnf_file1);
+
+ FAIL_IF(strcmp(mysql_character_set_name(mysql), "latin2"), "expected charset latin2");
+ mysql_get_optionv(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_IF(reconnect != 1, "expected reconnect=1");
+ mysql_close(mysql);
+ return OK;
+}
+#endif
+
+static int test_get_info(MYSQL *mysql)
+{
+ size_t sval;
+ unsigned int ival;
+ char *cval;
+ int rc;
+ MY_CHARSET_INFO cs;
+ MARIADB_CHARSET_INFO *ci;
+ char **errors;
+
+ rc= mariadb_get_infov(mysql, MARIADB_MAX_ALLOWED_PACKET, &sval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("max_allowed_packet: %lu", (unsigned long)sval);
+ rc= mariadb_get_infov(mysql, MARIADB_NET_BUFFER_LENGTH, &sval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("net_buffer_length: %lu", (unsigned long)sval);
+ rc= mariadb_get_infov(mysql, MARIADB_CLIENT_VERSION_ID, &sval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("client_version_id: %lu", (unsigned long)sval);
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_VERSION_ID, &sval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("server_version_id: %lu", (unsigned long)sval);
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_MARIADB_CHARSET_INFO, &cs);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("charset name: %s", cs.csname);
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_PVIO_TYPE, &ival);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("connection type: %d", ival);
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_PROTOCOL_VERSION_ID, &ival);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("protocol_version: %d", ival);
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_TYPE, &cval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("server_type: %s", cval);
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_VERSION, &cval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("server_version: %s", cval);
+ rc= mariadb_get_infov(mysql, MARIADB_CLIENT_VERSION, &cval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("client_version: %s", cval);
+ rc= mariadb_get_infov(mysql, MARIADB_CHARSET_NAME, &ci, "utf8");
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("charset_name: %s", ci->csname);
+ diag("charset_nr: %d", ci->nr);
+ rc= mariadb_get_infov(mysql, MARIADB_CHARSET_ID, &ci, 63);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("charset_name: %s", ci->csname);
+ rc= mariadb_get_infov(mysql, MARIADB_CLIENT_ERRORS, &errors);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("error[0]: %s", errors[0]);
+ rc= mysql_query(mysql, "DROP TABLE IF exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1),(2)");
+ check_mysql_rc(rc, mysql);
+ rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_INFO, &cval);
+ FAIL_IF(rc, "mysql_get_info failed");
+ diag("mariadb_info: %s", cval);
+ return OK;
+}
+
+static int test_zerofill(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int(10) zerofill)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT a FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ if ((res= mysql_store_result(mysql)))
+ {
+ row= mysql_fetch_row(res);
+ diag("zerofill: %s", row[0]);
+ mysql_free_result(res);
+ }
+ return OK;
+}
+
+static int test_server_status(MYSQL *mysql)
+{
+ int rc;
+ unsigned int server_status;
+// MYSQL_STMT *stmt;
+
+ if (mysql_get_server_version(mysql) < 100200)
+ return SKIP;
+
+// stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_autocommit(mysql, 1);
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_STATUS, &server_status);
+ FAIL_IF(!(server_status & SERVER_STATUS_AUTOCOMMIT),
+ "autocommit flag not set");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "UPDATE t1 SET a=9 WHERE a=8");
+ check_mysql_rc(rc, mysql);
+
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_STATUS, &server_status);
+ FAIL_IF(!(server_status & SERVER_QUERY_NO_INDEX_USED), "autocommit flag not set");
+
+ rc= mysql_query(mysql, "CREATE SCHEMA test_tmp");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_select_db(mysql, "test_tmp");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP SCHEMA test_tmp");
+ check_mysql_rc(rc, mysql);
+
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_STATUS, &server_status);
+ FAIL_IF(!(server_status & SERVER_STATUS_DB_DROPPED),
+ "DB_DROP flag not set");
+
+ FAIL_IF(!(server_status & SERVER_SESSION_STATE_CHANGED),
+ "SESSION_STATE_CHANGED flag not set");
+
+ rc= mysql_select_db(mysql, schema);
+ check_mysql_rc(rc, mysql);
+
+// mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_wl6797(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+ my_ulonglong res;
+
+ if (mysql_get_server_version(mysql) < 50703 ||
+ (mariadb_connection(mysql) && mysql_get_server_version(mysql) < 100203))
+ {
+ diag("Skipping test_wl6797: "
+ "tested feature does not exist in versions before MySQL 5.7.3 and MariaDB 10.2\n");
+ return OK;
+ }
+ /* clean up the session */
+ rc= mysql_reset_connection(mysql);
+ FAIL_UNLESS(rc == 0, "");
+
+ /* do prepare of a query */
+ mysql_query(mysql, "use test");
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ mysql_query(mysql, "CREATE TABLE t1 (a int)");
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "INSERT INTO t1 VALUES (1), (2)";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ /* Execute the insert statement */
+ rc= mysql_stmt_execute(stmt);
+ check_mysql_rc(rc, mysql);
+
+ /*
+ clean the session this should remove the prepare statement
+ from the cache.
+ */
+ rc= mysql_reset_connection(mysql);
+ FAIL_UNLESS(rc == 0, "");
+
+ /* this below stmt should report error */
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(rc == 0, "");
+
+ /*
+ bug#17653288: MYSQL_RESET_CONNECTION DOES NOT RESET LAST_INSERT_ID
+ */
+
+ mysql_query(mysql, "DROP TABLE IF EXISTS t2");
+ rc= mysql_query(mysql, "CREATE TABLE t2 (a int NOT NULL PRIMARY KEY"\
+ " auto_increment)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t2 VALUES (null)");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 1, "");
+ rc= mysql_reset_connection(mysql);
+ FAIL_UNLESS(rc == 0, "");
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+
+ rc= mysql_query(mysql, "INSERT INTO t2 VALUES (last_insert_id(100))");
+ check_mysql_rc(rc, mysql);
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 100, "");
+ rc= mysql_reset_connection(mysql);
+ FAIL_UNLESS(rc == 0, "");
+ res= mysql_insert_id(mysql);
+ FAIL_UNLESS(res == 0, "");
+
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ mysql_query(mysql, "DROP TABLE IF EXISTS t2");
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_conc384(MYSQL *my __attribute__((unused)))
+{
+ char value[1000];
+ int len;
+ MYSQL *mysql= mysql_init(NULL);
+
+ memset(&value, 'A', 999);
+ value[999]= 0;
+
+ mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "foo", value);
+ len= (int)mysql->options.extension->connect_attrs_len;
+ /* Length: 1 (=len) + 3 (="foo") + 3 (=len) + 999 (="AAA...") = 1006 */
+ FAIL_IF(len != 1006, "Wrong length");
+ mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_DELETE, "foo");
+ len= (int)mysql->options.extension->connect_attrs_len;
+ /* Length should be zero after deleting the connection attribute */
+ FAIL_IF(len != 0, "Wrong length");
+ mysql_close(mysql);
+ return OK;
+}
+
+#ifndef _WIN32
+static int test_conc395(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+ FILE *fp= NULL;
+ const char *env= getenv("MYSQL_TMP_DIR");
+ char cnf_file1[FN_REFLEN + 1];
+
+ SKIP_SKYSQL;
+ if (travis_test)
+ return SKIP;
+
+ if (!env)
+ env= "/tmp";
+
+ setenv("HOME", env, 1);
+
+ snprintf(cnf_file1, FN_REFLEN, "%s%c.my.cnf", env, FN_LIBCHAR);
+
+ FAIL_IF(!access(cnf_file1, R_OK), "access");
+
+ mysql= mysql_init(NULL);
+ fp= fopen(cnf_file1, "w");
+ FAIL_IF(!fp, "fopen");
+
+ /* Mix dash and underscore */
+ fprintf(fp, "[client]\ndefault_character-set=latin2\n");
+ fclose(fp);
+
+ mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
+ my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, 0);
+
+ remove(cnf_file1);
+
+ FAIL_IF(strcmp(mysql_character_set_name(mysql), "latin2"), "expected charset latin2");
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_sslenforce(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+ FILE *fp= NULL;
+ const char *env= getenv("MYSQL_TMP_DIR");
+ char cnf_file1[FN_REFLEN + 1];
+
+ SKIP_NOTLS;
+ SKIP_SKYSQL;
+
+ if (travis_test)
+ return SKIP;
+
+ if (!env)
+ env= "/tmp";
+ setenv("HOME", env, 1);
+
+ snprintf(cnf_file1, FN_REFLEN, "%s%c.my.cnf", env, FN_LIBCHAR);
+
+ FAIL_IF(!access(cnf_file1, R_OK), "access");
+
+ mysql= mysql_init(NULL);
+ fp= fopen(cnf_file1, "w");
+ FAIL_IF(!fp, "fopen");
+
+ /* Mix dash and underscore */
+ fprintf(fp, "[client]\nssl_enforce=1\n");
+ fclose(fp);
+
+ mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "");
+ my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, 0);
+
+ remove(cnf_file1);
+
+ FAIL_IF(!mysql_get_ssl_cipher(mysql), "no secure connection");
+ mysql_close(mysql);
+ return OK;
+}
+#endif
+
+#if !__has_feature(memory_sanitizer)
+static int test_conc457(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+
+ SKIP_MYSQL(mysql);
+
+ result= mysql_list_processes(mysql);
+
+ FAIL_IF(mysql_field_count(mysql) != 9, "expected 9 columns");
+ mysql_free_result(result);
+ return OK;
+}
+#endif
+
+static int test_conc458(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ FAIL_IF(mysql_get_timeout_value(mysql) != 0, "expected timeout 0");
+ mysql_close(mysql);
+ return OK;
+}
+
+
+static int test_conc533(MYSQL *mysql)
+{
+ my_bool skip= 1;
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char buffer[10];
+
+ rc= mysql_options(mysql, MARIADB_OPT_SKIP_READ_RESPONSE, &skip);
+
+ rc= mysql_real_query(mysql, SL("SELECT 1"));
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql->methods->db_read_query_result(mysql);
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+
+ FAIL_IF(strcmp(row[0], "1"), "Expected value \"1\"");
+ mysql_free_result(result);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL("SELECT 1"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql->methods->db_read_prepare_response(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_field_count(stmt) != 1, "Expected field_count= 1");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql->methods->db_read_execute_response(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer= buffer;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer_length= 10;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(strcmp(buffer, "1"), "Expected value \"1\"");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+int display_extended_field_attribute(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ MYSQL_FIELD *fields;
+
+ if (mysql_query(mysql, "CREATE TEMPORARY TABLE t1 (a POINT)"))
+ return 1;
+
+ if (mysql_query(mysql, "SELECT a FROM t1"))
+ return 1;
+
+ if (!(result= mysql_store_result(mysql)))
+ return 1;
+
+ if ((fields= mysql_fetch_fields(result)))
+ {
+ MARIADB_CONST_STRING field_attr;
+
+ if (!mariadb_field_attr(&field_attr, &fields[0],
+ MARIADB_FIELD_ATTR_DATA_TYPE_NAME))
+ {
+ printf("Extended field attribute: %s\n", field_attr.str);
+ }
+ }
+ mysql_free_result(result);
+ return 0;
+}
+
+
+static int test_ext_field_attr(MYSQL *mysql)
+{
+ display_extended_field_attribute(mysql);
+
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_ext_field_attr", test_ext_field_attr, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc533", test_conc533, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc458", test_conc458, TEST_CONNECTION_NONE, 0, NULL, NULL},
+#if !__has_feature(memory_sanitizer)
+ {"test_conc457", test_conc457, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+#endif
+ {"test_conc384", test_conc384, TEST_CONNECTION_NONE, 0, NULL, NULL},
+#ifndef _WIN32
+ {"test_mdev12965", test_mdev12965, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc395", test_conc395, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_sslenforce", test_sslenforce, TEST_CONNECTION_NONE, 0, NULL, NULL},
+#endif
+ {"test_wl6797", test_wl6797, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_server_status", test_server_status, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_read_timeout", test_read_timeout, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_zerofill", test_zerofill, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+#if !__has_feature(memory_sanitizer)
+#ifdef HAVE_REMOTEIO
+ {"test_remote1", test_remote1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_remote2", test_remote2, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#endif
+#endif
+ {"test_get_info", test_get_info, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc117", test_conc117, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc_114", test_conc_114, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_connect_attrs", test_connect_attrs, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc49", test_conc49, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_bug28075", test_bug28075, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug28505", test_bug28505, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_debug_example", test_debug_example, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug29692", test_bug29692, TEST_CONNECTION_NEW, CLIENT_FOUND_ROWS, NULL, NULL},
+ {"test_bug31418", test_bug31418, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_frm_bug", test_frm_bug, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_wl4166_1", test_wl4166_1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_wl4166_2", test_wl4166_2, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_wl4166_3", test_wl4166_3, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_wl4166_4", test_wl4166_4, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_wl4284_1", test_wl4284_1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_bug49694", test_bug49694, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_ldi_path", test_ldi_path, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#ifdef _WIN32
+ {"test_conc44", test_conc44, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#endif
+ {NULL, NULL, 0, 0, NULL, 0}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/my_test.h b/libmariadb/unittest/libmariadb/my_test.h
new file mode 100644
index 00000000..9f75d67a
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/my_test.h
@@ -0,0 +1,770 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include <ma_global.h>
+#include <ma_sys.h>
+#include <mysql.h>
+#include <tap.h>
+#include "ma_getopt.h"
+#include <memory.h>
+#include <string.h>
+#include <errmsg.h>
+#include <stdlib.h>
+#include <ma_server_error.h>
+#include <mysql/client_plugin.h>
+#include <errmsg.h>
+
+#ifndef WIN32
+#include <pthread.h>
+#else
+#include <io.h>
+#define unlink _unlink
+#endif
+
+#ifndef OK
+# define OK 0
+#endif
+#ifndef FAIL
+# define FAIL 1
+#endif
+#ifndef SKIP
+# define SKIP -1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#define IS_SKYSQL(a) ((a) && strstr((a), "skysql.mariadb.com"))
+#define SKIP_SKYSQL \
+if (IS_SKYSQL(hostname)) \
+{ \
+ diag("Not supported by SkySQL"); \
+ return SKIP; \
+}
+
+#ifndef HAVE_SSL
+#define SKIP_NOTLS \
+{ \
+ diag("TLS not supported"); \
+ return SKIP;\
+}
+#else
+#define SKIP_NOTLS
+#endif
+
+#define SKIP_TLS \
+if (force_tls)\
+{\
+ diag("Test doesn't work with TLS");\
+ return SKIP;\
+}
+
+MYSQL *mysql_default = NULL; /* default connection */
+
+#define IS_MAXSCALE()\
+ ((mysql_default && strstr(mysql_get_server_info(mysql_default), "maxScale")) ||\
+ (getenv("srv")!=NULL && (strcmp(getenv("srv"), "maxscale") == 0 ||\
+ strcmp(getenv("srv"), "skysql-ha") == 0)))
+
+#define SKIP_MAXSCALE \
+if (IS_MAXSCALE()) \
+{ \
+ diag("test disabled with maxscale"); \
+ return SKIP; \
+}
+
+#define IS_XPAND()\
+ ((mysql_default && strstr(mysql_get_server_info(mysql_default), "Xpand")) ||\
+ (getenv("srv")!=NULL && strcmp(getenv("srv"), "xpand") == 0))
+
+#define SKIP_XPAND \
+if (IS_XPAND()) \
+{ \
+ diag("test disabled with Xpand"); \
+ return SKIP; \
+}
+
+#define SKIP_LOAD_INFILE_DISABLE \
+if (!((mysql->server_capabilities & CLIENT_LOCAL_FILES) && \
+ (mysql->options.client_flag & CLIENT_LOCAL_FILES)) || \
+ IS_XPAND()) { \
+ diag("Load local infile not supported"); \
+ return SKIP; \
+}
+
+#define MAX_KEY MAX_INDEXES
+#define MAX_KEY_LENGTH_DECIMAL_WIDTH 4 /* strlen("4096") */
+
+#define SL(s) (s), (unsigned long)strlen((s))
+#define SL_BIN(s) (s), (unsigned long)sizeof((s))
+
+#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
+
+/* prevent warnings on Win64 by using STMT_LEN instead of strlen */
+#define STMT_LEN(A) ((unsigned long)strlen((A)))
+
+#define SKIP_TRAVIS()\
+do {\
+ if (getenv("TRAVIS"))\
+ {\
+ diag("Skip test on Travis CI");\
+ return SKIP;\
+ }\
+}while(0)
+
+#define SKIP_MYSQL(mysql)\
+do {\
+ if (!mariadb_connection(mysql))\
+ {\
+ diag("Skip test for non MariaDB server");\
+ return OK;\
+ }\
+} while(0)
+
+#define check_mysql_rc(rc, mysql) \
+do {\
+ if (rc)\
+ {\
+ diag("Error (%d): %s (%d) in %s line %d", rc, mysql_error(mysql), \
+ mysql_errno(mysql), __FILE__, __LINE__);\
+ return(FAIL);\
+ }\
+} while(0)
+
+#define check_stmt_rc(rc, stmt) \
+do {\
+ if (rc)\
+ {\
+ diag("Error: %s (%s: %d)", mysql_stmt_error(stmt), __FILE__, __LINE__);\
+ return(FAIL);\
+ }\
+} while(0)
+
+#define FAIL_IF(expr, reason)\
+do {\
+ if (expr)\
+ {\
+ diag("Error: %s (%s: %d)", reason, __FILE__, __LINE__);\
+ return FAIL;\
+ }\
+} while(0)
+
+#define FAIL_UNLESS(expr, reason)\
+do {\
+ if (!(expr))\
+ {\
+ diag("Error: %s (%s: %d)", reason, __FILE__, __LINE__);\
+ return FAIL;\
+ }\
+} while(0)
+
+#define SKIP_CONNECTION_HANDLER \
+do {\
+ if (hostname && strstr(hostname, "://"))\
+ {\
+ diag("Test skipped (connection handler)");\
+ return SKIP;\
+ }\
+} while(0)
+
+/* connection options */
+#define TEST_CONNECTION_DEFAULT 1 /* default connection */
+#define TEST_CONNECTION_NONE 2 /* tests creates own connection */
+#define TEST_CONNECTION_NEW 4 /* create a separate connection */
+#define TEST_CONNECTION_DONT_CLOSE 8 /* don't close connection */
+
+struct my_option_st
+{
+ enum mysql_option option;
+ char *value;
+};
+
+struct my_tests_st
+{
+ const char *name;
+ int (*function)(MYSQL *);
+ int connection;
+ ulong connect_flags;
+ struct my_option_st *options;
+ const char *skipmsg;
+};
+
+MYSQL *my_test_connect(MYSQL *mysql,
+ const char *host,
+ const char *user,
+ const char *passwd,
+ const char *db,
+ unsigned int port,
+ const char *unix_socket,
+ unsigned long clientflag);
+
+static const char *schema = 0;
+static char *hostname = 0;
+static char *password = 0;
+static unsigned int port = 0;
+static unsigned int ssl_port = 0;
+static char *socketname = 0;
+static char *username = 0;
+static int force_tls= 0;
+static uchar is_mariadb= 0;
+static char *this_host= 0;
+static char *plugindir= 0;
+static unsigned char travis_test= 0;
+/*
+static struct my_option test_options[] =
+{
+ {"schema", 'd', "database to use", (uchar **) &schema, (uchar **) &schema,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
+ 0, 0, 0, 0, 0},
+ {"host", 'h', "Connect to host", (uchar **) &hostname, (uchar **) &hostname,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"password", 'p',
+ "Password to use when connecting to server.", (uchar **) &password, (uchar **) &password,
+ 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"port", 'P', "Port number to use for connection or 0 for default to, in "
+ "order of preference, my.cnf, $MYSQL_TCP_PORT, "
+#if MYSQL_PORT_DEFAULT == 0
+ "/etc/services, "
+#endif
+ "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
+ (uchar **) &port,
+ (uchar **) &port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"socket", 'S', "Socket file to use for connection",
+ (uchar **) &socketname, (uchar **) &socketname, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"user", 'u', "User for login if not current user", (uchar **) &username,
+ (uchar **) &username, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+*/
+#define verify_prepare_field(result,no,name,org_name,type,table,\
+ org_table,db,length,def) \
+ do_verify_prepare_field((result),(no),(name),(org_name),(type), \
+ (table),(org_table),(db),(length),(def), \
+ __FILE__, __LINE__)
+
+int do_verify_prepare_field(MYSQL_RES *result,
+ unsigned int no, const char *name,
+ const char *org_name,
+ enum enum_field_types type __attribute__((unused)),
+ const char *table,
+ const char *org_table, const char *db,
+ unsigned long length __attribute__((unused)),
+ const char *def __attribute__((unused)),
+ const char *file __attribute__((unused)),
+ int line __attribute__((unused)))
+{
+ MYSQL_FIELD *field;
+/* MARIADB_CHARSET_INFO *cs; */
+
+ FAIL_IF(!(field= mysql_fetch_field_direct(result, no)), "FAILED to get result");
+/* cs= mysql_find_charset_nr(field->charsetnr);
+ FAIL_UNLESS(cs, "Couldn't get character set"); */
+ FAIL_UNLESS(strcmp(field->name, name) == 0, "field->name differs");
+ FAIL_UNLESS(strcmp(field->org_name, org_name) == 0, "field->org_name differs");
+/*
+ if ((expected_field_length= length * cs->mbmaxlen) > UINT_MAX32)
+ expected_field_length= UINT_MAX32;
+*/
+ /*
+ XXX: silent column specification change works based on number of
+ bytes a column occupies. So CHAR -> VARCHAR upgrade is possible even
+ for CHAR(2) column if its character set is multibyte.
+ VARCHAR -> CHAR downgrade won't work for VARCHAR(3) as one would
+ expect.
+ */
+// if (cs->char_maxlen == 1)
+// FAIL_UNLESS(field->type == type, "field->type differs");
+ if (table)
+ FAIL_UNLESS(strcmp(field->table, table) == 0, "field->table differs");
+ if (org_table)
+ FAIL_UNLESS(strcmp(field->org_table, org_table) == 0, "field->org_table differs");
+ if (strcmp(field->db,db))
+ diag("%s / %s", field->db, db);
+ FAIL_UNLESS(strcmp(field->db, db) == 0, "field->db differs");
+ /*
+ Character set should be taken into account for multibyte encodings, such
+ as utf8. Field length is calculated as number of characters * maximum
+ number of bytes a character can occupy.
+ */
+
+ return OK;
+}
+
+void get_this_host(MYSQL *mysql)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ if (mysql_query(mysql, "select substr(current_user(), locate('@', current_user())+1)"))
+ return;
+
+ if ((res= mysql_store_result(mysql)))
+ {
+ if ((row= mysql_fetch_row(res)))
+ this_host= strdup(row[0]);
+ mysql_free_result(res);
+ }
+}
+
+/* Prepare statement, execute, and process result set for given query */
+
+int my_stmt_result(MYSQL *mysql, const char *buff)
+{
+ MYSQL_STMT *stmt;
+ int row_count= 0;
+ int rc;
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, buff, (unsigned long)strlen(buff));
+ FAIL_IF(rc, mysql_stmt_error(stmt));
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(rc, mysql_stmt_error(stmt));
+
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ row_count++;
+
+ mysql_stmt_close(stmt);
+
+ return row_count;
+}
+/*
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '?':
+ case 'I':
+ my_print_help(test_options);
+ exit(0);
+ break;
+ }
+ return 0;
+}
+*/
+/* Utility function to verify a particular column data */
+
+int verify_col_data(MYSQL *mysql, const char *table, const char *col,
+ const char *exp_data)
+{
+ static char query[MAX_TEST_QUERY_LENGTH];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc;
+
+ if (table && col)
+ {
+ sprintf(query, "SELECT %s FROM %s LIMIT 1", col, table);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+ }
+ result= mysql_use_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ if (!(row= mysql_fetch_row(result)) || !row[0]) {
+ diag("Failed to get the result");
+ goto error;
+ }
+ if(strcmp(row[0], exp_data)) {
+ diag("Expected %s, got %s", exp_data, row[0]);
+ goto error;
+ }
+ mysql_free_result(result);
+
+ return OK;
+
+error:
+ mysql_free_result(result);
+ return FAIL;
+}
+
+my_bool query_int_variable(MYSQL *con, const char *var_name, int *var_value)
+{
+ MYSQL_RES *rs;
+ MYSQL_ROW row;
+
+ char query_buffer[MAX_TEST_QUERY_LENGTH];
+
+ my_bool is_null;
+
+ sprintf(query_buffer,
+ "SELECT %s",
+ (const char *) var_name);
+
+ FAIL_IF(mysql_query(con, query_buffer), "Query failed");
+ FAIL_UNLESS(rs= mysql_store_result(con), "Invaliid result set");
+ FAIL_UNLESS(row= mysql_fetch_row(rs), "Nothing to fetch");
+
+ is_null= row[0] == NULL;
+
+ if (!is_null)
+ *var_value= atoi(row[0]);
+
+ mysql_free_result(rs);
+
+ return is_null;
+}
+
+static void usage()
+{
+ printf("Execute test with the following options:\n");
+ printf("-h hostname\n");
+ printf("-u username\n");
+ printf("-p password\n");
+ printf("-d database\n");
+ printf("-S socketname\n");
+ printf("-t force use of TLS\n");
+ printf("-P port number\n");
+ printf("? displays this help and exits\n");
+}
+
+void get_options(int argc, char **argv)
+{
+ int c= 0;
+
+ while ((c=getopt(argc,argv, "h:u:p:d:w:P:S:t:?")) >= 0)
+ {
+ switch(c) {
+ case 'h':
+ hostname= optarg;
+ break;
+ case 'u':
+ username= optarg;
+ break;
+ case 'p':
+ password= optarg;
+ break;
+ case 'd':
+ schema= optarg;
+ break;
+ case 'P':
+ port= atoi(optarg);
+ ssl_port=port;
+ break;
+ case 'S':
+ socketname= optarg;
+ break;
+ case 't':
+ force_tls= 1;
+ break;
+ case '?':
+ usage();
+ exit(0);
+ break;
+ default:
+ usage();
+ BAIL_OUT("Unknown option %c\n", c);
+ }
+ }
+}
+
+
+int check_variable(MYSQL *mysql, const char *variable, const char *value)
+{
+ char query[MAX_TEST_QUERY_LENGTH];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ sprintf(query, "SELECT %s", variable);
+ result= mysql_store_result(mysql);
+ if (!result)
+ return FAIL;
+
+ if ((row = mysql_fetch_row(result)))
+ if (strcmp(row[0], value) == 0) {
+ mysql_free_result(result);
+ return OK;
+ }
+ mysql_free_result(result);
+ return FAIL;
+}
+
+/*
+ * function *test_connect
+ *
+ * returns a new connection. This function will be called, if the test doesn't
+ * use default_connection.
+ */
+MYSQL *test_connect(struct my_tests_st *test)
+{
+ MYSQL *mysql;
+ int i= 0, rc;
+ int timeout= 10;
+ my_bool truncation_report= 1;
+ if (!(mysql = mysql_init(NULL))) {
+ BAIL_OUT("Not enough memory available - mysql_init failed");
+ }
+ mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &truncation_report);
+ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
+ if (plugindir)
+ mysql_options(mysql, MYSQL_PLUGIN_DIR, plugindir);
+
+ /* option handling */
+ if (test && test->options) {
+
+ while (test->options[i].option)
+ {
+ if (mysql_options(mysql, test->options[i].option, test->options[i].value)) {
+ diag("Couldn't set option %d. Error (%d) %s", test->options[i].option,
+ mysql_errno(mysql), mysql_error(mysql));
+ mysql_close(mysql);
+ return(NULL);
+ }
+ i++;
+ }
+ }
+ if (!(my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, (test) ? test->connect_flags:0)))
+ {
+ diag("Couldn't establish connection to server %s. Error (%d): %s",
+ hostname, mysql_errno(mysql), mysql_error(mysql));
+ mysql_close(mysql);
+ return(NULL);
+ }
+
+ /* Clear sql_mode when establishing a new connection. */
+ rc= mysql_query(mysql, "SET sql_mode=''");
+ if (rc)
+ {
+ diag("Error (%d): %s (%d) in %s line %d", rc, mysql_error(mysql),
+ mysql_errno(mysql), __FILE__, __LINE__);
+ return(NULL);
+ }
+
+ return(mysql);
+}
+
+static int reset_connection(MYSQL *mysql) {
+ int rc;
+
+ if (is_mariadb && !IS_MAXSCALE())
+ rc= mysql_change_user(mysql, username, password, schema);
+ else
+ rc= mysql_reset_connection(mysql);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "SET sql_mode=''");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ * function get_envvars((
+ *
+ * checks for connection related environment variables
+ */
+void get_envvars() {
+ char *envvar;
+
+ if (!getenv("MYSQLTEST_VARDIR") &&
+ !getenv("MARIADB_CC_TEST"))
+ {
+ skip_all("Tests skipped.\nFor running unittest suite outside of MariaDB server tests,\nplease specify MARIADB_CC_TEST environment variable.");
+ exit(0);
+ }
+
+ if (getenv("TRAVIS_JOB_ID"))
+ travis_test= 1;
+
+ if (!hostname && (envvar= getenv("MYSQL_TEST_HOST")))
+ hostname= envvar;
+
+
+ if (!username)
+ {
+ if ((envvar= getenv("MYSQL_TEST_USER")))
+ username= envvar;
+ else
+ username= (char *)"root";
+ }
+ if (!password && (envvar= getenv("MYSQL_TEST_PASSWD")))
+ password= envvar;
+ if (!schema && (envvar= getenv("MYSQL_TEST_DB")))
+ schema= envvar;
+ if (!schema)
+ schema= "test";
+ if (!port)
+ {
+ if ((envvar= getenv("MYSQL_TEST_PORT")))
+ port= atoi(envvar);
+ else if ((envvar= getenv("MASTER_MYPORT")))
+ port= atoi(envvar);
+ diag("port: %d", port);
+ }
+ if (!ssl_port)
+ {
+ if ((envvar= getenv("MYSQL_TEST_SSL_PORT")))
+ ssl_port= atoi(envvar);
+ else
+ ssl_port = port;
+ diag("ssl_port: %d", ssl_port);
+ }
+
+ if (!force_tls && (envvar= getenv("MYSQL_TEST_TLS")))
+ force_tls= atoi(envvar);
+ if (!socketname)
+ {
+ if ((envvar= getenv("MYSQL_TEST_SOCKET")))
+ socketname= envvar;
+ else if ((envvar= getenv("MASTER_MYSOCK")))
+ socketname= envvar;
+ diag("socketname: %s", socketname);
+ }
+ if ((envvar= getenv("MYSQL_TEST_PLUGINDIR")))
+ plugindir= envvar;
+
+ if (IS_XPAND())
+ {
+
+ }
+}
+
+MYSQL *my_test_connect(MYSQL *mysql,
+ const char *host,
+ const char *user,
+ const char *passwd,
+ const char *db,
+ unsigned int port,
+ const char *unix_socket,
+ unsigned long clientflag)
+{
+ if (force_tls)
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &force_tls);
+ if (!mysql_real_connect(mysql, host, user, passwd, db, port, unix_socket, clientflag))
+ {
+ diag("error: %s", mysql_error(mysql));
+ return NULL;
+ }
+
+ if (mysql && force_tls && !mysql_get_ssl_cipher(mysql))
+ {
+ diag("Error: TLS connection not established");
+ return NULL;
+ }
+ if (!this_host)
+ get_this_host(mysql);
+ return mysql;
+}
+
+
+void run_tests(struct my_tests_st *test) {
+ int i, rc, total=0;
+ MYSQL *mysql;
+
+ while (test[total].function)
+ total++;
+ plan(total);
+
+/* display TLS stats */
+ mysql= mysql_init(NULL);
+ mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
+
+ if (!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0))
+ {
+ BAIL_OUT("Can't establish TLS connection to server.");
+ }
+
+ if (!mysql_query(mysql, "SHOW VARIABLES LIKE '%ssl%'"))
+ {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ diag("TLS server variables");
+ diag("--------------------");
+
+ res= mysql_store_result(mysql);
+ while ((row= mysql_fetch_row(res)))
+ diag("%s: %s", row[0], row[1]);
+ mysql_free_result(res);
+ diag("Cipher in use: %s", mysql_get_ssl_cipher(mysql));
+ diag("--------------------");
+ }
+ mysql_close(mysql);
+
+
+ if ((mysql_default= test_connect(NULL)))
+ {
+ diag("Testing against MySQL Server %s", mysql_get_server_info(mysql_default));
+ diag("Host: %s", mysql_get_host_info(mysql_default));
+ diag("Client library: %s", mysql_get_client_info());
+ is_mariadb= mariadb_connection(mysql_default);
+ }
+ else
+ {
+ BAIL_OUT("Can't connect to a server. Aborting....");
+ }
+
+ for (i=0; i < total; i++) {
+ if (!mysql_default && (test[i].connection & TEST_CONNECTION_DEFAULT))
+ {
+ diag("MySQL server not running");
+ skip(1, "%s", test[i].name);
+ } else if (!test[i].skipmsg) {
+ mysql= mysql_default;
+ if (test[i].connection & TEST_CONNECTION_NEW)
+ mysql= test_connect(&test[i]);
+ if (test[i].connection & TEST_CONNECTION_NONE)
+ mysql= NULL;
+
+ /* run test */
+ rc= test[i].function(mysql);
+
+ if (rc == SKIP)
+ skip(1, "%s", test[i].name);
+ else
+ ok(rc == OK, "%s", test[i].name);
+
+ /* if test failed, close and reopen default connection to prevent
+ errors for further tests */
+ if ((rc == FAIL || mysql_errno(mysql_default)) && (test[i].connection & TEST_CONNECTION_DEFAULT)) {
+ mysql_close(mysql_default);
+ mysql_default= test_connect(&test[i]);
+ }
+ /* clear connection: reset default connection or close extra connection */
+ else if (mysql_default && (test[i].connection & TEST_CONNECTION_DEFAULT)) {
+ if (reset_connection(mysql))
+ return; /* default doesn't work anymore */
+ }
+ else if (mysql && !(test[i].connection & TEST_CONNECTION_DONT_CLOSE))
+ {
+ mysql_close(mysql);
+ }
+ } else {
+ skip(1, "%s", test[i].skipmsg);
+ }
+ }
+ if (this_host)
+ free(this_host);
+
+ if (mysql_default) {
+ diag("close default");
+ mysql_close(mysql_default);
+ }
+}
diff --git a/libmariadb/unittest/libmariadb/performance.c b/libmariadb/unittest/libmariadb/performance.c
new file mode 100644
index 00000000..f99253f7
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/performance.c
@@ -0,0 +1,76 @@
+/*
+Copyright (c) 2016 MariaDB Corporation AB
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+
+/**
+ Some basic tests of the client API.
+*/
+
+#include "my_test.h"
+#include "ma_common.h"
+
+static int perf1(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ const char *stmtstr= "SELECT s.emp_no, s.salary, e.emp_no, e.first_name, e.last_name, e.gender FROM salaries s, employees e WHERE s.emp_no = e.emp_no";
+
+ rc= mysql_select_db(mysql, "employees");
+ if (rc)
+ {
+ diag("Employees database not installed");
+ return SKIP;
+ }
+
+ stmt= mysql_stmt_init(mysql);
+
+ diag("prepare");
+ rc= mysql_stmt_prepare(stmt, SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ diag("execute");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ diag("store");
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ diag("fetch");
+ while (!mysql_stmt_fetch(stmt));
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"perf1", perf1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/ps.c b/libmariadb/unittest/libmariadb/ps.c
new file mode 100644
index 00000000..111ce2a6
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/ps.c
@@ -0,0 +1,5315 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+
+/* Utility function to verify the field members */
+
+static int test_conc97(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ diag("Please run this test manually");
+ return SKIP;
+ stmt= mysql_stmt_init(mysql);
+
+ mysql_close(mysql);
+
+ rc= mysql_stmt_reset(stmt);
+ FAIL_IF(!rc, "Error expected while resetting stmt");
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql= mysql_init(NULL);
+
+ return OK;
+}
+
+static int test_conc83(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL *mysql= mysql_init(NULL);
+ my_bool reconnect= 1;
+
+ const char *query= "SELECT 1,2,3 FROM DUAL";
+
+ SKIP_MAXSCALE;
+ SKIP_XPAND;
+
+ stmt= mysql_stmt_init(mysql);
+
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+ FAIL_IF(!(my_test_connect(mysql, hostname, username, password,
+ schema, port, socketname, 0)), "my_test_connect failed");
+
+ /* 1. Status is inited, so prepare should work */
+
+ rc= mysql_kill(mysql, mysql_thread_id(mysql));
+
+ rc= mysql_ping(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ diag("Ok");
+
+ /* 2. Status is prepared, execute should fail */
+ rc= mysql_kill(mysql, mysql_thread_id(mysql));
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_close(stmt);
+ mysql_close(mysql);
+ return OK;
+}
+
+
+static int test_conc60(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *query= "SELECT * FROM agendas";
+ my_bool x= 1;
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void *)&x);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ if (rc && mysql_stmt_errno(stmt) == 1146) {
+ diag("Internal test - customer data not available");
+ mysql_stmt_close(stmt);
+ return SKIP;
+ }
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_prepare_insert_update(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int i;
+ const char *testcase[]= {
+ "CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B))",
+ "INSERT t1 VALUES (1,2,10), (3,4,20)",
+ "INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100",
+ "SELECT * FROM t1",
+ "INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0",
+ "SELECT * FROM t1",
+ "INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a)",
+ NULL};
+ const char **cur_query;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ for (cur_query= testcase; *cur_query; cur_query++)
+ {
+ char query[MAX_TEST_QUERY_LENGTH];
+ strcpy(query, *cur_query);
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 0, "Paramcount is not 0");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* try the last query several times */
+ if (!cur_query[1])
+ {
+ for (i=0; i < 3;i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+ }
+ mysql_stmt_close(stmt);
+ }
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ Generalized conversion routine to handle DATE, TIME and DATETIME
+ conversion using MYSQL_TIME structure
+*/
+
+static int test_bind_date_conv(MYSQL *mysql, uint row_count)
+{
+ MYSQL_STMT *stmt= 0;
+ uint rc, i, count;
+ MYSQL_BIND my_bind[4];
+ my_bool is_null[4]= {0,0,0,0};
+ MYSQL_TIME tm[4];
+ ulong second_part;
+ uint year, month, day, hour, minute, sec;
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO test_date VALUES(?, ?, ?, ?)"));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 4, "param_count != 4");
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_TIMESTAMP;
+ my_bind[1].buffer_type= MYSQL_TYPE_TIME;
+ my_bind[2].buffer_type= MYSQL_TYPE_DATETIME;
+ my_bind[3].buffer_type= MYSQL_TYPE_DATETIME;
+
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].buffer= (void *) &tm[i];
+ my_bind[i].is_null= &is_null[i];
+ my_bind[i].buffer_length= sizeof(MYSQL_TIME);
+ }
+
+ second_part= 0;
+
+ year= 2000;
+ month= 01;
+ day= 10;
+
+ hour= 11;
+ minute= 16;
+ sec= 20;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ for (count= 0; count < row_count; count++)
+ {
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ memset(&tm[i], 0, sizeof(MYSQL_TIME));
+ tm[i].neg= 0;
+ tm[i].second_part= second_part+count;
+ if (my_bind[i].buffer_type != MYSQL_TYPE_TIME)
+ {
+ tm[i].year= year+count;
+ tm[i].month= month+count;
+ tm[i].day= day+count;
+ }
+ else
+ tm[i].year= tm[i].month= tm[i].day= 0;
+ if (my_bind[i].buffer_type != MYSQL_TYPE_DATE)
+ {
+ tm[i].hour= hour+count;
+ tm[i].minute= minute+count;
+ tm[i].second= sec+count;
+ }
+ else
+ tm[i].hour= tm[i].minute= tm[i].second= 0;
+ }
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ mysql_stmt_close(stmt);
+
+ rc= my_stmt_result(mysql, "SELECT * FROM test_date");
+ FAIL_UNLESS(row_count == rc, "rowcount != rc");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_date"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ for (count= 0; count < row_count; count++)
+ {
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 0 || rc == MYSQL_DATA_TRUNCATED, "rc != 0 | rc != MYSQL_DATA_TRUNCATED");
+
+ for (i= 0; i < array_elements(my_bind); i++)
+ {
+ FAIL_UNLESS(tm[i].year == 0 || tm[i].year == year+count, "wrong value for year");
+ FAIL_UNLESS(tm[i].month == 0 || tm[i].month == month+count, "wrong value for month");
+ FAIL_UNLESS(tm[i].day == 0 || tm[i].day == day+count, "wrong value for day");
+ FAIL_UNLESS(tm[i].hour == 0 || tm[i].hour % 24 == 0 || tm[i].hour % 24 == hour+count, "wrong value for hour");
+ FAIL_UNLESS(tm[i].minute == 0 || tm[i].minute == minute+count, "wrong value for minute");
+ FAIL_UNLESS(tm[i].second == 0 || tm[i].second == sec+count, "wrong value for second");
+ FAIL_UNLESS(tm[i].second_part == 0 ||
+ tm[i].second_part == second_part+count, "wrong value for second_part");
+ }
+ }
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+
+/* Test simple prepares of all DML statements */
+
+static int test_prepare_simple(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_simple");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_simple("
+ "id int, name varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* insert */
+ strcpy(query, "INSERT INTO test_prepare_simple VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount is not 2");
+ mysql_stmt_close(stmt);
+
+ /* update */
+ strcpy(query, "UPDATE test_prepare_simple SET id=? "
+ "WHERE id=? AND CONVERT(name USING utf8)= ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 3, "Paramcount is not 3");
+ mysql_stmt_close(stmt);
+
+ /* delete */
+ strcpy(query, "DELETE FROM test_prepare_simple WHERE id=10");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 0, "Paramcount is not 0");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ /* delete */
+ strcpy(query, "DELETE FROM test_prepare_simple WHERE id=?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "Paramcount != 1");
+
+ mysql_stmt_close(stmt);
+
+ /* select */
+ strcpy(query, "SELECT * FROM test_prepare_simple WHERE id=? "
+ "AND CONVERT(name USING utf8)= ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_simple");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_prepare_field_result(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_field_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_field_result(int_c int, "
+ "var_c varchar(50), ts_c timestamp, "
+ "char_c char(4), date_c date, extra tinyint)");
+ check_mysql_rc(rc, mysql);
+
+ /* insert */
+ strcpy(query, "SELECT int_c, var_c, date_c as date, ts_c, char_c FROM "
+ " test_prepare_field_result as t1 WHERE int_c=?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "Paramcount != 1");
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, mysql_stmt_error(stmt));
+
+ if (verify_prepare_field(result, 0, "int_c", "int_c", MYSQL_TYPE_LONG,
+ "t1", "test_prepare_field_result", schema, 11, 0))
+ goto error;
+ if (verify_prepare_field(result, 1, "var_c", "var_c", MYSQL_TYPE_VAR_STRING,
+ "t1", "test_prepare_field_result", schema, 50, 0))
+ goto error;
+ if (verify_prepare_field(result, 2, "date", "date_c", MYSQL_TYPE_DATE,
+ "t1", "test_prepare_field_result", schema, 10, 0))
+ goto error;
+ if (verify_prepare_field(result, 3, "ts_c", "ts_c", MYSQL_TYPE_TIMESTAMP,
+ "t1", "test_prepare_field_result", schema, 19, 0))
+ goto error;
+ if (verify_prepare_field(result, 4, "char_c", "char_c",
+ (mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING),
+ "t1", "test_prepare_field_result", schema, 4, 0))
+ goto error;
+
+ FAIL_IF(mysql_num_fields(result) != 5, "Paramcount != 5");
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_field_result");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+
+error:
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+ return FAIL;
+}
+
+
+/* Test simple prepare field results */
+
+static int test_prepare_syntax(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_syntax");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_syntax("
+ "id int, name varchar(50), extra int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "START TRANSACTION");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_prepare_syntax VALUES(?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(!rc, "error expected");
+
+ strcpy(query, "SELECT id, name FROM test_prepare_syntax WHERE id=? AND WHERE");
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(!rc, "error expected");
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_syntax");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_prepare(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ int int_data, o_int_data;
+ char str_data[50], data[50];
+ char tiny_data, o_tiny_data;
+ short small_data, o_small_data;
+ longlong big_data, o_big_data;
+ float real_data, o_real_data;
+ double double_data, o_double_data;
+ ulong length[7], len;
+ my_bool is_null[7];
+ MYSQL_BIND my_bind[7];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE my_prepare(col1 tinyint, "
+ "col2 varchar(15), col3 int, "
+ "col4 smallint, col5 bigint, "
+ "col6 float, col7 double )");
+ check_mysql_rc(rc, mysql);
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ /* insert by prepare */
+ strcpy(query, "INSERT INTO my_prepare VALUES(?, ?, ?, ?, ?, ?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 7, "Paramcount != 7");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /* tinyint */
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&tiny_data;
+ /* string */
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)str_data;
+ my_bind[1].buffer_length= 1000; /* Max string length */
+ /* integer */
+ my_bind[2].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[2].buffer= (void *)&int_data;
+ /* short */
+ my_bind[3].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[3].buffer= (void *)&small_data;
+ /* bigint */
+ my_bind[4].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[4].buffer= (void *)&big_data;
+ /* float */
+ my_bind[5].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[5].buffer= (void *)&real_data;
+ /* double */
+ my_bind[6].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[6].buffer= (void *)&double_data;
+
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].length= &length[i];
+ my_bind[i].is_null= &is_null[i];
+ is_null[i]= 0;
+ }
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ int_data= 320;
+ small_data= 1867;
+ big_data= 1000;
+ real_data= 2;
+ double_data= 6578.001;
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (tiny_data= 0; tiny_data < 100; tiny_data++)
+ {
+ length[1]= sprintf(str_data, "MySQL%d", int_data);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ int_data += 25;
+ small_data += 10;
+ big_data += 100;
+ real_data += 1;
+ double_data += 10.09;
+ }
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* test the results now, only one row should exist */
+ rc= my_stmt_result(mysql, "SELECT * FROM my_prepare");
+ FAIL_UNLESS(rc != 1, "rowcount != 1");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, "SELECT * FROM my_prepare", 25);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ /* get the result */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ o_int_data= 320;
+ o_small_data= 1867;
+ o_big_data= 1000;
+ o_real_data= 2;
+ o_double_data= 6578.001;
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (o_tiny_data= 0; o_tiny_data < 100; o_tiny_data++)
+ {
+ len= sprintf(data, "MySQL%d", o_int_data);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(tiny_data == o_tiny_data, "Wrong value for tiny_data");
+ FAIL_UNLESS(is_null[0] == 0, "Wrong value for is_null");
+ FAIL_UNLESS(length[0] == 1, "length != 0");
+
+ FAIL_UNLESS(int_data == o_int_data, "Wrong value for int_data");
+ FAIL_UNLESS(length[2] == 4, "length != 4");
+
+ FAIL_UNLESS(small_data == o_small_data, "Wrong value for small_data");
+ FAIL_UNLESS(length[3] == 2, "length != 2");
+
+ FAIL_UNLESS(big_data == o_big_data, "Wrong value for big_data");
+ FAIL_UNLESS(length[4] == 8, "length != 8");
+
+ FAIL_UNLESS(real_data == o_real_data, "Wrong value for real_data");
+ FAIL_UNLESS(length[5] == 4, "length != 4");
+
+ FAIL_UNLESS(double_data == o_double_data, "Wrong value for double_data");
+ FAIL_UNLESS(length[6] == 8, "length != 8");
+
+ FAIL_UNLESS(strcmp(data, str_data) == 0, "Wrong value for data");
+ FAIL_UNLESS(length[1] == len, "length != len");
+
+ o_int_data += 25;
+ o_small_data += 10;
+ o_big_data += 100;
+ o_real_data += 1;
+ o_double_data += 10.09;
+ }
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "MYSQL_NO_DATA expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_prepare_multi_statements(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ char query[MAX_TEST_QUERY_LENGTH];
+ int rc;
+
+ strcpy(query, "select 1; select 'another value'");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_prepare_ext(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char *sql;
+ int nData= 1;
+ char tData= 1;
+ short sData= 10;
+ longlong bData= 20;
+ int rowcount= 0;
+ MYSQL_BIND my_bind[6];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_ext");
+ check_mysql_rc(rc, mysql);
+
+ sql= (char *)"CREATE TABLE test_prepare_ext"
+ "("
+ " c1 tinyint,"
+ " c2 smallint,"
+ " c3 mediumint,"
+ " c4 int,"
+ " c5 integer,"
+ " c6 bigint,"
+ " c7 float,"
+ " c8 double,"
+ " c9 double precision,"
+ " c10 real,"
+ " c11 decimal(7, 4),"
+ " c12 numeric(8, 4),"
+ " c13 date,"
+ " c14 datetime,"
+ " c15 timestamp,"
+ " c16 time,"
+ " c17 year,"
+ " c18 bit,"
+ " c19 bool,"
+ " c20 char,"
+ " c21 char(10),"
+ " c22 varchar(30),"
+ " c23 tinyblob,"
+ " c24 tinytext,"
+ " c25 blob,"
+ " c26 text,"
+ " c27 mediumblob,"
+ " c28 mediumtext,"
+ " c29 longblob,"
+ " c30 longtext,"
+ " c31 enum('one', 'two', 'three'),"
+ " c32 set('monday', 'tuesday', 'wednesday'))";
+
+ rc= mysql_query(mysql, sql);
+ check_mysql_rc(rc, mysql);
+
+ /* insert by prepare - all integers */
+ strcpy(query, "INSERT INTO test_prepare_ext(c1, c2, c3, c4, c5, c6) VALUES(?, ?, ?, ?, ?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 6, "Paramcount != 6");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /*tinyint*/
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&tData;
+
+ /*smallint*/
+ my_bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[1].buffer= (void *)&sData;
+
+ /*mediumint*/
+ my_bind[2].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[2].buffer= (void *)&nData;
+
+ /*int*/
+ my_bind[3].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[3].buffer= (void *)&nData;
+
+ /*integer*/
+ my_bind[4].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[4].buffer= (void *)&nData;
+
+ /*bigint*/
+ my_bind[5].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[5].buffer= (void *)&bData;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ /*
+ * integer to integer
+ */
+ for (nData= 0; nData<10; nData++, tData++, sData++, bData++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+
+ strcpy(query, "SELECT c1, c2, c3, c4, c5, c6 FROM test_prepare_ext");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ /* get the result */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+
+ FAIL_UNLESS(nData == rowcount, "Invalid rowcount");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_ext");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_prepare_alter(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL *mysql_new;
+ int rc, id;
+ MYSQL_BIND my_bind[1];
+ my_bool is_null;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_alter");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_prep_alter(id int, name char(20))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_prep_alter values(10, 'venu'), (20, 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_prep_alter VALUES(?, 'monty')");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "Paramcount != 1");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ is_null= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[0].buffer= (void *)&id;
+ my_bind[0].is_null= &is_null;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ id= 30;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_new= mysql_init(NULL);
+ FAIL_IF(!mysql_new, "mysql_init failed");
+ FAIL_IF(!(my_test_connect(mysql_new, hostname, username, password,
+ schema, port, socketname, 0)), "my_test_connect failed");
+ rc= mysql_query(mysql_new, "ALTER TABLE test_prep_alter change id id_new varchar(20)");
+ diag("Error: %d %s", mysql_errno(mysql_new), mysql_error(mysql_new));
+ check_mysql_rc(rc, mysql_new);
+ mysql_close(mysql_new);
+
+ is_null= 1;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= my_stmt_result(mysql, "SELECT * FROM test_prep_alter");
+ FAIL_UNLESS(rc == 4, "rowcount != 4");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_alter");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_prepare_resultset(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_RES *result;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_resultset");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_prepare_resultset(id int, \
+ name varchar(50), extra double)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ strcpy(query, "SELECT * FROM test_prepare_resultset");
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt), "Paramcount != 0");
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, "Invalid resultset");
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_resultset");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Test the direct query execution in the middle of open stmts */
+
+static int test_open_direct(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_open_direct");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_open_direct(id int, name char(6))");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_open_direct values(10, 'mysql')");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "invalid resultset");
+
+ FAIL_IF(mysql_num_rows(result), "rowcount != 0");
+ mysql_free_result(result);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "affected rows != 1");
+
+ rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "invalid resultset");
+
+ FAIL_IF(mysql_num_rows(result) != 1, "rowcount != 1");
+ mysql_free_result(result);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "affected rows != 1");
+
+ rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid resultset");
+ FAIL_IF(mysql_num_rows(result) != 2, "rowcount != 2");
+
+ mysql_free_result(result);
+
+ mysql_stmt_close(stmt);
+
+ /* run a direct query in the middle of a fetch */
+
+ strcpy(query, "SELECT * FROM test_open_direct");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "INSERT INTO test_open_direct(id) VALUES(20)");
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "INSERT INTO test_open_direct(id) VALUES(20)");
+ check_mysql_rc(rc, mysql);
+
+ /* run a direct query with store result */
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "drop table test_open_direct");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ return OK;
+}
+
+static int test_select_show(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+ int rowcount;
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_show");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL primary "
+ " key, name char(2))");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "show columns from test_show");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_stmt_error(stmt));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 0, "Paramcount != 0");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 2, "rowcount != 2");
+
+ mysql_stmt_close(stmt);
+
+ strcpy(query, "show tables from mysql like ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(!rc, "Error expected");
+
+ strcpy(query, "show tables like \'test_show\'");
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+ mysql_stmt_close(stmt);
+
+ strcpy(query, "describe test_show");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 2, "rowcount != 2");
+ mysql_stmt_close(stmt);
+
+ strcpy(query, "show keys from test_show");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_show");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_simple_update(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char szData[25];
+ int nData= 1;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[2];
+ ulong length[2];
+ int rowcount= 0;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_update(col1 int, "
+ " col2 varchar(50), col3 int )");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_update VALUES(1, 'MySQL', 100)");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_affected_rows(mysql) != 1, "Affected rows != 1");
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* insert by prepare */
+ strcpy(query, "UPDATE test_update SET col2= ? WHERE col1= ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ nData= 1;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= szData; /* string data */
+ my_bind[0].buffer_length= sizeof(szData);
+ my_bind[0].length= &length[0];
+ length[0]= sprintf(szData, "updated-data");
+
+ my_bind[1].buffer= (void *) &nData;
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "Affected_rows != 1");
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* test the results now, only one row should exist */
+ rc= mysql_query(mysql, "SELECT * FROM test_update");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid resultset");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/* Test simple long data handling */
+
+static int test_long_data(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, int_data;
+ char *data= NullS;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[3];
+ int rowcount;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data(col1 int, "
+ " col2 MEDIUMTEXT, col3 MEDIUMTEXT)");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_long_data(col1, col2) VALUES(?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(!rc, "Error expected");
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ strcpy(query, "INSERT INTO test_long_data(col1, col2, col3) VALUES(?, ?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 3, "Paramcount != 3");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer= (void *)&int_data;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+
+ my_bind[2]= my_bind[1];
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ int_data= 999;
+ data= (char *)"Michael";
+
+ /* supply data in pieces */
+ rc= mysql_stmt_send_long_data(stmt, 1, SL(data));
+ check_stmt_rc(rc, stmt);
+ data= (char *)" 'Monty' Widenius";
+ rc= mysql_stmt_send_long_data(stmt, 1, SL(data));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_send_long_data(stmt, 2, "Venu (venu@mysql.com)", 4);
+ check_stmt_rc(rc, stmt);
+
+ /* execute */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* now fetch the results ..*/
+ rc= mysql_query(mysql, "SELECT * FROM test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rowcount= 0;
+ while (mysql_fetch_row(result))
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+ mysql_free_result(result);
+
+ if (verify_col_data(mysql, "test_long_data", "col1", "999"))
+ goto error;
+ if (verify_col_data(mysql, "test_long_data", "col2", "Michael 'Monty' Widenius"))
+ goto error;
+ if (verify_col_data(mysql, "test_long_data", "col3", "Venu"))
+ goto error;
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data");
+ check_mysql_rc(rc, mysql);
+ return OK;
+
+error:
+ mysql_stmt_close(stmt);
+ return FAIL;
+}
+
+
+/* Test long data (string) handling */
+
+static int test_long_data_str(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i, rowcount= 0;
+ char data[255];
+ long length;
+ ulong length1;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[2];
+ my_bool is_null[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_str");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data_str(id int, longstr MEDIUMTEXT)");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_long_data_str VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer= (void *)&length;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].is_null= &is_null[0];
+ is_null[0]= 0;
+ length= 0;
+
+ my_bind[1].buffer= data; /* string data */
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].length= &length1;
+ my_bind[1].is_null= &is_null[1];
+ is_null[1]= 0;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ length= 40;
+ strcpy(data, "MySQL AB");
+
+ /* supply data in pieces */
+ for(i= 0; i < 4; i++)
+ {
+ rc= mysql_stmt_send_long_data(stmt, 1, (char *)data, 5);
+ check_stmt_rc(rc, stmt);
+ }
+ /* execute */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* now fetch the results ..*/
+ rc= mysql_query(mysql, "SELECT LENGTH(longstr), longstr FROM test_long_data_str");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+
+ mysql_free_result(result);
+
+ sprintf(data, "%d", i*5);
+ if (verify_col_data(mysql, "test_long_data_str", "LENGTH(longstr)", data))
+ goto error;
+ strcpy(data, "MySQLMySQLMySQLMySQL");
+ if (verify_col_data(mysql, "test_long_data_str", "longstr", data))
+ goto error;
+
+ rc= mysql_query(mysql, "DROP TABLE test_long_data_str");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+
+error:
+ rc= mysql_query(mysql, "DROP TABLE test_long_data_str");
+ check_mysql_rc(rc, mysql);
+ return FAIL;
+}
+
+
+/* Test long data (string) handling */
+
+static int test_long_data_str1(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i, rowcount= 0;
+ char data[255];
+ long length;
+ unsigned long max_blob_length, blob_length, length1;
+ my_bool true_value;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[2];
+ MYSQL_FIELD *field;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_str");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data_str(longstr MEDIUMTEXT, blb MEDIUMBLOB)");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_long_data_str VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer= data; /* string data */
+ my_bind[0].buffer_length= sizeof(data);
+ my_bind[0].length= (unsigned long *)&length1;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ length1= 0;
+
+ my_bind[1]= my_bind[0];
+ my_bind[1].buffer_type= MYSQL_TYPE_BLOB;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ length= sprintf(data, "MySQL AB");
+
+ /* supply data in pieces */
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_send_long_data(stmt, 0, data, length);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_send_long_data(stmt, 1, data, 2);
+ check_stmt_rc(rc, stmt);
+ }
+
+ /* execute */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* now fetch the results ..*/
+ rc= mysql_query(mysql, "SELECT LENGTH(longstr), longstr, LENGTH(blb), blb FROM test_long_data_str");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+
+ mysql_field_seek(result, 1);
+ field= mysql_fetch_field(result);
+ max_blob_length= field->max_length;
+
+ FAIL_IF(!result, "Invalid result set");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+ mysql_free_result(result);
+
+ sprintf(data, "%ld", (long)i*length);
+ if (verify_col_data(mysql, "test_long_data_str", "length(longstr)", data))
+ return FAIL;
+
+ sprintf(data, "%d", i*2);
+ if (verify_col_data(mysql, "test_long_data_str", "length(blb)", data))
+ return FAIL;
+
+ /* Test length of field->max_length */
+ strcpy(query, "SELECT * from test_long_data_str");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 0, "Paramcount != 0");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_fields(result);
+
+ /* First test what happens if STMT_ATTR_UPDATE_MAX_LENGTH is not used */
+ FAIL_IF(field->max_length != 0, "field->max_length != 0");
+ mysql_free_result(result);
+
+ /* Enable updating of field->max_length */
+ true_value= 1;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &true_value);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_fields(result);
+
+ diag("max_length: %lu max_blob_length: %lu", (unsigned long)field->max_length, (unsigned long)max_blob_length);
+ FAIL_UNLESS(field->max_length == max_blob_length, "field->max_length != max_blob_length");
+
+ /* Fetch results into a data buffer that is smaller than data */
+ memset(my_bind, '\0', sizeof(*my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_BLOB;
+ my_bind[0].buffer= (void *) &data; /* this buffer won't be altered */
+ my_bind[0].buffer_length= 16;
+ my_bind[0].length= (unsigned long *)&blob_length;
+ my_bind[0].error= &my_bind[0].error_value;
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ data[16]= 0;
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_DATA_TRUNCATED, "truncation expected");
+ FAIL_UNLESS(my_bind[0].error_value, "No error value");
+ FAIL_UNLESS(strlen(data) == 16, "Invalid string length");
+ FAIL_UNLESS(blob_length == max_blob_length, "blob_length != max_blob_length");
+
+ /* Fetch all data */
+ memset((my_bind+1), '\0', sizeof(*my_bind));
+ my_bind[1].buffer_type= MYSQL_TYPE_BLOB;
+ my_bind[1].buffer= (void *) &data; /* this buffer won't be altered */
+ my_bind[1].buffer_length= sizeof(data);
+ my_bind[1].length= (unsigned long *)&blob_length;
+ memset(data, '\0', sizeof(data));
+ mysql_stmt_fetch_column(stmt, my_bind+1, 0, 0);
+ FAIL_UNLESS(strlen(data) == max_blob_length, "strlen(data) != max_blob_length");
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ /* Drop created table */
+ rc= mysql_query(mysql, "DROP TABLE test_long_data_str");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/* Test long data (binary) handling */
+
+static int test_long_data_bin(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, rowcount= 0;
+ char data[255];
+ long length;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_bin");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data_bin(id int, longbin long varbinary)");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_long_data_bin VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer= (void *)&length;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ length= 0;
+
+ my_bind[1].buffer= data; /* string data */
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG_BLOB;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ length= 10;
+ strcpy(data, "MySQL AB");
+
+ /* supply data in pieces */
+ {
+ int i;
+ for (i= 0; i < 100; i++)
+ {
+ rc= mysql_stmt_send_long_data(stmt, 1, (char *)data, 4);
+ check_stmt_rc(rc, stmt);
+ }
+ }
+ /* execute */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* now fetch the results ..*/
+ rc= mysql_query(mysql, "SELECT LENGTH(longbin), longbin FROM test_long_data_bin");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+ mysql_free_result(result);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_bin");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+
+/* Test simple delete */
+
+static int test_simple_delete(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, rowcount= 0;
+ char szData[30]= {0};
+ int nData= 1;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[2];
+ ulong length[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_simple_delete");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_simple_delete(col1 int, \
+ col2 varchar(50), col3 int )");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_simple_delete VALUES(1, 'MySQL', 100)");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_IF(mysql_affected_rows(mysql) != 1, "Affected rows != 1");
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* insert by prepare */
+ strcpy(query, "DELETE FROM test_simple_delete WHERE col1= ? AND "
+ "CONVERT(col2 USING utf8)= ? AND col3= 100");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ nData= 1;
+ strcpy(szData, "MySQL");
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= szData; /* string data */
+ my_bind[1].buffer_length= sizeof(szData);
+ my_bind[1].length= &length[1];
+ length[1]= 5;
+
+ my_bind[0].buffer= (void *)&nData;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "Affected rows != 1");
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* test the results now, only one row should exist */
+ rc= mysql_query(mysql, "SELECT * FROM test_simple_delete");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+
+ FAIL_IF(rowcount, "rowcount > 0");
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_simple_delete");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_update(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char szData[25];
+ int nData= 1, rowcount= 0;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[2];
+ ulong length[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_update("
+ "col1 int primary key auto_increment, "
+ "col2 varchar(50), col3 int )");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_update(col2, col3) VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /* string data */
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= szData;
+ my_bind[0].buffer_length= sizeof(szData);
+ my_bind[0].length= &length[0];
+ length[0]= sprintf(szData, "inserted-data");
+
+ my_bind[1].buffer= (void *)&nData;
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ nData= 100;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "Affected rows != 1");
+ mysql_stmt_close(stmt);
+
+ strcpy(query, "UPDATE test_update SET col2= ? WHERE col3= ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Paramcount != 2");
+ nData= 100;
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= szData;
+ my_bind[0].buffer_length= sizeof(szData);
+ my_bind[0].length= &length[0];
+ length[0]= sprintf(szData, "updated-data");
+
+ my_bind[1].buffer= (void *)&nData;
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 1, "Affected rows != 1");
+
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* test the results now, only one row should exist */
+ rc= mysql_query(mysql, "SELECT * FROM test_update");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/* Test prepare without parameters */
+
+static int test_prepare_noparam(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, rowcount= 0;
+ MYSQL_RES *result;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
+ check_mysql_rc(rc, mysql);
+
+
+ rc= mysql_query(mysql, "CREATE TABLE my_prepare(col1 int, col2 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* insert by prepare */
+ strcpy(query, "INSERT INTO my_prepare VALUES(10, 'venu')");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 0, "Paramcount != 0");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* test the results now, only one row should exist */
+ rc= mysql_query(mysql, "SELECT * FROM my_prepare");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/* Test simple bind result */
+
+static int test_bind_result(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int nData;
+ ulong length1;
+ char szData[100];
+ MYSQL_BIND my_bind[2];
+ my_bool is_null[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(col1 int , col2 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(10, 'venu')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(20, 'MySQL')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result(col2) VALUES('monty')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* fetch */
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *) &nData; /* integer data */
+ my_bind[0].is_null= &is_null[0];
+
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= szData; /* string data */
+ my_bind[1].buffer_length= sizeof(szData);
+ my_bind[1].length= &length1;
+ my_bind[1].is_null= &is_null[1];
+
+ strcpy(query, "SELECT * FROM test_bind_result");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 10, "nData != 10");
+ FAIL_UNLESS(strcmp(szData, "venu") == 0, "szData != 'Venu'");
+ FAIL_UNLESS(length1 == 4, "length1 != 4");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 20, "nData != 20");
+ FAIL_UNLESS(strcmp(szData, "MySQL") == 0, "szData != 'MySQL'");
+ FAIL_UNLESS(length1 == 5, "length1 != 5");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(is_null[0], "null flag not set");
+ FAIL_UNLESS(strcmp(szData, "monty") == 0, "szData != 'Monty'");
+ FAIL_UNLESS(length1 == 5, "length1 != 5");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "MYSQL_NO_DATA expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bind_result_ext(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ uchar t_data;
+ short s_data;
+ int i_data;
+ longlong b_data;
+ float f_data;
+ double d_data;
+ char szData[20], bData[20];
+ ulong szLength, bLength;
+ MYSQL_BIND my_bind[8];
+ ulong length[8];
+ my_bool is_null[8];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 tinyint, "
+ " c2 smallint, "
+ " c3 int, c4 bigint, "
+ " c5 float, c6 double, "
+ " c7 varbinary(10), "
+ " c8 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result "
+ "VALUES (19, 2999, 3999, 4999999, "
+ " 2345.6, 5678.89563, 'venu', 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i= 0; i < (int) array_elements(my_bind); i++)
+ {
+ my_bind[i].length= &length[i];
+ my_bind[i].is_null= &is_null[i];
+ }
+
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&t_data;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[2].buffer_type= MYSQL_TYPE_LONG;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[1].buffer= (void *)&s_data;
+
+ my_bind[2].buffer= (void *)&i_data;
+ my_bind[3].buffer= (void *)&b_data;
+
+ my_bind[4].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[4].buffer= (void *)&f_data;
+
+ my_bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[5].buffer= (void *)&d_data;
+
+ my_bind[6].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[6].buffer= (void *)szData;
+ my_bind[6].buffer_length= sizeof(szData);
+ my_bind[6].length= &szLength;
+
+ my_bind[7].buffer_type= MYSQL_TYPE_TINY_BLOB;
+ my_bind[7].buffer= (void *)&bData;
+ my_bind[7].length= &bLength;
+ my_bind[7].buffer_length= sizeof(bData);
+
+ strcpy(query, "select * from test_bind_result");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(t_data == 19, "tdata != 19");
+ FAIL_UNLESS(s_data == 2999, "s_data != 2999");
+ FAIL_UNLESS(i_data == 3999, "i_data != 3999");
+ FAIL_UNLESS(b_data == 4999999, "b_data != 4999999");
+ FAIL_UNLESS(strcmp(szData, "venu") == 0, "szData != 'Venu'");
+ FAIL_UNLESS(strncmp(bData, "mysql", 5) == 0, "nData != 'mysql'");
+ FAIL_UNLESS(szLength == 4, "szLength != 4");
+ FAIL_UNLESS(bLength == 5, "bLength != 5");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "MYSQL_NO_DATA expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+
+/* Test ext bind result */
+
+static int test_bind_result_ext1(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ uint i;
+ int rc;
+ char t_data[20];
+ float s_data;
+ short i_data;
+ uchar b_data;
+ int f_data;
+ long bData;
+ char d_data[20];
+ double szData;
+ MYSQL_BIND my_bind[8];
+ ulong length[8];
+ my_bool is_null[8];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
+ c3 int, c4 bigint, \
+ c5 float, c6 double, \
+ c7 varbinary(10), \
+ c8 varchar(10))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(120, 2999, 3999, 54, \
+ 2.6, 58.89, \
+ '206', '6.7')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *) t_data;
+ my_bind[0].buffer_length= sizeof(t_data);
+ my_bind[0].error= &my_bind[0].error_value;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[1].buffer= (void *)&s_data;
+ my_bind[1].buffer_length= 0;
+ my_bind[1].error= &my_bind[1].error_value;
+
+ my_bind[2].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[2].buffer= (void *)&i_data;
+ my_bind[2].buffer_length= 0;
+ my_bind[2].error= &my_bind[2].error_value;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[3].buffer= (void *)&b_data;
+ my_bind[3].buffer_length= 0;
+ my_bind[3].error= &my_bind[3].error_value;
+
+ my_bind[4].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[4].buffer= (void *)&f_data;
+ my_bind[4].buffer_length= 0;
+ my_bind[4].error= &my_bind[4].error_value;
+
+ my_bind[5].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[5].buffer= (void *)d_data;
+ my_bind[5].buffer_length= sizeof(d_data);
+ my_bind[5].error= &my_bind[5].error_value;
+
+ my_bind[6].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[6].buffer= (void *)&bData;
+ my_bind[6].buffer_length= 0;
+ my_bind[6].error= &my_bind[6].error_value;
+
+ my_bind[7].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[7].buffer= (void *)&szData;
+ my_bind[7].buffer_length= 0;
+ my_bind[7].error= &my_bind[7].error_value;
+
+ for (i= 0; i < array_elements(my_bind); i++)
+ {
+ my_bind[i].is_null= &is_null[i];
+ my_bind[i].length= &length[i];
+ }
+
+ strcpy(query, "select * from test_bind_result");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(strcmp(t_data, "120") == 0, "t_data != 120");
+ FAIL_UNLESS(i_data == 3999, "i_data != 3999");
+ FAIL_UNLESS(f_data == 2, "f_data != 2");
+ FAIL_UNLESS(strcmp(d_data, "58.89") == 0, "d_data != 58.89");
+ FAIL_UNLESS(b_data == 54, "b_data != 54");
+
+ FAIL_UNLESS(length[0] == 3, "Wrong length");
+ FAIL_UNLESS(length[1] == 4, "Wrong length");
+ FAIL_UNLESS(length[2] == 2, "Wrong length");
+ FAIL_UNLESS(length[3] == 1, "Wrong length");
+ FAIL_UNLESS(length[4] == 4, "Wrong length");
+ FAIL_UNLESS(length[5] == 5, "Wrong length");
+ FAIL_UNLESS(length[6] == 4, "Wrong length");
+ FAIL_UNLESS(length[7] == 8, "Wrong length");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "MYSQL_NO_DATA expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bind_negative(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ char *query;
+ int rc;
+ MYSQL_BIND my_bind[1];
+ int32 my_val= 0;
+ ulong my_length= 0L;
+ my_bool my_null= FALSE;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create temporary table t1 (c1 int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (-1)");
+ check_mysql_rc(rc, mysql);
+
+ query= (char*)"INSERT INTO t1 VALUES (?)";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ /* bind parameters */
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&my_val;
+ my_bind[0].length= &my_length;
+ my_bind[0].is_null= &my_null;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ my_val= -1;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_buffers(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ int rc;
+ ulong length;
+ my_bool is_null;
+ char buffer[20];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_buffer");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_buffer(str varchar(20))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into test_buffer values('MySQL')\
+ , ('Database'), ('Open-Source'), ('Popular')");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "select str from test_buffer");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(buffer, '\0', sizeof(buffer)); /* Avoid overruns in printf() */
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].length= &length;
+ my_bind[0].is_null= &is_null;
+ my_bind[0].buffer_length= 1;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)buffer;
+ my_bind[0].error= &my_bind[0].error_value;
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ buffer[1]= 'X';
+ rc= mysql_stmt_fetch(stmt);
+
+ FAIL_UNLESS(rc == MYSQL_DATA_TRUNCATED, "rc != MYSQL_DATA_TRUNCATED");
+ FAIL_UNLESS(my_bind[0].error_value, "Errorflag not set");
+ FAIL_UNLESS(buffer[0] == 'M', "buffer[0] != M");
+ FAIL_UNLESS(buffer[1] == 'X', "buffer[1] != X");
+ FAIL_UNLESS(length == 5, "length != 5");
+
+ my_bind[0].buffer_length= 8;
+ rc= mysql_stmt_bind_result(stmt, my_bind);/* re-bind */
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(strncmp(buffer, "Database", 8) == 0, "buffer != 'Database'");
+ FAIL_UNLESS(length == 8, "length != 8");
+
+ my_bind[0].buffer_length= 12;
+ rc= mysql_stmt_bind_result(stmt, my_bind);/* re-bind */
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(strcmp(buffer, "Open-Source") == 0, "buffer != 'Open-Source'");
+ FAIL_UNLESS(length == 11, "Length != 11");
+
+ my_bind[0].buffer_length= 6;
+ rc= mysql_stmt_bind_result(stmt, my_bind);/* re-bind */
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_DATA_TRUNCATED, "rc != MYSQL_DATA_TRUNCATED");
+ FAIL_UNLESS(my_bind[0].error_value, "Errorflag not set");
+ FAIL_UNLESS(strncmp(buffer, "Popula", 6) == 0, "buffer != 'Popula'");
+ FAIL_UNLESS(length == 7, "length != 7");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_buffer");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_xjoin(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query=
+ "select t.id, p1.value, n1.value, p2.value, n2.value from t3 t LEFT JOIN t1 p1 ON (p1.id=t.param1_id) LEFT JOIN t2 p2 ON (p2.id=t.param2_id) LEFT JOIN t4 n1 ON (n1.id=p1.name_id) LEFT JOIN t4 n2 ON (n2.id=p2.name_id) where t.id=1";
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3, t4");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t3 (id int(8), param1_id int(8), param2_id int(8)) ENGINE=InnoDB DEFAULT CHARSET=utf8");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 ( id int(8), name_id int(8), value varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t2 (id int(8), name_id int(8), value varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t4(id int(8), value varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t3 values (1, 1, 1), (2, 2, null)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values (1, 1, 'aaa'), (2, null, 'bbb')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t2 values (1, 2, 'ccc')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t4 values (1, 'Name1'), (2, null)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1, t2, t3, t4");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_union_param(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ char *query;
+ int rc, i;
+ MYSQL_BIND my_bind[2];
+ char my_val[4];
+ ulong my_length= 3L;
+ my_bool my_null= FALSE;
+
+ strcpy(my_val, "abc");
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ query= (char*)"select ? as my_col union distinct select ?";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /* bind parameters */
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (char*) &my_val;
+ my_bind[0].buffer_length= 4;
+ my_bind[0].length= &my_length;
+ my_bind[0].is_null= &my_null;
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (char*) &my_val;
+ my_bind[1].buffer_length= 4;
+ my_bind[1].length= &my_length;
+ my_bind[1].is_null= &my_null;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+ }
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_union(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *query= "SELECT t1.name FROM t1 UNION "
+ "SELECT t2.name FROM t2";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "CREATE TABLE t1 "
+ "(id INTEGER NOT NULL PRIMARY KEY, "
+ " name VARCHAR(20) NOT NULL)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "INSERT INTO t1 (id, name) VALUES "
+ "(2, 'Ja'), (3, 'Ede'), "
+ "(4, 'Haag'), (5, 'Kabul'), "
+ "(6, 'Almere'), (7, 'Utrecht'), "
+ "(8, 'Qandahar'), (9, 'Amsterdam'), "
+ "(10, 'Amersfoort'), (11, 'Constantine')");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "CREATE TABLE t2 "
+ "(id INTEGER NOT NULL PRIMARY KEY, "
+ " name VARCHAR(20) NOT NULL)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "INSERT INTO t2 (id, name) VALUES "
+ "(4, 'Guam'), (5, 'Aruba'), "
+ "(6, 'Angola'), (7, 'Albania'), "
+ "(8, 'Anguilla'), (9, 'Argentina'), "
+ "(10, 'Azerbaijan'), (11, 'Afghanistan'), "
+ "(12, 'Burkina Faso'), (13, 'Faroe Islands')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 20, "rc != 20");
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_union2(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query= "select col1 FROM t1 where col1=1 union distinct "
+ "select col1 FROM t1 where col1=2";
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1(col1 INT, \
+ col2 VARCHAR(40), \
+ col3 SMALLINT, \
+ col4 TIMESTAMP)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 0, "rowcount != 0");
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Misc tests to keep pure coverage happy */
+
+static int test_pure_coverage(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ int rc;
+ ulong length;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_pure");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_pure(c1 int, c2 varchar(20))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "START TRANSACTION");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("insert into test_pure(c67788) values(10)"));
+ FAIL_IF(!rc, "Error expected");
+ mysql_stmt_close(stmt);
+
+ /* Query without params and result should allow one to bind 0 arrays */
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("insert into test_pure(c2) values(10)"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, (MYSQL_BIND*)0);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_result(stmt, (MYSQL_BIND*)0);
+ FAIL_UNLESS(rc == 1, "");
+
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("insert into test_pure(c2) values(?)"));
+ check_stmt_rc(rc, stmt);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].length= &length;
+ my_bind[0].is_null= 0;
+ my_bind[0].buffer_length= 0;
+
+ my_bind[0].buffer_type= MYSQL_TYPE_GEOMETRY;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ FAIL_IF(!rc, "Error expected");
+
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("select * from test_pure"));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ mysql_query(mysql, "DROP TABLE test_pure");
+ return OK;
+}
+
+static int test_insert_select(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt_insert, *stmt_select;
+ char *query;
+ int rc;
+ uint i;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t2 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t2 values (1)");
+ check_mysql_rc(rc, mysql);
+
+ query= (char*)"insert into t1 select a from t2";
+ stmt_insert= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_insert, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_insert, SL(query));
+ check_stmt_rc(rc, stmt_insert);
+
+ query= (char*)"select * from t1";
+ stmt_select= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_select, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_select, SL(query));
+ check_stmt_rc(rc, stmt_select);
+
+ for(i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt_insert);
+ check_stmt_rc(rc, stmt_insert);
+
+ rc= mysql_stmt_execute(stmt_select);
+ check_stmt_rc(rc, stmt_select);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt_select) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == (int)(i+1), "rc != i+1");
+ }
+
+ mysql_stmt_close(stmt_insert);
+ mysql_stmt_close(stmt_select);
+ rc= mysql_query(mysql, "drop table t1, t2");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test simple prepare-insert */
+
+static int test_insert(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char str_data[50];
+ char tiny_data;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[2];
+ ulong length;
+
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_insert");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_prep_insert(col1 tinyint, \
+ col2 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* insert by prepare */
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO test_prep_insert VALUES(?, ?)"));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Param_count != 2");
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /* tinyint */
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&tiny_data;
+
+ /* string */
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= str_data;
+ my_bind[1].buffer_length= sizeof(str_data);;
+ my_bind[1].length= &length;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (tiny_data= 0; tiny_data < 3; tiny_data++)
+ {
+ length= sprintf(str_data, "MySQL%d", tiny_data);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* test the results now, only one row should exist */
+ rc= mysql_query(mysql, "SELECT * FROM test_prep_insert");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS((int) tiny_data == rc, "rowcount != tinydata");
+ mysql_free_result(result);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_insert");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_join(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i, j;
+ const char *query[]= {"SELECT * FROM t2 join t1 on (t1.a=t2.a)",
+ "SELECT * FROM t2 natural join t1",
+ "SELECT * FROM t2 join t1 using(a)",
+ "SELECT * FROM t2 left join t1 on(t1.a=t2.a)",
+ "SELECT * FROM t2 natural left join t1",
+ "SELECT * FROM t2 left join t1 using(a)",
+ "SELECT * FROM t2 right join t1 on(t1.a=t2.a)",
+ "SELECT * FROM t2 natural right join t1",
+ "SELECT * FROM t2 right join t1 using(a)"};
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t2 (a int , c int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "insert into t2 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
+ check_mysql_rc(rc, mysql);
+
+ for (j= 0; j < 9; j++)
+ {
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query[j]));
+ check_stmt_rc(rc, stmt);
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 5, "rowcount != 5");
+ }
+ mysql_stmt_close(stmt);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_left_join_view(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query=
+ "select t1.a, v1.x from t1 left join v1 on (t1.a= v1.x);";
+
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1");
+ check_mysql_rc(rc, mysql);
+
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"insert into t1 values (1), (2), (3)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"create view v1 (x) as select a from t1 where a > 1");
+ check_mysql_rc(rc, mysql);
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 3, "rowcount != 3");
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test simple sample - manual */
+
+static int test_manual_sample(MYSQL *mysql)
+{
+ unsigned int param_count;
+ MYSQL_STMT *stmt;
+ short small_data;
+ int int_data;
+ int rc;
+ char str_data[50];
+ ulonglong affected_rows;
+ MYSQL_BIND my_bind[3];
+ my_bool is_null;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+
+ /*
+ Sample which is incorporated directly in the manual under Prepared
+ statements section (Example from mysql_stmt_execute()
+ */
+
+ memset(str_data, 0, sizeof(str_data));
+ mysql_autocommit(mysql, 1);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_table");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_table(col1 int, col2 varchar(50), \
+ col3 smallint, \
+ col4 timestamp)");
+ check_mysql_rc(rc, mysql);
+
+ /* Prepare a insert query with 3 parameters */
+ strcpy(query, "INSERT INTO test_table(col1, col2, col3) values(?, ?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ /* Get the parameter count from the statement */
+ param_count= mysql_stmt_param_count(stmt);
+ FAIL_IF(param_count != 3, "param_count != 3");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /* INTEGER PART */
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&int_data;
+
+ /* STRING PART */
+ my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ my_bind[1].buffer= (void *)str_data;
+ my_bind[1].buffer_length= sizeof(str_data);
+
+ /* SMALLINT PART */
+ my_bind[2].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[2].buffer= (void *)&small_data;
+ my_bind[2].is_null= &is_null;
+ is_null= 0;
+
+ /* Bind the buffers */
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ /* Specify the data */
+ int_data= 10; /* integer */
+ strcpy(str_data, "MySQL"); /* string */
+
+ /* INSERT SMALLINT data as NULL */
+ is_null= 1;
+
+ /* Execute the insert statement - 1*/
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* Get the total rows affected */
+ affected_rows= mysql_stmt_affected_rows(stmt);
+ FAIL_IF(affected_rows != 1, "affected-rows != 1");
+
+ /* Re-execute the insert, by changing the values */
+ int_data= 1000;
+ strcpy(str_data, "The most popular open source database");
+ small_data= 1000; /* smallint */
+ is_null= 0; /* reset */
+
+ /* Execute the insert statement - 2*/
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* Get the total rows affected */
+ affected_rows= mysql_stmt_affected_rows(stmt);
+
+ FAIL_IF(affected_rows != 1, "affected_rows != 1");
+
+ /* Close the statement */
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* DROP THE TABLE */
+ rc= mysql_query(mysql, "DROP TABLE test_table");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_create_drop(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt_create, *stmt_drop, *stmt_select, *stmt_create_select;
+ char *query;
+ int rc, i;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t2 (a int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (a int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t2 values (3), (2), (1);");
+ check_mysql_rc(rc, mysql);
+
+ query= (char*)"create table t1 (a int)";
+ stmt_create= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_create, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_create, SL(query));
+ check_stmt_rc(rc, stmt_create);
+
+ query= (char*)"drop table t1";
+ stmt_drop= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_drop, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_drop, SL(query));
+ check_stmt_rc(rc, stmt_drop);
+
+ query= (char*)"select a in (select a from t2) from t1";
+ stmt_select= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_select, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_select, SL(query));
+ check_stmt_rc(rc, stmt_select);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ query= (char*)"create table t1 select a from t2";
+ stmt_create_select= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_create_select, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_create_select, SL(query));
+ check_stmt_rc(rc, stmt_create_select);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt_create);
+ check_stmt_rc(rc, stmt_create);
+
+ rc= mysql_stmt_execute(stmt_select);
+ check_stmt_rc(rc, stmt_select);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt_select) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 0, "rowcount != 0");
+
+ rc= mysql_stmt_execute(stmt_drop);
+ check_stmt_rc(rc, stmt_drop);
+
+ rc= mysql_stmt_execute(stmt_create_select);
+ check_stmt_rc(rc, stmt_create_select);
+
+ rc= mysql_stmt_execute(stmt_select);
+ check_stmt_rc(rc, stmt_select);
+ rc= 0;
+ while (mysql_stmt_fetch(stmt_select) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 3, "rowcount != 3");
+
+ rc= mysql_stmt_execute(stmt_drop);
+ check_stmt_rc(rc, stmt_drop);
+ }
+
+ mysql_stmt_close(stmt_create);
+ mysql_stmt_close(stmt_drop);
+ mysql_stmt_close(stmt_select);
+ mysql_stmt_close(stmt_create_select);
+
+ rc= mysql_query(mysql, "DROP TABLE t2");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test DATE, TIME, DATETIME and TS with MYSQL_TIME conversion */
+
+static int test_date(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIMESTAMP, \
+ c2 TIME, \
+ c3 DATETIME, \
+ c4 DATE)");
+
+ check_mysql_rc(rc, mysql);
+
+ rc= test_bind_date_conv(mysql, 5);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ return rc;
+}
+
+
+/* Test all time types to DATE and DATE to all types */
+
+static int test_date_date(MYSQL *mysql)
+{
+ int rc;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 DATE, \
+ c2 DATE, \
+ c3 DATE, \
+ c4 DATE)");
+
+ check_mysql_rc(rc, mysql);
+
+ rc= test_bind_date_conv(mysql, 3);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ return rc;
+}
+
+/* Test all time types to TIMESTAMP and TIMESTAMP to all types */
+
+static int test_date_ts(MYSQL *mysql)
+{
+ int rc;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIMESTAMP, \
+ c2 TIMESTAMP, \
+ c3 TIMESTAMP, \
+ c4 TIMESTAMP)");
+
+ check_mysql_rc(rc, mysql);
+
+ rc= test_bind_date_conv(mysql, 2);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ return rc;
+}
+
+
+/* Test all time types to DATETIME and DATETIME to all types */
+
+static int test_date_dt(MYSQL *mysql)
+{
+ int rc;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 datetime, "
+ " c2 datetime, c3 datetime, c4 date)");
+ check_mysql_rc(rc, mysql);
+
+ rc= test_bind_date_conv(mysql, 2);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ return rc;
+}
+
+/* Test all time types to TIME and TIME to all types */
+
+static int test_date_time(MYSQL *mysql)
+{
+ int rc;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIME, \
+ c2 TIME, \
+ c3 TIME, \
+ c4 TIME)");
+
+ check_mysql_rc(rc, mysql);
+
+ rc= test_bind_date_conv(mysql, 3);
+ mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
+ return rc;
+}
+
+/*
+ Test of basic checks that are performed in server for components
+ of MYSQL_TIME parameters.
+*/
+
+static int test_datetime_ranges(MYSQL *mysql)
+{
+ const char *stmt_text;
+ int rc, i;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[6];
+ MYSQL_TIME tm[6];
+
+ if (!is_mariadb)
+ return SKIP;
+
+ stmt_text= "drop table if exists t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "create table t1 (year datetime, month datetime, day datetime, "
+ "hour datetime, min datetime, sec datetime)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ stmt_text= "INSERT INTO t1 VALUES (?, ?, ?, ?, ?, ?)";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(mysql_stmt_param_count(stmt) != 6, "param_count != 6");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i= 0; i < 6; i++)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_DATETIME;
+ my_bind[i].buffer= &tm[i];
+ }
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ tm[0].year= 2004; tm[0].month= 11; tm[0].day= 10;
+ tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
+ tm[0].second_part= 0; tm[0].neg= 0;
+
+ tm[5]= tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
+ tm[0].year= 10000; tm[1].month= 13; tm[2].day= 32;
+ tm[3].hour= 24; tm[4].minute= 60; tm[5].second= 60;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(!mysql_warning_count(mysql), "warnings expected");
+
+ if (verify_col_data(mysql, "t1", "year", "0000-00-00 00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "month", "0000-00-00 00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "day", "0000-00-00 00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "hour", "0000-00-00 00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "min", "0000-00-00 00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "sec", "0000-00-00 00:00:00"))
+ goto error;
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "delete from t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "INSERT INTO t1 (year, month, day) VALUES (?, ?, ?)";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ /*
+ We reuse contents of bind and tm arrays left from previous part of test.
+ */
+ for (i= 0; i < 3; i++)
+ my_bind[i].buffer_type= MYSQL_TYPE_DATE;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(!mysql_warning_count(mysql), "warnings expected");
+
+ if (verify_col_data(mysql, "t1", "year", "0000-00-00 00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "month", "0000-00-00 00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "day", "0000-00-00 00:00:00"))
+ goto error;
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "create table t1 (day_ovfl time, day time, hour time, min time, sec time)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ stmt_text= "INSERT INTO t1 VALUES (?,?,?,?,?)";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(mysql_stmt_param_count(stmt) != 5, "param_count != 5");
+
+ /*
+ Again we reuse what we can from previous part of test.
+ */
+ for (i= 0; i < 5; i++)
+ my_bind[i].buffer_type= MYSQL_TYPE_TIME;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ tm[0].year= 0; tm[0].month= 0; tm[0].day= 10;
+ tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
+ tm[0].second_part= 0; tm[0].neg= 0;
+
+ tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
+ tm[0].day= 35; tm[1].day= 34; tm[2].hour= 30; tm[3].minute= 60; tm[4].second= 60;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(mysql_warning_count(mysql) != 2, "warning_count != 2");
+
+ if (verify_col_data(mysql, "t1", "day_ovfl", "838:59:59"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "day", "828:30:30"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "hour", "270:30:30"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "min", "00:00:00"))
+ goto error;
+ if (verify_col_data(mysql, "t1", "sec", "00:00:00"))
+ goto error;
+
+ mysql_stmt_close(stmt);
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+error:
+ mysql_stmt_close(stmt);
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_derived(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ MYSQL_BIND my_bind[1];
+ int32 my_val= 0;
+ ulong my_length= 0L;
+ my_bool my_null= FALSE;
+ const char *query=
+ "select count(1) from (select f.id from t1 f where f.id=?) as x";
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (id int(8), primary key (id)) \
+ENGINE=InnoDB DEFAULT CHARSET=utf8");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values (1)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&my_val;
+ my_bind[0].length= &my_length;
+ my_bind[0].is_null= &my_null;
+ my_val= 1;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_distinct(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query=
+ "SELECT 2+count(distinct b), group_concat(a) FROM t1 group by a";
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), \
+(1, 10), (2, 20), (3, 30), (4, 40), (5, 50);");
+ check_mysql_rc(rc, mysql);
+
+ for (i= 0; i < 3; i++)
+ {
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 5, "rowcount != 5");
+ mysql_stmt_close(stmt);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_do_set(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt_do, *stmt_set;
+ char *query;
+ int rc, i;
+
+ // XPAND doesn't support DO command
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ query= (char*)"do @var:=(1 in (select * from t1))";
+ stmt_do= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_do, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_do, SL(query));
+ check_stmt_rc(rc, stmt_do);
+
+ query= (char*)"set @var=(1 in (select * from t1))";
+ stmt_set= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_set, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_set, SL(query));
+ check_stmt_rc(rc, stmt_set);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt_do);
+ check_stmt_rc(rc, stmt_do);
+ rc= mysql_stmt_execute(stmt_set);
+ check_stmt_rc(rc, stmt_set);
+ }
+
+ mysql_stmt_close(stmt_do);
+ mysql_stmt_close(stmt_set);
+ return OK;
+}
+
+static int test_double_compare(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char real_data[10], tiny_data;
+ double double_data;
+ MYSQL_RES *result;
+ MYSQL_BIND my_bind[3];
+ ulong length[3];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_double_compare");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_double_compare(col1 tinyint, "
+ " col2 float, col3 double )");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_double_compare "
+ "VALUES (1, 10.2, 34.5)");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "UPDATE test_double_compare SET col1=100 "
+ "WHERE col1 = ? AND col2 = ? AND COL3 = ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 3, "param_count != 3");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /* tinyint */
+ my_bind[0].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[0].buffer= (void *)&tiny_data;
+
+ /* string->float */
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)&real_data;
+ my_bind[1].buffer_length= sizeof(real_data);
+ my_bind[1].length= &length[1];
+
+ /* double */
+ my_bind[2].buffer_type= MYSQL_TYPE_DOUBLE;
+ my_bind[2].buffer= (void *)&double_data;
+
+ tiny_data= 1;
+ strcpy(real_data, "10.2");
+ length[1]= (ulong)strlen(real_data);
+ double_data= 34.5;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt), "affected_rows != 0");
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* test the results now, only one row should exist */
+ rc= mysql_query(mysql, "SELECT * FROM test_double_compare");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS((int)tiny_data == rc, "rowcount != tinydata");
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_double_compare");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_multi(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt_delete, *stmt_update, *stmt_select1, *stmt_select2;
+ char *query;
+ MYSQL_BIND my_bind[1];
+ int rc, i;
+ int32 param= 1;
+ ulong length= 1;
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&param;
+ my_bind[0].length= &length;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (a int, b int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t2 (a int, b int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values (3, 3), (2, 2), (1, 1)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t2 values (3, 3), (2, 2), (1, 1)");
+ check_mysql_rc(rc, mysql);
+
+ query= (char*)"delete t1, t2 from t1, t2 where t1.a=t2.a and t1.b=10";
+ stmt_delete= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_delete, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_delete, SL(query));
+ check_stmt_rc(rc, stmt_delete);
+
+ query= (char*)"update t1, t2 set t1.b=10, t2.b=10 where t1.a=t2.a and t1.b=?";
+ stmt_update= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_update, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_update, SL(query));
+ check_stmt_rc(rc, stmt_update);
+
+ query= (char*)"select * from t1";
+ stmt_select1= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_select1, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_select1, SL(query));
+ check_stmt_rc(rc, stmt_select1);
+
+ query= (char*)"select * from t2";
+ stmt_select2= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_select2, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_select2, SL(query));
+ check_stmt_rc(rc, stmt_select2);
+
+ for(i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_bind_param(stmt_update, my_bind);
+ check_stmt_rc(rc, stmt_update);
+
+ rc= mysql_stmt_execute(stmt_update);
+ check_stmt_rc(rc, stmt_update);
+
+ rc= mysql_stmt_execute(stmt_delete);
+ check_stmt_rc(rc, stmt_delete);
+
+ rc= mysql_stmt_execute(stmt_select1);
+ check_stmt_rc(rc, stmt_select1);
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt_select1))
+ rc++;
+ FAIL_UNLESS(rc == 3-param, "rc != 3 - param");
+
+ rc= mysql_stmt_execute(stmt_select2);
+ check_stmt_rc(rc, stmt_select2);
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt_select2))
+ rc++;
+ FAIL_UNLESS(rc == 3-param, "rc != 3 - param");
+
+ param++;
+ }
+
+ mysql_stmt_close(stmt_delete);
+ mysql_stmt_close(stmt_update);
+ mysql_stmt_close(stmt_select1);
+ mysql_stmt_close(stmt_select2);
+ rc= mysql_query(mysql, "drop table t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Multiple stmts .. */
+
+static int test_multi_stmt(MYSQL *mysql)
+{
+
+ MYSQL_STMT *stmt, *stmt1, *stmt2;
+ int rc;
+ uint32 id;
+ char name[50];
+ MYSQL_BIND my_bind[2];
+ ulong length[2];
+ my_bool is_null[2];
+ const char *query;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_multi_table");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_multi_table(id int, name char(20))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_multi_table values(10, 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ query= "SELECT * FROM test_multi_table WHERE id=?";
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ stmt2= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt2, mysql_error(mysql));
+ query= "UPDATE test_multi_table SET name='updated' WHERE id=10";
+ rc= mysql_stmt_prepare(stmt2, SL(query));
+ check_stmt_rc(rc, stmt2);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "param_count != 1");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&id;
+ my_bind[0].is_null= &is_null[0];
+ my_bind[0].length= &length[0];
+ is_null[0]= 0;
+ length[0]= 0;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)name;
+ my_bind[1].buffer_length= sizeof(name);
+ my_bind[1].length= &length[1];
+ my_bind[1].is_null= &is_null[1];
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ id= 10;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ id= 999;
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(id == 10, "id != 10");
+ FAIL_UNLESS(strcmp(name, "mysql") == 0, "name != 'mysql'");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "");
+
+ /* alter the table schema now */
+ stmt1= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt1, mysql_error(mysql));
+ query= "DELETE FROM test_multi_table WHERE id=? AND CONVERT(name USING utf8)=?";
+ rc= mysql_stmt_prepare(stmt1, SL(query));
+ check_stmt_rc(rc, stmt1);
+
+ FAIL_IF(mysql_stmt_param_count(stmt1) != 2, "param_count != 2");
+
+ rc= mysql_stmt_bind_param(stmt1, my_bind);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_execute(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt2) != 1, "affected_rows != 1");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(id == 10, "id != 10");
+ FAIL_UNLESS(strcmp(name, "updated") == 0, "name != 'updated'");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt1) != 1, "affected_rows != 1");
+
+ mysql_stmt_close(stmt1);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ rc= my_stmt_result(mysql, "SELECT * FROM test_multi_table");
+ FAIL_UNLESS(rc == 0, "rc != 0");
+
+ mysql_stmt_close(stmt);
+ mysql_stmt_close(stmt2);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_multi_table");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Test 'n' statements create and close */
+
+static int test_nstmts(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ char query[255];
+ int rc;
+ static uint i, total_stmts= 2000;
+ MYSQL_BIND my_bind[1];
+
+ SKIP_SKYSQL;
+
+ mysql_autocommit(mysql, TRUE);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_nstmts");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_nstmts(id int)");
+ check_mysql_rc(rc, mysql);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer= (void *)&i;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+
+ for (i= 0; i < total_stmts; i++)
+ {
+ strcpy(query, "insert into test_nstmts values(?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ }
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(" select count(*) from test_nstmts"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ i= 0;
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS( i == total_stmts, "total_stmts != i");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE test_nstmts");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test simple null */
+
+static int test_null(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ uint nData;
+ MYSQL_BIND my_bind[2];
+ my_bool is_null[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_null");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_null(col1 int, col2 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "FLUSH TABLES");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "START TRANSACTION");
+ check_mysql_rc(rc, mysql);
+
+ /* insert by prepare, wrong column name */
+ strcpy(query, "INSERT INTO test_null(col3, col2) VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ FAIL_IF(!rc, "Error expected");
+ mysql_stmt_close(stmt);
+
+ strcpy(query, "INSERT INTO test_null(col1, col2) VALUES(?, ?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "param_count != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].is_null= &is_null[0];
+ is_null[0]= 1;
+ my_bind[1]= my_bind[0];
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ /* now, execute the prepared statement to insert 10 records.. */
+ for (nData= 0; nData<10; nData++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ /* Re-bind with MYSQL_TYPE_NULL */
+ my_bind[0].buffer_type= MYSQL_TYPE_NULL;
+ is_null[0]= 0; /* reset */
+ my_bind[1]= my_bind[0];
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ for (nData= 0; nData<10; nData++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ mysql_stmt_close(stmt);
+
+ /* now fetch the results ..*/
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ nData*= 2;
+ rc= my_stmt_result(mysql, "SELECT * FROM test_null");;
+ FAIL_UNLESS((int) nData == rc, "rc != ndata");
+
+ /* Fetch results */
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&nData; /* this buffer won't be altered */
+ my_bind[0].length= 0;
+ my_bind[1]= my_bind[0];
+ my_bind[0].is_null= &is_null[0];
+ my_bind[1].is_null= &is_null[1];
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_null"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ is_null[0]= is_null[1]= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ FAIL_UNLESS(is_null[0], "!is_null");
+ FAIL_UNLESS(is_null[1], "!is_null");
+ rc++;
+ is_null[0]= is_null[1]= 0;
+ }
+ FAIL_UNLESS(rc == (int) nData, "rc != nData");
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_null");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_order_param(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *query;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1(a INT, b char(10))");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ query= "select sum(a) + 200, 1 from t1 "
+ " union distinct "
+ "select sum(a) + 200, 1 from t1 group by b ";
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ query= "select sum(a) + 200, ? from t1 group by b "
+ " union distinct "
+ "select sum(a) + 200, 1 from t1 group by b ";
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ query= "select sum(a) + 200, ? from t1 "
+ " union distinct "
+ "select sum(a) + 200, 1 from t1 group by b ";
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_rename(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *query= "rename table t1 to t2, t3 to t4";
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3, t4");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "create table t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_query(mysql, "create table t3 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, "Errr expected");
+
+ rc= mysql_query(mysql, "rename table t2 to t1, t4 to t3");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t2, t4");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_rewind(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind;
+ int rc = 0;
+ const char *stmt_text;
+ long unsigned int length=4, Data=0;
+ my_bool isnull=0;
+
+
+ stmt_text= "CREATE TABLE t1 (a int)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "INSERT INTO t1 VALUES(2),(3),(4)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT * FROM t1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ memset(&my_bind, '\0', sizeof(MYSQL_BIND));
+ my_bind.buffer_type= MYSQL_TYPE_LONG;
+ my_bind.buffer= (void *)&Data; /* this buffer won't be altered */
+ my_bind.length= &length;
+ my_bind.is_null= &isnull;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, &my_bind);
+ check_stmt_rc(rc, stmt);
+
+ /* retrieve all result sets till we are at the end */
+ while(!(rc=mysql_stmt_fetch(stmt)));
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ /* seek to the first row */
+ mysql_stmt_data_seek(stmt, 0);
+
+ /* now we should be able to fetch the results again */
+ /* but mysql_stmt_fetch returns MYSQL_NO_DATA */
+ while(!(rc= mysql_stmt_fetch(stmt)));
+
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ stmt_text= "DROP TABLE t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ rc= mysql_stmt_free_result(stmt);
+ rc= mysql_stmt_close(stmt);
+ return OK;
+}
+
+/* Test simple select */
+
+static int test_select(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char szData[25];
+ int nData= 1;
+ MYSQL_BIND my_bind[2];
+ ulong length[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id int, name varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* insert a row and commit the transaction */
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 'venu')");
+ check_mysql_rc(rc, mysql);
+
+ /* now insert the second row, and roll back the transaction */
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(20, 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ strcpy(query, "SELECT * FROM test_select WHERE id= ? "
+ "AND CONVERT(name USING utf8) =?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "param_count != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ /* string data */
+ nData= 10;
+ strcpy(szData, (char *)"venu");
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)szData;
+ my_bind[1].buffer_length= 4;
+ my_bind[1].length= &length[1];
+ length[1]= 4;
+
+ my_bind[0].buffer= (void *)&nData;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rc != 1");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test simple select with prepare */
+
+static int test_select_prepare(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id int, name varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* insert a row and commit the transaction */
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 'venu')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_select"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE test_select");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_select(id tinyint, id1 int, "
+ " id2 float, id3 float, "
+ " name varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* insert a row and commit the transaction */
+ rc= mysql_query(mysql, "INSERT INTO test_select(id, id1, id2, name) VALUES(10, 5, 2.3, 'venu')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_select"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test simple show */
+
+static int test_select_show_table(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SHOW TABLES FROM mysql"));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt), "param_count != 0");
+
+ for (i= 1; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ while (!mysql_stmt_fetch(stmt));
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+/* Test simple select */
+
+static int test_select_version(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT @@version"));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt), "param_count != 0");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ while (!mysql_stmt_fetch(stmt));
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_selecttmp(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query= "select a, (select count(distinct t1.b) as sum from t1, t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3";
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t2 (a int, b int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t3 (a int, b int);");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "insert into t1 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7), \
+(2, -1), (3, 10);");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "insert into t2 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1);");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "insert into t3 values (3, 3), (2, 2), (1, 1);");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 3, "rowcount != 3");
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1, t2, t3");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_set_option(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ int rc;
+
+
+ mysql_autocommit(mysql, TRUE);
+
+ /* LIMIT the rows count to 2 */
+ rc= mysql_query(mysql, "SET SQL_SELECT_LIMIT= 2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_limit");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_limit(a tinyint)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_limit VALUES(10), (20), (30), (40)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT * FROM test_limit");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 2, "rowcount != 2");
+ mysql_free_result(result);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_limit"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 2, "");
+
+ mysql_stmt_close(stmt);
+
+ /* RESET the LIMIT the rows count to 0 */
+ rc= mysql_query(mysql, "SET SQL_SELECT_LIMIT=DEFAULT");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_limit"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 4, "rowcount != 4");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_limit");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test simple set-variable prepare */
+
+static int test_set_variable(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt, *stmt1;
+ int rc;
+ int set_count, def_count, get_count;
+ ulong length;
+ char var[NAME_LEN+1];
+ MYSQL_BIND set_bind[1], get_bind[2];
+
+
+ mysql_autocommit(mysql, TRUE);
+
+ stmt1= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt1, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt1, SL("show variables like 'max_error_count'"));
+ check_stmt_rc(rc, stmt1);
+
+ memset(get_bind, '\0', sizeof(get_bind));
+
+ get_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ get_bind[0].buffer= (void *)var;
+ get_bind[0].length= &length;
+ get_bind[0].buffer_length= (int)NAME_LEN;
+ length= NAME_LEN;
+
+ get_bind[1].buffer_type= MYSQL_TYPE_LONG;
+ get_bind[1].buffer= (void *)&get_count;
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_bind_result(stmt1, get_bind);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ def_count= get_count;
+
+ FAIL_UNLESS(strcmp(var, "max_error_count") == 0, "var != max_error_count");
+ rc= mysql_stmt_fetch(stmt1);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("set max_error_count=?"));
+ check_stmt_rc(rc, stmt);
+
+ memset(set_bind, '\0', sizeof(set_bind));
+
+ set_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ set_bind[0].buffer= (void *)&set_count;
+
+ rc= mysql_stmt_bind_param(stmt, set_bind);
+ check_stmt_rc(rc, stmt);
+
+ set_count= 31;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_commit(mysql);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ FAIL_UNLESS(get_count == set_count, "get_count != set_count");
+
+ rc= mysql_stmt_fetch(stmt1);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ /* restore back to default */
+ set_count= def_count;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ rc= mysql_stmt_fetch(stmt1);
+ check_stmt_rc(rc, stmt1);
+
+ FAIL_UNLESS(get_count == set_count, "get_count != set_count");
+
+ rc= mysql_stmt_fetch(stmt1);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ mysql_stmt_close(stmt1);
+ return OK;
+}
+
+/* Test SQLmode */
+
+static int test_sqlmode(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ char c1[5], c2[5];
+ int rc;
+ int ignore_space= 0;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_piping");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_piping(name varchar(10))");
+ check_mysql_rc(rc, mysql);
+
+ /* PIPES_AS_CONCAT */
+ strcpy(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)c1;
+ my_bind[0].buffer_length= 2;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= (void *)c2;
+ my_bind[1].buffer_length= 3;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ strcpy(c1, "My"); strcpy(c2, "SQL");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ if (verify_col_data(mysql, "test_piping", "name", "MySQL"))
+ return FAIL;
+
+ rc= mysql_query(mysql, "DELETE FROM test_piping");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "SELECT connection_id ()");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ /* ANSI */
+ strcpy(query, "SET SQL_MODE= \"ANSI\"");
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ strcpy(c1, "My"); strcpy(c2, "SQL");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ if (verify_col_data(mysql, "test_piping", "name", "MySQL"))
+ return FAIL;
+
+ /* ANSI mode spaces ...
+ skip, if ignore_space was set
+ */
+ query_int_variable(mysql, "@@sql_mode LIKE '%IGNORE_SPACE%'", &ignore_space);
+
+ if (!ignore_space)
+ {
+ strcpy(query, "SELECT connection_id ()");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ }
+ /* IGNORE SPACE MODE */
+ strcpy(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "SELECT connection_id ()");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_piping");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test mysql_stmt_close for open stmts */
+
+static int test_stmt_close(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt1, *stmt2, *stmt3, *stmt_x;
+ MYSQL_BIND my_bind[1];
+ MYSQL_RES *result;
+ unsigned int count;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+ my_bool reconnect= 1;
+
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+
+ /* set AUTOCOMMIT to ON*/
+ mysql_autocommit(mysql, TRUE);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stmt_close");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_stmt_close(id int)");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "DO \"nothing\"");
+ stmt1= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt1, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt1, SL(query));
+ check_stmt_rc(rc, stmt1);
+
+ FAIL_IF(mysql_stmt_param_count(stmt1), "param_count != 0");
+
+ strcpy(query, "INSERT INTO test_stmt_close(id) VALUES(?)");
+ stmt_x= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt_x, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt_x, SL(query));
+ check_stmt_rc(rc, stmt_x);
+
+ FAIL_IF(mysql_stmt_param_count(stmt_x) != 1, "param_count != 1");
+
+ strcpy(query, "UPDATE test_stmt_close SET id= ? WHERE id= ?");
+ stmt3= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt3, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt3, SL(query));
+ check_stmt_rc(rc, stmt3);
+
+ FAIL_IF(mysql_stmt_param_count(stmt3) != 2, "param_count != 2");
+
+ strcpy(query, "SELECT * FROM test_stmt_close WHERE id= ?");
+ stmt2= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt2, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt2, SL(query));
+ check_stmt_rc(rc, stmt2);
+
+ FAIL_IF(mysql_stmt_param_count(stmt2) != 1, "param_count != 1");
+
+ rc= mysql_stmt_close(stmt1);
+
+ /*
+ Originally we were going to close all statements automatically in
+ mysql_close(). This proved to not work well - users weren't able to
+ close statements by hand once mysql_close() had been called.
+ Now mysql_close() doesn't free any statements, so this test doesn't
+ serve its original designation any more.
+ Here we free stmt2 and stmt3 by hand to avoid memory leaks.
+ */
+ mysql_stmt_close(stmt2);
+ mysql_stmt_close(stmt3);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer= (void *)&count;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ count= 100;
+
+ rc= mysql_stmt_bind_param(stmt_x, my_bind);
+ check_stmt_rc(rc, stmt_x);
+
+ rc= mysql_stmt_execute(stmt_x);
+ check_stmt_rc(rc, stmt_x);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt_x) != 1, "affected_rows != 1");
+
+ rc= mysql_stmt_close(stmt_x);
+ check_stmt_rc(rc, stmt_x);
+
+ rc= mysql_query(mysql, "SELECT id FROM test_stmt_close");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rwcount != 1");
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stmt_close");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_new_date(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ int rc;
+ char buffer[50];
+ my_bool reconnect= 1;
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
+
+ /* set AUTOCOMMIT to ON*/
+ mysql_autocommit(mysql, TRUE);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a date, b date)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (now(), now() + INTERVAL 1 day)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, "SELECT if(1, a, b) FROM t1", 26);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer_length= 50;
+ bind[0].buffer= (void *)buffer;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc != MYSQL_NO_DATA, "NO DATA expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_long_data1(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind[1];
+ char query[MAX_TEST_QUERY_LENGTH];
+ const char *data= "12345";
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS tld");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE tld (col1 int, "
+ "col2 MEDIUMTEXT)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO tld VALUES (1,'test')");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "UPDATE tld SET col2=? WHERE col1=1");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_send_long_data(stmt, 0, data, 6);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS tld");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+int test_blob_9000(MYSQL *mysql)
+{
+ MYSQL_BIND bind[1];
+ MYSQL_STMT *stmt;
+ int rc;
+ char buffer[9200];
+ const char *query= "INSERT INTO tb9000 VALUES (?)";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS tb9000");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE tb9000 (a blob)");
+ check_mysql_rc(rc, mysql);
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ memset(buffer, 'C', 9200);
+ bind[0].buffer= buffer;
+ bind[0].buffer_length= 9200;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS tb9000");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+int test_fracseconds(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *str= "SELECT NOW(6)";
+ char buffer[60], buffer1[60];
+ MYSQL_BIND bind[2];
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(str));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer= buffer;
+ bind[0].buffer_length=60;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(strlen(buffer) != 26, "Expected timestamp with length of 26");
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a timestamp(6), b time(6))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES ('2012-04-25 10:20:49.0194','10:20:49.0194' )");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, "SELECT a,b FROM t1", 18);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+ bind[0].buffer= buffer;
+ bind[1].buffer= buffer1;
+ bind[0].buffer_length= bind[1].buffer_length= 60;
+ bind[0].buffer_type= bind[1].buffer_type= MYSQL_TYPE_STRING;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(strcmp(buffer, "2012-04-25 10:20:49.019400") != 0, "Wrong result");
+ FAIL_IF(strcmp(buffer1, "10:20:49.019400") != 0, "Wrong result");
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+
+ return OK;
+}
+
+int test_notrunc(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ my_bool trunc= 1;
+ MYSQL_BIND bind[2];
+ char buffer[5], buffer2[5];
+ int rc;
+ my_bool error= 0;
+ unsigned long len= 1;
+
+ const char *query= "SELECT '1234567890', 'foo' FROM DUAL";
+
+ mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &trunc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ strcpy(buffer, "bar");
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 2);
+ bind[0].buffer_type= MYSQL_TYPE_NULL;
+ bind[0].buffer= buffer;
+ bind[0].buffer_length= 1;
+ bind[0].length= &len;
+ bind[0].flags|= MADB_BIND_DUMMY;
+ bind[0].error= &error;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= buffer2;
+ bind[1].buffer_length= 5;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_store_result(stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ mysql_stmt_close(stmt);
+
+ FAIL_IF(rc!= 0, "expected rc= 0");
+ FAIL_IF(strcmp(buffer, "bar"), "Bind dummy failed");
+ FAIL_IF(strcmp(buffer2, "foo"), "Invalid second buffer");
+
+ return OK;
+}
+
+static int test_bit2tiny(MYSQL *mysql)
+{
+ MYSQL_BIND bind[2];
+ char data[11];
+ unsigned long length[2];
+ my_bool is_null[2], error[2];
+ const char *query = "SELECT val FROM justbit";
+ MYSQL_STMT *stmt;
+ int rc;
+
+ mysql_query(mysql, "DROP TABLE IF EXISTS justbit");
+ mysql_query(mysql, "CREATE TABLE justbit(val bit(1) not null)");
+ mysql_query(mysql, "INSERT INTO justbit values (1)");
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, '\0', sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_TINY;
+ bind[0].buffer= &data[0];
+ bind[0].buffer_length= 1;
+ bind[0].is_null= &is_null[0];
+ bind[0].length= &length[0];
+ bind[0].error= &error[0];
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_fetch(stmt);
+
+ FAIL_IF(data[0] != 1, "Value should be 1");
+
+ mysql_stmt_free_result(stmt);
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS justbit");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_reexecute(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND ps_params[3]; /* input parameter buffers */
+ int int_data[3]; /* input/output values */
+ int rc;
+
+ if (!mariadb_connection(mysql))
+ return SKIP;
+
+ /* set up stored procedure */
+ rc = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ rc = mysql_query(mysql,
+ "CREATE PROCEDURE p1("
+ " IN p_in INT, "
+ " OUT p_out INT, "
+ " INOUT p_inout INT) "
+ "BEGIN "
+ " SELECT p_in, p_out, p_inout; "
+ " SET p_in = 100, p_out = 200, p_inout = 300; "
+ " SELECT p_in, p_out, p_inout; "
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ /* initialize and prepare CALL statement with parameter placeholders */
+ stmt = mysql_stmt_init(mysql);
+ if (!stmt)
+ {
+ diag("Could not initialize statement");
+ exit(1);
+ }
+ rc = mysql_stmt_prepare(stmt, "CALL p1(?, ?, ?)", 16);
+ check_stmt_rc(rc, stmt);
+
+ /* initialize parameters: p_in, p_out, p_inout (all INT) */
+ memset(ps_params, 0, sizeof (ps_params));
+
+ ps_params[0].buffer_type = MYSQL_TYPE_LONG;
+ ps_params[0].buffer = (char *) &int_data[0];
+ ps_params[0].length = 0;
+ ps_params[0].is_null = 0;
+
+ ps_params[1].buffer_type = MYSQL_TYPE_LONG;
+ ps_params[1].buffer = (char *) &int_data[1];
+ ps_params[1].length = 0;
+ ps_params[1].is_null = 0;
+
+ ps_params[2].buffer_type = MYSQL_TYPE_LONG;
+ ps_params[2].buffer = (char *) &int_data[2];
+ ps_params[2].length = 0;
+ ps_params[2].is_null = 0;
+
+ /* bind parameters */
+ rc = mysql_stmt_bind_param(stmt, ps_params);
+ check_stmt_rc(rc, stmt);
+
+ /* assign values to parameters and execute statement */
+ int_data[0]= 10; /* p_in */
+ int_data[1]= 20; /* p_out */
+ int_data[2]= 30; /* p_inout */
+
+ rc = mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_prepare_error(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT 1 FROM tbl_not_exists"));
+ FAIL_IF(!rc, "Expected error");
+
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT 1 FROM tbl_not_exists"));
+ FAIL_IF(!rc, "Expected error");
+
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_prepare(stmt, SL("SET @a:=1"));
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_conc349(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+ enum mysql_stmt_state state;
+
+ rc= mysql_stmt_attr_get(stmt, STMT_ATTR_STATE, &state);
+ FAIL_IF(state != MYSQL_STMT_INITTED, "expected status MYSQL_STMT_INITTED");
+
+ rc= mysql_stmt_prepare(stmt, SL("SET @a:=1"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_get(stmt, STMT_ATTR_STATE, &state);
+ FAIL_IF(state != MYSQL_STMT_PREPARED, "expected status MYSQL_STMT_PREPARED");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_get(stmt, STMT_ATTR_STATE, &state);
+ FAIL_IF(state != MYSQL_STMT_EXECUTED, "expected status MYSQL_STMT_EXECUTED");
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_conc565(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_FIELD *fields_binary, *fields_text;
+ MYSQL_RES *result;
+ int rc;
+ unsigned int i;
+ my_bool x=1;
+ my_bool error= 0;
+
+ rc= mysql_query(mysql, "CREATE TEMPORARY TABLE t1 (a year, b tinyint unsigned, c smallint unsigned, d mediumint unsigned, e int unsigned, f bigint unsigned)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (2020, 127, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, "select a,b,c,d,e,f from t1", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void *)&x);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_store_result(stmt);
+ fields_binary= mariadb_stmt_fetch_fields(stmt);
+
+ rc= mysql_query(mysql, "SELECT a,b,c,d,e,f FROM t1");
+ result= mysql_store_result(mysql);
+ fields_text= mysql_fetch_fields(result);
+
+ for (i=0; i < mysql_field_count(mysql); i++)
+ {
+ if (fields_binary[i].length != fields_text[i].length ||
+ fields_binary[i].max_length != fields_text[i].max_length)
+ {
+ diag("Sizes differ for column %d (type= %d)", i, fields_binary[i].type);
+ diag("Binary (length=%ld max_length=%ld) != Text(length=%ld max_length=%ld",
+ fields_binary[i].length, fields_binary[i].max_length,
+ fields_text[i].length, fields_text[i].max_length);
+ error= 1;
+ goto end;
+ }
+ }
+end:
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ return error ? FAIL : OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc565", test_conc565, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc349", test_conc349, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_prepare_error", test_prepare_error, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_reexecute", test_reexecute, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_bit2tiny", test_bit2tiny, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc97", test_conc97, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc83", test_conc83, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc60", test_conc60, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_notrunc", test_notrunc, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_fracseconds", test_fracseconds, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_blob_9000", test_blob_9000, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_long_data1", test_long_data1, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_insert_update", test_prepare_insert_update, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_simple", test_prepare_simple, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_syntax", test_prepare_syntax, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_field_result", test_prepare_field_result, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare", test_prepare, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_ext", test_prepare_ext, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_multi_statements", test_prepare_multi_statements, TEST_CONNECTION_NEW, 0, NULL , NULL},
+ {"test_prepare_alter", test_prepare_alter, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_resultset", test_prepare_resultset, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_open_direct", test_open_direct, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_select_show", test_select_show, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_select", test_select, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_long_data", test_long_data, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_long_data_str", test_long_data_str, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_long_data_str1", test_long_data_str1, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_long_data_bin", test_long_data_bin, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_simple_update", test_simple_update, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_simple_delete", test_simple_delete, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_update", test_update, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_prepare_noparam", test_prepare_noparam, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bind_result", test_bind_result, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bind_result_ext", test_bind_result_ext, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bind_result_ext1", test_bind_result_ext1, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bind_negative", test_bind_negative, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_buffers", test_buffers, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_xjoin", test_xjoin, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_union", test_union, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_union2", test_union2, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_union_param", test_union_param, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_pure_coverage", test_pure_coverage, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_insert_select", test_insert_select, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_insert", test_insert, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_join", test_join, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_left_join_view", test_left_join_view, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_manual_sample", test_manual_sample, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_create_drop", test_create_drop, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_date", test_date, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_date_ts", test_date_ts, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_date_dt", test_date_dt, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_date_date", test_date_date, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_date_time", test_date_time, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_datetime_ranges", test_datetime_ranges, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_derived", test_derived, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_distinct", test_distinct, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_do_set", test_do_set, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_double_compare", test_double_compare, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_multi", test_multi, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_multi_stmt", test_multi_stmt, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_nstmts", test_nstmts, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_null", test_null, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_order_param", test_order_param, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_rename", test_rename, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_rewind", test_rewind, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_select_prepare", test_select_prepare, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_select_show_table", test_select_show_table, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_select_version", test_select_version, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_selecttmp", test_selecttmp, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_set_option", test_set_option, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_set_variable", test_set_variable, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_sqlmode", test_sqlmode, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_stmt_close", test_stmt_close, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_new_date", test_new_date, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/ps_bugs.c b/libmariadb/unittest/libmariadb/ps_bugs.c
new file mode 100644
index 00000000..efe3d447
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/ps_bugs.c
@@ -0,0 +1,5846 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+#include <math.h>
+
+#define MY_INT64_NUM_DECIMAL_DIGITS 21
+#define MAX_INDEXES 64
+
+/* A workaround for Sun Forte 5.6 on Solaris x86 */
+
+static int cmp_double(double *a, double *b)
+{
+ return *a == *b;
+ return OK;
+}
+
+/* Test BUG#1115 (incorrect string parameter value allocation) */
+
+static int test_conc67(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ const char *query= "SELECT a,b FROM conc67 WHERE a=?";
+ int rc, i;
+ MYSQL_BIND bind[2];
+ char val[20];
+ MYSQL_BIND rbind;
+ MYSQL_RES *res;
+ ulong prefetch_rows= 1000;
+ ulong cursor_type= CURSOR_TYPE_READ_ONLY;
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc67");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE conc67 (a int, b text)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO conc67 VALUES (1, 'foo')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, &prefetch_rows);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ memset(&rbind, 0, sizeof(MYSQL_BIND));
+ i= 1;
+ rbind.buffer_type= MYSQL_TYPE_LONG;
+ rbind.buffer= &i;
+ rbind.buffer_length= 4;
+ mysql_stmt_bind_param(stmt, &rbind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ res= mysql_stmt_result_metadata(stmt);
+ mysql_free_result(res);
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+
+ i= 0;
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= &i;
+ bind[0].buffer_length= 4;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= &val;
+ bind[1].buffer_length= 20;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(i != 1, "expected value 1 for first row");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc != MYSQL_NO_DATA, "Eof expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc67");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug1115(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, rowcount;
+ MYSQL_BIND my_bind[1];
+ ulong length[1];
+ char szData[11];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_select(\
+session_id char(9) NOT NULL, \
+ a int(8) unsigned NOT NULL, \
+ b int(5) NOT NULL, \
+ c int(5) NOT NULL, \
+ d datetime NOT NULL)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES "
+ "(\"abc\", 1, 2, 3, 2003-08-30), "
+ "(\"abd\", 1, 2, 3, 2003-08-30), "
+ "(\"abf\", 1, 2, 3, 2003-08-30), "
+ "(\"abg\", 1, 2, 3, 2003-08-30), "
+ "(\"abh\", 1, 2, 3, 2003-08-30), "
+ "(\"abj\", 1, 2, 3, 2003-08-30), "
+ "(\"abk\", 1, 2, 3, 2003-08-30), "
+ "(\"abl\", 1, 2, 3, 2003-08-30), "
+ "(\"abq\", 1, 2, 3, 2003-08-30) ");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES "
+ "(\"abw\", 1, 2, 3, 2003-08-30), "
+ "(\"abe\", 1, 2, 3, 2003-08-30), "
+ "(\"abr\", 1, 2, 3, 2003-08-30), "
+ "(\"abt\", 1, 2, 3, 2003-08-30), "
+ "(\"aby\", 1, 2, 3, 2003-08-30), "
+ "(\"abu\", 1, 2, 3, 2003-08-30), "
+ "(\"abi\", 1, 2, 3, 2003-08-30), "
+ "(\"abo\", 1, 2, 3, 2003-08-30), "
+ "(\"abp\", 1, 2, 3, 2003-08-30), "
+ "(\"abz\", 1, 2, 3, 2003-08-30), "
+ "(\"abx\", 1, 2, 3, 2003-08-30)");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "SELECT * FROM test_select WHERE "
+ "CONVERT(session_id USING utf8)= ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "Paramcount != 1");
+
+ memset(my_bind, '\0', sizeof(MYSQL_BIND));
+
+ strcpy(szData, (char *)"abc");
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)szData;
+ my_bind[0].buffer_length= 10;
+ my_bind[0].length= &length[0];
+ length[0]= 3;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount=%d != 1");
+
+ strcpy(szData, (char *)"venu");
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)szData;
+ my_bind[0].buffer_length= 10;
+ my_bind[0].length= &length[0];
+ length[0]= 4;
+ my_bind[0].is_null= 0;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 0, "rowcount != 0");
+
+ strcpy(szData, (char *)"abc");
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)szData;
+ my_bind[0].buffer_length= 10;
+ my_bind[0].length= &length[0];
+ length[0]= 3;
+ my_bind[0].is_null= 0;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+/* Test BUG#1180 (optimized away part of WHERE clause) */
+
+static int test_bug1180(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, rowcount;
+ MYSQL_BIND my_bind[1];
+ ulong length[1];
+ char szData[11];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_select(session_id char(9) NOT NULL)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_select VALUES (\"abc\")");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "SELECT * FROM test_select WHERE ?= \"1111\" and "
+ "session_id= \"abc\"");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "Paramcount != 1");
+
+ memset(my_bind, '\0', sizeof(MYSQL_BIND));
+
+ strcpy(szData, (char *)"abc");
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)szData;
+ my_bind[0].buffer_length= 10;
+ my_bind[0].length= &length[0];
+ length[0]= 3;
+ my_bind[0].is_null= 0;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 0, "rowcount != 0");
+
+ strcpy(szData, (char *)"1111");
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)szData;
+ my_bind[0].buffer_length= 10;
+ my_bind[0].length= &length[0];
+ length[0]= 4;
+ my_bind[0].is_null= 0;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 1, "rowcount != 1");
+
+ strcpy(szData, (char *)"abc");
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)szData;
+ my_bind[0].buffer_length= 10;
+ my_bind[0].length= &length[0];
+ length[0]= 3;
+ my_bind[0].is_null= 0;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rowcount= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 0, "rowcount != 0");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/*
+ Test BUG#1644 (Insertion of more than 3 NULL columns with parameter
+ binding fails)
+*/
+
+static int test_bug1644(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MYSQL_BIND my_bind[4];
+ int num;
+ my_bool isnull;
+ int rc, i;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS foo_dfr");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "CREATE TABLE foo_dfr(col1 int, col2 int, col3 int, col4 int);");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "INSERT INTO foo_dfr VALUES (?, ?, ?, ? )");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 4, "Paramcount != 4");
+
+ memset(my_bind, '\0', sizeof(MYSQL_BIND) * 4);
+
+ num= 22;
+ isnull= 0;
+ for (i= 0 ; i < 4 ; i++)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].buffer= (void *)&num;
+ my_bind[i].is_null= &isnull;
+ }
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ isnull= 1;
+ for (i= 0 ; i < 4 ; i++)
+ my_bind[i].is_null= &isnull;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ isnull= 0;
+ num= 88;
+ for (i= 0 ; i < 4 ; i++)
+ my_bind[i].is_null= &isnull;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT * FROM foo_dfr");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid resultset");
+
+ FAIL_IF(mysql_num_rows(result) != 3, "rowcount != 3");
+
+ mysql_data_seek(result, 0);
+
+ row= mysql_fetch_row(result);
+ FAIL_IF(!row, "row = NULL");
+ for (i= 0 ; i < 4 ; i++)
+ {
+ FAIL_UNLESS(strcmp(row[i], "22") == 0, "Wrong value");
+ }
+ row= mysql_fetch_row(result);
+ FAIL_IF(!row, "Invalid row");
+ for (i= 0 ; i < 4 ; i++)
+ {
+ FAIL_UNLESS(row[i] == 0, "row[i] != 0");
+ }
+ row= mysql_fetch_row(result);
+ FAIL_IF(!row, "Invalid row");
+ for (i= 0 ; i < 4 ; i++)
+ {
+ FAIL_UNLESS(strcmp(row[i], "88") == 0, "row[i] != 88");
+ }
+ row= mysql_fetch_row(result);
+ FAIL_IF(row, "row != NULL");
+
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS foo_dfr");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug11037(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (id int not null)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values (1)");
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "select id FROM t1";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+
+ /* expected error */
+ rc = mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc==1, "Error expected");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc==MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc==MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/* Bug#11183 "mysql_stmt_reset() doesn't reset information about error" */
+
+static int test_bug11183(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ char bug_statement[]= "insert into t1 values (1)";
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(bug_statement));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ /* Trying to execute statement that should fail on execute stage */
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_reset(stmt);
+ FAIL_IF(mysql_stmt_errno(stmt) != 0, "stmt->error != 0");
+
+ rc= mysql_query(mysql, "create table t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ /* Trying to execute statement that should pass ok */
+ if (mysql_stmt_execute(stmt))
+ {
+ mysql_stmt_reset(stmt);
+ FAIL_IF(mysql_stmt_errno(stmt) == 0, "stmt->error != 0");
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug12744(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt = NULL;
+ int rc;
+
+ SKIP_MAXSCALE;
+
+ stmt = mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, "SET @a:=1", 9);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* set reconnect, kill and ping to reconnect */
+ rc= mysql_query(mysql, "SET @a:=1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_kill(mysql, mysql_thread_id(mysql));
+
+ rc= mysql_ping(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ return OK;
+}
+
+static int test_bug1500(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[3];
+ int rc= 0;
+ int32 int_data[3]= {2, 3, 4};
+ const char *data;
+ const char *query;
+
+ // XPAND doesn't support AGAINST
+ SKIP_XPAND
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bg1500");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (i INT)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_bg1500 VALUES (1), (2)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ query= "SELECT i FROM test_bg1500 WHERE i IN (?, ?, ?)";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 3, "paramcount != 3");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer= (void *)int_data;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[2]= my_bind[1]= my_bind[0];
+ my_bind[1].buffer= (void *)(int_data + 1);
+ my_bind[2].buffer= (void *)(int_data + 2);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE test_bg1500");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (s VARCHAR(25), FULLTEXT(s)) engine=MyISAM");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "INSERT INTO test_bg1500 VALUES ('Gravedigger'), ('Greed'), ('Hollow Dogs')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ query= "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (?)";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "paramcount != 1");
+
+ data= "Dogs";
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *) data;
+ my_bind[0].buffer_length= (unsigned long)strlen(data);
+ my_bind[0].is_null= 0;
+ my_bind[0].length= 0;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ mysql_stmt_close(stmt);
+
+ /* This should work too */
+ query= "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?, 'digger'))";
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "paramcount != 1");
+
+ data= "Grave";
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *) data;
+ my_bind[0].buffer_length= (unsigned long)strlen(data);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bg1500");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug15510(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *query= "select 1 from dual where 1/0";
+
+ SKIP_MYSQL(mysql);
+
+ rc= mysql_query(mysql, "set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO'");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(mysql_warning_count(mysql), "Warning expected");
+
+ /* Cleanup */
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "set @@sql_mode=''");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ Bug #15518 - Reusing a stmt that has failed during prepare
+ does not clear error
+*/
+
+static int test_bug15518(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ stmt= mysql_stmt_init(mysql);
+
+ /*
+ The prepare of foo should fail with errno 1064 since
+ it's not a valid query
+ */
+ rc= mysql_stmt_prepare(stmt, "foo", 3);
+ FAIL_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql), "Error expected");
+
+ /*
+ Use the same stmt and reprepare with another query that
+ succeeds
+ */
+ rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12);
+ FAIL_UNLESS(!rc || mysql_stmt_errno(stmt) || mysql_errno(mysql), "Error not expected");
+
+ rc= mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+ /*
+ part2, when connection to server has been closed
+ after first prepare
+ */
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, "foo", 3);
+ FAIL_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql), "Error expected");
+
+ /* Close connection to server */
+ mysql_close(mysql);
+
+ /*
+ Use the same stmt and reprepare with another query that
+ succeeds. The prepare should fail with error 2013 since
+ connection to server has been closed.
+ */
+ rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12);
+ FAIL_UNLESS(rc && mysql_stmt_errno(stmt), "Error expected");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+/*
+ Bug #15613: "libmysqlclient API function mysql_stmt_prepare returns wrong
+ field length"
+*/
+
+static int test_bug15613(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ MYSQL_RES *metadata;
+ MYSQL_FIELD *field;
+ int rc;
+
+ //https://jira.mariadb.org/browse/XPT-273
+ SKIP_XPAND;
+
+ /* I. Prepare the table */
+ rc= mysql_query(mysql, "set names latin1");
+ check_mysql_rc(rc, mysql);
+ mysql_query(mysql, "drop table if exists t1");
+ rc= mysql_query(mysql,
+ "create table t1 (t text character set utf8, "
+ "tt tinytext character set utf8, "
+ "mt mediumtext character set utf8, "
+ "lt longtext character set utf8, "
+ "vl varchar(255) character set latin1,"
+ "vb varchar(255) character set binary,"
+ "vu varchar(255) character set utf8)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+
+ /* II. Check SELECT metadata */
+ stmt_text= ("select t, tt, mt, lt, vl, vb, vu from t1");
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ metadata= mysql_stmt_result_metadata(stmt);
+ field= mysql_fetch_fields(metadata);
+ FAIL_UNLESS(field[0].length == 65535, "length != 65535");
+ FAIL_UNLESS(field[1].length == 255, "length != 255");
+ FAIL_UNLESS(field[2].length == 16777215, "length != 166777215");
+ FAIL_UNLESS(field[3].length == 4294967295UL, "length != 4294967295UL");
+ FAIL_UNLESS(field[4].length == 255, "length != 255");
+ FAIL_UNLESS(field[5].length == 255, "length != 255");
+ FAIL_UNLESS(field[6].length == 255, "length != 255");
+ mysql_free_result(metadata);
+ mysql_stmt_free_result(stmt);
+
+ /* III. Cleanup */
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "set names default");
+ check_mysql_rc(rc, mysql);
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_bug16144(MYSQL *mysql)
+{
+ const my_bool flag_orig= (my_bool) 0xde;
+ my_bool flag= flag_orig;
+ MYSQL_STMT *stmt;
+
+ /* Check that attr_get returns correct data on little and big endian CPUs */
+ stmt= mysql_stmt_init(mysql);
+ mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*) &flag);
+ mysql_stmt_attr_get(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &flag);
+ FAIL_UNLESS(flag == flag_orig, "flag != flag_orig");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+/*
+ This tests for various mysql_stmt_send_long_data bugs described in #1664
+*/
+
+static int test_bug1664(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, int_data;
+ const char *data;
+ const char *str_data= "Simple string";
+ MYSQL_BIND my_bind[2];
+ const char *query= "INSERT INTO test_long_data(col2, col1) VALUES(?, ?)";
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_long_data(col1 int, col2 MEDIUMTEXT)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Param count != 2");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)str_data;
+ my_bind[0].buffer_length= (unsigned long)strlen(str_data);
+
+ my_bind[1].buffer= (void *)&int_data;
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ int_data= 1;
+
+ /*
+ Let us supply empty long_data. This should work and should
+ not break following execution.
+ */
+ data= "";
+ rc= mysql_stmt_send_long_data(stmt, 0, SL(data));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ if (verify_col_data(mysql, "test_long_data", "col1", "1"))
+ goto error;
+ if (verify_col_data(mysql, "test_long_data", "col2", ""))
+ goto error;
+ rc= mysql_query(mysql, "DELETE FROM test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ /* This should pass OK */
+ data= (char *)"Data";
+ rc= mysql_stmt_send_long_data(stmt, 0, SL(data));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ if (verify_col_data(mysql, "test_long_data", "col1", "1"))
+ goto error;
+ if (verify_col_data(mysql, "test_long_data", "col2", "Data"))
+ goto error;
+
+ /* clean up */
+ rc= mysql_query(mysql, "DELETE FROM test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ /*
+ Now we are changing int parameter and don't do anything
+ with first parameter. Second mysql_stmt_execute() should run
+ OK treating this first parameter as string parameter.
+ */
+
+ int_data= 2;
+ /* execute */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ if (verify_col_data(mysql, "test_long_data", "col1", "2"))
+ goto error;
+ if (verify_col_data(mysql, "test_long_data", "col2", str_data))
+ goto error;
+
+ /* clean up */
+ rc= mysql_query(mysql, "DELETE FROM test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ /*
+ Now we are sending other long data. It should not be
+ concatenated to previous.
+ */
+
+ data= (char *)"SomeOtherData";
+ rc= mysql_stmt_send_long_data(stmt, 0, SL(data));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ if (verify_col_data(mysql, "test_long_data", "col1", "2"))
+ goto error;
+ if (verify_col_data(mysql, "test_long_data", "col2", "SomeOtherData"))
+ goto error;
+
+ mysql_stmt_close(stmt);
+
+ /* clean up */
+ rc= mysql_query(mysql, "DELETE FROM test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ /* Now let us test how mysql_stmt_reset works. */
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ data= (char *)"SomeData";
+ rc= mysql_stmt_send_long_data(stmt, 0, SL(data));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ if (verify_col_data(mysql, "test_long_data", "col1", "2"))
+ goto error;
+ if (verify_col_data(mysql, "test_long_data", "col2", str_data))
+ goto error;
+
+ mysql_stmt_close(stmt);
+
+ /* Final clean up */
+ rc= mysql_query(mysql, "DROP TABLE test_long_data");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+
+error:
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE test_long_data");
+ return FAIL;
+}
+/* Test a misc bug */
+
+static int test_ushort_bug(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[4];
+ ushort short_value;
+ uint32 long_value;
+ ulong s_length, l_length, ll_length, t_length;
+ ulonglong longlong_value;
+ int rc;
+ uchar tiny_value;
+ const char *query= "SELECT * FROM test_ushort";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ushort");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_ushort(a smallint unsigned, \
+ b smallint unsigned, \
+ c smallint unsigned, \
+ d smallint unsigned)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,
+ "INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[0].buffer= (void *)&short_value;
+ my_bind[0].is_unsigned= TRUE;
+ my_bind[0].length= &s_length;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[1].buffer= (void *)&long_value;
+ my_bind[1].length= &l_length;
+
+ my_bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[2].buffer= (void *)&longlong_value;
+ my_bind[2].length= &ll_length;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[3].buffer= (void *)&tiny_value;
+ my_bind[3].is_unsigned= TRUE;
+ my_bind[3].length= &t_length;
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(short_value == 35999, "short_value != 35999");
+ FAIL_UNLESS(s_length == 2, "length != 2");
+
+ FAIL_UNLESS(long_value == 35999, "long_value != 35999");
+ FAIL_UNLESS(l_length == 4, "length != 4");
+
+ FAIL_UNLESS(longlong_value == 35999, "longlong_value != 35999");
+ FAIL_UNLESS(ll_length == 8, "length != 8");
+
+ FAIL_UNLESS(tiny_value == 200, "tiny_value != 200");
+ FAIL_UNLESS(t_length == 1, "length != 1");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ushort");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug1946(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *query= "INSERT INTO prepare_command VALUES (?)";
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS prepare_command");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE prepare_command(ID INT)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_real_query(mysql, SL(query));
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE prepare_command");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug20152(MYSQL *mysql)
+{
+ MYSQL_BIND my_bind[1];
+ MYSQL_STMT *stmt;
+ MYSQL_TIME tm;
+ int rc;
+ const char *query= "INSERT INTO t1 (f1) VALUES (?)";
+
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_DATE;
+ my_bind[0].buffer= (void*)&tm;
+
+ memset(&tm, 0, sizeof(MYSQL_TIME));
+
+ tm.year = 2006;
+ tm.month = 6;
+ tm.day = 18;
+ tm.hour = 14;
+ tm.minute = 9;
+ tm.second = 42;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (f1 DATE)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ FAIL_UNLESS(tm.hour == 14 && tm.minute == 9 && tm.second == 42, "time != 14:09:42");
+ return OK;
+}
+
+static int test_bug2247(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *res;
+ int rc;
+ int i;
+ const char *create= "CREATE TABLE bug2247(id INT UNIQUE AUTO_INCREMENT)";
+ const char *insert= "INSERT INTO bug2247 VALUES (NULL)";
+ const char *SELECT= "SELECT id FROM bug2247";
+ const char *update= "UPDATE bug2247 SET id=id+10";
+ const char *drop= "DROP TABLE IF EXISTS bug2247";
+ ulonglong exp_count;
+ enum { NUM_ROWS= 5 };
+
+
+ /* create table and insert few rows */
+ rc= mysql_query(mysql, drop);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, create);
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(insert));
+ check_stmt_rc(rc, stmt);
+ for (i= 0; i < NUM_ROWS; ++i)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+ exp_count= mysql_stmt_affected_rows(stmt);
+ FAIL_UNLESS(exp_count == 1, "exp_count != 1");
+
+ rc= mysql_query(mysql, SELECT);
+ check_mysql_rc(rc, mysql);
+ /*
+ mysql_store_result overwrites mysql->affected_rows. Check that
+ mysql_stmt_affected_rows() returns the same value, whereas
+ mysql_affected_rows() value is correct.
+ */
+ res= mysql_store_result(mysql);
+ FAIL_IF(!res, "Invalid result set");
+
+ FAIL_UNLESS(mysql_affected_rows(mysql) == NUM_ROWS, "affected_rows != NUM_ROWS");
+ FAIL_UNLESS(exp_count == mysql_stmt_affected_rows(stmt), "affected_rows != exp_count");
+
+ rc= mysql_query(mysql, update);
+ check_mysql_rc(rc, mysql);
+ FAIL_UNLESS(mysql_affected_rows(mysql) == NUM_ROWS, "affected_rows != NUM_ROWS");
+ FAIL_UNLESS(exp_count == mysql_stmt_affected_rows(stmt), "affected_rows != exp_count");
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+
+ /* check that mysql_stmt_store_result modifies mysql_stmt_affected_rows */
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(SELECT));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt); rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt); exp_count= mysql_stmt_affected_rows(stmt);
+ FAIL_UNLESS(exp_count == NUM_ROWS, "exp_count != NUM_ROWS");
+
+ rc= mysql_query(mysql, insert);
+ check_mysql_rc(rc, mysql);
+ FAIL_UNLESS(mysql_affected_rows(mysql) == 1, "affected_rows != 1");
+ FAIL_UNLESS(exp_count == mysql_stmt_affected_rows(stmt), "affected_rows != exp_count");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, drop);
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ Test for bug#2248 "mysql_fetch without prior mysql_stmt_execute hangs"
+*/
+
+static int test_bug2248(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *query1= "SELECT DATABASE()";
+ const char *query2= "INSERT INTO test_bug2248 VALUES (10)";
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bug2248");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_bug2248 (id int)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query1));
+ check_stmt_rc(rc, stmt);
+
+ /* This should not hang */
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ /* And this too */
+ rc= mysql_stmt_store_result(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query2));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ /* This too should not hang but should return proper error */
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 1, "rc != 1");
+
+ /* This too should not hang but should not bark */
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+ /* This should return proper error */
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 1, "rc != 1");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE test_bug2248");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ BUG#23383: mysql_affected_rows() returns different values than
+ mysql_stmt_affected_rows()
+
+ Test that both mysql_affected_rows() and mysql_stmt_affected_rows()
+ return -1 on error, 0 when no rows were affected, and (positive) row
+ count when some rows were affected.
+*/
+static int test_bug23383(MYSQL *mysql)
+{
+ const char *insert_query= "INSERT INTO t1 VALUES (1), (2)";
+ const char *update_query= "UPDATE t1 SET i= 4 WHERE i = 3";
+ MYSQL_STMT *stmt;
+ unsigned long long row_count;
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (i INT UNIQUE)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, insert_query);
+ check_mysql_rc(rc, mysql);
+ row_count= mysql_affected_rows(mysql);
+ FAIL_UNLESS(row_count == 2, "row_count != 2");
+
+ rc= mysql_query(mysql, insert_query);
+ FAIL_IF(!rc, "Error expected");
+ row_count= mysql_affected_rows(mysql);
+ FAIL_UNLESS(row_count == (unsigned long long)-1, "rowcount != -1");
+
+ rc= mysql_query(mysql, update_query);
+ check_mysql_rc(rc, mysql);
+ row_count= mysql_affected_rows(mysql);
+ FAIL_UNLESS(row_count == 0, "");
+
+ rc= mysql_query(mysql, "DELETE FROM t1");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(insert_query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ row_count= mysql_stmt_affected_rows(stmt);
+ FAIL_UNLESS(row_count == 2, "row_count != 2");
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_UNLESS(rc != 0, "");
+ row_count= mysql_stmt_affected_rows(stmt);
+ FAIL_UNLESS(row_count == (unsigned long long)-1, "rowcount != -1");
+
+ rc= mysql_stmt_prepare(stmt, SL(update_query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ row_count= mysql_stmt_affected_rows(stmt);
+ FAIL_UNLESS(row_count == 0, "rowcount != 0");
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/*
+ Bug#27592 (stack overrun when storing datetime value using prepared statements)
+*/
+
+static int test_bug27592(MYSQL *mysql)
+{
+ const int NUM_ITERATIONS= 40;
+ int i;
+ int rc;
+ MYSQL_STMT *stmt= NULL;
+ MYSQL_BIND bind[1];
+ MYSQL_TIME time_val;
+
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ mysql_query(mysql, "CREATE TABLE t1(c2 DATETIME)");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO t1 VALUES (?)"));
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, '\0', sizeof(bind));
+
+ bind[0].buffer_type= MYSQL_TYPE_DATETIME;
+ bind[0].buffer= (char *) &time_val;
+ bind[0].length= NULL;
+
+ for (i= 0; i < NUM_ITERATIONS; i++)
+ {
+ time_val.year= 2007;
+ time_val.month= 6;
+ time_val.day= 7;
+ time_val.hour= 18;
+ time_val.minute= 41;
+ time_val.second= 3;
+
+ time_val.second_part=0;
+ time_val.neg=0;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ mysql_stmt_close(stmt);
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+
+ return OK;
+}
+
+/*
+ Bug#28934: server crash when receiving malformed com_execute packets
+*/
+
+static int test_bug28934(MYSQL *mysql)
+{
+ my_bool error= 0;
+ MYSQL_BIND bind[5];
+ MYSQL_STMT *stmt;
+ int rc, cnt;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1(id int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values(1),(2),(3),(4),(5)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("select * from t1 where id in(?,?,?,?,?)"));
+ check_stmt_rc(rc, stmt);
+
+ memset (&bind, '\0', sizeof (bind));
+ for (cnt= 0; cnt < 5; cnt++)
+ {
+ bind[cnt].buffer_type= MYSQL_TYPE_LONG;
+ bind[cnt].buffer= (char*)&cnt;
+ bind[cnt].buffer_length= 0;
+ }
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ stmt->param_count=2;
+ error= mysql_stmt_execute(stmt);
+ FAIL_UNLESS(error != 0, "Error expected");
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug3035(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind_array[12], *my_bind= bind_array, *bind_end= my_bind + 12;
+ int8 int8_val;
+ uint8 uint8_val;
+ int16 int16_val;
+ uint16 uint16_val;
+ int32 int32_val;
+ uint32 uint32_val;
+ longlong int64_val;
+ ulonglong uint64_val;
+ double double_val, udouble_val, double_tmp;
+ char longlong_as_string[22], ulonglong_as_string[22];
+
+ /* mins and maxes */
+ const int8 int8_min= -128;
+ const int8 int8_max= 127;
+ const uint8 uint8_min= 0;
+ const uint8 uint8_max= 255;
+
+ const int16 int16_min= -32768;
+ const int16 int16_max= 32767;
+ const uint16 uint16_min= 0;
+ const uint16 uint16_max= 65535;
+
+ const int32 int32_max= 2147483647L;
+ const int32 int32_min= -int32_max - 1;
+ const uint32 uint32_min= 0;
+ const uint32 uint32_max= 4294967295U;
+
+ /* it might not work okay everyplace */
+ const longlong int64_max= 9223372036854775807LL;
+ const longlong int64_min= -int64_max - 1;
+
+ const ulonglong uint64_min= 0U;
+ const ulonglong uint64_max= 18446744073709551615ULL;
+
+ const char *stmt_text;
+
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "CREATE TABLE t1 (i8 TINYINT, ui8 TINYINT UNSIGNED, "
+ "i16 SMALLINT, ui16 SMALLINT UNSIGNED, "
+ "i32 INT, ui32 INT UNSIGNED, "
+ "i64 BIGINT, ui64 BIGINT UNSIGNED, "
+ "id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ memset(bind_array, '\0', sizeof(bind_array));
+ for (my_bind= bind_array; my_bind < bind_end; my_bind++)
+ my_bind->error= &my_bind->error_value;
+
+ bind_array[0].buffer_type= MYSQL_TYPE_TINY;
+ bind_array[0].buffer= (void *) &int8_val;
+
+ bind_array[1].buffer_type= MYSQL_TYPE_TINY;
+ bind_array[1].buffer= (void *) &uint8_val;
+ bind_array[1].is_unsigned= 1;
+
+ bind_array[2].buffer_type= MYSQL_TYPE_SHORT;
+ bind_array[2].buffer= (void *) &int16_val;
+
+ bind_array[3].buffer_type= MYSQL_TYPE_SHORT;
+ bind_array[3].buffer= (void *) &uint16_val;
+ bind_array[3].is_unsigned= 1;
+
+ bind_array[4].buffer_type= MYSQL_TYPE_LONG;
+ bind_array[4].buffer= (void *) &int32_val;
+
+ bind_array[5].buffer_type= MYSQL_TYPE_LONG;
+ bind_array[5].buffer= (void *) &uint32_val;
+ bind_array[5].is_unsigned= 1;
+
+ bind_array[6].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind_array[6].buffer= (void *) &int64_val;
+
+ bind_array[7].buffer_type= MYSQL_TYPE_LONGLONG;
+ bind_array[7].buffer= (void *) &uint64_val;
+ bind_array[7].is_unsigned= 1;
+
+ stmt= mysql_stmt_init(mysql);
+ check_stmt_rc(rc, stmt);
+
+ stmt_text= "INSERT INTO t1 (i8, ui8, i16, ui16, i32, ui32, i64, ui64) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_bind_param(stmt, bind_array);
+
+ int8_val= int8_min;
+ uint8_val= uint8_min;
+ int16_val= int16_min;
+ uint16_val= uint16_min;
+ int32_val= int32_min;
+ uint32_val= uint32_min;
+ int64_val= int64_min;
+ uint64_val= uint64_min;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ int8_val= int8_max;
+ uint8_val= uint8_max;
+ int16_val= int16_max;
+ uint16_val= uint16_max;
+ int32_val= int32_max;
+ uint32_val= uint32_max;
+ int64_val= int64_max;
+ uint64_val= uint64_max;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ stmt_text= "SELECT i8, ui8, i16, ui16, i32, ui32, i64, ui64, ui64, "
+ "cast(ui64 as signed), ui64, cast(ui64 as signed)"
+ "FROM t1 ORDER BY id ASC";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ bind_array[8].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind_array[8].buffer= (void *) &udouble_val;
+
+ bind_array[9].buffer_type= MYSQL_TYPE_DOUBLE;
+ bind_array[9].buffer= (void *) &double_val;
+
+ bind_array[10].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[10].buffer= (void *) &ulonglong_as_string;
+ bind_array[10].buffer_length= sizeof(ulonglong_as_string);
+
+ bind_array[11].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[11].buffer= (void *) &longlong_as_string;
+ bind_array[11].buffer_length= sizeof(longlong_as_string);
+
+ mysql_stmt_bind_result(stmt, bind_array);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(int8_val == int8_min, "int8_val != int8_min");
+ FAIL_UNLESS(uint8_val == uint8_min, "uint8_val != uint8_min");
+ FAIL_UNLESS(int16_val == int16_min, "int16_val != int16_min");
+ FAIL_UNLESS(uint16_val == uint16_min, "uint16_val != uint16_min");
+ FAIL_UNLESS(int32_val == int32_min, "int32_val != int32_min");
+ FAIL_UNLESS(uint32_val == uint32_min, "uint32_val != uint32_min");
+ FAIL_UNLESS(int64_val == int64_min, "int64_val != int64_min");
+ FAIL_UNLESS(uint64_val == uint64_min, "uint64_val != uint64_min");
+ FAIL_UNLESS(double_val == (longlong) uint64_min, "double_val != uint64_min");
+ double_tmp= ulonglong2double(uint64_val);
+ FAIL_UNLESS(cmp_double(&udouble_val,&double_tmp), "udouble_val != double_tmp");
+ FAIL_UNLESS(!strcmp(longlong_as_string, "0"), "longlong_as_string != '0'");
+ FAIL_UNLESS(!strcmp(ulonglong_as_string, "0"), "ulonglong_as_string != '0'");
+
+ rc= mysql_stmt_fetch(stmt);
+
+ FAIL_UNLESS(rc == MYSQL_DATA_TRUNCATED || rc == 0, "rc != 0,MYSQL_DATA_TRUNCATED");
+
+ FAIL_UNLESS(int8_val == int8_max, "int8_val != int8_max");
+ FAIL_UNLESS(uint8_val == uint8_max, "uint8_val != uint8_max");
+ FAIL_UNLESS(int16_val == int16_max, "int16_val != int16_max");
+ FAIL_UNLESS(uint16_val == uint16_max, "uint16_val != uint16_max");
+ FAIL_UNLESS(int32_val == int32_max, "int32_val != int32_max");
+ FAIL_UNLESS(uint32_val == uint32_max, "uint32_val != uint32_max");
+ FAIL_UNLESS(int64_val == int64_max, "int64_val != int64_max");
+ FAIL_UNLESS(uint64_val == uint64_max, "uint64_val != uint64_max");
+ FAIL_UNLESS(double_val == (longlong) uint64_val, "double_val != uint64_val");
+ double_tmp= ulonglong2double(uint64_val);
+ FAIL_UNLESS(cmp_double(&udouble_val,&double_tmp), "udouble_val != double_tmp");
+ FAIL_UNLESS(!strcmp(longlong_as_string, "-1"), "longlong_as_string != '-1'");
+ FAIL_UNLESS(!strcmp(ulonglong_as_string, "18446744073709551615"), "ulonglong_as_string != '18446744073709551615'");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "");
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "DROP TABLE t1";
+ mysql_real_query(mysql, SL(stmt_text));
+ return OK;
+}
+
+/*
+ Test for BUG#3420 ("select id1, value1 from t where id= ? or value= ?"
+ returns all rows in the table)
+*/
+
+static int test_ps_conj_select(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND my_bind[2];
+ int32 int_data;
+ char str_data[32];
+ unsigned long str_length;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0', "
+ "value2 varchar(100), value1 varchar(100))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values (1, 'hh', 'hh'), "
+ "(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "select id1, value1 from t1 where id1= ? or "
+ "CONVERT(value1 USING utf8)= ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "param_count != 2");
+
+ /* Always bzero all members of bind parameter */
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&int_data;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ my_bind[1].buffer= (void *)str_data;
+ my_bind[1].buffer_length= array_elements(str_data);
+ my_bind[1].length= &str_length;
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ int_data= 1;
+ strcpy(str_data, "hh");
+ str_length= (unsigned long)strlen(str_data);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc=0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 3, "rc != 3");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test for NULL as PS parameter (BUG#3367, BUG#3371) */
+
+static int test_ps_null_param(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ MYSQL_BIND in_bind;
+ my_bool in_is_null;
+ long int in_long;
+
+ MYSQL_BIND out_bind;
+ ulong out_length;
+ my_bool out_is_null;
+ char out_str_data[20];
+
+ const char *queries[]= {"select ?", "select ?+1",
+ "select col1 from test_ps_nulls where col1 <=> ?",
+ NULL
+ };
+ const char **cur_query= queries;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ps_nulls");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_ps_nulls(col1 int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_ps_nulls values (1), (null)");
+ check_mysql_rc(rc, mysql);
+
+ /* Always bzero all members of bind parameter */
+ memset(&in_bind, '\0', sizeof(in_bind));
+ memset(&out_bind, '\0', sizeof(out_bind));
+ in_bind.buffer_type= MYSQL_TYPE_LONG;
+ in_bind.is_null= &in_is_null;
+ in_bind.length= 0;
+ in_bind.buffer= (void *)&in_long;
+ in_is_null= 1;
+ in_long= 1;
+
+ out_bind.buffer_type= MYSQL_TYPE_STRING;
+ out_bind.is_null= &out_is_null;
+ out_bind.length= &out_length;
+ out_bind.buffer= out_str_data;
+ out_bind.buffer_length= array_elements(out_str_data);
+
+ /* Execute several queries, all returning NULL in result. */
+ for(cur_query= queries; *cur_query; cur_query++)
+ {
+ char query[MAX_TEST_QUERY_LENGTH];
+ strcpy(query, *cur_query);
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ diag("statement: %s", query);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(mysql_stmt_param_count(stmt) != 1, "param_count != 1");
+
+ rc= mysql_stmt_bind_param(stmt, &in_bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_result(stmt, &out_bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc != MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ FAIL_UNLESS(out_is_null, "!out_is_null");
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ mysql_stmt_close(stmt);
+ }
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ps_nulls");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/*
+ utility for the next test; expects 3 rows in the result from a SELECT,
+ compares each row/field with an expected value.
+ */
+#define test_ps_query_cache_result(i1,s1,l1,i2,s2,l2,i3,s3,l3) \
+ r_metadata= mysql_stmt_result_metadata(stmt); \
+ FAIL_UNLESS(r_metadata != NULL, ""); \
+ rc= mysql_stmt_fetch(stmt); \
+ check_stmt_rc(rc,stmt); \
+ FAIL_UNLESS((r_int_data == i1) && (r_str_length == l1) && \
+ (strcmp(r_str_data, s1) == 0), "test_ps_query_cache_result failure"); \
+ rc= mysql_stmt_fetch(stmt); \
+ check_stmt_rc(rc,stmt); \
+ FAIL_UNLESS((r_int_data == i2) && (r_str_length == l2) && \
+ (strcmp(r_str_data, s2) == 0), "test_ps_query_cache_result failure"); \
+ rc= mysql_stmt_fetch(stmt); \
+ check_stmt_rc(rc,stmt); \
+ FAIL_UNLESS((r_int_data == i3) && (r_str_length == l3) && \
+ (strcmp(r_str_data, s3) == 0), "test_ps_query_cache_result failure"); \
+ rc= mysql_stmt_fetch(stmt); \
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); \
+ mysql_free_result(r_metadata);
+
+/* reads Qcache_hits from server and returns its value */
+static int query_cache_hits(MYSQL *mysql)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+ uint result;
+
+ rc= mysql_query(mysql, "show status like 'qcache_hits'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_use_result(mysql);
+
+ row= mysql_fetch_row(res);
+
+ result= atoi(row[1]);
+ mysql_free_result(res);
+ return result;
+}
+
+
+/*
+ Test that prepared statements make use of the query cache just as normal
+ statements (BUG#735).
+*/
+static int test_ps_query_cache(MYSQL *mysql)
+{
+ MYSQL *lmysql= mysql;
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND p_bind[2],r_bind[2]; /* p: param bind; r: result bind */
+ int32 p_int_data, r_int_data;
+ char p_str_data[32], r_str_data[32];
+ unsigned long p_str_length, r_str_length;
+ MYSQL_RES *r_metadata;
+ char query[MAX_TEST_QUERY_LENGTH];
+ uint hits1, hits2;
+ enum enum_test_ps_query_cache
+ {
+ /*
+ We iterate the same prepare/executes block, but have iterations where
+ we vary the query cache conditions.
+ */
+ /* the query cache is enabled for the duration of prep&execs: */
+ TEST_QCACHE_ON= 0,
+ /*
+ same but using a new connection (to see if qcache serves results from
+ the previous connection as it should):
+ */
+ TEST_QCACHE_ON_WITH_OTHER_CONN,
+ /*
+ First border case: disables the query cache before prepare and
+ re-enables it before execution (to test if we have no bug then):
+ */
+ TEST_QCACHE_OFF_ON,
+ /*
+ Second border case: enables the query cache before prepare and
+ disables it before execution:
+ */
+ TEST_QCACHE_ON_OFF
+ };
+ enum enum_test_ps_query_cache iteration;
+
+ diag("test needs to be fixed");
+ return SKIP;
+ /* prepare the table */
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0', "
+ "value2 varchar(100), value1 varchar(100))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into t1 values (1, 'hh', 'hh'), "
+ "(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')");
+ check_mysql_rc(rc, mysql);
+
+ for (iteration= TEST_QCACHE_ON; iteration <= TEST_QCACHE_ON_OFF; iteration++)
+ {
+ switch (iteration) {
+ case TEST_QCACHE_ON:
+ case TEST_QCACHE_ON_OFF:
+ rc= mysql_query(lmysql, "set global query_cache_size=1000000");
+ check_mysql_rc(rc, mysql);
+ break;
+ case TEST_QCACHE_OFF_ON:
+ rc= mysql_query(lmysql, "set global query_cache_size=0");
+ check_mysql_rc(rc, mysql);
+ break;
+ case TEST_QCACHE_ON_WITH_OTHER_CONN:
+ lmysql= test_connect(NULL);
+ FAIL_IF(!lmysql, "Opening new connection failed");
+ break;
+ }
+
+ strcpy(query, "select id1, value1 from t1 where id1= ? or "
+ "CONVERT(value1 USING utf8)= ?");
+ stmt= mysql_stmt_init(lmysql);
+ FAIL_IF(!stmt, mysql_error(lmysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 2, "param_count != 2");
+
+ switch (iteration) {
+ case TEST_QCACHE_OFF_ON:
+ rc= mysql_query(lmysql, "set global query_cache_size=1000000");
+ check_mysql_rc(rc, mysql);
+ break;
+ case TEST_QCACHE_ON_OFF:
+ rc= mysql_query(lmysql, "set global query_cache_size=0");
+ check_mysql_rc(rc, mysql);
+ default:
+ break;
+ }
+
+ memset(p_bind, '\0', sizeof(p_bind));
+ p_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ p_bind[0].buffer= (void *)&p_int_data;
+ p_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ p_bind[1].buffer= (void *)p_str_data;
+ p_bind[1].buffer_length= array_elements(p_str_data);
+ p_bind[1].length= &p_str_length;
+
+ rc= mysql_stmt_bind_param(stmt, p_bind);
+ check_stmt_rc(rc, stmt);
+ p_int_data= 1;
+ strcpy(p_str_data, "hh");
+ p_str_length= (unsigned long)strlen(p_str_data);
+
+ memset(r_bind, '\0', sizeof(r_bind));
+ r_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ r_bind[0].buffer= (void *)&r_int_data;
+ r_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
+ r_bind[1].buffer= (void *)r_str_data;
+ r_bind[1].buffer_length= array_elements(r_str_data);
+ r_bind[1].length= &r_str_length;
+
+ rc= mysql_stmt_bind_result(stmt, r_bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ test_ps_query_cache_result(1, "hh", 2, 2, "hh", 2, 1, "ii", 2);
+ r_metadata= mysql_stmt_result_metadata(stmt);
+ FAIL_UNLESS(r_metadata != NULL, "");
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+ FAIL_UNLESS((r_int_data == 1) && (r_str_length == 2) &&
+ (strcmp(r_str_data, "hh") == 0), "test_ps_query_cache_result failure"); \
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+ FAIL_UNLESS((r_int_data == 2) && (r_str_length == 2) &&
+ (strcmp(r_str_data, "hh") == 0), "test_ps_query_cache_result failure"); \
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc,stmt);
+ FAIL_UNLESS((r_int_data == 1) && (r_str_length == 2) &&
+ (strcmp(r_str_data, "ii") == 0), "test_ps_query_cache_result failure"); \
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ mysql_free_result(r_metadata);
+
+
+ /* now retry with the same parameter values and see qcache hits */
+ hits1= query_cache_hits(lmysql);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt); test_ps_query_cache_result(1, "hh", 2, 2, "hh", 2, 1, "ii", 2);
+ hits2= query_cache_hits(lmysql);
+ switch(iteration) {
+ case TEST_QCACHE_ON_WITH_OTHER_CONN:
+ case TEST_QCACHE_ON: /* should have hit */
+ FAIL_UNLESS(hits2-hits1 == 1, "hits2 != hits1 + 1");
+ break;
+ case TEST_QCACHE_OFF_ON:
+ case TEST_QCACHE_ON_OFF: /* should not have hit */
+ FAIL_UNLESS(hits2-hits1 == 0, "hits2 != hits1");
+ break;
+ }
+
+ /* now modify parameter values and see qcache hits */
+ strcpy(p_str_data, "ii");
+ p_str_length= (unsigned long)strlen(p_str_data);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ test_ps_query_cache_result(1, "hh", 2, 1, "ii", 2, 2, "ii", 2);
+ hits1= query_cache_hits(lmysql);
+
+ switch(iteration) {
+ case TEST_QCACHE_ON:
+ case TEST_QCACHE_OFF_ON:
+ case TEST_QCACHE_ON_OFF: /* should not have hit */
+ FAIL_UNLESS(hits2-hits1 == 0, "hits2 != hits1");
+ break;
+ case TEST_QCACHE_ON_WITH_OTHER_CONN: /* should have hit */
+ FAIL_UNLESS(hits1-hits2 == 1, "hits2 != hits1+1");
+ break;
+ }
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ test_ps_query_cache_result(1, "hh", 2, 1, "ii", 2, 2, "ii", 2);
+ hits2= query_cache_hits(lmysql);
+
+ mysql_stmt_close(stmt);
+
+ switch(iteration) {
+ case TEST_QCACHE_ON: /* should have hit */
+ FAIL_UNLESS(hits2-hits1 == 1, "hits2 != hits1+1");
+ break;
+ case TEST_QCACHE_OFF_ON:
+ case TEST_QCACHE_ON_OFF: /* should not have hit */
+ FAIL_UNLESS(hits2-hits1 == 0, "hits2 != hits1");
+ break;
+ case TEST_QCACHE_ON_WITH_OTHER_CONN: /* should have hit */
+ FAIL_UNLESS(hits2-hits1 == 1, "hits2 != hits1+1");
+ break;
+ }
+
+ } /* for(iteration=...) */
+
+ if (lmysql != mysql)
+ mysql_close(lmysql);
+
+ rc= mysql_query(mysql, "set global query_cache_size=0");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug3117(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND buffer;
+ longlong lii;
+ ulong length;
+ my_bool is_null;
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (id int auto_increment primary key)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT LAST_INSERT_ID()"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ memset(&buffer, '\0', sizeof(buffer));
+ buffer.buffer_type= MYSQL_TYPE_LONGLONG;
+ buffer.buffer_length= sizeof(lii);
+ buffer.buffer= (void *)&lii;
+ buffer.length= &length;
+ buffer.is_null= &is_null;
+
+ rc= mysql_stmt_bind_result(stmt, &buffer);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(is_null == 0 && lii == 1, "is_null != 0 || lii != 1");
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(is_null == 0 && lii == 2, "is_null != 0 || lii != 2");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/**
+ Bug#36004 mysql_stmt_prepare resets the list of warnings
+*/
+
+static int test_bug36004(MYSQL *mysql)
+{
+ int rc, warning_count= 0;
+ MYSQL_STMT *stmt;
+ SKIP_MAXSCALE;
+ SKIP_MYSQL(mysql); // don't send expected warnings
+
+ if (mysql_get_server_version(mysql) < 60000) {
+ diag("Test requires MySQL Server version 6.0 or above");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "drop table if exists inexistant");
+ check_mysql_rc(rc, mysql);
+
+ FAIL_UNLESS(mysql_warning_count(mysql) == 1, "");
+ query_int_variable(mysql, "@@warning_count", &warning_count);
+ FAIL_UNLESS(warning_count, "Warning expected");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("select 1"));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(mysql_warning_count(mysql) == 0, "No warning expected");
+ query_int_variable(mysql, "@@warning_count", &warning_count);
+ FAIL_UNLESS(warning_count, "warning expected");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(mysql_warning_count(mysql) == 0, "No warning expected");
+ mysql_stmt_close(stmt);
+
+ query_int_variable(mysql, "@@warning_count", &warning_count);
+ FAIL_UNLESS(warning_count, "Warning expected");
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("drop table if exists inexistant"));
+ check_stmt_rc(rc, stmt);
+
+ query_int_variable(mysql, "@@warning_count", &warning_count);
+ FAIL_UNLESS(warning_count == 0, "No warning expected");
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_bug3796(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ const char *concat_arg0= "concat_with_";
+ enum { OUT_BUFF_SIZE= 30 };
+ char out_buff[OUT_BUFF_SIZE];
+ char canonical_buff[OUT_BUFF_SIZE];
+ ulong out_length;
+ const char *stmt_text;
+ int rc;
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ /* Create and fill test table */
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "CREATE TABLE t1 (a INT, b VARCHAR(30))";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "INSERT INTO t1 VALUES(1, 'ONE'), (2, 'TWO')";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ /* Create statement handle and prepare it with select */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT concat(?, b) FROM t1";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ /* Bind input buffers */
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *) concat_arg0;
+ my_bind[0].buffer_length= (unsigned long)strlen(concat_arg0);
+
+ mysql_stmt_bind_param(stmt, my_bind);
+
+ /* Execute the select statement */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ my_bind[0].buffer= (void *) out_buff;
+ my_bind[0].buffer_length= OUT_BUFF_SIZE;
+ my_bind[0].length= &out_length;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ strcpy(canonical_buff, concat_arg0);
+ strcat(canonical_buff, "ONE");
+ FAIL_UNLESS(strlen(canonical_buff) == out_length &&
+ strncmp(out_buff, canonical_buff, out_length) == 0, "");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ strcpy(canonical_buff + strlen(concat_arg0), "TWO");
+ FAIL_UNLESS(strlen(canonical_buff) == out_length &&
+ strncmp(out_buff, canonical_buff, out_length) == 0, "");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug4026(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ MYSQL_TIME time_in, time_out;
+ MYSQL_TIME datetime_in, datetime_out;
+ const char *stmt_text;
+ int rc;
+
+
+ /* Check that microseconds are inserted and selected successfully */
+
+ /* Create a statement handle and prepare it with select */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT ?, ?";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ /* Bind input buffers */
+ memset(my_bind, '\0', sizeof(MYSQL_BIND) * 2);
+ memset(&time_in, '\0', sizeof(MYSQL_TIME));
+ memset(&time_out, '\0', sizeof(MYSQL_TIME));
+ memset(&datetime_in, '\0', sizeof(MYSQL_TIME));
+ memset(&datetime_out, '\0', sizeof(MYSQL_TIME));
+ my_bind[0].buffer_type= MYSQL_TYPE_TIME;
+ my_bind[0].buffer= (void *) &time_in;
+ my_bind[1].buffer_type= MYSQL_TYPE_DATETIME;
+ my_bind[1].buffer= (void *) &datetime_in;
+
+ time_in.hour= 23;
+ time_in.minute= 59;
+ time_in.second= 59;
+ time_in.second_part= 123456;
+ /*
+ This is not necessary, just to make DIE_UNLESS below work: this field
+ is filled in when time is received from server
+ */
+ time_in.time_type= MYSQL_TIMESTAMP_TIME;
+
+ datetime_in= time_in;
+ datetime_in.year= 2003;
+ datetime_in.month= 12;
+ datetime_in.day= 31;
+ datetime_in.time_type= MYSQL_TIMESTAMP_DATETIME;
+
+ mysql_stmt_bind_param(stmt, my_bind);
+
+ /* Execute the select statement */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ my_bind[0].buffer= (void *) &time_out;
+ my_bind[1].buffer= (void *) &datetime_out;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+ FAIL_UNLESS(memcmp(&time_in, &time_out, sizeof(time_in)) == 0, "time_in != time_out");
+ FAIL_UNLESS(memcmp(&datetime_in, &datetime_out, sizeof(datetime_in)) == 0, "datetime_in != datetime_out");
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_bug4030(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[3];
+ MYSQL_TIME time_canonical, time_out;
+ MYSQL_TIME date_canonical, date_out;
+ MYSQL_TIME datetime_canonical, datetime_out;
+ const char *stmt_text;
+ int rc;
+
+
+ /* Check that microseconds are inserted and selected successfully */
+
+ /* Execute a query with time values in prepared mode */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT '23:59:59.123456', '2003-12-31', "
+ "'2003-12-31 23:59:59.123456'";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ /* Bind output buffers */
+ memset(my_bind, '\0', sizeof(my_bind));
+ memset(&time_canonical, '\0', sizeof(time_canonical));
+ memset(&time_out, '\0', sizeof(time_out));
+ memset(&date_canonical, '\0', sizeof(date_canonical));
+ memset(&date_out, '\0', sizeof(date_out));
+ memset(&datetime_canonical, '\0', sizeof(datetime_canonical));
+ memset(&datetime_out, '\0', sizeof(datetime_out));
+ my_bind[0].buffer_type= MYSQL_TYPE_TIME;
+ my_bind[0].buffer= (void *) &time_out;
+ my_bind[1].buffer_type= MYSQL_TYPE_DATE;
+ my_bind[1].buffer= (void *) &date_out;
+ my_bind[2].buffer_type= MYSQL_TYPE_DATETIME;
+ my_bind[2].buffer= (void *) &datetime_out;
+
+ time_canonical.hour= 23;
+ time_canonical.minute= 59;
+ time_canonical.second= 59;
+ time_canonical.second_part= 123456;
+ time_canonical.time_type= MYSQL_TIMESTAMP_TIME;
+
+ date_canonical.year= 2003;
+ date_canonical.month= 12;
+ date_canonical.day= 31;
+ date_canonical.time_type= MYSQL_TIMESTAMP_DATE;
+
+ datetime_canonical= time_canonical;
+ datetime_canonical.year= 2003;
+ datetime_canonical.month= 12;
+ datetime_canonical.day= 31;
+ datetime_canonical.time_type= MYSQL_TIMESTAMP_DATETIME;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+ FAIL_UNLESS(memcmp(&time_canonical, &time_out, sizeof(time_out)) == 0, "time_canonical != time_out");
+ FAIL_UNLESS(memcmp(&date_canonical, &date_out, sizeof(date_out)) == 0, "date_canoncical != date_out");
+ FAIL_UNLESS(memcmp(&datetime_canonical, &datetime_out, sizeof(datetime_out)) == 0, "datetime_canonical != datetime_out");
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug4079(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ const char *stmt_text;
+ uint32 res;
+ int rc;
+
+ /* Create and fill table */
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2)");
+
+ /* Prepare erroneous statement */
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT 1 < (SELECT a FROM t1)";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ /* Execute the select statement */
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ /* Bind input buffers */
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *) &res;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 1, "rc != 1");
+ /* buggy version of libmysql hanged up here */
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug4172(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[3];
+ const char *stmt_text;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+ char f[100], d[100], e[100];
+ ulong f_len, d_len, e_len;
+
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ mysql_query(mysql, "CREATE TABLE t1 (f float, d double, e decimal(10,4))");
+ mysql_query(mysql, "INSERT INTO t1 VALUES (12345.1234, 123456.123456, "
+ "123456.1234)");
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT f, d, e FROM t1";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt); rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ memset(my_bind, '\0', sizeof(my_bind)); my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= f;
+ my_bind[0].buffer_length= sizeof(f);
+ my_bind[0].length= &f_len;
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= d;
+ my_bind[1].buffer_length= sizeof(d);
+ my_bind[1].length= &d_len;
+ my_bind[2].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[2].buffer= e;
+ my_bind[2].buffer_length= sizeof(e);
+ my_bind[2].length= &e_len;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+
+ diag("expected %s %s %s", row[0], row[1], row[2]);
+ diag("fetched %s %s %s", f, d, e);
+ FAIL_UNLESS(!strcmp(f, row[0]) && !strcmp(d, row[1]) && !strcmp(e, row[2]), "");
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug4231(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ MYSQL_TIME tm[2];
+ const char *stmt_text;
+ int rc;
+
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "CREATE TABLE t1 (a int)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "INSERT INTO t1 VALUES (1)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT a FROM t1 WHERE ? = ?";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ /* Bind input buffers */
+ memset(my_bind, '\0', sizeof(my_bind)); memset(tm, '\0', sizeof(tm));
+ my_bind[0].buffer_type= MYSQL_TYPE_DATE;
+ my_bind[0].buffer= &tm[0];
+ my_bind[1].buffer_type= MYSQL_TYPE_DATE;
+ my_bind[1].buffer= &tm[1];
+
+ mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ /*
+ First set server-side params to some non-zero non-equal values:
+ then we will check that they are not used when client sends
+ new (zero) times.
+ */
+ tm[0].time_type = MYSQL_TIMESTAMP_DATE;
+ tm[0].year = 2000;
+ tm[0].month = 1;
+ tm[0].day = 1;
+ tm[1]= tm[0];
+ --tm[1].year; /* tm[0] != tm[1] */
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+
+ /* binds are unequal, no rows should be returned */
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ /* Set one of the dates to zero */
+ tm[0].year= tm[0].month= tm[0].day= 0;
+ tm[1]= tm[0];
+ mysql_stmt_execute(stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+
+ mysql_stmt_close(stmt);
+ stmt_text= "DROP TABLE t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug4236(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ MYSQL_STMT backup;
+
+ stmt= mysql_stmt_init(mysql);
+
+ /* mysql_stmt_execute() of statement with statement id= 0 crashed server */
+ stmt_text= "SELECT 1";
+ /* We need to prepare statement to pass by possible check in libmysql */
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt); /* Hack to check that server works OK if statement wasn't found */
+ backup.stmt_id= stmt->stmt_id;
+ stmt->stmt_id= 0;
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, "Error expected");
+
+ /* Restore original statement id to be able to reprepare it */
+ stmt->stmt_id= backup.stmt_id;
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug5126(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ int32 c1, c2;
+ const char *stmt_text;
+ int rc;
+
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "CREATE TABLE t1 (a mediumint, b int)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "INSERT INTO t1 VALUES (8386608, 1)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT a, b FROM t1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ /* Bind output buffers */
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= &c1;
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[1].buffer= &c2;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+ FAIL_UNLESS(c1 == 8386608 && c2 == 1, "c1 != 8386608 || c2 != 1");
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug5194(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND *my_bind;
+ char *query;
+ char *param_str;
+ int param_str_length;
+ const char *stmt_text;
+ int rc;
+ float float_array[250] =
+ {
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
+ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25
+ };
+ float *fa_ptr= float_array;
+ /* Number of columns per row */
+ const int COLUMN_COUNT= sizeof(float_array)/sizeof(*float_array);
+ /* Number of rows per bulk insert to start with */
+ const int MIN_ROWS_PER_INSERT= 262;
+ /* Max number of rows per bulk insert to end with */
+ const int MAX_ROWS_PER_INSERT= 300;
+ const int MAX_PARAM_COUNT= COLUMN_COUNT*MAX_ROWS_PER_INSERT;
+ const char *query_template= "insert into t1 values %s";
+ const int CHARS_PER_PARAM= 5; /* space needed to place ", ?" in the query */
+ const int uint16_max= 65535;
+ int nrows, i;
+
+ SKIP_MAXSCALE;
+
+ stmt_text= "drop table if exists t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+
+ stmt_text= "create table if not exists t1"
+ "(c1 float, c2 float, c3 float, c4 float, c5 float, c6 float, "
+ "c7 float, c8 float, c9 float, c10 float, c11 float, c12 float, "
+ "c13 float, c14 float, c15 float, c16 float, c17 float, c18 float, "
+ "c19 float, c20 float, c21 float, c22 float, c23 float, c24 float, "
+ "c25 float, c26 float, c27 float, c28 float, c29 float, c30 float, "
+ "c31 float, c32 float, c33 float, c34 float, c35 float, c36 float, "
+ "c37 float, c38 float, c39 float, c40 float, c41 float, c42 float, "
+ "c43 float, c44 float, c45 float, c46 float, c47 float, c48 float, "
+ "c49 float, c50 float, c51 float, c52 float, c53 float, c54 float, "
+ "c55 float, c56 float, c57 float, c58 float, c59 float, c60 float, "
+ "c61 float, c62 float, c63 float, c64 float, c65 float, c66 float, "
+ "c67 float, c68 float, c69 float, c70 float, c71 float, c72 float, "
+ "c73 float, c74 float, c75 float, c76 float, c77 float, c78 float, "
+ "c79 float, c80 float, c81 float, c82 float, c83 float, c84 float, "
+ "c85 float, c86 float, c87 float, c88 float, c89 float, c90 float, "
+ "c91 float, c92 float, c93 float, c94 float, c95 float, c96 float, "
+ "c97 float, c98 float, c99 float, c100 float, c101 float, c102 float, "
+ "c103 float, c104 float, c105 float, c106 float, c107 float, c108 float, "
+ "c109 float, c110 float, c111 float, c112 float, c113 float, c114 float, "
+ "c115 float, c116 float, c117 float, c118 float, c119 float, c120 float, "
+ "c121 float, c122 float, c123 float, c124 float, c125 float, c126 float, "
+ "c127 float, c128 float, c129 float, c130 float, c131 float, c132 float, "
+ "c133 float, c134 float, c135 float, c136 float, c137 float, c138 float, "
+ "c139 float, c140 float, c141 float, c142 float, c143 float, c144 float, "
+ "c145 float, c146 float, c147 float, c148 float, c149 float, c150 float, "
+ "c151 float, c152 float, c153 float, c154 float, c155 float, c156 float, "
+ "c157 float, c158 float, c159 float, c160 float, c161 float, c162 float, "
+ "c163 float, c164 float, c165 float, c166 float, c167 float, c168 float, "
+ "c169 float, c170 float, c171 float, c172 float, c173 float, c174 float, "
+ "c175 float, c176 float, c177 float, c178 float, c179 float, c180 float, "
+ "c181 float, c182 float, c183 float, c184 float, c185 float, c186 float, "
+ "c187 float, c188 float, c189 float, c190 float, c191 float, c192 float, "
+ "c193 float, c194 float, c195 float, c196 float, c197 float, c198 float, "
+ "c199 float, c200 float, c201 float, c202 float, c203 float, c204 float, "
+ "c205 float, c206 float, c207 float, c208 float, c209 float, c210 float, "
+ "c211 float, c212 float, c213 float, c214 float, c215 float, c216 float, "
+ "c217 float, c218 float, c219 float, c220 float, c221 float, c222 float, "
+ "c223 float, c224 float, c225 float, c226 float, c227 float, c228 float, "
+ "c229 float, c230 float, c231 float, c232 float, c233 float, c234 float, "
+ "c235 float, c236 float, c237 float, c238 float, c239 float, c240 float, "
+ "c241 float, c242 float, c243 float, c244 float, c245 float, c246 float, "
+ "c247 float, c248 float, c249 float, c250 float)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ my_bind= (MYSQL_BIND*) malloc(MAX_PARAM_COUNT * sizeof(MYSQL_BIND));
+ query= (char*) malloc(strlen(query_template) +
+ MAX_PARAM_COUNT * CHARS_PER_PARAM + 1);
+ param_str= (char*) malloc(COLUMN_COUNT * CHARS_PER_PARAM);
+
+ FAIL_IF(my_bind == 0 || query == 0 || param_str == 0, "Not enough memory");
+
+ stmt= mysql_stmt_init(mysql);
+
+ /* setup a template for one row of parameters */
+ sprintf(param_str, "(");
+ for (i= 1; i < COLUMN_COUNT; ++i)
+ strcat(param_str, "?, ");
+ strcat(param_str, "?)");
+ param_str_length= (int)strlen(param_str);
+
+ /* setup bind array */
+ memset(my_bind, '\0', MAX_PARAM_COUNT * sizeof(MYSQL_BIND));
+ for (i= 0; i < MAX_PARAM_COUNT; ++i)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_FLOAT;
+ my_bind[i].buffer= fa_ptr;
+ if (++fa_ptr == float_array + COLUMN_COUNT)
+ fa_ptr= float_array;
+ }
+
+ /*
+ Test each number of rows per bulk insert, so that we can see where
+ MySQL fails.
+ */
+ for (nrows= MIN_ROWS_PER_INSERT; nrows <= MAX_ROWS_PER_INSERT; ++nrows)
+ {
+ char *query_ptr;
+ /* Create statement text for current number of rows */
+ sprintf(query, query_template, param_str);
+ query_ptr= query + (unsigned long)strlen(query);
+ for (i= 1; i < nrows; ++i)
+ {
+ memcpy(query_ptr, ", ", 2);
+ query_ptr+= 2;
+ memcpy(query_ptr, param_str, param_str_length);
+ query_ptr+= param_str_length;
+ }
+ *query_ptr= '\0';
+
+ rc= mysql_stmt_prepare(stmt, query, (ulong)(query_ptr - query));
+
+ if (rc && nrows * COLUMN_COUNT > uint16_max) /* expected error */
+ break;
+
+ check_stmt_rc(rc, stmt);
+
+ /* bind the parameter array and execute the query */
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_reset(stmt);
+ }
+
+ free(param_str);
+ free(query);
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+ free(my_bind);
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug5315(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ stmt_text= "SELECT 1";
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_change_user(mysql, username, password, schema);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_UNLESS(rc != 0, "Error expected");
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug5399(MYSQL *mysql)
+{
+ /*
+ Ascii 97 is 'a', which gets mapped to Ascii 65 'A' unless internal
+ statement id hash in the server uses binary collation.
+ */
+#define NUM_OF_USED_STMT 97
+ MYSQL_STMT *stmt_list[NUM_OF_USED_STMT];
+ MYSQL_STMT **stmt;
+ MYSQL_BIND my_bind[1];
+ char buff[600];
+ int rc;
+ int32 no;
+
+
+ memset(my_bind, '\0', sizeof(my_bind)); my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= &no;
+
+ for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
+ {
+ sprintf(buff, "select %d", (int) (stmt - stmt_list));
+ *stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(*stmt, SL(buff));
+ check_stmt_rc(rc, *stmt); mysql_stmt_bind_result(*stmt, my_bind);
+ }
+
+ for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
+ {
+ rc= mysql_stmt_execute(*stmt);
+ check_stmt_rc(rc, *stmt);
+ rc= mysql_stmt_store_result(*stmt);
+ check_stmt_rc(rc, *stmt);
+ rc= mysql_stmt_fetch(*stmt);
+ FAIL_UNLESS((int32) (stmt - stmt_list) == no, "");
+ }
+
+ for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
+ mysql_stmt_close(*stmt);
+#undef NUM_OF_USED_STMT
+ return OK;
+}
+
+static int test_bug6046(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ short b= 1;
+ MYSQL_BIND my_bind[1];
+
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "CREATE TABLE t1 (a int, b int)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "INSERT INTO t1 VALUES (1,1),(2,2),(3,1),(4,2)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+
+ stmt_text= "SELECT t1.a FROM t1 NATURAL JOIN t1 as X1 "
+ "WHERE t1.b > ? ORDER BY t1.a";
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ b= 1;
+ memset(my_bind, '\0', sizeof(my_bind)); my_bind[0].buffer= &b;
+ my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
+
+ mysql_stmt_bind_param(stmt, my_bind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_store_result(stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug6049(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ const char *stmt_text;
+ char buffer[30];
+ ulong length;
+ int rc;
+
+
+ stmt_text= "SELECT MAKETIME(-25, 12, 12)";
+
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type = MYSQL_TYPE_STRING;
+ my_bind[0].buffer = &buffer;
+ my_bind[0].buffer_length = sizeof(buffer);
+ my_bind[0].length = &length;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(strcmp(row[0], (char*) buffer) == 0, "row[0] != buffer");
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug6058(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ const char *stmt_text;
+ char buffer[30];
+ ulong length;
+ int rc;
+
+
+ stmt_text= "SELECT CAST('0000-00-00' AS DATE)";
+
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type = MYSQL_TYPE_STRING;
+ my_bind[0].buffer = &buffer;
+ my_bind[0].buffer_length = sizeof(buffer);
+ my_bind[0].length = &length;
+
+ mysql_stmt_bind_result(stmt, my_bind);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(strcmp(row[0], buffer) == 0, "row[0] != buffer");
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+
+static int test_bug6059(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+
+ SKIP_SKYSQL;
+
+ stmt_text= "SELECT 'foo' INTO OUTFILE 'x.3'";
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(mysql_stmt_field_count(stmt) == 0, "");
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_bug6096(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *query_result, *stmt_metadata;
+ const char *stmt_text;
+ MYSQL_BIND my_bind[12];
+ MYSQL_FIELD *query_field_list, *stmt_field_list;
+ ulong query_field_count, stmt_field_count;
+ int rc;
+ my_bool update_max_length= TRUE;
+ uint i;
+
+
+ stmt_text= "drop table if exists t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ mysql_query(mysql, "set sql_mode=''");
+ stmt_text= "create table t1 (c_tinyint tinyint, c_smallint smallint, "
+ " c_mediumint mediumint, c_int int, "
+ " c_bigint bigint, c_float float, "
+ " c_double double, c_varchar varchar(20), "
+ " c_char char(20), c_time time, c_date date, "
+ " c_datetime datetime)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "insert into t1 values (-100, -20000, 30000000, 4, 8, 1.0, "
+ "2.0, 'abc', 'def', now(), now(), now())";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "select * from t1";
+
+ /* Run select in prepared and non-prepared mode and compare metadata */
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ query_result= mysql_store_result(mysql);
+ query_field_list= mysql_fetch_fields(query_result);
+ FAIL_IF(!query_field_list, "fetch_fields failed");
+ query_field_count= mysql_num_fields(query_result);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt); rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt); mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH,
+ (void*) &update_max_length);
+ mysql_stmt_store_result(stmt);
+ stmt_metadata= mysql_stmt_result_metadata(stmt);
+ stmt_field_list= mysql_fetch_fields(stmt_metadata);
+ stmt_field_count= mysql_num_fields(stmt_metadata);
+ FAIL_UNLESS(stmt_field_count == query_field_count, "");
+
+
+ /* Bind and fetch the data */
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i= 0; i < stmt_field_count; ++i)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[i].buffer_length= stmt_field_list[i].max_length + 1;
+ my_bind[i].buffer= malloc(my_bind[i].buffer_length);
+ }
+ mysql_stmt_bind_result(stmt, my_bind);
+ rc= mysql_stmt_fetch(stmt);
+ diag("rc=%d", rc);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ /* Clean up */
+
+ for (i= 0; i < stmt_field_count; ++i)
+ free(my_bind[i].buffer);
+ mysql_stmt_close(stmt);
+ mysql_free_result(query_result);
+ mysql_free_result(stmt_metadata);
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Bug#7990 - mysql_stmt_close doesn't reset mysql->net.last_error */
+
+static int test_bug7990(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, "foo", 3);
+ /*
+ XXX: the fact that we store errno both in STMT and in
+ MYSQL is not documented and is subject to change in 5.0
+ */
+ FAIL_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql), "Error expected");
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+/* Bug#8330 - mysql_stmt_execute crashes (libmysql) */
+
+static int test_bug8330(MYSQL *mysql)
+{
+ const char *stmt_text;
+ MYSQL_STMT *stmt[2];
+ int i, rc;
+ const char *query= "select a,b from t1 where a=?";
+ MYSQL_BIND my_bind[2];
+ long lval[2]= {1,2};
+
+ stmt_text= "drop table if exists t1";
+ /* in case some previous test failed */
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "create table t1 (a int, b int)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i=0; i < 2; i++)
+ {
+ stmt[i]= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt[i], SL(query));
+ check_stmt_rc(rc, stmt[i]);
+ my_bind[i].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[i].buffer= (void*) &lval[i];
+ my_bind[i].is_null= 0;
+ mysql_stmt_bind_param(stmt[i], &my_bind[i]);
+ }
+
+ rc= mysql_stmt_execute(stmt[0]);
+ check_stmt_rc(rc, stmt[0]);
+ rc= mysql_stmt_execute(stmt[1]);
+ FAIL_UNLESS(rc && mysql_stmt_errno(stmt[1]) == CR_COMMANDS_OUT_OF_SYNC, "Error expected");
+ rc= mysql_stmt_execute(stmt[0]);
+ check_stmt_rc(rc, stmt[0]);
+ mysql_stmt_close(stmt[0]);
+ mysql_stmt_close(stmt[1]);
+
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test misc field information, bug: #74 */
+
+static int test_field_misc(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ int rc;
+
+
+ rc= mysql_query(mysql, "SELECT @@autocommit");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ verify_prepare_field(result, 0,
+ "@@autocommit", "", /* field and its org name */
+ MYSQL_TYPE_LONGLONG, /* field type */
+ "", "", /* table and its org name */
+ "", 1, 0); /* db name, length(its bool flag)*/
+
+ mysql_free_result(result);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT @@autocommit"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ verify_prepare_field(result, 0,
+ "@@autocommit", "", /* field and its org name */
+ MYSQL_TYPE_LONGLONG, /* field type */
+ "", "", /* table and its org name */
+ "", 1, 0); /* db name, length(its bool flag)*/
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ // XPAND doesn't support @@max_error_count
+ SKIP_XPAND
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT @@max_error_count"));
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ if (verify_prepare_field(result, 0,
+ "@@max_error_count", "", /* field and its org name */
+ MYSQL_TYPE_LONGLONG, /* field type */
+ "", "", /* table and its org name */
+ /* db name, length */
+ "", MY_INT64_NUM_DECIMAL_DIGITS , 0))
+ goto error;
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT @@max_allowed_packet"));
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ if (verify_prepare_field(result, 0,
+ "@@max_allowed_packet", "", /* field and its org name */
+ MYSQL_TYPE_LONGLONG, /* field type */
+ "", "", /* table and its org name */
+ /* db name, length */
+ "", MY_INT64_NUM_DECIMAL_DIGITS, 0))
+ goto error;
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT @@sql_warnings"));
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ if (verify_prepare_field(result, 0,
+ "@@sql_warnings", "", /* field and its org name */
+ MYSQL_TYPE_LONGLONG, /* field type */
+ "", "", /* table and its org name */
+ "", 1, 0)) /* db name, length */
+ goto error;
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+ return OK;
+
+error:
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+ return FAIL;
+}
+
+/* Test a memory overrun bug */
+
+static int test_mem_overun(MYSQL *mysql)
+{
+ char buffer[10000], field[12];
+ MYSQL_STMT *stmt;
+ MYSQL_RES *field_res, *res;
+ int rc, i, length;
+
+ /*
+ Test a memory overrun bug when a table had 1000 fields with
+ a row of data
+ */
+ rc= mysql_query(mysql, "drop table if exists t_mem_overun");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(buffer, "create table t_mem_overun(");
+ for (i= 0; i < 1000; i++)
+ {
+ snprintf(field, sizeof(field), "c%d int, ", i);
+ strcat(buffer, field);
+ }
+ length= (int)strlen(buffer);
+ buffer[length-2]= ')';
+ buffer[--length]= '\0';
+
+ rc= mysql_real_query(mysql, buffer, length);
+ check_mysql_rc(rc, mysql);
+
+ strcpy(buffer, "insert into t_mem_overun values(");
+ for (i= 0; i < 1000; i++)
+ {
+ strcat(buffer, "1, ");
+ }
+ length= (int)strlen(buffer);
+ buffer[length-2]= ')';
+ buffer[--length]= '\0';
+
+ rc= mysql_real_query(mysql, buffer, length);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "select * from t_mem_overun");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ rc= 0;
+ while (mysql_fetch_row(res))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+ mysql_free_result(res);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("select * from t_mem_overun"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ field_res= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!field_res, "Invalid result set");
+
+ FAIL_UNLESS( 1000 == mysql_num_fields(field_res), "fields != 1000");
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "");
+
+ mysql_free_result(field_res);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table if exists t_mem_overun");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug8722(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+
+ /* Prepare test data */
+ stmt_text= "drop table if exists t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "drop view if exists v1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "CREATE TABLE t1 (c1 varchar(10), c2 varchar(10), c3 varchar(10),"
+ " c4 varchar(10), c5 varchar(10), c6 varchar(10),"
+ " c7 varchar(10), c8 varchar(10), c9 varchar(10),"
+ "c10 varchar(10))";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "INSERT INTO t1 VALUES (1,2,3,4,5,6,7,8,9,10)";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+ stmt_text= "CREATE VIEW v1 AS SELECT * FROM t1";
+ rc= mysql_real_query(mysql, SL(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "select * from v1";
+ rc= mysql_stmt_prepare(stmt, SL(stmt_text));
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+ stmt_text= "drop table if exists t1, v1";
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test DECIMAL conversion */
+
+static int test_decimal_bug(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ char data[30];
+ int rc;
+ my_bool is_null;
+
+ mysql_autocommit(mysql, TRUE);
+
+ rc= mysql_query(mysql, "drop table if exists test_decimal_bug");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table test_decimal_bug(c1 decimal(10, 2))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into test_decimal_bug value(8), (10.22), (5.61)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("select c1 from test_decimal_bug where c1=?"));
+ check_stmt_rc(rc, stmt);
+
+ /*
+ We need to bzero bind structure because mysql_stmt_bind_param checks all
+ its members.
+ */
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ memset(data, 0, sizeof(data));
+ my_bind[0].buffer_type= MYSQL_TYPE_NEWDECIMAL;
+ my_bind[0].buffer= (void *)data;
+ my_bind[0].buffer_length= 25;
+ my_bind[0].is_null= &is_null;
+
+ is_null= 0;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ strcpy(data, "8.0");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ data[0]= 0;
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(strcmp(data, "8.00") == 0, "data != '8.00'");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ strcpy(data, "5.61");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ data[0]= 0;
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(strcmp(data, "5.61") == 0, "data != '5.61'");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ is_null= 1;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ strcpy(data, "10.22"); is_null= 0;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ data[0]= 0;
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(strcmp(data, "10.22") == 0, "data != '10.22'");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table if exists test_decimal_bug");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test EXPLAIN bug (#115, reported by mark@mysql.com & georg@php.net). */
+
+static int test_explain_bug(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_RES *result;
+ int rc;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ mysql_autocommit(mysql, TRUE);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_explain");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_explain(id int, name char(2))");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("explain test_explain"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 2, "rowcount != 2");
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, "Invalid result set");
+
+ FAIL_UNLESS(6 == mysql_num_fields(result), "fields != 6");
+
+ if (verify_prepare_field(result, 0, "Field", "COLUMN_NAME",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0,
+ mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema",
+ 64, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 1, "Type", "COLUMN_TYPE", MYSQL_TYPE_BLOB,
+ 0, 0,
+ mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema",
+ 0, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 2, "Null", "IS_NULLABLE",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0,
+ mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema",
+ 3, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 3, "Key", "COLUMN_KEY",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0,
+ mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema",
+ 3, 0))
+ goto error;
+
+ if ( mysql_get_server_version(mysql) >= 50027 )
+ {
+ /* The patch for bug#23037 changes column type of DEAULT to blob */
+ if (verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
+ MYSQL_TYPE_BLOB, 0, 0,
+ mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema",
+ 0, 0))
+ goto error;
+ }
+ else
+ {
+ if (verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
+ mysql_get_server_version(mysql) >= 50027 ?
+ MYSQL_TYPE_BLOB :
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0,
+ mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema",
+ mysql_get_server_version(mysql) >= 50027 ? 0 :64, 0))
+ goto error;
+ }
+
+ if (verify_prepare_field(result, 5, "Extra", "EXTRA",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0,
+ mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema",
+ 27, 0))
+ goto error;
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("explain select id, name FROM test_explain"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (!mysql_stmt_fetch(stmt))
+ rc++;
+ FAIL_UNLESS(rc == 1, "rowcount != 1");
+
+ result= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!result, "Invalid result set");
+
+ FAIL_UNLESS(10 == mysql_num_fields(result), "fields != 10");
+
+ if (verify_prepare_field(result, 0, "id", "", MYSQL_TYPE_LONGLONG, "", "", "", 3, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 1, "select_type", "", MYSQL_TYPE_VAR_STRING, "", "", "", 19, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 2, "table", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 3, "type", "", MYSQL_TYPE_VAR_STRING, "", "", "", 10, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN*MAX_KEY, 0))
+ goto error;
+
+ if ( verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN, 0))
+ goto error;
+
+ if (mysql_get_server_version(mysql) <= 50000)
+ {
+ if (verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG, "", "", "", 3, 0))
+ goto error;
+ }
+ else if (mysql_get_server_version(mysql) <= 60000)
+ {
+ if (verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN*MAX_KEY, 0))
+ goto error;
+ }
+ else
+ {
+ if (verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", "", "", (MAX_KEY_LENGTH_DECIMAL_WIDTH + 1) * MAX_KEY, 0))
+ goto error;
+ }
+
+ if (verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING, "", "", "",
+ NAME_CHAR_LEN*16, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 8, "rows", "", MYSQL_TYPE_LONGLONG, "", "", "", 10, 0))
+ goto error;
+
+ if (verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_VAR_STRING, "", "", "", 255, 0))
+ goto error;
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_explain");
+ check_mysql_rc(rc, mysql);
+ return OK;
+error:
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+ return FAIL;
+}
+
+static int test_sshort_bug(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[4];
+ short short_value;
+ int32 long_value;
+ ulong s_length, l_length, ll_length, t_length;
+ ulonglong longlong_value;
+ int rc;
+ uchar tiny_value;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sshort");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_sshort(a smallint signed, \
+ b smallint signed, \
+ c smallint unsigned, \
+ d smallint unsigned)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)");
+ check_mysql_rc(rc, mysql);
+
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_sshort"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[0].buffer= (void *)&short_value;
+ my_bind[0].length= &s_length;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[1].buffer= (void *)&long_value;
+ my_bind[1].length= &l_length;
+
+ my_bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[2].buffer= (void *)&longlong_value;
+ my_bind[2].length= &ll_length;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[3].buffer= (void *)&tiny_value;
+ my_bind[3].is_unsigned= TRUE;
+ my_bind[3].length= &t_length;
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(short_value == -5999, "sv != -5999");
+ FAIL_UNLESS(s_length == 2, "s_length != 2");
+
+ FAIL_UNLESS(long_value == -5999, "l_v != -5999");
+ FAIL_UNLESS(l_length == 4, "l_length != 4");
+
+ FAIL_UNLESS(longlong_value == 35999, "llv != 35999");
+ FAIL_UNLESS(ll_length == 8, "ll_length != 8");
+
+ FAIL_UNLESS(tiny_value == 200, "t_v != 200");
+ FAIL_UNLESS(t_length == 1, "t_length != 1");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sshort");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+
+/* Test a misc tinyint-signed conversion bug */
+
+static int test_stiny_bug(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[4];
+ short short_value;
+ int32 long_value;
+ ulong s_length, l_length, ll_length, t_length;
+ ulonglong longlong_value;
+ int rc;
+ uchar tiny_value;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stiny");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_stiny(a tinyint signed, \
+ b tinyint signed, \
+ c tinyint unsigned, \
+ d tinyint unsigned)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_stiny VALUES(-128, -127, 255, 0)");
+ check_mysql_rc(rc, mysql);
+
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_stiny"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[0].buffer= (void *)&short_value;
+ my_bind[0].length= &s_length;
+
+ my_bind[1].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[1].buffer= (void *)&long_value;
+ my_bind[1].length= &l_length;
+
+ my_bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
+ my_bind[2].buffer= (void *)&longlong_value;
+ my_bind[2].length= &ll_length;
+
+ my_bind[3].buffer_type= MYSQL_TYPE_TINY;
+ my_bind[3].buffer= (void *)&tiny_value;
+ my_bind[3].length= &t_length;
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(short_value == -128, "s_v != -128");
+ FAIL_UNLESS(s_length == 2, "s_length != 2");
+
+ FAIL_UNLESS(long_value == -127, "l_v != -127");
+ FAIL_UNLESS(l_length == 4, "l_length != 4");
+
+ FAIL_UNLESS(longlong_value == 255, "llv != 255");
+ FAIL_UNLESS(ll_length == 8, "ll_length != 8");
+
+ FAIL_UNLESS(tiny_value == 0, "t_v != 0");
+ FAIL_UNLESS(t_length == 1, "t_length != 1");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stiny");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_bug53311(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ int i;
+ const char *query= "INSERT INTO bug53311 VALUES (1)";
+ SKIP_MAXSCALE;
+ SKIP_XPAND;
+
+ rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug53311");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE bug53311 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ for (i=0; i < 2; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+
+ /* kill connection */
+ rc= mysql_kill(mysql, mysql_thread_id(mysql));
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(rc == 0, "Error expected");
+ FAIL_IF(mysql_stmt_errno(stmt) == 0, "Errno != 0 expected");
+ rc= mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug53311");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+#define PREPARE_SQL "EXPLAIN SELECT t1.*, t2.* FROM test AS t1, test AS t2"
+
+#ifdef NOT_IN_USE
+static int test_metadata(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE=MYISAM");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')");
+ check_mysql_rc(rc, mysql);
+ printf("Client=%s\n", mysql_get_client_info());
+ printf("Server=%s\n", mysql_get_server_info(mysql));
+
+ {
+ MYSQL_STMT * stmt = mysql_stmt_init(mysql);
+ if (!stmt) {
+ fprintf(stderr, "Failed to init stmt: Error: %s\n", mysql_error(mysql));
+ goto end;
+ }
+ if (mysql_stmt_prepare(stmt, PREPARE_SQL, sizeof(PREPARE_SQL) - 1)) {
+ fprintf(stderr, "Failed to prepare stmt: Error: %s\n", mysql_stmt_error(stmt));
+ goto end2;
+ }
+ if (mysql_stmt_execute(stmt)) {
+ fprintf(stderr, "Failed to execute stmt: Error: %s\n", mysql_stmt_error(stmt));
+ goto end2;
+ }
+ {
+ MYSQL_FIELD * field = NULL;
+ MYSQL_RES * res = mysql_stmt_result_metadata(stmt);
+ if (!res) {
+ fprintf(stderr, "Failed to get metadata: Error: %s\n", mysql_stmt_error(stmt));
+ goto end2;
+ }
+ while ((field = mysql_fetch_field(res))) {
+ printf("name=%s\n", field->name);
+ printf("catalog=%s\n", field->catalog);
+ }
+ mysql_free_result(res);
+
+ }
+end2:
+ mysql_stmt_close(stmt);
+ }
+end:
+ return 0;
+}
+#endif
+
+static int test_conc_5(MYSQL *mysql)
+{
+ const char *query= "SELECT a FROM t1";
+ MYSQL_RES *res;
+ MYSQL_STMT *stmt;
+ MYSQL_FIELD *fields;
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, "couldn't allocate memory");
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ res= mysql_stmt_result_metadata(stmt);
+ FAIL_IF(!res, "Can't obtain resultset");
+
+ fields= mysql_fetch_fields(res);
+ FAIL_IF(!fields, "Can't obtain fields");
+
+ FAIL_IF(strcmp("def", fields[0].catalog), "unexpected value for field->catalog");
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_conc141(MYSQL *mysql)
+{
+ int rc;
+ const char *query= "CALL p_conc141";
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc141");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE conc141 (KeyVal int not null primary key)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO conc141 VALUES(1)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p_conc141");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE PROCEDURE p_conc141()\n"
+ "BEGIN\n"
+ "select * from conc141;\n"
+ "insert into conc141(KeyVal) VALUES(1);\n"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ /* skip first result */
+ rc= mysql_stmt_next_result(stmt);
+ FAIL_IF(rc==-1, "No more results and error expected");
+ mysql_stmt_free_result(stmt);
+ FAIL_IF(mysql_stmt_errno(stmt), "No Error expected");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc141");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p_conc141");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc154(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ const char *stmtstr= "SELECT * FROM t1";
+ int rc;
+
+ /* 1st: empty result set without free_result */
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a varchar(20))");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ /* 2nd: empty result set with free_result */
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ /* 3rd: non empty result without free_result */
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES ('test_conc154')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ /* 4th non empty result set with free_result */
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc155(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind;
+ char buffer[50];
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a TEXT)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES ('zero terminated string')");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM t1"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(buffer, 'X', 50);
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+
+ bind.buffer= buffer;
+ bind.buffer_length= 50;
+ bind.buffer_type= MYSQL_TYPE_STRING;
+
+ rc= mysql_stmt_bind_result(stmt, &bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ if (strlen(buffer) != strlen("zero terminated string"))
+ {
+ diag("Wrong buffer length");
+ return FAIL;
+ }
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc168(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+
+ MYSQL_BIND bind;
+ char buffer[100];
+ int rc;
+
+ //https://jira.mariadb.org/browse/XPT-273
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc168");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE conc168(a datetime(3))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO conc168 VALUES ('2016-03-09 07:51:49.000'),('2016-03-09 07:51:49.001'),('2016-03-09 07:51:49.010')");
+ check_mysql_rc(rc, mysql);
+
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+ bind.buffer= buffer;
+ bind.buffer_type= MYSQL_TYPE_STRING;
+ bind.buffer_length= 100;
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM conc168"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, &bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(strcmp(buffer, "2016-03-09 07:51:49.000"), "expected: 2016-03-09 07:51:49.000");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(strcmp(buffer, "2016-03-09 07:51:49.001"), "expected: 2016-03-09 07:51:49.001");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(strcmp(buffer, "2016-03-09 07:51:49.010"), "expected: 2016-03-09 07:51:49.010");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc168");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc167(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+
+ MYSQL_BIND bind[3];
+ char buffer[100];
+ int bit1=0, bit2=0;
+ int rc;
+ const char *stmt_str= "SELECT a,b,c FROM conc168";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc168");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE conc168(a bit, b bit, c varchar(10))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO conc168 VALUES (1,0, 'test12345')");
+ check_mysql_rc(rc, mysql);
+
+ memset(bind, 0, 3 * sizeof(MYSQL_BIND));
+ bind[0].buffer= &bit1;
+ bind[0].buffer_type= MYSQL_TYPE_BIT;
+ bind[0].buffer_length= sizeof(int);
+ bind[1].buffer= &bit2;
+ bind[1].buffer_type= MYSQL_TYPE_BIT;
+ bind[1].buffer_length= sizeof(int);
+ bind[2].buffer= buffer;
+ bind[2].buffer_type= MYSQL_TYPE_STRING;
+ bind[2].buffer_length= 100;
+
+ rc= mysql_stmt_prepare(stmt, SL(stmt_str));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ diag("bit=%d %d char=%s", bit1, bit2, buffer);
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_conc177(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind[2];
+ const char *stmt_str= "SELECT a,b FROM t1";
+ char buf1[128], buf2[128];
+
+ // https://jira.mariadb.org/browse/XPT-286
+ SKIP_XPAND
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a double zerofill default 8.8,b float zerofill default 8.8)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (DEFAULT, DEFAULT)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_str));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+ bind[0].buffer= &buf1;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer_length= 128;
+ bind[1].buffer= &buf2;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer_length= 128;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ mysql_stmt_close(stmt);
+
+ diag("buf1 %s\nbuf2 %s", buf1, buf2);
+
+ FAIL_IF(strcmp(buf1, "00000000000000000008.8"), "Expected 00000000000000000008.8");
+ FAIL_IF(strcmp(buf2, "0000000008.8"), "Expected 0000000008.8");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int(8) zerofill default 1, b int(4) zerofill default 1)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (DEFAULT, DEFAULT)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_str));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+ bind[0].buffer= &buf1;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer_length= 128;
+ bind[1].buffer= &buf2;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer_length= 128;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ mysql_stmt_close(stmt);
+
+ diag("buf1 %s\nbuf2 %s", buf1, buf2);
+
+ FAIL_IF(strcmp(buf1, "00000001"), "Expected 00000001");
+ FAIL_IF(strcmp(buf2, "0001"), "Expected 0001");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc179(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmtstr= "select 1 as ' '";
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ if (mysql_get_server_version(mysql) >= 100100)
+ {
+ FAIL_IF(mysql_warning_count(mysql) < 1, "expected 1 or more warnings");
+ FAIL_IF(mysql_stmt_warning_count(stmt) < 1, "expected 1 or more warnings");
+ }
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc182(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind[2];
+ char buf1[22];
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS t1", -1);
+ check_stmt_rc(rc, stmt);
+ rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS t1", -1);
+ check_stmt_rc(rc, stmt);
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1);
+ check_stmt_rc(rc, stmt);
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_close(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "SELECT row_count()");
+ result= mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+ diag("buf: %s", row[0]);
+ mysql_free_result(result);
+
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, "SELECT row_count()", -1);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+
+ memset(bind, 0, 2 * sizeof(MYSQL_BIND));
+ bind[0].buffer= &buf1;
+ bind[0].buffer_length= bind[1].buffer_length= 20;
+ bind[0].buffer_type= bind[1].buffer_type= MYSQL_TYPE_STRING;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+
+ while(!mysql_stmt_fetch(stmt))
+ diag("b1: %s", buf1);
+ rc= mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc181(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_BIND bind;
+ const char *stmt_str= "SELECT a FROM t1";
+ float f=1;
+ my_bool err= 0;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES(1073741825)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(stmt_str));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+ bind.buffer= &f;
+ bind.error= &err;
+ bind.buffer_type= MYSQL_TYPE_FLOAT;
+ rc= mysql_stmt_bind_result(stmt, &bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ diag("rc=%d err=%d float=%f, %d", rc, err, f, MYSQL_DATA_TRUNCATED);
+
+ rc= mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc198(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt1, *stmt2;
+ MYSQL_BIND my_bind[1];
+ int32 a;
+ int rc;
+ int num_rows= 0;
+ ulong type;
+ ulong prefetch_rows= 3;
+
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key)");
+ rc= mysql_query(mysql, "insert into t1 (id) values "
+ " (1), (2), (3), (4), (5), (6), (7), (8), (9)");
+ check_mysql_rc(rc, mysql);
+
+ stmt1= mysql_stmt_init(mysql);
+ stmt2= mysql_stmt_init(mysql);
+ /* Not implemented in 5.0 */
+ type= (ulong) CURSOR_TYPE_SCROLLABLE;
+ rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ FAIL_UNLESS(rc, "Error expected");
+ rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ FAIL_UNLESS(rc, "Error expected");
+
+ type= (ulong) CURSOR_TYPE_READ_ONLY;
+ rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (void*) &type);
+ check_stmt_rc(rc, stmt2);
+ rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_PREFETCH_ROWS,
+ (void*) &prefetch_rows);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_PREFETCH_ROWS,
+ (void*) &prefetch_rows);
+ check_stmt_rc(rc, stmt2);
+ rc= mysql_stmt_prepare(stmt1, "SELECT * FROM t1 ORDER by id ASC" , -1);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_prepare(stmt2, "SELECT * FROM t1 ORDER by id DESC", -1);
+ check_stmt_rc(rc, stmt2);
+
+ rc= mysql_stmt_execute(stmt1);
+ check_stmt_rc(rc, stmt1);
+ rc= mysql_stmt_execute(stmt2);
+ check_stmt_rc(rc, stmt2);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void*) &a;
+ my_bind[0].buffer_length= sizeof(a);
+ mysql_stmt_bind_result(stmt1, my_bind);
+ mysql_stmt_bind_result(stmt2, my_bind);
+
+ while ((rc= mysql_stmt_fetch(stmt1)) == 0)
+ ++num_rows;
+ FAIL_UNLESS(num_rows == 9, "num_rows != 9");
+
+ num_rows= 0;
+ while ((rc= mysql_stmt_fetch(stmt2)) == 0)
+ ++num_rows;
+ FAIL_UNLESS(num_rows == 9, "num_rows != 9");
+
+ rc= mysql_stmt_close(stmt1);
+ rc= mysql_stmt_close(stmt2);
+ FAIL_UNLESS(rc == 0, "");
+
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc205(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[3];
+ char data[8];
+ ulong length[3];
+ int rc, int_col;
+ short smint_col;
+ my_bool is_null[3];
+ const char *query = "SELECT text_col, smint_col, int_col FROM test_conc205";
+
+ rc= mysql_query(mysql, "drop table if exists test_conc205");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_conc205 (text_col TEXT, smint_col SMALLINT, int_col INT)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_conc205 VALUES('data01', 21893, 1718038908), ('data2', -25734, -1857802040)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)data;
+ my_bind[0].buffer_length= sizeof(data);
+ my_bind[0].is_null= &is_null[0];
+ my_bind[0].length= &length[0];
+
+ my_bind[1].buffer_type= MYSQL_TYPE_SHORT;
+ my_bind[1].buffer= &smint_col;
+ my_bind[1].buffer_length= 2;
+ my_bind[1].is_null= &is_null[1];
+ my_bind[1].length= &length[1];
+
+ my_bind[2].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[2].buffer= &int_col;
+ my_bind[2].buffer_length= 4;
+ my_bind[2].is_null= &is_null[2];
+ my_bind[2].length= &length[2];
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(length[0] != 6, "Wrong fetched string length");
+ FAIL_IF(length[1] != 2, "Wrong fetched short length");
+ FAIL_IF(length[2] != 4, "Wrong fetched int length");
+
+ FAIL_IF(strncmp(data, "data01", length[0] + 1) != 0, "Wrong string value");
+ FAIL_IF(smint_col != 21893, "Expected 21893");
+ FAIL_IF(int_col != 1718038908, "Expected 1718038908");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(length[0] != 5, "Wrong fetched string length");
+ FAIL_IF(length[1] != 2, "Wrong fetched short length");
+ FAIL_IF(length[2] != 4, "Wrong fetched int length");
+
+ FAIL_IF(strncmp(data, "data2", length[0] + 1) != 0, "Wrong string value");
+ FAIL_IF(smint_col != -25734, "Expected -25734");
+ FAIL_IF(int_col != -1857802040, "Expected -1857802040");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc != MYSQL_NO_DATA, "Expected MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table test_conc205");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc217(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+
+ SKIP_MAXSCALE;
+ rc= mariadb_stmt_execute_direct(stmt, "SELECT 1 FROM nonexisting_table", -1);
+ FAIL_IF(rc==0, "Expected error\n");
+ rc= mysql_query(mysql, "drop table if exists t_count");
+ check_mysql_rc(rc, mysql);
+ mysql_stmt_close(stmt);
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc208(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+ int data;
+ MYSQL_BIND bind;
+
+ rc= mysql_stmt_prepare(stmt, "SELECT \"100\" UNION SELECT \"88\" UNION SELECT \"389789\"", -1);
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+ bind.buffer_type= MYSQL_TYPE_LONG;
+ bind.buffer= (void *)&data;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, &bind);
+
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ {
+ diag("data=%d", data);
+ FAIL_IF(data != 100 && data != 88 && data != 389789, "Wrong value");
+ }
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_mdev14165(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_FIELD *fields;
+ MYSQL_RES *result;
+ my_bool val= 1;
+ MYSQL_BIND bind[1];
+ char buf1[52];
+
+ rc= mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &val);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ rc= mysql_query(mysql, "CREATE TABLE t1 (i INT(20) ZEROFILL)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (2),(1)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_stmt_prepare(stmt, "SELECT i FROM t1", -1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer_length= 51;
+ bind[0].buffer= buf1;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &val);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+
+ fields= mysql_fetch_fields(result);
+
+ FAIL_IF(fields[0].length < 20, "Expected length=20");
+ FAIL_IF(fields[0].max_length < 20, "Expected max_length=20");
+
+ mysql_stmt_fetch(stmt);
+
+ FAIL_UNLESS(strcmp(buf1, "00000000000000000002") == 0, "Wrong result");
+ mysql_free_result(result);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_compress(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+
+ rc= mariadb_stmt_execute_direct(stmt, SL("SELECT 1 FROM DUAL"));
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int equal_MYSQL_TIME(MYSQL_TIME *tm1, MYSQL_TIME *tm2)
+{
+ return tm1->day==tm2->day && tm1->hour==tm2->hour && tm1->minute==tm2->minute &&
+ tm1->month==tm2->month && tm1->neg==tm2->neg && tm1->second==tm2->second &&
+ tm1->second_part==tm2->second_part && tm1->time_type==tm2->time_type && tm1->year==tm2->year;
+}
+
+static int test_str_to_int(MYSQL *mysql)
+{
+ int i;
+ struct st_atoi_test{
+ const char *str_value;
+ int int_value;
+ int rc;
+ } atoi_tests[]=
+ {
+ {"0", 0, 0},
+ {" 1",1, 0},
+ {"123 ",123, 0},
+ {"10.2",10, MYSQL_DATA_TRUNCATED},
+ {"a", 0, MYSQL_DATA_TRUNCATED},
+ {"1 2 3", 1, MYSQL_DATA_TRUNCATED},
+ {NULL, 0, 0}
+ };
+
+ for(i=0; atoi_tests[i].str_value; i++)
+ {
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ struct st_atoi_test *test= &atoi_tests[i];
+ char sql[256];
+ int int_value;
+
+ snprintf(sql, sizeof(sql), "SELECT '%s'",test->str_value);
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, sql, (ulong)strlen(sql));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_store_result(stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= &int_value;
+ bind[0].buffer_length= sizeof(int_value);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+
+ diag("test: str='%s', expected/returned value =%d/%d, expected/returned rc=%d/%d",
+ test->str_value, test->int_value, int_value, test->rc, rc);
+ FAIL_UNLESS(rc == test->rc, "unexpected return code");
+ FAIL_UNLESS(int_value == test->int_value, "unexpected int value");
+ mysql_stmt_close(stmt);
+ }
+ return OK;
+}
+
+
+static int test_codbc138(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ MYSQL_TIME tm;
+ int i= 0;
+
+ struct st_time_test {
+ const char *statement;
+ MYSQL_TIME tm;
+ } time_test[]={
+ { "SELECT DATE_ADD('2018-02-01', INTERVAL -188 DAY)",
+ { 2017,7,28,0,0,0,0L,0, MYSQL_TIMESTAMP_DATE }
+ },
+ { "SELECT '2001-02-03 11:12:13.123456'",
+ { 2001,2,3,11,12,13,123456L,0, MYSQL_TIMESTAMP_DATETIME }
+ },
+ { "SELECT '2001-02-03 11:12:13.123'",
+ { 2001,2,3,11,12,13,123000L,0, MYSQL_TIMESTAMP_DATETIME }
+ },
+ { "SELECT '-11:12:13'",
+ { 0,0,0,11,12,13,0,1, MYSQL_TIMESTAMP_TIME }
+ },
+ { "SELECT ' '",
+ { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR }
+ },
+ { "SELECT '1--'",
+ { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR }
+ },
+ { "SELECT '-2001-01-01'",
+ { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR }
+ },
+ { "SELECT '-11:00'",
+ { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR }
+ },
+ {"SELECT '1972-04-22'",
+ {1972,4,22, 0,0,0, 0,0,MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT ' 1972-04-22 '",
+ {1972,4,22, 0,0,0, 0,0,MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '1972-04-22a'",
+ {1972,4,22, 0,0,0, 0,0,MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '0000-00-00'",
+ {0,0,0, 0,0,0 ,0,0,MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '1970-01-00'",
+ {1970,1,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '0069-12-31'",
+ {69,12,31, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '69-12-31'",
+ {2069,12,31, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '68-12-31'",
+ {2068,12,31, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '70-01-01'",
+ {1970,1,1, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE}
+ },
+ {"SELECT '2010-1-1'",
+ {2010,1,1, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE}
+ },
+
+ {"SELECT '10000-01-01'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1979-a-01'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1979-01-32'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1979-13-01'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1YYY-01-01'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1979-0M-01'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1979-00-'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1979-00'",
+ {0,0,0, 0,0,0, 0,0,MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '1979'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+ {"SELECT '79'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}
+ },
+
+ {"SELECT '10:15:00'",
+ {0,0,0, 10,15,0, 0,0, MYSQL_TIMESTAMP_TIME}
+ },
+ {"SELECT '10:15:01'",
+ {0,0,0, 10,15,1, 0,0, MYSQL_TIMESTAMP_TIME}
+ },
+ {"SELECT '00:00:00'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_TIME}
+ },
+ {"SELECT '0:0:0'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_TIME}
+ },
+ {"SELECT '10:15:01.'",
+ {0,0,0, 10,15,1, 0,0, MYSQL_TIMESTAMP_TIME},
+ },
+ {"SELECT '25:59:59'",
+ {0,0,0, 25,59,59, 0,0, MYSQL_TIMESTAMP_TIME},
+ },
+ {"SELECT '838:59:59'",
+ {0,0,0, 838,59,59, 0,0, MYSQL_TIMESTAMP_TIME},
+ },
+ {"SELECT '-838:59:59'",
+ {0,0,0, 838,59,59, 0, 1, MYSQL_TIMESTAMP_TIME},
+ },
+
+ {"SELECT '00:60:00'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR},
+ },
+ {"SELECT '839:00:00'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR},
+ },
+ {"SELECT '-839:00:00'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR},
+ },
+ {"SELECT '-10:15:a'",
+ { 0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR },
+ },
+ {"SELECT '1999-12-31 23:59:59.9999999'",
+ {1999,12,31, 23,59,59, 999999, 0, MYSQL_TIMESTAMP_DATETIME},
+ },
+ {"SELECT '00-08-11 8:46:40'",
+ {2000,8,11, 8,46,40, 0,0, MYSQL_TIMESTAMP_DATETIME},
+ },
+ {"SELECT '1999-12-31 25:59:59.999999'",
+ {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR },
+ },
+ { NULL,{ 0 } }
+ };
+
+ while (time_test[i].statement)
+ {
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(time_test[i].statement));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_store_result(stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer_type= MYSQL_TYPE_DATETIME;
+ bind[0].buffer= &tm;
+ bind[0].buffer_length= sizeof(MYSQL_TIME);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ diag("test: %s %d %d", time_test[i].statement, tm.time_type, time_test[i].tm.time_type);
+ if (time_test[i].tm.time_type == MYSQL_TIMESTAMP_ERROR)
+ {
+ FAIL_UNLESS(tm.time_type == MYSQL_TIMESTAMP_ERROR, "MYSQL_TIMESTAMP_ERROR expected");
+ }
+ else
+ FAIL_UNLESS(equal_MYSQL_TIME(&tm, &time_test[i].tm), "time_in != time_out");
+ mysql_stmt_close(stmt);
+ i++;
+ }
+
+ return OK;
+}
+
+static int test_conc334(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+ int rc;
+
+ rc= mysql_stmt_prepare(stmt, SL("SHOW ENGINES"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ result= mysql_stmt_result_metadata(stmt);
+ if (!result)
+ {
+ diag("Couldn't retrieve result set");
+ mysql_stmt_close(stmt);
+ return FAIL;
+ }
+
+ mysql_field_seek(result, 0);
+
+ while ((field= mysql_fetch_field(result)))
+ {
+ FAIL_IF(field->name_length == 0, "Invalid name length (0)");
+ FAIL_IF(field->table_length == 0, "Invalid name length (0)");
+ }
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+static int test_conc344(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1,1), (2,2),(3,3),(4,4),(5,5)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM t1 ORDER BY a"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ while (!mysql_stmt_fetch(stmt));
+ FAIL_IF(mysql_stmt_num_rows(stmt) != 5, "expected 5 rows");
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ diag("num_rows: %lld", mysql_stmt_num_rows(stmt));
+ FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "expected 1 row");
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+
+static int test_conc_fraction(MYSQL *mysql)
+{
+ MYSQL_TIME tm;
+ MYSQL_BIND bind[1];
+ char query[1024];
+ int i;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+ unsigned long frac= 0;
+
+ for (i=0; i < 10; i++, frac=frac*10+i)
+ {
+ unsigned long expected= 0;
+ sprintf(query, "SELECT '2018-11-05 22:25:59.%ld'", frac);
+
+ diag("%d: %s", i, query);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc = mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer_type= MYSQL_TYPE_DATETIME;
+ bind[0].buffer= &tm;
+ bind[0].buffer_length= sizeof(MYSQL_TIME);
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ diag("second_part: %ld", tm.second_part);
+
+ expected= i > 6 ? 123456 : frac * (unsigned int)powl(10, (6 - i));
+
+ if (tm.second_part != expected)
+ {
+ diag("Error: tm.second_part=%ld expected=%ld", tm.second_part, expected);
+ return FAIL;
+ }
+ }
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_zerofill_1byte(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ int rc;
+ MYSQL_BIND bind;
+ char buffer[3];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int zerofill)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES(1)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM t1"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+ bind.buffer_type= MYSQL_TYPE_STRING;
+ bind.buffer= buffer;
+ bind.buffer_length= 1;
+
+ rc= mysql_stmt_bind_result(stmt, &bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc != 101, "expected truncation warning");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc424(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ my_bool max_len= 1;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_table1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE test_table1 (test_int INT, b int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO test_table1 values(10,11),(11,12)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS testCursor");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE PROCEDURE testCursor()\n"
+ "BEGIN\n"
+ "DECLARE test_int INT;\n"
+ "DECLARE b INT;\n"
+ "DECLARE done INT DEFAULT FALSE;\n"
+ "DECLARE testCursor CURSOR\n"
+ "FOR\n"
+ "SELECT test_int,b FROM test_table1;\n"
+ "DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\n"
+ "OPEN testCursor;\n"
+
+ " read_loop: LOOP\n"
+ " FETCH testCursor INTO test_int, b;\n"
+ " IF done THEN\n"
+ " LEAVE read_loop;\n"
+ " END IF;\n"
+ " SELECT test_int,b;"
+ " END LOOP;\n"
+ "CLOSE testCursor;\n"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL("CALL testCursor()"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &max_len);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ do {
+ if (mysql_stmt_field_count(stmt))
+ {
+ MYSQL_RES *res= mysql_stmt_result_metadata(stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc, "Wrong return code");
+ mysql_free_result(res);
+ }
+ rc= mysql_stmt_next_result(stmt);
+
+ } while (!rc);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP PROCEDURE testCursor");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE test_table1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_maxparam(MYSQL *mysql)
+{
+ const char *query= "INSERT INTO t1 VALUES (?)";
+ int rc;
+ char *buffer;
+ int i;
+ int val= 1;
+ size_t mem= strlen(query) + 1 + 4 * 65535 + 1;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_BIND* bind;
+
+ bind = calloc(sizeof(MYSQL_BIND), 65535);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ buffer= calloc(1, mem);
+ strcpy(buffer, query);
+ for (i=0; i < 65534.; i++)
+ strcat(buffer, ",(?)");
+ rc= mysql_stmt_prepare(stmt, SL(buffer));
+ check_stmt_rc(rc, stmt);
+
+ for (i=0; i < 65534; i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_LONG;
+ bind[i].buffer= &val;
+ }
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 65535, "Expected affected_rows=65535");
+
+ strcat(buffer, ",(?)");
+ rc= mysql_stmt_prepare(stmt, SL(buffer));
+ free(buffer);
+ FAIL_IF(!rc, "Error expected");
+ FAIL_IF(mysql_stmt_errno(stmt) != ER_PS_MANY_PARAM, "Expected ER_PS_MANY_PARAM error");
+
+ mysql_stmt_close(stmt);
+ free(bind);
+ return OK;
+}
+
+static int test_mdev_21920(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_BIND bind[1];
+ int rc;
+ char buffer[128];
+
+ rc= mysql_stmt_prepare(stmt, SL("SELECT ''"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ buffer[0]= 1;
+
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= buffer;
+ bind[0].buffer_length= 127;
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(buffer[0] != 0, "Expected empty string");
+
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_returning(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ MYSQL_RES *result;
+ int rc;
+
+ diag("MDEV-23768 not fixed yet");
+ mysql_stmt_close(stmt);
+ return SKIP;
+
+ rc= mysql_query(mysql, "CREATE TEMPORARY TABLE t1 (a int not null auto_increment primary key, b json)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 (a,b) VALUES (NULL, '[incorrect json]') RETURNING a");
+ check_mysql_rc(rc, mysql);
+
+ if (!rc) diag("should have fail");
+
+ result= mysql_store_result(mysql);
+ mysql_free_result(result);
+
+ diag("Error: %s", mysql_error(mysql));
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO t1 (a,b) VALUES (NULL, '[incorrect json]') RETURNING a"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_conc504(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+ const char *sp= "CREATE PROCEDURE p1()\n" \
+ "BEGIN\n"\
+ " SELECT 1;\n"\
+ " SELECT 2;\n"\
+ " SELECT 3;\n"\
+ "END";
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, sp);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("CALL p1()"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_store_result(stmt);
+ FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "Expected 1 row");
+
+ mysql_stmt_next_result(stmt);
+ mysql_stmt_store_result(stmt);
+ FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "Expected 1 row");
+
+ mysql_stmt_next_result(stmt);
+ mysql_stmt_store_result(stmt);
+ FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "Expected 1 row");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE p1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_conc512(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind;
+ float f;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+
+ rc= mysql_real_query(mysql, SL("CREATE TABLE t1 (a int)"));
+
+ rc= mysql_real_query(mysql, SL("INSERT INTO t1 VALUES (1073741825)"));
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM t1"));
+ check_stmt_rc(rc, stmt);
+
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+ bind.buffer= &f;
+ bind.buffer_type= MYSQL_TYPE_FLOAT;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, &bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(rc != 101, "Truncation expected");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc525(MYSQL *mysql)
+{
+ FILE *fp;
+ MYSQL_STMT *stmt;
+ int rc;
+
+ rc= mysql_query(mysql, "create temporary table t1 (a blob)");
+ check_mysql_rc(rc, mysql);
+
+ /* create a dummy import file */
+ if (!(fp= fopen("./test.csv", "w")))
+ {
+ diag("couldn't create file './test.csv'");
+ return FAIL;
+ }
+ fprintf(fp, "1\n2\n");
+ fclose(fp);
+
+ /* Test: prepare and execute
+ should fail due to non existing file */
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("LOAD DATA LOCAL INFILE './test.notexist' INTO table t1"));
+
+ if (rc && mysql_stmt_errno(stmt) == ER_UNSUPPORTED_PS)
+ {
+ diag("Server doesn't support LOAD LOCAL INFILE in binary protocol.");
+ mysql_stmt_close(stmt);
+ return SKIP;
+ }
+
+ rc= mysql_stmt_execute(stmt);
+ FAIL_IF(!rc, "Error expected (file does not exist)");
+
+ mysql_stmt_close(stmt);
+
+ /* Test: prepare and execute
+ 2 rows should be inserted */
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("LOAD DATA LOCAL INFILE './test.csv' INTO table t1"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 2, "Expected 2 inserted rows");
+
+ mysql_stmt_close(stmt);
+ stmt= mysql_stmt_init(mysql);
+
+ /* Test: execute_direct
+ 2 rows should be inserted */
+ rc= mariadb_stmt_execute_direct(stmt, SL("LOAD DATA LOCAL INFILE './test.csv' INTO table t1"));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_affected_rows(stmt) != 2, "Expected 2 inserted rows");
+
+ /* Cleanup */
+ mysql_stmt_close(stmt);
+ unlink("./test.csv");
+
+ return OK;
+}
+
+static int test_conc566(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt = mysql_stmt_init(mysql);
+ unsigned long cursor = CURSOR_TYPE_READ_ONLY;
+ const char* query= "call sp()";
+
+ SKIP_SKYSQL;
+
+ rc= mysql_query(mysql,"drop procedure if exists sp");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,"create procedure sp() select 1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt,query,-1);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql,"drop procedure sp");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+#define MDEV19838_MAX_PARAM_COUNT 32
+#define MDEV19838_FIELDS_COUNT 17
+
+static int test_mdev19838(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_BIND bind[MDEV19838_MAX_PARAM_COUNT];
+ unsigned int i, paramCount = 1;
+ char charvalue[] = "012345678901234567890123456789012345";
+ MYSQL_STMT *stmt;
+
+ SKIP_MAXSCALE;
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+
+ rc = mysql_query(mysql, "CREATE temporary TABLE mdev19838("
+ "f1 char(36),"
+ "f2 char(36),"
+ "f3 char(36),"
+ "f4 char(36),"
+ "f5 char(36),"
+ "f6 char(36),"
+ "f7 char(36),"
+ "f8 char(36),"
+ "f9 char(36),"
+ "f10 char(36),"
+ "f11 char(36),"
+ "f12 char(36),"
+ "f13 char(36),"
+ "f14 char(36),"
+ "f15 char(36),"
+ "f16 char(36),"
+ "f17 char(36)"
+ ")");
+ check_mysql_rc(rc, mysql);
+
+ stmt = mysql_stmt_init(mysql);
+
+ memset(bind, 0, sizeof(bind));
+
+ for (i = 0; i < MDEV19838_MAX_PARAM_COUNT; ++i)
+ {
+ bind[i].buffer = charvalue;
+ bind[i].buffer_type = MYSQL_TYPE_STRING;
+ bind[i].buffer_length = sizeof charvalue;
+ bind[i].length = &bind[i].length_value;
+ bind[i].length_value = bind[i].buffer_length - 1;
+ }
+
+ for (paramCount = 1; paramCount < MDEV19838_FIELDS_COUNT; ++paramCount)
+ {
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &paramCount);
+
+ rc = mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
+ "(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17)"
+ " VALUES "
+ "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", -1);
+
+ /* Expecting an error */
+ FAIL_UNLESS(rc != 0, "rc!=0");
+
+ mysql_stmt_close(stmt);
+ stmt = mysql_stmt_init(mysql);
+ }
+
+ paramCount = 0;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &paramCount);
+ rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838(f1)"
+ " VALUES (?)", -1);
+ /* Expecting an error */
+ FAIL_UNLESS(rc != 0, "rc!=0");
+ mysql_stmt_close(stmt);
+
+ stmt = mysql_stmt_init(mysql);
+ /* Correct number of parameters */
+ paramCount = MDEV19838_FIELDS_COUNT;
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &paramCount);
+ mysql_stmt_bind_param(stmt, bind);
+
+ rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
+ "(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17)"
+ " VALUES "
+ "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", -1);
+ check_stmt_rc(rc, stmt);
+
+ /* MYSQL_TYPE_TINY = 1. This parameter byte can be read as "parameters send" flag byte.
+ Checking that wrong packet is still detected */
+ bind[0].buffer_type = MYSQL_TYPE_TINY;
+ bind[0].length_value = 1;
+ bind[0].buffer_length = 1;
+
+ for (paramCount = 8; paramCount > 0; --paramCount)
+ {
+ mysql_stmt_close(stmt);
+ stmt = mysql_stmt_init(mysql);
+
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &paramCount);
+
+ rc = mysql_stmt_bind_param(stmt, bind);
+
+ rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
+ "(f1, f2, f3, f4, f5, f6, f7, f8, f9)"
+ " VALUES "
+ "(?, ?, ?, ?, ?, ?, ?, ?, ?)", -1);
+
+ /* Expecting an error */
+ FAIL_UNLESS(rc != 0, "rc");
+ }
+
+ /* Test of query w/out parameters, with parameter sent and not sent */
+ for (paramCount = MDEV19838_MAX_PARAM_COUNT; paramCount != (unsigned int)-1; --paramCount)
+ {
+ mysql_stmt_close(stmt);
+ stmt = mysql_stmt_init(mysql);
+
+ mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &paramCount);
+
+ if (paramCount > 0)
+ {
+ rc = mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ }
+
+ rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
+ "(f1)"
+ " VALUES "
+ "(0x1111111111111111)", -1);
+
+ /*
+ We allow junk at the end of the packet in case of
+ no parameters. So it will succeed.
+ */
+ FAIL_UNLESS(rc == 0, "");
+ }
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+my_bool conc623_param_callback(void *data __attribute((unused)),
+ MYSQL_BIND *bind __attribute((unused)),
+ unsigned int row_nr __attribute((unused)))
+{
+ return 1;
+}
+
+static int test_conc623(MYSQL *mysql)
+{
+ int rc;
+ unsigned int paramcount= 1;
+ unsigned int array_size= 2;
+ MYSQL_BIND bind;
+
+ MYSQL_STMT *stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_query(mysql, "CREATE TEMPORARY TABLE t1 (a int)");
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CB_USER_DATA, mysql);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &paramcount);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CB_PARAM, conc623_param_callback);
+ check_stmt_rc(rc, stmt);
+
+ bind.buffer_type= MYSQL_TYPE_LONG;
+ rc= mysql_stmt_bind_param(stmt, &bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_prepare(stmt, SL("INSERT INTO t1 VALUES (?)"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ if (!rc)
+ {
+ diag("Error expected from callback function");
+ mysql_stmt_close(stmt);
+ return FAIL;
+ }
+
+ diag("Error (expected) %s", mysql_stmt_error(stmt));
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+static int test_conc627(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+
+ SKIP_MYSQL(mysql);
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL("show grants for mysqltest_8"));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ mysql_stmt_store_result(stmt);
+ FAIL_IF(!mysql_stmt_errno(stmt), "Expected error");
+ FAIL_IF(strcmp(mysql_error(mysql), mysql_stmt_error(stmt)), "Error messages differ");
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_conc633(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL *my= NULL;
+ int ret= FAIL;
+ int rc;
+
+ SKIP_MYSQL(mysql);
+
+ stmt= mysql_stmt_init(mysql);
+
+ if (!mariadb_stmt_execute_direct(stmt, SL("SÄLECT 1")))
+ {
+ diag("Syntax error expected");
+ goto end;
+ }
+
+ if (mysql_errno(mysql) != mysql_stmt_errno(stmt))
+ {
+ diag("Different error codes. mysql_errno= %d, mysql_stmt_errno=%d",
+ mysql_errno(mysql), mysql_stmt_errno(stmt));
+ goto end;
+ }
+
+ if ((long)stmt->stmt_id != -1)
+ {
+ diag("Error: expected stmt_id=-1");
+ goto end;
+ }
+
+ if (!(my= test_connect(NULL)))
+ {
+ diag("Can establish connection (%s)", mysql_error(my));
+ goto end;
+ }
+
+ rc= mysql_query(my, "CREATE OR REPLACE TABLE conc633 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SET @@lock_wait_timeout=3");
+
+ rc= mysql_query(my, "LOCK TABLES conc633 WRITE");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SET @@lock_wait_timeout=3");
+ check_mysql_rc(rc, mysql);
+
+ if (!mariadb_stmt_execute_direct(stmt, SL("INSERT INTO conc633 VALUES (1)")))
+ {
+ diag("lock wait timeout error expected");
+ goto end;
+ }
+
+ if (stmt->state != MYSQL_STMT_PREPARED)
+ {
+ diag("Error: stmt hasn't prepared status");
+ goto end;
+ }
+
+ if ((long)stmt->stmt_id == -1)
+ {
+ diag("Error: no stmt_id assigned");
+ goto end;
+ }
+
+ rc= mysql_query(my, "UNLOCK TABLES");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(my, "DROP TABLE conc633");
+ check_mysql_rc(rc, mysql);
+
+ ret= OK;
+
+end:
+ if (my)
+ mysql_close(my);
+ mysql_stmt_close(stmt);
+ return ret;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc633", test_conc633, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc623", test_conc623, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc627", test_conc627, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_mdev19838", test_mdev19838, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc525", test_conc525, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc566", test_conc566, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc512", test_conc512, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc504", test_conc504, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_returning", test_returning, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_mdev_21920", test_mdev_21920, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_maxparam", test_maxparam, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc424", test_conc424, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc344", test_conc344, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc334", test_conc334, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_compress", test_compress, TEST_CONNECTION_NEW, CLIENT_COMPRESS, NULL, NULL},
+ {"test_zerofill_1byte", test_zerofill_1byte, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_codbc138", test_codbc138, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc208", test_conc208, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_mdev14165", test_mdev14165, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc208", test_conc208, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc217", test_conc217, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc205", test_conc205, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc198", test_conc198, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc182", test_conc182, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc181", test_conc181, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc179", test_conc179, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc177", test_conc177, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc167", test_conc167, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc168", test_conc168, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc155", test_conc155, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_conc154", test_conc154, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_conc141", test_conc141, TEST_CONNECTION_NEW, 0, NULL , NULL},
+ {"test_conc67", test_conc67, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_conc_5", test_conc_5, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug1115", test_bug1115, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug1180", test_bug1180, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug1644", test_bug1644, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11037", test_bug11037, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11183", test_bug11183, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug12744", test_bug12744, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug1500", test_bug1500, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug15510", test_bug15510, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug15518", test_bug15518, TEST_CONNECTION_NEW | TEST_CONNECTION_DONT_CLOSE, CLIENT_MULTI_STATEMENTS, NULL , NULL},
+ {"test_bug15613", test_bug15613, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug16144", test_bug16144, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug1664", test_bug1664, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug1946", test_bug1946, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug2247", test_bug2247, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug2248", test_bug2248, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug20152", test_bug20152, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug23383", test_bug23383, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug27592", test_bug27592, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug28934", test_bug28934, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug36004", test_bug36004, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug3035", test_bug3035, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug3117", test_bug3117, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug3796", test_bug3796, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug4026", test_bug4026, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug4030", test_bug4030, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug4079", test_bug4079, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug4172", test_bug4172, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug4231", test_bug4231, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug4236", test_bug4236, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug5126", test_bug5126, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug5194", test_bug5194, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug5315", test_bug5315, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug5399", test_bug5399, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug6046", test_bug6046, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug6049", test_bug6049, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug6058", test_bug6058, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug6059", test_bug6059, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug6096", test_bug6096, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug7990", test_bug7990, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug8330", test_bug8330, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug8722", test_bug8722, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_ps_conj_select", test_ps_conj_select, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_ps_null_param", test_ps_null_param, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_ps_query_cache", test_ps_query_cache, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_ushort_bug", test_ushort_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_field_misc", test_field_misc, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_mem_overun", test_mem_overun, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_decimal_bug", test_decimal_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_explain_bug", test_explain_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_sshort_bug", test_sshort_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_stiny_bug", test_stiny_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug53311", test_bug53311, TEST_CONNECTION_NEW, 0, NULL , NULL},
+ {"test_conc_fraction", test_conc_fraction, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_str_to_int", test_str_to_int, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/ps_new.c b/libmariadb/unittest/libmariadb/ps_new.c
new file mode 100644
index 00000000..ea228f1c
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/ps_new.c
@@ -0,0 +1,526 @@
+/************************************************************************************
+ Copyright (C) 2012 Monty Program AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+ *************************************************************************************/
+
+#include "my_test.h"
+
+/* Utility function to verify the field members */
+
+
+static int test_multi_result(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND ps_params[3]; /* input parameter buffers */
+ MYSQL_BIND rs_bind[3];
+ int int_data[3]; /* input/output values */
+ my_bool is_null[3]; /* output value nullability */
+ int rc, i;
+
+ //https://jira.mariadb.org/browse/XPT-268
+ SKIP_XPAND;
+
+ /* set up stored procedure */
+ rc = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ rc = mysql_query(mysql,
+ "CREATE PROCEDURE p1("
+ " IN p_in INT, "
+ " OUT p_out INT, "
+ " INOUT p_inout INT) "
+ "BEGIN "
+ " SELECT p_in, p_out, p_inout; "
+ " SET p_in = 100, p_out = 200, p_inout = 300; "
+ " SELECT p_in, p_out, p_inout; "
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ /* initialize and prepare CALL statement with parameter placeholders */
+ stmt = mysql_stmt_init(mysql);
+ if (!stmt)
+ {
+ diag("Could not initialize statement");
+ exit(1);
+ }
+ rc = mysql_stmt_prepare(stmt, "CALL p1(?, ?, ?)", 16);
+ check_stmt_rc(rc, stmt);
+
+ /* initialize parameters: p_in, p_out, p_inout (all INT) */
+ memset(ps_params, 0, sizeof (ps_params));
+
+ ps_params[0].buffer_type = MYSQL_TYPE_LONG;
+ ps_params[0].buffer = (char *) &int_data[0];
+ ps_params[0].length = 0;
+ ps_params[0].is_null = 0;
+
+ ps_params[1].buffer_type = MYSQL_TYPE_LONG;
+ ps_params[1].buffer = (char *) &int_data[1];
+ ps_params[1].length = 0;
+ ps_params[1].is_null = 0;
+
+ ps_params[2].buffer_type = MYSQL_TYPE_LONG;
+ ps_params[2].buffer = (char *) &int_data[2];
+ ps_params[2].length = 0;
+ ps_params[2].is_null = 0;
+
+ /* bind parameters */
+ rc = mysql_stmt_bind_param(stmt, ps_params);
+ check_stmt_rc(rc, stmt);
+
+ /* assign values to parameters and execute statement */
+ int_data[0]= 10; /* p_in */
+ int_data[1]= 20; /* p_out */
+ int_data[2]= 30; /* p_inout */
+
+ rc = mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_field_count(stmt) != 3, "expected 3 fields");
+
+ memset(rs_bind, 0, sizeof (MYSQL_BIND) * 3);
+ for (i=0; i < 3; i++)
+ {
+ rs_bind[i].buffer = (char *) &(int_data[i]);
+ rs_bind[i].buffer_length = sizeof (int_data);
+ rs_bind[i].buffer_type = MYSQL_TYPE_LONG;
+ rs_bind[i].is_null = &is_null[i];
+ }
+ rc= mysql_stmt_bind_result(stmt, rs_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(int_data[0] != 10 || int_data[1] != 20 || int_data[2] != 30,
+ "expected 10 20 30");
+ rc= mysql_stmt_next_result(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_result(stmt, rs_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(mysql_stmt_field_count(stmt) != 3, "expected 3 fields");
+ FAIL_IF(int_data[0] != 100 || int_data[1] != 200 || int_data[2] != 300,
+ "expected 100 200 300");
+
+ FAIL_IF(mysql_stmt_next_result(stmt) != 0, "expected more results");
+ rc= mysql_stmt_bind_result(stmt, rs_bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_IF(mysql_stmt_field_count(stmt) != 2, "expected 2 fields");
+ FAIL_IF(int_data[0] != 200 || int_data[1] != 300,
+ "expected 200 300");
+
+ FAIL_IF(mysql_stmt_next_result(stmt) != 0, "expected more results");
+ FAIL_IF(mysql_stmt_field_count(stmt) != 0, "expected 0 fields");
+
+ rc= mysql_stmt_close(stmt);
+ rc = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+int test_sp_params(MYSQL *mysql)
+{
+ int i, rc;
+ MYSQL_STMT *stmt;
+ int a[] = {10,20,30};
+ MYSQL_BIND bind[3];
+ const char *stmtstr= "CALL P1(?,?,?)";
+ char res[3][20];
+
+ //https://jira.mariadb.org/browse/XPT-268
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19), IN p_in INT, INOUT p_inout INT)"
+ "BEGIN "
+ " SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
+ " SELECT p_inout, p_in, substring(p_out, 9);"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt,SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 3, "expected param_count=3");
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+ for (i=0; i < 3; i++)
+ {
+ bind[i].buffer= &a[i];
+ bind[i].buffer_type= MYSQL_TYPE_LONG;
+ }
+ bind[0].buffer_type= MYSQL_TYPE_NULL;
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(res, 0, 60);
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+ for (i=0; i < 3; i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_STRING;
+ bind[i].buffer_length= 20;
+ bind[i].buffer= res[i];
+ }
+
+ do {
+ if (mysql->server_status & SERVER_PS_OUT_PARAMS)
+ {
+ diag("out param result set");
+ FAIL_IF(mysql_stmt_field_count(stmt) != 2, "expected 2 columns");
+ FAIL_IF(strcmp(stmt->fields[0].org_name, "p_out") != 0, "wrong field name");
+ FAIL_IF(strcmp(stmt->fields[1].org_name, "p_inout") != 0, "wrong field name");
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(strcmp(res[0],"This is OUT param") != 0, "comparison failed");
+ FAIL_IF(strcmp(res[1],"200") != 0, "comparison failed");
+ }
+ else
+ if (mysql_stmt_field_count(stmt))
+ {
+ diag("sp result set");
+ FAIL_IF(mysql_stmt_field_count(stmt) != 3, "expected 3 columns");
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_IF(strcmp(res[0],"200") != 0, "comparison failed");
+ FAIL_IF(strcmp(res[1],"300") != 0, "comparison failed");
+ FAIL_IF(strcmp(res[2],"OUT param") != 0, "comparison failed");
+
+ }
+ } while (mysql_stmt_next_result(stmt) == 0);
+
+ rc= mysql_stmt_close(stmt);
+ return OK;
+}
+
+int test_sp_reset(MYSQL *mysql)
+{
+ int i, rc;
+ MYSQL_STMT *stmt;
+ int a[] = {10,20,30};
+ MYSQL_BIND bind[3];
+ const char *stmtstr= "CALL P1(?,?,?)";
+
+ //https://jira.mariadb.org/browse/XPT-268
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19), IN p_in INT, INOUT p_inout INT)"
+ "BEGIN "
+ " SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
+ " SELECT p_inout, p_in, substring(p_out, 9);"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt,SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ FAIL_IF(mysql_stmt_param_count(stmt) != 3, "expected param_count=3");
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 3);
+ for (i=0; i < 3; i++)
+ {
+ bind[i].buffer= &a[i];
+ bind[i].buffer_type= MYSQL_TYPE_LONG;
+ }
+ bind[0].buffer_type= MYSQL_TYPE_NULL;
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /*connection shouldn't be blocked now */
+
+ rc= mysql_query(mysql, "DROP PROCEDURE p1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_close(stmt);
+ return OK;
+}
+
+int test_sp_reset1(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+
+ char tmp[20];
+ const char *stmtstr= "CALL P1(?)";
+
+ // https://jira.mariadb.org/browse/XPT-268
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19))"
+ "BEGIN "
+ " SET p_out = 'foo';"
+ " SELECT 'foo' FROM DUAL;"
+ " SELECT 'bar' FROM DUAL;"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt,SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ memset(tmp, 0, sizeof(tmp));
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer= tmp;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer_length= 4;
+
+ mysql_stmt_bind_param(stmt, bind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_next_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* mysql_stmt_reset should set statement in prepared state.
+ * this means: all subsequent result sets should be flushed.
+ * Let's try!
+ */
+ rc= mysql_stmt_reset(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE p1");
+ check_mysql_rc(rc, mysql);
+
+ mysql_stmt_close(stmt);
+ return OK;
+}
+
+int test_sp_reset2(MYSQL *mysql)
+{
+ int rc, i;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[4];
+ long l[4];
+ const char *stmtstr= "CALL P1()";
+
+ memset(l, 0, sizeof(l));
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE PROCEDURE p1()"
+ "BEGIN "
+ " SET @a:=1;"
+ " INSERT INTO t1 VALUES(1);"
+ " SELECT 1 FROM DUAL;"
+ " SELECT 2,3 FROM DUAL;"
+ " INSERT INTO t1 VALUES(2);"
+ " SELECT 3,4,5 FROM DUAL;"
+ " SELECT 4,5,6,7 FROM DUAL;"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt,SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(bind, 0, sizeof(MYSQL_BIND) * 4);
+ for (i=0; i < 4; i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_LONG;
+ bind[i].buffer= &l[i];
+ }
+
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ while (rc != MYSQL_NO_DATA)
+ {
+ rc= mysql_stmt_fetch(stmt);
+ diag("l=%ld", l[0]);
+ }
+
+ rc= mysql_stmt_next_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* now rebind since we expect 2 columns */
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ while (rc != MYSQL_NO_DATA)
+ {
+ rc= mysql_stmt_fetch(stmt);
+ diag("l=%ld l=%ld", l[0], l[1]);
+ }
+
+
+ rc= mysql_stmt_next_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ /* now rebind since we expect 2 columns */
+ rc= mysql_stmt_bind_result(stmt, bind);
+ check_stmt_rc(rc, stmt);
+
+ while (rc != MYSQL_NO_DATA)
+ {
+ rc= mysql_stmt_fetch(stmt);
+ diag("l=%ld l=%ld l=%ld", l[0], l[1], l[2]);
+ }
+
+ rc= mysql_stmt_close(stmt);
+
+
+ rc= mysql_query(mysql, "DROP PROCEDURE p1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+int test_query(MYSQL *mysql)
+{
+ int rc;
+ int i;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+
+ char tmp[20];
+ const char *stmtstr= "CALL P1(?)";
+
+ // https://jira.mariadb.org/browse/XPT-268
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19))"
+ "BEGIN "
+ " SET p_out = 'foo';"
+ " SELECT 1 FROM DUAL;"
+ "END");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_stmt_prepare(stmt,SL(stmtstr));
+ check_stmt_rc(rc, stmt);
+
+ for (i=0; i < 1000; i++)
+ {
+ int status;
+ memset(tmp, 0, sizeof(tmp));
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ bind[0].buffer= tmp;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer_length= 4;
+
+ mysql_stmt_bind_param(stmt, bind);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ do {
+ if (stmt->field_count)
+ {
+ mysql_stmt_bind_result(stmt, bind);
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+ while(mysql_stmt_fetch(stmt) == 0);
+
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+ }
+ status= mysql_stmt_next_result(stmt);
+ if (status == 1)
+ check_stmt_rc(status, stmt);
+ } while (status == 0);
+
+ rc= mysql_stmt_reset(stmt);
+ if (rc)
+ diag("reset failed after %d iterations", i);
+ check_stmt_rc(rc, stmt);
+ }
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+struct my_tests_st my_tests[] = {
+ {"test_query", test_query, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_RESULTS , NULL , NULL},
+ {"test_sp_params", test_sp_params, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
+ {"test_sp_reset", test_sp_reset, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
+ {"test_sp_reset1", test_sp_reset1, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
+ {"test_sp_reset2", test_sp_reset2, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
+ {"test_multi_result", test_multi_result, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/result.c b/libmariadb/unittest/libmariadb/result.c
new file mode 100644
index 00000000..c4a56438
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/result.c
@@ -0,0 +1,1105 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ Some basic tests of the client API.
+*/
+
+#include "my_test.h"
+
+static int client_store_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ int rc, rowcount= 0;
+
+ rc= mysql_query(mysql, "SELECT 'foo' FROM DUAL UNION SELECT 'bar' FROM DUAL");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ /* since we use store result, we should be able execute other api calls */
+ rc= mysql_ping(mysql);
+ FAIL_IF(rc, "mysql_ping failed");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+
+ FAIL_IF(rowcount != 2, "rowcount != 2");
+
+ mysql_free_result(result);
+
+ return OK;
+}
+
+static int client_use_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ int rc, rowcount= 0;
+
+ rc= mysql_query(mysql, "SELECT 'foo' FROM DUAL UNION SELECT 'bar' FROM DUAL");
+ check_mysql_rc(rc, mysql);
+
+ /* get the result */
+ result= mysql_use_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ /* since we use use result, we shouldn't be able execute other api calls */
+ rc= mysql_ping(mysql);
+ FAIL_IF(!rc, "Error expected");
+
+ while (mysql_fetch_row(result))
+ rowcount++;
+
+ FAIL_IF(rowcount != 2, "rowcount != 2");
+
+ mysql_free_result(result);
+
+ return OK;
+}
+
+static int test_free_result(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ char c2[5];
+ ulong bl1, l2;
+ int rc, c1, bc1;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "drop table if exists test_free_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table test_free_result("
+ "c1 int primary key auto_increment)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into test_free_result values(), (), ()");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "select * from test_free_result");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&bc1;
+ my_bind[0].length= &bl1;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ c2[0]= '\0'; l2= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)c2;
+ my_bind[0].buffer_length= 7;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l2;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(strncmp(c2, "1", 1) == 0, "c2 != '1'");
+ FAIL_UNLESS(l2 == 1, "l2 != 1");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ c1= 0, l2= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&c1;
+ my_bind[0].buffer_length= 0;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l2;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(c1 == 2, "c1 != 2");
+ FAIL_UNLESS(l2 == 4, "l2 != 4");
+
+ rc= mysql_query(mysql, "drop table test_free_result");
+ FAIL_IF(!rc, "Error commands out of sync expected");
+
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "drop table test_free_result");
+ check_mysql_rc(rc, mysql); /* should be successful */
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+
+/* Test mysql_stmt_store_result() */
+
+static int test_free_store_result(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ char c2[5];
+ ulong bl1, l2;
+ int rc, c1, bc1;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "drop table if exists test_free_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "insert into test_free_result values(), (), ()");
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "select * from test_free_result");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&bc1;
+ my_bind[0].buffer_length= 0;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &bl1;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ c2[0]= '\0'; l2= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (void *)c2;
+ my_bind[0].buffer_length= 7;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l2;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(strncmp(c2, "1", 1) == 0, "c2 != '1'");
+ FAIL_UNLESS(l2 == 1, "l2 != 1");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ c1= 0, l2= 0;
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *)&c1;
+ my_bind[0].buffer_length= 0;
+ my_bind[0].is_null= 0;
+ my_bind[0].length= &l2;
+
+ rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(c1 == 2, "c1 != 2");
+ FAIL_UNLESS(l2 == 4, "l2 != 4");
+
+ rc= mysql_stmt_free_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_query(mysql, "drop table test_free_result");
+ check_mysql_rc(rc, mysql);
+
+ mysql_stmt_close(stmt);
+
+ return OK;
+}
+
+static int test_store_result(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int32 nData;
+ char szData[100];
+ MYSQL_BIND my_bind[2];
+ ulong length, length1;
+ my_bool is_null[2];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ /* fetch */
+ memset(my_bind, '\0', sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *) &nData; /* integer data */
+ my_bind[0].length= &length;
+ my_bind[0].is_null= &is_null[0];
+
+ length= 0;
+ my_bind[1].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[1].buffer= szData; /* string data */
+ my_bind[1].buffer_length= sizeof(szData);
+ my_bind[1].length= &length1;
+ my_bind[1].is_null= &is_null[1];
+ length1= 0;
+
+ strcpy(query, "SELECT * FROM test_store_result");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 10, "nData != 10");
+ FAIL_UNLESS(strcmp(szData, "venu") == 0, "szData != 'Venu'");
+ FAIL_UNLESS(length1 == 4, "length1 != 4");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 20, "nData != 20");
+ FAIL_UNLESS(strcmp(szData, "mysql") == 0, "szDaza != 'mysql'");
+ FAIL_UNLESS(length1 == 5, "length1 != 5");
+
+ length= 99;
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(is_null[0], "isnull set");
+ FAIL_UNLESS(strcmp(szData, "monty") == 0, "szData != 'monty'");
+ FAIL_UNLESS(length1 == 5, "length1 != 5");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 10, "nData != 10");
+ FAIL_UNLESS(strcmp(szData, "venu") == 0, "szData != 'Venu'");
+ FAIL_UNLESS(length1 == 4, "length1 != 4");
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 20, "nData != 20");
+ FAIL_UNLESS(strcmp(szData, "mysql") == 0, "szDaza != 'mysql'");
+ FAIL_UNLESS(length1 == 5, "length1 != 5");
+
+ length= 99;
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(is_null[0], "isnull set");
+ FAIL_UNLESS(strcmp(szData, "monty") == 0, "szData != 'monty'");
+ FAIL_UNLESS(length1 == 5, "length1 != 5");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/* Test simple bind store result */
+
+static int test_store_result1(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ strcpy(query, "SELECT * FROM test_store_result");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 3, "rowcount != 3");
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= 0;
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rc++;
+ FAIL_UNLESS(rc == 3, "rowcount != 3");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+/* Another test for bind and store result */
+
+static int test_store_result2(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ int nData;
+ ulong length;
+ MYSQL_BIND my_bind[1];
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_commit(mysql);
+ check_mysql_rc(rc, mysql);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+
+ my_bind[0].buffer_type= MYSQL_TYPE_LONG;
+ my_bind[0].buffer= (void *) &nData; /* integer data */
+ my_bind[0].length= &length;
+ my_bind[0].is_null= 0;
+
+ strcpy((char *)query , "SELECT col1 FROM test_store_result where col1= ?");
+ stmt= mysql_stmt_init(mysql);
+ FAIL_IF(!stmt, mysql_error(mysql));
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ nData= 10; length= 0;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ nData= 0;
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 10, "nData != 10");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+
+ nData= 20;
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ nData= 0;
+ rc= mysql_stmt_store_result(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+
+ FAIL_UNLESS(nData == 20, "nData != 20");
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug11718(MYSQL *mysql)
+{
+ MYSQL_RES *res;
+ int rc;
+ const char *query= "select str_to_date(concat(f3),'%Y%m%d') from t1,t2 "
+ "where f1=f2 order by f1";
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (f1 int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t2 (f2 int, f3 numeric(8))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values (1), (2)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t2 values (1,20050101), (2,20050202)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+ res = mysql_store_result(mysql);
+
+ FAIL_UNLESS(res->fields[0].type == MYSQL_TYPE_DATE, "type != MYSQL_TYPE_DATE");
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "drop table t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug19671(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ int rc;
+
+ mysql_query(mysql, "set sql_mode=''");
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "drop view if exists v1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1(f1 int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create view v1 as select va.* from t1 va");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_list_fields(mysql, "v1", NULL);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 0, "");
+
+ if (verify_prepare_field(result, 0, "f1", "f1", MYSQL_TYPE_LONG,
+ "v1", "v1", schema, 11, "0")) {
+ mysql_free_result(result);
+ diag("verify_prepare_field failed");
+ return FAIL;
+ }
+
+ mysql_free_result(result);
+ check_mysql_rc(mysql_query(mysql, "drop view v1"), mysql);
+ check_mysql_rc(mysql_query(mysql, "drop table t1"), mysql);
+ return OK;
+}
+
+/*
+ Bug#21726: Incorrect result with multiple invocations of
+ LAST_INSERT_ID
+
+ Test that client gets updated value of insert_id on UPDATE that uses
+ LAST_INSERT_ID(expr).
+ select_query added to test for bug
+ #26921 Problem in mysql_insert_id() Embedded C API function
+*/
+static int test_bug21726(MYSQL *mysql)
+{
+ const char *create_table[]=
+ {
+ "DROP TABLE IF EXISTS t1",
+ "CREATE TABLE t1 (i INT)",
+ "INSERT INTO t1 VALUES (1)",
+ };
+ const char *update_query= "UPDATE t1 SET i= LAST_INSERT_ID(i + 1)";
+ int rc;
+ unsigned long long insert_id;
+ const char *select_query= "SELECT * FROM t1";
+ MYSQL_RES *result;
+
+ rc= mysql_query(mysql, create_table[0]);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, create_table[1]);
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, create_table[2]);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, update_query);
+ check_mysql_rc(rc, mysql);
+ insert_id= mysql_insert_id(mysql);
+ FAIL_UNLESS(insert_id == 2, "insert_id != 2");
+
+ rc= mysql_query(mysql, update_query);
+ check_mysql_rc(rc, mysql);
+ insert_id= mysql_insert_id(mysql);
+ FAIL_UNLESS(insert_id == 3, "insert_id != 3");
+
+ rc= mysql_query(mysql, select_query);
+ check_mysql_rc(rc, mysql);
+ insert_id= mysql_insert_id(mysql);
+ FAIL_UNLESS(insert_id == 3, "insert_id != 3");
+ result= mysql_store_result(mysql);
+ mysql_free_result(result);
+
+ return OK;
+}
+
+/* Bug#6761 - mysql_list_fields doesn't work */
+
+static int test_bug6761(MYSQL *mysql)
+{
+ const char *stmt_text;
+ MYSQL_RES *res;
+ int rc;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ check_mysql_rc(rc, mysql);
+
+ stmt_text= "CREATE TABLE t1 (a int, b char(255), c decimal)";
+ rc= mysql_real_query(mysql, stmt_text, (unsigned long)strlen(stmt_text));
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_list_fields(mysql, "t1", "%");
+ FAIL_UNLESS(res && mysql_num_fields(res) == 3, "num_fields != 3");
+ mysql_free_result(res);
+
+ stmt_text= "DROP TABLE t1";
+ rc= mysql_real_query(mysql, stmt_text, (unsigned long)strlen(stmt_text));
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test field flags (verify .NET provider) */
+
+static int test_field_flags(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ // https://jira.mariadb.org/browse/XPT-287
+ SKIP_XPAND;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_flags");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_field_flags(id int NOT NULL AUTO_INCREMENT PRIMARY KEY, \
+ id1 int NOT NULL, \
+ id2 int UNIQUE, \
+ id3 int, \
+ id4 int NOT NULL, \
+ id5 int, \
+ KEY(id3, id4))");
+ check_mysql_rc(rc, mysql);
+
+ /* with table name included with TRUE column name */
+ rc= mysql_query(mysql, "SELECT * FROM test_field_flags");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_use_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ mysql_field_seek(result, 0);
+
+ field= mysql_fetch_field(result);
+ FAIL_UNLESS(field->flags & NOT_NULL_FLAG &&
+ field->flags & PRI_KEY_FLAG &&
+ field->flags & AUTO_INCREMENT_FLAG, "Wrong flags for field 0");
+
+ field= mysql_fetch_field(result);
+ FAIL_UNLESS(field->flags & NOT_NULL_FLAG, "Wrong flags for field 1");
+
+ field= mysql_fetch_field(result);
+ FAIL_UNLESS(field->flags & UNIQUE_KEY_FLAG, "Wrong flags for field 2");
+
+ field= mysql_fetch_field(result);
+ FAIL_UNLESS(field->flags & MULTIPLE_KEY_FLAG, "Wrong flags for field 3");
+
+ field= mysql_fetch_field(result);
+ FAIL_UNLESS(field->flags & NOT_NULL_FLAG, "Wrong flags for field 4");
+
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_flags");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test real and alias names */
+
+static int test_field_names(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names2");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_field_names1(id int, name varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_field_names2(id int, name varchar(50))");
+ check_mysql_rc(rc, mysql);
+
+ /* with table name included with TRUE column name */
+ rc= mysql_query(mysql, "SELECT id as 'id-alias' FROM test_field_names1");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_use_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 0, "rowcount != 0");
+ mysql_free_result(result);
+
+ /* with table name included with TRUE column name */
+ rc= mysql_query(mysql, "SELECT t1.id as 'id-alias', test_field_names2.name FROM test_field_names1 t1, test_field_names2");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_use_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 0, "rowcount != 0");
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names2");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test FUNCTION field info / DATE_FORMAT() table_name . */
+
+static int test_func_fields(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+
+ rc= mysql_autocommit(mysql, TRUE);
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_dateformat");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE test_dateformat(id int, \
+ ts timestamp)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO test_dateformat(id) values(10)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT ts FROM test_dateformat");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ field= mysql_fetch_field(result);
+ FAIL_IF(!field, "Invalid field");
+ FAIL_UNLESS(strcmp(field->table, "test_dateformat") == 0, "field->table != 'test_dateformat'");
+
+ field= mysql_fetch_field(result);
+ FAIL_IF(field, "no more fields expected");
+
+ mysql_free_result(result);
+
+ /* DATE_FORMAT */
+ rc= mysql_query(mysql, "SELECT DATE_FORMAT(ts, '%Y') AS 'venu' FROM test_dateformat");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ field= mysql_fetch_field(result);
+ FAIL_IF(!field, "Invalid field");
+ FAIL_UNLESS(field->table[0] == '\0', "field->table != ''");
+
+ field= mysql_fetch_field(result);
+ FAIL_IF(field, "no more fields expected");
+
+ mysql_free_result(result);
+
+ /* FIELD ALIAS TEST */
+ rc= mysql_query(mysql, "SELECT DATE_FORMAT(ts, '%Y') AS 'YEAR' FROM test_dateformat");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ field= mysql_fetch_field(result);
+ FAIL_IF(!field, "Invalid field");
+ FAIL_UNLESS(strcmp(field->name, "YEAR") == 0, "name != 'YEAR'");
+ FAIL_UNLESS(field->org_name[0] == '\0', "org_name != ''");
+
+ field= mysql_fetch_field(result);
+ FAIL_IF(field, "no more fields expected");
+
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_dateformat");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+/* Test mysql_list_fields() */
+
+static int test_list_fields(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ int rc;
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10) default 'mysql')");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_list_fields(mysql, "t1", NULL);
+ FAIL_IF(!result, "Invalid result set");
+
+ rc= 0;
+ while (mysql_fetch_row(result))
+ rc++;
+ FAIL_UNLESS(rc == 0, "rowcount != 0");
+
+ if (verify_prepare_field(result, 0, "c1", "c1", MYSQL_TYPE_LONG,
+ "t1", "t1",
+ schema, 11, "0"))
+ goto error;
+
+ if (verify_prepare_field(result, 1, "c2", "c2", MYSQL_TYPE_STRING,
+ "t1", "t1",
+ schema, 10, "mysql"))
+ goto error;
+
+ mysql_free_result(result);
+ check_mysql_rc(mysql_query(mysql, "drop table t1"), mysql);
+ return OK;
+
+error:
+ mysql_free_result(result);
+ check_mysql_rc(mysql_query(mysql, "drop table t1"), mysql);
+ return FAIL;
+}
+
+/* Test correct max length for MEDIUMTEXT and LONGTEXT columns */
+
+static int test_bug9735(MYSQL *mysql)
+{
+ MYSQL_RES *res;
+ int rc;
+
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (a mediumtext, b longtext) "
+ "character set latin1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "select * from t1");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ if (verify_prepare_field(res, 0, "a", "a", MYSQL_TYPE_BLOB,
+ "t1", "t1", schema, (1U << 24)-1, 0))
+ goto error;
+ if (verify_prepare_field(res, 1, "b", "b", MYSQL_TYPE_BLOB,
+ "t1", "t1", schema, ~0U, 0))
+ goto error;
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+ return OK;
+error:
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "drop table t1");
+ return FAIL;
+}
+
+/*
+ Check that mysql_next_result works properly in case when one of
+ the statements used in a multi-statement query is erroneous
+*/
+
+static int test_bug9992(MYSQL *mysql)
+{
+ MYSQL_RES* res ;
+ int rc;
+
+ /* Sic: SHOW DATABASE is incorrect syntax. */
+ rc= mysql_query(mysql, "SHOW TABLES; SHOW DATABASE; SELECT 1;");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_UNLESS(res, "Invalid resultset");
+ mysql_free_result(res);
+ rc= mysql_next_result(mysql);
+ FAIL_UNLESS(rc == 1, "Error expected"); /* Got errors, as expected */
+
+ return OK;
+}
+
+/* Test the support of multi-statement executions */
+
+static int test_multi_statements(MYSQL *mysql)
+{
+ MYSQL *mysql_local;
+ MYSQL_RES *result;
+ int rc;
+
+ const char *query= "\
+DROP TABLE IF EXISTS test_multi_tab;\
+CREATE TABLE test_multi_tab(id int, name char(20));\
+INSERT INTO test_multi_tab(id) VALUES(10), (20);\
+INSERT INTO test_multi_tab VALUES(20, 'insert;comma');\
+SELECT * FROM test_multi_tab;\
+UPDATE test_multi_tab SET name='new;name' WHERE id=20;\
+DELETE FROM test_multi_tab WHERE name='new;name';\
+SELECT * FROM test_multi_tab;\
+DELETE FROM test_multi_tab WHERE id=10;\
+SELECT * FROM test_multi_tab;\
+DROP TABLE test_multi_tab;\
+select 1;\
+DROP TABLE IF EXISTS test_multi_tab";
+ uint count, exp_value;
+ uint rows[]= {0, 0, 2, 1, 3, 2, 2, 1, 1, 0, 0, 1, 0};
+ my_bool reconnect= 1;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ /*
+ First test that we get an error for multi statements
+ (Because default connection is not opened with CLIENT_MULTI_STATEMENTS)
+ */
+ mysql_local= mysql;
+ mysql = test_connect(NULL);
+ rc= mysql_query(mysql, query); /* syntax error */
+ FAIL_IF(!rc, "Error expected");
+
+ rc= mysql_next_result(mysql);
+ FAIL_UNLESS(rc == -1, "rc != -1");
+ rc= mysql_more_results(mysql);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+
+ mysql_close(mysql);
+ mysql= mysql_local;
+
+ mysql_options(mysql_local, MYSQL_OPT_RECONNECT, &reconnect);
+
+ rc= mysql_query(mysql_local, query);
+ check_mysql_rc(rc, mysql);
+
+ for (count= 0 ; count < array_elements(rows) ; count++)
+ {
+ if ((result= mysql_store_result(mysql_local)))
+ {
+ mysql_free_result(result);
+ }
+
+ exp_value= (uint) mysql_affected_rows(mysql_local);
+ FAIL_IF(rows[count] != exp_value, "row[count] != exp_value");
+ if (count != array_elements(rows) -1)
+ {
+ rc= mysql_more_results(mysql_local);
+ FAIL_IF(!rc, "More results expected");
+ rc= mysql_next_result(mysql_local);
+ check_mysql_rc(rc, mysql_local);
+ }
+ else
+ {
+ rc= mysql_more_results(mysql_local);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+ rc= mysql_next_result(mysql_local);
+ FAIL_UNLESS(rc == -1, "rc != -1");
+ }
+ }
+
+ /* check that errors abort multi statements */
+
+ rc= mysql_query(mysql_local, "select 1+1+a;select 1+1");
+ FAIL_IF(!rc, "Error expected");
+ rc= mysql_more_results(mysql_local);
+ FAIL_UNLESS(rc == 0, "rc != 0");
+ rc= mysql_next_result(mysql_local);
+ FAIL_UNLESS(rc == -1, "rc != -1");
+
+ rc= mysql_query(mysql_local, "select 1+1;select 1+1+a;select 1");
+ check_mysql_rc(rc, mysql);
+ result= mysql_store_result(mysql_local);
+ FAIL_IF(!result, "Invalid result set");
+ mysql_free_result(result);
+ rc= mysql_more_results(mysql_local);
+ FAIL_UNLESS(rc == 1, "rc != 1");
+ rc= mysql_next_result(mysql_local);
+ FAIL_UNLESS(rc > 0, "rc <= 0");
+
+ /*
+ Ensure that we can now do a simple query (this checks that the server is
+ not trying to send us the results for the last 'select 1'
+ */
+ rc= mysql_query(mysql_local, "select 1+1+1");
+ check_mysql_rc(rc, mysql);
+ result= mysql_store_result(mysql_local);
+ FAIL_IF(!result, "Invalid result set");
+ mysql_free_result(result);
+
+ /*
+ Check if errors in one of the queries handled properly.
+ */
+ rc= mysql_query(mysql_local, "select 1; select * from not_existing_table");
+ check_mysql_rc(rc, mysql);
+ result= mysql_store_result(mysql_local);
+ mysql_free_result(result);
+
+ rc= mysql_next_result(mysql_local);
+ FAIL_UNLESS(rc > 0, "rc <= 0");
+
+ rc= mysql_next_result(mysql_local);
+ FAIL_UNLESS(rc < 0, "rc >= 0");
+
+ return OK;
+}
+
+static int test_conc160(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+ int rc;
+
+ rc= mysql_query(mysql, "SELECT cast(1.234 AS DECIMAL)");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ field= mysql_fetch_field(result);
+
+ FAIL_UNLESS(field->flags & NUM_FLAG, "Numeric flag not set");
+
+ mysql_free_result(result);
+ return OK;
+}
+
+
+
+struct my_tests_st my_tests[] = {
+ {"test_conc160", test_conc160, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"client_store_result", client_store_result, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"client_use_result", client_use_result, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_free_result", test_free_result, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_free_store_result", test_free_store_result, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_store_result", test_store_result, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_store_result1", test_store_result1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_store_result2", test_store_result2, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug11718", test_bug11718, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug19671", test_bug19671, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug21726", test_bug21726, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug6761", test_bug6761, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_field_flags", test_field_flags, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_field_names", test_field_names, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_func_fields", test_func_fields, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_list_fields", test_list_fields, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug9735", test_bug9735, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+ {"test_bug9992", test_bug9992, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL, NULL},
+ {"test_multi_statements", test_multi_statements, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/rpl_api.c b/libmariadb/unittest/libmariadb/rpl_api.c
new file mode 100644
index 00000000..f65a2915
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/rpl_api.c
@@ -0,0 +1,363 @@
+/*
+Copyright (c) 2018 MariaDB Corporation AB
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ Some basic tests of the client API.
+*/
+
+#include "my_test.h"
+#include "mariadb_rpl.h"
+
+static int test_rpl_async(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MARIADB_RPL_EVENT *event= NULL;
+ MARIADB_RPL *rpl;
+ int events= 0, rc;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "SELECT @@log_bin");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+ if (!atoi(row[0]))
+ rc= SKIP;
+ mysql_free_result(result);
+
+ if (rc == SKIP)
+ {
+ diag("binary log disabled -> skip");
+ mysql_close(mysql);
+ return SKIP;
+ }
+
+ rpl = mariadb_rpl_init(mysql);
+
+ mysql_query(mysql, "SET @mariadb_slave_capability=4");
+ mysql_query(mysql, "SET NAMES latin1");
+ mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
+ mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
+ mysql_query(mysql, "SET NAMES utf8");
+ mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
+ rpl->server_id= 12;
+ rpl->start_position= 4;
+ rpl->flags= MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS;
+
+ if (mariadb_rpl_open(rpl))
+ return FAIL;
+
+ /* We run rpl_api as very last test, too make sure
+ binary log contains > 10000 events.
+ */
+ while((event= mariadb_rpl_fetch(rpl, event)) && events < 10000)
+ {
+ events++;
+ }
+ mariadb_free_rpl_event(event);
+ mariadb_rpl_close(rpl);
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_rpl_semisync(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MARIADB_RPL_EVENT *event= NULL;
+ MARIADB_RPL *rpl;
+ int events= 0, rc;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "SELECT @@log_bin");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+ if (!atoi(row[0]))
+ rc= SKIP;
+ mysql_free_result(result);
+
+ if (rc == SKIP)
+ {
+ diag("binary log disabled -> skip");
+ mysql_close(mysql);
+ return SKIP;
+ }
+
+ rpl = mariadb_rpl_init(mysql);
+
+ mariadb_rpl_optionsv(rpl, MARIADB_RPL_HOST, "foo");
+
+ mysql_query(mysql, "SET @mariadb_slave_capability=4");
+ mysql_query(mysql, "SET NAMES latin1");
+ mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
+ mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
+ mysql_query(mysql, "SET NAMES utf8");
+ mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
+ rpl->server_id= 12;
+ rpl->start_position= 4;
+ rpl->flags= MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS;
+
+ mysql_query(mysql, "SET @mariadb_slave_capability=4");
+ mysql_query(mysql, "SET NAMES latin1");
+ mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
+ mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
+ mysql_query(mysql, "SET NAMES utf8");
+ mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
+ rpl->server_id= 12;
+ rpl->start_position= 4;
+ rpl->flags= MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS;
+
+ if (mariadb_rpl_open(rpl))
+ return FAIL;
+
+ /* We run rpl_api as very last test, too make sure
+ binary log contains > 10000 events.
+ */
+ while((event= mariadb_rpl_fetch(rpl, event)) && events < 10000)
+ {
+ events++;
+ }
+ mariadb_free_rpl_event(event);
+ mariadb_rpl_close(rpl);
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_conc467(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MARIADB_RPL_EVENT *event= NULL;
+ MARIADB_RPL *rpl;
+ int rc;
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "SELECT @@log_bin");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+ if (!atoi(row[0]))
+ rc= SKIP;
+ mysql_free_result(result);
+
+ if (rc == SKIP)
+ {
+ diag("binary log disabled -> skip");
+ mysql_close(mysql);
+ return SKIP;
+ }
+
+ /* Force to create a log rotate event */
+ rc= mysql_query(mysql, "FLUSH logs");
+ check_mysql_rc(rc, mysql);
+
+ rpl = mariadb_rpl_init(mysql);
+
+ mysql_query(mysql, "SET @mariadb_slave_capability=4");
+ mysql_query(mysql, "SET NAMES latin1");
+ mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
+ mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
+ mysql_query(mysql, "SET NAMES utf8");
+ mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
+ rpl->server_id= 12;
+ rpl->start_position= 4;
+ rpl->flags= MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS;
+
+ if (mariadb_rpl_open(rpl))
+ return FAIL;
+
+ if (!(event= mariadb_rpl_fetch(rpl, event)))
+ rc= FAIL;
+ else
+ {
+ if (!rpl->filename)
+ {
+ diag("error: filename not set");
+ rc= FAIL;
+ }
+ else
+ diag("filename: %.*s", (int)rpl->filename_length, rpl->filename);
+ }
+
+ mariadb_free_rpl_event(event);
+ mariadb_rpl_close(rpl);
+ mysql_close(mysql);
+ return rc;
+}
+
+static int test_conc592(MYSQL *my __attribute__((unused)))
+{
+ MARIADB_RPL *rpl;
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL *mysql_check= mysql_init(NULL);
+ const char *host= "myhost";
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ int rc;
+ int found= 0;
+
+
+ mysql_optionsv(mysql, MARIADB_OPT_RPL_REGISTER_REPLICA, host, 123);
+
+ SKIP_SKYSQL;
+ SKIP_MAXSCALE;
+
+ if (!is_mariadb)
+ return SKIP;
+
+ if (!my_test_connect(mysql, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ if (!my_test_connect(mysql_check, hostname, username,
+ password, schema, port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+
+ rc= mysql_query(mysql, "SELECT @@log_bin");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ row= mysql_fetch_row(result);
+ if (!atoi(row[0]))
+ rc= SKIP;
+ mysql_free_result(result);
+
+ if (rc == SKIP)
+ {
+ diag("binary log disabled -> skip");
+ mysql_close(mysql);
+ return SKIP;
+ }
+
+ rpl = mariadb_rpl_init(mysql);
+
+ mysql_query(mysql, "SET @mariadb_slave_capability=4");
+ mysql_query(mysql, "SET NAMES latin1");
+ mysql_query(mysql, "SET @slave_gtid_strict_mode=1");
+ mysql_query(mysql, "SET @slave_gtid_ignore_duplicates=1");
+ mysql_query(mysql, "SET NAMES utf8");
+ mysql_query(mysql, "SET @master_binlog_checksum= @@global.binlog_checksum");
+ mysql_query(mysql, "SET @rpl_semi_sync_slave=1");
+ rpl->server_id= 12;
+ rpl->start_position= 4;
+ rpl->flags= MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS;
+
+ if (mariadb_rpl_open(rpl))
+ return FAIL;
+
+ rc= mysql_query(mysql_check, "SHOW SLAVE HOSTS");
+ check_mysql_rc(rc, mysql_check);
+
+ result= mysql_store_result(mysql_check);
+
+ while ((row= mysql_fetch_row(result)))
+ if (!strcmp(row[1], host))
+ found= 1;
+
+ mysql_free_result(result);
+ mysql_close(mysql);
+ mysql_close(mysql_check);
+
+ if (!found)
+ {
+ diag("Host '%s' not found in replica list", host);
+ return FAIL;
+ }
+
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc592", test_conc592, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_rpl_async", test_rpl_async, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_rpl_semisync", test_rpl_semisync, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc467", test_conc467, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/sp.c b/libmariadb/unittest/libmariadb/sp.c
new file mode 100644
index 00000000..6aeb557e
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/sp.c
@@ -0,0 +1,91 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+
+/* Bug#15752 "Lost connection to MySQL server when calling a SP from C API" */
+
+static int test_bug15752(MYSQL *mysql)
+{
+ int rc, i;
+ const int ITERATION_COUNT= 100;
+ const char *query= "CALL p1()";
+
+
+ rc= mysql_query(mysql, "drop procedure if exists p1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create procedure p1() select 1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_real_query(mysql, SL(query));
+ check_mysql_rc(rc, mysql);
+ mysql_free_result(mysql_store_result(mysql));
+
+ rc= mysql_real_query(mysql, SL(query));
+ FAIL_UNLESS(rc && mysql_errno(mysql) == CR_COMMANDS_OUT_OF_SYNC, "Error expected");
+
+ rc= mysql_next_result(mysql);
+ check_mysql_rc(rc, mysql);
+
+ mysql_free_result(mysql_store_result(mysql));
+
+ rc= mysql_next_result(mysql);
+ FAIL_IF(rc != -1, "rc != -1");
+
+ for (i = 0; i < ITERATION_COUNT; i++)
+ {
+ rc= mysql_real_query(mysql, SL(query));
+ check_mysql_rc(rc, mysql);
+ mysql_free_result(mysql_store_result(mysql));
+ rc= mysql_next_result(mysql);
+ check_mysql_rc(rc, mysql);
+ mysql_free_result(mysql_store_result(mysql));
+ rc= mysql_next_result(mysql);
+ FAIL_IF(rc != -1, "rc != -1");
+
+ }
+ rc= mysql_query(mysql, "drop procedure p1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+
+
+struct my_tests_st my_tests[] = {
+ {"test_bug15752", test_bug15752, TEST_CONNECTION_NEW, 0, NULL , NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/ssl.c b/libmariadb/unittest/libmariadb/ssl.c
new file mode 100644
index 00000000..0cabe7c4
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/ssl.c
@@ -0,0 +1,1424 @@
+/************************************************************************************
+ Copyright (C) 2012 Monty Program AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not see <http://www.gnu.org/licenses>
+ or write to the Free Software Foundation, Inc.,
+ 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
+ *************************************************************************************/
+#if defined(WIN32) && defined(HEAP_CHECK)
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include "my_test.h"
+#include <ma_pthread.h>
+#ifdef HAVE_OPENSSL
+#include <openssl/opensslv.h>
+#include <openssl/ssl.h>
+#endif
+
+#define FNLEN 4096
+
+static int skip_ssl= 1;
+static uchar have_openssl= 1;
+static unsigned char have_tls13= 0;
+
+const char *ssluser= "ssluser";
+const char *sslpw= "sslpw";
+char sslhost[128];
+char sslcert[FNLEN];
+char sslcombined[FNLEN];
+char sslkey[FNLEN];
+char sslkey_enc[FNLEN];
+char sslca[FNLEN];
+char sslcrl[FNLEN];
+char ssl_cert_finger_print[129]= {0};
+char bad_cert_finger_print[]= "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:01:23:45:67";
+
+pthread_mutex_t LOCK_test;
+
+void read_fingerprint()
+{
+ FILE *f= fopen(CERT_PATH "/server-cert.sha1", "r");
+ if (f)
+ {
+ if (!fscanf(f, "%128s", ssl_cert_finger_print))
+ ssl_cert_finger_print[0]= 0;
+ fclose(f);
+ }
+}
+
+int check_skip_ssl()
+{
+ const char *ssldir= NULL;
+#ifndef HAVE_TLS
+ diag("client library built without OpenSSL support -> skip");
+ return 1;
+#endif
+ if (skip_ssl)
+ {
+ diag("server doesn't support SSL -> skip");
+ return 1;
+ }
+ if (!(ssldir= getenv("SECURE_LOAD_PATH")))
+ {
+ ssldir= CERT_PATH;
+ if (!strlen(ssldir))
+ {
+ diag("certificate directory not found");
+ return 1;
+ }
+ }
+ snprintf(sslcert, FNLEN - 1, "%s/%s", ssldir, "client-cert.pem");
+ snprintf(sslcombined, FNLEN - 1, "%s/%s", ssldir, "client-certkey.pem");
+ snprintf(sslkey, FNLEN - 1, "%s/%s", ssldir, "client-key.pem");
+ snprintf(sslkey_enc, FNLEN - 1, "%s/%s", ssldir, "client-key-enc.pem");
+ snprintf(sslca, FNLEN - 1, "%s/%s", ssldir, "cacert.pem");
+ return 0;
+}
+
+static int check_cipher(MYSQL *mysql)
+{
+ char *cipher= (char *)mysql_get_ssl_cipher(mysql);
+ if (!cipher)
+ return 1;
+ diag("cipher: %s", cipher);
+
+ return 0;
+}
+
+static int create_ssl_user(const char *ssluser, my_bool is_X509)
+{
+ int rc;
+ char query[1024];
+ MYSQL *mysql= mysql_init(NULL);
+
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(mysql));
+
+ sprintf(query, "DROP USER '%s'@'%s'", ssluser, this_host);
+ rc= mysql_query(mysql, query);
+
+ sprintf(query, "CREATE USER '%s'@'%s' IDENTIFIED BY '%s'", ssluser, this_host, sslpw);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc,mysql);
+
+ sprintf(query, "GRANT ALL ON %s.* TO '%s'@'%s' REQUIRE %s", schema, ssluser, this_host, is_X509 ? "X509" : "SSL");
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc,mysql);
+ rc= mysql_query(mysql, "FLUSH PRIVILEGES");
+ check_mysql_rc(rc,mysql);
+
+ mysql_close(mysql);
+
+ return rc;
+}
+
+static int test_ssl(MYSQL *mysql)
+{
+ int rc;
+ unsigned int iversion;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char *tls_library;
+ MYSQL *my= mysql_init(NULL);
+
+ mysql_ssl_set(my,0, 0, 0, 0, 0);
+
+ create_ssl_user("ssluser", 0);
+
+ FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ mariadb_get_infov(my, MARIADB_CONNECTION_TLS_VERSION_ID, &iversion);
+ diag("iversion: %d", iversion);
+ if (iversion == 4)
+ have_tls13= 1;
+
+ mysql_close(my);
+
+ rc= mysql_query(mysql, "SELECT @@have_ssl, @@have_openssl");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_IF(!res, mysql_error(mysql));
+
+ while ((row= mysql_fetch_row(res)))
+ {
+ if (!strcmp(row[0], "YES"))
+ skip_ssl= 0;
+ if (strcmp(row[1], "YES"))
+ have_openssl= 0;
+ diag("SSL: %s", row[0]);
+ }
+ mysql_free_result(res);
+
+ /* In MySQL we need to check tls_version */
+ if (!mariadb_connection(mysql))
+ {
+ rc= mysql_query(mysql, "select locate('v1.2', @@tls_version) > 0");
+ check_mysql_rc(rc, mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_IF(!res, mysql_error(mysql));
+
+ if ((row= mysql_fetch_row(res)))
+ {
+ if (row[0] && row[0][0] == '0')
+ have_openssl= 0;
+ }
+ mysql_free_result(res);
+ }
+ diag("OpenSSL: %d", have_openssl);
+
+ mariadb_get_infov(NULL, MARIADB_TLS_LIBRARY, &tls_library);
+ diag("SSL library: %s", tls_library);
+
+ sslhost[0]= 0;
+
+ if (!skip_ssl)
+ {
+ char *p;
+
+ rc= mysql_query(mysql, "SELECT CURRENT_USER()");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ diag("user: %s", row[0]);
+ if ((p= strchr(row[0], '@')))
+ strcpy(sslhost, p+1);
+ mysql_free_result(res);
+ }
+
+ return OK;
+}
+
+static int test_ssl_cipher(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *my;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ mysql_ssl_set(my,0, 0, sslca, 0, 0);
+
+ FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ rc= mysql_query(my, "SHOW session status like 'Ssl_version'");
+ check_mysql_rc(rc, my);
+ res= mysql_store_result(my);
+ row= mysql_fetch_row(res);
+ diag("%s: %s", row[0], row[1]);
+ diag("cipher: %s", mysql_get_ssl_cipher(my));
+ mysql_free_result(res);
+
+ FAIL_IF(check_cipher(my) != 0, "Invalid cipher");
+ mysql_close(my);
+ return OK;
+}
+
+static int test_conc95(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ create_ssl_user("ssluser1", 1);
+
+ mysql= mysql_init(NULL);
+ mysql_ssl_set(mysql,
+ sslkey,
+ sslcert,
+ NULL,
+ NULL,
+ NULL);
+
+ if (!mysql_real_connect(mysql, hostname, "ssluser1", sslpw, schema,
+ ssl_port, socketname, 0))
+ {
+ diag("could not establish x509 connection. Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ return FAIL;
+ }
+ mysql_close(mysql);
+ return OK;
+}
+
+static int test_multi_ssl_connections(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql[50], *my;
+ int i, rc;
+ int old_connections= 0, new_connections= 0;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ diag("Test doesn't work with yassl");
+ return SKIP;
+
+ create_ssl_user(ssluser, 0);
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my,"mysql_init() failed");
+ FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ rc= mysql_query(my, "SHOW STATUS LIKE 'Ssl_accepts'");
+ check_mysql_rc(rc, my);
+
+ res= mysql_store_result(my);
+ if ((row= mysql_fetch_row(res)))
+ old_connections= atoi(row[1]);
+ mysql_free_result(res);
+
+ for (i=0; i < 50; i++)
+ {
+ mysql[i]= mysql_init(NULL);
+ FAIL_IF(!mysql[i],"mysql_init() failed");
+
+ mysql_ssl_set(mysql[i], 0, 0, sslca, 0, 0);
+
+ mysql_real_connect(mysql[i], hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ if (mysql_errno(mysql[i]))
+ {
+ diag("loop: %d error: %d %s", i, mysql_errno(mysql[i]), mysql_error(mysql[i]));
+ return FAIL;
+ }
+
+ FAIL_IF(check_cipher(mysql[i]) != 0, "Invalid cipher");
+ }
+ for (i=0; i < 50; i++)
+ mysql_close(mysql[i]);
+
+ rc= mysql_query(my, "SHOW STATUS LIKE 'Ssl_accepts'");
+ check_mysql_rc(rc, my);
+
+ res= mysql_store_result(my);
+ if ((row= mysql_fetch_row(res)))
+ new_connections= atoi(row[1]);
+ mysql_free_result(res);
+
+ mysql_close(my);
+
+ diag("%d SSL connections processed", new_connections - old_connections);
+ FAIL_IF(new_connections - old_connections < 50, "new_connections should be at least old_connections + 50");
+ return OK;
+}
+
+#ifndef WIN32
+static void ssl_thread(void *unused __attribute__((unused)))
+#else
+DWORD WINAPI ssl_thread(void *dummy)
+#endif
+{
+ MYSQL *mysql= NULL;
+
+ mysql_thread_init();
+
+ if (!(mysql= mysql_init(NULL)))
+ {
+ goto end;
+ }
+ mysql_ssl_set(mysql, 0, 0, sslca, 0, 0);
+
+ if(!mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0))
+ {
+ diag(">Error: %s", mysql_error(mysql));
+ goto end;
+ }
+
+ pthread_mutex_lock(&LOCK_test);
+ mysql_query(mysql, "UPDATE ssltest SET a=a+1");
+ pthread_mutex_unlock(&LOCK_test);
+
+end:
+ if(mysql)
+ mysql_close(mysql);
+ mysql_thread_end();
+#ifdef _WIN32
+ return 0;
+#endif
+}
+
+static int test_ssl_threads(MYSQL *mysql)
+{
+ int i, rc;
+#ifndef WIN32
+ pthread_t threads[50];
+#else
+ HANDLE hthreads[50];
+ DWORD dthreads[50];
+#endif
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ rc= mysql_query(mysql, "DROP TABLE IF exists ssltest");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE ssltest (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT into ssltest VALUES (0)");
+ check_mysql_rc(rc, mysql);
+ pthread_mutex_init(&LOCK_test, NULL);
+
+ pthread_mutex_init(&LOCK_test, NULL);
+
+ for (i=0; i < 50; i++)
+ {
+#ifndef WIN32
+ pthread_create(&threads[i], NULL, (void *)ssl_thread, NULL);
+#else
+ hthreads[i]= CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ssl_thread, NULL, 0, &dthreads[i]);
+ if (hthreads[i]==NULL)
+ diag("error while starting thread");
+#endif
+ }
+ for (i=0; i < 50; i++)
+#ifndef WIN32
+ pthread_join(threads[i], NULL);
+#else
+ WaitForSingleObject(hthreads[i], INFINITE);
+#endif
+
+ pthread_mutex_destroy(&LOCK_test);
+
+ rc= mysql_query(mysql, "SELECT a FROM ssltest");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ diag("Found: %s", row[0]);
+ FAIL_IF(strcmp(row[0], "50") != 0, "Expected 50");
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "DROP TABLE IF exists ssltest");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_phpbug51647(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL* mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, sslkey,
+ sslcert,
+ sslca, 0, 0);
+
+ FAIL_IF(!mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+ diag("%s", mysql_get_ssl_cipher(mysql));
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_password_protected(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL* mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, sslkey_enc,
+ sslcert,
+ sslca, 0, 0);
+
+ mysql_options(mysql, MARIADB_OPT_TLS_PASSPHRASE, "qwerty");
+
+ FAIL_IF(!mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+ diag("%s", mysql_get_ssl_cipher(mysql));
+ mysql_close(mysql);
+
+ return OK;
+}
+
+
+static int test_conc50(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, NULL, NULL, "./non_exisiting_cert.pem", NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ diag("Error: %d %s", mysql_errno(mysql), mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql) != 2026, "Expected errno 2026");
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_conc50_1(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ if (!have_openssl)
+ {
+ diag("Server with OpenSSL required");
+ return SKIP;
+ }
+
+ create_ssl_user(ssluser, 0);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, NULL, NULL, sslca, NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ if (mysql_errno(mysql))
+ diag("Error: %d %s", mysql_errno(mysql), mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql), "No error expected");
+
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_conc50_2(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, NULL, NULL, "./non_exisiting_cert.pem", NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ FAIL_IF(mysql_errno(mysql) != 2026, "Expected errno 2026");
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_conc127(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ diag("test disabled - for testing disable other tests or run this test as first test");
+ return SKIP;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, NULL, NULL, "./non_exisiting.pem", NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ diag("Error: %s", mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql) == 0, "Error expected (invalid certificate)");
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_conc50_3(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ create_ssl_user(ssluser, 0);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ FAIL_IF(!mysql_errno(mysql), "Error expected, SSL connection required!");
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, NULL, NULL, sslca, NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ diag("Error: %s<", mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql), "No error expected");
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_conc50_4(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, NULL, sslca, NULL, NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ FAIL_IF(!mysql_errno(mysql) , "Error expected");
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int verify_ssl_server_cert(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+ uint verify= 1;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ if (!hostname || !strcmp(hostname, "localhost"))
+ return SKIP;
+
+ SKIP_TRAVIS();
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, NULL, NULL, sslca, NULL, NULL);
+ mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+
+ FAIL_IF(!mysql_errno(mysql), "Expected error");
+ diag("Error (expected): %s", mysql_error(mysql));
+ mysql_close(mysql);
+
+ return OK;
+}
+
+static int test_bug62743(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, "dummykey", NULL, NULL, NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ diag("Error: %s", mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql) != 2026, "Expected errno 2026");
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, sslkey, NULL, NULL, NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ diag("Error with key: %s", mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql) != 2026, "Expected errno 2026");
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, sslkey,
+ sslcert, NULL, NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ FAIL_IF(mysql_errno(mysql) != 0, "Expected no error");
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ FAIL_IF(!mysql, "Can't allocate memory");
+
+ mysql_ssl_set(mysql, sslkey, "blablubb", NULL, NULL, NULL);
+
+ mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0);
+ diag("Error with cert: %s", mysql_error(mysql));
+ FAIL_IF(mysql_errno(mysql) == 0, "Expected error");
+ mysql_close(mysql);
+
+ return OK;
+}
+
+#ifndef WIN32
+int thread_conc102(void)
+#else
+DWORD WINAPI thread_conc102(void)
+#endif
+{
+ MYSQL *mysql;
+ int rc;
+ MYSQL_RES *res;
+ mysql_thread_init();
+ mysql= mysql_init(NULL);
+
+ mysql_ssl_set(mysql, sslkey,
+ sslcert,
+ sslca,
+ NULL, NULL);
+ mysql_ssl_set(mysql,0, 0, sslca, 0, 0);
+
+ if(!mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0))
+ {
+ diag(">Error: %s", mysql_error(mysql));
+ goto end;
+ }
+ if (!mysql_get_ssl_cipher(mysql))
+ {
+ diag("Error: No ssl connection");
+ goto end;
+ }
+ pthread_mutex_lock(&LOCK_test);
+ rc= mysql_query(mysql, "UPDATE t_conc102 SET a=a+1");
+ check_mysql_rc(rc, mysql);
+ pthread_mutex_unlock(&LOCK_test);
+ check_mysql_rc(rc, mysql);
+ if ((res= mysql_store_result(mysql)))
+ mysql_free_result(res);
+end:
+ mysql_close(mysql);
+ mysql_thread_end();
+ return 0;
+}
+
+static int test_conc_102(MYSQL *mysql)
+{
+
+ int rc;
+ int i;
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+#ifndef WIN32
+ pthread_t threads[50];
+#else
+ HANDLE hthreads[50];
+ DWORD threads[50];
+#endif
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t_conc102");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t_conc102 ( a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO t_conc102 VALUES (0)");
+ check_mysql_rc(rc, mysql);
+ pthread_mutex_init(&LOCK_test, NULL);
+
+ for (i=0; i < 50; i++)
+ {
+#ifndef WIN32
+ pthread_create(&threads[i], NULL, (void *)thread_conc102, NULL);
+#else
+ hthreads[i]= CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_conc102, NULL, 0, &threads[i]);
+ if (hthreads[i]==NULL)
+ diag("error while starting thread");
+#endif
+ }
+ for (i=0; i < 50; i++)
+ {
+#ifndef WIN32
+ pthread_join(threads[i], NULL);
+#else
+ WaitForSingleObject(hthreads[i], INFINITE);
+#endif
+ }
+ pthread_mutex_destroy(&LOCK_test);
+ rc= mysql_query(mysql, "SELECT a FROM t_conc102");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ diag("Found: %s", row[0]);
+ FAIL_IF(strcmp(row[0], "50") != 0, "Expected 50");
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t_conc102");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_ssl_fp(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *my;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ mysql_ssl_set(my,0, 0, sslca, 0, 0);
+
+ mysql_options(my, MARIADB_OPT_SSL_FP, bad_cert_finger_print);
+
+ FAIL_IF(mysql_real_connect(my, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ mysql_options(my, MARIADB_OPT_SSL_FP, ssl_cert_finger_print);
+
+ FAIL_IF(!mysql_real_connect(my, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ FAIL_IF(check_cipher(my) != 0, "Invalid cipher");
+
+ rc= mysql_query(my, "SET @a:=1");
+ check_mysql_rc(rc, my);
+
+ rc= mysql_query(my, "SELECT @a");
+ check_mysql_rc(rc, my);
+
+ if ((res= mysql_store_result(my)))
+ {
+ row= mysql_fetch_row(res);
+ diag("@a:=%s", row[0]);
+ mysql_free_result(res);
+ }
+
+ mysql_close(my);
+ return OK;
+}
+
+static int test_ssl_fp_list(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *my;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ mysql_ssl_set(my,0, 0, sslca, 0, 0);
+
+ mysql_options(my, MARIADB_OPT_SSL_FP_LIST, CERT_PATH "/server-cert.sha1");
+
+ if(!mysql_real_connect(my, hostname, username, password, schema,
+ ssl_port, socketname, 0))
+ {
+ diag("Error: %s", mysql_error(my));
+ mysql_close(my);
+ return FAIL;
+ }
+
+ FAIL_IF(check_cipher(my) != 0, "Invalid cipher");
+ mysql_close(my);
+ return OK;
+}
+
+static int test_ssl_version(MYSQL *unused __attribute__((unused)))
+{
+ unsigned int iversion;
+ char *version, *library;
+ MYSQL *my;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ mysql_ssl_set(my,0, 0, sslca, 0, 0);
+ FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ diag("cipher: %s", mysql_get_ssl_cipher(my));
+ mariadb_get_infov(my, MARIADB_CONNECTION_TLS_VERSION_ID, &iversion);
+ diag("protocol: %d", iversion);
+ mariadb_get_infov(my, MARIADB_CONNECTION_TLS_VERSION, &version);
+ diag("protocol: %s", version);
+
+ mariadb_get_infov(my, MARIADB_TLS_LIBRARY, &library);
+ diag("library: %s", library);
+
+ mysql_close(my);
+
+ return OK;
+}
+
+#ifdef HAVE_SCHANNEL
+static int test_schannel_cipher(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *my;
+ unsigned int cipher_strength= 256;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ mysql_ssl_set(my,0, 0, sslca, 0, 0);
+ mysql_options(my, MARIADB_OPT_TLS_CIPHER_STRENGTH, &cipher_strength);
+ FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ diag("cipher: %s", mysql_get_ssl_cipher(my));
+
+ mysql_close(my);
+
+ return OK;
+}
+
+#endif
+
+#if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
+
+static int test_cipher_mapping(MYSQL *unused __attribute__((unused)))
+{
+ unsigned int i=0;
+ const char *ciphers[]= { "DHE-RSA-AES256-GCM-SHA384", "DHE-RSA-AES256-SHA256", "DHE-RSA-AES256-SHA",
+#ifdef TEST_CAMELLIA_CIPHER
+ "DHE-RSA-CAMELLIA256-SHA", "CAMELLIA256-SHA",
+ "DHE-RSA-CAMELLIA128-SHA", "CAMELLIA128-SHA",
+#endif
+#ifdef TEST_DES_CIPHER
+ "EDH-RSA-DES-CBC3-SHA",
+ "DES-CBC3-SHA",
+#endif
+ "AES256-GCM-SHA384", "AES256-SHA256", "AES256-SHA",
+ "DHE-RSA-AES128-GCM-SHA256", "DHE-RSA-AES128-SHA256", "DHE-RSA-AES128-SHA",
+ "AES128-GCM-SHA256", "AES128-SHA256", "AES128-SHA",
+ "DHE-RSA-AES256-SHA", "AES256-SHA",
+ NULL };
+
+ diag("This test depends on OpenSSL version - since several ciphers might not be available");
+ return SKIP;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ if (!have_openssl)
+ {
+ diag("test requires Server with OpenSSL");
+ return SKIP;
+ }
+
+ while (ciphers[i] != NULL)
+ {
+ MYSQL *mysql= mysql_init(NULL);
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+ char c[100];
+ int rc;
+ const char *cipher;
+
+ mysql_options(mysql, MYSQL_OPT_TLS_VERSION, "TLSv1.0,TLSv1.1,TLSv1.2");
+ mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, ciphers[i]);
+ diag("%s", ciphers[i]);
+
+ mysql->options.use_ssl= 1;
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+ if (!(cipher= mysql_get_ssl_cipher(mysql)) ||
+ strcmp(ciphers[i], cipher) != 0)
+ {
+ diag("cipher %s differs: (%s)", ciphers[i], cipher);
+ mysql_close(mysql);
+ goto cont;
+ }
+ else
+ {
+ rc= mysql_query(mysql, "SHOW STATUS LIKE 'ssl_cipher'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+ strcpy(c, row[1]);
+ mysql_free_result(res);
+ mysql_close(mysql);
+ if (strcmp(ciphers[i], c) != 0)
+ {
+ diag("expected: %s instead of %s", ciphers[i], c);
+ /* depending if server supports ECC, ciphers may differ,
+ so we don't return failure here */
+ }
+ }
+cont:
+ i++;
+ }
+ return OK;
+}
+#endif
+
+static int test_openssl_1(MYSQL *mysql)
+{
+ int rc;
+ MYSQL *my;
+ uchar val= 1;
+ char query[1024];
+ int i;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ if (have_tls13)
+ return SKIP;
+
+ if (!mariadb_connection(mysql))
+ return SKIP;
+
+ for (i=1; i < 6; i++)
+ {
+ sprintf(query, "DROP USER 'ssluser%d'@'%s'", i, this_host);
+ rc= mysql_query(mysql, query);
+ sprintf(query, "CREATE USER 'ssluser%d'@'%s'", i, this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+ }
+ rc= mysql_query(mysql, "FLUSH PRIVILEGES");
+ check_mysql_rc(rc, mysql);
+ diag("sslusers created");
+
+ diag("ssluser1");
+ sprintf(query, "grant select on %s.* to 'ssluser1'@'%s' require ssl", schema, this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+
+ my= mysql_init(NULL);
+ mysql_ssl_set(my, NULL, NULL, NULL, NULL, "AES128-SHA");
+ FAIL_IF(!mysql_real_connect(my, hostname, "ssluser1", NULL, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+ FAIL_IF(!mysql_get_ssl_cipher(my), "No TLS connection");
+ mysql_close(my);
+
+ my= mysql_init(NULL);
+ mysql_options(my, MYSQL_OPT_SSL_ENFORCE, &val);
+ FAIL_IF(!mysql_real_connect(my, hostname, "ssluser1", NULL, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+ FAIL_IF(!mysql_get_ssl_cipher(my), "No TLS connection");
+ mysql_close(my);
+
+ diag("ssluser2");
+ sprintf(query, "grant select on %s.* to 'ssluser2'@'%s' require cipher 'AES256-SHA'", schema, this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+#ifdef TEST_RANDOM_RESULT
+/* ssl_user2: connect with enforce should work */
+ my= mysql_init(NULL);
+ mysql_options(my, MYSQL_OPT_SSL_ENFORCE, &val);
+ mysql_real_connect(my, hostname, "ssluser2", NULL, schema,
+ ssl_port, socketname, 0);
+ if (!mysql_error(my) &&
+ strcmp(mysql_get_ssl_cipher(my), "AES256-SHA"))
+ {
+ diag("Expected error or correct cipher");
+ return FAIL;
+ }
+ mysql_close(my);
+#endif
+ /* ssl_user2: connect with correct cipher */
+ diag("ssluser2");
+ if (mysql_get_server_version(mysql) >= 100100)
+ {
+ my= mysql_init(NULL);
+ mysql_ssl_set(my, NULL, NULL, NULL, NULL, "AES256-SHA");
+ FAIL_IF(!mysql_real_connect(my, hostname, "ssluser2", NULL, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+ FAIL_IF(strcmp("AES256-SHA", mysql_get_ssl_cipher(my)) != 0, "expected cipher AES256-SHA");
+ mysql_close(my);
+ }
+
+ /* ssl_user2: connect with wrong cipher should not work */
+ diag("ssluser2");
+ my= mysql_init(NULL);
+ mysql_ssl_set(my, NULL, NULL, NULL, NULL, "AES128-SHA");
+ FAIL_IF(mysql_real_connect(my, hostname, "ssluser2", NULL, schema,
+ ssl_port, socketname, 0), "Error expected");
+ mysql_close(my);
+
+
+ if (!travis_test)
+ {
+ sprintf(query, "grant select on %s.* to 'ssluser3'@'%s' require cipher 'AES256-SHA' AND "
+ " SUBJECT '/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB/CN=client'", schema, this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ /* ssluser3: connect with cipher only */
+ my= mysql_init(NULL);
+ mysql_ssl_set(my, NULL, NULL, NULL, NULL, "AES256-SHA");
+ FAIL_IF(mysql_real_connect(my, hostname, "ssluser3", NULL, schema,
+ ssl_port, socketname, 0), "Error expected");
+ mysql_close(my);
+
+ /* ssluser3 connect with cipher and certs */
+ my= mysql_init(NULL);
+ mysql_ssl_set(my, sslkey,
+ sslcert,
+ sslca,
+ NULL,
+ "AES256-SHA");
+ FAIL_IF(!mysql_real_connect(my, hostname, "ssluser3", NULL, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ mysql_close(my);
+
+ sprintf(query, "grant select on %s.* to 'ssluser4'@'%s' require cipher 'AES256-SHA' AND "
+ " ISSUER '/CN=cacert/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB'", schema, this_host);
+ rc= mysql_query(mysql, query);
+ check_mysql_rc(rc, mysql);
+
+ /* ssluser4: connect with cipher only */
+ my= mysql_init(NULL);
+ mysql_ssl_set(my, NULL, NULL, NULL, NULL, "AES256-SHA");
+ FAIL_IF(mysql_real_connect(my, hostname, "ssluser4", NULL, schema,
+ ssl_port, socketname, 0), "Error expected");
+ mysql_close(my);
+
+ /* ssluser4 connect with cipher and certs */
+ my= mysql_init(NULL);
+ mysql_ssl_set(my, sslkey,
+ sslcert,
+ sslca,
+ NULL,
+ "AES256-SHA");
+ FAIL_IF(!mysql_real_connect(my, hostname, "ssluser4", NULL, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+ mysql_close(my);
+ }
+ diag("drop users");
+ for (i=1; i < 6; i++)
+ {
+ sprintf(query, "DROP USER 'ssluser%d'@'%s'", i, this_host);
+ rc= mysql_query(mysql, query);
+ }
+
+ return OK;
+}
+
+static int test_ssl_timeout(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *mysql;
+ my_bool enforce= 1;
+ int read_timeout= 1;
+ int rc;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &enforce);
+ mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, &read_timeout);
+ mysql->options.use_ssl= 1;
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+ diag("cipher: %s\n", mysql_get_ssl_cipher(mysql));
+ rc= mysql_query(mysql, "SELECT SLEEP(600)");
+ if (!rc)
+ {
+ diag("error expected (timeout)");
+ return FAIL;
+ }
+
+ mysql_close(mysql);
+ return OK;
+}
+
+static int drop_ssl_user(MYSQL *mysql)
+{
+ int rc;
+
+ rc= mysql_query(mysql, "DELETE FROM mysql.user where user like 'ssl%'");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DELETE FROM mysql.db where user like 'ssl%'");
+ check_mysql_rc(rc, mysql);
+ return OK;
+}
+
+static int test_conc286(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL *my;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ mysql_options(my, MARIADB_OPT_SSL_FP, ssl_cert_finger_print);
+
+ FAIL_IF(!mysql_real_connect(my, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(my));
+
+ FAIL_IF(check_cipher(my) != 0, "Invalid cipher");
+
+ mysql_close(my);
+ return OK;
+}
+
+static int test_mdev14027(MYSQL *mysql __attribute__((unused)))
+{
+ char *tls_library;
+ const char *check_library=
+#if defined(HAVE_OPENSSL)
+#if defined(HAVE_LIBRESSL)
+ "LibreSSL";
+#else
+ "OpenSSL";
+#endif
+#elif defined(HAVE_GNUTLS)
+ "GnuTLS";
+#elif defined(HAVE_SCHANNEL)
+ "Schannel";
+#else
+ "Off";
+#endif
+ mariadb_get_infov(NULL, MARIADB_TLS_LIBRARY, &tls_library);
+ diag("TLS/SSL library in use: %s\n", tls_library);
+ if (!strstr(tls_library, check_library))
+ {
+ diag("expected %s, got %s", check_library, tls_library);
+ return FAIL;
+ }
+ return OK;
+}
+
+static int test_mdev14101(MYSQL *my __attribute__((unused)))
+{
+ struct {
+ bool do_yassl;
+ const char *opt_tls_version;
+ const char *expected;
+ } combinations[]= {
+ {1, "TLSv1.1", "TLSv1.1"},
+ {1, "TLSv1,TLSv1.1", "TLSv1.1"},
+ {0, "TLSv1.2", "TLSv1.2"},
+ {0, "TLSv1.1,TLSv1.2", "TLSv1.2"},
+ {1, NULL, NULL}
+ };
+
+ int i;
+#ifdef HAVE_SCHANNEL
+ bool skip_tlsv12= 1;
+#else
+ bool skip_tlsv12= !have_openssl;
+#endif
+
+#if defined(HAVE_OPENSSL) && defined(TLS1_3_VERSION)
+ diag("Test fails with TLS v1.3");
+ return(SKIP);
+#endif
+
+ for (i=0; combinations[i].expected; i++)
+ {
+ MYSQL *mysql;
+ bool val=1;
+ char *tls_version;
+
+ if (!combinations[i].do_yassl && skip_tlsv12)
+ break;
+
+ diag("combination %d: %s", i, combinations[i].opt_tls_version);
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &val);
+ mysql_options(mysql, MARIADB_OPT_TLS_VERSION, combinations[i].opt_tls_version);
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+ mariadb_get_infov(mysql, MARIADB_CONNECTION_TLS_VERSION, &tls_version);
+ diag("options: %s", combinations[i].opt_tls_version);
+ diag("protocol: %s expected: %s", tls_version, combinations[i].expected);
+ FAIL_IF(strcmp(combinations[i].expected, tls_version), "Wrong tls_version");
+ mysql_close(mysql);
+ }
+ return OK;
+}
+
+static int test_conc386(MYSQL *mysql)
+{
+ mysql= mysql_init(NULL);
+ mysql_ssl_set(mysql,
+ sslcombined,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+ FAIL_IF(check_cipher(mysql) != 0, "Invalid cipher");
+ mysql_close(mysql);
+ return OK;
+}
+
+#ifndef HAVE_SCHANNEL
+static int test_ssl_verify(MYSQL *my __attribute__((unused)))
+{
+ MYSQL *mysql;
+ my_bool verify= 1, enforce= 1;
+
+ if (check_skip_ssl())
+ return SKIP;
+
+ /* verify, using system ca should fail with self signed certificate */
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &enforce);
+ mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
+ FAIL_IF(mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0), "Error expected");
+ diag("error expected: %s\n", mysql_error(mysql));
+ mysql_close(mysql);
+
+ /* verify, using system ca should pass */
+
+ /* Disable this for now, since for some unknown reason it fails on travis
+ setenv("SSL_CERT_DIR", CERT_PATH, 1);
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &enforce);
+ mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(mysql));
+ mysql_close(mysql);
+ unsetenv("SSL_CERT_DIR");
+ */
+
+ /* verify against local ca, this should pass */
+ mysql= mysql_init(NULL);
+ mysql_ssl_set(mysql,0, 0, sslca, 0, 0);
+ mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+ mysql_close(mysql);
+
+ mysql= mysql_init(NULL);
+ mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &enforce);
+ FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
+ ssl_port, socketname, 0), mysql_error(mysql));
+
+ diag("cipher: %s", mysql_get_ssl_cipher(mysql));
+ mysql_close(mysql);
+ return OK;
+}
+#endif
+
+struct my_tests_st my_tests[] = {
+ {"test_ssl", test_ssl, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#ifndef HAVE_SCHANNEL
+ {"test_ssl_verify", test_ssl_verify, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#endif
+ {"test_mdev14101", test_mdev14101, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_mdev14027", test_mdev14027, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc286", test_conc286, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_ssl_timeout", test_ssl_timeout, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_openssl_1", test_openssl_1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#ifndef HAVE_SCHANNEL
+ {"test_cipher_mapping", test_cipher_mapping, TEST_CONNECTION_NONE, 0, NULL, NULL},
+#endif
+ {"test_conc127", test_conc127, TEST_CONNECTION_NEW, 0, NULL, NULL},
+/* Both tests work with GNU tls, however we can't create fingerprints with
+ gnutls-cli in CMakeLists.txt */
+#ifndef HAVE_SCHANNEL
+ {"test_ssl_fp", test_ssl_fp, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_ssl_fp_list", test_ssl_fp_list, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#endif
+ {"test_conc50", test_conc50, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc50_1", test_conc50_1, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc50_2", test_conc50_2, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc50_3", test_conc50_3, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc50_4", test_conc50_4, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_conc95", test_conc95, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"verify_ssl_server_cert", verify_ssl_server_cert, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_bug62743", test_bug62743, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_phpbug51647", test_phpbug51647, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_ssl_cipher", test_ssl_cipher, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_multi_ssl_connections", test_multi_ssl_connections, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc_102", test_conc_102, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_ssl_version", test_ssl_version, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"test_ssl_threads", test_ssl_threads, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#ifndef HAVE_SCHANNEL
+ {"test_password_protected", test_password_protected, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#else
+ {"test_schannel_cipher", test_schannel_cipher, TEST_CONNECTION_NEW, 0, NULL, NULL},
+#endif
+ {"test_conc386", test_conc386, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {"drop_ssl_user", drop_ssl_user, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+#if defined(WIN32) && defined(HEAP_CHECK)
+ _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
+ _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
+ _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
+ _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
+ _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
+ _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
+#endif
+
+ get_envvars();
+ read_fingerprint();
+
+ if (argc > 1)
+ get_options(argc, argv);
+ run_tests(my_tests);
+
+ mysql_server_end();
+#if defined(WIN32) && defined(HEAP_CHECK)
+ _CrtDumpMemoryLeaks();
+#endif
+ return(exit_status());
+}
+
diff --git a/libmariadb/unittest/libmariadb/t_conc173.c b/libmariadb/unittest/libmariadb/t_conc173.c
new file mode 100644
index 00000000..5b9369b1
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/t_conc173.c
@@ -0,0 +1,72 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/**
+ Some basic tests of the client API.
+*/
+
+#include "my_test.h"
+
+static int test_conc_173(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL mysql;
+ int arg;
+ int i;
+
+ for (i = 0; i < 1000; i++)
+ {
+ mysql_init(&mysql);
+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client");
+ mysql_options(&mysql, MYSQL_OPT_COMPRESS, 0);
+
+ mysql_options(&mysql, MYSQL_OPT_NAMED_PIPE, 0);
+
+ arg = MYSQL_PROTOCOL_SOCKET;
+
+ mysql_options(&mysql, MYSQL_OPT_PROTOCOL, &arg);
+
+ if(!mysql_real_connect(&mysql, hostname, username, password, schema, port, 0, 0)) {
+ fprintf(stderr, "Failed to connect to database after %d iterations: Error: %s\n", i, mysql_error(&mysql));
+ return 1;
+ }
+ mysql_close(&mysql);
+ }
+ return OK;
+}
+
+struct my_tests_st my_tests[] = {
+ {"test_conc_173", test_conc_173, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
+};
+
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/thread.c b/libmariadb/unittest/libmariadb/thread.c
new file mode 100644
index 00000000..6fae38a8
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/thread.c
@@ -0,0 +1,180 @@
+/*
+*/
+
+#include "my_test.h"
+#include <ma_pthread.h>
+
+static int basic_connect(MYSQL *unused __attribute__((unused)))
+{
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+ MYSQL_FIELD *field;
+ int rc;
+
+ MYSQL *my= mysql_init(NULL);
+ FAIL_IF(!my, "mysql_init() failed");
+
+ FAIL_IF(!my_test_connect(my, hostname, username, password, schema,
+ port, socketname, 0), mysql_error(my));
+
+ rc= mysql_query(my, "SELECT @@version");
+ check_mysql_rc(rc, my);
+
+ res= mysql_store_result(my);
+ FAIL_IF(!res, mysql_error(my));
+ field= mysql_fetch_fields(res);
+ FAIL_IF(!field, "Couldn't fetch fields");
+
+ while ((row= mysql_fetch_row(res)) != NULL)
+ {
+ FAIL_IF(mysql_num_fields(res) != 1, "Got the wrong number of fields");
+ }
+ FAIL_IF(mysql_errno(my), mysql_error(my));
+
+ mysql_free_result(res);
+ mysql_close(my);
+
+
+ return OK;
+}
+
+pthread_mutex_t LOCK_test;
+
+#ifndef _WIN32
+int thread_conc27(void);
+#else
+DWORD WINAPI thread_conc27(void);
+#endif
+
+#define THREAD_NUM 100
+
+/* run this test as root and increase the number of handles (ulimit -n) */
+static int test_conc_27(MYSQL *mysql)
+{
+
+ int rc;
+ int i;
+ MYSQL_ROW row;
+ MYSQL_RES *res;
+#ifndef _WIN32
+ pthread_t threads[THREAD_NUM];
+#else
+ HANDLE hthreads[THREAD_NUM];
+ DWORD threads[THREAD_NUM];
+#endif
+
+ diag("please run this test manually as root");
+ return SKIP;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t_conc27");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "CREATE TABLE t_conc27(a int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "INSERT INTO t_conc27 VALUES(0)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SET @a:=@@max_connections");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SET GLOBAL max_connections=100000");
+ check_mysql_rc(rc, mysql);
+
+ pthread_mutex_init(&LOCK_test, NULL);
+ for (i=0; i < THREAD_NUM; i++)
+ {
+#ifndef _WIN32
+ pthread_create(&threads[i], NULL, (void *)thread_conc27, NULL);
+#else
+ hthreads[i]= CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_conc27, NULL, 0, &threads[i]);
+ if (hthreads[i]==NULL)
+ diag("error while starting thread");
+#endif
+ }
+ for (i=0; i < THREAD_NUM; i++)
+ {
+#ifndef _WIN32
+ pthread_join(threads[i], NULL);
+#else
+ WaitForSingleObject(hthreads[i], INFINITE);
+#endif
+ }
+
+ pthread_mutex_destroy(&LOCK_test);
+
+ rc= mysql_query(mysql, "SET GLOBAL max_connections=@a");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT a FROM t_conc27");
+ check_mysql_rc(rc,mysql);
+
+ res= mysql_store_result(mysql);
+ FAIL_IF(!res, "invalid result");
+
+ row= mysql_fetch_row(res);
+ FAIL_IF(!row, "can't fetch row");
+
+ diag("row=%s", row[0]);
+ FAIL_IF(atoi(row[0]) != THREAD_NUM, "expected value THREAD_NUM");
+ mysql_free_result(res);
+ rc= mysql_query(mysql, "DROP TABLE t_conc27");
+ check_mysql_rc(rc,mysql);
+
+ return OK;
+}
+
+#ifndef _WIN32
+int thread_conc27(void)
+#else
+DWORD WINAPI thread_conc27(void)
+#endif
+{
+ MYSQL *mysql;
+ int rc;
+ MYSQL_RES *res;
+ mysql_thread_init();
+ mysql= mysql_init(NULL);
+ if(!my_test_connect(mysql, hostname, username, password, schema,
+ port, socketname, 0))
+ {
+ diag(">Error: %s", mysql_error(mysql));
+ mysql_close(mysql);
+ mysql_thread_end();
+ goto end;
+ }
+ pthread_mutex_lock(&LOCK_test);
+ rc= mysql_query(mysql, "UPDATE t_conc27 SET a=a+1");
+ check_mysql_rc(rc, mysql);
+ pthread_mutex_unlock(&LOCK_test);
+ check_mysql_rc(rc, mysql);
+ if ((res= mysql_store_result(mysql)))
+ mysql_free_result(res);
+ mysql_close(mysql);
+end:
+ mysql_thread_end();
+ return 0;
+}
+
+struct my_tests_st my_tests[] = {
+ {"basic_connect", basic_connect, TEST_CONNECTION_NONE, 0, NULL, NULL},
+ {"test_conc_27", test_conc_27, TEST_CONNECTION_NEW, 0, NULL, NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+
+int main(int argc, char **argv)
+{
+
+ mysql_library_init(0,0,NULL);
+
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ mysql_server_end();
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/libmariadb/view.c b/libmariadb/unittest/libmariadb/view.c
new file mode 100644
index 00000000..ac2c1e56
--- /dev/null
+++ b/libmariadb/unittest/libmariadb/view.c
@@ -0,0 +1,723 @@
+/*
+Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+
+The MySQL Connector/C is licensed under the terms of the GPLv2
+<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
+MySQL Connectors. There are special exceptions to the terms and
+conditions of the GPLv2 as it is applied to this software, see the
+FLOSS License Exception
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "my_test.h"
+
+static int test_view(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ MYSQL_BIND my_bind[1];
+ char str_data[50];
+ ulong length = 0L;
+ my_bool is_null = 0;
+ const char *query=
+ "SELECT COUNT(*) FROM v1 WHERE SERVERNAME=?";
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3,v1");
+ check_mysql_rc(rc, mysql);
+
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,t1,t2,t3");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"CREATE TABLE t1 ("
+ " SERVERGRP varchar(20) NOT NULL default '', "
+ " DBINSTANCE varchar(20) NOT NULL default '', "
+ " PRIMARY KEY (SERVERGRP)) "
+ " CHARSET=latin1 collate=latin1_bin");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"CREATE TABLE t2 ("
+ " SERVERNAME varchar(20) NOT NULL, "
+ " SERVERGRP varchar(20) NOT NULL, "
+ " PRIMARY KEY (SERVERNAME)) "
+ " CHARSET=latin1 COLLATE latin1_bin");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "CREATE TABLE t3 ("
+ " SERVERGRP varchar(20) BINARY NOT NULL, "
+ " TABNAME varchar(30) NOT NULL, MAPSTATE char(1) NOT NULL, "
+ " ACTSTATE char(1) NOT NULL , "
+ " LOCAL_NAME varchar(30) NOT NULL, "
+ " CHG_DATE varchar(8) NOT NULL default '00000000', "
+ " CHG_TIME varchar(6) NOT NULL default '000000', "
+ " MXUSER varchar(12) NOT NULL default '', "
+ " PRIMARY KEY (SERVERGRP, TABNAME, MAPSTATE, ACTSTATE, "
+ " LOCAL_NAME)) CHARSET=latin1 COLLATE latin1_bin");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"CREATE VIEW v1 AS select sql_no_cache"
+ " T0001.SERVERNAME AS SERVERNAME, T0003.TABNAME AS"
+ " TABNAME,T0003.LOCAL_NAME AS LOCAL_NAME,T0002.DBINSTANCE AS"
+ " DBINSTANCE from t2 T0001 join t1 T0002 join t3 T0003 where"
+ " ((T0002.SERVERGRP = T0001.SERVERGRP) and"
+ " (T0002.SERVERGRP = T0003.SERVERGRP)"
+ " and (T0003.MAPSTATE = _latin1'A') and"
+ " (T0003.ACTSTATE = _latin1' '))");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ strcpy(str_data, "TEST");
+ memset(my_bind, '\0', sizeof(MYSQL_BIND));
+ my_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[0].buffer= (char *)&str_data;
+ my_bind[0].buffer_length= 50;
+ my_bind[0].length= &length;
+ length= 4;
+ my_bind[0].is_null= &is_null;
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ int rowcount= 0;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_IF(rowcount != 1, "Expected 1 row");
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1,t2,t3");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int test_view_where(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query=
+ "select v1.c,v2.c from v1, v2";
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1,v2");
+ check_mysql_rc(rc, mysql);
+
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,v2,t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"CREATE TABLE t1 (a int, b int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"create view v1 (c) as select b from t1 where a<3");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"create view v2 (c) as select b from t1 where a>=3");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ int rowcount= 0;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_UNLESS(4 == rowcount, "Expected 4 rows");
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW v1, v2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int test_view_2where(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ MYSQL_BIND my_bind[8];
+ char params[8][100];
+ ulong length[8];
+ const char *query=
+ "select relid, report, handle, log_group, username, variant, type, "
+ "version, erfdat, erftime, erfname, aedat, aetime, aename, dependvars, "
+ "inactive from V_LTDX where mandt = ? and relid = ? and report = ? and "
+ "handle = ? and log_group = ? and username in ( ? , ? ) and type = ?";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS LTDX");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS V_LTDX");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "CREATE TABLE LTDX (MANDT char(3) NOT NULL default '000', "
+ " RELID char(2) NOT NULL, REPORT varchar(40) NOT NULL,"
+ " HANDLE varchar(4) NOT NULL, LOG_GROUP varchar(4) NOT NULL,"
+ " USERNAME varchar(12) NOT NULL,"
+ " VARIANT varchar(12) NOT NULL,"
+ " TYPE char(1) NOT NULL, SRTF2 int(11) NOT NULL,"
+ " VERSION varchar(6) NOT NULL default '000000',"
+ " ERFDAT varchar(8) NOT NULL default '00000000',"
+ " ERFTIME varchar(6) NOT NULL default '000000',"
+ " ERFNAME varchar(12) NOT NULL,"
+ " AEDAT varchar(8) NOT NULL default '00000000',"
+ " AETIME varchar(6) NOT NULL default '000000',"
+ " AENAME varchar(12) NOT NULL,"
+ " DEPENDVARS varchar(10) NOT NULL,"
+ " INACTIVE char(1) NOT NULL, CLUSTR smallint(6) NOT NULL,"
+ " CLUSTD blob,"
+ " PRIMARY KEY (MANDT, RELID, REPORT, HANDLE, LOG_GROUP, "
+ "USERNAME, VARIANT, TYPE, SRTF2))"
+ " CHARSET=latin1 COLLATE latin1_bin");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "CREATE VIEW V_LTDX AS select T0001.MANDT AS "
+ " MANDT,T0001.RELID AS RELID,T0001.REPORT AS "
+ " REPORT,T0001.HANDLE AS HANDLE,T0001.LOG_GROUP AS "
+ " LOG_GROUP,T0001.USERNAME AS USERNAME,T0001.VARIANT AS "
+ " VARIANT,T0001.TYPE AS TYPE,T0001.VERSION AS "
+ " VERSION,T0001.ERFDAT AS ERFDAT,T0001.ERFTIME AS "
+ " ERFTIME,T0001.ERFNAME AS ERFNAME,T0001.AEDAT AS "
+ " AEDAT,T0001.AETIME AS AETIME,T0001.AENAME AS "
+ " AENAME,T0001.DEPENDVARS AS DEPENDVARS,T0001.INACTIVE AS "
+ " INACTIVE from LTDX T0001 where (T0001.SRTF2 = 0)");
+ check_mysql_rc(rc, mysql);
+ memset(my_bind, '\0', 8 * sizeof(MYSQL_BIND));
+ for (i=0; i < 8; i++) {
+ strcpy(params[i], "1");
+ my_bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+ my_bind[i].buffer = (char *)&params[i];
+ my_bind[i].buffer_length = 1;
+ my_bind[i].is_null = 0;
+ length[i] = 1;
+ my_bind[i].length = &length[i];
+ }
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(MYSQL_NO_DATA == rc, "Expected 0 rows");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP VIEW V_LTDX");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE LTDX");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int test_view_star(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ MYSQL_BIND my_bind[8];
+ char params[8][100];
+ ulong length[8];
+ const char *query= "SELECT * FROM vt1 WHERE a IN (?,?)";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, vt1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS t1, vt1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE VIEW vt1 AS SELECT a FROM t1");
+ check_mysql_rc(rc, mysql);
+ memset(my_bind, '\0', 8 * sizeof(MYSQL_BIND));
+ for (i= 0; i < 2; i++) {
+ sprintf((char *)&params[i], "%d", i);
+ my_bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+ my_bind[i].buffer = (char *)&params[i];
+ my_bind[i].buffer_length = 100;
+ my_bind[i].is_null = 0;
+ my_bind[i].length = &length[i];
+ length[i] = 1;
+ }
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_fetch(stmt);
+ FAIL_UNLESS(MYSQL_NO_DATA == rc, "Expected 0 rows");
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW vt1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int test_view_insert(MYSQL *mysql)
+{
+ MYSQL_STMT *insert_stmt, *select_stmt;
+ int rc, i;
+ MYSQL_BIND my_bind[1];
+ int my_val = 0;
+ ulong my_length = 0L;
+ my_bool my_null = 0;
+ const char *query=
+ "insert into v1 values (?)";
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1");
+ check_mysql_rc(rc, mysql);
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS t1,v1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql,"create table t1 (a int, primary key (a))");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create view v1 as select a from t1 where a>=1");
+ check_mysql_rc(rc, mysql);
+
+ insert_stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(insert_stmt, SL(query));
+ check_stmt_rc(rc, insert_stmt);
+ query= "select * from t1";
+ select_stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(select_stmt, SL(query));
+ check_stmt_rc(rc, select_stmt);
+
+ memset(my_bind, '\0', sizeof(MYSQL_BIND));
+ my_bind[0].buffer_type = MYSQL_TYPE_LONG;
+ my_bind[0].buffer = (char *)&my_val;
+ my_bind[0].length = &my_length;
+ my_bind[0].is_null = &my_null;
+ rc= mysql_stmt_bind_param(insert_stmt, my_bind);
+ check_stmt_rc(rc, select_stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ int rowcount= 0;
+ my_val= i;
+
+ rc= mysql_stmt_execute(insert_stmt);
+ check_stmt_rc(rc, insert_stmt);;
+
+ rc= mysql_stmt_execute(select_stmt);
+ check_stmt_rc(rc, select_stmt);;
+ while (mysql_stmt_fetch(select_stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_UNLESS((i+1) == rowcount, "rowcount != i+1");
+ }
+ mysql_stmt_close(insert_stmt);
+ mysql_stmt_close(select_stmt);
+
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int test_left_join_view(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ int rc, i;
+ const char *query=
+ "select t1.a, v1.x from t1 left join v1 on (t1.a= v1.x);";
+
+ rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1");
+ check_mysql_rc(rc, mysql);
+
+ rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,t1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"CREATE TABLE t1 (a int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"insert into t1 values (1), (2), (3)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,"create view v1 (x) as select a from t1 where a > 1");
+ check_mysql_rc(rc, mysql);
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+
+ for (i= 0; i < 3; i++)
+ {
+ int rowcount= 0;
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_UNLESS(3 == rowcount, "Expected 3 rows");
+ }
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+static int test_view_insert_fields(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ char parm[11][1000];
+ ulong l[11];
+ int rc, i;
+ int rowcount= 0;
+ MYSQL_BIND my_bind[11];
+ const char *query= "INSERT INTO `v1` ( `K1C4` ,`K2C4` ,`K3C4` ,`K4N4` ,`F1C4` ,`F2I4` ,`F3N5` ,`F7F8` ,`F6N4` ,`F5C8` ,`F9D8` ) VALUES( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? )";
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS t1, v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "CREATE TABLE t1 (K1C4 varchar(4) NOT NULL,"
+ "K2C4 varchar(4) NOT NULL, K3C4 varchar(4) NOT NULL,"
+ "K4N4 varchar(4) NOT NULL default '0000',"
+ "F1C4 varchar(4) NOT NULL, F2I4 int(11) NOT NULL,"
+ "F3N5 varchar(5) NOT NULL default '00000',"
+ "F4I4 int(11) NOT NULL default '0', F5C8 varchar(8) NOT NULL,"
+ "F6N4 varchar(4) NOT NULL default '0000',"
+ "F7F8 double NOT NULL default '0',"
+ "F8F8 double NOT NULL default '0',"
+ "F9D8 decimal(8,2) NOT NULL default '0.00',"
+ "PRIMARY KEY (K1C4,K2C4,K3C4,K4N4))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql,
+ "CREATE VIEW v1 AS select sql_no_cache "
+ " K1C4 AS K1C4, K2C4 AS K2C4, K3C4 AS K3C4, K4N4 AS K4N4, "
+ " F1C4 AS F1C4, F2I4 AS F2I4, F3N5 AS F3N5,"
+ " F7F8 AS F7F8, F6N4 AS F6N4, F5C8 AS F5C8, F9D8 AS F9D8"
+ " from t1 T0001");
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i= 0; i < 11; i++)
+ {
+ l[i]= 2;
+ my_bind[i].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[i].is_null= 0;
+ my_bind[i].buffer= (char *)&parm[i];
+
+ strcpy(parm[i], "1");
+ my_bind[i].buffer_length= 2;
+ my_bind[i].length= &l[i];
+ }
+
+ // https://jira.mariadb.org/browse/XPT-266
+ if (IS_XPAND()) {
+ rc= mysql_query(mysql, "SET NAMES UTF8");
+ check_mysql_rc(rc, mysql);
+ }
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ mysql_stmt_close(stmt);
+
+ query= "select * from t1";
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+ while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
+ rowcount++;
+ FAIL_UNLESS(1 == rowcount, "Expected 1 row");
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_view_sp_list_fields(MYSQL *mysql)
+{
+ int rc;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int skip;
+
+ /* skip this test if bin_log is on */
+ rc= mysql_query(mysql, "SHOW VARIABLES LIKE 'log_bin'");
+ check_mysql_rc(rc, mysql);
+ res= mysql_store_result(mysql);
+ FAIL_IF(!res, "empty/invalid resultset");
+ row = mysql_fetch_row(res);
+ skip= (strcmp((char *)row[1], "ON") == 0);
+ mysql_free_result(res);
+
+ if (skip) {
+ diag("bin_log is ON -> skip");
+ return SKIP;
+ }
+
+ rc= mysql_query(mysql, "DROP FUNCTION IF EXISTS f1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS v1, t1, t2");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1, t1, t2");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create function f1 () returns int return 5");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (s1 char,s2 char)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t2 (s1 int);");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create view v1 as select s2,sum(s1) - \
+count(s2) as vx from t1 group by s2 having sum(s1) - count(s2) < (select f1() \
+from t2);");
+ check_mysql_rc(rc, mysql);
+ res= mysql_list_fields(mysql, "v1", NullS);
+ FAIL_UNLESS(res != 0 && mysql_num_fields(res) != 0, "0 Fields");
+ rc= mysql_query(mysql, "DROP FUNCTION f1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP TABLE t1, t2");
+ mysql_free_result(res);
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+static int test_bug19671(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+ int rc, retcode= OK;
+
+
+ rc= mysql_query(mysql, "set sql_mode=''");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "drop table if exists t1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "drop view if exists v1");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create table t1(f1 int)");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "create view v1 as select va.* from t1 va");
+ check_mysql_rc(rc, mysql);
+
+ rc= mysql_query(mysql, "SELECT * FROM v1");
+ check_mysql_rc(rc, mysql);
+
+ result= mysql_store_result(mysql);
+ FAIL_IF(!result, "Invalid result set");
+
+ field= mysql_fetch_field(result);
+ FAIL_IF(!field, "Can't fetch field");
+
+ if (strcmp(field->table, "v1") != 0) {
+ diag("Wrong value '%s' for field_table. Expected 'v1'. (%s: %d)", field->table, __FILE__, __LINE__);
+ retcode= FAIL;
+ }
+
+ mysql_free_result(result);
+
+ rc= mysql_query(mysql, "drop view v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "drop table t1");
+ check_mysql_rc(rc, mysql);
+
+ return retcode;
+}
+
+/*
+ Bug#11111: fetch from view returns wrong data
+*/
+
+static int test_bug11111(MYSQL *mysql)
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[2];
+ char buf[2][20];
+ ulong len[2];
+ int i;
+ int rc;
+ const char *query= "SELECT DISTINCT f1,ff2 FROM v1";
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2, v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "drop view if exists t1, t2, v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t1 (f1 int, f2 int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create table t2 (ff1 int, ff2 int)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "create view v1 as select * from t1, t2 where f1=ff1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t1 values (1,1), (2,2), (3,3)");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "insert into t2 values (1,1), (2,2), (3,3)");
+ check_mysql_rc(rc, mysql);
+
+ stmt= mysql_stmt_init(mysql);
+
+ rc= mysql_stmt_prepare(stmt, SL(query));
+ check_stmt_rc(rc, stmt);
+ rc= mysql_stmt_execute(stmt);
+ check_stmt_rc(rc, stmt);
+
+ memset(my_bind, '\0', sizeof(my_bind));
+ for (i=0; i < 2; i++)
+ {
+ my_bind[i].buffer_type= MYSQL_TYPE_STRING;
+ my_bind[i].buffer= (uchar* *)&buf[i];
+ my_bind[i].buffer_length= 20;
+ my_bind[i].length= &len[i];
+ }
+
+ rc= mysql_stmt_bind_result(stmt, my_bind);
+ check_stmt_rc(rc, stmt);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_stmt_rc(rc, stmt);
+ FAIL_UNLESS(!strcmp(buf[1],"1"), "buf[1] != '1'");
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop view v1");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "drop table t1, t2");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+/**
+ Bug#29306 Truncated data in MS Access with decimal (3,1) columns in a VIEW
+*/
+
+static int test_bug29306(MYSQL *mysql)
+{
+ MYSQL_FIELD *field;
+ int rc;
+ MYSQL_RES *res;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS tab17557");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS view17557");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE TABLE tab17557 (dd decimal (3,1))");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "CREATE VIEW view17557 as SELECT dd FROM tab17557");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "INSERT INTO tab17557 VALUES (7.6)");
+ check_mysql_rc(rc, mysql);
+
+ /* Checking the view */
+ res= mysql_list_fields(mysql, "view17557", NULL);
+ while ((field= mysql_fetch_field(res)))
+ {
+ FAIL_UNLESS(field->decimals == 1, "field->decimals != 1");
+ }
+ mysql_free_result(res);
+
+ rc= mysql_query(mysql, "DROP TABLE tab17557");
+ check_mysql_rc(rc, mysql);
+ rc= mysql_query(mysql, "DROP VIEW view17557");
+ check_mysql_rc(rc, mysql);
+
+ return OK;
+}
+
+
+struct my_tests_st my_tests[] = {
+ {"test_view", test_view, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_view_where", test_view_where, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_view_2where", test_view_2where, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_view_star", test_view_star, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_view_insert", test_view_insert, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_left_join_view", test_left_join_view, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_view_insert_fields", test_view_insert_fields, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_view_sp_list_fields", test_view_sp_list_fields,TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug19671", test_bug19671, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug29306", test_bug29306, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {"test_bug11111", test_bug11111, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
+ {NULL, NULL, 0, 0, NULL, NULL}
+};
+
+int main(int argc, char **argv)
+{
+ if (argc > 1)
+ get_options(argc, argv);
+
+ get_envvars();
+
+ run_tests(my_tests);
+
+ return(exit_status());
+}
diff --git a/libmariadb/unittest/mytap/CMakeLists.txt b/libmariadb/unittest/mytap/CMakeLists.txt
new file mode 100644
index 00000000..1a03d7ac
--- /dev/null
+++ b/libmariadb/unittest/mytap/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2007 MySQL AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include ${CC_SOURCE_DIR}/zlib
+ ${CC_BINARY_DIR}/include)
+ADD_LIBRARY(cctap tap.c)
diff --git a/libmariadb/unittest/mytap/Doxyfile b/libmariadb/unittest/mytap/Doxyfile
new file mode 100644
index 00000000..1b1c82b4
--- /dev/null
+++ b/libmariadb/unittest/mytap/Doxyfile
@@ -0,0 +1,1156 @@
+# Doxyfile 1.3.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME =
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of source
+# files, where putting all generated files in the same directory would otherwise
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories
+# that contain documented source files. You may enter file names like
+# "myfile.cpp" or directories like "/usr/src/myproject". Separate the
+# files or directories with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like
+# *.cpp and *.h) to filter out the source-files in the directories. If
+# left blank the following patterns are tested: *.c *.cc *.cxx *.cpp
+# *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp *.h++
+# *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not
+# subdirectories should be searched for input files as well. Possible
+# values are YES and NO. If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that
+# should excluded from the INPUT source files. This way you can easily
+# exclude a subdirectory from a directory tree whose root is specified
+# with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are
+# excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to
+# exclude certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = e
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *.c
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more
+# wildcard patterns (like *.h and *.hpp) to filter out the
+# header-files in the directories. If left blank, the patterns
+# specified with FILE_PATTERNS will be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names
+# that are defined before the preprocessor is started (similar to the
+# -D option of gcc). The argument of the tag is a list of macros of
+# the form: name or name=definition (no spaces). If the definition and
+# the = are omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES
+# then this tag can be used to specify a list of macro names that
+# should be expanded. The macro definition that is found in the
+# sources will be used. Use the PREDEFINED tag if you want to use a
+# different macro definition.
+
+EXPAND_AS_DEFINED = __attribute__
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are
+# alone on a line, have an all uppercase name, and do not end with a
+# semicolon. Such function macros are typically used for boiler-plate
+# code, and will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/libmariadb/unittest/mytap/t/basic-t.c b/libmariadb/unittest/mytap/t/basic-t.c
new file mode 100644
index 00000000..c0ceb5bf
--- /dev/null
+++ b/libmariadb/unittest/mytap/t/basic-t.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "my_config.h"
+
+#include <stdlib.h>
+#include "../tap.h"
+
+int main() {
+ plan(5);
+ ok(1 == 1, "testing basic functions");
+ ok(2 == 2, " ");
+ ok(3 == 3, NULL);
+ if (1 == 1)
+ skip(2, "Sensa fragoli");
+ else {
+ ok(1 == 2, "Should not be run at all");
+ ok(1, "This one neither");
+ }
+ return exit_status();
+}
diff --git a/libmariadb/unittest/mytap/tap.c b/libmariadb/unittest/mytap/tap.c
new file mode 100644
index 00000000..0290389f
--- /dev/null
+++ b/libmariadb/unittest/mytap/tap.c
@@ -0,0 +1,600 @@
+/* Copyright (C) 2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA
+
+ Library for providing TAP support for testing C and C++ was written
+ by Mats Kindahl <mats@mysql.com>.
+*/
+
+#include "tap.h"
+
+#include "ma_global.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+/*
+ Visual Studio 2003 does not know vsnprintf but knows _vsnprintf.
+ We don't put this #define in config-win.h because we prefer
+ ma_vsnprintf everywhere instead, except when linking with libmysys
+ is not desirable - the case here.
+*/
+#if defined(_MSC_VER) && ( _MSC_VER == 1310 )
+#define vsnprintf _vsnprintf
+#endif
+
+/**
+ @defgroup MyTAP_Internal MyTAP Internals
+
+ Internal functions and data structures for the MyTAP implementation.
+*/
+
+/**
+ Test data structure.
+
+ Data structure containing all information about the test suite.
+
+ @ingroup MyTAP_Internal
+ */
+static TEST_DATA g_test = { 0, 0, 0, "" };
+
+/**
+ Output stream for test report message.
+
+ The macro is just a temporary solution.
+
+ @ingroup MyTAP_Internal
+ */
+#define tapout stdout
+
+/**
+ Emit the beginning of a test line, that is: "(not) ok", test number,
+ and description.
+
+ To emit the directive, use the emit_dir() function
+
+ @ingroup MyTAP_Internal
+
+ @see emit_dir
+
+ @param pass 'true' if test passed, 'false' otherwise
+ @param fmt Description of test in printf() format.
+ @param ap Vararg list for the description string above.
+ */
+static void
+vemit_tap(int pass, char const *fmt, va_list ap)
+{
+ fprintf(tapout, "%sok %d%s",
+ pass ? "" : "not ",
+ ++g_test.last,
+ (fmt && *fmt) ? " - " : "");
+ if (fmt && *fmt)
+ vfprintf(tapout, fmt, ap);
+}
+
+
+/**
+ Emit a TAP directive.
+
+ TAP directives are comments after that have the form:
+
+ @code
+ ok 1 # skip reason for skipping
+ not ok 2 # todo some text explaining what remains
+ @endcode
+
+ @ingroup MyTAP_Internal
+
+ @param dir Directive as a string
+ @param why Explanation string
+ */
+static void
+emit_dir(const char *dir, const char *why)
+{
+ fprintf(tapout, " # %s %s", dir, why);
+}
+
+
+/**
+ Emit a newline to the TAP output stream.
+
+ @ingroup MyTAP_Internal
+ */
+static void
+emit_endl()
+{
+ fprintf(tapout, "\n");
+}
+
+static void
+handle_core_signal(int signo)
+{
+ BAIL_OUT("Signal %d thrown", signo);
+}
+
+void
+BAIL_OUT(char const *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(tapout, "Bail out! ");
+ vfprintf(tapout, fmt, ap);
+ emit_endl();
+ va_end(ap);
+ exit(255);
+}
+
+
+void
+diag(char const *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(tapout, "# ");
+ vfprintf(tapout, fmt, ap);
+ emit_endl();
+ va_end(ap);
+}
+
+typedef struct signal_entry {
+ int signo;
+ void (*handler)(int);
+} signal_entry;
+
+static signal_entry install_signal[]= {
+#ifdef SIGQUIT
+ { SIGQUIT, handle_core_signal },
+#endif
+ { SIGILL, handle_core_signal },
+ { SIGABRT, handle_core_signal },
+ { SIGFPE, handle_core_signal },
+ { SIGSEGV, handle_core_signal }
+#ifdef SIGBUS
+ , { SIGBUS, handle_core_signal }
+#endif
+#ifdef SIGXCPU
+ , { SIGXCPU, handle_core_signal }
+#endif
+#ifdef SIGXCPU
+ , { SIGXFSZ, handle_core_signal }
+#endif
+#ifdef SIGXCPU
+ , { SIGSYS, handle_core_signal }
+#endif
+#ifdef SIGXCPU
+ , { SIGTRAP, handle_core_signal }
+#endif
+};
+
+int skip_big_tests= 1;
+
+void
+plan(int const count)
+{
+ char *config= getenv("MYTAP_CONFIG");
+ size_t i;
+
+ if (config)
+ skip_big_tests= strcmp(config, "big");
+
+ setvbuf(tapout, 0, _IONBF, 0); /* provide output at once */
+ /*
+ Install signal handler
+ */
+
+ for (i= 0; i < sizeof(install_signal)/sizeof(*install_signal); ++i)
+ signal(install_signal[i].signo, install_signal[i].handler);
+
+ g_test.plan= count;
+ switch (count)
+ {
+ case NO_PLAN:
+ break;
+ default:
+ if (count > 0)
+ fprintf(tapout, "1..%d\n", count);
+ break;
+ }
+}
+
+
+void
+skip_all(char const *reason, ...)
+{
+ va_list ap;
+ va_start(ap, reason);
+ fprintf(tapout, "1..0 # skip ");
+ vfprintf(tapout, reason, ap);
+ va_end(ap);
+ exit(0);
+}
+
+void
+ok(int const pass, char const *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ if (!pass && *g_test.todo == '\0')
+ ++g_test.failed;
+
+ vemit_tap(pass, fmt, ap);
+ va_end(ap);
+ if (*g_test.todo != '\0')
+ emit_dir("todo", g_test.todo);
+ emit_endl();
+}
+
+
+void
+skip(int how_many, char const *const fmt, ...)
+{
+ char reason[80];
+ if (fmt && *fmt)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(reason, sizeof(reason), fmt, ap);
+ va_end(ap);
+ }
+ else
+ reason[0] = '\0';
+
+ while (how_many-- > 0)
+ {
+ va_list ap;
+ memset((char*) &ap, 0, sizeof(ap)); /* Keep compiler happy */
+ vemit_tap(1, NULL, ap);
+ emit_dir("skip", reason);
+ emit_endl();
+ }
+}
+
+void
+todo_start(char const *message, ...)
+{
+ va_list ap;
+ va_start(ap, message);
+ vsnprintf(g_test.todo, sizeof(g_test.todo), message, ap);
+ va_end(ap);
+}
+
+void
+todo_end()
+{
+ *g_test.todo = '\0';
+}
+
+int exit_status() {
+ /*
+ If there were no plan, we write one last instead.
+ */
+ if (g_test.plan == NO_PLAN)
+ plan(g_test.last);
+
+ if (g_test.plan != g_test.last)
+ {
+ diag("%d tests planned but%s %d executed",
+ g_test.plan, (g_test.plan > g_test.last ? " only" : ""), g_test.last);
+ return EXIT_FAILURE;
+ }
+
+ if (g_test.failed > 0)
+ {
+ diag("Failed %d tests!", g_test.failed);
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/**
+ @mainpage Testing C and C++ using MyTAP
+
+ @section IntroSec Introduction
+
+ Unit tests are used to test individual components of a system. In
+ contrast, functional tests usually test the entire system. The
+ rationale is that each component should be correct if the system is
+ to be correct. Unit tests are usually small pieces of code that
+ tests an individual function, class, a module, or other unit of the
+ code.
+
+ Observe that a correctly functioning system can be built from
+ "faulty" components. The problem with this approach is that as the
+ system evolves, the bugs surface in unexpected ways, making
+ maintenance harder.
+
+ The advantages of using unit tests to test components of the system
+ are several:
+
+ - The unit tests can make a more thorough testing than the
+ functional tests by testing correctness even for pathological use
+ (which shouldn't be present in the system). This increases the
+ overall robustness of the system and makes maintenance easier.
+
+ - It is easier and faster to find problems with a malfunctioning
+ component than to find problems in a malfunctioning system. This
+ shortens the compile-run-edit cycle and therefore improves the
+ overall performance of development.
+
+ - The component has to support at least two uses: in the system and
+ in a unit test. This leads to more generic and stable interfaces
+ and in addition promotes the development of reusable components.
+
+ For example, the following are typical functional tests:
+ - Does transactions work according to specifications?
+ - Can we connect a client to the server and execute statements?
+
+ In contrast, the following are typical unit tests:
+
+ - Can the 'String' class handle a specified list of character sets?
+ - Does all operations for 'my_bitmap' produce the correct result?
+ - Does all the NIST test vectors for the AES implementation encrypt
+ correctly?
+
+
+ @section UnitTest Writing unit tests
+
+ The purpose of writing unit tests is to use them to drive component
+ development towards a solution that passes the tests. This means that the
+ unit tests has to be as complete as possible, testing at least:
+
+ - Normal input
+ - Borderline cases
+ - Faulty input
+ - Error handling
+ - Bad environment
+
+ @subsection NormalSubSec Normal input
+
+ This is to test that the component have the expected behaviour.
+ This is just plain simple: test that it works. For example, test
+ that you can unpack what you packed, adding gives the sum, pinching
+ the duck makes it quack.
+
+ This is what everybody does when they write tests.
+
+
+ @subsection BorderlineTests Borderline cases
+
+ If you have a size anywhere for your component, does it work for
+ size 1? Size 0? Sizes close to <code>UINT_MAX</code>?
+
+ It might not be sensible to have a size 0, so in this case it is
+ not a borderline case, but rather a faulty input (see @ref
+ FaultyInputTests).
+
+
+ @subsection FaultyInputTests Faulty input
+
+ Does your bitmap handle 0 bits size? Well, it might not be designed
+ for it, but is should <em>not</em> crash the application, but
+ rather produce an error. This is called defensive programming.
+
+ Unfortunately, adding checks for values that should just not be
+ entered at all is not always practical: the checks cost cycles and
+ might cost more than it's worth. For example, some functions are
+ designed so that you may not give it a null pointer. In those
+ cases it's not sensible to pass it <code>NULL</code> just to see it
+ crash.
+
+ Since every experienced programmer add an <code>assert()</code> to
+ ensure that you get a proper failure for the debug builds when a
+ null pointer passed (you add asserts too, right?), you will in this
+ case instead have a controlled (early) crash in the debug build.
+
+
+ @subsection ErrorHandlingTests Error handling
+
+ This is testing that the errors your component is designed to give
+ actually are produced. For example, testing that trying to open a
+ non-existing file produces a sensible error code.
+
+
+ @subsection BadEnvironmentTests Environment
+
+ Sometimes, modules has to behave well even when the environment
+ fails to work correctly. Typical examples are when the computer is
+ out of dynamic memory or when the disk is full. You can emulate
+ this by replacing, e.g., <code>malloc()</code> with your own
+ version that will work for a while, but then fail. Some things are
+ worth to keep in mind here:
+
+ - Make sure to make the function fail deterministically, so that
+ you really can repeat the test.
+
+ - Make sure that it doesn't just fail immediately. The unit might
+ have checks for the first case, but might actually fail some time
+ in the near future.
+
+
+ @section UnitTest How to structure a unit test
+
+ In this section we will give some advice on how to structure the
+ unit tests to make the development run smoothly. The basic
+ structure of a test is:
+
+ - Plan
+ - Test
+ - Report
+
+
+ @subsection TestPlanning Plan the test
+
+ Planning the test means telling how many tests there are. In the
+ event that one of the tests causes a crash, it is then possible to
+ see that there are fewer tests than expected, and print a proper
+ error message.
+
+ To plan a test, use the @c plan() function in the following manner:
+
+ @code
+ int main(int argc, char *argv[])
+ {
+ plan(5);
+ .
+ .
+ .
+ }
+ @endcode
+
+ If you don't call the @c plan() function, the number of tests
+ executed will be printed at the end. This is intended to be used
+ while developing the unit and you are constantly adding tests. It
+ is not indented to be used after the unit has been released.
+
+
+ @subsection TestRunning Execute the test
+
+ To report the status of a test, the @c ok() function is used in the
+ following manner:
+
+ @code
+ int main(int argc, char *argv[])
+ {
+ plan(5);
+ ok(ducks == paddling_ducks,
+ "%d ducks did not paddle", ducks - paddling_ducks);
+ .
+ .
+ .
+ }
+ @endcode
+
+ This will print a test result line on the standard output in TAP
+ format, which allows TAP handling frameworks (like Test::Harness)
+ to parse the status of the test.
+
+ @subsection TestReport Report the result of the test
+
+ At the end, a complete test report should be written, with some
+ statistics. If the test returns EXIT_SUCCESS, all tests were
+ successful, otherwise at least one test failed.
+
+ To get a TAP compliant output and exit status, report the exit
+ status in the following manner:
+
+ @code
+ int main(int argc, char *argv[])
+ {
+ plan(5);
+ ok(ducks == paddling_ducks,
+ "%d ducks did not paddle", ducks - paddling_ducks);
+ .
+ .
+ .
+ return exit_status();
+ }
+ @endcode
+
+ @section DontDoThis Ways to not do unit testing
+
+ In this section, we'll go through some quite common ways to write
+ tests that are <em>not</em> a good idea.
+
+ @subsection BreadthFirstTests Doing breadth-first testing
+
+ If you're writing a library with several functions, don't test all
+ functions using size 1, then all functions using size 2, etc. If a
+ test for size 42 fails, you have no easy way of tracking down why
+ it failed.
+
+ It is better to concentrate on getting one function to work at a
+ time, which means that you test each function for all sizes that
+ you think is reasonable. Then you continue with the next function,
+ doing the same. This is usually also the way that a library is
+ developed (one function at a time) so stick to testing that is
+ appropriate for now the unit is developed.
+
+ @subsection JustToBeSafeTest Writing unnecessarily large tests
+
+ Don't write tests that use parameters in the range 1-1024 unless
+ you have a very good reason to believe that the component will
+ succeed for 562 but fail for 564 (the numbers picked are just
+ examples).
+
+ It is very common to write extensive tests "just to be safe."
+ Having a test suite with a lot of values might give you a warm
+ fuzzy feeling, but it doesn't really help you find the bugs. Good
+ tests fail; seriously, if you write a test that you expect to
+ succeed, you don't need to write it. If you think that it
+ <em>might</em> fail, <em>then</em> you should write it.
+
+ Don't take this as an excuse to avoid writing any tests at all
+ "since I make no mistakes" (when it comes to this, there are two
+ kinds of people: those who admit they make mistakes, and those who
+ don't); rather, this means that there is no reason to test that
+ using a buffer with size 100 works when you have a test for buffer
+ size 96.
+
+ The drawback is that the test suite takes longer to run, for little
+ or no benefit. It is acceptable to do a exhaustive test if it
+ doesn't take too long to run and it is quite common to do an
+ exhaustive test of a function for a small set of values.
+ Use your judgment to decide what is excessive: your milage may
+ vary.
+*/
+
+/**
+ @example simple.t.c
+
+ This is an simple example of how to write a test using the
+ library. The output of this program is:
+
+ @code
+ 1..1
+ # Testing basic functions
+ ok 1 - Testing gcs()
+ @endcode
+
+ The basic structure is: plan the number of test points using the
+ plan() function, perform the test and write out the result of each
+ test point using the ok() function, print out a diagnostics message
+ using diag(), and report the result of the test by calling the
+ exit_status() function. Observe that this test does excessive
+ testing (see @ref JustToBeSafeTest), but the test point doesn't
+ take very long time.
+*/
+
+/**
+ @example todo.t.c
+
+ This example demonstrates how to use the <code>todo_start()</code>
+ and <code>todo_end()</code> function to mark a sequence of tests to
+ be done. Observe that the tests are assumed to fail: if any test
+ succeeds, it is considered a "bonus".
+*/
+
+/**
+ @example skip.t.c
+
+ This is an example of how the <code>SKIP_BLOCK_IF</code> can be
+ used to skip a predetermined number of tests. Observe that the
+ macro actually skips the following statement, but it's not sensible
+ to use anything than a block.
+*/
+
+/**
+ @example skip_all.t.c
+
+ Sometimes, you skip an entire test because it's testing a feature
+ that doesn't exist on the system that you're testing. To skip an
+ entire test, use the <code>skip_all()</code> function according to
+ this example.
+ */
diff --git a/libmariadb/unittest/mytap/tap.h b/libmariadb/unittest/mytap/tap.h
new file mode 100644
index 00000000..15b1842b
--- /dev/null
+++ b/libmariadb/unittest/mytap/tap.h
@@ -0,0 +1,305 @@
+/* Copyright (C) 2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA
+
+ Library for providing TAP support for testing C and C++ was written
+ by Mats Kindahl <mats@mysql.com>.
+*/
+
+#ifndef TAP_H
+#define TAP_H
+
+#include "ma_global.h"
+
+/*
+ @defgroup MyTAP MySQL support for performing unit tests according to
+ the Test Anything Protocol (TAP).
+*/
+
+#define NO_PLAN (0)
+
+/**
+ Data about test plan.
+
+ @ingroup MyTAP_Internal
+
+ @internal We are using the "typedef struct X { ... } X" idiom to
+ create class/struct X both in C and C++.
+ */
+
+typedef struct TEST_DATA {
+ /**
+ Number of tests that is planned to execute.
+
+ Can be zero (<code>NO_PLAN</code>) meaning that the plan string
+ will be printed at the end of test instead.
+ */
+ int plan;
+
+ /** Number of last test that was done or skipped. */
+ int last;
+
+ /** Number of tests that failed. */
+ int failed;
+
+ /** Todo reason. */
+ char todo[128];
+} TEST_DATA;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ Defines whether "big" tests should be skipped.
+
+ This variable is set by plan() function unless MYTAP_CONFIG environment
+ variable is set to the string "big". It is supposed to be used as
+
+ @code
+ if (skip_big_tests) {
+ skip(1, "Big test skipped");
+ } else {
+ ok(life_universe_and_everything() == 42, "The answer is CORRECT");
+ }
+ @endcode
+
+ @see SKIP_BIG_TESTS
+*/
+extern int skip_big_tests;
+
+/**
+ @defgroup MyTAP_API MyTAP API
+
+ MySQL support for performing unit tests according to TAP.
+
+ @{
+*/
+
+/**
+ Set number of tests that is planned to execute.
+
+ The function also accepts the predefined constant
+ <code>NO_PLAN</code>. If the function is not called, it is as if
+ it was called with <code>NO_PLAN</code>, i.e., the test plan will
+ be printed after all the test lines.
+
+ The plan() function will install signal handlers for all signals
+ that generate a core, so if you want to override these signals, do
+ it <em>after</em> you have called the plan() function.
+
+ It will also set skip_big_tests variable if MYTAP_CONFIG environment
+ variable is defined.
+
+ @see skip_big_tests
+
+ @param count The planned number of tests to run.
+*/
+
+void plan(int const count);
+
+
+/**
+ Report test result as a TAP line.
+
+ Function used to write status of an individual test. Call this
+ function in the following manner:
+
+ @code
+ ok(ducks == paddling,
+ "%d ducks did not paddle", ducks - paddling);
+ @endcode
+
+ @param pass Zero if the test failed, non-zero if it passed.
+ @param fmt Format string in printf() format. NULL is allowed, in
+ which case nothing is printed.
+*/
+
+void ok(int const pass, char const *fmt, ...)
+ __attribute__((format(printf,2,3)));
+
+
+/**
+ Skip a determined number of tests.
+
+ Function to print that <em>how_many</em> tests have been skipped.
+ The reason is printed for each skipped test. Observe that this
+ function does not do the actual skipping for you, it just prints
+ information that tests have been skipped. This function is not
+ usually used, but rather the macro @c SKIP_BLOCK_IF, which does the
+ skipping for you.
+
+ It shall be used in the following manner:
+
+ @code
+ if (ducks == 0) {
+ skip(2, "No ducks in the pond");
+ } else {
+ int i;
+ for (i = 0 ; i < 2 ; ++i)
+ ok(duck[i] == paddling, "is duck %d paddling?", i);
+ }
+ @endcode
+
+ @see SKIP_BLOCK_IF
+
+ @param how_many Number of tests that are to be skipped.
+ @param reason A reason for skipping the tests
+ */
+
+void skip(int how_many, char const *const reason, ...)
+ __attribute__((format(printf,2,3)));
+
+
+/**
+ Helper macro to skip a block of code. The macro can be used to
+ simplify conditionally skipping a block of code. It is used in the
+ following manner:
+
+ @code
+ SKIP_BLOCK_IF(ducks == 0, 2, "No ducks in the pond")
+ {
+ int i;
+ for (i = 0 ; i < 2 ; ++i)
+ ok(duck[i] == paddling, "is duck %d paddling?", i);
+ }
+ @endcode
+
+ @see skip
+ */
+
+#define SKIP_BLOCK_IF(SKIP_IF_TRUE, COUNT, REASON) \
+ if (SKIP_IF_TRUE) skip((COUNT),(REASON)); else
+
+
+/**
+ Helper macro to skip a group of "big" tests. It is used in the following
+ manner:
+
+ @code
+ SKIP_BIG_TESTS(1)
+ {
+ ok(life_universe_and_everything() == 42, "The answer is CORRECT");
+ }
+ @endcode
+
+ @see skip_big_tests
+ */
+
+#define SKIP_BIG_TESTS(COUNT) \
+ if (skip_big_tests) skip((COUNT), "big test"); else
+
+
+/**
+ Print a diagnostics message.
+
+ @param fmt Diagnostics message in printf() format.
+ */
+
+void diag(char const *fmt, ...)
+ __attribute__((format(printf,1,2)));
+
+
+/**
+ Print a bail out message.
+
+ A bail out message can be issued when no further testing can be
+ done, e.g., when there are missing dependencies.
+
+ The test will exit with status 255. This function does not return.
+
+ @code
+ BAIL_OUT("Lost connection to server %s", server_name);
+ @endcode
+
+ @note A bail out message is printed if a signal that generates a
+ core is raised.
+
+ @param fmt Bail out message in printf() format.
+*/
+
+void BAIL_OUT(char const *fmt, ...)
+ __attribute__((noreturn, format(printf,1,2)));
+
+
+/**
+ Print summary report and return exit status.
+
+ This function will print a summary report of how many tests passed,
+ how many were skipped, and how many remains to do. The function
+ should be called after all tests are executed in the following
+ manner:
+
+ @code
+ return exit_status();
+ @endcode
+
+ @returns @c EXIT_SUCCESS if all tests passed, @c EXIT_FAILURE if
+ one or more tests failed.
+ */
+
+int exit_status(void);
+
+
+/**
+ Skip entire test suite.
+
+ To skip the entire test suite, use this function. It will
+ automatically call exit(), so there is no need to have checks
+ around it.
+ */
+
+void skip_all(char const *reason, ...)
+ __attribute__((noreturn, format(printf, 1, 2)));
+
+
+/**
+ Start section of tests that are not yet ready.
+
+ To start a section of tests that are not ready and are expected to
+ fail, use this function and todo_end() in the following manner:
+
+ @code
+ todo_start("Not ready yet");
+ ok(is_rocketeering(duck), "Rocket-propelled ducks");
+ ok(is_kamikaze(duck), "Kamikaze ducks");
+ todo_end();
+ @endcode
+
+ @see todo_end
+
+ @note
+ It is not possible to nest todo sections.
+
+ @param message Message that will be printed before the todo tests.
+*/
+
+void todo_start(char const *message, ...)
+ __attribute__((format(printf, 1, 2)));
+
+
+/**
+ End a section of tests that are not yet ready.
+*/
+
+void todo_end();
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TAP_H */
diff --git a/libmariadb/win-iconv/iconv.h b/libmariadb/win-iconv/iconv.h
new file mode 100644
index 00000000..eca8070b
--- /dev/null
+++ b/libmariadb/win-iconv/iconv.h
@@ -0,0 +1,14 @@
+#ifndef _LIBICONV_H
+#define _LIBICONV_H
+#include <stddef.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef void* iconv_t;
+iconv_t iconv_open(const char *tocode, const char *fromcode);
+int iconv_close(iconv_t cd);
+size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+#ifdef __cplusplus
+}
+#endif
+#endif//_LIBICONV_H \ No newline at end of file
diff --git a/libmariadb/win-iconv/mlang.h b/libmariadb/win-iconv/mlang.h
new file mode 100644
index 00000000..5cbf779c
--- /dev/null
+++ b/libmariadb/win-iconv/mlang.h
@@ -0,0 +1,54 @@
+HRESULT WINAPI ConvertINetString(
+ LPDWORD lpdwMode,
+ DWORD dwSrcEncoding,
+ DWORD dwDstEncoding,
+ LPCSTR lpSrcStr,
+ LPINT lpnSrcSize,
+ LPBYTE lpDstStr,
+ LPINT lpnDstSize
+);
+
+HRESULT WINAPI ConvertINetMultiByteToUnicode(
+ LPDWORD lpdwMode,
+ DWORD dwSrcEncoding,
+ LPCSTR lpSrcStr,
+ LPINT lpnMultiCharCount,
+ LPWSTR lpDstStr,
+ LPINT lpnWideCharCount
+);
+
+HRESULT WINAPI ConvertINetUnicodeToMultiByte(
+ LPDWORD lpdwMode,
+ DWORD dwEncoding,
+ LPCWSTR lpSrcStr,
+ LPINT lpnWideCharCount,
+ LPSTR lpDstStr,
+ LPINT lpnMultiCharCount
+);
+
+HRESULT WINAPI IsConvertINetStringAvailable(
+ DWORD dwSrcEncoding,
+ DWORD dwDstEncoding
+);
+
+HRESULT WINAPI LcidToRfc1766A(
+ LCID Locale,
+ LPSTR pszRfc1766,
+ int nChar
+);
+
+HRESULT WINAPI LcidToRfc1766W(
+ LCID Locale,
+ LPWSTR pszRfc1766,
+ int nChar
+);
+
+HRESULT WINAPI Rfc1766ToLcidA(
+ LCID *pLocale,
+ LPSTR pszRfc1766
+);
+
+HRESULT WINAPI Rfc1766ToLcidW(
+ LCID *pLocale,
+ LPWSTR pszRfc1766
+);
diff --git a/libmariadb/win-iconv/win_iconv.c b/libmariadb/win-iconv/win_iconv.c
new file mode 100644
index 00000000..84bb43b0
--- /dev/null
+++ b/libmariadb/win-iconv/win_iconv.c
@@ -0,0 +1,2051 @@
+/*
+ * iconv implementation using Win32 API to convert.
+ *
+ * This file is placed in the public domain.
+ */
+
+/* for WC_NO_BEST_FIT_CHARS */
+#ifndef WINVER
+# define WINVER 0x0500
+#endif
+
+#define STRICT
+#include <windows.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef __GNUC__
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+
+/* WORKAROUND: */
+#ifndef UNDER_CE
+#define GetProcAddressA GetProcAddress
+#endif
+
+#if 0
+# define MAKE_EXE
+# define MAKE_DLL
+# define USE_LIBICONV_DLL
+#endif
+
+#if !defined(DEFAULT_LIBICONV_DLL)
+# define DEFAULT_LIBICONV_DLL ""
+#endif
+
+#define MB_CHAR_MAX 16
+
+#define UNICODE_MODE_BOM_DONE 1
+#define UNICODE_MODE_SWAPPED 2
+
+#define FLAG_USE_BOM 1
+#define FLAG_TRANSLIT 2 /* //TRANSLIT */
+#define FLAG_IGNORE 4 /* //IGNORE */
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+
+typedef void* iconv_t;
+
+iconv_t iconv_open(const char *tocode, const char *fromcode);
+int iconv_close(iconv_t cd);
+size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+
+/* libiconv interface for vim */
+#if defined(MAKE_DLL)
+int
+iconvctl (iconv_t cd, int request, void* argument)
+{
+ /* not supported */
+ return 0;
+}
+#endif
+
+typedef struct compat_t compat_t;
+typedef struct csconv_t csconv_t;
+typedef struct rec_iconv_t rec_iconv_t;
+
+typedef iconv_t (*f_iconv_open)(const char *tocode, const char *fromcode);
+typedef int (*f_iconv_close)(iconv_t cd);
+typedef size_t (*f_iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+typedef int* (*f_errno)(void);
+typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
+typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
+typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize);
+typedef int (*f_flush)(csconv_t *cv, uchar *buf, int bufsize);
+
+#define COMPAT_IN 1
+#define COMPAT_OUT 2
+
+/* unicode mapping for compatibility with other conversion table. */
+struct compat_t {
+ uint in;
+ uint out;
+ uint flag;
+};
+
+struct csconv_t {
+ int codepage;
+ int flags;
+ f_mbtowc mbtowc;
+ f_wctomb wctomb;
+ f_mblen mblen;
+ f_flush flush;
+ DWORD mode;
+ compat_t *compat;
+};
+
+struct rec_iconv_t {
+ iconv_t cd;
+ f_iconv_close iconv_close;
+ f_iconv iconv;
+ f_errno _errno;
+ csconv_t from;
+ csconv_t to;
+#if defined(USE_LIBICONV_DLL)
+ HMODULE hlibiconv;
+#endif
+};
+
+static int win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode);
+static int win_iconv_close(iconv_t cd);
+static size_t win_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+
+static int load_mlang(void);
+static int make_csconv(const char *name, csconv_t *cv);
+static int name_to_codepage(const char *name);
+static uint utf16_to_ucs4(const ushort *wbuf);
+static void ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize);
+static int mbtowc_flags(int codepage);
+static int must_use_null_useddefaultchar(int codepage);
+static char *strrstr(const char *str, const char *token);
+static char *xstrndup(const char *s, size_t n);
+static int seterror(int err);
+
+#if defined(USE_LIBICONV_DLL)
+static int libiconv_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode);
+static PVOID MyImageDirectoryEntryToData(LPVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size);
+static HMODULE find_imported_module_by_funcname(HMODULE hModule, const char *funcname);
+
+static HMODULE hwiniconv;
+#endif
+
+static int sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
+static int dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
+static int mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
+static int utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize);
+static int eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize);
+
+static int kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
+static int kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
+static int mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
+static int mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
+static int utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
+static int utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
+static int utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
+static int utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
+static int iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
+static int iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
+static int iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize);
+
+static struct {
+ int codepage;
+ const char *name;
+} codepage_alias[] = {
+ {65001, "CP65001"},
+ {65001, "UTF8"},
+ {65001, "UTF-8"},
+
+ {1200, "CP1200"},
+ {1200, "UTF16LE"},
+ {1200, "UTF-16LE"},
+ {1200, "UCS2LE"},
+ {1200, "UCS-2LE"},
+
+ {1201, "CP1201"},
+ {1201, "UTF16BE"},
+ {1201, "UTF-16BE"},
+ {1201, "UCS2BE"},
+ {1201, "UCS-2BE"},
+ {1201, "unicodeFFFE"},
+
+ {12000, "CP12000"},
+ {12000, "UTF32LE"},
+ {12000, "UTF-32LE"},
+ {12000, "UCS4LE"},
+ {12000, "UCS-4LE"},
+
+ {12001, "CP12001"},
+ {12001, "UTF32BE"},
+ {12001, "UTF-32BE"},
+ {12001, "UCS4BE"},
+ {12001, "UCS-4BE"},
+
+#ifndef GLIB_COMPILATION
+ /*
+ * Default is big endian.
+ * See rfc2781 4.3 Interpreting text labelled as UTF-16.
+ */
+ {1201, "UTF16"},
+ {1201, "UTF-16"},
+ {1201, "UCS2"},
+ {1201, "UCS-2"},
+ {12001, "UTF32"},
+ {12001, "UTF-32"},
+ {12001, "UCS-4"},
+ {12001, "UCS4"},
+#else
+ /* Default is little endian, because the platform is */
+ {1200, "UTF16"},
+ {1200, "UTF-16"},
+ {1200, "UCS2"},
+ {1200, "UCS-2"},
+ {12000, "UTF32"},
+ {12000, "UTF-32"},
+ {12000, "UCS4"},
+ {12000, "UCS-4"},
+#endif
+
+ /* copy from libiconv `iconv -l` */
+ /* !IsValidCodePage(367) */
+ {20127, "ANSI_X3.4-1968"},
+ {20127, "ANSI_X3.4-1986"},
+ {20127, "ASCII"},
+ {20127, "CP367"},
+ {20127, "IBM367"},
+ {20127, "ISO-IR-6"},
+ {20127, "ISO646-US"},
+ {20127, "ISO_646.IRV:1991"},
+ {20127, "US"},
+ {20127, "US-ASCII"},
+ {20127, "CSASCII"},
+
+ /* !IsValidCodePage(819) */
+ {1252, "CP819"},
+ {1252, "IBM819"},
+ {28591, "ISO-8859-1"},
+ {28591, "ISO-IR-100"},
+ {28591, "ISO8859-1"},
+ {28591, "ISO_8859-1"},
+ {28591, "ISO_8859-1:1987"},
+ {28591, "L1"},
+ {28591, "LATIN1"},
+ {28591, "CSISOLATIN1"},
+
+ {1250, "CP1250"},
+ {1250, "MS-EE"},
+ {1250, "WINDOWS-1250"},
+
+ {1251, "CP1251"},
+ {1251, "MS-CYRL"},
+ {1251, "WINDOWS-1251"},
+
+ {1252, "CP1252"},
+ {1252, "MS-ANSI"},
+ {1252, "WINDOWS-1252"},
+
+ {1253, "CP1253"},
+ {1253, "MS-GREEK"},
+ {1253, "WINDOWS-1253"},
+
+ {1254, "CP1254"},
+ {1254, "MS-TURK"},
+ {1254, "WINDOWS-1254"},
+
+ {1255, "CP1255"},
+ {1255, "MS-HEBR"},
+ {1255, "WINDOWS-1255"},
+
+ {1256, "CP1256"},
+ {1256, "MS-ARAB"},
+ {1256, "WINDOWS-1256"},
+
+ {1257, "CP1257"},
+ {1257, "WINBALTRIM"},
+ {1257, "WINDOWS-1257"},
+
+ {1258, "CP1258"},
+ {1258, "WINDOWS-1258"},
+
+ {850, "850"},
+ {850, "CP850"},
+ {850, "IBM850"},
+ {850, "CSPC850MULTILINGUAL"},
+
+ /* !IsValidCodePage(862) */
+ {862, "862"},
+ {862, "CP862"},
+ {862, "IBM862"},
+ {862, "CSPC862LATINHEBREW"},
+
+ {866, "866"},
+ {866, "CP866"},
+ {866, "IBM866"},
+ {866, "CSIBM866"},
+
+ /* !IsValidCodePage(154) */
+ {154, "CP154"},
+ {154, "CYRILLIC-ASIAN"},
+ {154, "PT154"},
+ {154, "PTCP154"},
+ {154, "CSPTCP154"},
+
+ /* !IsValidCodePage(1133) */
+ {1133, "CP1133"},
+ {1133, "IBM-CP1133"},
+
+ {874, "CP874"},
+ {874, "WINDOWS-874"},
+
+ /* !IsValidCodePage(51932) */
+ {51932, "CP51932"},
+ {51932, "MS51932"},
+ {51932, "WINDOWS-51932"},
+ {51932, "EUC-JP"},
+
+ {932, "CP932"},
+ {932, "MS932"},
+ {932, "SHIFFT_JIS"},
+ {932, "SHIFFT_JIS-MS"},
+ {932, "SJIS"},
+ {932, "SJIS-MS"},
+ {932, "SJIS-OPEN"},
+ {932, "SJIS-WIN"},
+ {932, "WINDOWS-31J"},
+ {932, "WINDOWS-932"},
+ {932, "CSWINDOWS31J"},
+
+ {50221, "CP50221"},
+ {50221, "ISO-2022-JP"},
+ {50221, "ISO-2022-JP-MS"},
+ {50221, "ISO2022-JP"},
+ {50221, "ISO2022-JP-MS"},
+ {50221, "MS50221"},
+ {50221, "WINDOWS-50221"},
+
+ {936, "CP936"},
+ {936, "GBK"},
+ {936, "MS936"},
+ {936, "WINDOWS-936"},
+
+ {950, "CP950"},
+ {950, "BIG5"},
+ {950, "BIG5HKSCS"},
+ {950, "BIG5-HKSCS"},
+
+ {949, "CP949"},
+ {949, "UHC"},
+ {949, "EUC-KR"},
+
+ {1361, "CP1361"},
+ {1361, "JOHAB"},
+
+ {437, "437"},
+ {437, "CP437"},
+ {437, "IBM437"},
+ {437, "CSPC8CODEPAGE437"},
+
+ {737, "CP737"},
+
+ {775, "CP775"},
+ {775, "IBM775"},
+ {775, "CSPC775BALTIC"},
+
+ {852, "852"},
+ {852, "CP852"},
+ {852, "IBM852"},
+ {852, "CSPCP852"},
+
+ /* !IsValidCodePage(853) */
+ {853, "CP853"},
+
+ {855, "855"},
+ {855, "CP855"},
+ {855, "IBM855"},
+ {855, "CSIBM855"},
+
+ {857, "857"},
+ {857, "CP857"},
+ {857, "IBM857"},
+ {857, "CSIBM857"},
+
+ /* !IsValidCodePage(858) */
+ {858, "CP858"},
+
+ {860, "860"},
+ {860, "CP860"},
+ {860, "IBM860"},
+ {860, "CSIBM860"},
+
+ {861, "861"},
+ {861, "CP-IS"},
+ {861, "CP861"},
+ {861, "IBM861"},
+ {861, "CSIBM861"},
+
+ {863, "863"},
+ {863, "CP863"},
+ {863, "IBM863"},
+ {863, "CSIBM863"},
+
+ {864, "CP864"},
+ {864, "IBM864"},
+ {864, "CSIBM864"},
+
+ {865, "865"},
+ {865, "CP865"},
+ {865, "IBM865"},
+ {865, "CSIBM865"},
+
+ {869, "869"},
+ {869, "CP-GR"},
+ {869, "CP869"},
+ {869, "IBM869"},
+ {869, "CSIBM869"},
+
+ /* !IsValidCodePage(1152) */
+ {1125, "CP1125"},
+
+ /*
+ * Code Page Identifiers
+ * http://msdn2.microsoft.com/en-us/library/ms776446.aspx
+ */
+ {37, "IBM037"}, /* IBM EBCDIC US-Canada */
+ {437, "IBM437"}, /* OEM United States */
+ {500, "IBM500"}, /* IBM EBCDIC International */
+ {708, "ASMO-708"}, /* Arabic (ASMO 708) */
+ /* 709 Arabic (ASMO-449+, BCON V4) */
+ /* 710 Arabic - Transparent Arabic */
+ {720, "DOS-720"}, /* Arabic (Transparent ASMO); Arabic (DOS) */
+ {737, "ibm737"}, /* OEM Greek (formerly 437G); Greek (DOS) */
+ {775, "ibm775"}, /* OEM Baltic; Baltic (DOS) */
+ {850, "ibm850"}, /* OEM Multilingual Latin 1; Western European (DOS) */
+ {852, "ibm852"}, /* OEM Latin 2; Central European (DOS) */
+ {855, "IBM855"}, /* OEM Cyrillic (primarily Russian) */
+ {857, "ibm857"}, /* OEM Turkish; Turkish (DOS) */
+ {858, "IBM00858"}, /* OEM Multilingual Latin 1 + Euro symbol */
+ {860, "IBM860"}, /* OEM Portuguese; Portuguese (DOS) */
+ {861, "ibm861"}, /* OEM Icelandic; Icelandic (DOS) */
+ {862, "DOS-862"}, /* OEM Hebrew; Hebrew (DOS) */
+ {863, "IBM863"}, /* OEM French Canadian; French Canadian (DOS) */
+ {864, "IBM864"}, /* OEM Arabic; Arabic (864) */
+ {865, "IBM865"}, /* OEM Nordic; Nordic (DOS) */
+ {866, "cp866"}, /* OEM Russian; Cyrillic (DOS) */
+ {869, "ibm869"}, /* OEM Modern Greek; Greek, Modern (DOS) */
+ {870, "IBM870"}, /* IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 */
+ {874, "windows-874"}, /* ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) */
+ {875, "cp875"}, /* IBM EBCDIC Greek Modern */
+ {932, "shift_jis"}, /* ANSI/OEM Japanese; Japanese (Shift-JIS) */
+ {932, "shift-jis"}, /* alternative name for it */
+ {936, "gb2312"}, /* ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) */
+ {949, "ks_c_5601-1987"}, /* ANSI/OEM Korean (Unified Hangul Code) */
+ {950, "big5"}, /* ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) */
+ {950, "big5hkscs"}, /* ANSI/OEM Traditional Chinese (Hong Kong SAR); Chinese Traditional (Big5-HKSCS) */
+ {950, "big5-hkscs"}, /* alternative name for it */
+ {1026, "IBM1026"}, /* IBM EBCDIC Turkish (Latin 5) */
+ {1047, "IBM01047"}, /* IBM EBCDIC Latin 1/Open System */
+ {1140, "IBM01140"}, /* IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) */
+ {1141, "IBM01141"}, /* IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) */
+ {1142, "IBM01142"}, /* IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) */
+ {1143, "IBM01143"}, /* IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) */
+ {1144, "IBM01144"}, /* IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) */
+ {1145, "IBM01145"}, /* IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) */
+ {1146, "IBM01146"}, /* IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) */
+ {1147, "IBM01147"}, /* IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) */
+ {1148, "IBM01148"}, /* IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) */
+ {1149, "IBM01149"}, /* IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) */
+ {1250, "windows-1250"}, /* ANSI Central European; Central European (Windows) */
+ {1251, "windows-1251"}, /* ANSI Cyrillic; Cyrillic (Windows) */
+ {1252, "windows-1252"}, /* ANSI Latin 1; Western European (Windows) */
+ {1253, "windows-1253"}, /* ANSI Greek; Greek (Windows) */
+ {1254, "windows-1254"}, /* ANSI Turkish; Turkish (Windows) */
+ {1255, "windows-1255"}, /* ANSI Hebrew; Hebrew (Windows) */
+ {1256, "windows-1256"}, /* ANSI Arabic; Arabic (Windows) */
+ {1257, "windows-1257"}, /* ANSI Baltic; Baltic (Windows) */
+ {1258, "windows-1258"}, /* ANSI/OEM Vietnamese; Vietnamese (Windows) */
+ {1361, "Johab"}, /* Korean (Johab) */
+ {10000, "macintosh"}, /* MAC Roman; Western European (Mac) */
+ {10001, "x-mac-japanese"}, /* Japanese (Mac) */
+ {10002, "x-mac-chinesetrad"}, /* MAC Traditional Chinese (Big5); Chinese Traditional (Mac) */
+ {10003, "x-mac-korean"}, /* Korean (Mac) */
+ {10004, "x-mac-arabic"}, /* Arabic (Mac) */
+ {10005, "x-mac-hebrew"}, /* Hebrew (Mac) */
+ {10006, "x-mac-greek"}, /* Greek (Mac) */
+ {10007, "x-mac-cyrillic"}, /* Cyrillic (Mac) */
+ {10008, "x-mac-chinesesimp"}, /* MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) */
+ {10010, "x-mac-romanian"}, /* Romanian (Mac) */
+ {10017, "x-mac-ukrainian"}, /* Ukrainian (Mac) */
+ {10021, "x-mac-thai"}, /* Thai (Mac) */
+ {10029, "x-mac-ce"}, /* MAC Latin 2; Central European (Mac) */
+ {10079, "x-mac-icelandic"}, /* Icelandic (Mac) */
+ {10081, "x-mac-turkish"}, /* Turkish (Mac) */
+ {10082, "x-mac-croatian"}, /* Croatian (Mac) */
+ {20000, "x-Chinese_CNS"}, /* CNS Taiwan; Chinese Traditional (CNS) */
+ {20001, "x-cp20001"}, /* TCA Taiwan */
+ {20002, "x_Chinese-Eten"}, /* Eten Taiwan; Chinese Traditional (Eten) */
+ {20003, "x-cp20003"}, /* IBM5550 Taiwan */
+ {20004, "x-cp20004"}, /* TeleText Taiwan */
+ {20005, "x-cp20005"}, /* Wang Taiwan */
+ {20105, "x-IA5"}, /* IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) */
+ {20106, "x-IA5-German"}, /* IA5 German (7-bit) */
+ {20107, "x-IA5-Swedish"}, /* IA5 Swedish (7-bit) */
+ {20108, "x-IA5-Norwegian"}, /* IA5 Norwegian (7-bit) */
+ {20127, "us-ascii"}, /* US-ASCII (7-bit) */
+ {20261, "x-cp20261"}, /* T.61 */
+ {20269, "x-cp20269"}, /* ISO 6937 Non-Spacing Accent */
+ {20273, "IBM273"}, /* IBM EBCDIC Germany */
+ {20277, "IBM277"}, /* IBM EBCDIC Denmark-Norway */
+ {20278, "IBM278"}, /* IBM EBCDIC Finland-Sweden */
+ {20280, "IBM280"}, /* IBM EBCDIC Italy */
+ {20284, "IBM284"}, /* IBM EBCDIC Latin America-Spain */
+ {20285, "IBM285"}, /* IBM EBCDIC United Kingdom */
+ {20290, "IBM290"}, /* IBM EBCDIC Japanese Katakana Extended */
+ {20297, "IBM297"}, /* IBM EBCDIC France */
+ {20420, "IBM420"}, /* IBM EBCDIC Arabic */
+ {20423, "IBM423"}, /* IBM EBCDIC Greek */
+ {20424, "IBM424"}, /* IBM EBCDIC Hebrew */
+ {20833, "x-EBCDIC-KoreanExtended"}, /* IBM EBCDIC Korean Extended */
+ {20838, "IBM-Thai"}, /* IBM EBCDIC Thai */
+ {20866, "koi8-r"}, /* Russian (KOI8-R); Cyrillic (KOI8-R) */
+ {20871, "IBM871"}, /* IBM EBCDIC Icelandic */
+ {20880, "IBM880"}, /* IBM EBCDIC Cyrillic Russian */
+ {20905, "IBM905"}, /* IBM EBCDIC Turkish */
+ {20924, "IBM00924"}, /* IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) */
+ {20932, "EUC-JP"}, /* Japanese (JIS 0208-1990 and 0121-1990) */
+ {20936, "x-cp20936"}, /* Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) */
+ {20949, "x-cp20949"}, /* Korean Wansung */
+ {21025, "cp1025"}, /* IBM EBCDIC Cyrillic Serbian-Bulgarian */
+ /* 21027 (deprecated) */
+ {21866, "koi8-u"}, /* Ukrainian (KOI8-U); Cyrillic (KOI8-U) */
+ {28591, "iso-8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */
+ {28591, "iso8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */
+ {28592, "iso-8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */
+ {28592, "iso8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */
+ {28593, "iso-8859-3"}, /* ISO 8859-3 Latin 3 */
+ {28593, "iso8859-3"}, /* ISO 8859-3 Latin 3 */
+ {28594, "iso-8859-4"}, /* ISO 8859-4 Baltic */
+ {28594, "iso8859-4"}, /* ISO 8859-4 Baltic */
+ {28595, "iso-8859-5"}, /* ISO 8859-5 Cyrillic */
+ {28595, "iso8859-5"}, /* ISO 8859-5 Cyrillic */
+ {28596, "iso-8859-6"}, /* ISO 8859-6 Arabic */
+ {28596, "iso8859-6"}, /* ISO 8859-6 Arabic */
+ {28597, "iso-8859-7"}, /* ISO 8859-7 Greek */
+ {28597, "iso8859-7"}, /* ISO 8859-7 Greek */
+ {28598, "iso-8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */
+ {28598, "iso8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */
+ {28599, "iso-8859-9"}, /* ISO 8859-9 Turkish */
+ {28599, "iso8859-9"}, /* ISO 8859-9 Turkish */
+ {28603, "iso-8859-13"}, /* ISO 8859-13 Estonian */
+ {28603, "iso8859-13"}, /* ISO 8859-13 Estonian */
+ {28605, "iso-8859-15"}, /* ISO 8859-15 Latin 9 */
+ {28605, "iso8859-15"}, /* ISO 8859-15 Latin 9 */
+ {29001, "x-Europa"}, /* Europa 3 */
+ {38598, "iso-8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */
+ {38598, "iso8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */
+ {50220, "iso-2022-jp"}, /* ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) */
+ {50221, "csISO2022JP"}, /* ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) */
+ {50222, "iso-2022-jp"}, /* ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) */
+ {50225, "iso-2022-kr"}, /* ISO 2022 Korean */
+ {50225, "iso2022-kr"}, /* ISO 2022 Korean */
+ {50227, "x-cp50227"}, /* ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) */
+ /* 50229 ISO 2022 Traditional Chinese */
+ /* 50930 EBCDIC Japanese (Katakana) Extended */
+ /* 50931 EBCDIC US-Canada and Japanese */
+ /* 50933 EBCDIC Korean Extended and Korean */
+ /* 50935 EBCDIC Simplified Chinese Extended and Simplified Chinese */
+ /* 50936 EBCDIC Simplified Chinese */
+ /* 50937 EBCDIC US-Canada and Traditional Chinese */
+ /* 50939 EBCDIC Japanese (Latin) Extended and Japanese */
+ {51932, "euc-jp"}, /* EUC Japanese */
+ {51936, "EUC-CN"}, /* EUC Simplified Chinese; Chinese Simplified (EUC) */
+ {51949, "euc-kr"}, /* EUC Korean */
+ /* 51950 EUC Traditional Chinese */
+ {52936, "hz-gb-2312"}, /* HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) */
+ {54936, "GB18030"}, /* Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) */
+ {57002, "x-iscii-de"}, /* ISCII Devanagari */
+ {57003, "x-iscii-be"}, /* ISCII Bengali */
+ {57004, "x-iscii-ta"}, /* ISCII Tamil */
+ {57005, "x-iscii-te"}, /* ISCII Telugu */
+ {57006, "x-iscii-as"}, /* ISCII Assamese */
+ {57007, "x-iscii-or"}, /* ISCII Oriya */
+ {57008, "x-iscii-ka"}, /* ISCII Kannada */
+ {57009, "x-iscii-ma"}, /* ISCII Malayalam */
+ {57010, "x-iscii-gu"}, /* ISCII Gujarati */
+ {57011, "x-iscii-pa"}, /* ISCII Punjabi */
+
+ {0, NULL}
+};
+
+/*
+ * SJIS SHIFTJIS table CP932 table
+ * ---- --------------------------- --------------------------------
+ * 5C U+00A5 YEN SIGN U+005C REVERSE SOLIDUS
+ * 7E U+203E OVERLINE U+007E TILDE
+ * 815C U+2014 EM DASH U+2015 HORIZONTAL BAR
+ * 815F U+005C REVERSE SOLIDUS U+FF3C FULLWIDTH REVERSE SOLIDUS
+ * 8160 U+301C WAVE DASH U+FF5E FULLWIDTH TILDE
+ * 8161 U+2016 DOUBLE VERTICAL LINE U+2225 PARALLEL TO
+ * 817C U+2212 MINUS SIGN U+FF0D FULLWIDTH HYPHEN-MINUS
+ * 8191 U+00A2 CENT SIGN U+FFE0 FULLWIDTH CENT SIGN
+ * 8192 U+00A3 POUND SIGN U+FFE1 FULLWIDTH POUND SIGN
+ * 81CA U+00AC NOT SIGN U+FFE2 FULLWIDTH NOT SIGN
+ *
+ * EUC-JP and ISO-2022-JP should be compatible with CP932.
+ *
+ * Kernel and MLang have different Unicode mapping table. Make sure
+ * which API is used.
+ */
+static compat_t cp932_compat[] = {
+ {0x00A5, 0x005C, COMPAT_OUT},
+ {0x203E, 0x007E, COMPAT_OUT},
+ {0x2014, 0x2015, COMPAT_OUT},
+ {0x301C, 0xFF5E, COMPAT_OUT},
+ {0x2016, 0x2225, COMPAT_OUT},
+ {0x2212, 0xFF0D, COMPAT_OUT},
+ {0x00A2, 0xFFE0, COMPAT_OUT},
+ {0x00A3, 0xFFE1, COMPAT_OUT},
+ {0x00AC, 0xFFE2, COMPAT_OUT},
+ {0, 0, 0}
+};
+
+static compat_t cp20932_compat[] = {
+ {0x00A5, 0x005C, COMPAT_OUT},
+ {0x203E, 0x007E, COMPAT_OUT},
+ {0x2014, 0x2015, COMPAT_OUT},
+ {0xFF5E, 0x301C, COMPAT_OUT|COMPAT_IN},
+ {0x2225, 0x2016, COMPAT_OUT|COMPAT_IN},
+ {0xFF0D, 0x2212, COMPAT_OUT|COMPAT_IN},
+ {0xFFE0, 0x00A2, COMPAT_OUT|COMPAT_IN},
+ {0xFFE1, 0x00A3, COMPAT_OUT|COMPAT_IN},
+ {0xFFE2, 0x00AC, COMPAT_OUT|COMPAT_IN},
+ {0, 0, 0}
+};
+
+static compat_t *cp51932_compat = cp932_compat;
+
+/* cp20932_compat for kernel. cp932_compat for mlang. */
+static compat_t *cp5022x_compat = cp932_compat;
+
+typedef HRESULT (WINAPI *CONVERTINETSTRING)(
+ LPDWORD lpdwMode,
+ DWORD dwSrcEncoding,
+ DWORD dwDstEncoding,
+ LPCSTR lpSrcStr,
+ LPINT lpnSrcSize,
+ LPBYTE lpDstStr,
+ LPINT lpnDstSize
+);
+typedef HRESULT (WINAPI *CONVERTINETMULTIBYTETOUNICODE)(
+ LPDWORD lpdwMode,
+ DWORD dwSrcEncoding,
+ LPCSTR lpSrcStr,
+ LPINT lpnMultiCharCount,
+ LPWSTR lpDstStr,
+ LPINT lpnWideCharCount
+);
+typedef HRESULT (WINAPI *CONVERTINETUNICODETOMULTIBYTE)(
+ LPDWORD lpdwMode,
+ DWORD dwEncoding,
+ LPCWSTR lpSrcStr,
+ LPINT lpnWideCharCount,
+ LPSTR lpDstStr,
+ LPINT lpnMultiCharCount
+);
+typedef HRESULT (WINAPI *ISCONVERTINETSTRINGAVAILABLE)(
+ DWORD dwSrcEncoding,
+ DWORD dwDstEncoding
+);
+typedef HRESULT (WINAPI *LCIDTORFC1766A)(
+ LCID Locale,
+ LPSTR pszRfc1766,
+ int nChar
+);
+typedef HRESULT (WINAPI *LCIDTORFC1766W)(
+ LCID Locale,
+ LPWSTR pszRfc1766,
+ int nChar
+);
+typedef HRESULT (WINAPI *RFC1766TOLCIDA)(
+ LCID *pLocale,
+ LPSTR pszRfc1766
+);
+typedef HRESULT (WINAPI *RFC1766TOLCIDW)(
+ LCID *pLocale,
+ LPWSTR pszRfc1766
+);
+static CONVERTINETSTRING ConvertINetString;
+static CONVERTINETMULTIBYTETOUNICODE ConvertINetMultiByteToUnicode;
+static CONVERTINETUNICODETOMULTIBYTE ConvertINetUnicodeToMultiByte;
+static ISCONVERTINETSTRINGAVAILABLE IsConvertINetStringAvailable;
+static LCIDTORFC1766A LcidToRfc1766A;
+static RFC1766TOLCIDA Rfc1766ToLcidA;
+
+static int
+load_mlang(void)
+{
+ HMODULE h;
+ if (ConvertINetString != NULL)
+ return TRUE;
+ h = LoadLibrary(TEXT("mlang.dll"));
+ if (!h)
+ return FALSE;
+ ConvertINetString = (CONVERTINETSTRING)GetProcAddressA(h, "ConvertINetString");
+ ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddressA(h, "ConvertINetMultiByteToUnicode");
+ ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddressA(h, "ConvertINetUnicodeToMultiByte");
+ IsConvertINetStringAvailable = (ISCONVERTINETSTRINGAVAILABLE)GetProcAddressA(h, "IsConvertINetStringAvailable");
+ LcidToRfc1766A = (LCIDTORFC1766A)GetProcAddressA(h, "LcidToRfc1766A");
+ Rfc1766ToLcidA = (RFC1766TOLCIDA)GetProcAddressA(h, "Rfc1766ToLcidA");
+ return TRUE;
+}
+
+iconv_t
+iconv_open(const char *tocode, const char *fromcode)
+{
+ rec_iconv_t *cd;
+
+ cd = (rec_iconv_t *)calloc(1, sizeof(rec_iconv_t));
+ if (cd == NULL)
+ return (iconv_t)(-1);
+
+#if defined(USE_LIBICONV_DLL)
+ errno = 0;
+ if (libiconv_iconv_open(cd, tocode, fromcode))
+ return (iconv_t)cd;
+#endif
+
+ /* reset the errno to prevent reporting wrong error code.
+ * 0 for unsorted error. */
+ errno = 0;
+ if (win_iconv_open(cd, tocode, fromcode))
+ return (iconv_t)cd;
+
+ free(cd);
+
+ return (iconv_t)(-1);
+}
+
+int
+iconv_close(iconv_t _cd)
+{
+ rec_iconv_t *cd = (rec_iconv_t *)_cd;
+ int r = cd->iconv_close(cd->cd);
+ int e = *(cd->_errno());
+#if defined(USE_LIBICONV_DLL)
+ if (cd->hlibiconv != NULL)
+ FreeLibrary(cd->hlibiconv);
+#endif
+ free(cd);
+ errno = e;
+ return r;
+}
+
+size_t
+iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
+{
+ rec_iconv_t *cd = (rec_iconv_t *)_cd;
+ size_t r = cd->iconv(cd->cd, inbuf, inbytesleft, outbuf, outbytesleft);
+ errno = *(cd->_errno());
+ return r;
+}
+
+static int
+win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode)
+{
+ if (!make_csconv(fromcode, &cd->from) || !make_csconv(tocode, &cd->to))
+ return FALSE;
+ cd->iconv_close = win_iconv_close;
+ cd->iconv = win_iconv;
+ cd->_errno = _errno;
+ cd->cd = (iconv_t)cd;
+ return TRUE;
+}
+
+static int
+win_iconv_close(iconv_t cd UNUSED)
+{
+ return 0;
+}
+
+static size_t
+win_iconv(iconv_t _cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
+{
+ rec_iconv_t *cd = (rec_iconv_t *)_cd;
+ ushort wbuf[MB_CHAR_MAX]; /* enough room for one character */
+ int insize;
+ int outsize;
+ int wsize;
+ DWORD frommode;
+ DWORD tomode;
+ uint wc;
+ compat_t *cp;
+ int i;
+
+ if (inbuf == NULL || *inbuf == NULL)
+ {
+ if (outbuf != NULL && *outbuf != NULL && cd->to.flush != NULL)
+ {
+ tomode = cd->to.mode;
+ outsize = cd->to.flush(&cd->to, (uchar *)*outbuf, (int)*outbytesleft);
+ if (outsize == -1)
+ {
+ if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG)
+ {
+ outsize = 0;
+ }
+ else
+ {
+ cd->to.mode = tomode;
+ return (size_t)(-1);
+ }
+ }
+ *outbuf += outsize;
+ *outbytesleft -= outsize;
+ }
+ cd->from.mode = 0;
+ cd->to.mode = 0;
+ return 0;
+ }
+
+ while (*inbytesleft != 0)
+ {
+ frommode = cd->from.mode;
+ tomode = cd->to.mode;
+ wsize = MB_CHAR_MAX;
+
+ insize = cd->from.mbtowc(&cd->from, (const uchar *)*inbuf, (int)*inbytesleft, wbuf, &wsize);
+ if (insize == -1)
+ {
+ if (cd->to.flags & FLAG_IGNORE)
+ {
+ cd->from.mode = frommode;
+ insize = 1;
+ wsize = 0;
+ }
+ else
+ {
+ cd->from.mode = frommode;
+ return (size_t)(-1);
+ }
+ }
+
+ if (wsize == 0)
+ {
+ *inbuf += insize;
+ *inbytesleft -= insize;
+ continue;
+ }
+
+ if (cd->from.compat != NULL)
+ {
+ wc = utf16_to_ucs4(wbuf);
+ cp = cd->from.compat;
+ for (i = 0; cp[i].in != 0; ++i)
+ {
+ if ((cp[i].flag & COMPAT_IN) && cp[i].out == wc)
+ {
+ ucs4_to_utf16(cp[i].in, wbuf, &wsize);
+ break;
+ }
+ }
+ }
+
+ if (cd->to.compat != NULL)
+ {
+ wc = utf16_to_ucs4(wbuf);
+ cp = cd->to.compat;
+ for (i = 0; cp[i].in != 0; ++i)
+ {
+ if ((cp[i].flag & COMPAT_OUT) && cp[i].in == wc)
+ {
+ ucs4_to_utf16(cp[i].out, wbuf, &wsize);
+ break;
+ }
+ }
+ }
+
+ outsize = cd->to.wctomb(&cd->to, wbuf, wsize, (uchar *)*outbuf, (int)*outbytesleft);
+ if (outsize == -1)
+ {
+ if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG)
+ {
+ cd->to.mode = tomode;
+ outsize = 0;
+ }
+ else
+ {
+ cd->from.mode = frommode;
+ cd->to.mode = tomode;
+ return (size_t)(-1);
+ }
+ }
+
+ *inbuf += insize;
+ *outbuf += outsize;
+ *inbytesleft -= insize;
+ *outbytesleft -= outsize;
+ }
+
+ return 0;
+}
+
+static int
+make_csconv(const char *_name, csconv_t *cv)
+{
+ CPINFO cpinfo;
+ int use_compat = TRUE;
+ int flag = 0;
+ char *name;
+ char *p;
+
+ name = xstrndup(_name, strlen(_name));
+ if (name == NULL)
+ return FALSE;
+
+ /* check for option "enc_name//opt1//opt2" */
+ while ((p = strrstr(name, "//")) != NULL)
+ {
+ if (_stricmp(p + 2, "nocompat") == 0)
+ use_compat = FALSE;
+ else if (_stricmp(p + 2, "translit") == 0)
+ flag |= FLAG_TRANSLIT;
+ else if (_stricmp(p + 2, "ignore") == 0)
+ flag |= FLAG_IGNORE;
+ *p = 0;
+ }
+
+ cv->mode = 0;
+ cv->flags = flag;
+ cv->mblen = NULL;
+ cv->flush = NULL;
+ cv->compat = NULL;
+ cv->codepage = name_to_codepage(name);
+ if (cv->codepage == 1200 || cv->codepage == 1201)
+ {
+ cv->mbtowc = utf16_mbtowc;
+ cv->wctomb = utf16_wctomb;
+ if (_stricmp(name, "UTF-16") == 0 || _stricmp(name, "UTF16") == 0 ||
+ _stricmp(name, "UCS-2") == 0 || _stricmp(name, "UCS2") == 0)
+ cv->flags |= FLAG_USE_BOM;
+ }
+ else if (cv->codepage == 12000 || cv->codepage == 12001)
+ {
+ cv->mbtowc = utf32_mbtowc;
+ cv->wctomb = utf32_wctomb;
+ if (_stricmp(name, "UTF-32") == 0 || _stricmp(name, "UTF32") == 0 ||
+ _stricmp(name, "UCS-4") == 0 || _stricmp(name, "UCS4") == 0)
+ cv->flags |= FLAG_USE_BOM;
+ }
+ else if (cv->codepage == 65001)
+ {
+ cv->mbtowc = kernel_mbtowc;
+ cv->wctomb = kernel_wctomb;
+ cv->mblen = utf8_mblen;
+ }
+ else if ((cv->codepage == 50220 || cv->codepage == 50221 || cv->codepage == 50222) && load_mlang())
+ {
+ cv->mbtowc = iso2022jp_mbtowc;
+ cv->wctomb = iso2022jp_wctomb;
+ cv->flush = iso2022jp_flush;
+ }
+ else if (cv->codepage == 51932 && load_mlang())
+ {
+ cv->mbtowc = mlang_mbtowc;
+ cv->wctomb = mlang_wctomb;
+ cv->mblen = eucjp_mblen;
+ }
+ else if (IsValidCodePage(cv->codepage)
+ && GetCPInfo(cv->codepage, &cpinfo) != 0)
+ {
+ cv->mbtowc = kernel_mbtowc;
+ cv->wctomb = kernel_wctomb;
+ if (cpinfo.MaxCharSize == 1)
+ cv->mblen = sbcs_mblen;
+ else if (cpinfo.MaxCharSize == 2)
+ cv->mblen = dbcs_mblen;
+ else
+ cv->mblen = mbcs_mblen;
+ }
+ else
+ {
+ /* not supported */
+ free(name);
+ errno = EINVAL;
+ return FALSE;
+ }
+
+ if (use_compat)
+ {
+ switch (cv->codepage)
+ {
+ case 932: cv->compat = cp932_compat; break;
+ case 20932: cv->compat = cp20932_compat; break;
+ case 51932: cv->compat = cp51932_compat; break;
+ case 50220: case 50221: case 50222: cv->compat = cp5022x_compat; break;
+ }
+ }
+
+ free(name);
+
+ return TRUE;
+}
+
+static int
+name_to_codepage(const char *name)
+{
+ int i;
+
+ if (*name == '\0' ||
+ strcmp(name, "char") == 0)
+ return GetACP();
+ else if (strcmp(name, "wchar_t") == 0)
+ return 1200;
+ else if (_strnicmp(name, "cp", 2) == 0)
+ return atoi(name + 2); /* CP123 */
+ else if ('0' <= name[0] && name[0] <= '9')
+ return atoi(name); /* 123 */
+ else if (_strnicmp(name, "xx", 2) == 0)
+ return atoi(name + 2); /* XX123 for debug */
+
+ for (i = 0; codepage_alias[i].name != NULL; ++i)
+ if (_stricmp(name, codepage_alias[i].name) == 0)
+ return codepage_alias[i].codepage;
+ return -1;
+}
+
+/*
+ * http://www.faqs.org/rfcs/rfc2781.html
+ */
+static uint
+utf16_to_ucs4(const ushort *wbuf)
+{
+ uint wc = wbuf[0];
+ if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF)
+ wc = ((wbuf[0] & 0x3FF) << 10) + (wbuf[1] & 0x3FF) + 0x10000;
+ return wc;
+}
+
+static void
+ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize)
+{
+ if (wc < 0x10000)
+ {
+ wbuf[0] = wc;
+ *wbufsize = 1;
+ }
+ else
+ {
+ wc -= 0x10000;
+ wbuf[0] = 0xD800 | ((wc >> 10) & 0x3FF);
+ wbuf[1] = 0xDC00 | (wc & 0x3FF);
+ *wbufsize = 2;
+ }
+}
+
+/*
+ * Check if codepage is one of those for which the dwFlags parameter
+ * to MultiByteToWideChar() must be zero. Return zero or
+ * MB_ERR_INVALID_CHARS. The docs in Platform SDK for for Windows
+ * Server 2003 R2 claims that also codepage 65001 is one of these, but
+ * that doesn't seem to be the case. The MSDN docs for MSVS2008 leave
+ * out 65001 (UTF-8), and that indeed seems to be the case on XP, it
+ * works fine to pass MB_ERR_INVALID_CHARS in dwFlags when converting
+ * from UTF-8.
+ */
+static int
+mbtowc_flags(int codepage)
+{
+ return (codepage == 50220 || codepage == 50221 ||
+ codepage == 50222 || codepage == 50225 ||
+ codepage == 50227 || codepage == 50229 ||
+ codepage == 52936 || codepage == 54936 ||
+ (codepage >= 57002 && codepage <= 57011) ||
+ codepage == 65000 || codepage == 42) ? 0 : MB_ERR_INVALID_CHARS;
+}
+
+/*
+ * Check if codepage is one those for which the lpUsedDefaultChar
+ * parameter to WideCharToMultiByte() must be NULL. The docs in
+ * Platform SDK for for Windows Server 2003 R2 claims that this is the
+ * list below, while the MSDN docs for MSVS2008 claim that it is only
+ * for 65000 (UTF-7) and 65001 (UTF-8). This time the earlier Platform
+ * SDK seems to be correct, at least for XP.
+ */
+static int
+must_use_null_useddefaultchar(int codepage)
+{
+ return (codepage == 65000 || codepage == 65001 ||
+ codepage == 50220 || codepage == 50221 ||
+ codepage == 50222 || codepage == 50225 ||
+ codepage == 50227 || codepage == 50229 ||
+ codepage == 52936 || codepage == 54936 ||
+ (codepage >= 57002 && codepage <= 57011) ||
+ codepage == 42);
+}
+
+static char *
+strrstr(const char *str, const char *token)
+{
+ size_t len = strlen(token);
+ const char *p = str + strlen(str);
+
+ while (str <= --p)
+ if (p[0] == token[0] && strncmp(p, token, len) == 0)
+ return (char *)p;
+ return NULL;
+}
+
+static char *
+xstrndup(const char *s, size_t n)
+{
+ char *p;
+
+ p = (char *)malloc(n + 1);
+ if (p == NULL)
+ return NULL;
+ memcpy(p, s, n);
+ p[n] = '\0';
+ return p;
+}
+
+static int
+seterror(int err)
+{
+ errno = err;
+ return -1;
+}
+
+#if defined(USE_LIBICONV_DLL)
+static int
+libiconv_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode)
+{
+ HMODULE hlibiconv = NULL;
+ HMODULE hmsvcrt = NULL;
+ char *dllname;
+ const char *p;
+ const char *e;
+ f_iconv_open _iconv_open;
+
+ /*
+ * always try to load dll, so that we can switch dll in runtime.
+ */
+
+ /* XXX: getenv() can't get variable set by SetEnvironmentVariable() */
+ p = getenv("WINICONV_LIBICONV_DLL");
+ if (p == NULL)
+ p = DEFAULT_LIBICONV_DLL;
+ /* parse comma separated value */
+ for ( ; *p != 0; p = (*e == ',') ? e + 1 : e)
+ {
+ e = strchr(p, ',');
+ if (p == e)
+ continue;
+ else if (e == NULL)
+ e = p + strlen(p);
+ dllname = xstrndup(p, e - p);
+ if (dllname == NULL)
+ return FALSE;
+ hlibiconv = LoadLibraryA(dllname);
+ free(dllname);
+ if (hlibiconv != NULL)
+ {
+ if (hlibiconv == hwiniconv)
+ {
+ FreeLibrary(hlibiconv);
+ hlibiconv = NULL;
+ continue;
+ }
+ break;
+ }
+ }
+
+ if (hlibiconv == NULL)
+ goto failed;
+
+ hmsvcrt = find_imported_module_by_funcname(hlibiconv, "_errno");
+ if (hmsvcrt == NULL)
+ goto failed;
+
+ _iconv_open = (f_iconv_open)GetProcAddressA(hlibiconv, "libiconv_open");
+ if (_iconv_open == NULL)
+ _iconv_open = (f_iconv_open)GetProcAddressA(hlibiconv, "iconv_open");
+ cd->iconv_close = (f_iconv_close)GetProcAddressA(hlibiconv, "libiconv_close");
+ if (cd->iconv_close == NULL)
+ cd->iconv_close = (f_iconv_close)GetProcAddressA(hlibiconv, "iconv_close");
+ cd->iconv = (f_iconv)GetProcAddressA(hlibiconv, "libiconv");
+ if (cd->iconv == NULL)
+ cd->iconv = (f_iconv)GetProcAddressA(hlibiconv, "iconv");
+ cd->_errno = (f_errno)GetProcAddressA(hmsvcrt, "_errno");
+ if (_iconv_open == NULL || cd->iconv_close == NULL
+ || cd->iconv == NULL || cd->_errno == NULL)
+ goto failed;
+
+ cd->cd = _iconv_open(tocode, fromcode);
+ if (cd->cd == (iconv_t)(-1))
+ goto failed;
+
+ cd->hlibiconv = hlibiconv;
+ return TRUE;
+
+failed:
+ if (hlibiconv != NULL)
+ FreeLibrary(hlibiconv);
+ /* do not free hmsvcrt which is obtained by GetModuleHandle() */
+ return FALSE;
+}
+
+/*
+ * Reference:
+ * http://forums.belution.com/ja/vc/000/234/78s.shtml
+ * http://nienie.com/~masapico/api_ImageDirectoryEntryToData.html
+ *
+ * The formal way is
+ * imagehlp.h or dbghelp.h
+ * imagehlp.lib or dbghelp.lib
+ * ImageDirectoryEntryToData()
+ */
+#define TO_DOS_HEADER(base) ((PIMAGE_DOS_HEADER)(base))
+#define TO_NT_HEADERS(base) ((PIMAGE_NT_HEADERS)((LPBYTE)(base) + TO_DOS_HEADER(base)->e_lfanew))
+static PVOID
+MyImageDirectoryEntryToData(LPVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size)
+{
+ /* TODO: MappedAsImage? */
+ PIMAGE_DATA_DIRECTORY p;
+ p = TO_NT_HEADERS(Base)->OptionalHeader.DataDirectory + DirectoryEntry;
+ if (p->VirtualAddress == 0) {
+ *Size = 0;
+ return NULL;
+ }
+ *Size = p->Size;
+ return (PVOID)((LPBYTE)Base + p->VirtualAddress);
+}
+
+static HMODULE
+find_imported_module_by_funcname(HMODULE hModule, const char *funcname)
+{
+ DWORD_PTR Base;
+ ULONG Size;
+ PIMAGE_IMPORT_DESCRIPTOR Imp;
+ PIMAGE_THUNK_DATA Name; /* Import Name Table */
+ PIMAGE_IMPORT_BY_NAME ImpName;
+
+ Base = (DWORD_PTR)hModule;
+ Imp = (PIMAGE_IMPORT_DESCRIPTOR)MyImageDirectoryEntryToData(
+ (LPVOID)Base,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_IMPORT,
+ &Size);
+ if (Imp == NULL)
+ return NULL;
+ for ( ; Imp->OriginalFirstThunk != 0; ++Imp)
+ {
+ Name = (PIMAGE_THUNK_DATA)(Base + Imp->OriginalFirstThunk);
+ for ( ; Name->u1.Ordinal != 0; ++Name)
+ {
+ if (!IMAGE_SNAP_BY_ORDINAL(Name->u1.Ordinal))
+ {
+ ImpName = (PIMAGE_IMPORT_BY_NAME)
+ (Base + (DWORD_PTR)Name->u1.AddressOfData);
+ if (strcmp((char *)ImpName->Name, funcname) == 0)
+ return GetModuleHandleA((char *)(Base + Imp->Name));
+ }
+ }
+ }
+ return NULL;
+}
+#endif
+
+static int
+sbcs_mblen(csconv_t *cv UNUSED, const uchar *buf UNUSED, int bufsize UNUSED)
+{
+ return 1;
+}
+
+static int
+dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize)
+{
+ int len = IsDBCSLeadByteEx(cv->codepage, buf[0]) ? 2 : 1;
+ if (bufsize < len)
+ return seterror(EINVAL);
+ return len;
+}
+
+static int
+mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize)
+{
+ int len = 0;
+
+ if (cv->codepage == 54936) {
+ if (buf[0] <= 0x7F) len = 1;
+ else if (buf[0] >= 0x81 && buf[0] <= 0xFE &&
+ bufsize >= 2 &&
+ ((buf[1] >= 0x40 && buf[1] <= 0x7E) ||
+ (buf[1] >= 0x80 && buf[1] <= 0xFE))) len = 2;
+ else if (buf[0] >= 0x81 && buf[0] <= 0xFE &&
+ bufsize >= 4 &&
+ buf[1] >= 0x30 && buf[1] <= 0x39) len = 4;
+ else
+ return seterror(EINVAL);
+ return len;
+ }
+ else
+ return seterror(EINVAL);
+}
+
+static int
+utf8_mblen(csconv_t *cv UNUSED, const uchar *buf, int bufsize)
+{
+ int len = 0;
+
+ if (buf[0] < 0x80) len = 1;
+ else if ((buf[0] & 0xE0) == 0xC0) len = 2;
+ else if ((buf[0] & 0xF0) == 0xE0) len = 3;
+ else if ((buf[0] & 0xF8) == 0xF0) len = 4;
+ else if ((buf[0] & 0xFC) == 0xF8) len = 5;
+ else if ((buf[0] & 0xFE) == 0xFC) len = 6;
+
+ if (len == 0)
+ return seterror(EILSEQ);
+ else if (bufsize < len)
+ return seterror(EINVAL);
+ return len;
+}
+
+static int
+eucjp_mblen(csconv_t *cv UNUSED, const uchar *buf, int bufsize)
+{
+ if (buf[0] < 0x80) /* ASCII */
+ return 1;
+ else if (buf[0] == 0x8E) /* JIS X 0201 */
+ {
+ if (bufsize < 2)
+ return seterror(EINVAL);
+ else if (!(0xA1 <= buf[1] && buf[1] <= 0xDF))
+ return seterror(EILSEQ);
+ return 2;
+ }
+ else if (buf[0] == 0x8F) /* JIS X 0212 */
+ {
+ if (bufsize < 3)
+ return seterror(EINVAL);
+ else if (!(0xA1 <= buf[1] && buf[1] <= 0xFE)
+ || !(0xA1 <= buf[2] && buf[2] <= 0xFE))
+ return seterror(EILSEQ);
+ return 3;
+ }
+ else /* JIS X 0208 */
+ {
+ if (bufsize < 2)
+ return seterror(EINVAL);
+ else if (!(0xA1 <= buf[0] && buf[0] <= 0xFE)
+ || !(0xA1 <= buf[1] && buf[1] <= 0xFE))
+ return seterror(EILSEQ);
+ return 2;
+ }
+}
+
+static int
+kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
+{
+ int len;
+
+ len = cv->mblen(cv, buf, bufsize);
+ if (len == -1)
+ return -1;
+ *wbufsize = MultiByteToWideChar(cv->codepage, mbtowc_flags (cv->codepage),
+ (const char *)buf, len, (wchar_t *)wbuf, *wbufsize);
+ if (*wbufsize == 0)
+ return seterror(EILSEQ);
+ return len;
+}
+
+static int
+kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
+{
+ BOOL usedDefaultChar = 0;
+ BOOL *p = NULL;
+ int flags = 0;
+ int len;
+
+ if (bufsize == 0)
+ return seterror(E2BIG);
+ if (!must_use_null_useddefaultchar(cv->codepage))
+ {
+ p = &usedDefaultChar;
+#ifdef WC_NO_BEST_FIT_CHARS
+ if (!(cv->flags & FLAG_TRANSLIT))
+ flags |= WC_NO_BEST_FIT_CHARS;
+#endif
+ }
+ len = WideCharToMultiByte(cv->codepage, flags,
+ (const wchar_t *)wbuf, wbufsize, (char *)buf, bufsize, NULL, p);
+ if (len == 0)
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ return seterror(E2BIG);
+ return seterror(EILSEQ);
+ }
+ else if (usedDefaultChar && !(cv->flags & FLAG_TRANSLIT))
+ return seterror(EILSEQ);
+ else if (cv->mblen(cv, buf, len) != len) /* validate result */
+ return seterror(EILSEQ);
+ return len;
+}
+
+/*
+ * It seems that the mode (cv->mode) is fixnum.
+ * For example, when converting iso-2022-jp(cp50221) to unicode:
+ * in ascii sequence: mode=0xC42C0000
+ * in jisx0208 sequence: mode=0xC42C0001
+ * "C42C" is same for each convert session.
+ * It should be: ((codepage-1)<<16)|state
+ */
+static int
+mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
+{
+ int len;
+ int insize;
+ HRESULT hr;
+
+ len = cv->mblen(cv, buf, bufsize);
+ if (len == -1)
+ return -1;
+ insize = len;
+ hr = ConvertINetMultiByteToUnicode(&cv->mode, cv->codepage,
+ (const char *)buf, &insize, (wchar_t *)wbuf, wbufsize);
+ if (hr != S_OK || insize != len)
+ return seterror(EILSEQ);
+ return len;
+}
+
+static int
+mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
+{
+ char tmpbuf[MB_CHAR_MAX]; /* enough room for one character */
+ int tmpsize = MB_CHAR_MAX;
+ int insize = wbufsize;
+ HRESULT hr;
+
+ hr = ConvertINetUnicodeToMultiByte(&cv->mode, cv->codepage,
+ (const wchar_t *)wbuf, &wbufsize, tmpbuf, &tmpsize);
+ if (hr != S_OK || insize != wbufsize)
+ return seterror(EILSEQ);
+ else if (bufsize < tmpsize)
+ return seterror(E2BIG);
+ else if (cv->mblen(cv, (uchar *)tmpbuf, tmpsize) != tmpsize)
+ return seterror(EILSEQ);
+ memcpy(buf, tmpbuf, tmpsize);
+ return tmpsize;
+}
+
+static int
+utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
+{
+ int codepage = cv->codepage;
+
+ /* swap endian: 1200 <-> 1201 */
+ if (cv->mode & UNICODE_MODE_SWAPPED)
+ codepage ^= 1;
+
+ if (bufsize < 2)
+ return seterror(EINVAL);
+ if (codepage == 1200) /* little endian */
+ wbuf[0] = (buf[1] << 8) | buf[0];
+ else if (codepage == 1201) /* big endian */
+ wbuf[0] = (buf[0] << 8) | buf[1];
+
+ if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE))
+ {
+ cv->mode |= UNICODE_MODE_BOM_DONE;
+ if (wbuf[0] == 0xFFFE)
+ {
+ cv->mode |= UNICODE_MODE_SWAPPED;
+ *wbufsize = 0;
+ return 2;
+ }
+ else if (wbuf[0] == 0xFEFF)
+ {
+ *wbufsize = 0;
+ return 2;
+ }
+ }
+
+ if (0xDC00 <= wbuf[0] && wbuf[0] <= 0xDFFF)
+ return seterror(EILSEQ);
+ if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF)
+ {
+ if (bufsize < 4)
+ return seterror(EINVAL);
+ if (codepage == 1200) /* little endian */
+ wbuf[1] = (buf[3] << 8) | buf[2];
+ else if (codepage == 1201) /* big endian */
+ wbuf[1] = (buf[2] << 8) | buf[3];
+ if (!(0xDC00 <= wbuf[1] && wbuf[1] <= 0xDFFF))
+ return seterror(EILSEQ);
+ *wbufsize = 2;
+ return 4;
+ }
+ *wbufsize = 1;
+ return 2;
+}
+
+static int
+utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
+{
+ if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE))
+ {
+ int r;
+
+ cv->mode |= UNICODE_MODE_BOM_DONE;
+ if (bufsize < 2)
+ return seterror(E2BIG);
+ if (cv->codepage == 1200) /* little endian */
+ memcpy(buf, "\xFF\xFE", 2);
+ else if (cv->codepage == 1201) /* big endian */
+ memcpy(buf, "\xFE\xFF", 2);
+
+ r = utf16_wctomb(cv, wbuf, wbufsize, buf + 2, bufsize - 2);
+ if (r == -1)
+ return -1;
+ return r + 2;
+ }
+
+ if (bufsize < 2)
+ return seterror(E2BIG);
+ if (cv->codepage == 1200) /* little endian */
+ {
+ buf[0] = (wbuf[0] & 0x00FF);
+ buf[1] = (wbuf[0] & 0xFF00) >> 8;
+ }
+ else if (cv->codepage == 1201) /* big endian */
+ {
+ buf[0] = (wbuf[0] & 0xFF00) >> 8;
+ buf[1] = (wbuf[0] & 0x00FF);
+ }
+ if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF)
+ {
+ if (bufsize < 4)
+ return seterror(E2BIG);
+ if (cv->codepage == 1200) /* little endian */
+ {
+ buf[2] = (wbuf[1] & 0x00FF);
+ buf[3] = (wbuf[1] & 0xFF00) >> 8;
+ }
+ else if (cv->codepage == 1201) /* big endian */
+ {
+ buf[2] = (wbuf[1] & 0xFF00) >> 8;
+ buf[3] = (wbuf[1] & 0x00FF);
+ }
+ return 4;
+ }
+ return 2;
+}
+
+static int
+utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
+{
+ int codepage = cv->codepage;
+ uint wc;
+
+ /* swap endian: 12000 <-> 12001 */
+ if (cv->mode & UNICODE_MODE_SWAPPED)
+ codepage ^= 1;
+
+ if (bufsize < 4)
+ return seterror(EINVAL);
+ if (codepage == 12000) /* little endian */
+ wc = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ else if (codepage == 12001) /* big endian */
+ wc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+
+ if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE))
+ {
+ cv->mode |= UNICODE_MODE_BOM_DONE;
+ if (wc == 0xFFFE0000)
+ {
+ cv->mode |= UNICODE_MODE_SWAPPED;
+ *wbufsize = 0;
+ return 4;
+ }
+ else if (wc == 0x0000FEFF)
+ {
+ *wbufsize = 0;
+ return 4;
+ }
+ }
+
+ if ((0xD800 <= wc && wc <= 0xDFFF) || 0x10FFFF < wc)
+ return seterror(EILSEQ);
+ ucs4_to_utf16(wc, wbuf, wbufsize);
+ return 4;
+}
+
+static int
+utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
+{
+ uint wc;
+
+ if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE))
+ {
+ int r;
+
+ cv->mode |= UNICODE_MODE_BOM_DONE;
+ if (bufsize < 4)
+ return seterror(E2BIG);
+ if (cv->codepage == 12000) /* little endian */
+ memcpy(buf, "\xFF\xFE\x00\x00", 4);
+ else if (cv->codepage == 12001) /* big endian */
+ memcpy(buf, "\x00\x00\xFE\xFF", 4);
+
+ r = utf32_wctomb(cv, wbuf, wbufsize, buf + 4, bufsize - 4);
+ if (r == -1)
+ return -1;
+ return r + 4;
+ }
+
+ if (bufsize < 4)
+ return seterror(E2BIG);
+ wc = utf16_to_ucs4(wbuf);
+ if (cv->codepage == 12000) /* little endian */
+ {
+ buf[0] = wc & 0x000000FF;
+ buf[1] = (wc & 0x0000FF00) >> 8;
+ buf[2] = (wc & 0x00FF0000) >> 16;
+ buf[3] = (wc & 0xFF000000) >> 24;
+ }
+ else if (cv->codepage == 12001) /* big endian */
+ {
+ buf[0] = (wc & 0xFF000000) >> 24;
+ buf[1] = (wc & 0x00FF0000) >> 16;
+ buf[2] = (wc & 0x0000FF00) >> 8;
+ buf[3] = wc & 0x000000FF;
+ }
+ return 4;
+}
+
+/*
+ * 50220: ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)
+ * 50221: ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow
+ * 1 byte Kana)
+ * 50222: ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte
+ * Kana - SO/SI)
+ *
+ * MultiByteToWideChar() and WideCharToMultiByte() behave differently
+ * depending on Windows version. On XP, WideCharToMultiByte() doesn't
+ * terminate result sequence with ascii escape. But Vista does.
+ * Use MLang instead.
+ */
+
+#define ISO2022_MODE(cs, shift) (((cs) << 8) | (shift))
+#define ISO2022_MODE_CS(mode) (((mode) >> 8) & 0xFF)
+#define ISO2022_MODE_SHIFT(mode) ((mode) & 0xFF)
+
+#define ISO2022_SI 0
+#define ISO2022_SO 1
+
+/* shift in */
+static const char iso2022_SI_seq[] = "\x0F";
+/* shift out */
+static const char iso2022_SO_seq[] = "\x0E";
+
+typedef struct iso2022_esc_t iso2022_esc_t;
+struct iso2022_esc_t {
+ const char *esc;
+ int esc_len;
+ int len;
+ int cs;
+};
+
+#define ISO2022JP_CS_ASCII 0
+#define ISO2022JP_CS_JISX0201_ROMAN 1
+#define ISO2022JP_CS_JISX0201_KANA 2
+#define ISO2022JP_CS_JISX0208_1978 3
+#define ISO2022JP_CS_JISX0208_1983 4
+#define ISO2022JP_CS_JISX0212 5
+
+static iso2022_esc_t iso2022jp_esc[] = {
+ {"\x1B\x28\x42", 3, 1, ISO2022JP_CS_ASCII},
+ {"\x1B\x28\x4A", 3, 1, ISO2022JP_CS_JISX0201_ROMAN},
+ {"\x1B\x28\x49", 3, 1, ISO2022JP_CS_JISX0201_KANA},
+ {"\x1B\x24\x40", 3, 2, ISO2022JP_CS_JISX0208_1983}, /* unify 1978 with 1983 */
+ {"\x1B\x24\x42", 3, 2, ISO2022JP_CS_JISX0208_1983},
+ {"\x1B\x24\x28\x44", 4, 2, ISO2022JP_CS_JISX0212},
+ {NULL, 0, 0, 0}
+};
+
+static int
+iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize)
+{
+ iso2022_esc_t *iesc = iso2022jp_esc;
+ char tmp[MB_CHAR_MAX];
+ int insize;
+ HRESULT hr;
+ DWORD dummy = 0;
+ int len;
+ int esc_len;
+ int cs;
+ int shift;
+ int i;
+
+ if (buf[0] == 0x1B)
+ {
+ for (i = 0; iesc[i].esc != NULL; ++i)
+ {
+ esc_len = iesc[i].esc_len;
+ if (bufsize < esc_len)
+ {
+ if (strncmp((char *)buf, iesc[i].esc, bufsize) == 0)
+ return seterror(EINVAL);
+ }
+ else
+ {
+ if (strncmp((char *)buf, iesc[i].esc, esc_len) == 0)
+ {
+ cv->mode = ISO2022_MODE(iesc[i].cs, ISO2022_SI);
+ *wbufsize = 0;
+ return esc_len;
+ }
+ }
+ }
+ /* not supported escape sequence */
+ return seterror(EILSEQ);
+ }
+ else if (buf[0] == iso2022_SO_seq[0])
+ {
+ cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SO);
+ *wbufsize = 0;
+ return 1;
+ }
+ else if (buf[0] == iso2022_SI_seq[0])
+ {
+ cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SI);
+ *wbufsize = 0;
+ return 1;
+ }
+
+ cs = ISO2022_MODE_CS(cv->mode);
+ shift = ISO2022_MODE_SHIFT(cv->mode);
+
+ /* reset the mode for informal sequence */
+ if (buf[0] < 0x20)
+ {
+ cs = ISO2022JP_CS_ASCII;
+ shift = ISO2022_SI;
+ }
+
+ len = iesc[cs].len;
+ if (bufsize < len)
+ return seterror(EINVAL);
+ for (i = 0; i < len; ++i)
+ if (!(buf[i] < 0x80))
+ return seterror(EILSEQ);
+ esc_len = iesc[cs].esc_len;
+ memcpy(tmp, iesc[cs].esc, esc_len);
+ if (shift == ISO2022_SO)
+ {
+ memcpy(tmp + esc_len, iso2022_SO_seq, 1);
+ esc_len += 1;
+ }
+ memcpy(tmp + esc_len, buf, len);
+
+ if ((cv->codepage == 50220 || cv->codepage == 50221
+ || cv->codepage == 50222) && shift == ISO2022_SO)
+ {
+ /* XXX: shift-out cannot be used for mbtowc (both kernel and
+ * mlang) */
+ esc_len = iesc[ISO2022JP_CS_JISX0201_KANA].esc_len;
+ memcpy(tmp, iesc[ISO2022JP_CS_JISX0201_KANA].esc, esc_len);
+ memcpy(tmp + esc_len, buf, len);
+ }
+
+ insize = len + esc_len;
+ hr = ConvertINetMultiByteToUnicode(&dummy, cv->codepage,
+ (const char *)tmp, &insize, (wchar_t *)wbuf, wbufsize);
+ if (hr != S_OK || insize != len + esc_len)
+ return seterror(EILSEQ);
+
+ /* Check for conversion error. Assuming defaultChar is 0x3F. */
+ /* ascii should be converted from ascii */
+ if (wbuf[0] == buf[0]
+ && cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI))
+ return seterror(EILSEQ);
+
+ /* reset the mode for informal sequence */
+ if (cv->mode != (DWORD)ISO2022_MODE(cs, shift))
+ cv->mode = (DWORD)ISO2022_MODE(cs, shift);
+
+ return len;
+}
+
+static int
+iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize)
+{
+ iso2022_esc_t *iesc = iso2022jp_esc;
+ char tmp[MB_CHAR_MAX];
+ int tmpsize = MB_CHAR_MAX;
+ int insize = wbufsize;
+ HRESULT hr;
+ DWORD dummy = 0;
+ int len;
+ int esc_len;
+ int cs;
+ int shift;
+ int i;
+
+ /*
+ * MultiByte = [escape sequence] + character + [escape sequence]
+ *
+ * Whether trailing escape sequence is added depends on which API is
+ * used (kernel or MLang, and its version).
+ */
+ hr = ConvertINetUnicodeToMultiByte(&dummy, cv->codepage,
+ (const wchar_t *)wbuf, &wbufsize, tmp, &tmpsize);
+ if (hr != S_OK || insize != wbufsize)
+ return seterror(EILSEQ);
+ else if (bufsize < tmpsize)
+ return seterror(E2BIG);
+
+ if (tmpsize == 1)
+ {
+ cs = ISO2022JP_CS_ASCII;
+ esc_len = 0;
+ }
+ else
+ {
+ for (i = 1; iesc[i].esc != NULL; ++i)
+ {
+ esc_len = iesc[i].esc_len;
+ if (strncmp(tmp, iesc[i].esc, esc_len) == 0)
+ {
+ cs = iesc[i].cs;
+ break;
+ }
+ }
+ if (iesc[i].esc == NULL)
+ /* not supported escape sequence */
+ return seterror(EILSEQ);
+ }
+
+ shift = ISO2022_SI;
+ if (tmp[esc_len] == iso2022_SO_seq[0])
+ {
+ shift = ISO2022_SO;
+ esc_len += 1;
+ }
+
+ len = iesc[cs].len;
+
+ /* Check for converting error. Assuming defaultChar is 0x3F. */
+ /* ascii should be converted from ascii */
+ if (cs == ISO2022JP_CS_ASCII && !(wbuf[0] < 0x80))
+ return seterror(EILSEQ);
+ else if (tmpsize < esc_len + len)
+ return seterror(EILSEQ);
+
+ if (cv->mode == ISO2022_MODE(cs, shift))
+ {
+ /* remove escape sequence */
+ if (esc_len != 0)
+ memmove(tmp, tmp + esc_len, len);
+ esc_len = 0;
+ }
+ else
+ {
+ if (cs == ISO2022JP_CS_ASCII)
+ {
+ esc_len = iesc[ISO2022JP_CS_ASCII].esc_len;
+ memmove(tmp + esc_len, tmp, len);
+ memcpy(tmp, iesc[ISO2022JP_CS_ASCII].esc, esc_len);
+ }
+ if (ISO2022_MODE_SHIFT(cv->mode) == ISO2022_SO)
+ {
+ /* shift-in before changing to other mode */
+ memmove(tmp + 1, tmp, len + esc_len);
+ memcpy(tmp, iso2022_SI_seq, 1);
+ esc_len += 1;
+ }
+ }
+
+ if (bufsize < len + esc_len)
+ return seterror(E2BIG);
+ memcpy(buf, tmp, len + esc_len);
+ cv->mode = ISO2022_MODE(cs, shift);
+ return len + esc_len;
+}
+
+static int
+iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize)
+{
+ iso2022_esc_t *iesc = iso2022jp_esc;
+ int esc_len;
+
+ if (cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI))
+ {
+ esc_len = 0;
+ if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI)
+ esc_len += 1;
+ if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII)
+ esc_len += iesc[ISO2022JP_CS_ASCII].esc_len;
+ if (bufsize < esc_len)
+ return seterror(E2BIG);
+
+ esc_len = 0;
+ if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI)
+ {
+ memcpy(buf, iso2022_SI_seq, 1);
+ esc_len += 1;
+ }
+ if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII)
+ {
+ memcpy(buf + esc_len, iesc[ISO2022JP_CS_ASCII].esc,
+ iesc[ISO2022JP_CS_ASCII].esc_len);
+ esc_len += iesc[ISO2022JP_CS_ASCII].esc_len;
+ }
+ return esc_len;
+ }
+ return 0;
+}
+
+#if defined(MAKE_DLL) && defined(USE_LIBICONV_DLL)
+BOOL WINAPI
+DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+{
+ switch( fdwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ hwiniconv = (HMODULE)hinstDLL;
+ break;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+#endif
+
+#if defined(MAKE_EXE)
+#include <stdio.h>
+#include <fcntl.h>
+#include <io.h>
+int
+main(int argc, char **argv)
+{
+ char *fromcode = NULL;
+ char *tocode = NULL;
+ int i;
+ char inbuf[BUFSIZ];
+ char outbuf[BUFSIZ];
+ char *pin;
+ char *pout;
+ size_t inbytesleft;
+ size_t outbytesleft;
+ size_t rest = 0;
+ iconv_t cd;
+ size_t r;
+ FILE *in = stdin;
+ FILE *out = stdout;
+ int ignore = 0;
+ char *p;
+
+ _setmode(_fileno(stdin), _O_BINARY);
+ _setmode(_fileno(stdout), _O_BINARY);
+
+ for (i = 1; i < argc; ++i)
+ {
+ if (strcmp(argv[i], "-l") == 0)
+ {
+ for (i = 0; codepage_alias[i].name != NULL; ++i)
+ printf("%s\n", codepage_alias[i].name);
+ return 0;
+ }
+
+ if (strcmp(argv[i], "-f") == 0)
+ fromcode = argv[++i];
+ else if (strcmp(argv[i], "-t") == 0)
+ tocode = argv[++i];
+ else if (strcmp(argv[i], "-c") == 0)
+ ignore = 1;
+ else if (strcmp(argv[i], "--output") == 0)
+ {
+ out = fopen(argv[++i], "wb");
+ if(out == NULL)
+ {
+ fprintf(stderr, "cannot open %s\n", argv[i]);
+ return 1;
+ }
+ }
+ else
+ {
+ in = fopen(argv[i], "rb");
+ if (in == NULL)
+ {
+ fprintf(stderr, "cannot open %s\n", argv[i]);
+ return 1;
+ }
+ break;
+ }
+ }
+
+ if (fromcode == NULL || tocode == NULL)
+ {
+ printf("usage: %s [-c] -f from-enc -t to-enc [file]\n", argv[0]);
+ return 0;
+ }
+
+ if (ignore)
+ {
+ p = tocode;
+ tocode = (char *)malloc(strlen(p) + strlen("//IGNORE") + 1);
+ if (tocode == NULL)
+ {
+ perror("fatal error");
+ return 1;
+ }
+ strcpy(tocode, p);
+ strcat(tocode, "//IGNORE");
+ }
+
+ cd = iconv_open(tocode, fromcode);
+ if (cd == (iconv_t)(-1))
+ {
+ perror("iconv_open error");
+ return 1;
+ }
+
+ while ((inbytesleft = fread(inbuf + rest, 1, sizeof(inbuf) - rest, in)) != 0
+ || rest != 0)
+ {
+ inbytesleft += rest;
+ pin = inbuf;
+ pout = outbuf;
+ outbytesleft = sizeof(outbuf);
+ r = iconv(cd, &pin, &inbytesleft, &pout, &outbytesleft);
+ fwrite(outbuf, 1, sizeof(outbuf) - outbytesleft, out);
+ if (r == (size_t)(-1) && errno != E2BIG && (errno != EINVAL || feof(in)))
+ {
+ perror("conversion error");
+ return 1;
+ }
+ memmove(inbuf, pin, inbytesleft);
+ rest = inbytesleft;
+ }
+ pout = outbuf;
+ outbytesleft = sizeof(outbuf);
+ r = iconv(cd, NULL, NULL, &pout, &outbytesleft);
+ fwrite(outbuf, 1, sizeof(outbuf) - outbytesleft, out);
+ if (r == (size_t)(-1))
+ {
+ perror("conversion error");
+ return 1;
+ }
+
+ iconv_close(cd);
+
+ return 0;
+}
+#endif
+
diff --git a/libmariadb/win/packaging/CMakeLists.txt b/libmariadb/win/packaging/CMakeLists.txt
new file mode 100644
index 00000000..56db434c
--- /dev/null
+++ b/libmariadb/win/packaging/CMakeLists.txt
@@ -0,0 +1,107 @@
+SET(CLIENT_LIB_DIR ${CC_BINARY_DIR}/libmariadb/${CMAKE_BUILD_TYPE})
+SET(CLIENT_BIN_DIR ${CC_BINARY_DIR}/client/${CMAKE_BUILD_TYPE})
+SET(CLIENT_DBG_DIR ${CC_BINARY_DIR}/libmariadb/Debug)
+SET(CLIENT_INC_DIR ${CC_SOURCE_DIR}/include)
+
+SET(PRODUCT_NAME "MariaDB Connector C")
+SET(PRODUCT_INSTALL_DIR "MariaDB")
+SET(PRODUCT_MANUFACTURER "MariaDB Corporation")
+SET(PRODUCT_VERSION "${CPACK_PACKAGE_VERSION}")
+
+IF (${CMAKE_SIZEOF_VOID_P} EQUAL 8)
+ SET(PRODUCT_NAME "${PRODUCT_NAME} 64-bit")
+ SET(PLATFORM "win64")
+ SET(IS_WIN64 "yes")
+ SET(WIXPLATFORM "x64")
+ SET(PRODUCT_UPGRADE_CODE "4E630B8C-4645-416D-A561-45D88E7BDCF1")
+ SET(FOLDER "ProgramFiles64Folder")
+ELSE()
+ SET(PLATFORM "win32")
+ SET(IS_WIN64 "no")
+ SET(WIXPLATFORM "x86")
+ SET(PRODUCT_UPGRADE_CODE "FCBC4419-07C8-4595-9803-DFD602A84F29")
+ SET(FOLDER "ProgramFilesFolder")
+ENDIF()
+
+#
+# process dynamic plugins
+#
+FOREACH(plugin ${PLUGINS_DYNAMIC})
+ SET(TARGET ${plugin})
+ # Get dependencies
+ SET(DYNAMIC_TARGETS ${DYNAMIC_TARGETS} ${TARGET})
+ SET(FILE ${CC_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${TARGET}.dll)
+ SET(PDB ${CC_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${TARGET}.pdb)
+ MESSAGE(STATUS "Location for ${TARGET}: ${FILE}")
+ # build file list
+ STRING(REPLACE "$(Configuration)" "RelWithDebInfo" FILE ${FILE})
+ SET(MARIADB_PLUGINS "${MARIADB_PLUGINS} <File Id=\"${TARGET}.dll\" Name=\"${TARGET}.dll\" DiskId=\"1\" Source=\"${FILE}\"/>\n")
+ SET(MARIADB_PLUGINS "${MARIADB_PLUGINS} <File Id=\"${TARGET}.pdb\" Name=\"${TARGET}.pdb\" DiskId=\"1\" Source=\"${PDB}\"/>\n")
+ENDFOREACH()
+
+FOREACH(src ${WIX_INCLUDES})
+ STRING(REPLACE "${CC_SOURCE_DIR}/include/" "" src ${src})
+ # check binary dir
+ STRING(REPLACE "${CC_BINARY_DIR}/include/" "" chgbin ${src})
+ IF (${chgbin} STREQUAL ${src})
+ SET(SRC_DIR ${CC_SOURCE_DIR})
+ ELSE()
+ SET(SRC_DIR ${CC_BINARY_DIR})
+ STRING(REPLACE "${CC_BINARY_DIR}/include/" "" src ${src})
+ ENDIF()
+ STRING(REPLACE "-" "_" src_id ${src})
+ STRING(REPLACE "mysql/" "" src_id ${src_id})
+ STRING(REPLACE "mysql/" "" src_name ${src})
+ STRING(REPLACE "mariadb/" "" src_name ${src_name})
+ STRING(REPLACE "mariadb/" "" src_id ${src_id})
+ IF(${src} MATCHES "mysql/")
+ SET(MARIADB_INCLUDEMYSQL_FILES "${MARIADB_INCLUDEMYSQL_FILES} <File Id=\"${src_id}\" Name=\"${src_name}\" DiskId=\"1\" Source=\"${SRC_DIR}/include/${src}\"/>\n")
+ ELSEIF (${src} MATCHES "mariadb/")
+ SET(MARIADB_INCLUDEMARIADB_FILES "${MARIADB_INCLUDEMARIADB_FILES} <File Id=\"${src_id}\" Name=\"${src_name}\" DiskId=\"1\" Source=\"${SRC_DIR}/include/${src}\"/>\n")
+ ELSE()
+ SET(MARIADB_INCLUDE_FILES "${MARIADB_INCLUDE_FILES} <File Id=\"${src_id}\" Name=\"${src_name}\" DiskId=\"1\" Source=\"${SRC_DIR}/include/${src}\"/>\n")
+ ENDIF()
+ENDFOREACH()
+
+
+IF(NOT WIX_DIR)
+ SET(WIX_DIR $ENV{WIX}/bin)
+ENDIF()
+
+IF(NOT PACKAGE_STATUS_SUFFIX)
+ SET(MSI_PACKAGE "mariadb-connector-c-${PRODUCT_VERSION}-${PLATFORM}.msi")
+ELSE()
+ SET(MSI_PACKAGE "mariadb-connector-c-${PRODUCT_VERSION}-${PACKAGE_STATUS_SUFFIX}-${PLATFORM}.msi")
+ENDIF()
+
+IF(WITH_SIGNCODE)
+ IF(EXISTS "/tools/sign.bat")
+ ADD_CUSTOM_TARGET(SIGNMSI
+ DEPENDS ${MSI_PACKAGE}
+ COMMAND /tools/sign.bat ${MSI_PACKAGE})
+ ELSE()
+ ADD_CUSTOM_TARGET(SIGNMSI
+ DEPENDS ${MSI_PACKAGE}
+ COMMAND signtool sign ${SIGN_OPTIONS} ${MSI_PACKAGE})
+ ENDIF()
+ ADD_DEPENDENCIES(SIGNMSI ${MSI_PACKAGE})
+ SET_TARGET_PROPERTIES(SIGNMSI PROPERTIES EXCLUDE_FROM_ALL OFF)
+ENDIF()
+
+ADD_CUSTOM_TARGET(
+ ${MSI_PACKAGE}
+ DEPENDS WIXOBJ
+#mariadb-connector-c.wixobj
+ COMMAND ${WIX_DIR}/light.exe -ext WixUIExtension mariadb-connector-c.wixobj -o ${MSI_PACKAGE})
+
+ADD_CUSTOM_TARGET(WIXOBJ
+ DEPENDS mariadb-connector-c.xml}
+ COMMAND ${WIX_DIR}/candle.exe mariadb-connector-c.xml -o mariadb-connector-c.wixobj)
+
+SET_TARGET_PROPERTIES(${MSI_PACKAGE} PROPERTIES EXCLUDE_FROM_ALL OFF)
+SET_TARGET_PROPERTIES(${WIXOBJ} PROPERTIES EXCLUDE_FROM_ALL OFF)
+ADD_DEPENDENCIES(${MSI_PACKAGE} WIXOBJ)
+ADD_DEPENDENCIES(WIXOBJ libmariadb mariadbclient ${DYNAMIC_TARGETS})
+
+CONFIGURE_FILE(${CC_SOURCE_DIR}/win/packaging/mariadb-connector-c.xml.in
+ ${CC_BINARY_DIR}/win/packaging/mariadb-connector-c.xml)
diff --git a/libmariadb/win/packaging/WixUIBannerBmp.jpg b/libmariadb/win/packaging/WixUIBannerBmp.jpg
new file mode 100644
index 00000000..60cce899
--- /dev/null
+++ b/libmariadb/win/packaging/WixUIBannerBmp.jpg
Binary files differ
diff --git a/libmariadb/win/packaging/WixUIDialogBmp.jpg b/libmariadb/win/packaging/WixUIDialogBmp.jpg
new file mode 100644
index 00000000..b6ab2ff1
--- /dev/null
+++ b/libmariadb/win/packaging/WixUIDialogBmp.jpg
Binary files differ
diff --git a/libmariadb/win/packaging/license.rtf b/libmariadb/win/packaging/license.rtf
new file mode 100644
index 00000000..1ed38609
--- /dev/null
+++ b/libmariadb/win/packaging/license.rtf
@@ -0,0 +1,464 @@
+{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1031\deflangfe1031\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}
+{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}
+{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
+{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f322\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f323\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\f325\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f326\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f327\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f328\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\f329\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f330\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f342\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f343\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}
+{\f345\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f346\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f347\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f348\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}
+{\f349\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f350\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f662\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f663\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}
+{\f665\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f666\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f669\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f670\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}
+{\f692\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f693\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f695\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f696\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
+{\f699\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f700\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
+{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
+{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
+{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
+{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
+\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp
+\fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa200\sl276\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 \snext0 \sqformat \spriority0 Normal;}
+{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 \snext11 \ssemihidden \sunhideused
+Normal Table;}{\s15\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031
+\snext15 \sqformat \spriority1 \styrsid7013135 No Spacing;}}{\*\rsidtbl \rsid1254708\rsid7013135}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Windows User}
+{\creatim\yr2013\mo10\dy26\hr9\min47}{\revtim\yr2013\mo10\dy26\hr9\min55}{\version2}{\edmins0}{\nofpages9}{\nofwords3590}{\nofchars22619}{\nofcharsws26157}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}
+\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect
+\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120
+\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot7013135 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}
+{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}
+{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9
+\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0
+\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af2\afs28 \ltrch\fcs0 \b\fs28\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
+GNU LESSER GENERAL PUBLIC LICENSE
+\par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 Version 2.1, February 1999
+\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
+Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+\par \hich\af31506\dbch\af31505\loch\f31506 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+\par \hich\af31506\dbch\af31505\loch\f31506 Everyone is permitted to copy and distribute verbatim copies
+\par \hich\af31506\dbch\af31505\loch\f31506 of this license document, but changing it is not allowed.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 [This is the first released version of the Lesser GPL. \hich\af31506\dbch\af31505\loch\f31506 It also counts as the successor of the GNU Library Public License, version 2, \hich\af31506\dbch\af31505\loch\f31506
+hence the version number 2.1.]
+\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \b\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 Preamble
+\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par }\pard\plain \ltrpar\s15\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid7013135 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0
+\fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
+ The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to sh\hich\af31506\dbch\af31505\loch\f31506
+are and change free software--to make sure the software is free for all its users.
+\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af2 \ltrch\fcs0
+\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par \hich\af31506\dbch\af31505\loch\f31506 This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other au\hich\af31506\dbch\af31505\loch\f31506
+thors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 When we sp\hich\af31506\dbch\af31505\loch\f31506
+eak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source
+\hich\af31506\dbch\af31505\loch\f31506 c\hich\af31506\dbch\af31505\loch\f31506 ode or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 To protect your rights, we need to make restrictions that forbid distributors to deny y\hich\af31506\dbch\af31505\loch\f31506
+ou these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
+\par \hich\af31506\dbch\af31505\loch\f31506 For example, if you distribute copies of the library, whether gratis\hich\af31506\dbch\af31505\loch\f31506
+ or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so tha
+\hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer y\hich\af31506\dbch\af31505\loch\f31506
+ou this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else
+\hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506
+nd passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Finally, software patents pose a constant threat to t\hich\af31506\dbch\af31505\loch\f31506
+he existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of
+\hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 the library must be consistent with the full freedom of use specified in this license.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to c\hich\af31506\dbch\af31505\loch\f31506
+ertain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 When a program is linked with a library, whether \hich\af31506\dbch\af31505\loch\f31506
+statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteri
+\hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506 of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs.
+\hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506
+ These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 For example, on rare occasions, there may be a special need to encourag\hich\af31506\dbch\af31505\loch\f31506
+e the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free librarie
+\hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 . In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 In other cases, permission to use a particular library in non-free programs enables a greater number of people to u\hich\af31506\dbch\af31505\loch\f31506
+se a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Although the Lesser General \hich\af31506\dbch\af31505\loch\f31506
+Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 The precise terms and con\hich\af31506\dbch\af31505\loch\f31506
+ditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be comb
+\hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 ned with the library in order to run.
+\par \page
+\par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2\afs24 \ltrch\fcs0 \b\fs24\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
+GNU LESSER GENERAL PUBLIC LICENSE
+\par \hich\af31506\dbch\af31505\loch\f31506 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par \hich\af31506\dbch\af31505\loch\f31506 0. This License Agreement applies to any software library or other program which contains a no\hich\af31506\dbch\af31505\loch\f31506
+tice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 A "library" means a collection of softwa\hich\af31506\dbch\af31505\loch\f31506
+re functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 The "Library", below, refers to any such software library or work which has been distributed un\hich\af31506\dbch\af31505\loch\f31506
+der these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardl
+\hich\af31506\dbch\af31505\loch\f31506 y\hich\af31506\dbch\af31505\loch\f31506 into another language. (Hereinafter, translation is included without limitation in the term "modification".)
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all t\hich\af31506\dbch\af31505\loch\f31506
+he source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Activities other than copying, distribution and modification are not covered by thi\hich\af31506\dbch\af31505\loch\f31506
+s License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a too
+\hich\af31506\dbch\af31505\loch\f31506 l\hich\af31506\dbch\af31505\loch\f31506 for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided tha\hich\af31506\dbch\af31505\loch\f31506
+t you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along w
+\hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 th the Library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+\par \page
+\par \hich\af31506\dbch\af31505\loch\f31506 2. You may modify your copy or copies of the Library or any portion of it, thus forming a w\hich\af31506\dbch\af31505\loch\f31506
+ork based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 a) The modified work must itself be a software library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 b) You mus\hich\af31506\dbch\af31505\loch\f31506 t cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 d) If a\hich\af31506\dbch\af31505\loch\f31506
+ facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that
+,\hich\af31506\dbch\af31505\loch\f31506 in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 (For example, a function in a library to compute square roots has a purpose that is entirel\hich\af31506\dbch\af31505\loch\f31506
+y well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute sq
+\hich\af31506\dbch\af31505\loch\f31506 u\hich\af31506\dbch\af31505\loch\f31506 are roots.)
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms,
+\hich\af31506\dbch\af31505\loch\f31506
+ do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permi
+\hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 sions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to e\hich\af31506\dbch\af31505\loch\f31506
+xercise the right to control the distribution of derivative or collective works based on the Library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or\hich\af31506\dbch\af31505\loch\f31506
+ distribution medium does not bring the other work under the scope of this License.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the \hich\af31506\dbch\af31505\loch\f31506
+notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify tha
+\hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 version instead if you wish.) Do not make any other change in
+\par \hich\af31506\dbch\af31505\loch\f31506 these notices.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works m\hich\af31506\dbch\af31505\loch\f31506
+ade from that copy.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or exe\hich\af31506\dbch\af31505\loch\f31506
+cutable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for softwa
+\hich\af31506\dbch\af31505\loch\f31506 r\hich\af31506\dbch\af31505\loch\f31506 e interchange.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though th
+\hich\af31506\dbch\af31505\loch\f31506 ird parties are not compelled to copy the source along with the object code.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the L
+\hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 brary, and therefore falls outside the scope of this License.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work t
+\hich\af31506\dbch\af31505\loch\f31506 hat uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 When a "work that uses the Library" uses material from a header file that is part of the Library, the object code \hich\af31506\dbch\af31505\loch\f31506
+for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true
+\hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 s not precisely defined by law.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, rega
+\hich\af31506\dbch\af31505\loch\f31506 rdless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Otherwise, if the work is a derivative of the Library, you may distribute the object code for the\hich\af31506\dbch\af31505\loch\f31506
+ work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 6. As an exception to the Sections above, you may also combine or link a "work that use\hich\af31506\dbch\af31505\loch\f31506
+s the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debug
+\hich\af31506\dbch\af31505\loch\f31506 g\hich\af31506\dbch\af31505\loch\f31506 ing such modifications.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution display
+\hich\af31506\dbch\af31505\loch\f31506 s copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 a) Accompany the work with the complete corresponding\hich\af31506\dbch\af31505\loch\f31506
+ machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work th
+\hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506
+t uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions file
+\hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 in the Library will not necessarily be able to recompile the application to use the modified definitions.)
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the l\hich\af31506\dbch\af31505\loch\f31506
+ibrary already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-c
+\hich\af31506\dbch\af31505\loch\f31506 o\hich\af31506\dbch\af31505\loch\f31506 mpatible with the version that the work was made with.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing
+\hich\af31506\dbch\af31505\loch\f31506 this distribution.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 e) Verify that the user has already received a copy o\hich\af31506\dbch\af31505\loch\f31506 f these materials or that you have already sent this user a copy.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special e
+\hich\af31506\dbch\af31505\loch\f31506
+xception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that co
+\hich\af31506\dbch\af31505\loch\f31506 m\hich\af31506\dbch\af31505\loch\f31506 ponent itself accompanies the executable.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them a
+\hich\af31506\dbch\af31505\loch\f31506 nd the Library together in an executable that you distribute.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution
+\hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other libr\hich\af31506\dbch\af31505\loch\f31506
+ary facilities. This must be distributed under the terms of the Sections above.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined fo\hich\af31506\dbch\af31505\loch\f31506
+rm of the same work.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will
+\hich\af31506\dbch\af31505\loch\f31506
+l automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 9. You are not requir\hich\af31506\dbch\af31505\loch\f31506
+ed to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modif
+\hich\af31506\dbch\af31505\loch\f31506 y\hich\af31506\dbch\af31505\loch\f31506
+ing or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 10. Each time you redist\hich\af31506\dbch\af31505\loch\f31506
+ribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further re
+\hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 trictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other \hich\af31506\dbch\af31505\loch\f31506
+reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so
+\hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506
+s to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Lib
+\hich\af31506\dbch\af31505\loch\f31506 r\hich\af31506\dbch\af31505\loch\f31506
+ary by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 If any portion of this section is held invalid or unenforce\hich\af31506\dbch\af31505\loch\f31506
+able under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 It is not the purpose of this section to induce you to infringe any patents or other property \hich\af31506\dbch\af31505\loch\f31506
+right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions
+\hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506
+o the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose
+\hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 hat choice.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted int\hich\af31506\dbch\af31505\loch\f31506
+erfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such c
+\hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506 se, this License incorporates the limitation as if written in the body of this License.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar i\hich\af31506\dbch\af31505\loch\f31506
+n spirit to the present version, but may differ in detail to address new problems or concerns.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", y\hich\af31506\dbch\af31505\loch\f31506
+ou have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the
+\hich\af31506\dbch\af31505\loch\f31506 F\hich\af31506\dbch\af31505\loch\f31506 ree Software Foundation.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506
+ 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free So
+\hich\af31506\dbch\af31505\loch\f31506
+ftware Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of
+\hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 oftware generally.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af2 \ltrch\fcs0 \b\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 NO WARRANTY
+\par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par \hich\af31506\dbch\af31505\loch\f31506 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTH\hich\af31506\dbch\af31505\loch\f31506
+ERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULA
+\hich\af31506\dbch\af31505\loch\f31506 R\hich\af31506\dbch\af31505\loch\f31506
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGRE\hich\af31506\dbch\af31505\loch\f31506
+ED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR I
+\hich\af31506\dbch\af31505\loch\f31506 N\hich\af31506\dbch\af31505\loch\f31506
+ABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEE
+\hich\af31506\dbch\af31505\loch\f31506 N\hich\af31506\dbch\af31505\loch\f31506 ADVISED OF THE POSSIBILITY OF SUCH
+\par \hich\af31506\dbch\af31505\loch\f31506 DAMAGES.
+\par
+\par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 END OF TERMS AND CONDITIONS
+
+\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \b\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
+How to Apply These Terms to Your New Libraries
+\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par \hich\af31506\dbch\af31505\loch\f31506 If you develop a new library, and you want it to be of the greatest possible use to the public, we \hich\af31506\dbch\af31505\loch\f31506
+recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 To apply these terms, attach the foll\hich\af31506\dbch\af31505\loch\f31506
+owing notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
+
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 <one line to give the library's name and a brief idea of what it does.> }{\rtlch\fcs1 \af2 \ltrch\fcs0 \insrsid1254708\charrsid7013135
+\hich\af31506\dbch\af31505\loch\f31506 Copyright (C) <year> <name of author>
+\par
+\par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
+ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as publishe\hich\af31506\dbch\af31505\loch\f31506
+d by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\hich\af31506\dbch\af31505\loch\f31506
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software
+\par \hich\af31506\dbch\af31505\loch\f31506 Foundation, Inc\hich\af31506\dbch\af31505\loch\f31506 ., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Also add information on how to contact you by electronic and paper mail.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaim\hich\af31506\dbch\af31505\loch\f31506 er" for the library, if
+\par \hich\af31506\dbch\af31505\loch\f31506 necessary. Here is a sample; alter the names:
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 Yoyodyne, Inc., hereby disclaims all copyright interest in the
+\par \hich\af31506\dbch\af31505\loch\f31506 library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+\par
+\par \hich\af31506\dbch\af31505\loch\f31506 <signature of Ty Coon>, 1 April 1990
+\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af2 \ltrch\fcs0 \insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 Ty Coon, President of Vice
+\par
+\par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 That's all there is to it!
+\par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
+\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
+9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
+5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
+b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
+0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
+a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
+c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
+0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
+a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
+6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
+4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
+4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f
+7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87
+615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad
+79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b
+5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab
+999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9
+699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586
+8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6
+0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f
+9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be
+15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979
+3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d
+32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a
+f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86
+e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90
+fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2
+ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae
+a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1
+399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5
+4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84
+0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b
+c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7
+689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20
+5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0
+aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d
+316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840
+545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a
+c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100
+0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7
+8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89
+d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500
+1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f
+bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6
+a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a
+0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021
+0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008
+00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000}
+{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
+617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
+6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
+656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
+{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
+\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;
+\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7;
+\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000
+4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
+d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e500000000000000000000000050f6
+efc420d2ce01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file
diff --git a/libmariadb/win/packaging/mariadb-connector-c.xml.in b/libmariadb/win/packaging/mariadb-connector-c.xml.in
new file mode 100644
index 00000000..d75d2a6b
--- /dev/null
+++ b/libmariadb/win/packaging/mariadb-connector-c.xml.in
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+ <Product Id="*" Name="@PRODUCT_NAME@" Language="1033"
+ Version="@PRODUCT_VERSION@"
+ Manufacturer="@PRODUCT_MANUFACTURER@" UpgradeCode="@PRODUCT_UPGRADE_CODE@">
+ <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Platform="@WIXPLATFORM@"/>
+
+ <MajorUpgrade DowngradeErrorMessage="A newer version of @PRODUCT_NAME@ is already installed." />
+ <MediaTemplate EmbedCab="yes" />
+
+ <UIRef Id="WixUI_Mondo" />
+ <WixVariable Id="WixUILicenseRtf" Value="@CMAKE_SOURCE_DIR@/win/packaging/license.rtf" />
+ <WixVariable Id="WixUIBannerBmp" Value="@CMAKE_SOURCE_DIR@/win/packaging/WixUIBannerBmp.jpg" />
+ <WixVariable Id="WixUIDialogBmp" Value="@CMAKE_SOURCE_DIR@/win/packaging/WixUIDialogBmp.jpg" />
+
+ <Feature Id="ProductFeature" Title="@PRODUCT_NAME@ @PRODUCT_VERSION@" Level="1">
+ <ComponentRef Id="RegistryKeys" />
+ <ComponentRef Id="Library"/>
+ <ComponentRef Id="Plugins"/>
+ <ComponentRef Id="Binaries" />
+ </Feature>
+ <Feature Id="IncludeFeature" Title="Include Files" Level="1">
+ <ComponentRef Id="Includes"/>
+ <ComponentRef Id="MysqlIncludes"/>
+ <ComponentRef Id="MariadbIncludes"/>
+ </Feature>
+ </Product>
+
+ <Fragment>
+ <Directory Id="TARGETDIR" Name="SourceDir">
+ <Directory Id="@FOLDER@">
+ <Directory Id="Mariadb" Name="@PRODUCT_INSTALL_DIR@">
+ <Directory Id="INSTALLFOLDER" Name="@PRODUCT_NAME@" >
+ <Directory Id="inst_bin" Name="bin"/>
+ <Directory Id="instlib" Name="lib">
+ <Directory Id="instlib_debug" Name="debug"/>
+ <Directory Id="instlib_plugin" Name="plugin"/>
+ </Directory>
+ <Directory Id="instinclude" Name="include" >
+ <Directory Id="instincludemysql" Name="mysql"/>
+ <Directory Id="instincludemariadb" Name="mariadb"/>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Directory>
+ </Fragment>
+
+<Fragment>
+ <Component Id="RegistryKeys" Guid="755726EA-9706-413D-86B3-E70582FF2819" DiskId="1" Directory="INSTALLFOLDER" Win64="@IS_WIN64@">
+ <RegistryKey Id="Version" Root="HKLM" Key="SOFTWARE\@PRODUCT_MANUFACTURER@\@PRODUCT_NAME@" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
+ <RegistryValue Name="Version" Type="string" Value="@PRODUCT_VERSION@"/>
+ </RegistryKey>
+ </Component>
+ <Component Id="Library" Guid="89E28283-23AE-4F10-B743-B5FA485E9F9A" KeyPath="yes" DiskId="1" Directory="instlib" Win64="@IS_WIN64@">
+ <Environment Id="LIB_PATH" Name="PATH" Value="[instlib]" Permanent="no" Action="set" Part="last" System="yes"/>
+ <File Id="libdll" Name="libmariadb.dll" DiskId="1" Source="@CLIENT_LIB_DIR@/libmariadb.dll" />
+ <File Id="libdllimp" Name="libmariadb.lib" DiskId="1" Source="@CLIENT_LIB_DIR@/libmariadb.lib" />
+ <File Id="libstatic" Name="mariadbclient.lib" DiskId="1" Source="@CLIENT_LIB_DIR@/mariadbclient.lib" />
+ <File Id="libpdb" Name="libmariadb.pdb" DiskId="1" Source="@CLIENT_LIB_DIR@/libmariadb.pdb" />
+ </Component>
+ <Component Id="Binaries" Guid="4b074269-7d81-11e5-8cf9-a0a8cd7fad46" KeyPath="yes" DiskId="1" Directory="inst_bin" Win64="@IS_WIN64@">
+ <!--
+ <File Id="mariadb_client_plugin_info" Name="mariadb_clent_plugin_info.exe" DiskId="1"
+ Source="@CLIENT_BIN_DIR@/mariadb_client_plugin_info.exe" />
+ -->
+ </Component>
+ <Component Id="Plugins" Guid="5B2E98C9-DFF2-4129-8360-C6AD16F6BBEA" KeyPath="yes" DiskId="1" Directory="instlib_plugin" Win64="@IS_WIN64@">
+ <Environment Id="PLUGIN_PATH" Name="PATH" Value="[instlib_plugin]" Permanent="no" Action="set" Part="last" System="yes"/>
+ @MARIADB_PLUGINS@
+ </Component>
+ <Component Id="Includes" Guid="5CFB93CC-FC30-4E13-B665-E52690AB56E3" KeyPath="yes" Directory="instinclude" DiskId="1" Win64="@IS_WIN64@">
+ @MARIADB_INCLUDE_FILES@
+ </Component>
+ <Component Id="MysqlIncludes" Guid="6BD3D62D-8013-4C0A-B032-61AA04A98EDE" Directory="instincludemysql" DiskId="1" Win64="@IS_WIN64@">
+ <CreateFolder/>
+ @MARIADB_INCLUDEMYSQL_FILES@
+ </Component>
+ <Component Id="MariadbIncludes" Guid="DEFD4D6B-0143-442A-BEB8-C041F7156BF1" Directory="instincludemariadb" DiskId="1" Win64="@IS_WIN64@">
+ <CreateFolder/>
+ @MARIADB_INCLUDEMARIADB_FILES@
+ </Component>
+</Fragment>
+</Wix>
+
diff --git a/libmariadb/win/resource.rc.in b/libmariadb/win/resource.rc.in
new file mode 100644
index 00000000..0b3e5976
--- /dev/null
+++ b/libmariadb/win/resource.rc.in
@@ -0,0 +1,34 @@
+#include "winver.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @MAJOR_FILE_VERSION@,@MINOR_FILE_VERSION@,@PATCH_FILE_VERSION@,@TINY_FILE_VERSION@
+ PRODUCTVERSION @MAJOR_FILE_VERSION@,@MINOR_FILE_VERSION@,@PATCH_FILE_VERSION@,@TINY_FILE_VERSION@
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE @FILE_TYPE@
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "MariaDB Corporation AB"
+ VALUE "FileDescription", "@FILE_DESCRIPTION@"
+ VALUE "FileVersion", "@CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@.@CPACK_PACKAGE_VERSION_PATCH@.@FILE_VERSION@"
+ VALUE "LegalCopyright", "2013-2018 MariaDB Corporation Ab"
+ VALUE "ProductName", "MariaDB Connector/C"
+ VALUE "ProductVersion", "@CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@.@CPACK_PACKAGE_VERSION_PATCH@"
+ VALUE "OriginalFilename", "@ORIGINAL_FILE_NAME@"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+