summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-11-30 22:37:25 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-12-06 15:11:04 +0300
commitf1f39911e0d2d88c98eae96a3eb14a53c664206f (patch)
tree4cf4e3a84d895f59323d3b6ab4bfab38b3cab489
parentfc9499b8a7b7a3e350bfabf2cd6ae0bc13f04bea (diff)
Upgrade to 12.1
-rw-r--r--.gitignore20
-rw-r--r--.gitmodules4
-rw-r--r--COPYRIGHT23
-rw-r--r--README-DEV212
-rw-r--r--TODO14
-rw-r--r--build/bootstrap.build44
-rw-r--r--buildfile10
-rw-r--r--libpq/.gitignore20
l---------libpq/COPYRIGHT1
-rw-r--r--libpq/INSTALL (renamed from INSTALL)0
-rw-r--r--libpq/README (renamed from README)2
-rw-r--r--libpq/README-DEV77
-rw-r--r--libpq/build/.gitignore (renamed from build/.gitignore)0
-rw-r--r--libpq/build/bootstrap.build40
-rw-r--r--libpq/build/export.build (renamed from build/export.build)0
-rw-r--r--libpq/build/root.build (renamed from build/root.build)3
-rw-r--r--libpq/buildfile188
-rw-r--r--libpq/chklocale.c445
-rw-r--r--libpq/encnames.c553
-rw-r--r--libpq/fe-auth.c841
-rw-r--r--libpq/fe-auth.h24
-rw-r--r--libpq/fe-connect.c6002
-rw-r--r--libpq/fe-exec.c3764
-rw-r--r--libpq/fe-lobj.c1103
-rw-r--r--libpq/fe-misc.c1267
-rw-r--r--libpq/fe-print.c761
-rw-r--r--libpq/fe-protocol2.c1623
-rw-r--r--libpq/fe-protocol3.c2204
-rw-r--r--libpq/fe-secure.c505
-rw-r--r--libpq/getpeereid.c80
-rw-r--r--libpq/inet_net_ntop.c298
-rw-r--r--libpq/ip.c819
-rw-r--r--libpq/libpq-events.c209
-rw-r--r--libpq/libpq-events.h94
-rw-r--r--libpq/libpq-fe.h607
-rw-r--r--libpq/libpq-int.h675
-rw-r--r--libpq/libpq/.gitignore3
-rw-r--r--libpq/libpq/buildfile233
l---------libpq/libpq/common/base64.c1
l---------libpq/libpq/common/ip.c1
l---------libpq/libpq/common/link-canary.c1
l---------libpq/libpq/common/md5.c1
l---------libpq/libpq/common/saslprep.c1
l---------libpq/libpq/common/scram-common.c1
l---------libpq/libpq/common/sha2_openssl.c1
l---------libpq/libpq/common/unicode_norm.c1
l---------libpq/libpq/include/c.h1
l---------libpq/libpq/include/common1
l---------libpq/libpq/include/getaddrinfo.h1
l---------libpq/libpq/include/libpq/libpq-fs.h1
l---------libpq/libpq/include/libpq/pqcomm.h1
l---------libpq/libpq/include/mb/pg_wchar.h1
l---------libpq/libpq/include/pg_config_manual.h1
l---------libpq/libpq/include/port.h1
l---------libpq/libpq/include/port/darwin.h1
l---------libpq/libpq/include/port/freebsd.h1
l---------libpq/libpq/include/port/linux.h1
l---------libpq/libpq/include/port/pg_bswap.h1
l---------libpq/libpq/include/port/win321
l---------libpq/libpq/include/port/win32.h1
l---------libpq/libpq/include/port/win32_msvc1
l---------libpq/libpq/include/port/win32_port.h1
l---------libpq/libpq/include/postgres_ext.h1
l---------libpq/libpq/include/postgres_fe.h1
-rw-r--r--libpq/libpq/libpqdll.def178
-rw-r--r--libpq/libpq/libpqdll.map178
l---------libpq/libpq/mb/encnames.c1
l---------libpq/libpq/mb/wchar.c1
-rw-r--r--libpq/libpq/pg_config.h (renamed from libpq/postgresql/pg_config.h)107
l---------libpq/libpq/pg_config.h.in.orig1
l---------libpq/libpq/pg_config.h.win32.orig1
-rw-r--r--libpq/libpq/pg_config_ext.h (renamed from libpq/postgresql/pg_config_ext.h)7
l---------libpq/libpq/pg_config_ext.h.in.orig1
l---------libpq/libpq/pg_config_ext.h.win32.orig1
-rw-r--r--libpq/libpq/pg_config_os.h21
-rw-r--r--libpq/libpq/pg_config_paths.h11
l---------libpq/libpq/port/chklocale.c1
l---------libpq/libpq/port/getaddrinfo.c1
l---------libpq/libpq/port/getpeereid.c1
l---------libpq/libpq/port/inet_aton.c1
l---------libpq/libpq/port/inet_net_ntop.c1
l---------libpq/libpq/port/noblock.c1
l---------libpq/libpq/port/open.c1
l---------libpq/libpq/port/pg_strong_random.c1
l---------libpq/libpq/port/pgsleep.c1
l---------libpq/libpq/port/pgstrcasecmp.c1
l---------libpq/libpq/port/pthread-win32.h1
l---------libpq/libpq/port/snprintf.c1
l---------libpq/libpq/port/strerror.c1
l---------libpq/libpq/port/strlcpy.c1
l---------libpq/libpq/port/system.c1
l---------libpq/libpq/port/thread.c1
l---------libpq/libpq/port/win32error.c1
l---------libpq/libpq/port/win32setlocale.c1
l---------libpq/libpq/pq1
-rw-r--r--libpq/libpq/version.h.in17
-rw-r--r--libpq/manifest (renamed from manifest)13
-rw-r--r--libpq/md5.c345
-rw-r--r--libpq/noblock.c66
-rw-r--r--libpq/non-bsd/strlcpy.c71
-rw-r--r--libpq/pg_service.conf.sample17
-rw-r--r--libpq/pgstrcasecmp.c151
-rw-r--r--libpq/postgresql/c.h1107
-rw-r--r--libpq/postgresql/common/fe_memutils.h44
-rw-r--r--libpq/postgresql/getaddrinfo.h164
-rw-r--r--libpq/postgresql/libpq/ip.h51
-rw-r--r--libpq/postgresql/libpq/libpq-fs.h24
-rw-r--r--libpq/postgresql/libpq/md5.h30
-rw-r--r--libpq/postgresql/libpq/pqcomm.h206
-rw-r--r--libpq/postgresql/mb/pg_wchar.h561
-rw-r--r--libpq/postgresql/pg_config.h.in.orig931
-rw-r--r--libpq/postgresql/pg_config.h.win32.orig682
-rw-r--r--libpq/postgresql/pg_config_ext.h.in.orig7
-rw-r--r--libpq/postgresql/pg_config_ext.h.win32.orig7
-rw-r--r--libpq/postgresql/pg_config_manual.h327
-rw-r--r--libpq/postgresql/pg_config_paths.h1
-rw-r--r--libpq/postgresql/port.h477
-rw-r--r--libpq/postgresql/port/bsd/pg_config_os.h0
-rw-r--r--libpq/postgresql/port/darwin/pg_config_os.h8
-rw-r--r--libpq/postgresql/port/linux/pg_config_os.h22
-rw-r--r--libpq/postgresql/port/win32/arpa/inet.h3
-rw-r--r--libpq/postgresql/port/win32/netdb.h1
-rw-r--r--libpq/postgresql/port/win32/netinet/in.h3
-rw-r--r--libpq/postgresql/port/win32/pg_config_os.h486
-rw-r--r--libpq/postgresql/port/win32/pthread-win32.h22
-rw-r--r--libpq/postgresql/port/win32/pwd.h3
-rw-r--r--libpq/postgresql/port/win32/sys/socket.h33
-rw-r--r--libpq/postgresql/port/win32/sys/wait.h3
-rw-r--r--libpq/postgresql/port/win32_msvc/sys/file.h1
-rw-r--r--libpq/postgresql/port/win32_msvc/sys/param.h1
-rw-r--r--libpq/postgresql/port/win32_msvc/sys/time.h1
-rw-r--r--libpq/postgresql/port/win32_msvc/unistd.h1
-rw-r--r--libpq/postgresql/postgres_ext.h70
-rw-r--r--libpq/postgresql/postgres_fe.h29
-rw-r--r--libpq/pqexpbuffer.c430
-rw-r--r--libpq/pqexpbuffer.h182
-rw-r--r--libpq/pqsignal.c90
-rw-r--r--libpq/tests/.gitignore (renamed from tests/.gitignore)0
-rw-r--r--libpq/tests/build/.gitignore (renamed from tests/build/.gitignore)0
-rw-r--r--libpq/tests/build/bootstrap.build (renamed from tests/build/bootstrap.build)0
-rw-r--r--libpq/tests/build/root.build (renamed from tests/build/root.build)2
-rw-r--r--libpq/tests/buildfile (renamed from tests/buildfile)0
-rw-r--r--libpq/tests/conninfo/buildfile (renamed from tests/conninfo/buildfile)4
-rw-r--r--libpq/tests/conninfo/driver.c (renamed from tests/conninfo/driver.c)4
-rw-r--r--libpq/tests/conninfo/expected.out (renamed from tests/conninfo/expected.out)0
-rw-r--r--libpq/tests/conninfo/postgres_fe.h19
-rw-r--r--libpq/tests/conninfo/regress.in (renamed from tests/conninfo/regress.in)0
-rw-r--r--libpq/tests/conninfo/testscript (renamed from tests/conninfo/testscript)0
l---------libpq/tests/conninfo/uri-regress.c1
-rw-r--r--libpq/thread.c146
-rw-r--r--libpq/version.h.in26
-rw-r--r--libpq/wchar.c2054
-rw-r--r--libpq/win32/crypt.c1085
-rw-r--r--libpq/win32/getaddrinfo.c412
-rw-r--r--libpq/win32/inet_aton.c147
-rw-r--r--libpq/win32/libpq.rc.in31
-rw-r--r--libpq/win32/libpqdll.def174
-rw-r--r--libpq/win32/libpqdll.def.orig174
-rw-r--r--libpq/win32/open.c167
-rw-r--r--libpq/win32/pgsleep.c63
-rw-r--r--libpq/win32/pthread-win32.c61
-rw-r--r--libpq/win32/pthread-win32.h22
-rw-r--r--libpq/win32/snprintf.c1141
-rw-r--r--libpq/win32/system.c119
-rw-r--r--libpq/win32/win32.c327
-rw-r--r--libpq/win32/win32.h40
-rw-r--r--libpq/win32/win32error.c206
-rw-r--r--libpq/win32/win32setlocale.c189
-rw-r--r--packages.manifest2
-rw-r--r--repositories.manifest6
-rw-r--r--tests/conninfo/postgres_fe.h19
-rw-r--r--tests/conninfo/uri-regress.c84
m---------upstream0
173 files changed, 1098 insertions, 35636 deletions
diff --git a/.gitignore b/.gitignore
index c3de2e7..13d880b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,21 +1 @@
.bdep/
-
-# Compiler/linker output.
-#
-*.d
-*.t
-*.i
-*.ii
-*.o
-*.obj
-*.so
-*.dll
-*.a
-*.lib
-*.exp
-*.pdb
-*.ilk
-*.exe
-*.exe.dlls/
-*.exe.manifest
-*.pc
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..c8379c3
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "upstream"]
+ path = upstream
+ url = https://git.postgresql.org/git/postgresql.git
+ ignore = untracked
diff --git a/COPYRIGHT b/COPYRIGHT
deleted file mode 100644
index c320ecc..0000000
--- a/COPYRIGHT
+++ /dev/null
@@ -1,23 +0,0 @@
-PostgreSQL Database Management System
-(formerly known as Postgres, then as Postgres95)
-
-Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
-
-Portions Copyright (c) 1994, The Regents of the University of California
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose, without fee, and without a written agreement
-is hereby granted, provided that the above copyright notice and this
-paragraph and the following two paragraphs appear in all copies.
-
-IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
-DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
-LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
-DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
-ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
-PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
diff --git a/README-DEV b/README-DEV
index acdefd9..c7ba5e1 100644
--- a/README-DEV
+++ b/README-DEV
@@ -1,102 +1,120 @@
-This document describes how libpq was packaged for build2. In particular,
-this understanding will be useful when ugrading to a new upstream version.
-
-The original libpq library is packaged together with the PostgreSQL server and
-client utilities. Most of the libpq source files are located in the
-src/interfaces/libpq/ directory. Some .c files are symlinked (copied on
-Windows) from other src/ subdirectories during make. So run configure script
-in the package root, run make in src/interfaces/libpq/ and then copy source
-files and symlink targets into libpq/ directory of the build2 package. Note
-that to obtain the full set of source files that includes Windows-specific
-ones, you should perform these steps in the MSYS2/MinGW environment. Copy
-Windows-specific files and strlcpy.c to libpq/win32/ and libpq/non-bsd/
-directories respectively. Also copy src/port/pthread-win32.h to libpq/ (next
-to pthread-win32.c).
-
-Note that the library name in the .def file takes precedence over the one
-specified in the linker command line for both VC and MinGW GCC. So we comment
-it out in libpq/win32/libpqdll.def.
-
-Besides libpq-specific files some of the PostgreSQL common headers are also
-required. All of them except one (see below) are located in src/include/
-subdirectories. Copy them into the libpq/postgresql/ directory, preserving the
-original directory structure, with the following exceptions:
-
- * src/include/pg_config_os.h
-
- This is a symlink referencing the target-specific header in the
- src/include/port/ directory, created by the configure script. Copy these
- headers under postgresql/port/*/pg_config_os.h path names for the supported
- target classes. For example, copy src/include/port/linux.h to
- libpq/postgresql/port/linux/pg_config_os.h. During compilation the
- '-I.../libpq/postgresql/port/linux' option will be passed to the compiler,
- so the appropriate pg_config_os.h is picked up.
-
- * src/port/pg_config_paths.h
-
- This file is generated by src/port/Makfile and defines several directory
- path macros. Only SYSCONFDIR macro is used in libpq source files. Make the
- file empty and place it into libpq/postgresql directory. During compilation
- the macro will be defined with -DSYSCONFDIR preprocessor option.
-
- * src/include/pg_config.h.in,
- src/include/pg_config.h.win32
- pg_config_ext.h.in
- pg_config_ext.h.win32
-
- Use as sources for the manual creation of libpq/postgresql/pg_config.h and
- libpq/postgresql/pg_config_ext.h, that are used for all target systems.
- Also add the source headers to the package appending the '.orig' extension
- to their names.
-
-By default the original package installs the library into the /usr/local/pgsql
-directory. There are also several 'unofficial API' headers installed into the
-/usr/local/pgsql/include/internal directory. If installing at some custom
-location that has no postgresql or pgsql words in its path, then it becomes
-<custom-location>/include/postgresql/internal. We currently do not install
-unofficial API headers.
-
-For the record, the PostgreSQL binary and development packages install
-libraries and headers into the following directories:
-
-Debian/Ubuntu:
- /usr/lib/x86_64-linux-gnu
- /usr/include/postgresql
- /usr/include/postgresql/internal
-
-Fedora/RHEL:
- /usr/lib64
- /usr/include
- /usr/include/pgsql/internal
-
-When merge libpq build2 package with a new version of the original package
-make sure that all the preprocessor include directives reference the packaged
-header files, rather than PostgreSQL headers that are installed into the
-system. It's easy to miss some headers in the package if the PostgreSQL
-development package is installed on the host. To verify the correctness you
-can build the merged project, concatenate the produced .d files, sort the
-resulting file removing duplicates and edit the result, leaving only the
-system headers. Afterwards grep through the remained headers for the
-'PostgreSQL' pattern:
+This document describes an approach applied to packaging PostgreSQL for
+build2. In particular, this understanding will be useful when upgrading to a
+new upstream version.
-$ cat `find . -name '*.d'` | sort -u >headers
-$ emacs headers # Edit, leaving system headers only.
-$ fgrep PostgreSQL `cat headers`
+The upstream package contains the PostgreSQL server, libpq library, and client
+utilities. Currently, we only package libpq (see libpq/README-DEV for
+details).
+
+We add the upstream package as a git submodule and symlink the required files
+and subdirectories into the build2 package subdirectories. Then, when required,
+we "overlay" the upstream with our own headers, placing them into the library
+directory.
+
+Note that symlinking upstream submodule subdirectories into a build2 package
+subdirectory results in creating intermediate build files (.d, .o, etc) inside
+upstream directory while building the package in source tree. That's why we
+need to make sure that packages do not share upstream source files via
+subdirectory symlinks, not to also share the related intermediate files. If
+several packages need to compile the same upstream source file, then only one
+of them can symlink it via the parent directory while others must symlink it
+directly. We also add the `ignore = untracked` configuration option into
+.gitmodules to make sure that git ignores the intermediate build files under
+upstream/ subdirectory.
+
+The upstream package can be configured to contain a specific feature set. We
+reproduce the union of features configured for the upstream source package in
+Debian and Fedora distributions. The configuration options defining these sets
+are specified in the Debian's rules and Fedora's RPM .spec files. Note,
+that at the time of this writing the latest packaged versions are different
+(12.1 on Debian and 11.6 on Fedora). That's probably ok since 12.1 doesn't
+introduce any new configuration options comparing to 11.6. These files can be
+obtained as follows:
+
+$ wget http://deb.debian.org/debian/pool/main/p/postgresql-12/postgresql-12_12.1-1.debian.tar.xz
+$ tar xf postgresql-12_12.1-1.debian.tar.xz debian/rules
+
+$ wget https://kojipkgs.fedoraproject.org/packages/libpq/11.6/1.fc32/src/libpq-11.6-1.fc32.src.rpm
+$ rpm2cpio libpq-11.6-1.fc32.src.rpm | cpio -civ '*.spec'
+
+As a side note, on Debian and Fedora the source, library, and headers are
+packaged as follows:
+
+ src libpq headers
+Debian/Ubuntu: postgresql-12 libpq5 libpq-dev
+Fedora/RHEL: libpq libpq libpq-devel
+
+Search for the Debian and Fedora packages at https://packages.debian.org/search
+and https://apps.fedoraproject.org/packages/.
+
+Here are the discovered configuration options.
+
+Debian:
+
+ --with-icu --with-tcl --with-perl --with-python --with-pam --with-openssl
+ --with-libxml --with-libxslt --enable-nls --enable-integer-datetimes
+ --with-gssapi --with-ldap --enable-thread-safety
+
+Fedora:
+
+ --with-ldap --with-openssl --with-gssapi --enable-nls --without-readline
+
+The union of these feature sets translates into the following options, after
+suppressing the defaults:
-Also make sure that the macros set in libpq/postgresql/pg_config.h is still up
-to date. For that purpose obtain the macros that are used in the new source
-base, then obtain the macros (un)defined in the current
-libpq/postgresql/pg_config.h and compare the sets. That can be achieved
-running the following commands in the build2 project root directory:
+ --with-icu --with-tcl --with-perl --with-python --with-pam --with-openssl
+ --with-libxml --with-libxslt --enable-nls --with-gssapi --with-ldap
-$ for m in `cat libpq/postgresql/pg_config.h.in.orig libpq/postgresql/pg_config.h.win32.orig | sed -n 's/.*#\s*\(define\|undef\)\s\{1,\}\([_A-Z0-9]\{1,\}\)\(\s.*\)\{0,1\}$/\2/p' | sort -u`; do
- if grep -q -e "\b$m\b" `find . -name '*.h' -a ! -name 'pg_config.h' -o -name '*.c'`; then
- echo "$m"
- fi
- done >used-macros
+We, however, drop the external dependencies that are not packaged for build2
+and end up with the following options:
-$ cat libpq/postgresql/pg_config.h |
- sed -n 's/#\s*\(define\|undef\)\s\{1,\}\([_A-Z0-9]\{1,\}\)\(\s.*\)\{0,1\}$/\2/p' |
- sort -u >defined-macros
+ --with-openssl --without-readline --without-zlib
-$ diff defined-macros used-macros
+See the configuration options description at the "Installation Procedure" page
+(https://www.postgresql.org/docs/current/install-procedure.html).
+
+Normally, when packaging a project, we need to replace some auto-generated
+headers with our own implementations and deduce compilation/linking options.
+For PostgreSQL we can rely on the configure.in, GNUmakefile.in, and the
+manually maintained makefiles for that. In practice, however, that can be
+uneasy and error prone, so you may also need to refer to auto-generated
+header files or to see the actual compiler and linker command lines in the
+build log. If that's the case, you can configure/build the upstream package on
+the platform of interest running the following commands in the upstream
+project root directory.
+
+On POSIX and for MinGW GCC:
+
+$ mkdir build
+$ cd build
+$ ../configure --with-openssl --without-readline --without-zlib >build.log 2>&1
+$ cd src/interfaces/libpq
+$ make >>../../../build.log 2>&1
+
+See the "Installation from Source Code" page
+(https://www.postgresql.org/docs/current/installation.html) for details.
+
+For MSVC:
+
+Add bison and flex to PATH, if building in the git repository. Install
+OpenSSL.
+
+> cd src\tools\msvc
+
+Edit config_default.pl to enable OpenSSL:
+
+ openssl => 'c:\OpenSSL', # --with-openssl=<path>
+
+> build libpq >>build.log 2>&1
+
+See the "Building with Visual C++ or the Microsoft Windows SDK" page
+(https://www.postgresql.org/docs/current/install-windows-full.html) for
+details.
+
+When the packaging is complete, build all the project packages in source tree
+and make sure that no PostgreSQL headers are included from the system, running
+the following commands from the project root:
+
+$ cat `find . -name '*.d'` | sort -u >headers
+$ emacs headers # Edit, leaving system headers only.
+$ fgrep PostgreSQL <headers
diff --git a/TODO b/TODO
deleted file mode 100644
index 49528d6..0000000
--- a/TODO
+++ /dev/null
@@ -1,14 +0,0 @@
-@@ Should we enable/make configurable Native Language Support? See --enable-nls
- configure option (off by default, at least for locale with
- LANG=en_US.UTF-8), ENABLE_NLS macro, libintl.h, src/interfaces/libpq/po/ for
- details.
-
-@@ Should we make configurable OpenSSL support? See --with-openssl configure
- option, fe-secure-openssl.c (should also be compiled/linked), USE_OPENSSL
- macro for details.
-
-@@ Should we make configurable LDAP support? See --with-ldap configure option,
- USE_LDAP macro.
-
-@@ Should we make configurable GSSAPI support? See --with-gssapi configure
- option, ENABLE_GSS macro.
diff --git a/build/bootstrap.build b/build/bootstrap.build
deleted file mode 100644
index d950149..0000000
--- a/build/bootstrap.build
+++ /dev/null
@@ -1,44 +0,0 @@
-# file : build/bootstrap.build
-# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
-# license : PostgreSQL License; see accompanying COPYRIGHT file
-
-project = libpq
-
-using version
-using config
-using dist
-using test
-using install
-
-# PostgreSQL releases (for quite a long time) had the 3-component versions,
-# where the first 2 components denote a major version and the third one the
-# minor version. This has changed starting from version 10, with the major
-# version represented by a single component. Minor releases are guaranteed to
-# be backwards-compatible and contain only bug fixes. See also:
-#
-# https://www.postgresql.org/support/versioning/
-#
-# There is no document that describes libpq ABI versioning and compatibility
-# rules, so everything that follows is just a guess.
-#
-# The library naming schema on POSIX is libpq.so.<so_major>.<so_minor> with
-# the so_minor number incremented with each major release unless the so_major
-# number is incremented, in which case it is reset to 0. It is unclear when
-# the so_major is incremented (it, for example, hasn't been in the 9.6 to
-# 10 transition).
-#
-# The <so_major>.<so_minor> pair constitutes the version of the ABI that is
-# backwards-compatible between PostgreSQL minor releases. However, we can not
-# deduce the ABI version from the release major version and will have to check
-# it for each major release by examining the SO_MAJOR_VERSION and
-# SO_MINOR_VERSION variables in src/interfaces/libpq/Makefile.
-#
-if ($version.major == 9 && $version.minor == 6)
-{
- abi_major = 5
- abi_minor = 9
-}
-else
- fail "increment the ABI version?"
-
-abi_version = $abi_major.$abi_minor
diff --git a/buildfile b/buildfile
deleted file mode 100644
index 4f873b0..0000000
--- a/buildfile
+++ /dev/null
@@ -1,10 +0,0 @@
-# file : buildfile
-# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
-# license : PostgreSQL License; see accompanying COPYRIGHT file
-
-./: {*/ -build/} doc{COPYRIGHT INSTALL README} manifest
-
-# Don't install tests or the INSTALL file.
-#
-tests/: install = false
-doc{INSTALL}@./: install = false
diff --git a/libpq/.gitignore b/libpq/.gitignore
index 620b4c8..cece09c 100644
--- a/libpq/.gitignore
+++ b/libpq/.gitignore
@@ -1,3 +1,19 @@
-# Generated version.h.
+# Compiler/linker output.
#
-version.h
+*.d
+*.t
+*.i
+*.ii
+*.o
+*.obj
+*.so
+*.dll
+*.a
+*.lib
+*.exp
+*.pdb
+*.ilk
+*.exe
+*.exe.dlls/
+*.exe.manifest
+*.pc
diff --git a/libpq/COPYRIGHT b/libpq/COPYRIGHT
new file mode 120000
index 0000000..945f098
--- /dev/null
+++ b/libpq/COPYRIGHT
@@ -0,0 +1 @@
+../upstream/COPYRIGHT \ No newline at end of file
diff --git a/INSTALL b/libpq/INSTALL
index 61ec557..61ec557 100644
--- a/INSTALL
+++ b/libpq/INSTALL
diff --git a/README b/libpq/README
index 4aa73f2..f57e7a7 100644
--- a/README
+++ b/libpq/README
@@ -8,6 +8,8 @@ https://www.postgresql.org/
This package contains the original libpq library source code overlaid with the
build2-based build system and packaged for the build2 package manager (bpkg).
+See the INSTALL file for the prerequisites and installation instructions.
+
Send questions, bug reports, or any other feedback about the library itself to
the PostgreSQL mailing lists. Send build system and packaging-related feedback
to the packaging@build2.org mailing list (see https://lists.build2.org for
diff --git a/libpq/README-DEV b/libpq/README-DEV
new file mode 100644
index 0000000..cadfe63
--- /dev/null
+++ b/libpq/README-DEV
@@ -0,0 +1,77 @@
+This document describes how libpq was packaged for build2. In particular, this
+understanding will be useful when upgrading to a new upstream version. See
+../README-DEV for general notes on PostgreSQL packaging.
+
+The upstream package builds the common and ports static libraries and links
+them to the libpq library. These static libraries are generic enough to fit
+all the binaries built by the package. We will build libpq selecting only the
+required static libraries source files, relying on the linker diagnostics
+(unresolved symbol errors, etc).
+
+Symlink the required upstream components and provide our own implementations
+for auto-generated headers:
+
+$ ln -s ../upstream/COPYRIGHT
+
+Note that we symlink the libpq directory under the different name not to
+confuse the headers auto-generating machinery while it maps the header
+directory prefixes.
+
+$ ln -s ../../upstream/src/interfaces/libpq libpq/pq
+
+Note that while we could symlink the upstream's top source directories, this
+would potentially bloat the distribution, uglify the buildfile, and complicate
+pg_config.h change tracking on upgrade (see below). Thus, we selectively
+symlink only the required files.
+
+$ mkdir libpq/mb
+$ ln -s ../../../upstream/src/backend/utils/mb/{encnames,wchar}.c libpq/mb
+
+$ mkdir -p libpq/include/libpq libpq/include/mb libpq/include/port
+$ ln -s ../../../upstream/src/include/{c,getaddrinfo,pg_config_manual,port,postgres_ext,postgres_fe}.h libpq/include
+$ ln -s ../../../../upstream/src/include/libpq/{libpq-fs,pqcomm}.h libpq/include/libpq
+$ ln -s ../../../../upstream/src/include/mb/pg_wchar.h libpq/include/mb
+$ ln -s ../../../../upstream/src/include/port/{linux,freebsd,darwin,win32,win32_port,pg_bswap}.h libpq/include/port
+$ ln -s ../../../../upstream/src/include/port/{win32,win32_msvc} libpq/include/port
+
+$ mkdir libpq/common
+$ ln -s ../../../upstream/src/common/{md5,scram-common,ip,sha2_openssl,link-canary,base64,saslprep,unicode_norm}.c \
+ libpq/common
+
+$ mkdir libpq/port
+$ ln -s ../../../upstream/src/port/{pgstrcasecmp,snprintf,getpeereid,pg_strong_random,thread,strerror,chklocale,noblock,inet_net_ntop,strlcpy,win32setlocale,getaddrinfo,open,inet_aton,pgsleep,win32error,system}.c libpq/port
+$ ln -s ../../../upstream/src/port/pthread-win32.h libpq/port
+
+$ ln -s ../../upstream/src/include/pg_config_ext.h.in libpq/pg_config_ext.h.in.orig
+$ ln -s ../../upstream/src/include/pg_config_ext.h.win32 libpq/pg_config_ext.h.win32.orig
+$ ln -s ../../upstream/src/include/pg_config.h.in libpq/pg_config.h.in.orig
+$ ln -s ../../upstream/src/include/pg_config.h.win32 libpq/pg_config.h.win32.orig
+
+$ ln -s ../../../upstream/src/interfaces/libpq/test/uri-regress.c tests/conninfo
+
+Create libpq/{pg_config,pg_config_ext,pg_config_os,pg_config_paths}.h using as
+a base the upstream's auto-generated headers and/or the corresponding
+templates, makefiles, and perl/batch/shell scripts.
+
+Note that re-creating libpq/pg_config.h from scratch every time we upgrade to
+a new upstream version would be a real pain. Instead we can only (un)define
+the newly introduced macros, comparing the already defined and currently used
+macro sets:
+
+$ for m in `cat libpq/pg_config.h.in.orig libpq/pg_config.h.win32.orig | \
+ sed -n 's/.*#\s*\(define\|undef\)\s\{1,\}\([_A-Z0-9]\{1,\}\)\(\s.*\)\{0,1\}$/\2/p' | \
+ sort -u`; do
+ if grep -q -e "\b$m\b" `find -L . -name '*.h' -a ! -name 'pg_config.h' -o -name '*.c'`; then
+ echo "$m"
+ fi
+ done >used-macros
+
+$ cat libpq/pg_config.h | \
+ sed -n 's/#\s*\(define\|undef\)\s\{1,\}\([_A-Z0-9]\{1,\}\)\(\s.*\)\{0,1\}$/\2/p' | \
+ sort -u >defined-macros
+
+$ diff defined-macros used-macros
+
+Copy upstream's auto-generated src/interfaces/libpq/{exports.list,libpqdll.def}
+to libpq/{libpqdll.map,libpqdll.def} or create them manually based on
+pq/exports.txt. Comment out the "LIBRARY LIBPQ" line in libpqdll.def.
diff --git a/build/.gitignore b/libpq/build/.gitignore
index 4a730a3..4a730a3 100644
--- a/build/.gitignore
+++ b/libpq/build/.gitignore
diff --git a/libpq/build/bootstrap.build b/libpq/build/bootstrap.build
new file mode 100644
index 0000000..22b180f
--- /dev/null
+++ b/libpq/build/bootstrap.build
@@ -0,0 +1,40 @@
+# file : build/bootstrap.build
+# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
+# license : PostgreSQL License; see accompanying COPYRIGHT file
+
+project = libpq
+
+using version
+using config
+using dist
+using test
+using install
+
+# PostgreSQL releases (for quite a long time) had the 3-component versions,
+# where the first 2 components denoted a major version and the third one --
+# the minor version. This has changed starting from version 10, with the major
+# version represented by a single component. Minor releases are guaranteed to
+# be backwards-compatible and contain only bug fixes. See also:
+#
+# https://www.postgresql.org/support/versioning/
+#
+# Note that the release version is not a semantic version and we will map it to
+# the standard version as <major>.<minor>.0.
+#
+# There is no document that describes libpq ABI versioning and compatibility
+# rules, so everything that follows is implied from
+# src/interfaces/libpq/Makefile.
+#
+# The library naming schema on Linux is libpq.so.<so_major>.<so_minor>
+# (SO_MAJOR_VERSION and SO_MINOR_VERSION in the Makefile) So presumably
+# so_major is incremented on backwards-incompatible ABI changes (it hasn't
+# been for the several last major version releases). And so_minor is equal to
+# the package major version.
+#
+if ($version.major == 12 && $version.minor == 1)
+{
+ abi_major = 5
+ abi_minor = 12
+}
+else
+ fail "increment the ABI version?"
diff --git a/build/export.build b/libpq/build/export.build
index 748c3ea..748c3ea 100644
--- a/build/export.build
+++ b/libpq/build/export.build
diff --git a/build/root.build b/libpq/build/root.build
index 8ab7774..76b1aa3 100644
--- a/build/root.build
+++ b/libpq/build/root.build
@@ -2,6 +2,9 @@
# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
# license : PostgreSQL License; see accompanying COPYRIGHT file
+# We rely on this in macros/options deduction (see
+# libpq/{buildfile,pg_config.h} for details).
+#
c.std = 99
using c
diff --git a/libpq/buildfile b/libpq/buildfile
index 5a1732b..e2ceea2 100644
--- a/libpq/buildfile
+++ b/libpq/buildfile
@@ -1,188 +1,10 @@
-# file : libpq/buildfile
+# file : buildfile
# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
# license : PostgreSQL Licenes; see accompanying COPYRIGHT file
-# Headers other than these are not installed so treat them as files.
-#
-# @@ Make it postgresql/{postgres_ext.h pg_config_ext.h} when name pattern can
-# be represented with a reversible name.
-#
-# @@ TODO: we should be able to redo it with install=true/false
-#
-h = version.h libpq-fe.h libpq-events.h \
- postgresql/postgres_ext.h postgresql/pg_config_ext.h
-
-lib{pq}: c{*} h{$h} file{**.h -{$h}} def{win32/libpqdll} \
- file{pg_service.conf.sample}
-
-tclass = $c.target.class
-
-bsd = ($tclass == 'bsd')
-macos = ($tclass == 'macos')
-windows = ($tclass == 'windows')
-
-msvc_runtime = ($c.target.system == 'win32-msvc')
-
-gcc = ($c.class == 'gcc')
-msvc = ($c.class == 'msvc')
-
-lib{pq}: win32/c{*}: include = $windows
-lib{pq}: non-bsd/c{*}: include = (($bsd || $macos) == false)
+./: {*/ -build/} doc{COPYRIGHT INSTALL README} manifest
-# The version file is an internal one (it is only included from
-# postgresql/pg_config.h) so we don't distribute nor install it (see below).
+# Don't install tests or the INSTALL file.
#
-h{version}: in{version} $src_root/manifest
-
-# Build options.
-#
-c.poptions += -DFRONTEND -DUNSAFE_STAT_OK -DSO_MAJOR_VERSION=$abi_major
-
-if! $windows
- # Note that the original package uses -pthread compiler/linker option. It is
- # currently unsupported by build2, so we use -D_REENTRANT and -lpthread
- # preprocessor/linker options instead. We also omit -D_THREAD_SAFE (synonym
- # for -D_REENTRANT) and Solaris-specific -D_POSIX_PTHREAD_SEMANTICS.
- #
- # @@ Maybe makes sense to support -pthread in build2, adding -lpthread
- # to pkg-config's Libs.private and to cc.export.libs?
- #
- c.poptions += -D_REENTRANT -D_GNU_SOURCE
-else
- # Note that the original package defines the WIN32 macro for VC only, relying
- # on the fact that MinGW GCC defines it by default. However, the macro
- # disappears from the default ones if to compile with -std=c9x (as we do). So
- # we define it for both VC and MinGW GCC.
- #
- # It's tempting to move this definition to libpq/postgresql/pg_config.h.
- # However this header is not included into all files that use the macro, for
- # example, libpq/win32/open.c.
- #
- c.poptions += -DWIN32
-
-port_dir = ($windows ? "win32" : \
- $macos ? "darwin" : \
- $tclass)
-
-# Note that we add "-I$src_root" for the headers auto-generating machinery to
-# work properly.
-#
-c.poptions =+ "-I$out_root" "-I$src_root" "-I$src_base" \
- "-I$src_base/postgresql/port/$port_dir" \
- "-I$src_base/postgresql"
-
-if $windows
- c.poptions =+ "-I$src_base/win32"
-
-if $msvc_runtime
-{
- c.poptions =+ "-I$src_base/postgresql/port/win32_msvc"
-
- c.poptions += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
-
- # Disable warnings that pop up with /W3.
- #
- if $msvc
- c.coptions += /wd4018 /wd4244 /wd4267
-}
-elif $gcc
-{
- # Omit -fexcess-precision=standard as -std=9x implies it.
- #
- c.coptions += -fno-strict-aliasing -fwrapv
-
- # Disable warnings that pop up with -Wall -Wextra. Upstream doesn't seem to
- # care about these and it is not easy to disable specific warnings in a way
- # that works across compilers/version (some -Wno-* options are only
- # recognized in newer versions).
- #
- c.coptions += -Wno-all -Wno-extra
-}
-
-# Define SYSCONFDIR macro. This path is used as a last resort for the
-# pg_service.conf file search (see libpq/fe-connect.c for details).
-#
-# The whole idea feels utterly broken (hello cross-compilation) so we will
-# just do bare minimum and wait and see.
-#
-# @@ We should probably allow to configure this macros via configuration
-# variable config.libpq.sysconfdir.
-#
-if! $windows
-{
- # For the original package if the resulted sysconfdir path doesn't contain
- # the 'postgres' or 'pgsql' substring then the '/postgresql' suffix is
- # automatically appended (see the original INSTALL file for details). Note
- # that the same rule is applied for the datadir and docdir paths. Also if
- # the root directory is /usr, then the resulting sysconfdir path is
- # /etc/postgresql (rather than /usr/etc/postgresql).
- #
- # Let's do the same for the sysconfdir to increase the chance that libpq
- # will find the configuration file. Note that we don't install anything at
- # this path and don't amend the install.data and install.doc path variables.
- # We also use the same default path as the original package.
- #
- if ($install.root != [null])
- {
- root = $install.resolve($install.root)
- sysconfdir = ($root != /usr ? $root/etc : /etc)
-
- if! $regex.match("$sysconfdir", '.*(pgsql|postgresql).*')
- sysconfdir = $sysconfdir/postgresql
- }
- else
- sysconfdir = /usr/local/pgsql/etc
-}
-else
-{
- # win32.mak from the original package does this.
- #
- sysconfdir = ""
-}
-
-# If we ever enable National Language Support (ENABLE_NLS macro) then we will
-# need to define the LOCALEDIR macro as well. It refers to the locale data
-# directory and should be $install.data/locale by default. We will also need
-# to install this directory (see configure script --enable-nls options and the
-# src/interfaces/libpq/po directory in the original package for details).
-#
-obj{fe-connect}: c.poptions += -DSYSCONFDIR="\"$sysconfdir\""
-
-if! $windows
- c.libs += -lpthread
-else
- # The original package also adds the resource file to the library. The file
- # contains only the version information. First, libpq.rc is produced from
- # libpq.rc.in with the following command:
- #
- # sed -e 's/\(VERSION.*\),0 *$/\1,'`date '+%y%j' | \
- # sed 's/^0*//'`'/' libpq.rc.in >libpq.rc
- #
- # Then libpq.rc is compiled with:
- #
- # windres -i libpq.rc -o libpqrc.o
- #
- # Afterwards libpqrc.o is linked to the library.
- #
- # @@ Currently we don't have support for the first two steps.
- #
- c.libs += $regex.apply(secur32 ws2_32 advapi32, \
- '(.+)', \
- $msvc_runtime ? '\1.lib' : '-l\1')
-
-# Export options.
-#
-lib{pq}: cc.export.poptions = "-I$src_base" "-I$src_base/postgresql"
-
-# See bootstrap.build for details.
-#
-if $version.pre_release
- lib{pq}: bin.lib.version = @"-$version.project_id"
-else
- lib{pq}: bin.lib.version = @"-$abi_version"
-
-# Internal header (see above).
-#
-h{version}: install = false
-
-file{pg_service.conf.sample}@./: install = data/
+tests/: install = false
+doc{INSTALL}@./: install = false
diff --git a/libpq/chklocale.c b/libpq/chklocale.c
deleted file mode 100644
index 3c0ef6a..0000000
--- a/libpq/chklocale.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * chklocale.c
- * Functions for handling locale-related info
- *
- *
- * Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- *
- * IDENTIFICATION
- * src/port/chklocale.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#if defined(WIN32) && (_MSC_VER >= 1900)
-#include <windows.h>
-#endif
-
-#include <locale.h>
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-
-#include "mb/pg_wchar.h"
-
-
-/*
- * This table needs to recognize all the CODESET spellings for supported
- * backend encodings, as well as frontend-only encodings where possible
- * (the latter case is currently only needed for initdb to recognize
- * error situations). On Windows, we rely on entries for codepage
- * numbers (CPnnn).
- *
- * Note that we search the table with pg_strcasecmp(), so variant
- * capitalizations don't need their own entries.
- */
-struct encoding_match
-{
- enum pg_enc pg_enc_code;
- const char *system_enc_name;
-};
-
-static const struct encoding_match encoding_match_list[] = {
- {PG_EUC_JP, "EUC-JP"},
- {PG_EUC_JP, "eucJP"},
- {PG_EUC_JP, "IBM-eucJP"},
- {PG_EUC_JP, "sdeckanji"},
- {PG_EUC_JP, "CP20932"},
-
- {PG_EUC_CN, "EUC-CN"},
- {PG_EUC_CN, "eucCN"},
- {PG_EUC_CN, "IBM-eucCN"},
- {PG_EUC_CN, "GB2312"},
- {PG_EUC_CN, "dechanzi"},
- {PG_EUC_CN, "CP20936"},
-
- {PG_EUC_KR, "EUC-KR"},
- {PG_EUC_KR, "eucKR"},
- {PG_EUC_KR, "IBM-eucKR"},
- {PG_EUC_KR, "deckorean"},
- {PG_EUC_KR, "5601"},
- {PG_EUC_KR, "CP51949"},
-
- {PG_EUC_TW, "EUC-TW"},
- {PG_EUC_TW, "eucTW"},
- {PG_EUC_TW, "IBM-eucTW"},
- {PG_EUC_TW, "cns11643"},
- /* No codepage for EUC-TW ? */
-
- {PG_UTF8, "UTF-8"},
- {PG_UTF8, "utf8"},
- {PG_UTF8, "CP65001"},
-
- {PG_LATIN1, "ISO-8859-1"},
- {PG_LATIN1, "ISO8859-1"},
- {PG_LATIN1, "iso88591"},
- {PG_LATIN1, "CP28591"},
-
- {PG_LATIN2, "ISO-8859-2"},
- {PG_LATIN2, "ISO8859-2"},
- {PG_LATIN2, "iso88592"},
- {PG_LATIN2, "CP28592"},
-
- {PG_LATIN3, "ISO-8859-3"},
- {PG_LATIN3, "ISO8859-3"},
- {PG_LATIN3, "iso88593"},
- {PG_LATIN3, "CP28593"},
-
- {PG_LATIN4, "ISO-8859-4"},
- {PG_LATIN4, "ISO8859-4"},
- {PG_LATIN4, "iso88594"},
- {PG_LATIN4, "CP28594"},
-
- {PG_LATIN5, "ISO-8859-9"},
- {PG_LATIN5, "ISO8859-9"},
- {PG_LATIN5, "iso88599"},
- {PG_LATIN5, "CP28599"},
-
- {PG_LATIN6, "ISO-8859-10"},
- {PG_LATIN6, "ISO8859-10"},
- {PG_LATIN6, "iso885910"},
-
- {PG_LATIN7, "ISO-8859-13"},
- {PG_LATIN7, "ISO8859-13"},
- {PG_LATIN7, "iso885913"},
-
- {PG_LATIN8, "ISO-8859-14"},
- {PG_LATIN8, "ISO8859-14"},
- {PG_LATIN8, "iso885914"},
-
- {PG_LATIN9, "ISO-8859-15"},
- {PG_LATIN9, "ISO8859-15"},
- {PG_LATIN9, "iso885915"},
- {PG_LATIN9, "CP28605"},
-
- {PG_LATIN10, "ISO-8859-16"},
- {PG_LATIN10, "ISO8859-16"},
- {PG_LATIN10, "iso885916"},
-
- {PG_KOI8R, "KOI8-R"},
- {PG_KOI8R, "CP20866"},
-
- {PG_KOI8U, "KOI8-U"},
- {PG_KOI8U, "CP21866"},
-
- {PG_WIN866, "CP866"},
- {PG_WIN874, "CP874"},
- {PG_WIN1250, "CP1250"},
- {PG_WIN1251, "CP1251"},
- {PG_WIN1251, "ansi-1251"},
- {PG_WIN1252, "CP1252"},
- {PG_WIN1253, "CP1253"},
- {PG_WIN1254, "CP1254"},
- {PG_WIN1255, "CP1255"},
- {PG_WIN1256, "CP1256"},
- {PG_WIN1257, "CP1257"},
- {PG_WIN1258, "CP1258"},
-
- {PG_ISO_8859_5, "ISO-8859-5"},
- {PG_ISO_8859_5, "ISO8859-5"},
- {PG_ISO_8859_5, "iso88595"},
- {PG_ISO_8859_5, "CP28595"},
-
- {PG_ISO_8859_6, "ISO-8859-6"},
- {PG_ISO_8859_6, "ISO8859-6"},
- {PG_ISO_8859_6, "iso88596"},
- {PG_ISO_8859_6, "CP28596"},
-
- {PG_ISO_8859_7, "ISO-8859-7"},
- {PG_ISO_8859_7, "ISO8859-7"},
- {PG_ISO_8859_7, "iso88597"},
- {PG_ISO_8859_7, "CP28597"},
-
- {PG_ISO_8859_8, "ISO-8859-8"},
- {PG_ISO_8859_8, "ISO8859-8"},
- {PG_ISO_8859_8, "iso88598"},
- {PG_ISO_8859_8, "CP28598"},
-
- {PG_SJIS, "SJIS"},
- {PG_SJIS, "PCK"},
- {PG_SJIS, "CP932"},
- {PG_SJIS, "SHIFT_JIS"},
-
- {PG_BIG5, "BIG5"},
- {PG_BIG5, "BIG5HKSCS"},
- {PG_BIG5, "Big5-HKSCS"},
- {PG_BIG5, "CP950"},
-
- {PG_GBK, "GBK"},
- {PG_GBK, "CP936"},
-
- {PG_UHC, "UHC"},
- {PG_UHC, "CP949"},
-
- {PG_JOHAB, "JOHAB"},
- {PG_JOHAB, "CP1361"},
-
- {PG_GB18030, "GB18030"},
- {PG_GB18030, "CP54936"},
-
- {PG_SHIFT_JIS_2004, "SJIS_2004"},
-
- {PG_SQL_ASCII, "US-ASCII"},
-
- {PG_SQL_ASCII, NULL} /* end marker */
-};
-
-#ifdef WIN32
-/*
- * On Windows, use CP<code page number> instead of the nl_langinfo() result
- *
- * Visual Studio 2012 expanded the set of valid LC_CTYPE values, so have its
- * locale machinery determine the code page. See comments at IsoLocaleName().
- * For other compilers, follow the locale's predictable format.
- *
- * Visual Studio 2015 should still be able to do the same, but the declaration
- * of lc_codepage is missing in _locale_t, causing this code compilation to
- * fail, hence this falls back instead on GetLocaleInfoEx. VS 2015 may be an
- * exception and post-VS2015 versions should be able to handle properly the
- * codepage number using _create_locale(). So, instead of the same logic as
- * VS 2012 and VS 2013, this routine uses GetLocaleInfoEx to parse short
- * locale names like "de-DE", "fr-FR", etc. If those cannot be parsed correctly
- * process falls back to the pre-VS-2010 manual parsing done with
- * using <Language>_<Country>.<CodePage> as a base.
- *
- * Returns a malloc()'d string for the caller to free.
- */
-static char *
-win32_langinfo(const char *ctype)
-{
- char *r = NULL;
-
-#if (_MSC_VER >= 1700) && (_MSC_VER < 1900)
- _locale_t loct = NULL;
-
- loct = _create_locale(LC_CTYPE, ctype);
- if (loct != NULL)
- {
- r = malloc(16); /* excess */
- if (r != NULL)
- sprintf(r, "CP%u", loct->locinfo->lc_codepage);
- _free_locale(loct);
- }
-#else
- char *codepage;
-
-#if (_MSC_VER >= 1900)
- uint32 cp;
- WCHAR wctype[LOCALE_NAME_MAX_LENGTH];
-
- memset(wctype, 0, sizeof(wctype));
- MultiByteToWideChar(CP_ACP, 0, ctype, -1, wctype, LOCALE_NAME_MAX_LENGTH);
-
- if (GetLocaleInfoEx(wctype,
- LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
- (LPWSTR) &cp, sizeof(cp) / sizeof(WCHAR)) > 0)
- {
- r = malloc(16); /* excess */
- if (r != NULL)
- sprintf(r, "CP%u", cp);
- }
- else
-#endif
- {
- /*
- * Locale format on Win32 is <Language>_<Country>.<CodePage> . For
- * example, English_United States.1252.
- */
- codepage = strrchr(ctype, '.');
- if (codepage != NULL)
- {
- int ln;
-
- codepage++;
- ln = strlen(codepage);
- r = malloc(ln + 3);
- if (r != NULL)
- sprintf(r, "CP%s", codepage);
- }
-
- }
-#endif
-
- return r;
-}
-
-#ifndef FRONTEND
-/*
- * Given a Windows code page identifier, find the corresponding PostgreSQL
- * encoding. Issue a warning and return -1 if none found.
- */
-int
-pg_codepage_to_encoding(UINT cp)
-{
- char sys[16];
- int i;
-
- sprintf(sys, "CP%u", cp);
-
- /* Check the table */
- for (i = 0; encoding_match_list[i].system_enc_name; i++)
- if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
- return encoding_match_list[i].pg_enc_code;
-
- ereport(WARNING,
- (errmsg("could not determine encoding for codeset \"%s\"", sys),
- errdetail("Please report this to <pgsql-bugs@postgresql.org>.")));
-
- return -1;
-}
-#endif
-#endif /* WIN32 */
-
-#if (defined(HAVE_LANGINFO_H) && defined(CODESET)) || defined(WIN32)
-
-/*
- * Given a setting for LC_CTYPE, return the Postgres ID of the associated
- * encoding, if we can determine it. Return -1 if we can't determine it.
- *
- * Pass in NULL to get the encoding for the current locale setting.
- * Pass "" to get the encoding selected by the server's environment.
- *
- * If the result is PG_SQL_ASCII, callers should treat it as being compatible
- * with any desired encoding.
- *
- * If running in the backend and write_message is false, this function must
- * cope with the possibility that elog() and palloc() are not yet usable.
- */
-int
-pg_get_encoding_from_locale(const char *ctype, bool write_message)
-{
- char *sys;
- int i;
-
- /* Get the CODESET property, and also LC_CTYPE if not passed in */
- if (ctype)
- {
- char *save;
- char *name;
-
- /* If locale is C or POSIX, we can allow all encodings */
- if (pg_strcasecmp(ctype, "C") == 0 ||
- pg_strcasecmp(ctype, "POSIX") == 0)
- return PG_SQL_ASCII;
-
- save = setlocale(LC_CTYPE, NULL);
- if (!save)
- return -1; /* setlocale() broken? */
- /* must copy result, or it might change after setlocale */
- save = strdup(save);
- if (!save)
- return -1; /* out of memory; unlikely */
-
- name = setlocale(LC_CTYPE, ctype);
- if (!name)
- {
- free(save);
- return -1; /* bogus ctype passed in? */
- }
-
-#ifndef WIN32
- sys = nl_langinfo(CODESET);
- if (sys)
- sys = strdup(sys);
-#else
- sys = win32_langinfo(name);
-#endif
-
- setlocale(LC_CTYPE, save);
- free(save);
- }
- else
- {
- /* much easier... */
- ctype = setlocale(LC_CTYPE, NULL);
- if (!ctype)
- return -1; /* setlocale() broken? */
-
- /* If locale is C or POSIX, we can allow all encodings */
- if (pg_strcasecmp(ctype, "C") == 0 ||
- pg_strcasecmp(ctype, "POSIX") == 0)
- return PG_SQL_ASCII;
-
-#ifndef WIN32
- sys = nl_langinfo(CODESET);
- if (sys)
- sys = strdup(sys);
-#else
- sys = win32_langinfo(ctype);
-#endif
- }
-
- if (!sys)
- return -1; /* out of memory; unlikely */
-
- /* Check the table */
- for (i = 0; encoding_match_list[i].system_enc_name; i++)
- {
- if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
- {
- free(sys);
- return encoding_match_list[i].pg_enc_code;
- }
- }
-
- /* Special-case kluges for particular platforms go here */
-
-#ifdef __darwin__
-
- /*
- * Current OS X has many locales that report an empty string for CODESET,
- * but they all seem to actually use UTF-8.
- */
- if (strlen(sys) == 0)
- {
- free(sys);
- return PG_UTF8;
- }
-#endif
-
- /*
- * We print a warning if we got a CODESET string but couldn't recognize
- * it. This means we need another entry in the table.
- */
- if (write_message)
- {
-#ifdef FRONTEND
- fprintf(stderr, _("could not determine encoding for locale \"%s\": codeset is \"%s\""),
- ctype, sys);
- /* keep newline separate so there's only one translatable string */
- fputc('\n', stderr);
-#else
- ereport(WARNING,
- (errmsg("could not determine encoding for locale \"%s\": codeset is \"%s\"",
- ctype, sys),
- errdetail("Please report this to <pgsql-bugs@postgresql.org>.")));
-#endif
- }
-
- free(sys);
- return -1;
-}
-#else /* (HAVE_LANGINFO_H && CODESET) || WIN32 */
-
-/*
- * stub if no multi-language platform support
- *
- * Note: we could return -1 here, but that would have the effect of
- * forcing users to specify an encoding to initdb on such platforms.
- * It seems better to silently default to SQL_ASCII.
- */
-int
-pg_get_encoding_from_locale(const char *ctype, bool write_message)
-{
- return PG_SQL_ASCII;
-}
-
-#endif /* (HAVE_LANGINFO_H && CODESET) || WIN32 */
diff --git a/libpq/encnames.c b/libpq/encnames.c
deleted file mode 100644
index 11099b8..0000000
--- a/libpq/encnames.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Encoding names and routines for work with it. All
- * in this file is shared between FE and BE.
- *
- * src/backend/utils/mb/encnames.c
- */
-#ifdef FRONTEND
-#include "postgres_fe.h"
-#else
-#include "postgres.h"
-#include "utils/builtins.h"
-#endif
-
-#include <ctype.h>
-#include <unistd.h>
-
-#include "mb/pg_wchar.h"
-
-
-/* ----------
- * All encoding names, sorted: *** A L P H A B E T I C ***
- *
- * All names must be without irrelevant chars, search routines use
- * isalnum() chars only. It means ISO-8859-1, iso_8859-1 and Iso8859_1
- * are always converted to 'iso88591'. All must be lower case.
- *
- * The table doesn't contain 'cs' aliases (like csISOLatin1). It's needed?
- *
- * Karel Zak, Aug 2001
- * ----------
- */
-typedef struct pg_encname
-{
- const char *name;
- pg_enc encoding;
-} pg_encname;
-
-static const pg_encname pg_encname_tbl[] =
-{
- {
- "abc", PG_WIN1258
- }, /* alias for WIN1258 */
- {
- "alt", PG_WIN866
- }, /* IBM866 */
- {
- "big5", PG_BIG5
- }, /* Big5; Chinese for Taiwan multibyte set */
- {
- "euccn", PG_EUC_CN
- }, /* EUC-CN; Extended Unix Code for simplified
- * Chinese */
- {
- "eucjis2004", PG_EUC_JIS_2004
- }, /* EUC-JIS-2004; Extended UNIX Code fixed
- * Width for Japanese, standard JIS X 0213 */
- {
- "eucjp", PG_EUC_JP
- }, /* EUC-JP; Extended UNIX Code fixed Width for
- * Japanese, standard OSF */
- {
- "euckr", PG_EUC_KR
- }, /* EUC-KR; Extended Unix Code for Korean , KS
- * X 1001 standard */
- {
- "euctw", PG_EUC_TW
- }, /* EUC-TW; Extended Unix Code for
- *
- * traditional Chinese */
- {
- "gb18030", PG_GB18030
- }, /* GB18030;GB18030 */
- {
- "gbk", PG_GBK
- }, /* GBK; Chinese Windows CodePage 936
- * simplified Chinese */
- {
- "iso88591", PG_LATIN1
- }, /* ISO-8859-1; RFC1345,KXS2 */
- {
- "iso885910", PG_LATIN6
- }, /* ISO-8859-10; RFC1345,KXS2 */
- {
- "iso885913", PG_LATIN7
- }, /* ISO-8859-13; RFC1345,KXS2 */
- {
- "iso885914", PG_LATIN8
- }, /* ISO-8859-14; RFC1345,KXS2 */
- {
- "iso885915", PG_LATIN9
- }, /* ISO-8859-15; RFC1345,KXS2 */
- {
- "iso885916", PG_LATIN10
- }, /* ISO-8859-16; RFC1345,KXS2 */
- {
- "iso88592", PG_LATIN2
- }, /* ISO-8859-2; RFC1345,KXS2 */
- {
- "iso88593", PG_LATIN3
- }, /* ISO-8859-3; RFC1345,KXS2 */
- {
- "iso88594", PG_LATIN4
- }, /* ISO-8859-4; RFC1345,KXS2 */
- {
- "iso88595", PG_ISO_8859_5
- }, /* ISO-8859-5; RFC1345,KXS2 */
- {
- "iso88596", PG_ISO_8859_6
- }, /* ISO-8859-6; RFC1345,KXS2 */
- {
- "iso88597", PG_ISO_8859_7
- }, /* ISO-8859-7; RFC1345,KXS2 */
- {
- "iso88598", PG_ISO_8859_8
- }, /* ISO-8859-8; RFC1345,KXS2 */
- {
- "iso88599", PG_LATIN5
- }, /* ISO-8859-9; RFC1345,KXS2 */
- {
- "johab", PG_JOHAB
- }, /* JOHAB; Extended Unix Code for simplified
- * Chinese */
- {
- "koi8", PG_KOI8R
- }, /* _dirty_ alias for KOI8-R (backward
- * compatibility) */
- {
- "koi8r", PG_KOI8R
- }, /* KOI8-R; RFC1489 */
- {
- "koi8u", PG_KOI8U
- }, /* KOI8-U; RFC2319 */
- {
- "latin1", PG_LATIN1
- }, /* alias for ISO-8859-1 */
- {
- "latin10", PG_LATIN10
- }, /* alias for ISO-8859-16 */
- {
- "latin2", PG_LATIN2
- }, /* alias for ISO-8859-2 */
- {
- "latin3", PG_LATIN3
- }, /* alias for ISO-8859-3 */
- {
- "latin4", PG_LATIN4
- }, /* alias for ISO-8859-4 */
- {
- "latin5", PG_LATIN5
- }, /* alias for ISO-8859-9 */
- {
- "latin6", PG_LATIN6
- }, /* alias for ISO-8859-10 */
- {
- "latin7", PG_LATIN7
- }, /* alias for ISO-8859-13 */
- {
- "latin8", PG_LATIN8
- }, /* alias for ISO-8859-14 */
- {
- "latin9", PG_LATIN9
- }, /* alias for ISO-8859-15 */
- {
- "mskanji", PG_SJIS
- }, /* alias for Shift_JIS */
- {
- "muleinternal", PG_MULE_INTERNAL
- },
- {
- "shiftjis", PG_SJIS
- }, /* Shift_JIS; JIS X 0202-1991 */
-
- {
- "shiftjis2004", PG_SHIFT_JIS_2004
- }, /* SHIFT-JIS-2004; Shift JIS for Japanese,
- * standard JIS X 0213 */
- {
- "sjis", PG_SJIS
- }, /* alias for Shift_JIS */
- {
- "sqlascii", PG_SQL_ASCII
- },
- {
- "tcvn", PG_WIN1258
- }, /* alias for WIN1258 */
- {
- "tcvn5712", PG_WIN1258
- }, /* alias for WIN1258 */
- {
- "uhc", PG_UHC
- }, /* UHC; Korean Windows CodePage 949 */
- {
- "unicode", PG_UTF8
- }, /* alias for UTF8 */
- {
- "utf8", PG_UTF8
- }, /* alias for UTF8 */
- {
- "vscii", PG_WIN1258
- }, /* alias for WIN1258 */
- {
- "win", PG_WIN1251
- }, /* _dirty_ alias for windows-1251 (backward
- * compatibility) */
- {
- "win1250", PG_WIN1250
- }, /* alias for Windows-1250 */
- {
- "win1251", PG_WIN1251
- }, /* alias for Windows-1251 */
- {
- "win1252", PG_WIN1252
- }, /* alias for Windows-1252 */
- {
- "win1253", PG_WIN1253
- }, /* alias for Windows-1253 */
- {
- "win1254", PG_WIN1254
- }, /* alias for Windows-1254 */
- {
- "win1255", PG_WIN1255
- }, /* alias for Windows-1255 */
- {
- "win1256", PG_WIN1256
- }, /* alias for Windows-1256 */
- {
- "win1257", PG_WIN1257
- }, /* alias for Windows-1257 */
- {
- "win1258", PG_WIN1258
- }, /* alias for Windows-1258 */
- {
- "win866", PG_WIN866
- }, /* IBM866 */
- {
- "win874", PG_WIN874
- }, /* alias for Windows-874 */
- {
- "win932", PG_SJIS
- }, /* alias for Shift_JIS */
- {
- "win936", PG_GBK
- }, /* alias for GBK */
- {
- "win949", PG_UHC
- }, /* alias for UHC */
- {
- "win950", PG_BIG5
- }, /* alias for BIG5 */
- {
- "windows1250", PG_WIN1250
- }, /* Windows-1251; Microsoft */
- {
- "windows1251", PG_WIN1251
- }, /* Windows-1251; Microsoft */
- {
- "windows1252", PG_WIN1252
- }, /* Windows-1252; Microsoft */
- {
- "windows1253", PG_WIN1253
- }, /* Windows-1253; Microsoft */
- {
- "windows1254", PG_WIN1254
- }, /* Windows-1254; Microsoft */
- {
- "windows1255", PG_WIN1255
- }, /* Windows-1255; Microsoft */
- {
- "windows1256", PG_WIN1256
- }, /* Windows-1256; Microsoft */
- {
- "windows1257", PG_WIN1257
- }, /* Windows-1257; Microsoft */
- {
- "windows1258", PG_WIN1258
- }, /* Windows-1258; Microsoft */
- {
- "windows866", PG_WIN866
- }, /* IBM866 */
- {
- "windows874", PG_WIN874
- }, /* Windows-874; Microsoft */
- {
- "windows932", PG_SJIS
- }, /* alias for Shift_JIS */
- {
- "windows936", PG_GBK
- }, /* alias for GBK */
- {
- "windows949", PG_UHC
- }, /* alias for UHC */
- {
- "windows950", PG_BIG5
- } /* alias for BIG5 */
-};
-
-/* ----------
- * These are "official" encoding names.
- * XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
- * ----------
- */
-#ifndef WIN32
-#define DEF_ENC2NAME(name, codepage) { #name, PG_##name }
-#else
-#define DEF_ENC2NAME(name, codepage) { #name, PG_##name, codepage }
-#endif
-const pg_enc2name pg_enc2name_tbl[] =
-{
- DEF_ENC2NAME(SQL_ASCII, 0),
- DEF_ENC2NAME(EUC_JP, 20932),
- DEF_ENC2NAME(EUC_CN, 20936),
- DEF_ENC2NAME(EUC_KR, 51949),
- DEF_ENC2NAME(EUC_TW, 0),
- DEF_ENC2NAME(EUC_JIS_2004, 20932),
- DEF_ENC2NAME(UTF8, 65001),
- DEF_ENC2NAME(MULE_INTERNAL, 0),
- DEF_ENC2NAME(LATIN1, 28591),
- DEF_ENC2NAME(LATIN2, 28592),
- DEF_ENC2NAME(LATIN3, 28593),
- DEF_ENC2NAME(LATIN4, 28594),
- DEF_ENC2NAME(LATIN5, 28599),
- DEF_ENC2NAME(LATIN6, 0),
- DEF_ENC2NAME(LATIN7, 0),
- DEF_ENC2NAME(LATIN8, 0),
- DEF_ENC2NAME(LATIN9, 28605),
- DEF_ENC2NAME(LATIN10, 0),
- DEF_ENC2NAME(WIN1256, 1256),
- DEF_ENC2NAME(WIN1258, 1258),
- DEF_ENC2NAME(WIN866, 866),
- DEF_ENC2NAME(WIN874, 874),
- DEF_ENC2NAME(KOI8R, 20866),
- DEF_ENC2NAME(WIN1251, 1251),
- DEF_ENC2NAME(WIN1252, 1252),
- DEF_ENC2NAME(ISO_8859_5, 28595),
- DEF_ENC2NAME(ISO_8859_6, 28596),
- DEF_ENC2NAME(ISO_8859_7, 28597),
- DEF_ENC2NAME(ISO_8859_8, 28598),
- DEF_ENC2NAME(WIN1250, 1250),
- DEF_ENC2NAME(WIN1253, 1253),
- DEF_ENC2NAME(WIN1254, 1254),
- DEF_ENC2NAME(WIN1255, 1255),
- DEF_ENC2NAME(WIN1257, 1257),
- DEF_ENC2NAME(KOI8U, 21866),
- DEF_ENC2NAME(SJIS, 932),
- DEF_ENC2NAME(BIG5, 950),
- DEF_ENC2NAME(GBK, 936),
- DEF_ENC2NAME(UHC, 949),
- DEF_ENC2NAME(GB18030, 54936),
- DEF_ENC2NAME(JOHAB, 0),
- DEF_ENC2NAME(SHIFT_JIS_2004, 932)
-};
-
-/* ----------
- * These are encoding names for gettext.
- *
- * This covers all encodings except MULE_INTERNAL, which is alien to gettext.
- * ----------
- */
-const pg_enc2gettext pg_enc2gettext_tbl[] =
-{
- {PG_SQL_ASCII, "US-ASCII"},
- {PG_UTF8, "UTF-8"},
- {PG_LATIN1, "LATIN1"},
- {PG_LATIN2, "LATIN2"},
- {PG_LATIN3, "LATIN3"},
- {PG_LATIN4, "LATIN4"},
- {PG_ISO_8859_5, "ISO-8859-5"},
- {PG_ISO_8859_6, "ISO_8859-6"},
- {PG_ISO_8859_7, "ISO-8859-7"},
- {PG_ISO_8859_8, "ISO-8859-8"},
- {PG_LATIN5, "LATIN5"},
- {PG_LATIN6, "LATIN6"},
- {PG_LATIN7, "LATIN7"},
- {PG_LATIN8, "LATIN8"},
- {PG_LATIN9, "LATIN-9"},
- {PG_LATIN10, "LATIN10"},
- {PG_KOI8R, "KOI8-R"},
- {PG_KOI8U, "KOI8-U"},
- {PG_WIN1250, "CP1250"},
- {PG_WIN1251, "CP1251"},
- {PG_WIN1252, "CP1252"},
- {PG_WIN1253, "CP1253"},
- {PG_WIN1254, "CP1254"},
- {PG_WIN1255, "CP1255"},
- {PG_WIN1256, "CP1256"},
- {PG_WIN1257, "CP1257"},
- {PG_WIN1258, "CP1258"},
- {PG_WIN866, "CP866"},
- {PG_WIN874, "CP874"},
- {PG_EUC_CN, "EUC-CN"},
- {PG_EUC_JP, "EUC-JP"},
- {PG_EUC_KR, "EUC-KR"},
- {PG_EUC_TW, "EUC-TW"},
- {PG_EUC_JIS_2004, "EUC-JP"},
- {PG_SJIS, "SHIFT-JIS"},
- {PG_BIG5, "BIG5"},
- {PG_GBK, "GBK"},
- {PG_UHC, "UHC"},
- {PG_GB18030, "GB18030"},
- {PG_JOHAB, "JOHAB"},
- {PG_SHIFT_JIS_2004, "SHIFT_JISX0213"},
- {0, NULL}
-};
-
-
-/* ----------
- * Encoding checks, for error returns -1 else encoding id
- * ----------
- */
-int
-pg_valid_client_encoding(const char *name)
-{
- int enc;
-
- if ((enc = pg_char_to_encoding(name)) < 0)
- return -1;
-
- if (!PG_VALID_FE_ENCODING(enc))
- return -1;
-
- return enc;
-}
-
-int
-pg_valid_server_encoding(const char *name)
-{
- int enc;
-
- if ((enc = pg_char_to_encoding(name)) < 0)
- return -1;
-
- if (!PG_VALID_BE_ENCODING(enc))
- return -1;
-
- return enc;
-}
-
-int
-pg_valid_server_encoding_id(int encoding)
-{
- return PG_VALID_BE_ENCODING(encoding);
-}
-
-/* ----------
- * Remove irrelevant chars from encoding name
- * ----------
- */
-static char *
-clean_encoding_name(const char *key, char *newkey)
-{
- const char *p;
- char *np;
-
- for (p = key, np = newkey; *p != '\0'; p++)
- {
- if (isalnum((unsigned char) *p))
- {
- if (*p >= 'A' && *p <= 'Z')
- *np++ = *p + 'a' - 'A';
- else
- *np++ = *p;
- }
- }
- *np = '\0';
- return newkey;
-}
-
-/* ----------
- * Search encoding by encoding name
- *
- * Returns encoding ID, or -1 for error
- * ----------
- */
-int
-pg_char_to_encoding(const char *name)
-{
- unsigned int nel = lengthof(pg_encname_tbl);
- const pg_encname *base = pg_encname_tbl,
- *last = base + nel - 1,
- *position;
- int result;
- char buff[NAMEDATALEN],
- *key;
-
- if (name == NULL || *name == '\0')
- return -1;
-
- if (strlen(name) >= NAMEDATALEN)
- {
-#ifdef FRONTEND
- fprintf(stderr, "encoding name too long\n");
- return -1;
-#else
- ereport(ERROR,
- (errcode(ERRCODE_NAME_TOO_LONG),
- errmsg("encoding name too long")));
-#endif
- }
- key = clean_encoding_name(name, buff);
-
- while (last >= base)
- {
- position = base + ((last - base) >> 1);
- result = key[0] - position->name[0];
-
- if (result == 0)
- {
- result = strcmp(key, position->name);
- if (result == 0)
- return position->encoding;
- }
- if (result < 0)
- last = position - 1;
- else
- base = position + 1;
- }
- return -1;
-}
-
-#ifndef FRONTEND
-Datum
-PG_char_to_encoding(PG_FUNCTION_ARGS)
-{
- Name s = PG_GETARG_NAME(0);
-
- PG_RETURN_INT32(pg_char_to_encoding(NameStr(*s)));
-}
-#endif
-
-const char *
-pg_encoding_to_char(int encoding)
-{
- if (PG_VALID_ENCODING(encoding))
- {
- const pg_enc2name *p = &pg_enc2name_tbl[encoding];
-
- Assert(encoding == p->encoding);
- return p->name;
- }
- return "";
-}
-
-#ifndef FRONTEND
-Datum
-PG_encoding_to_char(PG_FUNCTION_ARGS)
-{
- int32 encoding = PG_GETARG_INT32(0);
- const char *encoding_name = pg_encoding_to_char(encoding);
-
- return DirectFunctionCall1(namein, CStringGetDatum(encoding_name));
-}
-
-#endif
diff --git a/libpq/fe-auth.c b/libpq/fe-auth.c
deleted file mode 100644
index ab057e9..0000000
--- a/libpq/fe-auth.c
+++ /dev/null
@@ -1,841 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-auth.c
- * The front-end (client) authorization routines
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-auth.c
- *
- *-------------------------------------------------------------------------
- */
-
-/*
- * INTERFACE ROUTINES
- * frontend (client) routines:
- * pg_fe_sendauth send authentication information
- * pg_fe_getauthname get user's name according to the client side
- * of the authentication system
- */
-
-#include "postgres_fe.h"
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
-#include <sys/socket.h>
-#ifdef HAVE_SYS_UCRED_H
-#include <sys/ucred.h>
-#endif
-#ifndef MAXHOSTNAMELEN
-#include <netdb.h> /* for MAXHOSTNAMELEN on some */
-#endif
-#include <pwd.h>
-#endif
-
-#include "libpq-fe.h"
-#include "fe-auth.h"
-#include "libpq/md5.h"
-
-
-#ifdef ENABLE_GSS
-/*
- * GSSAPI authentication system.
- */
-
-#if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
-/*
- * MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
- * that contain the OIDs required. Redefine here, values copied
- * from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
- */
-static const gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_desc =
-{10, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"};
-static GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE = &GSS_C_NT_HOSTBASED_SERVICE_desc;
-#endif
-
-/*
- * Fetch all errors of a specific type and append to "str".
- */
-static void
-pg_GSS_error_int(PQExpBuffer str, const char *mprefix,
- OM_uint32 stat, int type)
-{
- OM_uint32 lmin_s;
- gss_buffer_desc lmsg;
- OM_uint32 msg_ctx = 0;
-
- do
- {
- gss_display_status(&lmin_s, stat, type,
- GSS_C_NO_OID, &msg_ctx, &lmsg);
- appendPQExpBuffer(str, "%s: %s\n", mprefix, (char *) lmsg.value);
- gss_release_buffer(&lmin_s, &lmsg);
- } while (msg_ctx);
-}
-
-/*
- * GSSAPI errors contain two parts; put both into conn->errorMessage.
- */
-static void
-pg_GSS_error(const char *mprefix, PGconn *conn,
- OM_uint32 maj_stat, OM_uint32 min_stat)
-{
- resetPQExpBuffer(&conn->errorMessage);
-
- /* Fetch major error codes */
- pg_GSS_error_int(&conn->errorMessage, mprefix, maj_stat, GSS_C_GSS_CODE);
-
- /* Add the minor codes as well */
- pg_GSS_error_int(&conn->errorMessage, mprefix, min_stat, GSS_C_MECH_CODE);
-}
-
-/*
- * Continue GSS authentication with next token as needed.
- */
-static int
-pg_GSS_continue(PGconn *conn)
-{
- OM_uint32 maj_stat,
- min_stat,
- lmin_s;
-
- maj_stat = gss_init_sec_context(&min_stat,
- GSS_C_NO_CREDENTIAL,
- &conn->gctx,
- conn->gtarg_nam,
- GSS_C_NO_OID,
- GSS_C_MUTUAL_FLAG,
- 0,
- GSS_C_NO_CHANNEL_BINDINGS,
- (conn->gctx == GSS_C_NO_CONTEXT) ? GSS_C_NO_BUFFER : &conn->ginbuf,
- NULL,
- &conn->goutbuf,
- NULL,
- NULL);
-
- if (conn->gctx != GSS_C_NO_CONTEXT)
- {
- free(conn->ginbuf.value);
- conn->ginbuf.value = NULL;
- conn->ginbuf.length = 0;
- }
-
- if (conn->goutbuf.length != 0)
- {
- /*
- * GSS generated data to send to the server. We don't care if it's the
- * first or subsequent packet, just send the same kind of password
- * packet.
- */
- if (pqPacketSend(conn, 'p',
- conn->goutbuf.value, conn->goutbuf.length)
- != STATUS_OK)
- {
- gss_release_buffer(&lmin_s, &conn->goutbuf);
- return STATUS_ERROR;
- }
- }
- gss_release_buffer(&lmin_s, &conn->goutbuf);
-
- if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
- {
- pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
- conn,
- maj_stat, min_stat);
- gss_release_name(&lmin_s, &conn->gtarg_nam);
- if (conn->gctx)
- gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
- return STATUS_ERROR;
- }
-
- if (maj_stat == GSS_S_COMPLETE)
- gss_release_name(&lmin_s, &conn->gtarg_nam);
-
- return STATUS_OK;
-}
-
-/*
- * Send initial GSS authentication token
- */
-static int
-pg_GSS_startup(PGconn *conn)
-{
- OM_uint32 maj_stat,
- min_stat;
- int maxlen;
- gss_buffer_desc temp_gbuf;
-
- if (!(conn->pghost && conn->pghost[0] != '\0'))
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("host name must be specified\n"));
- return STATUS_ERROR;
- }
-
- if (conn->gctx)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("duplicate GSS authentication request\n"));
- return STATUS_ERROR;
- }
-
- /*
- * Import service principal name so the proper ticket can be acquired by
- * the GSSAPI system.
- */
- maxlen = NI_MAXHOST + strlen(conn->krbsrvname) + 2;
- temp_gbuf.value = (char *) malloc(maxlen);
- if (!temp_gbuf.value)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return STATUS_ERROR;
- }
- snprintf(temp_gbuf.value, maxlen, "%s@%s",
- conn->krbsrvname, conn->pghost);
- temp_gbuf.length = strlen(temp_gbuf.value);
-
- maj_stat = gss_import_name(&min_stat, &temp_gbuf,
- GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam);
- free(temp_gbuf.value);
-
- if (maj_stat != GSS_S_COMPLETE)
- {
- pg_GSS_error(libpq_gettext("GSSAPI name import error"),
- conn,
- maj_stat, min_stat);
- return STATUS_ERROR;
- }
-
- /*
- * Initial packet is the same as a continuation packet with no initial
- * context.
- */
- conn->gctx = GSS_C_NO_CONTEXT;
-
- return pg_GSS_continue(conn);
-}
-#endif /* ENABLE_GSS */
-
-
-#ifdef ENABLE_SSPI
-/*
- * SSPI authentication system (Windows only)
- */
-
-static void
-pg_SSPI_error(PGconn *conn, const char *mprefix, SECURITY_STATUS r)
-{
- char sysmsg[256];
-
- if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, r, 0,
- sysmsg, sizeof(sysmsg), NULL) == 0)
- printfPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
- mprefix, (unsigned int) r);
- else
- printfPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
- mprefix, sysmsg, (unsigned int) r);
-}
-
-/*
- * Continue SSPI authentication with next token as needed.
- */
-static int
-pg_SSPI_continue(PGconn *conn)
-{
- SECURITY_STATUS r;
- CtxtHandle newContext;
- ULONG contextAttr;
- SecBufferDesc inbuf;
- SecBufferDesc outbuf;
- SecBuffer OutBuffers[1];
- SecBuffer InBuffers[1];
-
- if (conn->sspictx != NULL)
- {
- /*
- * On runs other than the first we have some data to send. Put this
- * data in a SecBuffer type structure.
- */
- inbuf.ulVersion = SECBUFFER_VERSION;
- inbuf.cBuffers = 1;
- inbuf.pBuffers = InBuffers;
- InBuffers[0].pvBuffer = conn->ginbuf.value;
- InBuffers[0].cbBuffer = conn->ginbuf.length;
- InBuffers[0].BufferType = SECBUFFER_TOKEN;
- }
-
- OutBuffers[0].pvBuffer = NULL;
- OutBuffers[0].BufferType = SECBUFFER_TOKEN;
- OutBuffers[0].cbBuffer = 0;
- outbuf.cBuffers = 1;
- outbuf.pBuffers = OutBuffers;
- outbuf.ulVersion = SECBUFFER_VERSION;
-
- r = InitializeSecurityContext(conn->sspicred,
- conn->sspictx,
- conn->sspitarget,
- ISC_REQ_ALLOCATE_MEMORY,
- 0,
- SECURITY_NETWORK_DREP,
- (conn->sspictx == NULL) ? NULL : &inbuf,
- 0,
- &newContext,
- &outbuf,
- &contextAttr,
- NULL);
-
- if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
- {
- pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r);
-
- return STATUS_ERROR;
- }
-
- if (conn->sspictx == NULL)
- {
- /* On first run, transfer retrieved context handle */
- conn->sspictx = malloc(sizeof(CtxtHandle));
- if (conn->sspictx == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
- return STATUS_ERROR;
- }
- memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
- }
- else
- {
- /*
- * On subsequent runs when we had data to send, free buffers that
- * contained this data.
- */
- free(conn->ginbuf.value);
- conn->ginbuf.value = NULL;
- conn->ginbuf.length = 0;
- }
-
- /*
- * If SSPI returned any data to be sent to the server (as it normally
- * would), send this data as a password packet.
- */
- if (outbuf.cBuffers > 0)
- {
- if (outbuf.cBuffers != 1)
- {
- /*
- * This should never happen, at least not for Kerberos
- * authentication. Keep check in case it shows up with other
- * authentication methods later.
- */
- printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n");
- return STATUS_ERROR;
- }
-
- /*
- * If the negotiation is complete, there may be zero bytes to send.
- * The server is at this point not expecting any more data, so don't
- * send it.
- */
- if (outbuf.pBuffers[0].cbBuffer > 0)
- {
- if (pqPacketSend(conn, 'p',
- outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
- {
- FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
- return STATUS_ERROR;
- }
- }
- FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
- }
-
- /* Cleanup is handled by the code in freePGconn() */
- return STATUS_OK;
-}
-
-/*
- * Send initial SSPI authentication token.
- * If use_negotiate is 0, use kerberos authentication package which is
- * compatible with Unix. If use_negotiate is 1, use the negotiate package
- * which supports both kerberos and NTLM, but is not compatible with Unix.
- */
-static int
-pg_SSPI_startup(PGconn *conn, int use_negotiate)
-{
- SECURITY_STATUS r;
- TimeStamp expire;
-
- if (conn->sspictx)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("duplicate SSPI authentication request\n"));
- return STATUS_ERROR;
- }
-
- /*
- * Retrieve credentials handle
- */
- conn->sspicred = malloc(sizeof(CredHandle));
- if (conn->sspicred == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
- return STATUS_ERROR;
- }
-
- r = AcquireCredentialsHandle(NULL,
- use_negotiate ? "negotiate" : "kerberos",
- SECPKG_CRED_OUTBOUND,
- NULL,
- NULL,
- NULL,
- NULL,
- conn->sspicred,
- &expire);
- if (r != SEC_E_OK)
- {
- pg_SSPI_error(conn, libpq_gettext("could not acquire SSPI credentials"), r);
- free(conn->sspicred);
- conn->sspicred = NULL;
- return STATUS_ERROR;
- }
-
- /*
- * Compute target principal name. SSPI has a different format from GSSAPI,
- * but not more complex. We can skip the @REALM part, because Windows will
- * fill that in for us automatically.
- */
- if (!(conn->pghost && conn->pghost[0] != '\0'))
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("host name must be specified\n"));
- return STATUS_ERROR;
- }
- conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(conn->pghost) + 2);
- if (!conn->sspitarget)
- {
- printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
- return STATUS_ERROR;
- }
- sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, conn->pghost);
-
- /*
- * Indicate that we're in SSPI authentication mode to make sure that
- * pg_SSPI_continue is called next time in the negotiation.
- */
- conn->usesspi = 1;
-
- return pg_SSPI_continue(conn);
-}
-#endif /* ENABLE_SSPI */
-
-/*
- * Respond to AUTH_REQ_SCM_CREDS challenge.
- *
- * Note: this is dead code as of Postgres 9.1, because current backends will
- * never send this challenge. But we must keep it as long as libpq needs to
- * interoperate with pre-9.1 servers. It is believed to be needed only on
- * Debian/kFreeBSD (ie, FreeBSD kernel with Linux userland, so that the
- * getpeereid() function isn't provided by libc).
- */
-static int
-pg_local_sendauth(PGconn *conn)
-{
-#ifdef HAVE_STRUCT_CMSGCRED
- char buf;
- struct iovec iov;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- union
- {
- struct cmsghdr hdr;
- unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))];
- } cmsgbuf;
-
- /*
- * The backend doesn't care what we send here, but it wants exactly one
- * character to force recvmsg() to block and wait for us.
- */
- buf = '\0';
- iov.iov_base = &buf;
- iov.iov_len = 1;
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- /* We must set up a message that will be filled in by kernel */
- memset(&cmsgbuf, 0, sizeof(cmsgbuf));
- msg.msg_control = &cmsgbuf.buf;
- msg.msg_controllen = sizeof(cmsgbuf.buf);
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_CREDS;
-
- if (sendmsg(conn->sock, &msg, 0) == -1)
- {
- char sebuf[256];
-
- printfPQExpBuffer(&conn->errorMessage,
- "pg_local_sendauth: sendmsg: %s\n",
- pqStrerror(errno, sebuf, sizeof(sebuf)));
- return STATUS_ERROR;
- }
- return STATUS_OK;
-#else
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SCM_CRED authentication method not supported\n"));
- return STATUS_ERROR;
-#endif
-}
-
-static int
-pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
-{
- int ret;
- char *crypt_pwd = NULL;
- const char *pwd_to_send;
-
- /* Encrypt the password if needed. */
-
- switch (areq)
- {
- case AUTH_REQ_MD5:
- {
- char *crypt_pwd2;
-
- /* Allocate enough space for two MD5 hashes */
- crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
- if (!crypt_pwd)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return STATUS_ERROR;
- }
-
- crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1;
- if (!pg_md5_encrypt(password, conn->pguser,
- strlen(conn->pguser), crypt_pwd2))
- {
- free(crypt_pwd);
- return STATUS_ERROR;
- }
- if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), conn->md5Salt,
- sizeof(conn->md5Salt), crypt_pwd))
- {
- free(crypt_pwd);
- return STATUS_ERROR;
- }
-
- pwd_to_send = crypt_pwd;
- break;
- }
- case AUTH_REQ_PASSWORD:
- pwd_to_send = password;
- break;
- default:
- return STATUS_ERROR;
- }
- /* Packet has a message type as of protocol 3.0 */
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- ret = pqPacketSend(conn, 'p', pwd_to_send, strlen(pwd_to_send) + 1);
- else
- ret = pqPacketSend(conn, 0, pwd_to_send, strlen(pwd_to_send) + 1);
- if (crypt_pwd)
- free(crypt_pwd);
- return ret;
-}
-
-/*
- * pg_fe_sendauth
- * client demux routine for outgoing authentication information
- */
-int
-pg_fe_sendauth(AuthRequest areq, PGconn *conn)
-{
- switch (areq)
- {
- case AUTH_REQ_OK:
- break;
-
- case AUTH_REQ_KRB4:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("Kerberos 4 authentication not supported\n"));
- return STATUS_ERROR;
-
- case AUTH_REQ_KRB5:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("Kerberos 5 authentication not supported\n"));
- return STATUS_ERROR;
-
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
- case AUTH_REQ_GSS:
-#if !defined(ENABLE_SSPI)
- /* no native SSPI, so use GSSAPI library for it */
- case AUTH_REQ_SSPI:
-#endif
- {
- int r;
-
- pglock_thread();
-
- /*
- * If we have both GSS and SSPI support compiled in, use SSPI
- * support by default. This is overridable by a connection
- * string parameter. Note that when using SSPI we still leave
- * the negotiate parameter off, since we want SSPI to use the
- * GSSAPI kerberos protocol. For actual SSPI negotiate
- * protocol, we use AUTH_REQ_SSPI.
- */
-#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
- if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
- r = pg_GSS_startup(conn);
- else
- r = pg_SSPI_startup(conn, 0);
-#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
- r = pg_GSS_startup(conn);
-#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
- r = pg_SSPI_startup(conn, 0);
-#endif
- if (r != STATUS_OK)
- {
- /* Error message already filled in. */
- pgunlock_thread();
- return STATUS_ERROR;
- }
- pgunlock_thread();
- }
- break;
-
- case AUTH_REQ_GSS_CONT:
- {
- int r;
-
- pglock_thread();
-#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
- if (conn->usesspi)
- r = pg_SSPI_continue(conn);
- else
- r = pg_GSS_continue(conn);
-#elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
- r = pg_GSS_continue(conn);
-#elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
- r = pg_SSPI_continue(conn);
-#endif
- if (r != STATUS_OK)
- {
- /* Error message already filled in. */
- pgunlock_thread();
- return STATUS_ERROR;
- }
- pgunlock_thread();
- }
- break;
-#else /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
- /* No GSSAPI *or* SSPI support */
- case AUTH_REQ_GSS:
- case AUTH_REQ_GSS_CONT:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("GSSAPI authentication not supported\n"));
- return STATUS_ERROR;
-#endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
-
-#ifdef ENABLE_SSPI
- case AUTH_REQ_SSPI:
-
- /*
- * SSPI has it's own startup message so libpq can decide which
- * method to use. Indicate to pg_SSPI_startup that we want SSPI
- * negotiation instead of Kerberos.
- */
- pglock_thread();
- if (pg_SSPI_startup(conn, 1) != STATUS_OK)
- {
- /* Error message already filled in. */
- pgunlock_thread();
- return STATUS_ERROR;
- }
- pgunlock_thread();
- break;
-#else
-
- /*
- * No SSPI support. However, if we have GSSAPI but not SSPI
- * support, AUTH_REQ_SSPI will have been handled in the codepath
- * for AUTH_REQ_GSSAPI above, so don't duplicate the case label in
- * that case.
- */
-#if !defined(ENABLE_GSS)
- case AUTH_REQ_SSPI:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SSPI authentication not supported\n"));
- return STATUS_ERROR;
-#endif /* !define(ENABLE_GSSAPI) */
-#endif /* ENABLE_SSPI */
-
-
- case AUTH_REQ_CRYPT:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("Crypt authentication not supported\n"));
- return STATUS_ERROR;
-
- case AUTH_REQ_MD5:
- case AUTH_REQ_PASSWORD:
- conn->password_needed = true;
- if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
- {
- printfPQExpBuffer(&conn->errorMessage,
- PQnoPasswordSupplied);
- return STATUS_ERROR;
- }
- if (pg_password_sendauth(conn, conn->pgpass, areq) != STATUS_OK)
- {
- printfPQExpBuffer(&conn->errorMessage,
- "fe_sendauth: error sending password authentication\n");
- return STATUS_ERROR;
- }
- break;
-
- case AUTH_REQ_SCM_CREDS:
- if (pg_local_sendauth(conn) != STATUS_OK)
- return STATUS_ERROR;
- break;
-
- /*
- * SASL authentication was introduced in version 10. Older
- * versions recognize the request only to give a nicer error
- * message. We call it "SCRAM authentication" in the error, rather
- * than SASL, because SCRAM is more familiar to users, and it's
- * the only SASL authentication mechanism that has been
- * implemented as of this writing, anyway.
- */
- case AUTH_REQ_SASL:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("SCRAM authentication requires libpq version 10 or above\n"));
- return STATUS_ERROR;
-
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("authentication method %u not supported\n"), areq);
- return STATUS_ERROR;
- }
-
- return STATUS_OK;
-}
-
-
-/*
- * pg_fe_getauthname
- *
- * Returns a pointer to malloc'd space containing whatever name the user
- * has authenticated to the system. If there is an error, return NULL,
- * and put a suitable error message in *errorMessage if that's not NULL.
- */
-char *
-pg_fe_getauthname(PQExpBuffer errorMessage)
-{
- char *result = NULL;
- const char *name = NULL;
-
-#ifdef WIN32
- /* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
- char username[256 + 1];
- DWORD namesize = sizeof(username);
-#else
- uid_t user_id = geteuid();
- char pwdbuf[BUFSIZ];
- struct passwd pwdstr;
- struct passwd *pw = NULL;
- int pwerr;
-#endif
-
- /*
- * Some users are using configure --enable-thread-safety-force, so we
- * might as well do the locking within our library to protect
- * pqGetpwuid(). In fact, application developers can use getpwuid() in
- * their application if they use the locking call we provide, or install
- * their own locking function using PQregisterThreadLock().
- */
- pglock_thread();
-
-#ifdef WIN32
- if (GetUserName(username, &namesize))
- name = username;
- else if (errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("user name lookup failure: error code %lu\n"),
- GetLastError());
-#else
- pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
- if (pw != NULL)
- name = pw->pw_name;
- else if (errorMessage)
- {
- if (pwerr != 0)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("could not look up local user ID %d: %s\n"),
- (int) user_id,
- pqStrerror(pwerr, pwdbuf, sizeof(pwdbuf)));
- else
- printfPQExpBuffer(errorMessage,
- libpq_gettext("local user with ID %d does not exist\n"),
- (int) user_id);
- }
-#endif
-
- if (name)
- {
- result = strdup(name);
- if (result == NULL && errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- }
-
- pgunlock_thread();
-
- return result;
-}
-
-
-/*
- * PQencryptPassword -- exported routine to encrypt a password
- *
- * This is intended to be used by client applications that wish to send
- * commands like ALTER USER joe PASSWORD 'pwd'. The password need not
- * be sent in cleartext if it is encrypted on the client side. This is
- * good because it ensures the cleartext password won't end up in logs,
- * pg_stat displays, etc. We export the function so that clients won't
- * be dependent on low-level details like whether the encryption is MD5
- * or something else.
- *
- * Arguments are the cleartext password, and the SQL name of the user it
- * is for.
- *
- * Return value is a malloc'd string, or NULL if out-of-memory. The client
- * may assume the string doesn't contain any special characters that would
- * require escaping.
- */
-char *
-PQencryptPassword(const char *passwd, const char *user)
-{
- char *crypt_pwd;
-
- crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
- if (!crypt_pwd)
- return NULL;
-
- if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
- {
- free(crypt_pwd);
- return NULL;
- }
-
- return crypt_pwd;
-}
diff --git a/libpq/fe-auth.h b/libpq/fe-auth.h
deleted file mode 100644
index 9d11654..0000000
--- a/libpq/fe-auth.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-auth.h
- *
- * Definitions for network authentication routines
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/interfaces/libpq/fe-auth.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef FE_AUTH_H
-#define FE_AUTH_H
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-
-
-extern int pg_fe_sendauth(AuthRequest areq, PGconn *conn);
-extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
-
-#endif /* FE_AUTH_H */
diff --git a/libpq/fe-connect.c b/libpq/fe-connect.c
deleted file mode 100644
index e61ed7d..0000000
--- a/libpq/fe-connect.c
+++ /dev/null
@@ -1,6002 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-connect.c
- * functions related to setting up a connection to the backend
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-connect.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres_fe.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-#include "fe-auth.h"
-#include "pg_config_paths.h"
-
-#ifdef WIN32
-#include "win32.h"
-#ifdef _WIN32_IE
-#undef _WIN32_IE
-#endif
-#define _WIN32_IE 0x0500
-#ifdef near
-#undef near
-#endif
-#define near
-#include <shlobj.h>
-#ifdef WIN32_ONLY_COMPILER /* mstcpip.h is missing on mingw */
-#include <mstcpip.h>
-#endif
-#else
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#include <arpa/inet.h>
-#endif
-
-#ifdef ENABLE_THREAD_SAFETY
-#ifdef WIN32
-#include "pthread-win32.h"
-#else
-#include <pthread.h>
-#endif
-#endif
-
-#ifdef USE_LDAP
-#ifdef WIN32
-#include <winldap.h>
-#else
-/* OpenLDAP deprecates RFC 1823, but we want standard conformance */
-#define LDAP_DEPRECATED 1
-#include <ldap.h>
-typedef struct timeval LDAP_TIMEVAL;
-#endif
-static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
- PQExpBuffer errorMessage);
-#endif
-
-#include "libpq/ip.h"
-#include "mb/pg_wchar.h"
-
-#ifndef FD_CLOEXEC
-#define FD_CLOEXEC 1
-#endif
-
-
-#ifndef WIN32
-#define PGPASSFILE ".pgpass"
-#else
-#define PGPASSFILE "pgpass.conf"
-#endif
-
-/*
- * Pre-9.0 servers will return this SQLSTATE if asked to set
- * application_name in a startup packet. We hard-wire the value rather
- * than looking into errcodes.h since it reflects historical behavior
- * rather than that of the current code.
- */
-#define ERRCODE_APPNAME_UNKNOWN "42704"
-
-/* This is part of the protocol so just define it */
-#define ERRCODE_INVALID_PASSWORD "28P01"
-/* This too */
-#define ERRCODE_CANNOT_CONNECT_NOW "57P03"
-
-/*
- * Cope with the various platform-specific ways to spell TCP keepalive socket
- * options. This doesn't cover Windows, which as usual does its own thing.
- */
-#if defined(TCP_KEEPIDLE)
-/* TCP_KEEPIDLE is the name of this option on Linux and *BSD */
-#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPIDLE
-#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPIDLE"
-#elif defined(TCP_KEEPALIVE_THRESHOLD)
-/* TCP_KEEPALIVE_THRESHOLD is the name of this option on Solaris >= 11 */
-#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE_THRESHOLD
-#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE_THRESHOLD"
-#elif defined(TCP_KEEPALIVE) && defined(__darwin__)
-/* TCP_KEEPALIVE is the name of this option on macOS */
-/* Caution: Solaris has this symbol but it means something different */
-#define PG_TCP_KEEPALIVE_IDLE TCP_KEEPALIVE
-#define PG_TCP_KEEPALIVE_IDLE_STR "TCP_KEEPALIVE"
-#endif
-
-/*
- * fall back options if they are not specified by arguments or defined
- * by environment variables
- */
-#define DefaultHost "localhost"
-#define DefaultTty ""
-#define DefaultOption ""
-#define DefaultAuthtype ""
-#define DefaultPassword ""
-#ifdef USE_SSL
-#define DefaultSSLMode "prefer"
-#else
-#define DefaultSSLMode "disable"
-#endif
-
-/* ----------
- * Definition of the conninfo parameters and their fallback resources.
- *
- * If Environment-Var and Compiled-in are specified as NULL, no
- * fallback is available. If after all no value can be determined
- * for an option, an error is returned.
- *
- * The value for the username is treated specially in conninfo_add_defaults.
- * If the value is not obtained any other way, the username is determined
- * by pg_fe_getauthname().
- *
- * The Label and Disp-Char entries are provided for applications that
- * want to use PQconndefaults() to create a generic database connection
- * dialog. Disp-Char is defined as follows:
- * "" Normal input field
- * "*" Password field - hide value
- * "D" Debug option - don't show by default
- *
- * PQconninfoOptions[] is a constant static array that we use to initialize
- * a dynamically allocated working copy. All the "val" fields in
- * PQconninfoOptions[] *must* be NULL. In a working copy, non-null "val"
- * fields point to malloc'd strings that should be freed when the working
- * array is freed (see PQconninfoFree).
- *
- * The first part of each struct is identical to the one in libpq-fe.h,
- * which is required since we memcpy() data between the two!
- * ----------
- */
-typedef struct _internalPQconninfoOption
-{
- char *keyword; /* The keyword of the option */
- char *envvar; /* Fallback environment variable name */
- char *compiled; /* Fallback compiled in default value */
- char *val; /* Option's current value, or NULL */
- char *label; /* Label for field in connect dialog */
- char *dispchar; /* Indicates how to display this field in a
- * connect dialog. Values are: "" Display
- * entered value as is "*" Password field -
- * hide value "D" Debug option - don't show
- * by default */
- int dispsize; /* Field size in characters for dialog */
- /* ---
- * Anything above this comment must be synchronized with
- * PQconninfoOption in libpq-fe.h, since we memcpy() data
- * between them!
- * ---
- */
- off_t connofs; /* Offset into PGconn struct, -1 if not there */
-} internalPQconninfoOption;
-
-static const internalPQconninfoOption PQconninfoOptions[] = {
- /*
- * "authtype" is no longer used, so mark it "don't show". We keep it in
- * the array so as not to reject conninfo strings from old apps that might
- * still try to set it.
- */
- {"authtype", "PGAUTHTYPE", DefaultAuthtype, NULL,
- "Database-Authtype", "D", 20, -1},
-
- {"service", "PGSERVICE", NULL, NULL,
- "Database-Service", "", 20, -1},
-
- {"user", "PGUSER", NULL, NULL,
- "Database-User", "", 20,
- offsetof(struct pg_conn, pguser)},
-
- {"password", "PGPASSWORD", NULL, NULL,
- "Database-Password", "*", 20,
- offsetof(struct pg_conn, pgpass)},
-
- {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
- "Connect-timeout", "", 10, /* strlen(INT32_MAX) == 10 */
- offsetof(struct pg_conn, connect_timeout)},
-
- {"dbname", "PGDATABASE", NULL, NULL,
- "Database-Name", "", 20,
- offsetof(struct pg_conn, dbName)},
-
- {"host", "PGHOST", NULL, NULL,
- "Database-Host", "", 40,
- offsetof(struct pg_conn, pghost)},
-
- {"hostaddr", "PGHOSTADDR", NULL, NULL,
- "Database-Host-IP-Address", "", 45,
- offsetof(struct pg_conn, pghostaddr)},
-
- {"port", "PGPORT", DEF_PGPORT_STR, NULL,
- "Database-Port", "", 6,
- offsetof(struct pg_conn, pgport)},
-
- {"client_encoding", "PGCLIENTENCODING", NULL, NULL,
- "Client-Encoding", "", 10,
- offsetof(struct pg_conn, client_encoding_initial)},
-
- /*
- * "tty" is no longer used either, but keep it present for backwards
- * compatibility.
- */
- {"tty", "PGTTY", DefaultTty, NULL,
- "Backend-Debug-TTY", "D", 40,
- offsetof(struct pg_conn, pgtty)},
-
- {"options", "PGOPTIONS", DefaultOption, NULL,
- "Backend-Debug-Options", "D", 40,
- offsetof(struct pg_conn, pgoptions)},
-
- {"application_name", "PGAPPNAME", NULL, NULL,
- "Application-Name", "", 64,
- offsetof(struct pg_conn, appname)},
-
- {"fallback_application_name", NULL, NULL, NULL,
- "Fallback-Application-Name", "", 64,
- offsetof(struct pg_conn, fbappname)},
-
- {"keepalives", NULL, NULL, NULL,
- "TCP-Keepalives", "", 1, /* should be just '0' or '1' */
- offsetof(struct pg_conn, keepalives)},
-
- {"keepalives_idle", NULL, NULL, NULL,
- "TCP-Keepalives-Idle", "", 10, /* strlen(INT32_MAX) == 10 */
- offsetof(struct pg_conn, keepalives_idle)},
-
- {"keepalives_interval", NULL, NULL, NULL,
- "TCP-Keepalives-Interval", "", 10, /* strlen(INT32_MAX) == 10 */
- offsetof(struct pg_conn, keepalives_interval)},
-
- {"keepalives_count", NULL, NULL, NULL,
- "TCP-Keepalives-Count", "", 10, /* strlen(INT32_MAX) == 10 */
- offsetof(struct pg_conn, keepalives_count)},
-
- /*
- * ssl options are allowed even without client SSL support because the
- * client can still handle SSL modes "disable" and "allow". Other
- * parameters have no effect on non-SSL connections, so there is no reason
- * to exclude them since none of them are mandatory.
- */
- {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
- "SSL-Mode", "", 12, /* sizeof("verify-full") == 12 */
- offsetof(struct pg_conn, sslmode)},
-
- {"sslcompression", "PGSSLCOMPRESSION", "1", NULL,
- "SSL-Compression", "", 1,
- offsetof(struct pg_conn, sslcompression)},
-
- {"sslcert", "PGSSLCERT", NULL, NULL,
- "SSL-Client-Cert", "", 64,
- offsetof(struct pg_conn, sslcert)},
-
- {"sslkey", "PGSSLKEY", NULL, NULL,
- "SSL-Client-Key", "", 64,
- offsetof(struct pg_conn, sslkey)},
-
- {"sslrootcert", "PGSSLROOTCERT", NULL, NULL,
- "SSL-Root-Certificate", "", 64,
- offsetof(struct pg_conn, sslrootcert)},
-
- {"sslcrl", "PGSSLCRL", NULL, NULL,
- "SSL-Revocation-List", "", 64,
- offsetof(struct pg_conn, sslcrl)},
-
- {"requirepeer", "PGREQUIREPEER", NULL, NULL,
- "Require-Peer", "", 10,
- offsetof(struct pg_conn, requirepeer)},
-
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
- /* Kerberos and GSSAPI authentication support specifying the service name */
- {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
- "Kerberos-service-name", "", 20,
- offsetof(struct pg_conn, krbsrvname)},
-#endif
-
-#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
-
- /*
- * GSSAPI and SSPI both enabled, give a way to override which is used by
- * default
- */
- {"gsslib", "PGGSSLIB", NULL, NULL,
- "GSS-library", "", 7, /* sizeof("gssapi") = 7 */
- offsetof(struct pg_conn, gsslib)},
-#endif
-
- {"replication", NULL, NULL, NULL,
- "Replication", "D", 5,
- offsetof(struct pg_conn, replication)},
-
- /* Terminating entry --- MUST BE LAST */
- {NULL, NULL, NULL, NULL,
- NULL, NULL, 0}
-};
-
-static const PQEnvironmentOption EnvironmentOptions[] =
-{
- /* common user-interface settings */
- {
- "PGDATESTYLE", "datestyle"
- },
- {
- "PGTZ", "timezone"
- },
- /* internal performance-related settings */
- {
- "PGGEQO", "geqo"
- },
- {
- NULL, NULL
- }
-};
-
-/* The connection URI must start with either of the following designators: */
-static const char uri_designator[] = "postgresql://";
-static const char short_uri_designator[] = "postgres://";
-
-static bool connectOptions1(PGconn *conn, const char *conninfo);
-static bool connectOptions2(PGconn *conn);
-static int connectDBStart(PGconn *conn);
-static int connectDBComplete(PGconn *conn);
-static PGPing internal_ping(PGconn *conn);
-static PGconn *makeEmptyPGconn(void);
-static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
-static void freePGconn(PGconn *conn);
-static void closePGconn(PGconn *conn);
-static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage);
-static PQconninfoOption *parse_connection_string(const char *conninfo,
- PQExpBuffer errorMessage, bool use_defaults);
-static int uri_prefix_length(const char *connstr);
-static bool recognized_connection_string(const char *connstr);
-static PQconninfoOption *conninfo_parse(const char *conninfo,
- PQExpBuffer errorMessage, bool use_defaults);
-static PQconninfoOption *conninfo_array_parse(const char *const * keywords,
- const char *const * values, PQExpBuffer errorMessage,
- bool use_defaults, int expand_dbname);
-static bool conninfo_add_defaults(PQconninfoOption *options,
- PQExpBuffer errorMessage);
-static PQconninfoOption *conninfo_uri_parse(const char *uri,
- PQExpBuffer errorMessage, bool use_defaults);
-static bool conninfo_uri_parse_options(PQconninfoOption *options,
- const char *uri, PQExpBuffer errorMessage);
-static bool conninfo_uri_parse_params(char *params,
- PQconninfoOption *connOptions,
- PQExpBuffer errorMessage);
-static char *conninfo_uri_decode(const char *str, PQExpBuffer errorMessage);
-static bool get_hexdigit(char digit, int *value);
-static const char *conninfo_getval(PQconninfoOption *connOptions,
- const char *keyword);
-static PQconninfoOption *conninfo_storeval(PQconninfoOption *connOptions,
- const char *keyword, const char *value,
- PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode);
-static PQconninfoOption *conninfo_find(PQconninfoOption *connOptions,
- const char *keyword);
-static void defaultNoticeReceiver(void *arg, const PGresult *res);
-static void defaultNoticeProcessor(void *arg, const char *message);
-static int parseServiceInfo(PQconninfoOption *options,
- PQExpBuffer errorMessage);
-static int parseServiceFile(const char *serviceFile,
- const char *service,
- PQconninfoOption *options,
- PQExpBuffer errorMessage,
- bool *group_found);
-static char *pwdfMatchesString(char *buf, char *token);
-static char *PasswordFromFile(char *hostname, char *port, char *dbname,
- char *username);
-static bool getPgPassFilename(char *pgpassfile);
-static void dot_pg_pass_warning(PGconn *conn);
-static void default_threadlock(int acquire);
-
-
-/* global variable because fe-auth.c needs to access it */
-pgthreadlock_t pg_g_threadlock = default_threadlock;
-
-
-/*
- * pqDropConnection
- *
- * Close any physical connection to the server, and reset associated
- * state inside the connection object. We don't release state that
- * would be needed to reconnect, though.
- *
- * We can always flush the output buffer, since there's no longer any hope
- * of sending that data. However, unprocessed input data might still be
- * valuable, so the caller must tell us whether to flush that or not.
- */
-void
-pqDropConnection(PGconn *conn, bool flushInput)
-{
- /* Drop any SSL state */
- pqsecure_close(conn);
-
- /* Close the socket itself */
- if (conn->sock != PGINVALID_SOCKET)
- closesocket(conn->sock);
- conn->sock = PGINVALID_SOCKET;
-
- /* Optionally discard any unread data */
- if (flushInput)
- conn->inStart = conn->inCursor = conn->inEnd = 0;
-
- /* Always discard any unsent data */
- conn->outCount = 0;
-
- /* Free authentication state */
-#ifdef ENABLE_GSS
- {
- OM_uint32 min_s;
-
- if (conn->gctx)
- gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
- if (conn->gtarg_nam)
- gss_release_name(&min_s, &conn->gtarg_nam);
- if (conn->ginbuf.length)
- gss_release_buffer(&min_s, &conn->ginbuf);
- if (conn->goutbuf.length)
- gss_release_buffer(&min_s, &conn->goutbuf);
- }
-#endif
-#ifdef ENABLE_SSPI
- if (conn->ginbuf.length)
- free(conn->ginbuf.value);
- conn->ginbuf.length = 0;
- conn->ginbuf.value = NULL;
- if (conn->sspitarget)
- free(conn->sspitarget);
- conn->sspitarget = NULL;
- if (conn->sspicred)
- {
- FreeCredentialsHandle(conn->sspicred);
- free(conn->sspicred);
- conn->sspicred = NULL;
- }
- if (conn->sspictx)
- {
- DeleteSecurityContext(conn->sspictx);
- free(conn->sspictx);
- conn->sspictx = NULL;
- }
- conn->usesspi = 0;
-#endif
-}
-
-
-/*
- * Connecting to a Database
- *
- * There are now six different ways a user of this API can connect to the
- * database. Two are not recommended for use in new code, because of their
- * lack of extensibility with respect to the passing of options to the
- * backend. These are PQsetdb and PQsetdbLogin (the former now being a macro
- * to the latter).
- *
- * If it is desired to connect in a synchronous (blocking) manner, use the
- * function PQconnectdb or PQconnectdbParams. The former accepts a string of
- * option = value pairs (or a URI) which must be parsed; the latter takes two
- * NULL terminated arrays instead.
- *
- * To connect in an asynchronous (non-blocking) manner, use the functions
- * PQconnectStart or PQconnectStartParams (which differ in the same way as
- * PQconnectdb and PQconnectdbParams) and PQconnectPoll.
- *
- * Internally, the static functions connectDBStart, connectDBComplete
- * are part of the connection procedure.
- */
-
-/*
- * PQconnectdbParams
- *
- * establishes a connection to a postgres backend through the postmaster
- * using connection information in two arrays.
- *
- * The keywords array is defined as
- *
- * const char *params[] = {"option1", "option2", NULL}
- *
- * The values array is defined as
- *
- * const char *values[] = {"value1", "value2", NULL}
- *
- * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
- * if a memory allocation failed.
- * If the status field of the connection returned is CONNECTION_BAD,
- * then some fields may be null'ed out instead of having valid values.
- *
- * You should call PQfinish (if conn is not NULL) regardless of whether this
- * call succeeded.
- */
-PGconn *
-PQconnectdbParams(const char *const * keywords,
- const char *const * values,
- int expand_dbname)
-{
- PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
-
- if (conn && conn->status != CONNECTION_BAD)
- (void) connectDBComplete(conn);
-
- return conn;
-
-}
-
-/*
- * PQpingParams
- *
- * check server status, accepting parameters identical to PQconnectdbParams
- */
-PGPing
-PQpingParams(const char *const * keywords,
- const char *const * values,
- int expand_dbname)
-{
- PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
- PGPing ret;
-
- ret = internal_ping(conn);
- PQfinish(conn);
-
- return ret;
-}
-
-/*
- * PQconnectdb
- *
- * establishes a connection to a postgres backend through the postmaster
- * using connection information in a string.
- *
- * The conninfo string is either a whitespace-separated list of
- *
- * option = value
- *
- * definitions or a URI (refer to the documentation for details.) Value
- * might be a single value containing no whitespaces or a single quoted
- * string. If a single quote should appear anywhere in the value, it must be
- * escaped with a backslash like \'
- *
- * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
- * if a memory allocation failed.
- * If the status field of the connection returned is CONNECTION_BAD,
- * then some fields may be null'ed out instead of having valid values.
- *
- * You should call PQfinish (if conn is not NULL) regardless of whether this
- * call succeeded.
- */
-PGconn *
-PQconnectdb(const char *conninfo)
-{
- PGconn *conn = PQconnectStart(conninfo);
-
- if (conn && conn->status != CONNECTION_BAD)
- (void) connectDBComplete(conn);
-
- return conn;
-}
-
-/*
- * PQping
- *
- * check server status, accepting parameters identical to PQconnectdb
- */
-PGPing
-PQping(const char *conninfo)
-{
- PGconn *conn = PQconnectStart(conninfo);
- PGPing ret;
-
- ret = internal_ping(conn);
- PQfinish(conn);
-
- return ret;
-}
-
-/*
- * PQconnectStartParams
- *
- * Begins the establishment of a connection to a postgres backend through the
- * postmaster using connection information in a struct.
- *
- * See comment for PQconnectdbParams for the definition of the string format.
- *
- * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
- * you should not attempt to proceed with this connection. If the status
- * field of the connection returned is CONNECTION_BAD, an error has
- * occurred. In this case you should call PQfinish on the result, (perhaps
- * inspecting the error message first). Other fields of the structure may not
- * be valid if that occurs. If the status field is not CONNECTION_BAD, then
- * this stage has succeeded - call PQconnectPoll, using select(2) to see when
- * this is necessary.
- *
- * See PQconnectPoll for more info.
- */
-PGconn *
-PQconnectStartParams(const char *const * keywords,
- const char *const * values,
- int expand_dbname)
-{
- PGconn *conn;
- PQconninfoOption *connOptions;
-
- /*
- * Allocate memory for the conn structure
- */
- conn = makeEmptyPGconn();
- if (conn == NULL)
- return NULL;
-
- /*
- * Parse the conninfo arrays
- */
- connOptions = conninfo_array_parse(keywords, values,
- &conn->errorMessage,
- true, expand_dbname);
- if (connOptions == NULL)
- {
- conn->status = CONNECTION_BAD;
- /* errorMessage is already set */
- return conn;
- }
-
- /*
- * Move option values into conn structure
- */
- if (!fillPGconn(conn, connOptions))
- {
- PQconninfoFree(connOptions);
- return conn;
- }
-
- /*
- * Free the option info - all is in conn now
- */
- PQconninfoFree(connOptions);
-
- /*
- * Compute derived options
- */
- if (!connectOptions2(conn))
- return conn;
-
- /*
- * Connect to the database
- */
- if (!connectDBStart(conn))
- {
- /* Just in case we failed to set it in connectDBStart */
- conn->status = CONNECTION_BAD;
- }
-
- return conn;
-}
-
-/*
- * PQconnectStart
- *
- * Begins the establishment of a connection to a postgres backend through the
- * postmaster using connection information in a string.
- *
- * See comment for PQconnectdb for the definition of the string format.
- *
- * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
- * you should not attempt to proceed with this connection. If the status
- * field of the connection returned is CONNECTION_BAD, an error has
- * occurred. In this case you should call PQfinish on the result, (perhaps
- * inspecting the error message first). Other fields of the structure may not
- * be valid if that occurs. If the status field is not CONNECTION_BAD, then
- * this stage has succeeded - call PQconnectPoll, using select(2) to see when
- * this is necessary.
- *
- * See PQconnectPoll for more info.
- */
-PGconn *
-PQconnectStart(const char *conninfo)
-{
- PGconn *conn;
-
- /*
- * Allocate memory for the conn structure
- */
- conn = makeEmptyPGconn();
- if (conn == NULL)
- return NULL;
-
- /*
- * Parse the conninfo string
- */
- if (!connectOptions1(conn, conninfo))
- return conn;
-
- /*
- * Compute derived options
- */
- if (!connectOptions2(conn))
- return conn;
-
- /*
- * Connect to the database
- */
- if (!connectDBStart(conn))
- {
- /* Just in case we failed to set it in connectDBStart */
- conn->status = CONNECTION_BAD;
- }
-
- return conn;
-}
-
-/*
- * Move option values into conn structure
- *
- * Don't put anything cute here --- intelligence should be in
- * connectOptions2 ...
- *
- * Returns true on success. On failure, returns false and sets error message.
- */
-static bool
-fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
-{
- const internalPQconninfoOption *option;
-
- for (option = PQconninfoOptions; option->keyword; option++)
- {
- if (option->connofs >= 0)
- {
- const char *tmp = conninfo_getval(connOptions, option->keyword);
-
- if (tmp)
- {
- char **connmember = (char **) ((char *) conn + option->connofs);
-
- if (*connmember)
- free(*connmember);
- *connmember = strdup(tmp);
- if (*connmember == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-/*
- * connectOptions1
- *
- * Internal subroutine to set up connection parameters given an already-
- * created PGconn and a conninfo string. Derived settings should be
- * processed by calling connectOptions2 next. (We split them because
- * PQsetdbLogin overrides defaults in between.)
- *
- * Returns true if OK, false if trouble (in which case errorMessage is set
- * and so is conn->status).
- */
-static bool
-connectOptions1(PGconn *conn, const char *conninfo)
-{
- PQconninfoOption *connOptions;
-
- /*
- * Parse the conninfo string
- */
- connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
- if (connOptions == NULL)
- {
- conn->status = CONNECTION_BAD;
- /* errorMessage is already set */
- return false;
- }
-
- /*
- * Move option values into conn structure
- */
- if (!fillPGconn(conn, connOptions))
- {
- conn->status = CONNECTION_BAD;
- PQconninfoFree(connOptions);
- return false;
- }
-
- /*
- * Free the option info - all is in conn now
- */
- PQconninfoFree(connOptions);
-
- return true;
-}
-
-/*
- * connectOptions2
- *
- * Compute derived connection options after absorbing all user-supplied info.
- *
- * Returns true if OK, false if trouble (in which case errorMessage is set
- * and so is conn->status).
- */
-static bool
-connectOptions2(PGconn *conn)
-{
- /*
- * If user name was not given, fetch it. (Most likely, the fetch will
- * fail, since the only way we get here is if pg_fe_getauthname() failed
- * during conninfo_add_defaults(). But now we want an error message.)
- */
- if (conn->pguser == NULL || conn->pguser[0] == '\0')
- {
- if (conn->pguser)
- free(conn->pguser);
- conn->pguser = pg_fe_getauthname(&conn->errorMessage);
- if (!conn->pguser)
- {
- conn->status = CONNECTION_BAD;
- return false;
- }
- }
-
- /*
- * If database name was not given, default it to equal user name
- */
- if (conn->dbName == NULL || conn->dbName[0] == '\0')
- {
- if (conn->dbName)
- free(conn->dbName);
- conn->dbName = strdup(conn->pguser);
- if (!conn->dbName)
- goto oom_error;
- }
-
- /*
- * Supply default password if none given
- */
- if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
- {
- if (conn->pgpass)
- free(conn->pgpass);
- conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
- conn->dbName, conn->pguser);
- if (conn->pgpass == NULL)
- {
- conn->pgpass = strdup(DefaultPassword);
- if (!conn->pgpass)
- goto oom_error;
- }
- else
- conn->dot_pgpass_used = true;
- }
-
- /*
- * Allow unix socket specification in the host name
- */
- if (conn->pghost && is_absolute_path(conn->pghost))
- {
- if (conn->pgunixsocket)
- free(conn->pgunixsocket);
- conn->pgunixsocket = conn->pghost;
- conn->pghost = NULL;
- }
-
- /*
- * validate sslmode option
- */
- if (conn->sslmode)
- {
- if (strcmp(conn->sslmode, "disable") != 0
- && strcmp(conn->sslmode, "allow") != 0
- && strcmp(conn->sslmode, "prefer") != 0
- && strcmp(conn->sslmode, "require") != 0
- && strcmp(conn->sslmode, "verify-ca") != 0
- && strcmp(conn->sslmode, "verify-full") != 0)
- {
- conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid sslmode value: \"%s\"\n"),
- conn->sslmode);
- return false;
- }
-
-#ifndef USE_SSL
- switch (conn->sslmode[0])
- {
- case 'a': /* "allow" */
- case 'p': /* "prefer" */
-
- /*
- * warn user that an SSL connection will never be negotiated
- * since SSL was not compiled in?
- */
- break;
-
- case 'r': /* "require" */
- case 'v': /* "verify-ca" or "verify-full" */
- conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
- conn->sslmode);
- return false;
- }
-#endif
- }
- else
- {
- conn->sslmode = strdup(DefaultSSLMode);
- if (!conn->sslmode)
- goto oom_error;
- }
-
- /*
- * Resolve special "auto" client_encoding from the locale
- */
- if (conn->client_encoding_initial &&
- strcmp(conn->client_encoding_initial, "auto") == 0)
- {
- free(conn->client_encoding_initial);
- conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
- if (!conn->client_encoding_initial)
- goto oom_error;
- }
-
- /*
- * Only if we get this far is it appropriate to try to connect. (We need a
- * state flag, rather than just the boolean result of this function, in
- * case someone tries to PQreset() the PGconn.)
- */
- conn->options_valid = true;
-
- return true;
-
-oom_error:
- conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return false;
-}
-
-/*
- * PQconndefaults
- *
- * Construct a default connection options array, which identifies all the
- * available options and shows any default values that are available from the
- * environment etc. On error (eg out of memory), NULL is returned.
- *
- * Using this function, an application may determine all possible options
- * and their current default values.
- *
- * NOTE: as of PostgreSQL 7.0, the returned array is dynamically allocated
- * and should be freed when no longer needed via PQconninfoFree(). (In prior
- * versions, the returned array was static, but that's not thread-safe.)
- * Pre-7.0 applications that use this function will see a small memory leak
- * until they are updated to call PQconninfoFree.
- */
-PQconninfoOption *
-PQconndefaults(void)
-{
- PQExpBufferData errorBuf;
- PQconninfoOption *connOptions;
-
- /* We don't actually report any errors here, but callees want a buffer */
- initPQExpBuffer(&errorBuf);
- if (PQExpBufferDataBroken(errorBuf))
- return NULL; /* out of memory already :-( */
-
- connOptions = conninfo_init(&errorBuf);
- if (connOptions != NULL)
- {
- /* pass NULL errorBuf to ignore errors */
- if (!conninfo_add_defaults(connOptions, NULL))
- {
- PQconninfoFree(connOptions);
- connOptions = NULL;
- }
- }
-
- termPQExpBuffer(&errorBuf);
- return connOptions;
-}
-
-/* ----------------
- * PQsetdbLogin
- *
- * establishes a connection to a postgres backend through the postmaster
- * at the specified host and port.
- *
- * returns a PGconn* which is needed for all subsequent libpq calls
- *
- * if the status field of the connection returned is CONNECTION_BAD,
- * then only the errorMessage is likely to be useful.
- * ----------------
- */
-PGconn *
-PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
- const char *pgtty, const char *dbName, const char *login,
- const char *pwd)
-{
- PGconn *conn;
-
- /*
- * Allocate memory for the conn structure
- */
- conn = makeEmptyPGconn();
- if (conn == NULL)
- return NULL;
-
- /*
- * If the dbName parameter contains what looks like a connection string,
- * parse it into conn struct using connectOptions1.
- */
- if (dbName && recognized_connection_string(dbName))
- {
- if (!connectOptions1(conn, dbName))
- return conn;
- }
- else
- {
- /*
- * Old-style path: first, parse an empty conninfo string in order to
- * set up the same defaults that PQconnectdb() would use.
- */
- if (!connectOptions1(conn, ""))
- return conn;
-
- /* Insert dbName parameter value into struct */
- if (dbName && dbName[0] != '\0')
- {
- if (conn->dbName)
- free(conn->dbName);
- conn->dbName = strdup(dbName);
- if (!conn->dbName)
- goto oom_error;
- }
- }
-
- /*
- * Insert remaining parameters into struct, overriding defaults (as well
- * as any conflicting data from dbName taken as a conninfo).
- */
- if (pghost && pghost[0] != '\0')
- {
- if (conn->pghost)
- free(conn->pghost);
- conn->pghost = strdup(pghost);
- if (!conn->pghost)
- goto oom_error;
- }
-
- if (pgport && pgport[0] != '\0')
- {
- if (conn->pgport)
- free(conn->pgport);
- conn->pgport = strdup(pgport);
- if (!conn->pgport)
- goto oom_error;
- }
-
- if (pgoptions && pgoptions[0] != '\0')
- {
- if (conn->pgoptions)
- free(conn->pgoptions);
- conn->pgoptions = strdup(pgoptions);
- if (!conn->pgoptions)
- goto oom_error;
- }
-
- if (pgtty && pgtty[0] != '\0')
- {
- if (conn->pgtty)
- free(conn->pgtty);
- conn->pgtty = strdup(pgtty);
- if (!conn->pgtty)
- goto oom_error;
- }
-
- if (login && login[0] != '\0')
- {
- if (conn->pguser)
- free(conn->pguser);
- conn->pguser = strdup(login);
- if (!conn->pguser)
- goto oom_error;
- }
-
- if (pwd && pwd[0] != '\0')
- {
- if (conn->pgpass)
- free(conn->pgpass);
- conn->pgpass = strdup(pwd);
- if (!conn->pgpass)
- goto oom_error;
- }
-
- /*
- * Compute derived options
- */
- if (!connectOptions2(conn))
- return conn;
-
- /*
- * Connect to the database
- */
- if (connectDBStart(conn))
- (void) connectDBComplete(conn);
-
- return conn;
-
-oom_error:
- conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return conn;
-}
-
-
-/* ----------
- * connectNoDelay -
- * Sets the TCP_NODELAY socket option.
- * Returns 1 if successful, 0 if not.
- * ----------
- */
-static int
-connectNoDelay(PGconn *conn)
-{
-#ifdef TCP_NODELAY
- int on = 1;
-
- if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
- (char *) &on,
- sizeof(on)) < 0)
- {
- char sebuf[256];
-
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- return 0;
- }
-#endif
-
- return 1;
-}
-
-
-/* ----------
- * connectFailureMessage -
- * create a friendly error message on connection failure.
- * ----------
- */
-static void
-connectFailureMessage(PGconn *conn, int errorno)
-{
- char sebuf[256];
-
-#ifdef HAVE_UNIX_SOCKETS
- if (IS_AF_UNIX(conn->raddr.addr.ss_family))
- {
- char service[NI_MAXHOST];
-
- pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
- NULL, 0,
- service, sizeof(service),
- NI_NUMERICSERV);
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not connect to server: %s\n"
- "\tIs the server running locally and accepting\n"
- "\tconnections on Unix domain socket \"%s\"?\n"),
- SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
- service);
- }
- else
-#endif /* HAVE_UNIX_SOCKETS */
- {
- char host_addr[NI_MAXHOST];
- const char *displayed_host;
- struct sockaddr_storage *addr = &conn->raddr.addr;
-
- /*
- * Optionally display the network address with the hostname. This is
- * useful to distinguish between IPv4 and IPv6 connections.
- */
- if (conn->pghostaddr != NULL)
- strlcpy(host_addr, conn->pghostaddr, NI_MAXHOST);
- else if (addr->ss_family == AF_INET)
- {
- if (inet_net_ntop(AF_INET,
- &((struct sockaddr_in *) addr)->sin_addr.s_addr,
- 32,
- host_addr, sizeof(host_addr)) == NULL)
- strcpy(host_addr, "???");
- }
-#ifdef HAVE_IPV6
- else if (addr->ss_family == AF_INET6)
- {
- if (inet_net_ntop(AF_INET6,
- &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
- 128,
- host_addr, sizeof(host_addr)) == NULL)
- strcpy(host_addr, "???");
- }
-#endif
- else
- strcpy(host_addr, "???");
-
- if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
- displayed_host = conn->pghostaddr;
- else if (conn->pghost && conn->pghost[0] != '\0')
- displayed_host = conn->pghost;
- else
- displayed_host = DefaultHost;
-
- /*
- * If the user did not supply an IP address using 'hostaddr', and
- * 'host' was missing or does not match our lookup, display the
- * looked-up IP address.
- */
- if ((conn->pghostaddr == NULL) &&
- (conn->pghost == NULL || strcmp(conn->pghost, host_addr) != 0))
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not connect to server: %s\n"
- "\tIs the server running on host \"%s\" (%s) and accepting\n"
- "\tTCP/IP connections on port %s?\n"),
- SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
- displayed_host,
- host_addr,
- conn->pgport);
- else
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not connect to server: %s\n"
- "\tIs the server running on host \"%s\" and accepting\n"
- "\tTCP/IP connections on port %s?\n"),
- SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
- displayed_host,
- conn->pgport);
- }
-}
-
-/*
- * Should we use keepalives? Returns 1 if yes, 0 if no, and -1 if
- * conn->keepalives is set to a value which is not parseable as an
- * integer.
- */
-static int
-useKeepalives(PGconn *conn)
-{
- char *ep;
- int val;
-
- if (conn->keepalives == NULL)
- return 1;
- val = strtol(conn->keepalives, &ep, 10);
- if (*ep)
- return -1;
- return val != 0 ? 1 : 0;
-}
-
-#ifndef WIN32
-/*
- * Set the keepalive idle timer.
- */
-static int
-setKeepalivesIdle(PGconn *conn)
-{
- int idle;
-
- if (conn->keepalives_idle == NULL)
- return 1;
-
- idle = atoi(conn->keepalives_idle);
- if (idle < 0)
- idle = 0;
-
-#ifdef PG_TCP_KEEPALIVE_IDLE
- if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
- (char *) &idle, sizeof(idle)) < 0)
- {
- char sebuf[256];
-
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(%s) failed: %s\n"),
- PG_TCP_KEEPALIVE_IDLE_STR,
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- return 0;
- }
-#endif
-
- return 1;
-}
-
-/*
- * Set the keepalive interval.
- */
-static int
-setKeepalivesInterval(PGconn *conn)
-{
- int interval;
-
- if (conn->keepalives_interval == NULL)
- return 1;
-
- interval = atoi(conn->keepalives_interval);
- if (interval < 0)
- interval = 0;
-
-#ifdef TCP_KEEPINTVL
- if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
- (char *) &interval, sizeof(interval)) < 0)
- {
- char sebuf[256];
-
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(%s) failed: %s\n"),
- "TCP_KEEPINTVL",
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- return 0;
- }
-#endif
-
- return 1;
-}
-
-/*
- * Set the count of lost keepalive packets that will trigger a connection
- * break.
- */
-static int
-setKeepalivesCount(PGconn *conn)
-{
- int count;
-
- if (conn->keepalives_count == NULL)
- return 1;
-
- count = atoi(conn->keepalives_count);
- if (count < 0)
- count = 0;
-
-#ifdef TCP_KEEPCNT
- if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
- (char *) &count, sizeof(count)) < 0)
- {
- char sebuf[256];
-
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(%s) failed: %s\n"),
- "TCP_KEEPCNT",
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- return 0;
- }
-#endif
-
- return 1;
-}
-#else /* WIN32 */
-#ifdef SIO_KEEPALIVE_VALS
-/*
- * Enable keepalives and set the keepalive values on Win32,
- * where they are always set in one batch.
- */
-static int
-setKeepalivesWin32(PGconn *conn)
-{
- struct tcp_keepalive ka;
- DWORD retsize;
- int idle = 0;
- int interval = 0;
-
- if (conn->keepalives_idle)
- idle = atoi(conn->keepalives_idle);
- if (idle <= 0)
- idle = 2 * 60 * 60; /* 2 hours = default */
-
- if (conn->keepalives_interval)
- interval = atoi(conn->keepalives_interval);
- if (interval <= 0)
- interval = 1; /* 1 second = default */
-
- ka.onoff = 1;
- ka.keepalivetime = idle * 1000;
- ka.keepaliveinterval = interval * 1000;
-
- if (WSAIoctl(conn->sock,
- SIO_KEEPALIVE_VALS,
- (LPVOID) &ka,
- sizeof(ka),
- NULL,
- 0,
- &retsize,
- NULL,
- NULL)
- != 0)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui\n"),
- WSAGetLastError());
- return 0;
- }
- return 1;
-}
-#endif /* SIO_KEEPALIVE_VALS */
-#endif /* WIN32 */
-
-/* ----------
- * connectDBStart -
- * Begin the process of making a connection to the backend.
- *
- * Returns 1 if successful, 0 if not.
- * ----------
- */
-static int
-connectDBStart(PGconn *conn)
-{
- int portnum;
- char portstr[MAXPGPATH];
- struct addrinfo *addrs = NULL;
- struct addrinfo hint;
- const char *node;
- int ret;
-
- if (!conn)
- return 0;
-
- if (!conn->options_valid)
- goto connect_errReturn;
-
- /* Ensure our buffers are empty */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- conn->outCount = 0;
-
- /*
- * Determine the parameters to pass to pg_getaddrinfo_all.
- */
-
- /* Initialize hint structure */
- MemSet(&hint, 0, sizeof(hint));
- hint.ai_socktype = SOCK_STREAM;
- hint.ai_family = AF_UNSPEC;
-
- /* Set up port number as a string */
- if (conn->pgport != NULL && conn->pgport[0] != '\0')
- {
- portnum = atoi(conn->pgport);
- if (portnum < 1 || portnum > 65535)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid port number: \"%s\"\n"),
- conn->pgport);
- conn->options_valid = false;
- goto connect_errReturn;
- }
- }
- else
- portnum = DEF_PGPORT;
- snprintf(portstr, sizeof(portstr), "%d", portnum);
-
- if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
- {
- /* Using pghostaddr avoids a hostname lookup */
- node = conn->pghostaddr;
- hint.ai_family = AF_UNSPEC;
- hint.ai_flags = AI_NUMERICHOST;
- }
- else if (conn->pghost != NULL && conn->pghost[0] != '\0')
- {
- /* Using pghost, so we have to look-up the hostname */
- node = conn->pghost;
- hint.ai_family = AF_UNSPEC;
- }
- else
- {
-#ifdef HAVE_UNIX_SOCKETS
- /* pghostaddr and pghost are NULL, so use Unix domain socket */
- node = NULL;
- hint.ai_family = AF_UNIX;
- UNIXSOCK_PATH(portstr, portnum, conn->pgunixsocket);
- if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
- portstr,
- (int) (UNIXSOCK_PATH_BUFLEN - 1));
- conn->options_valid = false;
- goto connect_errReturn;
- }
-#else
- /* Without Unix sockets, default to localhost instead */
- node = DefaultHost;
- hint.ai_family = AF_UNSPEC;
-#endif /* HAVE_UNIX_SOCKETS */
- }
-
- /* Use pg_getaddrinfo_all() to resolve the address */
- ret = pg_getaddrinfo_all(node, portstr, &hint, &addrs);
- if (ret || !addrs)
- {
- if (node)
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
- node, gai_strerror(ret));
- else
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
- portstr, gai_strerror(ret));
- if (addrs)
- pg_freeaddrinfo_all(hint.ai_family, addrs);
- conn->options_valid = false;
- goto connect_errReturn;
- }
-
-#ifdef USE_SSL
- /* setup values based on SSL mode */
- if (conn->sslmode[0] == 'd') /* "disable" */
- conn->allow_ssl_try = false;
- else if (conn->sslmode[0] == 'a') /* "allow" */
- conn->wait_ssl_try = true;
-#endif
-
- /*
- * Set up to try to connect, with protocol 3.0 as the first attempt.
- */
- conn->addrlist = addrs;
- conn->addr_cur = addrs;
- conn->addrlist_family = hint.ai_family;
- conn->pversion = PG_PROTOCOL(3, 0);
- conn->send_appname = true;
- conn->status = CONNECTION_NEEDED;
-
- /*
- * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
- * so that it can easily be re-executed if needed again during the
- * asynchronous startup process. However, we must run it once here,
- * because callers expect a success return from this routine to mean that
- * we are in PGRES_POLLING_WRITING connection state.
- */
- if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
- return 1;
-
-connect_errReturn:
- pqDropConnection(conn, true);
- conn->status = CONNECTION_BAD;
- return 0;
-}
-
-
-/*
- * connectDBComplete
- *
- * Block and complete a connection.
- *
- * Returns 1 on success, 0 on failure.
- */
-static int
-connectDBComplete(PGconn *conn)
-{
- PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
- time_t finish_time = ((time_t) -1);
-
- if (conn == NULL || conn->status == CONNECTION_BAD)
- return 0;
-
- /*
- * Set up a time limit, if connect_timeout isn't zero.
- */
- if (conn->connect_timeout != NULL)
- {
- int timeout = atoi(conn->connect_timeout);
-
- if (timeout > 0)
- {
- /*
- * Rounding could cause connection to fail; need at least 2 secs
- */
- if (timeout < 2)
- timeout = 2;
- /* calculate the finish time based on start + timeout */
- finish_time = time(NULL) + timeout;
- }
- }
-
- for (;;)
- {
- /*
- * Wait, if necessary. Note that the initial state (just after
- * PQconnectStart) is to wait for the socket to select for writing.
- */
- switch (flag)
- {
- case PGRES_POLLING_OK:
-
- /*
- * Reset stored error messages since we now have a working
- * connection
- */
- resetPQExpBuffer(&conn->errorMessage);
- return 1; /* success! */
-
- case PGRES_POLLING_READING:
- if (pqWaitTimed(1, 0, conn, finish_time))
- {
- conn->status = CONNECTION_BAD;
- return 0;
- }
- break;
-
- case PGRES_POLLING_WRITING:
- if (pqWaitTimed(0, 1, conn, finish_time))
- {
- conn->status = CONNECTION_BAD;
- return 0;
- }
- break;
-
- default:
- /* Just in case we failed to set it in PQconnectPoll */
- conn->status = CONNECTION_BAD;
- return 0;
- }
-
- /*
- * Now try to advance the state machine.
- */
- flag = PQconnectPoll(conn);
- }
-}
-
-/* ----------------
- * PQconnectPoll
- *
- * Poll an asynchronous connection.
- *
- * Returns a PostgresPollingStatusType.
- * Before calling this function, use select(2) to determine when data
- * has arrived..
- *
- * You must call PQfinish whether or not this fails.
- *
- * This function and PQconnectStart are intended to allow connections to be
- * made without blocking the execution of your program on remote I/O. However,
- * there are a number of caveats:
- *
- * o If you call PQtrace, ensure that the stream object into which you trace
- * will not block.
- * o If you do not supply an IP address for the remote host (i.e. you
- * supply a host name instead) then PQconnectStart will block on
- * gethostbyname. You will be fine if using Unix sockets (i.e. by
- * supplying neither a host name nor a host address).
- * o If your backend wants to use Kerberos authentication then you must
- * supply both a host name and a host address, otherwise this function
- * may block on gethostname.
- *
- * ----------------
- */
-PostgresPollingStatusType
-PQconnectPoll(PGconn *conn)
-{
- PGresult *res;
- char sebuf[256];
- int optval;
-
- if (conn == NULL)
- return PGRES_POLLING_FAILED;
-
- /* Get the new data */
- switch (conn->status)
- {
- /*
- * We really shouldn't have been polled in these two cases, but we
- * can handle it.
- */
- case CONNECTION_BAD:
- return PGRES_POLLING_FAILED;
- case CONNECTION_OK:
- return PGRES_POLLING_OK;
-
- /* These are reading states */
- case CONNECTION_AWAITING_RESPONSE:
- case CONNECTION_AUTH_OK:
- {
- /* Load waiting data */
- int n = pqReadData(conn);
-
- if (n < 0)
- goto error_return;
- if (n == 0)
- return PGRES_POLLING_READING;
-
- break;
- }
-
- /* These are writing states, so we just proceed. */
- case CONNECTION_STARTED:
- case CONNECTION_MADE:
- break;
-
- /* We allow pqSetenvPoll to decide whether to proceed. */
- case CONNECTION_SETENV:
- break;
-
- /* Special cases: proceed without waiting. */
- case CONNECTION_SSL_STARTUP:
- case CONNECTION_NEEDED:
- break;
-
- default:
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext(
- "invalid connection state, "
- "probably indicative of memory corruption\n"
- ));
- goto error_return;
- }
-
-
-keep_going: /* We will come back to here until there is
- * nothing left to do. */
- switch (conn->status)
- {
- case CONNECTION_NEEDED:
- {
- /*
- * Try to initiate a connection to one of the addresses
- * returned by pg_getaddrinfo_all(). conn->addr_cur is the
- * next one to try. We fail when we run out of addresses.
- */
- while (conn->addr_cur != NULL)
- {
- struct addrinfo *addr_cur = conn->addr_cur;
-
- /* Remember current address for possible error msg */
- memcpy(&conn->raddr.addr, addr_cur->ai_addr,
- addr_cur->ai_addrlen);
- conn->raddr.salen = addr_cur->ai_addrlen;
-
- conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
- if (conn->sock == PGINVALID_SOCKET)
- {
- /*
- * ignore socket() failure if we have more addresses
- * to try
- */
- if (addr_cur->ai_next != NULL)
- {
- conn->addr_cur = addr_cur->ai_next;
- continue;
- }
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not create socket: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- break;
- }
-
- /*
- * Select socket options: no delay of outgoing data for
- * TCP sockets, nonblock mode, close-on-exec. Fail if any
- * of this fails.
- */
- if (!IS_AF_UNIX(addr_cur->ai_family))
- {
- if (!connectNoDelay(conn))
- {
- pqDropConnection(conn, true);
- conn->addr_cur = addr_cur->ai_next;
- continue;
- }
- }
- if (!pg_set_noblock(conn->sock))
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not set socket to nonblocking mode: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- pqDropConnection(conn, true);
- conn->addr_cur = addr_cur->ai_next;
- continue;
- }
-
-#ifdef F_SETFD
- if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- pqDropConnection(conn, true);
- conn->addr_cur = addr_cur->ai_next;
- continue;
- }
-#endif /* F_SETFD */
-
- if (!IS_AF_UNIX(addr_cur->ai_family))
- {
-#ifndef WIN32
- int on = 1;
-#endif
- int usekeepalives = useKeepalives(conn);
- int err = 0;
-
- if (usekeepalives < 0)
- {
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("keepalives parameter must be an integer\n"));
- err = 1;
- }
- else if (usekeepalives == 0)
- {
- /* Do nothing */
- }
-#ifndef WIN32
- else if (setsockopt(conn->sock,
- SOL_SOCKET, SO_KEEPALIVE,
- (char *) &on, sizeof(on)) < 0)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("setsockopt(%s) failed: %s\n"),
- "SO_KEEPALIVE",
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- err = 1;
- }
- else if (!setKeepalivesIdle(conn)
- || !setKeepalivesInterval(conn)
- || !setKeepalivesCount(conn))
- err = 1;
-#else /* WIN32 */
-#ifdef SIO_KEEPALIVE_VALS
- else if (!setKeepalivesWin32(conn))
- err = 1;
-#endif /* SIO_KEEPALIVE_VALS */
-#endif /* WIN32 */
-
- if (err)
- {
- pqDropConnection(conn, true);
- conn->addr_cur = addr_cur->ai_next;
- continue;
- }
- }
-
- /*----------
- * We have three methods of blocking SIGPIPE during
- * send() calls to this socket:
- *
- * - setsockopt(sock, SO_NOSIGPIPE)
- * - send(sock, ..., MSG_NOSIGNAL)
- * - setting the signal mask to SIG_IGN during send()
- *
- * The third method requires three syscalls per send,
- * so we prefer either of the first two, but they are
- * less portable. The state is tracked in the following
- * members of PGconn:
- *
- * conn->sigpipe_so - we have set up SO_NOSIGPIPE
- * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
- *
- * If we can use SO_NOSIGPIPE, then set sigpipe_so here
- * and we're done. Otherwise, set sigpipe_flag so that
- * we will try MSG_NOSIGNAL on sends. If we get an error
- * with MSG_NOSIGNAL, we'll clear that flag and revert to
- * signal masking.
- *----------
- */
- conn->sigpipe_so = false;
-#ifdef MSG_NOSIGNAL
- conn->sigpipe_flag = true;
-#else
- conn->sigpipe_flag = false;
-#endif /* MSG_NOSIGNAL */
-
-#ifdef SO_NOSIGPIPE
- optval = 1;
- if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
- (char *) &optval, sizeof(optval)) == 0)
- {
- conn->sigpipe_so = true;
- conn->sigpipe_flag = false;
- }
-#endif /* SO_NOSIGPIPE */
-
- /*
- * Start/make connection. This should not block, since we
- * are in nonblock mode. If it does, well, too bad.
- */
- if (connect(conn->sock, addr_cur->ai_addr,
- addr_cur->ai_addrlen) < 0)
- {
- if (SOCK_ERRNO == EINPROGRESS ||
-#ifdef WIN32
- SOCK_ERRNO == EWOULDBLOCK ||
-#endif
- SOCK_ERRNO == EINTR)
- {
- /*
- * This is fine - we're in non-blocking mode, and
- * the connection is in progress. Tell caller to
- * wait for write-ready on socket.
- */
- conn->status = CONNECTION_STARTED;
- return PGRES_POLLING_WRITING;
- }
- /* otherwise, trouble */
- }
- else
- {
- /*
- * Hm, we're connected already --- seems the "nonblock
- * connection" wasn't. Advance the state machine and
- * go do the next stuff.
- */
- conn->status = CONNECTION_STARTED;
- goto keep_going;
- }
-
- /*
- * This connection failed --- set up error report, then
- * close socket (do it this way in case close() affects
- * the value of errno...). We will ignore the connect()
- * failure and keep going if there are more addresses.
- */
- connectFailureMessage(conn, SOCK_ERRNO);
- pqDropConnection(conn, true);
-
- /*
- * Try the next address, if any.
- */
- conn->addr_cur = addr_cur->ai_next;
- } /* loop over addresses */
-
- /*
- * Ooops, no more addresses. An appropriate error message is
- * already set up, so just set the right status.
- */
- goto error_return;
- }
-
- case CONNECTION_STARTED:
- {
- ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
-
- /*
- * Write ready, since we've made it here, so the connection
- * has been made ... or has failed.
- */
-
- /*
- * Now check (using getsockopt) that there is not an error
- * state waiting for us on the socket.
- */
-
- if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
- (char *) &optval, &optlen) == -1)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not get socket error status: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- goto error_return;
- }
- else if (optval != 0)
- {
- /*
- * When using a nonblocking connect, we will typically see
- * connect failures at this point, so provide a friendly
- * error message.
- */
- connectFailureMessage(conn, optval);
- pqDropConnection(conn, true);
-
- /*
- * If more addresses remain, keep trying, just as in the
- * case where connect() returned failure immediately.
- */
- if (conn->addr_cur->ai_next != NULL)
- {
- conn->addr_cur = conn->addr_cur->ai_next;
- conn->status = CONNECTION_NEEDED;
- goto keep_going;
- }
- goto error_return;
- }
-
- /* Fill in the client address */
- conn->laddr.salen = sizeof(conn->laddr.addr);
- if (getsockname(conn->sock,
- (struct sockaddr *) & conn->laddr.addr,
- &conn->laddr.salen) < 0)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not get client address from socket: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- goto error_return;
- }
-
- /*
- * Make sure we can write before advancing to next step.
- */
- conn->status = CONNECTION_MADE;
- return PGRES_POLLING_WRITING;
- }
-
- case CONNECTION_MADE:
- {
- char *startpacket;
- int packetlen;
-
-#ifdef HAVE_UNIX_SOCKETS
-
- /*
- * Implement requirepeer check, if requested and it's a
- * Unix-domain socket.
- */
- if (conn->requirepeer && conn->requirepeer[0] &&
- IS_AF_UNIX(conn->raddr.addr.ss_family))
- {
- char pwdbuf[BUFSIZ];
- struct passwd pass_buf;
- struct passwd *pass;
- int passerr;
- uid_t uid;
- gid_t gid;
-
- errno = 0;
- if (getpeereid(conn->sock, &uid, &gid) != 0)
- {
- /*
- * Provide special error message if getpeereid is a
- * stub
- */
- if (errno == ENOSYS)
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("requirepeer parameter is not supported on this platform\n"));
- else
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not get peer credentials: %s\n"),
- pqStrerror(errno, sebuf, sizeof(sebuf)));
- goto error_return;
- }
-
- passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
- if (pass == NULL)
- {
- if (passerr != 0)
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not look up local user ID %d: %s\n"),
- (int) uid,
- pqStrerror(passerr, sebuf, sizeof(sebuf)));
- else
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("local user with ID %d does not exist\n"),
- (int) uid);
- goto error_return;
- }
-
- if (strcmp(pass->pw_name, conn->requirepeer) != 0)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
- conn->requirepeer, pass->pw_name);
- goto error_return;
- }
- }
-#endif /* HAVE_UNIX_SOCKETS */
-
-#ifdef USE_SSL
-
- /*
- * If SSL is enabled and we haven't already got it running,
- * request it instead of sending the startup message.
- */
- if (IS_AF_UNIX(conn->raddr.addr.ss_family))
- {
- /* Don't bother requesting SSL over a Unix socket */
- conn->allow_ssl_try = false;
- }
- if (conn->allow_ssl_try && !conn->wait_ssl_try &&
- !conn->ssl_in_use)
- {
- ProtocolVersion pv;
-
- /*
- * Send the SSL request packet.
- *
- * Theoretically, this could block, but it really
- * shouldn't since we only got here if the socket is
- * write-ready.
- */
- pv = htonl(NEGOTIATE_SSL_CODE);
- if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not send SSL negotiation packet: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- goto error_return;
- }
- /* Ok, wait for response */
- conn->status = CONNECTION_SSL_STARTUP;
- return PGRES_POLLING_READING;
- }
-#endif /* USE_SSL */
-
- /*
- * Build the startup packet.
- */
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- startpacket = pqBuildStartupPacket3(conn, &packetlen,
- EnvironmentOptions);
- else
- startpacket = pqBuildStartupPacket2(conn, &packetlen,
- EnvironmentOptions);
- if (!startpacket)
- {
- /*
- * will not appendbuffer here, since it's likely to also
- * run out of memory
- */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- goto error_return;
- }
-
- /*
- * Send the startup packet.
- *
- * Theoretically, this could block, but it really shouldn't
- * since we only got here if the socket is write-ready.
- */
- if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not send startup packet: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- free(startpacket);
- goto error_return;
- }
-
- free(startpacket);
-
- conn->status = CONNECTION_AWAITING_RESPONSE;
- return PGRES_POLLING_READING;
- }
-
- /*
- * Handle SSL negotiation: wait for postmaster messages and
- * respond as necessary.
- */
- case CONNECTION_SSL_STARTUP:
- {
-#ifdef USE_SSL
- PostgresPollingStatusType pollres;
-
- /*
- * On first time through, get the postmaster's response to our
- * SSL negotiation packet.
- */
- if (!conn->ssl_in_use)
- {
- /*
- * We use pqReadData here since it has the logic to
- * distinguish no-data-yet from connection closure. Since
- * conn->ssl isn't set, a plain recv() will occur.
- */
- char SSLok;
- int rdresult;
-
- rdresult = pqReadData(conn);
- if (rdresult < 0)
- {
- /* errorMessage is already filled in */
- goto error_return;
- }
- if (rdresult == 0)
- {
- /* caller failed to wait for data */
- return PGRES_POLLING_READING;
- }
- if (pqGetc(&SSLok, conn) < 0)
- {
- /* should not happen really */
- return PGRES_POLLING_READING;
- }
- if (SSLok == 'S')
- {
- /* mark byte consumed */
- conn->inStart = conn->inCursor;
- /* Set up global SSL state if required */
- if (pqsecure_initialize(conn) != 0)
- goto error_return;
- }
- else if (SSLok == 'N')
- {
- /* mark byte consumed */
- conn->inStart = conn->inCursor;
- /* OK to do without SSL? */
- if (conn->sslmode[0] == 'r' || /* "require" */
- conn->sslmode[0] == 'v') /* "verify-ca" or
- * "verify-full" */
- {
- /* Require SSL, but server does not want it */
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("server does not support SSL, but SSL was required\n"));
- goto error_return;
- }
- /* Otherwise, proceed with normal startup */
- conn->allow_ssl_try = false;
- conn->status = CONNECTION_MADE;
- return PGRES_POLLING_WRITING;
- }
- else if (SSLok == 'E')
- {
- /*
- * Server failure of some sort, such as failure to
- * fork a backend process. We need to process and
- * report the error message, which might be formatted
- * according to either protocol 2 or protocol 3.
- * Rather than duplicate the code for that, we flip
- * into AWAITING_RESPONSE state and let the code there
- * deal with it. Note we have *not* consumed the "E"
- * byte here.
- */
- conn->status = CONNECTION_AWAITING_RESPONSE;
- goto keep_going;
- }
- else
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("received invalid response to SSL negotiation: %c\n"),
- SSLok);
- goto error_return;
- }
- }
-
- /*
- * Begin or continue the SSL negotiation process.
- */
- pollres = pqsecure_open_client(conn);
- if (pollres == PGRES_POLLING_OK)
- {
- /* SSL handshake done, ready to send startup packet */
- conn->status = CONNECTION_MADE;
- return PGRES_POLLING_WRITING;
- }
- if (pollres == PGRES_POLLING_FAILED)
- {
- /*
- * Failed ... if sslmode is "prefer" then do a non-SSL
- * retry
- */
- if (conn->sslmode[0] == 'p' /* "prefer" */
- && conn->allow_ssl_try /* redundant? */
- && !conn->wait_ssl_try) /* redundant? */
- {
- /* only retry once */
- conn->allow_ssl_try = false;
- /* Must drop the old connection */
- pqDropConnection(conn, true);
- conn->status = CONNECTION_NEEDED;
- goto keep_going;
- }
- }
- return pollres;
-#else /* !USE_SSL */
- /* can't get here */
- goto error_return;
-#endif /* USE_SSL */
- }
-
- /*
- * Handle authentication exchange: wait for postmaster messages
- * and respond as necessary.
- */
- case CONNECTION_AWAITING_RESPONSE:
- {
- char beresp;
- int msgLength;
- int avail;
- AuthRequest areq;
-
- /*
- * Scan the message from current point (note that if we find
- * the message is incomplete, we will return without advancing
- * inStart, and resume here next time).
- */
- conn->inCursor = conn->inStart;
-
- /* Read type byte */
- if (pqGetc(&beresp, conn))
- {
- /* We'll come back when there is more data */
- return PGRES_POLLING_READING;
- }
-
- /*
- * Validate message type: we expect only an authentication
- * request or an error here. Anything else probably means
- * it's not Postgres on the other end at all.
- */
- if (!(beresp == 'R' || beresp == 'E'))
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "expected authentication request from "
- "server, but received %c\n"),
- beresp);
- goto error_return;
- }
-
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- /* Read message length word */
- if (pqGetInt(&msgLength, 4, conn))
- {
- /* We'll come back when there is more data */
- return PGRES_POLLING_READING;
- }
- }
- else
- {
- /* Set phony message length to disable checks below */
- msgLength = 8;
- }
-
- /*
- * Try to validate message length before using it.
- * Authentication requests can't be very large, although GSS
- * auth requests may not be that small. Errors can be a
- * little larger, but not huge. If we see a large apparent
- * length in an error, it means we're really talking to a
- * pre-3.0-protocol server; cope.
- */
- if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "expected authentication request from "
- "server, but received %c\n"),
- beresp);
- goto error_return;
- }
-
- if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
- {
- /* Handle error from a pre-3.0 server */
- conn->inCursor = conn->inStart + 1; /* reread data */
- if (pqGets_append(&conn->errorMessage, conn))
- {
- /* We'll come back when there is more data */
- return PGRES_POLLING_READING;
- }
- /* OK, we read the message; mark data consumed */
- conn->inStart = conn->inCursor;
-
- /*
- * The postmaster typically won't end its message with a
- * newline, so add one to conform to libpq conventions.
- */
- appendPQExpBufferChar(&conn->errorMessage, '\n');
-
- /*
- * If we tried to open the connection in 3.0 protocol,
- * fall back to 2.0 protocol.
- */
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- conn->pversion = PG_PROTOCOL(2, 0);
- /* Must drop the old connection */
- pqDropConnection(conn, true);
- conn->status = CONNECTION_NEEDED;
- goto keep_going;
- }
-
- goto error_return;
- }
-
- /*
- * Can't process if message body isn't all here yet.
- *
- * (In protocol 2.0 case, we are assuming messages carry at
- * least 4 bytes of data.)
- */
- msgLength -= 4;
- avail = conn->inEnd - conn->inCursor;
- if (avail < msgLength)
- {
- /*
- * Before returning, try to enlarge the input buffer if
- * needed to hold the whole message; see notes in
- * pqParseInput3.
- */
- if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
- conn))
- goto error_return;
- /* We'll come back when there is more data */
- return PGRES_POLLING_READING;
- }
-
- /* Handle errors. */
- if (beresp == 'E')
- {
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- if (pqGetErrorNotice3(conn, true))
- {
- /* We'll come back when there is more data */
- return PGRES_POLLING_READING;
- }
- }
- else
- {
- if (pqGets_append(&conn->errorMessage, conn))
- {
- /* We'll come back when there is more data */
- return PGRES_POLLING_READING;
- }
- }
- /* OK, we read the message; mark data consumed */
- conn->inStart = conn->inCursor;
-
-#ifdef USE_SSL
-
- /*
- * if sslmode is "allow" and we haven't tried an SSL
- * connection already, then retry with an SSL connection
- */
- if (conn->sslmode[0] == 'a' /* "allow" */
- && !conn->ssl_in_use
- && conn->allow_ssl_try
- && conn->wait_ssl_try)
- {
- /* only retry once */
- conn->wait_ssl_try = false;
- /* Must drop the old connection */
- pqDropConnection(conn, true);
- conn->status = CONNECTION_NEEDED;
- goto keep_going;
- }
-
- /*
- * if sslmode is "prefer" and we're in an SSL connection,
- * then do a non-SSL retry
- */
- if (conn->sslmode[0] == 'p' /* "prefer" */
- && conn->allow_ssl_try
- && !conn->wait_ssl_try) /* redundant? */
- {
- /* only retry once */
- conn->allow_ssl_try = false;
- /* Must drop the old connection */
- pqDropConnection(conn, true);
- conn->status = CONNECTION_NEEDED;
- goto keep_going;
- }
-#endif
-
- goto error_return;
- }
-
- /* It is an authentication request. */
- conn->auth_req_received = true;
-
- /* Get the type of request. */
- if (pqGetInt((int *) &areq, 4, conn))
- {
- /* We'll come back when there are more data */
- return PGRES_POLLING_READING;
- }
-
- /* Get the password salt if there is one. */
- if (areq == AUTH_REQ_MD5)
- {
- if (pqGetnchar(conn->md5Salt,
- sizeof(conn->md5Salt), conn))
- {
- /* We'll come back when there are more data */
- return PGRES_POLLING_READING;
- }
- }
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
-
- /*
- * Continue GSSAPI/SSPI authentication
- */
- if (areq == AUTH_REQ_GSS_CONT)
- {
- int llen = msgLength - 4;
-
- /*
- * We can be called repeatedly for the same buffer. Avoid
- * re-allocating the buffer in this case - just re-use the
- * old buffer.
- */
- if (llen != conn->ginbuf.length)
- {
- if (conn->ginbuf.value)
- free(conn->ginbuf.value);
-
- conn->ginbuf.length = llen;
- conn->ginbuf.value = malloc(llen);
- if (!conn->ginbuf.value)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory allocating GSSAPI buffer (%d)"),
- llen);
- goto error_return;
- }
- }
-
- if (pqGetnchar(conn->ginbuf.value, llen, conn))
- {
- /* We'll come back when there is more data. */
- return PGRES_POLLING_READING;
- }
- }
-#endif
-
- /*
- * OK, we successfully read the message; mark data consumed
- */
- conn->inStart = conn->inCursor;
-
- /* Respond to the request if necessary. */
-
- /*
- * Note that conn->pghost must be non-NULL if we are going to
- * avoid the Kerberos code doing a hostname look-up.
- */
-
- if (pg_fe_sendauth(areq, conn) != STATUS_OK)
- {
- conn->errorMessage.len = strlen(conn->errorMessage.data);
- goto error_return;
- }
- conn->errorMessage.len = strlen(conn->errorMessage.data);
-
- /*
- * Just make sure that any data sent by pg_fe_sendauth is
- * flushed out. Although this theoretically could block, it
- * really shouldn't since we don't send large auth responses.
- */
- if (pqFlush(conn))
- goto error_return;
-
- if (areq == AUTH_REQ_OK)
- {
- /* We are done with authentication exchange */
- conn->status = CONNECTION_AUTH_OK;
-
- /*
- * Set asyncStatus so that PQgetResult will think that
- * what comes back next is the result of a query. See
- * below.
- */
- conn->asyncStatus = PGASYNC_BUSY;
- }
-
- /* Look to see if we have more data yet. */
- goto keep_going;
- }
-
- case CONNECTION_AUTH_OK:
- {
- /*
- * Now we expect to hear from the backend. A ReadyForQuery
- * message indicates that startup is successful, but we might
- * also get an Error message indicating failure. (Notice
- * messages indicating nonfatal warnings are also allowed by
- * the protocol, as are ParameterStatus and BackendKeyData
- * messages.) Easiest way to handle this is to let
- * PQgetResult() read the messages. We just have to fake it
- * out about the state of the connection, by setting
- * asyncStatus = PGASYNC_BUSY (done above).
- */
-
- if (PQisBusy(conn))
- return PGRES_POLLING_READING;
-
- res = PQgetResult(conn);
-
- /*
- * NULL return indicating we have gone to IDLE state is
- * expected
- */
- if (res)
- {
- if (res->resultStatus != PGRES_FATAL_ERROR)
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("unexpected message from server during startup\n"));
- else if (conn->send_appname &&
- (conn->appname || conn->fbappname))
- {
- /*
- * If we tried to send application_name, check to see
- * if the error is about that --- pre-9.0 servers will
- * reject it at this stage of the process. If so,
- * close the connection and retry without sending
- * application_name. We could possibly get a false
- * SQLSTATE match here and retry uselessly, but there
- * seems no great harm in that; we'll just get the
- * same error again if it's unrelated.
- */
- const char *sqlstate;
-
- sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
- if (sqlstate &&
- strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
- {
- PQclear(res);
- conn->send_appname = false;
- /* Must drop the old connection */
- pqDropConnection(conn, true);
- conn->status = CONNECTION_NEEDED;
- goto keep_going;
- }
- }
-
- /*
- * if the resultStatus is FATAL, then conn->errorMessage
- * already has a copy of the error; needn't copy it back.
- * But add a newline if it's not there already, since
- * postmaster error messages may not have one.
- */
- if (conn->errorMessage.len <= 0 ||
- conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
- appendPQExpBufferChar(&conn->errorMessage, '\n');
- PQclear(res);
- goto error_return;
- }
-
- /* We can release the address list now. */
- pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
- conn->addrlist = NULL;
- conn->addr_cur = NULL;
-
- /* Fire up post-connection housekeeping if needed */
- if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
- {
- conn->status = CONNECTION_SETENV;
- conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_SEND;
- conn->next_eo = EnvironmentOptions;
- return PGRES_POLLING_WRITING;
- }
-
- /* Otherwise, we are open for business! */
- conn->status = CONNECTION_OK;
- return PGRES_POLLING_OK;
- }
-
- case CONNECTION_SETENV:
-
- /*
- * Do post-connection housekeeping (only needed in protocol 2.0).
- *
- * We pretend that the connection is OK for the duration of these
- * queries.
- */
- conn->status = CONNECTION_OK;
-
- switch (pqSetenvPoll(conn))
- {
- case PGRES_POLLING_OK: /* Success */
- break;
-
- case PGRES_POLLING_READING: /* Still going */
- conn->status = CONNECTION_SETENV;
- return PGRES_POLLING_READING;
-
- case PGRES_POLLING_WRITING: /* Still going */
- conn->status = CONNECTION_SETENV;
- return PGRES_POLLING_WRITING;
-
- default:
- goto error_return;
- }
-
- /* We are open for business! */
- conn->status = CONNECTION_OK;
- return PGRES_POLLING_OK;
-
- default:
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid connection state %d, "
- "probably indicative of memory corruption\n"),
- conn->status);
- goto error_return;
- }
-
- /* Unreachable */
-
-error_return:
-
- dot_pg_pass_warning(conn);
-
- /*
- * We used to close the socket at this point, but that makes it awkward
- * for those above us if they wish to remove this socket from their own
- * records (an fd_set for example). We'll just have this socket closed
- * when PQfinish is called (which is compulsory even after an error, since
- * the connection structure must be freed).
- */
- conn->status = CONNECTION_BAD;
- return PGRES_POLLING_FAILED;
-}
-
-
-/*
- * internal_ping
- * Determine if a server is running and if we can connect to it.
- *
- * The argument is a connection that's been started, but not completed.
- */
-static PGPing
-internal_ping(PGconn *conn)
-{
- /* Say "no attempt" if we never got to PQconnectPoll */
- if (!conn || !conn->options_valid)
- return PQPING_NO_ATTEMPT;
-
- /* Attempt to complete the connection */
- if (conn->status != CONNECTION_BAD)
- (void) connectDBComplete(conn);
-
- /* Definitely OK if we succeeded */
- if (conn->status != CONNECTION_BAD)
- return PQPING_OK;
-
- /*
- * Here begins the interesting part of "ping": determine the cause of the
- * failure in sufficient detail to decide what to return. We do not want
- * to report that the server is not up just because we didn't have a valid
- * password, for example. In fact, any sort of authentication request
- * implies the server is up. (We need this check since the libpq side of
- * things might have pulled the plug on the connection before getting an
- * error as such from the postmaster.)
- */
- if (conn->auth_req_received)
- return PQPING_OK;
-
- /*
- * If we failed to get any ERROR response from the postmaster, report
- * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
- * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
- * out of support. Another corner case where the server could return a
- * failure without a SQLSTATE is fork failure, but NO_RESPONSE isn't
- * totally unreasonable for that anyway. We expect that every other
- * failure case in a modern server will produce a report with a SQLSTATE.
- *
- * NOTE: whenever we get around to making libpq generate SQLSTATEs for
- * client-side errors, we should either not store those into
- * last_sqlstate, or add an extra flag so we can tell client-side errors
- * apart from server-side ones.
- */
- if (strlen(conn->last_sqlstate) != 5)
- return PQPING_NO_RESPONSE;
-
- /*
- * Report PQPING_REJECT if server says it's not accepting connections. (We
- * distinguish this case mainly for the convenience of pg_ctl.)
- */
- if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
- return PQPING_REJECT;
-
- /*
- * Any other SQLSTATE can be taken to indicate that the server is up.
- * Presumably it didn't like our username, password, or database name; or
- * perhaps it had some transient failure, but that should not be taken as
- * meaning "it's down".
- */
- return PQPING_OK;
-}
-
-
-/*
- * makeEmptyPGconn
- * - create a PGconn data structure with (as yet) no interesting data
- */
-static PGconn *
-makeEmptyPGconn(void)
-{
- PGconn *conn;
-
-#ifdef WIN32
-
- /*
- * Make sure socket support is up and running.
- */
- WSADATA wsaData;
-
- if (WSAStartup(MAKEWORD(1, 1), &wsaData))
- return NULL;
- WSASetLastError(0);
-#endif
-
- conn = (PGconn *) malloc(sizeof(PGconn));
- if (conn == NULL)
- {
-#ifdef WIN32
- WSACleanup();
-#endif
- return conn;
- }
-
- /* Zero all pointers and booleans */
- MemSet(conn, 0, sizeof(PGconn));
-
- /* install default notice hooks */
- conn->noticeHooks.noticeRec = defaultNoticeReceiver;
- conn->noticeHooks.noticeProc = defaultNoticeProcessor;
-
- conn->status = CONNECTION_BAD;
- conn->asyncStatus = PGASYNC_IDLE;
- conn->xactStatus = PQTRANS_IDLE;
- conn->options_valid = false;
- conn->nonblocking = false;
- conn->setenv_state = SETENV_STATE_IDLE;
- conn->client_encoding = PG_SQL_ASCII;
- conn->std_strings = false; /* unless server says differently */
- conn->verbosity = PQERRORS_DEFAULT;
- conn->show_context = PQSHOW_CONTEXT_ERRORS;
- conn->sock = PGINVALID_SOCKET;
- conn->auth_req_received = false;
- conn->password_needed = false;
- conn->dot_pgpass_used = false;
-#ifdef USE_SSL
- conn->allow_ssl_try = true;
- conn->wait_ssl_try = false;
- conn->ssl_in_use = false;
-#endif
-
- /*
- * We try to send at least 8K at a time, which is the usual size of pipe
- * buffers on Unix systems. That way, when we are sending a large amount
- * of data, we avoid incurring extra kernel context swaps for partial
- * bufferloads. The output buffer is initially made 16K in size, and we
- * try to dump it after accumulating 8K.
- *
- * With the same goal of minimizing context swaps, the input buffer will
- * be enlarged anytime it has less than 8K free, so we initially allocate
- * twice that.
- */
- conn->inBufSize = 16 * 1024;
- conn->inBuffer = (char *) malloc(conn->inBufSize);
- conn->outBufSize = 16 * 1024;
- conn->outBuffer = (char *) malloc(conn->outBufSize);
- conn->rowBufLen = 32;
- conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
- initPQExpBuffer(&conn->errorMessage);
- initPQExpBuffer(&conn->workBuffer);
-
- if (conn->inBuffer == NULL ||
- conn->outBuffer == NULL ||
- conn->rowBuf == NULL ||
- PQExpBufferBroken(&conn->errorMessage) ||
- PQExpBufferBroken(&conn->workBuffer))
- {
- /* out of memory already :-( */
- freePGconn(conn);
- conn = NULL;
- }
-
- return conn;
-}
-
-/*
- * freePGconn
- * - free an idle (closed) PGconn data structure
- *
- * NOTE: this should not overlap any functionality with closePGconn().
- * Clearing/resetting of transient state belongs there; what we do here is
- * release data that is to be held for the life of the PGconn structure.
- * If a value ought to be cleared/freed during PQreset(), do it there not here.
- */
-static void
-freePGconn(PGconn *conn)
-{
- int i;
-
- /* let any event procs clean up their state data */
- for (i = 0; i < conn->nEvents; i++)
- {
- PGEventConnDestroy evt;
-
- evt.conn = conn;
- (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
- conn->events[i].passThrough);
- free(conn->events[i].name);
- }
-
- if (conn->client_encoding_initial)
- free(conn->client_encoding_initial);
- if (conn->events)
- free(conn->events);
- if (conn->pghost)
- free(conn->pghost);
- if (conn->pghostaddr)
- free(conn->pghostaddr);
- if (conn->pgport)
- free(conn->pgport);
- if (conn->pgunixsocket)
- free(conn->pgunixsocket);
- if (conn->pgtty)
- free(conn->pgtty);
- if (conn->connect_timeout)
- free(conn->connect_timeout);
- if (conn->pgoptions)
- free(conn->pgoptions);
- if (conn->appname)
- free(conn->appname);
- if (conn->fbappname)
- free(conn->fbappname);
- if (conn->dbName)
- free(conn->dbName);
- if (conn->replication)
- free(conn->replication);
- if (conn->pguser)
- free(conn->pguser);
- if (conn->pgpass)
- free(conn->pgpass);
- if (conn->keepalives)
- free(conn->keepalives);
- if (conn->keepalives_idle)
- free(conn->keepalives_idle);
- if (conn->keepalives_interval)
- free(conn->keepalives_interval);
- if (conn->keepalives_count)
- free(conn->keepalives_count);
- if (conn->sslmode)
- free(conn->sslmode);
- if (conn->sslcert)
- free(conn->sslcert);
- if (conn->sslkey)
- free(conn->sslkey);
- if (conn->sslrootcert)
- free(conn->sslrootcert);
- if (conn->sslcrl)
- free(conn->sslcrl);
- if (conn->sslcompression)
- free(conn->sslcompression);
- if (conn->requirepeer)
- free(conn->requirepeer);
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
- if (conn->krbsrvname)
- free(conn->krbsrvname);
-#endif
-#if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
- if (conn->gsslib)
- free(conn->gsslib);
-#endif
- /* Note that conn->Pfdebug is not ours to close or free */
- if (conn->last_query)
- free(conn->last_query);
- if (conn->inBuffer)
- free(conn->inBuffer);
- if (conn->outBuffer)
- free(conn->outBuffer);
- if (conn->rowBuf)
- free(conn->rowBuf);
- termPQExpBuffer(&conn->errorMessage);
- termPQExpBuffer(&conn->workBuffer);
-
- free(conn);
-
-#ifdef WIN32
- WSACleanup();
-#endif
-}
-
-/*
- * closePGconn
- * - properly close a connection to the backend
- *
- * This should reset or release all transient state, but NOT the connection
- * parameters. On exit, the PGconn should be in condition to start a fresh
- * connection with the same parameters (see PQreset()).
- */
-static void
-closePGconn(PGconn *conn)
-{
- PGnotify *notify;
- pgParameterStatus *pstatus;
-
- /*
- * Note that the protocol doesn't allow us to send Terminate messages
- * during the startup phase.
- */
- if (conn->sock != PGINVALID_SOCKET && conn->status == CONNECTION_OK)
- {
- /*
- * Try to send "close connection" message to backend. Ignore any
- * error.
- */
- pqPutMsgStart('X', false, conn);
- pqPutMsgEnd(conn);
- (void) pqFlush(conn);
- }
-
- /*
- * Must reset the blocking status so a possible reconnect will work.
- *
- * Don't call PQsetnonblocking() because it will fail if it's unable to
- * flush the connection.
- */
- conn->nonblocking = FALSE;
-
- /*
- * Close the connection, reset all transient state, flush I/O buffers.
- */
- pqDropConnection(conn, true);
- conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just
- * absent */
- conn->asyncStatus = PGASYNC_IDLE;
- pqClearAsyncResult(conn); /* deallocate result */
- resetPQExpBuffer(&conn->errorMessage);
- pg_freeaddrinfo_all(conn->addrlist_family, conn->addrlist);
- conn->addrlist = NULL;
- conn->addr_cur = NULL;
- notify = conn->notifyHead;
- while (notify != NULL)
- {
- PGnotify *prev = notify;
-
- notify = notify->next;
- free(prev);
- }
- conn->notifyHead = conn->notifyTail = NULL;
- pstatus = conn->pstatus;
- while (pstatus != NULL)
- {
- pgParameterStatus *prev = pstatus;
-
- pstatus = pstatus->next;
- free(prev);
- }
- conn->pstatus = NULL;
- if (conn->lobjfuncs)
- free(conn->lobjfuncs);
- conn->lobjfuncs = NULL;
-}
-
-/*
- * PQfinish: properly close a connection to the backend. Also frees
- * the PGconn data structure so it shouldn't be re-used after this.
- */
-void
-PQfinish(PGconn *conn)
-{
- if (conn)
- {
- closePGconn(conn);
- freePGconn(conn);
- }
-}
-
-/*
- * PQreset: resets the connection to the backend by closing the
- * existing connection and creating a new one.
- */
-void
-PQreset(PGconn *conn)
-{
- if (conn)
- {
- closePGconn(conn);
-
- if (connectDBStart(conn) && connectDBComplete(conn))
- {
- /*
- * Notify event procs of successful reset. We treat an event proc
- * failure as disabling the connection ... good idea?
- */
- int i;
-
- for (i = 0; i < conn->nEvents; i++)
- {
- PGEventConnReset evt;
-
- evt.conn = conn;
- if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
- conn->events[i].passThrough))
- {
- conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
- conn->events[i].name);
- break;
- }
- }
- }
- }
-}
-
-
-/*
- * PQresetStart:
- * resets the connection to the backend
- * closes the existing connection and makes a new one
- * Returns 1 on success, 0 on failure.
- */
-int
-PQresetStart(PGconn *conn)
-{
- if (conn)
- {
- closePGconn(conn);
-
- return connectDBStart(conn);
- }
-
- return 0;
-}
-
-
-/*
- * PQresetPoll:
- * resets the connection to the backend
- * closes the existing connection and makes a new one
- */
-PostgresPollingStatusType
-PQresetPoll(PGconn *conn)
-{
- if (conn)
- {
- PostgresPollingStatusType status = PQconnectPoll(conn);
-
- if (status == PGRES_POLLING_OK)
- {
- /*
- * Notify event procs of successful reset. We treat an event proc
- * failure as disabling the connection ... good idea?
- */
- int i;
-
- for (i = 0; i < conn->nEvents; i++)
- {
- PGEventConnReset evt;
-
- evt.conn = conn;
- if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
- conn->events[i].passThrough))
- {
- conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
- conn->events[i].name);
- return PGRES_POLLING_FAILED;
- }
- }
- }
-
- return status;
- }
-
- return PGRES_POLLING_FAILED;
-}
-
-/*
- * PQgetCancel: get a PGcancel structure corresponding to a connection.
- *
- * A copy is needed to be able to cancel a running query from a different
- * thread. If the same structure is used all structure members would have
- * to be individually locked (if the entire structure was locked, it would
- * be impossible to cancel a synchronous query because the structure would
- * have to stay locked for the duration of the query).
- */
-PGcancel *
-PQgetCancel(PGconn *conn)
-{
- PGcancel *cancel;
-
- if (!conn)
- return NULL;
-
- if (conn->sock == PGINVALID_SOCKET)
- return NULL;
-
- cancel = malloc(sizeof(PGcancel));
- if (cancel == NULL)
- return NULL;
-
- memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
- cancel->be_pid = conn->be_pid;
- cancel->be_key = conn->be_key;
-
- return cancel;
-}
-
-/* PQfreeCancel: free a cancel structure */
-void
-PQfreeCancel(PGcancel *cancel)
-{
- if (cancel)
- free(cancel);
-}
-
-
-/*
- * PQcancel and PQrequestCancel: attempt to request cancellation of the
- * current operation.
- *
- * The return value is TRUE if the cancel request was successfully
- * dispatched, FALSE if not (in which case an error message is available).
- * Note: successful dispatch is no guarantee that there will be any effect at
- * the backend. The application must read the operation result as usual.
- *
- * CAUTION: we want this routine to be safely callable from a signal handler
- * (for example, an application might want to call it in a SIGINT handler).
- * This means we cannot use any C library routine that might be non-reentrant.
- * malloc/free are often non-reentrant, and anything that might call them is
- * just as dangerous. We avoid sprintf here for that reason. Building up
- * error messages with strcpy/strcat is tedious but should be quite safe.
- * We also save/restore errno in case the signal handler support doesn't.
- *
- * internal_cancel() is an internal helper function to make code-sharing
- * between the two versions of the cancel function possible.
- */
-static int
-internal_cancel(SockAddr *raddr, int be_pid, int be_key,
- char *errbuf, int errbufsize)
-{
- int save_errno = SOCK_ERRNO;
- pgsocket tmpsock = PGINVALID_SOCKET;
- char sebuf[256];
- int maxlen;
- struct
- {
- uint32 packetlen;
- CancelRequestPacket cp;
- } crp;
-
- /*
- * We need to open a temporary connection to the postmaster. Do this with
- * only kernel calls.
- */
- if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
- {
- strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
- goto cancel_errReturn;
- }
-retry3:
- if (connect(tmpsock, (struct sockaddr *) & raddr->addr,
- raddr->salen) < 0)
- {
- if (SOCK_ERRNO == EINTR)
- /* Interrupted system call - we'll just try again */
- goto retry3;
- strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
- goto cancel_errReturn;
- }
-
- /*
- * We needn't set nonblocking I/O or NODELAY options here.
- */
-
- /* Create and send the cancel request packet. */
-
- crp.packetlen = htonl((uint32) sizeof(crp));
- crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
- crp.cp.backendPID = htonl(be_pid);
- crp.cp.cancelAuthCode = htonl(be_key);
-
-retry4:
- if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
- {
- if (SOCK_ERRNO == EINTR)
- /* Interrupted system call - we'll just try again */
- goto retry4;
- strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
- goto cancel_errReturn;
- }
-
- /*
- * Wait for the postmaster to close the connection, which indicates that
- * it's processed the request. Without this delay, we might issue another
- * command only to find that our cancel zaps that command instead of the
- * one we thought we were canceling. Note we don't actually expect this
- * read to obtain any data, we are just waiting for EOF to be signaled.
- */
-retry5:
- if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
- {
- if (SOCK_ERRNO == EINTR)
- /* Interrupted system call - we'll just try again */
- goto retry5;
- /* we ignore other error conditions */
- }
-
- /* All done */
- closesocket(tmpsock);
- SOCK_ERRNO_SET(save_errno);
- return TRUE;
-
-cancel_errReturn:
-
- /*
- * Make sure we don't overflow the error buffer. Leave space for the \n at
- * the end, and for the terminating zero.
- */
- maxlen = errbufsize - strlen(errbuf) - 2;
- if (maxlen >= 0)
- {
- strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
- maxlen);
- strcat(errbuf, "\n");
- }
- if (tmpsock != PGINVALID_SOCKET)
- closesocket(tmpsock);
- SOCK_ERRNO_SET(save_errno);
- return FALSE;
-}
-
-/*
- * PQcancel: request query cancel
- *
- * Returns TRUE if able to send the cancel request, FALSE if not.
- *
- * On failure, an error message is stored in *errbuf, which must be of size
- * errbufsize (recommended size is 256 bytes). *errbuf is not changed on
- * success return.
- */
-int
-PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
-{
- if (!cancel)
- {
- strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
- return FALSE;
- }
-
- return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
- errbuf, errbufsize);
-}
-
-/*
- * PQrequestCancel: old, not thread-safe function for requesting query cancel
- *
- * Returns TRUE if able to send the cancel request, FALSE if not.
- *
- * On failure, the error message is saved in conn->errorMessage; this means
- * that this can't be used when there might be other active operations on
- * the connection object.
- *
- * NOTE: error messages will be cut off at the current size of the
- * error message buffer, since we dare not try to expand conn->errorMessage!
- */
-int
-PQrequestCancel(PGconn *conn)
-{
- int r;
-
- /* Check we have an open connection */
- if (!conn)
- return FALSE;
-
- if (conn->sock == PGINVALID_SOCKET)
- {
- strlcpy(conn->errorMessage.data,
- "PQrequestCancel() -- connection is not open\n",
- conn->errorMessage.maxlen);
- conn->errorMessage.len = strlen(conn->errorMessage.data);
-
- return FALSE;
- }
-
- r = internal_cancel(&conn->raddr, conn->be_pid, conn->be_key,
- conn->errorMessage.data, conn->errorMessage.maxlen);
-
- if (!r)
- conn->errorMessage.len = strlen(conn->errorMessage.data);
-
- return r;
-}
-
-
-/*
- * pqPacketSend() -- convenience routine to send a message to server.
- *
- * pack_type: the single-byte message type code. (Pass zero for startup
- * packets, which have no message type code.)
- *
- * buf, buf_len: contents of message. The given length includes only what
- * is in buf; the message type and message length fields are added here.
- *
- * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
- * SIDE_EFFECTS: may block.
- *
- * Note: all messages sent with this routine have a length word, whether
- * it's protocol 2.0 or 3.0.
- */
-int
-pqPacketSend(PGconn *conn, char pack_type,
- const void *buf, size_t buf_len)
-{
- /* Start the message. */
- if (pqPutMsgStart(pack_type, true, conn))
- return STATUS_ERROR;
-
- /* Send the message body. */
- if (pqPutnchar(buf, buf_len, conn))
- return STATUS_ERROR;
-
- /* Finish the message. */
- if (pqPutMsgEnd(conn))
- return STATUS_ERROR;
-
- /* Flush to ensure backend gets it. */
- if (pqFlush(conn))
- return STATUS_ERROR;
-
- return STATUS_OK;
-}
-
-#ifdef USE_LDAP
-
-#define LDAP_URL "ldap://"
-#define LDAP_DEF_PORT 389
-#define PGLDAP_TIMEOUT 2
-
-#define ld_is_sp_tab(x) ((x) == ' ' || (x) == '\t')
-#define ld_is_nl_cr(x) ((x) == '\r' || (x) == '\n')
-
-
-/*
- * ldapServiceLookup
- *
- * Search the LDAP URL passed as first argument, treat the result as a
- * string of connection options that are parsed and added to the array of
- * options passed as second argument.
- *
- * LDAP URLs must conform to RFC 1959 without escape sequences.
- * ldap://host:port/dn?attributes?scope?filter?extensions
- *
- * Returns
- * 0 if the lookup was successful,
- * 1 if the connection to the LDAP server could be established but
- * the search was unsuccessful,
- * 2 if a connection could not be established, and
- * 3 if a fatal error occurred.
- *
- * An error message is returned in the third argument for return codes 1 and 3.
- */
-static int
-ldapServiceLookup(const char *purl, PQconninfoOption *options,
- PQExpBuffer errorMessage)
-{
- int port = LDAP_DEF_PORT,
- scope,
- rc,
- size,
- state,
- oldstate,
- i;
-#ifndef WIN32
- int msgid;
-#endif
- bool found_keyword;
- char *url,
- *hostname,
- *portstr,
- *endptr,
- *dn,
- *scopestr,
- *filter,
- *result,
- *p,
- *p1 = NULL,
- *optname = NULL,
- *optval = NULL;
- char *attrs[2] = {NULL, NULL};
- LDAP *ld = NULL;
- LDAPMessage *res,
- *entry;
- struct berval **values;
- LDAP_TIMEVAL time = {PGLDAP_TIMEOUT, 0};
-
- if ((url = strdup(purl)) == NULL)
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
- return 3;
- }
-
- /*
- * Parse URL components, check for correctness. Basically, url has '\0'
- * placed at component boundaries and variables are pointed at each
- * component.
- */
-
- if (pg_strncasecmp(url, LDAP_URL, strlen(LDAP_URL)) != 0)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid LDAP URL \"%s\": scheme must be ldap://\n"), purl);
- free(url);
- return 3;
- }
-
- /* hostname */
- hostname = url + strlen(LDAP_URL);
- if (*hostname == '/') /* no hostname? */
- hostname = DefaultHost; /* the default */
-
- /* dn, "distinguished name" */
- p = strchr(url + strlen(LDAP_URL), '/');
- if (p == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
- {
- printfPQExpBuffer(errorMessage, libpq_gettext(
- "invalid LDAP URL \"%s\": missing distinguished name\n"), purl);
- free(url);
- return 3;
- }
- *p = '\0'; /* terminate hostname */
- dn = p + 1;
-
- /* attribute */
- if ((p = strchr(dn, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
- {
- printfPQExpBuffer(errorMessage, libpq_gettext(
- "invalid LDAP URL \"%s\": must have exactly one attribute\n"), purl);
- free(url);
- return 3;
- }
- *p = '\0';
- attrs[0] = p + 1;
-
- /* scope */
- if ((p = strchr(attrs[0], '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
- free(url);
- return 3;
- }
- *p = '\0';
- scopestr = p + 1;
-
- /* filter */
- if ((p = strchr(scopestr, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid LDAP URL \"%s\": no filter\n"), purl);
- free(url);
- return 3;
- }
- *p = '\0';
- filter = p + 1;
- if ((p = strchr(filter, '?')) != NULL)
- *p = '\0';
-
- /* port number? */
- if ((p1 = strchr(hostname, ':')) != NULL)
- {
- long lport;
-
- *p1 = '\0';
- portstr = p1 + 1;
- errno = 0;
- lport = strtol(portstr, &endptr, 10);
- if (*portstr == '\0' || *endptr != '\0' || errno || lport < 0 || lport > 65535)
- {
- printfPQExpBuffer(errorMessage, libpq_gettext(
- "invalid LDAP URL \"%s\": invalid port number\n"), purl);
- free(url);
- return 3;
- }
- port = (int) lport;
- }
-
- /* Allow only one attribute */
- if (strchr(attrs[0], ',') != NULL)
- {
- printfPQExpBuffer(errorMessage, libpq_gettext(
- "invalid LDAP URL \"%s\": must have exactly one attribute\n"), purl);
- free(url);
- return 3;
- }
-
- /* set scope */
- if (pg_strcasecmp(scopestr, "base") == 0)
- scope = LDAP_SCOPE_BASE;
- else if (pg_strcasecmp(scopestr, "one") == 0)
- scope = LDAP_SCOPE_ONELEVEL;
- else if (pg_strcasecmp(scopestr, "sub") == 0)
- scope = LDAP_SCOPE_SUBTREE;
- else
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
- free(url);
- return 3;
- }
-
- /* initialize LDAP structure */
- if ((ld = ldap_init(hostname, port)) == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("could not create LDAP structure\n"));
- free(url);
- return 3;
- }
-
- /*
- * Perform an explicit anonymous bind.
- *
- * LDAP does not require that an anonymous bind is performed explicitly,
- * but we want to distinguish between the case where LDAP bind does not
- * succeed within PGLDAP_TIMEOUT seconds (return 2 to continue parsing the
- * service control file) and the case where querying the LDAP server fails
- * (return 1 to end parsing).
- *
- * Unfortunately there is no way of setting a timeout that works for both
- * Windows and OpenLDAP.
- */
-#ifdef WIN32
- /* the nonstandard ldap_connect function performs an anonymous bind */
- if (ldap_connect(ld, &time) != LDAP_SUCCESS)
- {
- /* error or timeout in ldap_connect */
- free(url);
- ldap_unbind(ld);
- return 2;
- }
-#else /* !WIN32 */
- /* in OpenLDAP, use the LDAP_OPT_NETWORK_TIMEOUT option */
- if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
- {
- free(url);
- ldap_unbind(ld);
- return 3;
- }
-
- /* anonymous bind */
- if ((msgid = ldap_simple_bind(ld, NULL, NULL)) == -1)
- {
- /* error or network timeout */
- free(url);
- ldap_unbind(ld);
- return 2;
- }
-
- /* wait some time for the connection to succeed */
- res = NULL;
- if ((rc = ldap_result(ld, msgid, LDAP_MSG_ALL, &time, &res)) == -1 ||
- res == NULL)
- {
- /* error or timeout */
- if (res != NULL)
- ldap_msgfree(res);
- free(url);
- ldap_unbind(ld);
- return 2;
- }
- ldap_msgfree(res);
-
- /* reset timeout */
- time.tv_sec = -1;
- if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &time) != LDAP_SUCCESS)
- {
- free(url);
- ldap_unbind(ld);
- return 3;
- }
-#endif /* WIN32 */
-
- /* search */
- res = NULL;
- if ((rc = ldap_search_st(ld, dn, scope, filter, attrs, 0, &time, &res))
- != LDAP_SUCCESS)
- {
- if (res != NULL)
- ldap_msgfree(res);
- printfPQExpBuffer(errorMessage,
- libpq_gettext("lookup on LDAP server failed: %s\n"),
- ldap_err2string(rc));
- ldap_unbind(ld);
- free(url);
- return 1;
- }
-
- /* complain if there was not exactly one result */
- if ((rc = ldap_count_entries(ld, res)) != 1)
- {
- printfPQExpBuffer(errorMessage,
- rc ? libpq_gettext("more than one entry found on LDAP lookup\n")
- : libpq_gettext("no entry found on LDAP lookup\n"));
- ldap_msgfree(res);
- ldap_unbind(ld);
- free(url);
- return 1;
- }
-
- /* get entry */
- if ((entry = ldap_first_entry(ld, res)) == NULL)
- {
- /* should never happen */
- printfPQExpBuffer(errorMessage,
- libpq_gettext("no entry found on LDAP lookup\n"));
- ldap_msgfree(res);
- ldap_unbind(ld);
- free(url);
- return 1;
- }
-
- /* get values */
- if ((values = ldap_get_values_len(ld, entry, attrs[0])) == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("attribute has no values on LDAP lookup\n"));
- ldap_msgfree(res);
- ldap_unbind(ld);
- free(url);
- return 1;
- }
-
- ldap_msgfree(res);
- free(url);
-
- if (values[0] == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("attribute has no values on LDAP lookup\n"));
- ldap_value_free_len(values);
- ldap_unbind(ld);
- return 1;
- }
-
- /* concatenate values into a single string with newline terminators */
- size = 1; /* for the trailing null */
- for (i = 0; values[i] != NULL; i++)
- size += values[i]->bv_len + 1;
- if ((result = malloc(size)) == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- ldap_value_free_len(values);
- ldap_unbind(ld);
- return 3;
- }
- p = result;
- for (i = 0; values[i] != NULL; i++)
- {
- memcpy(p, values[i]->bv_val, values[i]->bv_len);
- p += values[i]->bv_len;
- *(p++) = '\n';
- }
- *p = '\0';
-
- ldap_value_free_len(values);
- ldap_unbind(ld);
-
- /* parse result string */
- oldstate = state = 0;
- for (p = result; *p != '\0'; ++p)
- {
- switch (state)
- {
- case 0: /* between entries */
- if (!ld_is_sp_tab(*p) && !ld_is_nl_cr(*p))
- {
- optname = p;
- state = 1;
- }
- break;
- case 1: /* in option name */
- if (ld_is_sp_tab(*p))
- {
- *p = '\0';
- state = 2;
- }
- else if (ld_is_nl_cr(*p))
- {
- printfPQExpBuffer(errorMessage, libpq_gettext(
- "missing \"=\" after \"%s\" in connection info string\n"),
- optname);
- free(result);
- return 3;
- }
- else if (*p == '=')
- {
- *p = '\0';
- state = 3;
- }
- break;
- case 2: /* after option name */
- if (*p == '=')
- {
- state = 3;
- }
- else if (!ld_is_sp_tab(*p))
- {
- printfPQExpBuffer(errorMessage, libpq_gettext(
- "missing \"=\" after \"%s\" in connection info string\n"),
- optname);
- free(result);
- return 3;
- }
- break;
- case 3: /* before option value */
- if (*p == '\'')
- {
- optval = p + 1;
- p1 = p + 1;
- state = 5;
- }
- else if (ld_is_nl_cr(*p))
- {
- optval = optname + strlen(optname); /* empty */
- state = 0;
- }
- else if (!ld_is_sp_tab(*p))
- {
- optval = p;
- state = 4;
- }
- break;
- case 4: /* in unquoted option value */
- if (ld_is_sp_tab(*p) || ld_is_nl_cr(*p))
- {
- *p = '\0';
- state = 0;
- }
- break;
- case 5: /* in quoted option value */
- if (*p == '\'')
- {
- *p1 = '\0';
- state = 0;
- }
- else if (*p == '\\')
- state = 6;
- else
- *(p1++) = *p;
- break;
- case 6: /* in quoted option value after escape */
- *(p1++) = *p;
- state = 5;
- break;
- }
-
- if (state == 0 && oldstate != 0)
- {
- found_keyword = false;
- for (i = 0; options[i].keyword; i++)
- {
- if (strcmp(options[i].keyword, optname) == 0)
- {
- if (options[i].val == NULL)
- {
- options[i].val = strdup(optval);
- if (!options[i].val)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- free(result);
- return 3;
- }
- }
- found_keyword = true;
- break;
- }
- }
- if (!found_keyword)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid connection option \"%s\"\n"),
- optname);
- free(result);
- return 1;
- }
- optname = NULL;
- optval = NULL;
- }
- oldstate = state;
- }
-
- free(result);
-
- if (state == 5 || state == 6)
- {
- printfPQExpBuffer(errorMessage, libpq_gettext(
- "unterminated quoted string in connection info string\n"));
- return 3;
- }
-
- return 0;
-}
-
-#endif /* USE_LDAP */
-
-#define MAXBUFSIZE 256
-
-static int
-parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
-{
- const char *service = conninfo_getval(options, "service");
- char serviceFile[MAXPGPATH];
- char *env;
- bool group_found = false;
- int status;
- struct stat stat_buf;
-
- /*
- * We have to special-case the environment variable PGSERVICE here, since
- * this is and should be called before inserting environment defaults for
- * other connection options.
- */
- if (service == NULL)
- service = getenv("PGSERVICE");
-
- if (service == NULL)
- return 0;
-
- if ((env = getenv("PGSERVICEFILE")) != NULL)
- strlcpy(serviceFile, env, sizeof(serviceFile));
- else
- {
- char homedir[MAXPGPATH];
-
- if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("could not get home directory to locate service definition file"));
- return 1;
- }
- snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
- errno = 0;
- if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
- goto next_file;
- }
-
- status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
- if (group_found || status != 0)
- return status;
-
-next_file:
-
- /*
- * This could be used by any application so we can't use the binary
- * location to find our config files.
- */
- snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
- getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
- errno = 0;
- if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
- goto last_file;
-
- status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
- if (status != 0)
- return status;
-
-last_file:
- if (!group_found)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("definition of service \"%s\" not found\n"), service);
- return 3;
- }
-
- return 0;
-}
-
-static int
-parseServiceFile(const char *serviceFile,
- const char *service,
- PQconninfoOption *options,
- PQExpBuffer errorMessage,
- bool *group_found)
-{
- int linenr = 0,
- i;
- FILE *f;
- char buf[MAXBUFSIZE],
- *line;
-
- f = fopen(serviceFile, "r");
- if (f == NULL)
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
- serviceFile);
- return 1;
- }
-
- while ((line = fgets(buf, sizeof(buf), f)) != NULL)
- {
- linenr++;
-
- if (strlen(line) >= sizeof(buf) - 1)
- {
- fclose(f);
- printfPQExpBuffer(errorMessage,
- libpq_gettext("line %d too long in service file \"%s\"\n"),
- linenr,
- serviceFile);
- return 2;
- }
-
- /* ignore EOL at end of line */
- if (strlen(line) && line[strlen(line) - 1] == '\n')
- line[strlen(line) - 1] = 0;
-
- /* ignore leading blanks */
- while (*line && isspace((unsigned char) line[0]))
- line++;
-
- /* ignore comments and empty lines */
- if (strlen(line) == 0 || line[0] == '#')
- continue;
-
- /* Check for right groupname */
- if (line[0] == '[')
- {
- if (*group_found)
- {
- /* group info already read */
- fclose(f);
- return 0;
- }
-
- if (strncmp(line + 1, service, strlen(service)) == 0 &&
- line[strlen(service) + 1] == ']')
- *group_found = true;
- else
- *group_found = false;
- }
- else
- {
- if (*group_found)
- {
- /*
- * Finally, we are in the right group and can parse the line
- */
- char *key,
- *val;
- bool found_keyword;
-
-#ifdef USE_LDAP
- if (strncmp(line, "ldap", 4) == 0)
- {
- int rc = ldapServiceLookup(line, options, errorMessage);
-
- /* if rc = 2, go on reading for fallback */
- switch (rc)
- {
- case 0:
- fclose(f);
- return 0;
- case 1:
- case 3:
- fclose(f);
- return 3;
- case 2:
- continue;
- }
- }
-#endif
-
- key = line;
- val = strchr(line, '=');
- if (val == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("syntax error in service file \"%s\", line %d\n"),
- serviceFile,
- linenr);
- fclose(f);
- return 3;
- }
- *val++ = '\0';
-
- if (strcmp(key, "service") == 0)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
- serviceFile,
- linenr);
- fclose(f);
- return 3;
- }
-
- /*
- * Set the parameter --- but don't override any previous
- * explicit setting.
- */
- found_keyword = false;
- for (i = 0; options[i].keyword; i++)
- {
- if (strcmp(options[i].keyword, key) == 0)
- {
- if (options[i].val == NULL)
- options[i].val = strdup(val);
- if (!options[i].val)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- fclose(f);
- return 3;
- }
- found_keyword = true;
- break;
- }
- }
-
- if (!found_keyword)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("syntax error in service file \"%s\", line %d\n"),
- serviceFile,
- linenr);
- fclose(f);
- return 3;
- }
- }
- }
- }
-
- fclose(f);
-
- return 0;
-}
-
-
-/*
- * PQconninfoParse
- *
- * Parse a string like PQconnectdb() would do and return the
- * resulting connection options array. NULL is returned on failure.
- * The result contains only options specified directly in the string,
- * not any possible default values.
- *
- * If errmsg isn't NULL, *errmsg is set to NULL on success, or a malloc'd
- * string on failure (use PQfreemem to free it). In out-of-memory conditions
- * both *errmsg and the result could be NULL.
- *
- * NOTE: the returned array is dynamically allocated and should
- * be freed when no longer needed via PQconninfoFree().
- */
-PQconninfoOption *
-PQconninfoParse(const char *conninfo, char **errmsg)
-{
- PQExpBufferData errorBuf;
- PQconninfoOption *connOptions;
-
- if (errmsg)
- *errmsg = NULL; /* default */
- initPQExpBuffer(&errorBuf);
- if (PQExpBufferDataBroken(errorBuf))
- return NULL; /* out of memory already :-( */
- connOptions = parse_connection_string(conninfo, &errorBuf, false);
- if (connOptions == NULL && errmsg)
- *errmsg = errorBuf.data;
- else
- termPQExpBuffer(&errorBuf);
- return connOptions;
-}
-
-/*
- * Build a working copy of the constant PQconninfoOptions array.
- */
-static PQconninfoOption *
-conninfo_init(PQExpBuffer errorMessage)
-{
- PQconninfoOption *options;
- PQconninfoOption *opt_dest;
- const internalPQconninfoOption *cur_opt;
-
- /*
- * Get enough memory for all options in PQconninfoOptions, even if some
- * end up being filtered out.
- */
- options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
- if (options == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- return NULL;
- }
- opt_dest = options;
-
- for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
- {
- /* Only copy the public part of the struct, not the full internal */
- memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
- opt_dest++;
- }
- MemSet(opt_dest, 0, sizeof(PQconninfoOption));
-
- return options;
-}
-
-/*
- * Connection string parser
- *
- * Returns a malloc'd PQconninfoOption array, if parsing is successful.
- * Otherwise, NULL is returned and an error message is left in errorMessage.
- *
- * If use_defaults is TRUE, default values are filled in (from a service file,
- * environment variables, etc).
- */
-static PQconninfoOption *
-parse_connection_string(const char *connstr, PQExpBuffer errorMessage,
- bool use_defaults)
-{
- /* Parse as URI if connection string matches URI prefix */
- if (uri_prefix_length(connstr) != 0)
- return conninfo_uri_parse(connstr, errorMessage, use_defaults);
-
- /* Parse as default otherwise */
- return conninfo_parse(connstr, errorMessage, use_defaults);
-}
-
-/*
- * Checks if connection string starts with either of the valid URI prefix
- * designators.
- *
- * Returns the URI prefix length, 0 if the string doesn't contain a URI prefix.
- *
- * XXX this is duplicated in psql/common.c.
- */
-static int
-uri_prefix_length(const char *connstr)
-{
- if (strncmp(connstr, uri_designator,
- sizeof(uri_designator) - 1) == 0)
- return sizeof(uri_designator) - 1;
-
- if (strncmp(connstr, short_uri_designator,
- sizeof(short_uri_designator) - 1) == 0)
- return sizeof(short_uri_designator) - 1;
-
- return 0;
-}
-
-/*
- * Recognized connection string either starts with a valid URI prefix or
- * contains a "=" in it.
- *
- * Must be consistent with parse_connection_string: anything for which this
- * returns true should at least look like it's parseable by that routine.
- *
- * XXX this is duplicated in psql/common.c
- */
-static bool
-recognized_connection_string(const char *connstr)
-{
- return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
-}
-
-/*
- * Subroutine for parse_connection_string
- *
- * Deal with a string containing key=value pairs.
- */
-static PQconninfoOption *
-conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
- bool use_defaults)
-{
- char *pname;
- char *pval;
- char *buf;
- char *cp;
- char *cp2;
- PQconninfoOption *options;
-
- /* Make a working copy of PQconninfoOptions */
- options = conninfo_init(errorMessage);
- if (options == NULL)
- return NULL;
-
- /* Need a modifiable copy of the input string */
- if ((buf = strdup(conninfo)) == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- PQconninfoFree(options);
- return NULL;
- }
- cp = buf;
-
- while (*cp)
- {
- /* Skip blanks before the parameter name */
- if (isspace((unsigned char) *cp))
- {
- cp++;
- continue;
- }
-
- /* Get the parameter name */
- pname = cp;
- while (*cp)
- {
- if (*cp == '=')
- break;
- if (isspace((unsigned char) *cp))
- {
- *cp++ = '\0';
- while (*cp)
- {
- if (!isspace((unsigned char) *cp))
- break;
- cp++;
- }
- break;
- }
- cp++;
- }
-
- /* Check that there is a following '=' */
- if (*cp != '=')
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
- pname);
- PQconninfoFree(options);
- free(buf);
- return NULL;
- }
- *cp++ = '\0';
-
- /* Skip blanks after the '=' */
- while (*cp)
- {
- if (!isspace((unsigned char) *cp))
- break;
- cp++;
- }
-
- /* Get the parameter value */
- pval = cp;
-
- if (*cp != '\'')
- {
- cp2 = pval;
- while (*cp)
- {
- if (isspace((unsigned char) *cp))
- {
- *cp++ = '\0';
- break;
- }
- if (*cp == '\\')
- {
- cp++;
- if (*cp != '\0')
- *cp2++ = *cp++;
- }
- else
- *cp2++ = *cp++;
- }
- *cp2 = '\0';
- }
- else
- {
- cp2 = pval;
- cp++;
- for (;;)
- {
- if (*cp == '\0')
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("unterminated quoted string in connection info string\n"));
- PQconninfoFree(options);
- free(buf);
- return NULL;
- }
- if (*cp == '\\')
- {
- cp++;
- if (*cp != '\0')
- *cp2++ = *cp++;
- continue;
- }
- if (*cp == '\'')
- {
- *cp2 = '\0';
- cp++;
- break;
- }
- *cp2++ = *cp++;
- }
- }
-
- /*
- * Now that we have the name and the value, store the record.
- */
- if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
- {
- PQconninfoFree(options);
- free(buf);
- return NULL;
- }
- }
-
- /* Done with the modifiable input string */
- free(buf);
-
- /*
- * Add in defaults if the caller wants that.
- */
- if (use_defaults)
- {
- if (!conninfo_add_defaults(options, errorMessage))
- {
- PQconninfoFree(options);
- return NULL;
- }
- }
-
- return options;
-}
-
-/*
- * Conninfo array parser routine
- *
- * If successful, a malloc'd PQconninfoOption array is returned.
- * If not successful, NULL is returned and an error message is
- * left in errorMessage.
- * Defaults are supplied (from a service file, environment variables, etc)
- * for unspecified options, but only if use_defaults is TRUE.
- *
- * If expand_dbname is non-zero, and the value passed for the first occurrence
- * of "dbname" keyword is a connection string (as indicated by
- * recognized_connection_string) then parse and process it, overriding any
- * previously processed conflicting keywords. Subsequent keywords will take
- * precedence, however. In-tree programs generally specify expand_dbname=true,
- * so command-line arguments naming a database can use a connection string.
- * Some code acquires arbitrary database names from known-literal sources like
- * PQdb(), PQconninfoParse() and pg_database.datname. When connecting to such
- * a database, in-tree code first wraps the name in a connection string.
- */
-static PQconninfoOption *
-conninfo_array_parse(const char *const * keywords, const char *const * values,
- PQExpBuffer errorMessage, bool use_defaults,
- int expand_dbname)
-{
- PQconninfoOption *options;
- PQconninfoOption *dbname_options = NULL;
- PQconninfoOption *option;
- int i = 0;
-
- /*
- * If expand_dbname is non-zero, check keyword "dbname" to see if val is
- * actually a recognized connection string.
- */
- while (expand_dbname && keywords[i])
- {
- const char *pname = keywords[i];
- const char *pvalue = values[i];
-
- /* first find "dbname" if any */
- if (strcmp(pname, "dbname") == 0 && pvalue)
- {
- /*
- * If value is a connection string, parse it, but do not use
- * defaults here -- those get picked up later. We only want to
- * override for those parameters actually passed.
- */
- if (recognized_connection_string(pvalue))
- {
- dbname_options = parse_connection_string(pvalue, errorMessage, false);
- if (dbname_options == NULL)
- return NULL;
- }
- break;
- }
- ++i;
- }
-
- /* Make a working copy of PQconninfoOptions */
- options = conninfo_init(errorMessage);
- if (options == NULL)
- {
- PQconninfoFree(dbname_options);
- return NULL;
- }
-
- /* Parse the keywords/values arrays */
- i = 0;
- while (keywords[i])
- {
- const char *pname = keywords[i];
- const char *pvalue = values[i];
-
- if (pvalue != NULL && pvalue[0] != '\0')
- {
- /* Search for the param record */
- for (option = options; option->keyword != NULL; option++)
- {
- if (strcmp(option->keyword, pname) == 0)
- break;
- }
-
- /* Check for invalid connection option */
- if (option->keyword == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid connection option \"%s\"\n"),
- pname);
- PQconninfoFree(options);
- PQconninfoFree(dbname_options);
- return NULL;
- }
-
- /*
- * If we are on the first dbname parameter, and we have a parsed
- * connection string, copy those parameters across, overriding any
- * existing previous settings.
- */
- if (strcmp(pname, "dbname") == 0 && dbname_options)
- {
- PQconninfoOption *str_option;
-
- for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
- {
- if (str_option->val != NULL)
- {
- int k;
-
- for (k = 0; options[k].keyword; k++)
- {
- if (strcmp(options[k].keyword, str_option->keyword) == 0)
- {
- if (options[k].val)
- free(options[k].val);
- options[k].val = strdup(str_option->val);
- if (!options[k].val)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- PQconninfoFree(options);
- PQconninfoFree(dbname_options);
- return NULL;
- }
- break;
- }
- }
- }
- }
-
- /*
- * Forget the parsed connection string, so that any subsequent
- * dbname parameters will not be expanded.
- */
- PQconninfoFree(dbname_options);
- dbname_options = NULL;
- }
- else
- {
- /*
- * Store the value, overriding previous settings
- */
- if (option->val)
- free(option->val);
- option->val = strdup(pvalue);
- if (!option->val)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- PQconninfoFree(options);
- PQconninfoFree(dbname_options);
- return NULL;
- }
- }
- }
- ++i;
- }
- PQconninfoFree(dbname_options);
-
- /*
- * Add in defaults if the caller wants that.
- */
- if (use_defaults)
- {
- if (!conninfo_add_defaults(options, errorMessage))
- {
- PQconninfoFree(options);
- return NULL;
- }
- }
-
- return options;
-}
-
-/*
- * Add the default values for any unspecified options to the connection
- * options array.
- *
- * Defaults are obtained from a service file, environment variables, etc.
- *
- * Returns TRUE if successful, otherwise FALSE; errorMessage, if supplied,
- * is filled in upon failure. Note that failure to locate a default value
- * is not an error condition here --- we just leave the option's value as
- * NULL.
- */
-static bool
-conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
-{
- PQconninfoOption *option;
- char *tmp;
-
- /*
- * If there's a service spec, use it to obtain any not-explicitly-given
- * parameters. Ignore error if no error message buffer is passed because
- * there is no way to pass back the failure message.
- */
- if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
- return false;
-
- /*
- * Get the fallback resources for parameters not specified in the conninfo
- * string nor the service.
- */
- for (option = options; option->keyword != NULL; option++)
- {
- if (option->val != NULL)
- continue; /* Value was in conninfo or service */
-
- /*
- * Try to get the environment variable fallback
- */
- if (option->envvar != NULL)
- {
- if ((tmp = getenv(option->envvar)) != NULL)
- {
- option->val = strdup(tmp);
- if (!option->val)
- {
- if (errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- return false;
- }
- continue;
- }
- }
-
- /*
- * Interpret the deprecated PGREQUIRESSL environment variable. Per
- * tradition, translate values starting with "1" to sslmode=require,
- * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
- * PGSSLMODE takes precedence; the opposite was true before v9.3.
- */
- if (strcmp(option->keyword, "sslmode") == 0)
- {
- const char *requiresslenv = getenv("PGREQUIRESSL");
-
- if (requiresslenv != NULL && requiresslenv[0] == '1')
- {
- option->val = strdup("require");
- if (!option->val)
- {
- if (errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- return false;
- }
- continue;
- }
- }
-
- /*
- * No environment variable specified or the variable isn't set - try
- * compiled-in default
- */
- if (option->compiled != NULL)
- {
- option->val = strdup(option->compiled);
- if (!option->val)
- {
- if (errorMessage)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- return false;
- }
- continue;
- }
-
- /*
- * Special handling for "user" option. Note that if pg_fe_getauthname
- * fails, we just leave the value as NULL; there's no need for this to
- * be an error condition if the caller provides a user name. The only
- * reason we do this now at all is so that callers of PQconndefaults
- * will see a correct default (barring error, of course).
- */
- if (strcmp(option->keyword, "user") == 0)
- {
- option->val = pg_fe_getauthname(NULL);
- continue;
- }
- }
-
- return true;
-}
-
-/*
- * Subroutine for parse_connection_string
- *
- * Deal with a URI connection string.
- */
-static PQconninfoOption *
-conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage,
- bool use_defaults)
-{
- PQconninfoOption *options;
-
- /* Make a working copy of PQconninfoOptions */
- options = conninfo_init(errorMessage);
- if (options == NULL)
- return NULL;
-
- if (!conninfo_uri_parse_options(options, uri, errorMessage))
- {
- PQconninfoFree(options);
- return NULL;
- }
-
- /*
- * Add in defaults if the caller wants that.
- */
- if (use_defaults)
- {
- if (!conninfo_add_defaults(options, errorMessage))
- {
- PQconninfoFree(options);
- return NULL;
- }
- }
-
- return options;
-}
-
-/*
- * conninfo_uri_parse_options
- * Actual URI parser.
- *
- * If successful, returns true while the options array is filled with parsed
- * options from the URI.
- * If not successful, returns false and fills errorMessage accordingly.
- *
- * Parses the connection URI string in 'uri' according to the URI syntax (RFC
- * 3986):
- *
- * postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
- *
- * where "netloc" is a hostname, an IPv4 address, or an IPv6 address surrounded
- * by literal square brackets.
- *
- * Any of the URI parts might use percent-encoding (%xy).
- */
-static bool
-conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
- PQExpBuffer errorMessage)
-{
- int prefix_len;
- char *p;
- char *buf;
- char *start;
- char prevchar = '\0';
- char *user = NULL;
- char *host = NULL;
- bool retval = false;
-
- /* need a modifiable copy of the input URI */
- buf = strdup(uri);
- if (buf == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("out of memory\n"));
- return false;
- }
- start = buf;
-
- /* Skip the URI prefix */
- prefix_len = uri_prefix_length(uri);
- if (prefix_len == 0)
- {
- /* Should never happen */
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
- uri);
- goto cleanup;
- }
- start += prefix_len;
- p = start;
-
- /* Look ahead for possible user credentials designator */
- while (*p && *p != '@' && *p != '/')
- ++p;
- if (*p == '@')
- {
- /*
- * Found username/password designator, so URI should be of the form
- * "scheme://user[:password]@[netloc]".
- */
- user = start;
-
- p = user;
- while (*p != ':' && *p != '@')
- ++p;
-
- /* Save last char and cut off at end of user name */
- prevchar = *p;
- *p = '\0';
-
- if (*user &&
- !conninfo_storeval(options, "user", user,
- errorMessage, false, true))
- goto cleanup;
-
- if (prevchar == ':')
- {
- const char *password = p + 1;
-
- while (*p != '@')
- ++p;
- *p = '\0';
-
- if (*password &&
- !conninfo_storeval(options, "password", password,
- errorMessage, false, true))
- goto cleanup;
- }
-
- /* Advance past end of parsed user name or password token */
- ++p;
- }
- else
- {
- /*
- * No username/password designator found. Reset to start of URI.
- */
- p = start;
- }
-
- /*
- * "p" has been incremented past optional URI credential information at
- * this point and now points at the "netloc" part of the URI.
- *
- * Look for IPv6 address.
- */
- if (*p == '[')
- {
- host = ++p;
- while (*p && *p != ']')
- ++p;
- if (!*p)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
- uri);
- goto cleanup;
- }
- if (p == host)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
- uri);
- goto cleanup;
- }
-
- /* Cut off the bracket and advance */
- *(p++) = '\0';
-
- /*
- * The address may be followed by a port specifier or a slash or a
- * query.
- */
- if (*p && *p != ':' && *p != '/' && *p != '?')
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
- *p, (int) (p - buf + 1), uri);
- goto cleanup;
- }
- }
- else
- {
- /* not an IPv6 address: DNS-named or IPv4 netloc */
- host = p;
-
- /*
- * Look for port specifier (colon) or end of host specifier (slash),
- * or query (question mark).
- */
- while (*p && *p != ':' && *p != '/' && *p != '?')
- ++p;
- }
-
- /* Save the hostname terminator before we null it */
- prevchar = *p;
- *p = '\0';
-
- if (*host &&
- !conninfo_storeval(options, "host", host,
- errorMessage, false, true))
- goto cleanup;
-
-
- if (prevchar == ':')
- {
- const char *port = ++p; /* advance past host terminator */
-
- while (*p && *p != '/' && *p != '?')
- ++p;
-
- prevchar = *p;
- *p = '\0';
-
- if (*port &&
- !conninfo_storeval(options, "port", port,
- errorMessage, false, true))
- goto cleanup;
- }
-
- if (prevchar && prevchar != '?')
- {
- const char *dbname = ++p; /* advance past host terminator */
-
- /* Look for query parameters */
- while (*p && *p != '?')
- ++p;
-
- prevchar = *p;
- *p = '\0';
-
- /*
- * Avoid setting dbname to an empty string, as it forces the default
- * value (username) and ignores $PGDATABASE, as opposed to not setting
- * it at all.
- */
- if (*dbname &&
- !conninfo_storeval(options, "dbname", dbname,
- errorMessage, false, true))
- goto cleanup;
- }
-
- if (prevchar)
- {
- ++p; /* advance past terminator */
-
- if (!conninfo_uri_parse_params(p, options, errorMessage))
- goto cleanup;
- }
-
- /* everything parsed okay */
- retval = true;
-
-cleanup:
- free(buf);
- return retval;
-}
-
-/*
- * Connection URI parameters parser routine
- *
- * If successful, returns true while connOptions is filled with parsed
- * parameters. Otherwise, returns false and fills errorMessage appropriately.
- *
- * Destructively modifies 'params' buffer.
- */
-static bool
-conninfo_uri_parse_params(char *params,
- PQconninfoOption *connOptions,
- PQExpBuffer errorMessage)
-{
- while (*params)
- {
- char *keyword = params;
- char *value = NULL;
- char *p = params;
- bool malloced = false;
-
- /*
- * Scan the params string for '=' and '&', marking the end of keyword
- * and value respectively.
- */
- for (;;)
- {
- if (*p == '=')
- {
- /* Was there '=' already? */
- if (value != NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
- keyword);
- return false;
- }
- /* Cut off keyword, advance to value */
- *p++ = '\0';
- value = p;
- }
- else if (*p == '&' || *p == '\0')
- {
- /*
- * If not at the end, cut off value and advance; leave p
- * pointing to start of the next parameter, if any.
- */
- if (*p != '\0')
- *p++ = '\0';
- /* Was there '=' at all? */
- if (value == NULL)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
- keyword);
- return false;
- }
- /* Got keyword and value, go process them. */
- break;
- }
- else
- ++p; /* Advance over all other bytes. */
- }
-
- keyword = conninfo_uri_decode(keyword, errorMessage);
- if (keyword == NULL)
- {
- /* conninfo_uri_decode already set an error message */
- return false;
- }
- value = conninfo_uri_decode(value, errorMessage);
- if (value == NULL)
- {
- /* conninfo_uri_decode already set an error message */
- free(keyword);
- return false;
- }
- malloced = true;
-
- /*
- * Special keyword handling for improved JDBC compatibility.
- */
- if (strcmp(keyword, "ssl") == 0 &&
- strcmp(value, "true") == 0)
- {
- free(keyword);
- free(value);
- malloced = false;
-
- keyword = "sslmode";
- value = "require";
- }
-
- /*
- * Store the value if the corresponding option exists; ignore
- * otherwise. At this point both keyword and value are not
- * URI-encoded.
- */
- if (!conninfo_storeval(connOptions, keyword, value,
- errorMessage, true, false))
- {
- /* Insert generic message if conninfo_storeval didn't give one. */
- if (errorMessage->len == 0)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid URI query parameter: \"%s\"\n"),
- keyword);
- /* And fail. */
- if (malloced)
- {
- free(keyword);
- free(value);
- }
- return false;
- }
-
- if (malloced)
- {
- free(keyword);
- free(value);
- }
-
- /* Proceed to next key=value pair, if any */
- params = p;
- }
-
- return true;
-}
-
-/*
- * Connection URI decoder routine
- *
- * If successful, returns the malloc'd decoded string.
- * If not successful, returns NULL and fills errorMessage accordingly.
- *
- * The string is decoded by replacing any percent-encoded tokens with
- * corresponding characters, while preserving any non-encoded characters. A
- * percent-encoded token is a character triplet: a percent sign, followed by a
- * pair of hexadecimal digits (0-9A-F), where lower- and upper-case letters are
- * treated identically.
- */
-static char *
-conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
-{
- char *buf;
- char *p;
- const char *q = str;
-
- buf = malloc(strlen(str) + 1);
- if (buf == NULL)
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
- return NULL;
- }
- p = buf;
-
- for (;;)
- {
- if (*q != '%')
- {
- /* copy and check for NUL terminator */
- if (!(*(p++) = *(q++)))
- break;
- }
- else
- {
- int hi;
- int lo;
- int c;
-
- ++q; /* skip the percent sign itself */
-
- /*
- * Possible EOL will be caught by the first call to
- * get_hexdigit(), so we never dereference an invalid q pointer.
- */
- if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
- str);
- free(buf);
- return NULL;
- }
-
- c = (hi << 4) | lo;
- if (c == 0)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
- str);
- free(buf);
- return NULL;
- }
- *(p++) = c;
- }
- }
-
- return buf;
-}
-
-/*
- * Convert hexadecimal digit character to its integer value.
- *
- * If successful, returns true and value is filled with digit's base 16 value.
- * If not successful, returns false.
- *
- * Lower- and upper-case letters in the range A-F are treated identically.
- */
-static bool
-get_hexdigit(char digit, int *value)
-{
- if ('0' <= digit && digit <= '9')
- *value = digit - '0';
- else if ('A' <= digit && digit <= 'F')
- *value = digit - 'A' + 10;
- else if ('a' <= digit && digit <= 'f')
- *value = digit - 'a' + 10;
- else
- return false;
-
- return true;
-}
-
-/*
- * Find an option value corresponding to the keyword in the connOptions array.
- *
- * If successful, returns a pointer to the corresponding option's value.
- * If not successful, returns NULL.
- */
-static const char *
-conninfo_getval(PQconninfoOption *connOptions,
- const char *keyword)
-{
- PQconninfoOption *option;
-
- option = conninfo_find(connOptions, keyword);
-
- return option ? option->val : NULL;
-}
-
-/*
- * Store a (new) value for an option corresponding to the keyword in
- * connOptions array.
- *
- * If uri_decode is true, the value is URI-decoded. The keyword is always
- * assumed to be non URI-encoded.
- *
- * If successful, returns a pointer to the corresponding PQconninfoOption,
- * which value is replaced with a strdup'd copy of the passed value string.
- * The existing value for the option is free'd before replacing, if any.
- *
- * If not successful, returns NULL and fills errorMessage accordingly.
- * However, if the reason of failure is an invalid keyword being passed and
- * ignoreMissing is TRUE, errorMessage will be left untouched.
- */
-static PQconninfoOption *
-conninfo_storeval(PQconninfoOption *connOptions,
- const char *keyword, const char *value,
- PQExpBuffer errorMessage, bool ignoreMissing,
- bool uri_decode)
-{
- PQconninfoOption *option;
- char *value_copy;
-
- /*
- * For backwards compatibility, requiressl=1 gets translated to
- * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
- * (which is the default for sslmode).
- */
- if (strcmp(keyword, "requiressl") == 0)
- {
- keyword = "sslmode";
- if (value[0] == '1')
- value = "require";
- else
- value = "prefer";
- }
-
- option = conninfo_find(connOptions, keyword);
- if (option == NULL)
- {
- if (!ignoreMissing)
- printfPQExpBuffer(errorMessage,
- libpq_gettext("invalid connection option \"%s\"\n"),
- keyword);
- return NULL;
- }
-
- if (uri_decode)
- {
- value_copy = conninfo_uri_decode(value, errorMessage);
- if (value_copy == NULL)
- /* conninfo_uri_decode already set an error message */
- return NULL;
- }
- else
- {
- value_copy = strdup(value);
- if (value_copy == NULL)
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
- return NULL;
- }
- }
-
- if (option->val)
- free(option->val);
- option->val = value_copy;
-
- return option;
-}
-
-/*
- * Find a PQconninfoOption option corresponding to the keyword in the
- * connOptions array.
- *
- * If successful, returns a pointer to the corresponding PQconninfoOption
- * structure.
- * If not successful, returns NULL.
- */
-static PQconninfoOption *
-conninfo_find(PQconninfoOption *connOptions, const char *keyword)
-{
- PQconninfoOption *option;
-
- for (option = connOptions; option->keyword != NULL; option++)
- {
- if (strcmp(option->keyword, keyword) == 0)
- return option;
- }
-
- return NULL;
-}
-
-
-/*
- * Return the connection options used for the connection
- */
-PQconninfoOption *
-PQconninfo(PGconn *conn)
-{
- PQExpBufferData errorBuf;
- PQconninfoOption *connOptions;
-
- if (conn == NULL)
- return NULL;
-
- /* We don't actually report any errors here, but callees want a buffer */
- initPQExpBuffer(&errorBuf);
- if (PQExpBufferDataBroken(errorBuf))
- return NULL; /* out of memory already :-( */
-
- connOptions = conninfo_init(&errorBuf);
-
- if (connOptions != NULL)
- {
- const internalPQconninfoOption *option;
-
- for (option = PQconninfoOptions; option->keyword; option++)
- {
- char **connmember;
-
- if (option->connofs < 0)
- continue;
-
- connmember = (char **) ((char *) conn + option->connofs);
-
- if (*connmember)
- conninfo_storeval(connOptions, option->keyword, *connmember,
- &errorBuf, true, false);
- }
- }
-
- termPQExpBuffer(&errorBuf);
-
- return connOptions;
-}
-
-
-void
-PQconninfoFree(PQconninfoOption *connOptions)
-{
- PQconninfoOption *option;
-
- if (connOptions == NULL)
- return;
-
- for (option = connOptions; option->keyword != NULL; option++)
- {
- if (option->val != NULL)
- free(option->val);
- }
- free(connOptions);
-}
-
-
-/* =========== accessor functions for PGconn ========= */
-char *
-PQdb(const PGconn *conn)
-{
- if (!conn)
- return NULL;
- return conn->dbName;
-}
-
-char *
-PQuser(const PGconn *conn)
-{
- if (!conn)
- return NULL;
- return conn->pguser;
-}
-
-char *
-PQpass(const PGconn *conn)
-{
- if (!conn)
- return NULL;
- return conn->pgpass;
-}
-
-char *
-PQhost(const PGconn *conn)
-{
- if (!conn)
- return NULL;
- if (conn->pghost != NULL && conn->pghost[0] != '\0')
- return conn->pghost;
- else
- {
-#ifdef HAVE_UNIX_SOCKETS
- if (conn->pgunixsocket != NULL && conn->pgunixsocket[0] != '\0')
- return conn->pgunixsocket;
- else
- return DEFAULT_PGSOCKET_DIR;
-#else
- return DefaultHost;
-#endif
- }
-}
-
-char *
-PQport(const PGconn *conn)
-{
- if (!conn)
- return NULL;
- return conn->pgport;
-}
-
-char *
-PQtty(const PGconn *conn)
-{
- if (!conn)
- return NULL;
- return conn->pgtty;
-}
-
-char *
-PQoptions(const PGconn *conn)
-{
- if (!conn)
- return NULL;
- return conn->pgoptions;
-}
-
-ConnStatusType
-PQstatus(const PGconn *conn)
-{
- if (!conn)
- return CONNECTION_BAD;
- return conn->status;
-}
-
-PGTransactionStatusType
-PQtransactionStatus(const PGconn *conn)
-{
- if (!conn || conn->status != CONNECTION_OK)
- return PQTRANS_UNKNOWN;
- if (conn->asyncStatus != PGASYNC_IDLE)
- return PQTRANS_ACTIVE;
- return conn->xactStatus;
-}
-
-const char *
-PQparameterStatus(const PGconn *conn, const char *paramName)
-{
- const pgParameterStatus *pstatus;
-
- if (!conn || !paramName)
- return NULL;
- for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
- {
- if (strcmp(pstatus->name, paramName) == 0)
- return pstatus->value;
- }
- return NULL;
-}
-
-int
-PQprotocolVersion(const PGconn *conn)
-{
- if (!conn)
- return 0;
- if (conn->status == CONNECTION_BAD)
- return 0;
- return PG_PROTOCOL_MAJOR(conn->pversion);
-}
-
-int
-PQserverVersion(const PGconn *conn)
-{
- if (!conn)
- return 0;
- if (conn->status == CONNECTION_BAD)
- return 0;
- return conn->sversion;
-}
-
-char *
-PQerrorMessage(const PGconn *conn)
-{
- if (!conn)
- return libpq_gettext("connection pointer is NULL\n");
-
- return conn->errorMessage.data;
-}
-
-/*
- * In Windows, socket values are unsigned, and an invalid socket value
- * (INVALID_SOCKET) is ~0, which equals -1 in comparisons (with no compiler
- * warning). Ideally we would return an unsigned value for PQsocket() on
- * Windows, but that would cause the function's return value to differ from
- * Unix, so we just return -1 for invalid sockets.
- * http://msdn.microsoft.com/en-us/library/windows/desktop/cc507522%28v=vs.85%29.aspx
- * http://stackoverflow.com/questions/10817252/why-is-invalid-socket-defined-as-0-in-winsock2-h-c
- */
-int
-PQsocket(const PGconn *conn)
-{
- if (!conn)
- return -1;
- return (conn->sock != PGINVALID_SOCKET) ? conn->sock : -1;
-}
-
-int
-PQbackendPID(const PGconn *conn)
-{
- if (!conn || conn->status != CONNECTION_OK)
- return 0;
- return conn->be_pid;
-}
-
-int
-PQconnectionNeedsPassword(const PGconn *conn)
-{
- if (!conn)
- return false;
- if (conn->password_needed &&
- (conn->pgpass == NULL || conn->pgpass[0] == '\0'))
- return true;
- else
- return false;
-}
-
-int
-PQconnectionUsedPassword(const PGconn *conn)
-{
- if (!conn)
- return false;
- if (conn->password_needed)
- return true;
- else
- return false;
-}
-
-int
-PQclientEncoding(const PGconn *conn)
-{
- if (!conn || conn->status != CONNECTION_OK)
- return -1;
- return conn->client_encoding;
-}
-
-int
-PQsetClientEncoding(PGconn *conn, const char *encoding)
-{
- char qbuf[128];
- static const char query[] = "set client_encoding to '%s'";
- PGresult *res;
- int status;
-
- if (!conn || conn->status != CONNECTION_OK)
- return -1;
-
- if (!encoding)
- return -1;
-
- /* Resolve special "auto" value from the locale */
- if (strcmp(encoding, "auto") == 0)
- encoding = pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true));
-
- /* check query buffer overflow */
- if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
- return -1;
-
- /* ok, now send a query */
- sprintf(qbuf, query, encoding);
- res = PQexec(conn, qbuf);
-
- if (res == NULL)
- return -1;
- if (res->resultStatus != PGRES_COMMAND_OK)
- status = -1;
- else
- {
- /*
- * In protocol 2 we have to assume the setting will stick, and adjust
- * our state immediately. In protocol 3 and up we can rely on the
- * backend to report the parameter value, and we'll change state at
- * that time.
- */
- if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
- pqSaveParameterStatus(conn, "client_encoding", encoding);
- status = 0; /* everything is ok */
- }
- PQclear(res);
- return status;
-}
-
-PGVerbosity
-PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
-{
- PGVerbosity old;
-
- if (!conn)
- return PQERRORS_DEFAULT;
- old = conn->verbosity;
- conn->verbosity = verbosity;
- return old;
-}
-
-PGContextVisibility
-PQsetErrorContextVisibility(PGconn *conn, PGContextVisibility show_context)
-{
- PGContextVisibility old;
-
- if (!conn)
- return PQSHOW_CONTEXT_ERRORS;
- old = conn->show_context;
- conn->show_context = show_context;
- return old;
-}
-
-void
-PQtrace(PGconn *conn, FILE *debug_port)
-{
- if (conn == NULL)
- return;
- PQuntrace(conn);
- conn->Pfdebug = debug_port;
-}
-
-void
-PQuntrace(PGconn *conn)
-{
- if (conn == NULL)
- return;
- if (conn->Pfdebug)
- {
- fflush(conn->Pfdebug);
- conn->Pfdebug = NULL;
- }
-}
-
-PQnoticeReceiver
-PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
-{
- PQnoticeReceiver old;
-
- if (conn == NULL)
- return NULL;
-
- old = conn->noticeHooks.noticeRec;
- if (proc)
- {
- conn->noticeHooks.noticeRec = proc;
- conn->noticeHooks.noticeRecArg = arg;
- }
- return old;
-}
-
-PQnoticeProcessor
-PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
-{
- PQnoticeProcessor old;
-
- if (conn == NULL)
- return NULL;
-
- old = conn->noticeHooks.noticeProc;
- if (proc)
- {
- conn->noticeHooks.noticeProc = proc;
- conn->noticeHooks.noticeProcArg = arg;
- }
- return old;
-}
-
-/*
- * The default notice message receiver just gets the standard notice text
- * and sends it to the notice processor. This two-level setup exists
- * mostly for backwards compatibility; perhaps we should deprecate use of
- * PQsetNoticeProcessor?
- */
-static void
-defaultNoticeReceiver(void *arg, const PGresult *res)
-{
- (void) arg; /* not used */
- if (res->noticeHooks.noticeProc != NULL)
- (*res->noticeHooks.noticeProc) (res->noticeHooks.noticeProcArg,
- PQresultErrorMessage(res));
-}
-
-/*
- * The default notice message processor just prints the
- * message on stderr. Applications can override this if they
- * want the messages to go elsewhere (a window, for example).
- * Note that simply discarding notices is probably a bad idea.
- */
-static void
-defaultNoticeProcessor(void *arg, const char *message)
-{
- (void) arg; /* not used */
- /* Note: we expect the supplied string to end with a newline already. */
- fprintf(stderr, "%s", message);
-}
-
-/*
- * returns a pointer to the next token or NULL if the current
- * token doesn't match
- */
-static char *
-pwdfMatchesString(char *buf, char *token)
-{
- char *tbuf,
- *ttok;
- bool bslash = false;
-
- if (buf == NULL || token == NULL)
- return NULL;
- tbuf = buf;
- ttok = token;
- if (tbuf[0] == '*' && tbuf[1] == ':')
- return tbuf + 2;
- while (*tbuf != 0)
- {
- if (*tbuf == '\\' && !bslash)
- {
- tbuf++;
- bslash = true;
- }
- if (*tbuf == ':' && *ttok == 0 && !bslash)
- return tbuf + 1;
- bslash = false;
- if (*ttok == 0)
- return NULL;
- if (*tbuf == *ttok)
- {
- tbuf++;
- ttok++;
- }
- else
- return NULL;
- }
- return NULL;
-}
-
-/* Get a password from the password file. Return value is malloc'd. */
-static char *
-PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
-{
- FILE *fp;
- char pgpassfile[MAXPGPATH];
- struct stat stat_buf;
-
-#define LINELEN NAMEDATALEN*5
- char buf[LINELEN];
-
- if (dbname == NULL || strlen(dbname) == 0)
- return NULL;
-
- if (username == NULL || strlen(username) == 0)
- return NULL;
-
- /* 'localhost' matches pghost of '' or the default socket directory */
- if (hostname == NULL)
- hostname = DefaultHost;
- else if (is_absolute_path(hostname))
-
- /*
- * We should probably use canonicalize_path(), but then we have to
- * bring path.c into libpq, and it doesn't seem worth it.
- */
- if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
- hostname = DefaultHost;
-
- if (port == NULL)
- port = DEF_PGPORT_STR;
-
- if (!getPgPassFilename(pgpassfile))
- return NULL;
-
- /* If password file cannot be opened, ignore it. */
- if (stat(pgpassfile, &stat_buf) != 0)
- return NULL;
-
-#ifndef WIN32
- if (!S_ISREG(stat_buf.st_mode))
- {
- fprintf(stderr,
- libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
- pgpassfile);
- return NULL;
- }
-
- /* If password file is insecure, alert the user and ignore it. */
- if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
- {
- fprintf(stderr,
- libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
- pgpassfile);
- return NULL;
- }
-#else
-
- /*
- * On Win32, the directory is protected, so we don't have to check the
- * file.
- */
-#endif
-
- fp = fopen(pgpassfile, "r");
- if (fp == NULL)
- return NULL;
-
- while (!feof(fp) && !ferror(fp))
- {
- char *t = buf,
- *ret,
- *p1,
- *p2;
- int len;
-
- if (fgets(buf, sizeof(buf), fp) == NULL)
- break;
-
- len = strlen(buf);
-
- /* Remove trailing newline */
- if (len > 0 && buf[len - 1] == '\n')
- {
- buf[--len] = '\0';
- /* Handle DOS-style line endings, too, even when not on Windows */
- if (len > 0 && buf[len - 1] == '\r')
- buf[--len] = '\0';
- }
-
- if (len == 0)
- continue;
-
- if ((t = pwdfMatchesString(t, hostname)) == NULL ||
- (t = pwdfMatchesString(t, port)) == NULL ||
- (t = pwdfMatchesString(t, dbname)) == NULL ||
- (t = pwdfMatchesString(t, username)) == NULL)
- continue;
-
- /* Found a match. */
- ret = strdup(t);
- fclose(fp);
-
- if (!ret)
- {
- /* Out of memory. XXX: an error message would be nice. */
- return NULL;
- }
-
- /* De-escape password. */
- for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
- {
- if (*p1 == '\\' && p1[1] != '\0')
- ++p1;
- *p2 = *p1;
- }
- *p2 = '\0';
-
- return ret;
- }
-
- fclose(fp);
- return NULL;
-
-#undef LINELEN
-}
-
-
-static bool
-getPgPassFilename(char *pgpassfile)
-{
- char *passfile_env;
-
- if ((passfile_env = getenv("PGPASSFILE")) != NULL)
- /* use the literal path from the environment, if set */
- strlcpy(pgpassfile, passfile_env, MAXPGPATH);
- else
- {
- char homedir[MAXPGPATH];
-
- if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
- return false;
- snprintf(pgpassfile, MAXPGPATH, "%s/%s", homedir, PGPASSFILE);
- }
- return true;
-}
-
-/*
- * If the connection failed, we should mention if
- * we got the password from .pgpass in case that
- * password is wrong.
- */
-static void
-dot_pg_pass_warning(PGconn *conn)
-{
- /* If it was 'invalid authorization', add .pgpass mention */
- /* only works with >= 9.0 servers */
- if (conn->dot_pgpass_used && conn->password_needed && conn->result &&
- strcmp(PQresultErrorField(conn->result, PG_DIAG_SQLSTATE),
- ERRCODE_INVALID_PASSWORD) == 0)
- {
- char pgpassfile[MAXPGPATH];
-
- if (!getPgPassFilename(pgpassfile))
- return;
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("password retrieved from file \"%s\"\n"),
- pgpassfile);
- }
-}
-
-
-/*
- * Obtain user's home directory, return in given buffer
- *
- * On Unix, this actually returns the user's home directory. On Windows
- * it returns the PostgreSQL-specific application data folder.
- *
- * This is essentially the same as get_home_path(), but we don't use that
- * because we don't want to pull path.c into libpq (it pollutes application
- * namespace)
- */
-bool
-pqGetHomeDirectory(char *buf, int bufsize)
-{
-#ifndef WIN32
- char pwdbuf[BUFSIZ];
- struct passwd pwdstr;
- struct passwd *pwd = NULL;
-
- (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
- if (pwd == NULL)
- return false;
- strlcpy(buf, pwd->pw_dir, bufsize);
- return true;
-#else
- char tmppath[MAX_PATH];
-
- ZeroMemory(tmppath, sizeof(tmppath));
- if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
- return false;
- snprintf(buf, bufsize, "%s/postgresql", tmppath);
- return true;
-#endif
-}
-
-/*
- * To keep the API consistent, the locking stubs are always provided, even
- * if they are not required.
- */
-
-static void
-default_threadlock(int acquire)
-{
-#ifdef ENABLE_THREAD_SAFETY
-#ifndef WIN32
- static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
-#else
- static pthread_mutex_t singlethread_lock = NULL;
- static long mutex_initlock = 0;
-
- if (singlethread_lock == NULL)
- {
- while (InterlockedExchange(&mutex_initlock, 1) == 1)
- /* loop, another thread own the lock */ ;
- if (singlethread_lock == NULL)
- {
- if (pthread_mutex_init(&singlethread_lock, NULL))
- PGTHREAD_ERROR("failed to initialize mutex");
- }
- InterlockedExchange(&mutex_initlock, 0);
- }
-#endif
- if (acquire)
- {
- if (pthread_mutex_lock(&singlethread_lock))
- PGTHREAD_ERROR("failed to lock mutex");
- }
- else
- {
- if (pthread_mutex_unlock(&singlethread_lock))
- PGTHREAD_ERROR("failed to unlock mutex");
- }
-#endif
-}
-
-pgthreadlock_t
-PQregisterThreadLock(pgthreadlock_t newhandler)
-{
- pgthreadlock_t prev = pg_g_threadlock;
-
- if (newhandler)
- pg_g_threadlock = newhandler;
- else
- pg_g_threadlock = default_threadlock;
-
- return prev;
-}
diff --git a/libpq/fe-exec.c b/libpq/fe-exec.c
deleted file mode 100644
index 87ff565..0000000
--- a/libpq/fe-exec.c
+++ /dev/null
@@ -1,3764 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-exec.c
- * functions related to sending a query down to the backend
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-exec.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <fcntl.h>
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-
-#include "mb/pg_wchar.h"
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <unistd.h>
-#endif
-
-/* keep this in same order as ExecStatusType in libpq-fe.h */
-char *const pgresStatus[] = {
- "PGRES_EMPTY_QUERY",
- "PGRES_COMMAND_OK",
- "PGRES_TUPLES_OK",
- "PGRES_COPY_OUT",
- "PGRES_COPY_IN",
- "PGRES_BAD_RESPONSE",
- "PGRES_NONFATAL_ERROR",
- "PGRES_FATAL_ERROR",
- "PGRES_COPY_BOTH",
- "PGRES_SINGLE_TUPLE"
-};
-
-/*
- * static state needed by PQescapeString and PQescapeBytea; initialize to
- * values that result in backward-compatible behavior
- */
-static int static_client_encoding = PG_SQL_ASCII;
-static bool static_std_strings = false;
-
-
-static PGEvent *dupEvents(PGEvent *events, int count);
-static bool pqAddTuple(PGresult *res, PGresAttValue *tup);
-static bool PQsendQueryStart(PGconn *conn);
-static int PQsendQueryGuts(PGconn *conn,
- const char *command,
- const char *stmtName,
- int nParams,
- const Oid *paramTypes,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat);
-static void parseInput(PGconn *conn);
-static PGresult *getCopyResult(PGconn *conn, ExecStatusType copytype);
-static bool PQexecStart(PGconn *conn);
-static PGresult *PQexecFinish(PGconn *conn);
-static int PQsendDescribe(PGconn *conn, char desc_type,
- const char *desc_target);
-static int check_field_number(const PGresult *res, int field_num);
-
-
-/* ----------------
- * Space management for PGresult.
- *
- * Formerly, libpq did a separate malloc() for each field of each tuple
- * returned by a query. This was remarkably expensive --- malloc/free
- * consumed a sizable part of the application's runtime. And there is
- * no real need to keep track of the fields separately, since they will
- * all be freed together when the PGresult is released. So now, we grab
- * large blocks of storage from malloc and allocate space for query data
- * within these blocks, using a trivially simple allocator. This reduces
- * the number of malloc/free calls dramatically, and it also avoids
- * fragmentation of the malloc storage arena.
- * The PGresult structure itself is still malloc'd separately. We could
- * combine it with the first allocation block, but that would waste space
- * for the common case that no extra storage is actually needed (that is,
- * the SQL command did not return tuples).
- *
- * We also malloc the top-level array of tuple pointers separately, because
- * we need to be able to enlarge it via realloc, and our trivial space
- * allocator doesn't handle that effectively. (Too bad the FE/BE protocol
- * doesn't tell us up front how many tuples will be returned.)
- * All other subsidiary storage for a PGresult is kept in PGresult_data blocks
- * of size PGRESULT_DATA_BLOCKSIZE. The overhead at the start of each block
- * is just a link to the next one, if any. Free-space management info is
- * kept in the owning PGresult.
- * A query returning a small amount of data will thus require three malloc
- * calls: one for the PGresult, one for the tuples pointer array, and one
- * PGresult_data block.
- *
- * Only the most recently allocated PGresult_data block is a candidate to
- * have more stuff added to it --- any extra space left over in older blocks
- * is wasted. We could be smarter and search the whole chain, but the point
- * here is to be simple and fast. Typical applications do not keep a PGresult
- * around very long anyway, so some wasted space within one is not a problem.
- *
- * Tuning constants for the space allocator are:
- * PGRESULT_DATA_BLOCKSIZE: size of a standard allocation block, in bytes
- * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data
- * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate
- * blocks, instead of being crammed into a regular allocation block.
- * Requirements for correct function are:
- * PGRESULT_ALIGN_BOUNDARY must be a multiple of the alignment requirements
- * of all machine data types. (Currently this is set from configure
- * tests, so it should be OK automatically.)
- * PGRESULT_SEP_ALLOC_THRESHOLD + PGRESULT_BLOCK_OVERHEAD <=
- * PGRESULT_DATA_BLOCKSIZE
- * pqResultAlloc assumes an object smaller than the threshold will fit
- * in a new block.
- * The amount of space wasted at the end of a block could be as much as
- * PGRESULT_SEP_ALLOC_THRESHOLD, so it doesn't pay to make that too large.
- * ----------------
- */
-
-#define PGRESULT_DATA_BLOCKSIZE 2048
-#define PGRESULT_ALIGN_BOUNDARY MAXIMUM_ALIGNOF /* from configure */
-#define PGRESULT_BLOCK_OVERHEAD Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)
-#define PGRESULT_SEP_ALLOC_THRESHOLD (PGRESULT_DATA_BLOCKSIZE / 2)
-
-
-/*
- * PQmakeEmptyPGresult
- * returns a newly allocated, initialized PGresult with given status.
- * If conn is not NULL and status indicates an error, the conn's
- * errorMessage is copied. Also, any PGEvents are copied from the conn.
- */
-PGresult *
-PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
-{
- PGresult *result;
-
- result = (PGresult *) malloc(sizeof(PGresult));
- if (!result)
- return NULL;
-
- result->ntups = 0;
- result->numAttributes = 0;
- result->attDescs = NULL;
- result->tuples = NULL;
- result->tupArrSize = 0;
- result->numParameters = 0;
- result->paramDescs = NULL;
- result->resultStatus = status;
- result->cmdStatus[0] = '\0';
- result->binary = 0;
- result->events = NULL;
- result->nEvents = 0;
- result->errMsg = NULL;
- result->errFields = NULL;
- result->errQuery = NULL;
- result->null_field[0] = '\0';
- result->curBlock = NULL;
- result->curOffset = 0;
- result->spaceLeft = 0;
-
- if (conn)
- {
- /* copy connection data we might need for operations on PGresult */
- result->noticeHooks = conn->noticeHooks;
- result->client_encoding = conn->client_encoding;
-
- /* consider copying conn's errorMessage */
- switch (status)
- {
- case PGRES_EMPTY_QUERY:
- case PGRES_COMMAND_OK:
- case PGRES_TUPLES_OK:
- case PGRES_COPY_OUT:
- case PGRES_COPY_IN:
- case PGRES_COPY_BOTH:
- case PGRES_SINGLE_TUPLE:
- /* non-error cases */
- break;
- default:
- pqSetResultError(result, conn->errorMessage.data);
- break;
- }
-
- /* copy events last; result must be valid if we need to PQclear */
- if (conn->nEvents > 0)
- {
- result->events = dupEvents(conn->events, conn->nEvents);
- if (!result->events)
- {
- PQclear(result);
- return NULL;
- }
- result->nEvents = conn->nEvents;
- }
- }
- else
- {
- /* defaults... */
- result->noticeHooks.noticeRec = NULL;
- result->noticeHooks.noticeRecArg = NULL;
- result->noticeHooks.noticeProc = NULL;
- result->noticeHooks.noticeProcArg = NULL;
- result->client_encoding = PG_SQL_ASCII;
- }
-
- return result;
-}
-
-/*
- * PQsetResultAttrs
- *
- * Set the attributes for a given result. This function fails if there are
- * already attributes contained in the provided result. The call is
- * ignored if numAttributes is zero or attDescs is NULL. If the
- * function fails, it returns zero. If the function succeeds, it
- * returns a non-zero value.
- */
-int
-PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs)
-{
- int i;
-
- /* If attrs already exist, they cannot be overwritten. */
- if (!res || res->numAttributes > 0)
- return FALSE;
-
- /* ignore no-op request */
- if (numAttributes <= 0 || !attDescs)
- return TRUE;
-
- res->attDescs = (PGresAttDesc *)
- PQresultAlloc(res, numAttributes * sizeof(PGresAttDesc));
-
- if (!res->attDescs)
- return FALSE;
-
- res->numAttributes = numAttributes;
- memcpy(res->attDescs, attDescs, numAttributes * sizeof(PGresAttDesc));
-
- /* deep-copy the attribute names, and determine format */
- res->binary = 1;
- for (i = 0; i < res->numAttributes; i++)
- {
- if (res->attDescs[i].name)
- res->attDescs[i].name = pqResultStrdup(res, res->attDescs[i].name);
- else
- res->attDescs[i].name = res->null_field;
-
- if (!res->attDescs[i].name)
- return FALSE;
-
- if (res->attDescs[i].format == 0)
- res->binary = 0;
- }
-
- return TRUE;
-}
-
-/*
- * PQcopyResult
- *
- * Returns a deep copy of the provided 'src' PGresult, which cannot be NULL.
- * The 'flags' argument controls which portions of the result will or will
- * NOT be copied. The created result is always put into the
- * PGRES_TUPLES_OK status. The source result error message is not copied,
- * although cmdStatus is.
- *
- * To set custom attributes, use PQsetResultAttrs. That function requires
- * that there are no attrs contained in the result, so to use that
- * function you cannot use the PG_COPYRES_ATTRS or PG_COPYRES_TUPLES
- * options with this function.
- *
- * Options:
- * PG_COPYRES_ATTRS - Copy the source result's attributes
- *
- * PG_COPYRES_TUPLES - Copy the source result's tuples. This implies
- * copying the attrs, seeing how the attrs are needed by the tuples.
- *
- * PG_COPYRES_EVENTS - Copy the source result's events.
- *
- * PG_COPYRES_NOTICEHOOKS - Copy the source result's notice hooks.
- */
-PGresult *
-PQcopyResult(const PGresult *src, int flags)
-{
- PGresult *dest;
- int i;
-
- if (!src)
- return NULL;
-
- dest = PQmakeEmptyPGresult(NULL, PGRES_TUPLES_OK);
- if (!dest)
- return NULL;
-
- /* Always copy these over. Is cmdStatus really useful here? */
- dest->client_encoding = src->client_encoding;
- strcpy(dest->cmdStatus, src->cmdStatus);
-
- /* Wants attrs? */
- if (flags & (PG_COPYRES_ATTRS | PG_COPYRES_TUPLES))
- {
- if (!PQsetResultAttrs(dest, src->numAttributes, src->attDescs))
- {
- PQclear(dest);
- return NULL;
- }
- }
-
- /* Wants to copy tuples? */
- if (flags & PG_COPYRES_TUPLES)
- {
- int tup,
- field;
-
- for (tup = 0; tup < src->ntups; tup++)
- {
- for (field = 0; field < src->numAttributes; field++)
- {
- if (!PQsetvalue(dest, tup, field,
- src->tuples[tup][field].value,
- src->tuples[tup][field].len))
- {
- PQclear(dest);
- return NULL;
- }
- }
- }
- }
-
- /* Wants to copy notice hooks? */
- if (flags & PG_COPYRES_NOTICEHOOKS)
- dest->noticeHooks = src->noticeHooks;
-
- /* Wants to copy PGEvents? */
- if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0)
- {
- dest->events = dupEvents(src->events, src->nEvents);
- if (!dest->events)
- {
- PQclear(dest);
- return NULL;
- }
- dest->nEvents = src->nEvents;
- }
-
- /* Okay, trigger PGEVT_RESULTCOPY event */
- for (i = 0; i < dest->nEvents; i++)
- {
- if (src->events[i].resultInitialized)
- {
- PGEventResultCopy evt;
-
- evt.src = src;
- evt.dest = dest;
- if (!dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
- dest->events[i].passThrough))
- {
- PQclear(dest);
- return NULL;
- }
- dest->events[i].resultInitialized = TRUE;
- }
- }
-
- return dest;
-}
-
-/*
- * Copy an array of PGEvents (with no extra space for more).
- * Does not duplicate the event instance data, sets this to NULL.
- * Also, the resultInitialized flags are all cleared.
- */
-static PGEvent *
-dupEvents(PGEvent *events, int count)
-{
- PGEvent *newEvents;
- int i;
-
- if (!events || count <= 0)
- return NULL;
-
- newEvents = (PGEvent *) malloc(count * sizeof(PGEvent));
- if (!newEvents)
- return NULL;
-
- for (i = 0; i < count; i++)
- {
- newEvents[i].proc = events[i].proc;
- newEvents[i].passThrough = events[i].passThrough;
- newEvents[i].data = NULL;
- newEvents[i].resultInitialized = FALSE;
- newEvents[i].name = strdup(events[i].name);
- if (!newEvents[i].name)
- {
- while (--i >= 0)
- free(newEvents[i].name);
- free(newEvents);
- return NULL;
- }
- }
-
- return newEvents;
-}
-
-
-/*
- * Sets the value for a tuple field. The tup_num must be less than or
- * equal to PQntuples(res). If it is equal, a new tuple is created and
- * added to the result.
- * Returns a non-zero value for success and zero for failure.
- */
-int
-PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len)
-{
- PGresAttValue *attval;
-
- if (!check_field_number(res, field_num))
- return FALSE;
-
- /* Invalid tup_num, must be <= ntups */
- if (tup_num < 0 || tup_num > res->ntups)
- return FALSE;
-
- /* need to allocate a new tuple? */
- if (tup_num == res->ntups)
- {
- PGresAttValue *tup;
- int i;
-
- tup = (PGresAttValue *)
- pqResultAlloc(res, res->numAttributes * sizeof(PGresAttValue),
- TRUE);
-
- if (!tup)
- return FALSE;
-
- /* initialize each column to NULL */
- for (i = 0; i < res->numAttributes; i++)
- {
- tup[i].len = NULL_LEN;
- tup[i].value = res->null_field;
- }
-
- /* add it to the array */
- if (!pqAddTuple(res, tup))
- return FALSE;
- }
-
- attval = &res->tuples[tup_num][field_num];
-
- /* treat either NULL_LEN or NULL value pointer as a NULL field */
- if (len == NULL_LEN || value == NULL)
- {
- attval->len = NULL_LEN;
- attval->value = res->null_field;
- }
- else if (len <= 0)
- {
- attval->len = 0;
- attval->value = res->null_field;
- }
- else
- {
- attval->value = (char *) pqResultAlloc(res, len + 1, TRUE);
- if (!attval->value)
- return FALSE;
- attval->len = len;
- memcpy(attval->value, value, len);
- attval->value[len] = '\0';
- }
-
- return TRUE;
-}
-
-/*
- * pqResultAlloc - exported routine to allocate local storage in a PGresult.
- *
- * We force all such allocations to be maxaligned, since we don't know
- * whether the value might be binary.
- */
-void *
-PQresultAlloc(PGresult *res, size_t nBytes)
-{
- return pqResultAlloc(res, nBytes, TRUE);
-}
-
-/*
- * pqResultAlloc -
- * Allocate subsidiary storage for a PGresult.
- *
- * nBytes is the amount of space needed for the object.
- * If isBinary is true, we assume that we need to align the object on
- * a machine allocation boundary.
- * If isBinary is false, we assume the object is a char string and can
- * be allocated on any byte boundary.
- */
-void *
-pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
-{
- char *space;
- PGresult_data *block;
-
- if (!res)
- return NULL;
-
- if (nBytes <= 0)
- return res->null_field;
-
- /*
- * If alignment is needed, round up the current position to an alignment
- * boundary.
- */
- if (isBinary)
- {
- int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
-
- if (offset)
- {
- res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
- res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
- }
- }
-
- /* If there's enough space in the current block, no problem. */
- if (nBytes <= (size_t) res->spaceLeft)
- {
- space = res->curBlock->space + res->curOffset;
- res->curOffset += nBytes;
- res->spaceLeft -= nBytes;
- return space;
- }
-
- /*
- * If the requested object is very large, give it its own block; this
- * avoids wasting what might be most of the current block to start a new
- * block. (We'd have to special-case requests bigger than the block size
- * anyway.) The object is always given binary alignment in this case.
- */
- if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
- {
- block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
- if (!block)
- return NULL;
- space = block->space + PGRESULT_BLOCK_OVERHEAD;
- if (res->curBlock)
- {
- /*
- * Tuck special block below the active block, so that we don't
- * have to waste the free space in the active block.
- */
- block->next = res->curBlock->next;
- res->curBlock->next = block;
- }
- else
- {
- /* Must set up the new block as the first active block. */
- block->next = NULL;
- res->curBlock = block;
- res->spaceLeft = 0; /* be sure it's marked full */
- }
- return space;
- }
-
- /* Otherwise, start a new block. */
- block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
- if (!block)
- return NULL;
- block->next = res->curBlock;
- res->curBlock = block;
- if (isBinary)
- {
- /* object needs full alignment */
- res->curOffset = PGRESULT_BLOCK_OVERHEAD;
- res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
- }
- else
- {
- /* we can cram it right after the overhead pointer */
- res->curOffset = sizeof(PGresult_data);
- res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
- }
-
- space = block->space + res->curOffset;
- res->curOffset += nBytes;
- res->spaceLeft -= nBytes;
- return space;
-}
-
-/*
- * pqResultStrdup -
- * Like strdup, but the space is subsidiary PGresult space.
- */
-char *
-pqResultStrdup(PGresult *res, const char *str)
-{
- char *space = (char *) pqResultAlloc(res, strlen(str) + 1, FALSE);
-
- if (space)
- strcpy(space, str);
- return space;
-}
-
-/*
- * pqSetResultError -
- * assign a new error message to a PGresult
- */
-void
-pqSetResultError(PGresult *res, const char *msg)
-{
- if (!res)
- return;
- if (msg && *msg)
- res->errMsg = pqResultStrdup(res, msg);
- else
- res->errMsg = NULL;
-}
-
-/*
- * pqCatenateResultError -
- * concatenate a new error message to the one already in a PGresult
- */
-void
-pqCatenateResultError(PGresult *res, const char *msg)
-{
- PQExpBufferData errorBuf;
-
- if (!res || !msg)
- return;
- initPQExpBuffer(&errorBuf);
- if (res->errMsg)
- appendPQExpBufferStr(&errorBuf, res->errMsg);
- appendPQExpBufferStr(&errorBuf, msg);
- pqSetResultError(res, errorBuf.data);
- termPQExpBuffer(&errorBuf);
-}
-
-/*
- * PQclear -
- * free's the memory associated with a PGresult
- */
-void
-PQclear(PGresult *res)
-{
- PGresult_data *block;
- int i;
-
- if (!res)
- return;
-
- for (i = 0; i < res->nEvents; i++)
- {
- /* only send DESTROY to successfully-initialized event procs */
- if (res->events[i].resultInitialized)
- {
- PGEventResultDestroy evt;
-
- evt.result = res;
- (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt,
- res->events[i].passThrough);
- }
- free(res->events[i].name);
- }
-
- if (res->events)
- free(res->events);
-
- /* Free all the subsidiary blocks */
- while ((block = res->curBlock) != NULL)
- {
- res->curBlock = block->next;
- free(block);
- }
-
- /* Free the top-level tuple pointer array */
- if (res->tuples)
- free(res->tuples);
-
- /* zero out the pointer fields to catch programming errors */
- res->attDescs = NULL;
- res->tuples = NULL;
- res->paramDescs = NULL;
- res->errFields = NULL;
- res->events = NULL;
- res->nEvents = 0;
- /* res->curBlock was zeroed out earlier */
-
- /* Free the PGresult structure itself */
- free(res);
-}
-
-/*
- * Handy subroutine to deallocate any partially constructed async result.
- *
- * Any "next" result gets cleared too.
- */
-void
-pqClearAsyncResult(PGconn *conn)
-{
- if (conn->result)
- PQclear(conn->result);
- conn->result = NULL;
- if (conn->next_result)
- PQclear(conn->next_result);
- conn->next_result = NULL;
-}
-
-/*
- * This subroutine deletes any existing async result, sets conn->result
- * to a PGresult with status PGRES_FATAL_ERROR, and stores the current
- * contents of conn->errorMessage into that result. It differs from a
- * plain call on PQmakeEmptyPGresult() in that if there is already an
- * async result with status PGRES_FATAL_ERROR, the current error message
- * is APPENDED to the old error message instead of replacing it. This
- * behavior lets us report multiple error conditions properly, if necessary.
- * (An example where this is needed is when the backend sends an 'E' message
- * and immediately closes the connection --- we want to report both the
- * backend error and the connection closure error.)
- */
-void
-pqSaveErrorResult(PGconn *conn)
-{
- /*
- * If no old async result, just let PQmakeEmptyPGresult make one. Likewise
- * if old result is not an error message.
- */
- if (conn->result == NULL ||
- conn->result->resultStatus != PGRES_FATAL_ERROR ||
- conn->result->errMsg == NULL)
- {
- pqClearAsyncResult(conn);
- conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
- }
- else
- {
- /* Else, concatenate error message to existing async result. */
- pqCatenateResultError(conn->result, conn->errorMessage.data);
- }
-}
-
-/*
- * This subroutine prepares an async result object for return to the caller.
- * If there is not already an async result object, build an error object
- * using whatever is in conn->errorMessage. In any case, clear the async
- * result storage and make sure PQerrorMessage will agree with the result's
- * error string.
- */
-PGresult *
-pqPrepareAsyncResult(PGconn *conn)
-{
- PGresult *res;
-
- /*
- * conn->result is the PGresult to return. If it is NULL (which probably
- * shouldn't happen) we assume there is an appropriate error message in
- * conn->errorMessage.
- */
- res = conn->result;
- if (!res)
- res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
- else
- {
- /*
- * Make sure PQerrorMessage agrees with result; it could be different
- * if we have concatenated messages.
- */
- resetPQExpBuffer(&conn->errorMessage);
- appendPQExpBufferStr(&conn->errorMessage,
- PQresultErrorMessage(res));
- }
-
- /*
- * Replace conn->result with next_result, if any. In the normal case
- * there isn't a next result and we're just dropping ownership of the
- * current result. In single-row mode this restores the situation to what
- * it was before we created the current single-row result.
- */
- conn->result = conn->next_result;
- conn->next_result = NULL;
-
- return res;
-}
-
-/*
- * pqInternalNotice - produce an internally-generated notice message
- *
- * A format string and optional arguments can be passed. Note that we do
- * libpq_gettext() here, so callers need not.
- *
- * The supplied text is taken as primary message (ie., it should not include
- * a trailing newline, and should not be more than one line).
- */
-void
-pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
-{
- char msgBuf[1024];
- va_list args;
- PGresult *res;
-
- if (hooks->noticeRec == NULL)
- return; /* nobody home to receive notice? */
-
- /* Format the message */
- va_start(args, fmt);
- vsnprintf(msgBuf, sizeof(msgBuf), libpq_gettext(fmt), args);
- va_end(args);
- msgBuf[sizeof(msgBuf) - 1] = '\0'; /* make real sure it's terminated */
-
- /* Make a PGresult to pass to the notice receiver */
- res = PQmakeEmptyPGresult(NULL, PGRES_NONFATAL_ERROR);
- if (!res)
- return;
- res->noticeHooks = *hooks;
-
- /*
- * Set up fields of notice.
- */
- pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, msgBuf);
- pqSaveMessageField(res, PG_DIAG_SEVERITY, libpq_gettext("NOTICE"));
- pqSaveMessageField(res, PG_DIAG_SEVERITY_NONLOCALIZED, "NOTICE");
- /* XXX should provide a SQLSTATE too? */
-
- /*
- * Result text is always just the primary message + newline. If we can't
- * allocate it, don't bother invoking the receiver.
- */
- res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, FALSE);
- if (res->errMsg)
- {
- sprintf(res->errMsg, "%s\n", msgBuf);
-
- /*
- * Pass to receiver, then free it.
- */
- (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
- }
- PQclear(res);
-}
-
-/*
- * pqAddTuple
- * add a row pointer to the PGresult structure, growing it if necessary
- * Returns TRUE if OK, FALSE if not enough memory to add the row
- */
-static bool
-pqAddTuple(PGresult *res, PGresAttValue *tup)
-{
- if (res->ntups >= res->tupArrSize)
- {
- /*
- * Try to grow the array.
- *
- * We can use realloc because shallow copying of the structure is
- * okay. Note that the first time through, res->tuples is NULL. While
- * ANSI says that realloc() should act like malloc() in that case,
- * some old C libraries (like SunOS 4.1.x) coredump instead. On
- * failure realloc is supposed to return NULL without damaging the
- * existing allocation. Note that the positions beyond res->ntups are
- * garbage, not necessarily NULL.
- */
- int newSize = (res->tupArrSize > 0) ? res->tupArrSize * 2 : 128;
- PGresAttValue **newTuples;
-
- if (res->tuples == NULL)
- newTuples = (PGresAttValue **)
- malloc(newSize * sizeof(PGresAttValue *));
- else
- newTuples = (PGresAttValue **)
- realloc(res->tuples, newSize * sizeof(PGresAttValue *));
- if (!newTuples)
- return FALSE; /* malloc or realloc failed */
- res->tupArrSize = newSize;
- res->tuples = newTuples;
- }
- res->tuples[res->ntups] = tup;
- res->ntups++;
- return TRUE;
-}
-
-/*
- * pqSaveMessageField - save one field of an error or notice message
- */
-void
-pqSaveMessageField(PGresult *res, char code, const char *value)
-{
- PGMessageField *pfield;
-
- pfield = (PGMessageField *)
- pqResultAlloc(res,
- offsetof(PGMessageField, contents) +
- strlen(value) + 1,
- TRUE);
- if (!pfield)
- return; /* out of memory? */
- pfield->code = code;
- strcpy(pfield->contents, value);
- pfield->next = res->errFields;
- res->errFields = pfield;
-}
-
-/*
- * pqSaveParameterStatus - remember parameter status sent by backend
- */
-void
-pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
-{
- pgParameterStatus *pstatus;
- pgParameterStatus *prev;
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n",
- name, value);
-
- /*
- * Forget any old information about the parameter
- */
- for (pstatus = conn->pstatus, prev = NULL;
- pstatus != NULL;
- prev = pstatus, pstatus = pstatus->next)
- {
- if (strcmp(pstatus->name, name) == 0)
- {
- if (prev)
- prev->next = pstatus->next;
- else
- conn->pstatus = pstatus->next;
- free(pstatus); /* frees name and value strings too */
- break;
- }
- }
-
- /*
- * Store new info as a single malloc block
- */
- pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
- strlen(name) +strlen(value) + 2);
- if (pstatus)
- {
- char *ptr;
-
- ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
- pstatus->name = ptr;
- strcpy(ptr, name);
- ptr += strlen(name) + 1;
- pstatus->value = ptr;
- strcpy(ptr, value);
- pstatus->next = conn->pstatus;
- conn->pstatus = pstatus;
- }
-
- /*
- * Special hacks: remember client_encoding and
- * standard_conforming_strings, and convert server version to a numeric
- * form. We keep the first two of these in static variables as well, so
- * that PQescapeString and PQescapeBytea can behave somewhat sanely (at
- * least in single-connection-using programs).
- */
- if (strcmp(name, "client_encoding") == 0)
- {
- conn->client_encoding = pg_char_to_encoding(value);
- /* if we don't recognize the encoding name, fall back to SQL_ASCII */
- if (conn->client_encoding < 0)
- conn->client_encoding = PG_SQL_ASCII;
- static_client_encoding = conn->client_encoding;
- }
- else if (strcmp(name, "standard_conforming_strings") == 0)
- {
- conn->std_strings = (strcmp(value, "on") == 0);
- static_std_strings = conn->std_strings;
- }
- else if (strcmp(name, "server_version") == 0)
- {
- int cnt;
- int vmaj,
- vmin,
- vrev;
-
- cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
-
- if (cnt == 3)
- {
- /* old style, e.g. 9.6.1 */
- conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
- }
- else if (cnt == 2)
- {
- if (vmaj >= 10)
- {
- /* new style, e.g. 10.1 */
- conn->sversion = 100 * 100 * vmaj + vmin;
- }
- else
- {
- /* old style without minor version, e.g. 9.6devel */
- conn->sversion = (100 * vmaj + vmin) * 100;
- }
- }
- else if (cnt == 1)
- {
- /* new style without minor version, e.g. 10devel */
- conn->sversion = 100 * 100 * vmaj;
- }
- else
- conn->sversion = 0; /* unknown */
- }
-}
-
-
-/*
- * pqRowProcessor
- * Add the received row to the current async result (conn->result).
- * Returns 1 if OK, 0 if error occurred.
- *
- * On error, *errmsgp can be set to an error string to be returned.
- * If it is left NULL, the error is presumed to be "out of memory".
- *
- * In single-row mode, we create a new result holding just the current row,
- * stashing the previous result in conn->next_result so that it becomes
- * active again after pqPrepareAsyncResult(). This allows the result metadata
- * (column descriptions) to be carried forward to each result row.
- */
-int
-pqRowProcessor(PGconn *conn, const char **errmsgp)
-{
- PGresult *res = conn->result;
- int nfields = res->numAttributes;
- const PGdataValue *columns = conn->rowBuf;
- PGresAttValue *tup;
- int i;
-
- /*
- * In single-row mode, make a new PGresult that will hold just this one
- * row; the original conn->result is left unchanged so that it can be used
- * again as the template for future rows.
- */
- if (conn->singleRowMode)
- {
- /* Copy everything that should be in the result at this point */
- res = PQcopyResult(res,
- PG_COPYRES_ATTRS | PG_COPYRES_EVENTS |
- PG_COPYRES_NOTICEHOOKS);
- if (!res)
- return 0;
- }
-
- /*
- * Basically we just allocate space in the PGresult for each field and
- * copy the data over.
- *
- * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
- * caller will take to mean "out of memory". This is preferable to trying
- * to set up such a message here, because evidently there's not enough
- * memory for gettext() to do anything.
- */
- tup = (PGresAttValue *)
- pqResultAlloc(res, nfields * sizeof(PGresAttValue), TRUE);
- if (tup == NULL)
- goto fail;
-
- for (i = 0; i < nfields; i++)
- {
- int clen = columns[i].len;
-
- if (clen < 0)
- {
- /* null field */
- tup[i].len = NULL_LEN;
- tup[i].value = res->null_field;
- }
- else
- {
- bool isbinary = (res->attDescs[i].format != 0);
- char *val;
-
- val = (char *) pqResultAlloc(res, clen + 1, isbinary);
- if (val == NULL)
- goto fail;
-
- /* copy and zero-terminate the data (even if it's binary) */
- memcpy(val, columns[i].value, clen);
- val[clen] = '\0';
-
- tup[i].len = clen;
- tup[i].value = val;
- }
- }
-
- /* And add the tuple to the PGresult's tuple array */
- if (!pqAddTuple(res, tup))
- goto fail;
-
- /*
- * Success. In single-row mode, make the result available to the client
- * immediately.
- */
- if (conn->singleRowMode)
- {
- /* Change result status to special single-row value */
- res->resultStatus = PGRES_SINGLE_TUPLE;
- /* Stash old result for re-use later */
- conn->next_result = conn->result;
- conn->result = res;
- /* And mark the result ready to return */
- conn->asyncStatus = PGASYNC_READY;
- }
-
- return 1;
-
-fail:
- /* release locally allocated PGresult, if we made one */
- if (res != conn->result)
- PQclear(res);
- return 0;
-}
-
-
-/*
- * PQsendQuery
- * Submit a query, but don't wait for it to finish
- *
- * Returns: 1 if successfully submitted
- * 0 if error (conn->errorMessage is set)
- */
-int
-PQsendQuery(PGconn *conn, const char *query)
-{
- if (!PQsendQueryStart(conn))
- return 0;
-
- /* check the argument */
- if (!query)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("command string is a null pointer\n"));
- return 0;
- }
-
- /* construct the outgoing Query message */
- if (pqPutMsgStart('Q', false, conn) < 0 ||
- pqPuts(query, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- {
- pqHandleSendFailure(conn);
- return 0;
- }
-
- /* remember we are using simple query protocol */
- conn->queryclass = PGQUERY_SIMPLE;
-
- /* and remember the query text too, if possible */
- /* if insufficient memory, last_query just winds up NULL */
- if (conn->last_query)
- free(conn->last_query);
- conn->last_query = strdup(query);
-
- /*
- * Give the data a push. In nonblock mode, don't complain if we're unable
- * to send it all; PQgetResult() will do any additional flushing needed.
- */
- if (pqFlush(conn) < 0)
- {
- pqHandleSendFailure(conn);
- return 0;
- }
-
- /* OK, it's launched! */
- conn->asyncStatus = PGASYNC_BUSY;
- return 1;
-}
-
-/*
- * PQsendQueryParams
- * Like PQsendQuery, but use protocol 3.0 so we can pass parameters
- */
-int
-PQsendQueryParams(PGconn *conn,
- const char *command,
- int nParams,
- const Oid *paramTypes,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat)
-{
- if (!PQsendQueryStart(conn))
- return 0;
-
- /* check the arguments */
- if (!command)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("command string is a null pointer\n"));
- return 0;
- }
- if (nParams < 0 || nParams > 65535)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of parameters must be between 0 and 65535\n"));
- return 0;
- }
-
- return PQsendQueryGuts(conn,
- command,
- "", /* use unnamed statement */
- nParams,
- paramTypes,
- paramValues,
- paramLengths,
- paramFormats,
- resultFormat);
-}
-
-/*
- * PQsendPrepare
- * Submit a Parse message, but don't wait for it to finish
- *
- * Returns: 1 if successfully submitted
- * 0 if error (conn->errorMessage is set)
- */
-int
-PQsendPrepare(PGconn *conn,
- const char *stmtName, const char *query,
- int nParams, const Oid *paramTypes)
-{
- if (!PQsendQueryStart(conn))
- return 0;
-
- /* check the arguments */
- if (!stmtName)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("statement name is a null pointer\n"));
- return 0;
- }
- if (!query)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("command string is a null pointer\n"));
- return 0;
- }
- if (nParams < 0 || nParams > 65535)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of parameters must be between 0 and 65535\n"));
- return 0;
- }
-
- /* This isn't gonna work on a 2.0 server */
- if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
- return 0;
- }
-
- /* construct the Parse message */
- if (pqPutMsgStart('P', false, conn) < 0 ||
- pqPuts(stmtName, conn) < 0 ||
- pqPuts(query, conn) < 0)
- goto sendFailed;
-
- if (nParams > 0 && paramTypes)
- {
- int i;
-
- if (pqPutInt(nParams, 2, conn) < 0)
- goto sendFailed;
- for (i = 0; i < nParams; i++)
- {
- if (pqPutInt(paramTypes[i], 4, conn) < 0)
- goto sendFailed;
- }
- }
- else
- {
- if (pqPutInt(0, 2, conn) < 0)
- goto sendFailed;
- }
- if (pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* construct the Sync message */
- if (pqPutMsgStart('S', false, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* remember we are doing just a Parse */
- conn->queryclass = PGQUERY_PREPARE;
-
- /* and remember the query text too, if possible */
- /* if insufficient memory, last_query just winds up NULL */
- if (conn->last_query)
- free(conn->last_query);
- conn->last_query = strdup(query);
-
- /*
- * Give the data a push. In nonblock mode, don't complain if we're unable
- * to send it all; PQgetResult() will do any additional flushing needed.
- */
- if (pqFlush(conn) < 0)
- goto sendFailed;
-
- /* OK, it's launched! */
- conn->asyncStatus = PGASYNC_BUSY;
- return 1;
-
-sendFailed:
- pqHandleSendFailure(conn);
- return 0;
-}
-
-/*
- * PQsendQueryPrepared
- * Like PQsendQuery, but execute a previously prepared statement,
- * using protocol 3.0 so we can pass parameters
- */
-int
-PQsendQueryPrepared(PGconn *conn,
- const char *stmtName,
- int nParams,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat)
-{
- if (!PQsendQueryStart(conn))
- return 0;
-
- /* check the arguments */
- if (!stmtName)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("statement name is a null pointer\n"));
- return 0;
- }
- if (nParams < 0 || nParams > 65535)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("number of parameters must be between 0 and 65535\n"));
- return 0;
- }
-
- return PQsendQueryGuts(conn,
- NULL, /* no command to parse */
- stmtName,
- nParams,
- NULL, /* no param types */
- paramValues,
- paramLengths,
- paramFormats,
- resultFormat);
-}
-
-/*
- * Common startup code for PQsendQuery and sibling routines
- */
-static bool
-PQsendQueryStart(PGconn *conn)
-{
- if (!conn)
- return false;
-
- /* clear the error string */
- resetPQExpBuffer(&conn->errorMessage);
-
- /* Don't try to send if we know there's no live connection. */
- if (conn->status != CONNECTION_OK)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no connection to the server\n"));
- return false;
- }
- /* Can't send while already busy, either. */
- if (conn->asyncStatus != PGASYNC_IDLE)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("another command is already in progress\n"));
- return false;
- }
-
- /* initialize async result-accumulation state */
- pqClearAsyncResult(conn);
-
- /* reset single-row processing mode */
- conn->singleRowMode = false;
-
- /* ready to send command message */
- return true;
-}
-
-/*
- * PQsendQueryGuts
- * Common code for protocol-3.0 query sending
- * PQsendQueryStart should be done already
- *
- * command may be NULL to indicate we use an already-prepared statement
- */
-static int
-PQsendQueryGuts(PGconn *conn,
- const char *command,
- const char *stmtName,
- int nParams,
- const Oid *paramTypes,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat)
-{
- int i;
-
- /* This isn't gonna work on a 2.0 server */
- if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
- return 0;
- }
-
- /*
- * We will send Parse (if needed), Bind, Describe Portal, Execute, Sync,
- * using specified statement name and the unnamed portal.
- */
-
- if (command)
- {
- /* construct the Parse message */
- if (pqPutMsgStart('P', false, conn) < 0 ||
- pqPuts(stmtName, conn) < 0 ||
- pqPuts(command, conn) < 0)
- goto sendFailed;
- if (nParams > 0 && paramTypes)
- {
- if (pqPutInt(nParams, 2, conn) < 0)
- goto sendFailed;
- for (i = 0; i < nParams; i++)
- {
- if (pqPutInt(paramTypes[i], 4, conn) < 0)
- goto sendFailed;
- }
- }
- else
- {
- if (pqPutInt(0, 2, conn) < 0)
- goto sendFailed;
- }
- if (pqPutMsgEnd(conn) < 0)
- goto sendFailed;
- }
-
- /* Construct the Bind message */
- if (pqPutMsgStart('B', false, conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPuts(stmtName, conn) < 0)
- goto sendFailed;
-
- /* Send parameter formats */
- if (nParams > 0 && paramFormats)
- {
- if (pqPutInt(nParams, 2, conn) < 0)
- goto sendFailed;
- for (i = 0; i < nParams; i++)
- {
- if (pqPutInt(paramFormats[i], 2, conn) < 0)
- goto sendFailed;
- }
- }
- else
- {
- if (pqPutInt(0, 2, conn) < 0)
- goto sendFailed;
- }
-
- if (pqPutInt(nParams, 2, conn) < 0)
- goto sendFailed;
-
- /* Send parameters */
- for (i = 0; i < nParams; i++)
- {
- if (paramValues && paramValues[i])
- {
- int nbytes;
-
- if (paramFormats && paramFormats[i] != 0)
- {
- /* binary parameter */
- if (paramLengths)
- nbytes = paramLengths[i];
- else
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("length must be given for binary parameter\n"));
- goto sendFailed;
- }
- }
- else
- {
- /* text parameter, do not use paramLengths */
- nbytes = strlen(paramValues[i]);
- }
- if (pqPutInt(nbytes, 4, conn) < 0 ||
- pqPutnchar(paramValues[i], nbytes, conn) < 0)
- goto sendFailed;
- }
- else
- {
- /* take the param as NULL */
- if (pqPutInt(-1, 4, conn) < 0)
- goto sendFailed;
- }
- }
- if (pqPutInt(1, 2, conn) < 0 ||
- pqPutInt(resultFormat, 2, conn))
- goto sendFailed;
- if (pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* construct the Describe Portal message */
- if (pqPutMsgStart('D', false, conn) < 0 ||
- pqPutc('P', conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* construct the Execute message */
- if (pqPutMsgStart('E', false, conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPutInt(0, 4, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* construct the Sync message */
- if (pqPutMsgStart('S', false, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* remember we are using extended query protocol */
- conn->queryclass = PGQUERY_EXTENDED;
-
- /* and remember the query text too, if possible */
- /* if insufficient memory, last_query just winds up NULL */
- if (conn->last_query)
- free(conn->last_query);
- if (command)
- conn->last_query = strdup(command);
- else
- conn->last_query = NULL;
-
- /*
- * Give the data a push. In nonblock mode, don't complain if we're unable
- * to send it all; PQgetResult() will do any additional flushing needed.
- */
- if (pqFlush(conn) < 0)
- goto sendFailed;
-
- /* OK, it's launched! */
- conn->asyncStatus = PGASYNC_BUSY;
- return 1;
-
-sendFailed:
- pqHandleSendFailure(conn);
- return 0;
-}
-
-/*
- * pqHandleSendFailure: try to clean up after failure to send command.
- *
- * Primarily, what we want to accomplish here is to process any ERROR or
- * NOTICE messages that the backend might have sent just before it died.
- * Since we're in IDLE state, all such messages will get sent to the notice
- * processor.
- *
- * NOTE: this routine should only be called in PGASYNC_IDLE state.
- */
-void
-pqHandleSendFailure(PGconn *conn)
-{
- /*
- * Accept and parse any available input data, ignoring I/O errors. Note
- * that if pqReadData decides the backend has closed the channel, it will
- * close our side of the socket --- that's just what we want here.
- */
- while (pqReadData(conn) > 0)
- parseInput(conn);
-
- /*
- * Be sure to parse available input messages even if we read no data.
- * (Note: calling parseInput within the above loop isn't really necessary,
- * but it prevents buffer bloat if there's a lot of data available.)
- */
- parseInput(conn);
-}
-
-/*
- * Select row-by-row processing mode
- */
-int
-PQsetSingleRowMode(PGconn *conn)
-{
- /*
- * Only allow setting the flag when we have launched a query and not yet
- * received any results.
- */
- if (!conn)
- return 0;
- if (conn->asyncStatus != PGASYNC_BUSY)
- return 0;
- if (conn->queryclass != PGQUERY_SIMPLE &&
- conn->queryclass != PGQUERY_EXTENDED)
- return 0;
- if (conn->result)
- return 0;
-
- /* OK, set flag */
- conn->singleRowMode = true;
- return 1;
-}
-
-/*
- * Consume any available input from the backend
- * 0 return: some kind of trouble
- * 1 return: no problem
- */
-int
-PQconsumeInput(PGconn *conn)
-{
- if (!conn)
- return 0;
-
- /*
- * for non-blocking connections try to flush the send-queue, otherwise we
- * may never get a response for something that may not have already been
- * sent because it's in our write buffer!
- */
- if (pqIsnonblocking(conn))
- {
- if (pqFlush(conn) < 0)
- return 0;
- }
-
- /*
- * Load more data, if available. We do this no matter what state we are
- * in, since we are probably getting called because the application wants
- * to get rid of a read-select condition. Note that we will NOT block
- * waiting for more input.
- */
- if (pqReadData(conn) < 0)
- return 0;
-
- /* Parsing of the data waits till later. */
- return 1;
-}
-
-
-/*
- * parseInput: if appropriate, parse input data from backend
- * until input is exhausted or a stopping state is reached.
- * Note that this function will NOT attempt to read more data from the backend.
- */
-static void
-parseInput(PGconn *conn)
-{
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- pqParseInput3(conn);
- else
- pqParseInput2(conn);
-}
-
-/*
- * PQisBusy
- * Return TRUE if PQgetResult would block waiting for input.
- */
-
-int
-PQisBusy(PGconn *conn)
-{
- if (!conn)
- return FALSE;
-
- /* Parse any available data, if our state permits. */
- parseInput(conn);
-
- /* PQgetResult will return immediately in all states except BUSY. */
- return conn->asyncStatus == PGASYNC_BUSY;
-}
-
-
-/*
- * PQgetResult
- * Get the next PGresult produced by a query. Returns NULL if no
- * query work remains or an error has occurred (e.g. out of
- * memory).
- */
-
-PGresult *
-PQgetResult(PGconn *conn)
-{
- PGresult *res;
-
- if (!conn)
- return NULL;
-
- /* Parse any available data, if our state permits. */
- parseInput(conn);
-
- /* If not ready to return something, block until we are. */
- while (conn->asyncStatus == PGASYNC_BUSY)
- {
- int flushResult;
-
- /*
- * If data remains unsent, send it. Else we might be waiting for the
- * result of a command the backend hasn't even got yet.
- */
- while ((flushResult = pqFlush(conn)) > 0)
- {
- if (pqWait(FALSE, TRUE, conn))
- {
- flushResult = -1;
- break;
- }
- }
-
- /* Wait for some more data, and load it. */
- if (flushResult ||
- pqWait(TRUE, FALSE, conn) ||
- pqReadData(conn) < 0)
- {
- /*
- * conn->errorMessage has been set by pqWait or pqReadData. We
- * want to append it to any already-received error message.
- */
- pqSaveErrorResult(conn);
- conn->asyncStatus = PGASYNC_IDLE;
- return pqPrepareAsyncResult(conn);
- }
-
- /* Parse it. */
- parseInput(conn);
- }
-
- /* Return the appropriate thing. */
- switch (conn->asyncStatus)
- {
- case PGASYNC_IDLE:
- res = NULL; /* query is complete */
- break;
- case PGASYNC_READY:
- res = pqPrepareAsyncResult(conn);
- /* Set the state back to BUSY, allowing parsing to proceed. */
- conn->asyncStatus = PGASYNC_BUSY;
- break;
- case PGASYNC_COPY_IN:
- res = getCopyResult(conn, PGRES_COPY_IN);
- break;
- case PGASYNC_COPY_OUT:
- res = getCopyResult(conn, PGRES_COPY_OUT);
- break;
- case PGASYNC_COPY_BOTH:
- res = getCopyResult(conn, PGRES_COPY_BOTH);
- break;
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("unexpected asyncStatus: %d\n"),
- (int) conn->asyncStatus);
- res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
- break;
- }
-
- if (res)
- {
- int i;
-
- for (i = 0; i < res->nEvents; i++)
- {
- PGEventResultCreate evt;
-
- evt.conn = conn;
- evt.result = res;
- if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
- res->events[i].passThrough))
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"),
- res->events[i].name);
- pqSetResultError(res, conn->errorMessage.data);
- res->resultStatus = PGRES_FATAL_ERROR;
- break;
- }
- res->events[i].resultInitialized = TRUE;
- }
- }
-
- return res;
-}
-
-/*
- * getCopyResult
- * Helper for PQgetResult: generate result for COPY-in-progress cases
- */
-static PGresult *
-getCopyResult(PGconn *conn, ExecStatusType copytype)
-{
- /*
- * If the server connection has been lost, don't pretend everything is
- * hunky-dory; instead return a PGRES_FATAL_ERROR result, and reset the
- * asyncStatus to idle (corresponding to what we'd do if we'd detected I/O
- * error in the earlier steps in PQgetResult). The text returned in the
- * result is whatever is in conn->errorMessage; we hope that was filled
- * with something relevant when the lost connection was detected.
- */
- if (conn->status != CONNECTION_OK)
- {
- pqSaveErrorResult(conn);
- conn->asyncStatus = PGASYNC_IDLE;
- return pqPrepareAsyncResult(conn);
- }
-
- /* If we have an async result for the COPY, return that */
- if (conn->result && conn->result->resultStatus == copytype)
- return pqPrepareAsyncResult(conn);
-
- /* Otherwise, invent a suitable PGresult */
- return PQmakeEmptyPGresult(conn, copytype);
-}
-
-
-/*
- * PQexec
- * send a query to the backend and package up the result in a PGresult
- *
- * If the query was not even sent, return NULL; conn->errorMessage is set to
- * a relevant message.
- * If the query was sent, a new PGresult is returned (which could indicate
- * either success or failure).
- * The user is responsible for freeing the PGresult via PQclear()
- * when done with it.
- */
-PGresult *
-PQexec(PGconn *conn, const char *query)
-{
- if (!PQexecStart(conn))
- return NULL;
- if (!PQsendQuery(conn, query))
- return NULL;
- return PQexecFinish(conn);
-}
-
-/*
- * PQexecParams
- * Like PQexec, but use protocol 3.0 so we can pass parameters
- */
-PGresult *
-PQexecParams(PGconn *conn,
- const char *command,
- int nParams,
- const Oid *paramTypes,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat)
-{
- if (!PQexecStart(conn))
- return NULL;
- if (!PQsendQueryParams(conn, command,
- nParams, paramTypes, paramValues, paramLengths,
- paramFormats, resultFormat))
- return NULL;
- return PQexecFinish(conn);
-}
-
-/*
- * PQprepare
- * Creates a prepared statement by issuing a v3.0 parse message.
- *
- * If the query was not even sent, return NULL; conn->errorMessage is set to
- * a relevant message.
- * If the query was sent, a new PGresult is returned (which could indicate
- * either success or failure).
- * The user is responsible for freeing the PGresult via PQclear()
- * when done with it.
- */
-PGresult *
-PQprepare(PGconn *conn,
- const char *stmtName, const char *query,
- int nParams, const Oid *paramTypes)
-{
- if (!PQexecStart(conn))
- return NULL;
- if (!PQsendPrepare(conn, stmtName, query, nParams, paramTypes))
- return NULL;
- return PQexecFinish(conn);
-}
-
-/*
- * PQexecPrepared
- * Like PQexec, but execute a previously prepared statement,
- * using protocol 3.0 so we can pass parameters
- */
-PGresult *
-PQexecPrepared(PGconn *conn,
- const char *stmtName,
- int nParams,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat)
-{
- if (!PQexecStart(conn))
- return NULL;
- if (!PQsendQueryPrepared(conn, stmtName,
- nParams, paramValues, paramLengths,
- paramFormats, resultFormat))
- return NULL;
- return PQexecFinish(conn);
-}
-
-/*
- * Common code for PQexec and sibling routines: prepare to send command
- */
-static bool
-PQexecStart(PGconn *conn)
-{
- PGresult *result;
-
- if (!conn)
- return false;
-
- /*
- * Silently discard any prior query result that application didn't eat.
- * This is probably poor design, but it's here for backward compatibility.
- */
- while ((result = PQgetResult(conn)) != NULL)
- {
- ExecStatusType resultStatus = result->resultStatus;
-
- PQclear(result); /* only need its status */
- if (resultStatus == PGRES_COPY_IN)
- {
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- /* In protocol 3, we can get out of a COPY IN state */
- if (PQputCopyEnd(conn,
- libpq_gettext("COPY terminated by new PQexec")) < 0)
- return false;
- /* keep waiting to swallow the copy's failure message */
- }
- else
- {
- /* In older protocols we have to punt */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("COPY IN state must be terminated first\n"));
- return false;
- }
- }
- else if (resultStatus == PGRES_COPY_OUT)
- {
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- /*
- * In protocol 3, we can get out of a COPY OUT state: we just
- * switch back to BUSY and allow the remaining COPY data to be
- * dropped on the floor.
- */
- conn->asyncStatus = PGASYNC_BUSY;
- /* keep waiting to swallow the copy's completion message */
- }
- else
- {
- /* In older protocols we have to punt */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("COPY OUT state must be terminated first\n"));
- return false;
- }
- }
- else if (resultStatus == PGRES_COPY_BOTH)
- {
- /* We don't allow PQexec during COPY BOTH */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PQexec not allowed during COPY BOTH\n"));
- return false;
- }
- /* check for loss of connection, too */
- if (conn->status == CONNECTION_BAD)
- return false;
- }
-
- /* OK to send a command */
- return true;
-}
-
-/*
- * Common code for PQexec and sibling routines: wait for command result
- */
-static PGresult *
-PQexecFinish(PGconn *conn)
-{
- PGresult *result;
- PGresult *lastResult;
-
- /*
- * For backwards compatibility, return the last result if there are more
- * than one --- but merge error messages if we get more than one error
- * result.
- *
- * We have to stop if we see copy in/out/both, however. We will resume
- * parsing after application performs the data transfer.
- *
- * Also stop if the connection is lost (else we'll loop infinitely).
- */
- lastResult = NULL;
- while ((result = PQgetResult(conn)) != NULL)
- {
- if (lastResult)
- {
- if (lastResult->resultStatus == PGRES_FATAL_ERROR &&
- result->resultStatus == PGRES_FATAL_ERROR)
- {
- pqCatenateResultError(lastResult, result->errMsg);
- PQclear(result);
- result = lastResult;
-
- /*
- * Make sure PQerrorMessage agrees with concatenated result
- */
- resetPQExpBuffer(&conn->errorMessage);
- appendPQExpBufferStr(&conn->errorMessage, result->errMsg);
- }
- else
- PQclear(lastResult);
- }
- lastResult = result;
- if (result->resultStatus == PGRES_COPY_IN ||
- result->resultStatus == PGRES_COPY_OUT ||
- result->resultStatus == PGRES_COPY_BOTH ||
- conn->status == CONNECTION_BAD)
- break;
- }
-
- return lastResult;
-}
-
-/*
- * PQdescribePrepared
- * Obtain information about a previously prepared statement
- *
- * If the query was not even sent, return NULL; conn->errorMessage is set to
- * a relevant message.
- * If the query was sent, a new PGresult is returned (which could indicate
- * either success or failure). On success, the PGresult contains status
- * PGRES_COMMAND_OK, and its parameter and column-heading fields describe
- * the statement's inputs and outputs respectively.
- * The user is responsible for freeing the PGresult via PQclear()
- * when done with it.
- */
-PGresult *
-PQdescribePrepared(PGconn *conn, const char *stmt)
-{
- if (!PQexecStart(conn))
- return NULL;
- if (!PQsendDescribe(conn, 'S', stmt))
- return NULL;
- return PQexecFinish(conn);
-}
-
-/*
- * PQdescribePortal
- * Obtain information about a previously created portal
- *
- * This is much like PQdescribePrepared, except that no parameter info is
- * returned. Note that at the moment, libpq doesn't really expose portals
- * to the client; but this can be used with a portal created by a SQL
- * DECLARE CURSOR command.
- */
-PGresult *
-PQdescribePortal(PGconn *conn, const char *portal)
-{
- if (!PQexecStart(conn))
- return NULL;
- if (!PQsendDescribe(conn, 'P', portal))
- return NULL;
- return PQexecFinish(conn);
-}
-
-/*
- * PQsendDescribePrepared
- * Submit a Describe Statement command, but don't wait for it to finish
- *
- * Returns: 1 if successfully submitted
- * 0 if error (conn->errorMessage is set)
- */
-int
-PQsendDescribePrepared(PGconn *conn, const char *stmt)
-{
- return PQsendDescribe(conn, 'S', stmt);
-}
-
-/*
- * PQsendDescribePortal
- * Submit a Describe Portal command, but don't wait for it to finish
- *
- * Returns: 1 if successfully submitted
- * 0 if error (conn->errorMessage is set)
- */
-int
-PQsendDescribePortal(PGconn *conn, const char *portal)
-{
- return PQsendDescribe(conn, 'P', portal);
-}
-
-/*
- * PQsendDescribe
- * Common code to send a Describe command
- *
- * Available options for desc_type are
- * 'S' to describe a prepared statement; or
- * 'P' to describe a portal.
- * Returns 1 on success and 0 on failure.
- */
-static int
-PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
-{
- /* Treat null desc_target as empty string */
- if (!desc_target)
- desc_target = "";
-
- if (!PQsendQueryStart(conn))
- return 0;
-
- /* This isn't gonna work on a 2.0 server */
- if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
- return 0;
- }
-
- /* construct the Describe message */
- if (pqPutMsgStart('D', false, conn) < 0 ||
- pqPutc(desc_type, conn) < 0 ||
- pqPuts(desc_target, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* construct the Sync message */
- if (pqPutMsgStart('S', false, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
-
- /* remember we are doing a Describe */
- conn->queryclass = PGQUERY_DESCRIBE;
-
- /* reset last-query string (not relevant now) */
- if (conn->last_query)
- {
- free(conn->last_query);
- conn->last_query = NULL;
- }
-
- /*
- * Give the data a push. In nonblock mode, don't complain if we're unable
- * to send it all; PQgetResult() will do any additional flushing needed.
- */
- if (pqFlush(conn) < 0)
- goto sendFailed;
-
- /* OK, it's launched! */
- conn->asyncStatus = PGASYNC_BUSY;
- return 1;
-
-sendFailed:
- pqHandleSendFailure(conn);
- return 0;
-}
-
-/*
- * PQnotifies
- * returns a PGnotify* structure of the latest async notification
- * that has not yet been handled
- *
- * returns NULL, if there is currently
- * no unhandled async notification from the backend
- *
- * the CALLER is responsible for FREE'ing the structure returned
- */
-PGnotify *
-PQnotifies(PGconn *conn)
-{
- PGnotify *event;
-
- if (!conn)
- return NULL;
-
- /* Parse any available data to see if we can extract NOTIFY messages. */
- parseInput(conn);
-
- event = conn->notifyHead;
- if (event)
- {
- conn->notifyHead = event->next;
- if (!conn->notifyHead)
- conn->notifyTail = NULL;
- event->next = NULL; /* don't let app see the internal state */
- }
- return event;
-}
-
-/*
- * PQputCopyData - send some data to the backend during COPY IN or COPY BOTH
- *
- * Returns 1 if successful, 0 if data could not be sent (only possible
- * in nonblock mode), or -1 if an error occurs.
- */
-int
-PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
-{
- if (!conn)
- return -1;
- if (conn->asyncStatus != PGASYNC_COPY_IN &&
- conn->asyncStatus != PGASYNC_COPY_BOTH)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
- return -1;
- }
-
- /*
- * Process any NOTICE or NOTIFY messages that might be pending in the
- * input buffer. Since the server might generate many notices during the
- * COPY, we want to clean those out reasonably promptly to prevent
- * indefinite expansion of the input buffer. (Note: the actual read of
- * input data into the input buffer happens down inside pqSendSome, but
- * it's not authorized to get rid of the data again.)
- */
- parseInput(conn);
-
- if (nbytes > 0)
- {
- /*
- * Try to flush any previously sent data in preference to growing the
- * output buffer. If we can't enlarge the buffer enough to hold the
- * data, return 0 in the nonblock case, else hard error. (For
- * simplicity, always assume 5 bytes of overhead even in protocol 2.0
- * case.)
- */
- if ((conn->outBufSize - conn->outCount - 5) < nbytes)
- {
- if (pqFlush(conn) < 0)
- return -1;
- if (pqCheckOutBufferSpace(conn->outCount + 5 + (size_t) nbytes,
- conn))
- return pqIsnonblocking(conn) ? 0 : -1;
- }
- /* Send the data (too simple to delegate to fe-protocol files) */
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- if (pqPutMsgStart('d', false, conn) < 0 ||
- pqPutnchar(buffer, nbytes, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return -1;
- }
- else
- {
- if (pqPutMsgStart(0, false, conn) < 0 ||
- pqPutnchar(buffer, nbytes, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return -1;
- }
- }
- return 1;
-}
-
-/*
- * PQputCopyEnd - send EOF indication to the backend during COPY IN
- *
- * After calling this, use PQgetResult() to check command completion status.
- *
- * Returns 1 if successful, 0 if data could not be sent (only possible
- * in nonblock mode), or -1 if an error occurs.
- */
-int
-PQputCopyEnd(PGconn *conn, const char *errormsg)
-{
- if (!conn)
- return -1;
- if (conn->asyncStatus != PGASYNC_COPY_IN &&
- conn->asyncStatus != PGASYNC_COPY_BOTH)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
- return -1;
- }
-
- /*
- * Send the COPY END indicator. This is simple enough that we don't
- * bother delegating it to the fe-protocol files.
- */
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- if (errormsg)
- {
- /* Send COPY FAIL */
- if (pqPutMsgStart('f', false, conn) < 0 ||
- pqPuts(errormsg, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return -1;
- }
- else
- {
- /* Send COPY DONE */
- if (pqPutMsgStart('c', false, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return -1;
- }
-
- /*
- * If we sent the COPY command in extended-query mode, we must issue a
- * Sync as well.
- */
- if (conn->queryclass != PGQUERY_SIMPLE)
- {
- if (pqPutMsgStart('S', false, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return -1;
- }
- }
- else
- {
- if (errormsg)
- {
- /* Ooops, no way to do this in 2.0 */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("function requires at least protocol version 3.0\n"));
- return -1;
- }
- else
- {
- /* Send old-style end-of-data marker */
- if (pqPutMsgStart(0, false, conn) < 0 ||
- pqPutnchar("\\.\n", 3, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return -1;
- }
- }
-
- /* Return to active duty */
- if (conn->asyncStatus == PGASYNC_COPY_BOTH)
- conn->asyncStatus = PGASYNC_COPY_OUT;
- else
- conn->asyncStatus = PGASYNC_BUSY;
- resetPQExpBuffer(&conn->errorMessage);
-
- /* Try to flush data */
- if (pqFlush(conn) < 0)
- return -1;
-
- return 1;
-}
-
-/*
- * PQgetCopyData - read a row of data from the backend during COPY OUT
- * or COPY BOTH
- *
- * If successful, sets *buffer to point to a malloc'd row of data, and
- * returns row length (always > 0) as result.
- * Returns 0 if no row available yet (only possible if async is true),
- * -1 if end of copy (consult PQgetResult), or -2 if error (consult
- * PQerrorMessage).
- */
-int
-PQgetCopyData(PGconn *conn, char **buffer, int async)
-{
- *buffer = NULL; /* for all failure cases */
- if (!conn)
- return -2;
- if (conn->asyncStatus != PGASYNC_COPY_OUT &&
- conn->asyncStatus != PGASYNC_COPY_BOTH)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
- return -2;
- }
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- return pqGetCopyData3(conn, buffer, async);
- else
- return pqGetCopyData2(conn, buffer, async);
-}
-
-/*
- * PQgetline - gets a newline-terminated string from the backend.
- *
- * Chiefly here so that applications can use "COPY <rel> to stdout"
- * and read the output string. Returns a null-terminated string in s.
- *
- * XXX this routine is now deprecated, because it can't handle binary data.
- * If called during a COPY BINARY we return EOF.
- *
- * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
- * the terminating \n (like gets(3)).
- *
- * CAUTION: the caller is responsible for detecting the end-of-copy signal
- * (a line containing just "\.") when using this routine.
- *
- * RETURNS:
- * EOF if error (eg, invalid arguments are given)
- * 0 if EOL is reached (i.e., \n has been read)
- * (this is required for backward-compatibility -- this
- * routine used to always return EOF or 0, assuming that
- * the line ended within maxlen bytes.)
- * 1 in other cases (i.e., the buffer was filled before \n is reached)
- */
-int
-PQgetline(PGconn *conn, char *s, int maxlen)
-{
- if (!s || maxlen <= 0)
- return EOF;
- *s = '\0';
- /* maxlen must be at least 3 to hold the \. terminator! */
- if (maxlen < 3)
- return EOF;
-
- if (!conn)
- return EOF;
-
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- return pqGetline3(conn, s, maxlen);
- else
- return pqGetline2(conn, s, maxlen);
-}
-
-/*
- * PQgetlineAsync - gets a COPY data row without blocking.
- *
- * This routine is for applications that want to do "COPY <rel> to stdout"
- * asynchronously, that is without blocking. Having issued the COPY command
- * and gotten a PGRES_COPY_OUT response, the app should call PQconsumeInput
- * and this routine until the end-of-data signal is detected. Unlike
- * PQgetline, this routine takes responsibility for detecting end-of-data.
- *
- * On each call, PQgetlineAsync will return data if a complete data row
- * is available in libpq's input buffer. Otherwise, no data is returned
- * until the rest of the row arrives.
- *
- * If -1 is returned, the end-of-data signal has been recognized (and removed
- * from libpq's input buffer). The caller *must* next call PQendcopy and
- * then return to normal processing.
- *
- * RETURNS:
- * -1 if the end-of-copy-data marker has been recognized
- * 0 if no data is available
- * >0 the number of bytes returned.
- *
- * The data returned will not extend beyond a data-row boundary. If possible
- * a whole row will be returned at one time. But if the buffer offered by
- * the caller is too small to hold a row sent by the backend, then a partial
- * data row will be returned. In text mode this can be detected by testing
- * whether the last returned byte is '\n' or not.
- *
- * The returned data is *not* null-terminated.
- */
-
-int
-PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
-{
- if (!conn)
- return -1;
-
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- return pqGetlineAsync3(conn, buffer, bufsize);
- else
- return pqGetlineAsync2(conn, buffer, bufsize);
-}
-
-/*
- * PQputline -- sends a string to the backend during COPY IN.
- * Returns 0 if OK, EOF if not.
- *
- * This is deprecated primarily because the return convention doesn't allow
- * caller to tell the difference between a hard error and a nonblock-mode
- * send failure.
- */
-int
-PQputline(PGconn *conn, const char *s)
-{
- return PQputnbytes(conn, s, strlen(s));
-}
-
-/*
- * PQputnbytes -- like PQputline, but buffer need not be null-terminated.
- * Returns 0 if OK, EOF if not.
- */
-int
-PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
-{
- if (PQputCopyData(conn, buffer, nbytes) > 0)
- return 0;
- else
- return EOF;
-}
-
-/*
- * PQendcopy
- * After completing the data transfer portion of a copy in/out,
- * the application must call this routine to finish the command protocol.
- *
- * When using protocol 3.0 this is deprecated; it's cleaner to use PQgetResult
- * to get the transfer status. Note however that when using 2.0 protocol,
- * recovering from a copy failure often requires a PQreset. PQendcopy will
- * take care of that, PQgetResult won't.
- *
- * RETURNS:
- * 0 on success
- * 1 on failure
- */
-int
-PQendcopy(PGconn *conn)
-{
- if (!conn)
- return 0;
-
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- return pqEndcopy3(conn);
- else
- return pqEndcopy2(conn);
-}
-
-
-/* ----------------
- * PQfn - Send a function call to the POSTGRES backend.
- *
- * conn : backend connection
- * fnid : OID of function to be called
- * result_buf : pointer to result buffer
- * result_len : actual length of result is returned here
- * result_is_int : If the result is an integer, this must be 1,
- * otherwise this should be 0
- * args : pointer to an array of function arguments
- * (each has length, if integer, and value/pointer)
- * nargs : # of arguments in args array.
- *
- * RETURNS
- * PGresult with status = PGRES_COMMAND_OK if successful.
- * *result_len is > 0 if there is a return value, 0 if not.
- * PGresult with status = PGRES_FATAL_ERROR if backend returns an error.
- * NULL on communications failure. conn->errorMessage will be set.
- * ----------------
- */
-
-PGresult *
-PQfn(PGconn *conn,
- int fnid,
- int *result_buf,
- int *result_len,
- int result_is_int,
- const PQArgBlock *args,
- int nargs)
-{
- *result_len = 0;
-
- if (!conn)
- return NULL;
-
- /* clear the error string */
- resetPQExpBuffer(&conn->errorMessage);
-
- if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
- conn->result != NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("connection in wrong state\n"));
- return NULL;
- }
-
- if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- return pqFunctionCall3(conn, fnid,
- result_buf, result_len,
- result_is_int,
- args, nargs);
- else
- return pqFunctionCall2(conn, fnid,
- result_buf, result_len,
- result_is_int,
- args, nargs);
-}
-
-
-/* ====== accessor funcs for PGresult ======== */
-
-ExecStatusType
-PQresultStatus(const PGresult *res)
-{
- if (!res)
- return PGRES_FATAL_ERROR;
- return res->resultStatus;
-}
-
-char *
-PQresStatus(ExecStatusType status)
-{
- if ((unsigned int) status >= sizeof pgresStatus / sizeof pgresStatus[0])
- return libpq_gettext("invalid ExecStatusType code");
- return pgresStatus[status];
-}
-
-char *
-PQresultErrorMessage(const PGresult *res)
-{
- if (!res || !res->errMsg)
- return "";
- return res->errMsg;
-}
-
-char *
-PQresultVerboseErrorMessage(const PGresult *res,
- PGVerbosity verbosity,
- PGContextVisibility show_context)
-{
- PQExpBufferData workBuf;
-
- /*
- * Because the caller is expected to free the result string, we must
- * strdup any constant result. We use plain strdup and document that
- * callers should expect NULL if out-of-memory.
- */
- if (!res ||
- (res->resultStatus != PGRES_FATAL_ERROR &&
- res->resultStatus != PGRES_NONFATAL_ERROR))
- return strdup(libpq_gettext("PGresult is not an error result\n"));
-
- initPQExpBuffer(&workBuf);
-
- /*
- * Currently, we pass this off to fe-protocol3.c in all cases; it will
- * behave reasonably sanely with an error reported by fe-protocol2.c as
- * well. If necessary, we could record the protocol version in PGresults
- * so as to be able to invoke a version-specific message formatter, but
- * for now there's no need.
- */
- pqBuildErrorMessage3(&workBuf, res, verbosity, show_context);
-
- /* If insufficient memory to format the message, fail cleanly */
- if (PQExpBufferDataBroken(workBuf))
- {
- termPQExpBuffer(&workBuf);
- return strdup(libpq_gettext("out of memory\n"));
- }
-
- return workBuf.data;
-}
-
-char *
-PQresultErrorField(const PGresult *res, int fieldcode)
-{
- PGMessageField *pfield;
-
- if (!res)
- return NULL;
- for (pfield = res->errFields; pfield != NULL; pfield = pfield->next)
- {
- if (pfield->code == fieldcode)
- return pfield->contents;
- }
- return NULL;
-}
-
-int
-PQntuples(const PGresult *res)
-{
- if (!res)
- return 0;
- return res->ntups;
-}
-
-int
-PQnfields(const PGresult *res)
-{
- if (!res)
- return 0;
- return res->numAttributes;
-}
-
-int
-PQbinaryTuples(const PGresult *res)
-{
- if (!res)
- return 0;
- return res->binary;
-}
-
-/*
- * Helper routines to range-check field numbers and tuple numbers.
- * Return TRUE if OK, FALSE if not
- */
-
-static int
-check_field_number(const PGresult *res, int field_num)
-{
- if (!res)
- return FALSE; /* no way to display error message... */
- if (field_num < 0 || field_num >= res->numAttributes)
- {
- pqInternalNotice(&res->noticeHooks,
- "column number %d is out of range 0..%d",
- field_num, res->numAttributes - 1);
- return FALSE;
- }
- return TRUE;
-}
-
-static int
-check_tuple_field_number(const PGresult *res,
- int tup_num, int field_num)
-{
- if (!res)
- return FALSE; /* no way to display error message... */
- if (tup_num < 0 || tup_num >= res->ntups)
- {
- pqInternalNotice(&res->noticeHooks,
- "row number %d is out of range 0..%d",
- tup_num, res->ntups - 1);
- return FALSE;
- }
- if (field_num < 0 || field_num >= res->numAttributes)
- {
- pqInternalNotice(&res->noticeHooks,
- "column number %d is out of range 0..%d",
- field_num, res->numAttributes - 1);
- return FALSE;
- }
- return TRUE;
-}
-
-static int
-check_param_number(const PGresult *res, int param_num)
-{
- if (!res)
- return FALSE; /* no way to display error message... */
- if (param_num < 0 || param_num >= res->numParameters)
- {
- pqInternalNotice(&res->noticeHooks,
- "parameter number %d is out of range 0..%d",
- param_num, res->numParameters - 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * returns NULL if the field_num is invalid
- */
-char *
-PQfname(const PGresult *res, int field_num)
-{
- if (!check_field_number(res, field_num))
- return NULL;
- if (res->attDescs)
- return res->attDescs[field_num].name;
- else
- return NULL;
-}
-
-/*
- * PQfnumber: find column number given column name
- *
- * The column name is parsed as if it were in a SQL statement, including
- * case-folding and double-quote processing. But note a possible gotcha:
- * downcasing in the frontend might follow different locale rules than
- * downcasing in the backend...
- *
- * Returns -1 if no match. In the present backend it is also possible
- * to have multiple matches, in which case the first one is found.
- */
-int
-PQfnumber(const PGresult *res, const char *field_name)
-{
- char *field_case;
- bool in_quotes;
- bool all_lower = true;
- const char *iptr;
- char *optr;
- int i;
-
- if (!res)
- return -1;
-
- /*
- * Note: it is correct to reject a zero-length input string; the proper
- * input to match a zero-length field name would be "".
- */
- if (field_name == NULL ||
- field_name[0] == '\0' ||
- res->attDescs == NULL)
- return -1;
-
- /*
- * Check if we can avoid the strdup() and related work because the
- * passed-in string wouldn't be changed before we do the check anyway.
- */
- for (iptr = field_name; *iptr; iptr++)
- {
- char c = *iptr;
-
- if (c == '"' || c != pg_tolower((unsigned char) c))
- {
- all_lower = false;
- break;
- }
- }
-
- if (all_lower)
- for (i = 0; i < res->numAttributes; i++)
- if (strcmp(field_name, res->attDescs[i].name) == 0)
- return i;
-
- /* Fall through to the normal check if that didn't work out. */
-
- /*
- * Note: this code will not reject partially quoted strings, eg
- * foo"BAR"foo will become fooBARfoo when it probably ought to be an error
- * condition.
- */
- field_case = strdup(field_name);
- if (field_case == NULL)
- return -1; /* grotty */
-
- in_quotes = false;
- optr = field_case;
- for (iptr = field_case; *iptr; iptr++)
- {
- char c = *iptr;
-
- if (in_quotes)
- {
- if (c == '"')
- {
- if (iptr[1] == '"')
- {
- /* doubled quotes become a single quote */
- *optr++ = '"';
- iptr++;
- }
- else
- in_quotes = false;
- }
- else
- *optr++ = c;
- }
- else if (c == '"')
- in_quotes = true;
- else
- {
- c = pg_tolower((unsigned char) c);
- *optr++ = c;
- }
- }
- *optr = '\0';
-
- for (i = 0; i < res->numAttributes; i++)
- {
- if (strcmp(field_case, res->attDescs[i].name) == 0)
- {
- free(field_case);
- return i;
- }
- }
- free(field_case);
- return -1;
-}
-
-Oid
-PQftable(const PGresult *res, int field_num)
-{
- if (!check_field_number(res, field_num))
- return InvalidOid;
- if (res->attDescs)
- return res->attDescs[field_num].tableid;
- else
- return InvalidOid;
-}
-
-int
-PQftablecol(const PGresult *res, int field_num)
-{
- if (!check_field_number(res, field_num))
- return 0;
- if (res->attDescs)
- return res->attDescs[field_num].columnid;
- else
- return 0;
-}
-
-int
-PQfformat(const PGresult *res, int field_num)
-{
- if (!check_field_number(res, field_num))
- return 0;
- if (res->attDescs)
- return res->attDescs[field_num].format;
- else
- return 0;
-}
-
-Oid
-PQftype(const PGresult *res, int field_num)
-{
- if (!check_field_number(res, field_num))
- return InvalidOid;
- if (res->attDescs)
- return res->attDescs[field_num].typid;
- else
- return InvalidOid;
-}
-
-int
-PQfsize(const PGresult *res, int field_num)
-{
- if (!check_field_number(res, field_num))
- return 0;
- if (res->attDescs)
- return res->attDescs[field_num].typlen;
- else
- return 0;
-}
-
-int
-PQfmod(const PGresult *res, int field_num)
-{
- if (!check_field_number(res, field_num))
- return 0;
- if (res->attDescs)
- return res->attDescs[field_num].atttypmod;
- else
- return 0;
-}
-
-char *
-PQcmdStatus(PGresult *res)
-{
- if (!res)
- return NULL;
- return res->cmdStatus;
-}
-
-/*
- * PQoidStatus -
- * if the last command was an INSERT, return the oid string
- * if not, return ""
- */
-char *
-PQoidStatus(const PGresult *res)
-{
- /*
- * This must be enough to hold the result. Don't laugh, this is better
- * than what this function used to do.
- */
- static char buf[24];
-
- size_t len;
-
- if (!res || strncmp(res->cmdStatus, "INSERT ", 7) != 0)
- return "";
-
- len = strspn(res->cmdStatus + 7, "0123456789");
- if (len > sizeof(buf) - 1)
- len = sizeof(buf) - 1;
- memcpy(buf, res->cmdStatus + 7, len);
- buf[len] = '\0';
-
- return buf;
-}
-
-/*
- * PQoidValue -
- * a perhaps preferable form of the above which just returns
- * an Oid type
- */
-Oid
-PQoidValue(const PGresult *res)
-{
- char *endptr = NULL;
- unsigned long result;
-
- if (!res ||
- strncmp(res->cmdStatus, "INSERT ", 7) != 0 ||
- res->cmdStatus[7] < '0' ||
- res->cmdStatus[7] > '9')
- return InvalidOid;
-
- result = strtoul(res->cmdStatus + 7, &endptr, 10);
-
- if (!endptr || (*endptr != ' ' && *endptr != '\0'))
- return InvalidOid;
- else
- return (Oid) result;
-}
-
-
-/*
- * PQcmdTuples -
- * If the last command was INSERT/UPDATE/DELETE/MOVE/FETCH/COPY, return
- * a string containing the number of inserted/affected tuples. If not,
- * return "".
- *
- * XXX: this should probably return an int
- */
-char *
-PQcmdTuples(PGresult *res)
-{
- char *p,
- *c;
-
- if (!res)
- return "";
-
- if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
- {
- p = res->cmdStatus + 7;
- /* INSERT: skip oid and space */
- while (*p && *p != ' ')
- p++;
- if (*p == 0)
- goto interpret_error; /* no space? */
- p++;
- }
- else if (strncmp(res->cmdStatus, "SELECT ", 7) == 0 ||
- strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
- strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
- p = res->cmdStatus + 7;
- else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
- p = res->cmdStatus + 6;
- else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
- strncmp(res->cmdStatus, "COPY ", 5) == 0)
- p = res->cmdStatus + 5;
- else
- return "";
-
- /* check that we have an integer (at least one digit, nothing else) */
- for (c = p; *c; c++)
- {
- if (!isdigit((unsigned char) *c))
- goto interpret_error;
- }
- if (c == p)
- goto interpret_error;
-
- return p;
-
-interpret_error:
- pqInternalNotice(&res->noticeHooks,
- "could not interpret result from server: %s",
- res->cmdStatus);
- return "";
-}
-
-/*
- * PQgetvalue:
- * return the value of field 'field_num' of row 'tup_num'
- */
-char *
-PQgetvalue(const PGresult *res, int tup_num, int field_num)
-{
- if (!check_tuple_field_number(res, tup_num, field_num))
- return NULL;
- return res->tuples[tup_num][field_num].value;
-}
-
-/* PQgetlength:
- * returns the actual length of a field value in bytes.
- */
-int
-PQgetlength(const PGresult *res, int tup_num, int field_num)
-{
- if (!check_tuple_field_number(res, tup_num, field_num))
- return 0;
- if (res->tuples[tup_num][field_num].len != NULL_LEN)
- return res->tuples[tup_num][field_num].len;
- else
- return 0;
-}
-
-/* PQgetisnull:
- * returns the null status of a field value.
- */
-int
-PQgetisnull(const PGresult *res, int tup_num, int field_num)
-{
- if (!check_tuple_field_number(res, tup_num, field_num))
- return 1; /* pretend it is null */
- if (res->tuples[tup_num][field_num].len == NULL_LEN)
- return 1;
- else
- return 0;
-}
-
-/* PQnparams:
- * returns the number of input parameters of a prepared statement.
- */
-int
-PQnparams(const PGresult *res)
-{
- if (!res)
- return 0;
- return res->numParameters;
-}
-
-/* PQparamtype:
- * returns type Oid of the specified statement parameter.
- */
-Oid
-PQparamtype(const PGresult *res, int param_num)
-{
- if (!check_param_number(res, param_num))
- return InvalidOid;
- if (res->paramDescs)
- return res->paramDescs[param_num].typid;
- else
- return InvalidOid;
-}
-
-
-/* PQsetnonblocking:
- * sets the PGconn's database connection non-blocking if the arg is TRUE
- * or makes it blocking if the arg is FALSE, this will not protect
- * you from PQexec(), you'll only be safe when using the non-blocking API.
- * Needs to be called only on a connected database connection.
- */
-int
-PQsetnonblocking(PGconn *conn, int arg)
-{
- bool barg;
-
- if (!conn || conn->status == CONNECTION_BAD)
- return -1;
-
- barg = (arg ? TRUE : FALSE);
-
- /* early out if the socket is already in the state requested */
- if (barg == conn->nonblocking)
- return 0;
-
- /*
- * to guarantee constancy for flushing/query/result-polling behavior we
- * need to flush the send queue at this point in order to guarantee proper
- * behavior. this is ok because either they are making a transition _from_
- * or _to_ blocking mode, either way we can block them.
- */
- /* if we are going from blocking to non-blocking flush here */
- if (pqFlush(conn))
- return -1;
-
- conn->nonblocking = barg;
-
- return 0;
-}
-
-/*
- * return the blocking status of the database connection
- * TRUE == nonblocking, FALSE == blocking
- */
-int
-PQisnonblocking(const PGconn *conn)
-{
- return pqIsnonblocking(conn);
-}
-
-/* libpq is thread-safe? */
-int
-PQisthreadsafe(void)
-{
-#ifdef ENABLE_THREAD_SAFETY
- return true;
-#else
- return false;
-#endif
-}
-
-
-/* try to force data out, really only useful for non-blocking users */
-int
-PQflush(PGconn *conn)
-{
- return pqFlush(conn);
-}
-
-
-/*
- * PQfreemem - safely frees memory allocated
- *
- * Needed mostly by Win32, unless multithreaded DLL (/MD in VC6)
- * Used for freeing memory from PQescapeByte()a/PQunescapeBytea()
- */
-void
-PQfreemem(void *ptr)
-{
- free(ptr);
-}
-
-/*
- * PQfreeNotify - free's the memory associated with a PGnotify
- *
- * This function is here only for binary backward compatibility.
- * New code should use PQfreemem(). A macro will automatically map
- * calls to PQfreemem. It should be removed in the future. bjm 2003-03-24
- */
-
-#undef PQfreeNotify
-void PQfreeNotify(PGnotify *notify);
-
-void
-PQfreeNotify(PGnotify *notify)
-{
- PQfreemem(notify);
-}
-
-
-/*
- * Escaping arbitrary strings to get valid SQL literal strings.
- *
- * Replaces "'" with "''", and if not std_strings, replaces "\" with "\\".
- *
- * length is the length of the source string. (Note: if a terminating NUL
- * is encountered sooner, PQescapeString stops short of "length"; the behavior
- * is thus rather like strncpy.)
- *
- * For safety the buffer at "to" must be at least 2*length + 1 bytes long.
- * A terminating NUL character is added to the output string, whether the
- * input is NUL-terminated or not.
- *
- * Returns the actual length of the output (not counting the terminating NUL).
- */
-static size_t
-PQescapeStringInternal(PGconn *conn,
- char *to, const char *from, size_t length,
- int *error,
- int encoding, bool std_strings)
-{
- const char *source = from;
- char *target = to;
- size_t remaining = length;
-
- if (error)
- *error = 0;
-
- while (remaining > 0 && *source != '\0')
- {
- char c = *source;
- int len;
- int i;
-
- /* Fast path for plain ASCII */
- if (!IS_HIGHBIT_SET(c))
- {
- /* Apply quoting if needed */
- if (SQL_STR_DOUBLE(c, !std_strings))
- *target++ = c;
- /* Copy the character */
- *target++ = c;
- source++;
- remaining--;
- continue;
- }
-
- /* Slow path for possible multibyte characters */
- len = pg_encoding_mblen(encoding, source);
-
- /* Copy the character */
- for (i = 0; i < len; i++)
- {
- if (remaining == 0 || *source == '\0')
- break;
- *target++ = *source++;
- remaining--;
- }
-
- /*
- * If we hit premature end of string (ie, incomplete multibyte
- * character), try to pad out to the correct length with spaces. We
- * may not be able to pad completely, but we will always be able to
- * insert at least one pad space (since we'd not have quoted a
- * multibyte character). This should be enough to make a string that
- * the server will error out on.
- */
- if (i < len)
- {
- if (error)
- *error = 1;
- if (conn)
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("incomplete multibyte character\n"));
- for (; i < len; i++)
- {
- if (((size_t) (target - to)) / 2 >= length)
- break;
- *target++ = ' ';
- }
- break;
- }
- }
-
- /* Write the terminating NUL character. */
- *target = '\0';
-
- return target - to;
-}
-
-size_t
-PQescapeStringConn(PGconn *conn,
- char *to, const char *from, size_t length,
- int *error)
-{
- if (!conn)
- {
- /* force empty-string result */
- *to = '\0';
- if (error)
- *error = 1;
- return 0;
- }
- return PQescapeStringInternal(conn, to, from, length, error,
- conn->client_encoding,
- conn->std_strings);
-}
-
-size_t
-PQescapeString(char *to, const char *from, size_t length)
-{
- return PQescapeStringInternal(NULL, to, from, length, NULL,
- static_client_encoding,
- static_std_strings);
-}
-
-
-/*
- * Escape arbitrary strings. If as_ident is true, we escape the result
- * as an identifier; if false, as a literal. The result is returned in
- * a newly allocated buffer. If we fail due to an encoding violation or out
- * of memory condition, we return NULL, storing an error message into conn.
- */
-static char *
-PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
-{
- const char *s;
- char *result;
- char *rp;
- int num_quotes = 0; /* single or double, depending on as_ident */
- int num_backslashes = 0;
- int input_len;
- int result_size;
- char quote_char = as_ident ? '"' : '\'';
-
- /* We must have a connection, else fail immediately. */
- if (!conn)
- return NULL;
-
- /* Scan the string for characters that must be escaped. */
- for (s = str; (s - str) < len && *s != '\0'; ++s)
- {
- if (*s == quote_char)
- ++num_quotes;
- else if (*s == '\\')
- ++num_backslashes;
- else if (IS_HIGHBIT_SET(*s))
- {
- int charlen;
-
- /* Slow path for possible multibyte characters */
- charlen = pg_encoding_mblen(conn->client_encoding, s);
-
- /* Multibyte character overruns allowable length. */
- if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("incomplete multibyte character\n"));
- return NULL;
- }
-
- /* Adjust s, bearing in mind that for loop will increment it. */
- s += charlen - 1;
- }
- }
-
- /* Allocate output buffer. */
- input_len = s - str;
- result_size = input_len + num_quotes + 3; /* two quotes, plus a NUL */
- if (!as_ident && num_backslashes > 0)
- result_size += num_backslashes + 2;
- result = rp = (char *) malloc(result_size);
- if (rp == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return NULL;
- }
-
- /*
- * If we are escaping a literal that contains backslashes, we use the
- * escape string syntax so that the result is correct under either value
- * of standard_conforming_strings. We also emit a leading space in this
- * case, to guard against the possibility that the result might be
- * interpolated immediately following an identifier.
- */
- if (!as_ident && num_backslashes > 0)
- {
- *rp++ = ' ';
- *rp++ = 'E';
- }
-
- /* Opening quote. */
- *rp++ = quote_char;
-
- /*
- * Use fast path if possible.
- *
- * We've already verified that the input string is well-formed in the
- * current encoding. If it contains no quotes and, in the case of
- * literal-escaping, no backslashes, then we can just copy it directly to
- * the output buffer, adding the necessary quotes.
- *
- * If not, we must rescan the input and process each character
- * individually.
- */
- if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
- {
- memcpy(rp, str, input_len);
- rp += input_len;
- }
- else
- {
- for (s = str; s - str < input_len; ++s)
- {
- if (*s == quote_char || (!as_ident && *s == '\\'))
- {
- *rp++ = *s;
- *rp++ = *s;
- }
- else if (!IS_HIGHBIT_SET(*s))
- *rp++ = *s;
- else
- {
- int i = pg_encoding_mblen(conn->client_encoding, s);
-
- while (1)
- {
- *rp++ = *s;
- if (--i == 0)
- break;
- ++s; /* for loop will provide the final increment */
- }
- }
- }
- }
-
- /* Closing quote and terminating NUL. */
- *rp++ = quote_char;
- *rp = '\0';
-
- return result;
-}
-
-char *
-PQescapeLiteral(PGconn *conn, const char *str, size_t len)
-{
- return PQescapeInternal(conn, str, len, false);
-}
-
-char *
-PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
-{
- return PQescapeInternal(conn, str, len, true);
-}
-
-/* HEX encoding support for bytea */
-static const char hextbl[] = "0123456789abcdef";
-
-static const int8 hexlookup[128] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-};
-
-static inline char
-get_hex(char c)
-{
- int res = -1;
-
- if (c > 0 && c < 127)
- res = hexlookup[(unsigned char) c];
-
- return (char) res;
-}
-
-
-/*
- * PQescapeBytea - converts from binary string to the
- * minimal encoding necessary to include the string in an SQL
- * INSERT statement with a bytea type column as the target.
- *
- * We can use either hex or escape (traditional) encoding.
- * In escape mode, the following transformations are applied:
- * '\0' == ASCII 0 == \000
- * '\'' == ASCII 39 == ''
- * '\\' == ASCII 92 == \\
- * anything < 0x20, or > 0x7e ---> \ooo
- * (where ooo is an octal expression)
- *
- * If not std_strings, all backslashes sent to the output are doubled.
- */
-static unsigned char *
-PQescapeByteaInternal(PGconn *conn,
- const unsigned char *from, size_t from_length,
- size_t *to_length, bool std_strings, bool use_hex)
-{
- const unsigned char *vp;
- unsigned char *rp;
- unsigned char *result;
- size_t i;
- size_t len;
- size_t bslash_len = (std_strings ? 1 : 2);
-
- /*
- * empty string has 1 char ('\0')
- */
- len = 1;
-
- if (use_hex)
- {
- len += bslash_len + 1 + 2 * from_length;
- }
- else
- {
- vp = from;
- for (i = from_length; i > 0; i--, vp++)
- {
- if (*vp < 0x20 || *vp > 0x7e)
- len += bslash_len + 3;
- else if (*vp == '\'')
- len += 2;
- else if (*vp == '\\')
- len += bslash_len + bslash_len;
- else
- len++;
- }
- }
-
- *to_length = len;
- rp = result = (unsigned char *) malloc(len);
- if (rp == NULL)
- {
- if (conn)
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return NULL;
- }
-
- if (use_hex)
- {
- if (!std_strings)
- *rp++ = '\\';
- *rp++ = '\\';
- *rp++ = 'x';
- }
-
- vp = from;
- for (i = from_length; i > 0; i--, vp++)
- {
- unsigned char c = *vp;
-
- if (use_hex)
- {
- *rp++ = hextbl[(c >> 4) & 0xF];
- *rp++ = hextbl[c & 0xF];
- }
- else if (c < 0x20 || c > 0x7e)
- {
- if (!std_strings)
- *rp++ = '\\';
- *rp++ = '\\';
- *rp++ = (c >> 6) + '0';
- *rp++ = ((c >> 3) & 07) + '0';
- *rp++ = (c & 07) + '0';
- }
- else if (c == '\'')
- {
- *rp++ = '\'';
- *rp++ = '\'';
- }
- else if (c == '\\')
- {
- if (!std_strings)
- {
- *rp++ = '\\';
- *rp++ = '\\';
- }
- *rp++ = '\\';
- *rp++ = '\\';
- }
- else
- *rp++ = c;
- }
- *rp = '\0';
-
- return result;
-}
-
-unsigned char *
-PQescapeByteaConn(PGconn *conn,
- const unsigned char *from, size_t from_length,
- size_t *to_length)
-{
- if (!conn)
- return NULL;
- return PQescapeByteaInternal(conn, from, from_length, to_length,
- conn->std_strings,
- (conn->sversion >= 90000));
-}
-
-unsigned char *
-PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length)
-{
- return PQescapeByteaInternal(NULL, from, from_length, to_length,
- static_std_strings,
- false /* can't use hex */ );
-}
-
-
-#define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3')
-#define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7')
-#define OCTVAL(CH) ((CH) - '0')
-
-/*
- * PQunescapeBytea - converts the null terminated string representation
- * of a bytea, strtext, into binary, filling a buffer. It returns a
- * pointer to the buffer (or NULL on error), and the size of the
- * buffer in retbuflen. The pointer may subsequently be used as an
- * argument to the function PQfreemem.
- *
- * The following transformations are made:
- * \\ == ASCII 92 == \
- * \ooo == a byte whose value = ooo (ooo is an octal number)
- * \x == x (x is any character not matched by the above transformations)
- */
-unsigned char *
-PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
-{
- size_t strtextlen,
- buflen;
- unsigned char *buffer,
- *tmpbuf;
- size_t i,
- j;
-
- if (strtext == NULL)
- return NULL;
-
- strtextlen = strlen((const char *) strtext);
-
- if (strtext[0] == '\\' && strtext[1] == 'x')
- {
- const unsigned char *s;
- unsigned char *p;
-
- buflen = (strtextlen - 2) / 2;
- /* Avoid unportable malloc(0) */
- buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1);
- if (buffer == NULL)
- return NULL;
-
- s = strtext + 2;
- p = buffer;
- while (*s)
- {
- char v1,
- v2;
-
- /*
- * Bad input is silently ignored. Note that this includes
- * whitespace between hex pairs, which is allowed by byteain.
- */
- v1 = get_hex(*s++);
- if (!*s || v1 == (char) -1)
- continue;
- v2 = get_hex(*s++);
- if (v2 != (char) -1)
- *p++ = (v1 << 4) | v2;
- }
-
- buflen = p - buffer;
- }
- else
- {
- /*
- * Length of input is max length of output, but add one to avoid
- * unportable malloc(0) if input is zero-length.
- */
- buffer = (unsigned char *) malloc(strtextlen + 1);
- if (buffer == NULL)
- return NULL;
-
- for (i = j = 0; i < strtextlen;)
- {
- switch (strtext[i])
- {
- case '\\':
- i++;
- if (strtext[i] == '\\')
- buffer[j++] = strtext[i++];
- else
- {
- if ((ISFIRSTOCTDIGIT(strtext[i])) &&
- (ISOCTDIGIT(strtext[i + 1])) &&
- (ISOCTDIGIT(strtext[i + 2])))
- {
- int byte;
-
- byte = OCTVAL(strtext[i++]);
- byte = (byte << 3) + OCTVAL(strtext[i++]);
- byte = (byte << 3) + OCTVAL(strtext[i++]);
- buffer[j++] = byte;
- }
- }
-
- /*
- * Note: if we see '\' followed by something that isn't a
- * recognized escape sequence, we loop around having done
- * nothing except advance i. Therefore the something will
- * be emitted as ordinary data on the next cycle. Corner
- * case: '\' at end of string will just be discarded.
- */
- break;
-
- default:
- buffer[j++] = strtext[i++];
- break;
- }
- }
- buflen = j; /* buflen is the length of the dequoted data */
- }
-
- /* Shrink the buffer to be no larger than necessary */
- /* +1 avoids unportable behavior when buflen==0 */
- tmpbuf = realloc(buffer, buflen + 1);
-
- /* It would only be a very brain-dead realloc that could fail, but... */
- if (!tmpbuf)
- {
- free(buffer);
- return NULL;
- }
-
- *retbuflen = buflen;
- return tmpbuf;
-}
diff --git a/libpq/fe-lobj.c b/libpq/fe-lobj.c
deleted file mode 100644
index 3b08768..0000000
--- a/libpq/fe-lobj.c
+++ /dev/null
@@ -1,1103 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-lobj.c
- * Front-end large object interface
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-lobj.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifdef WIN32
-/*
- * As unlink/rename are #define'd in port.h (via postgres_fe.h), io.h
- * must be included first on MS C. Might as well do it for all WIN32's
- * here.
- */
-#include <io.h>
-#endif
-
-#include "postgres_fe.h"
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <unistd.h>
-#endif
-
-#include <fcntl.h>
-#include <limits.h>
-#include <sys/stat.h>
-#include <netinet/in.h> /* for ntohl/htonl */
-#include <arpa/inet.h>
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-#include "libpq/libpq-fs.h" /* must come after sys/stat.h */
-
-#define LO_BUFSIZE 8192
-
-static int lo_initialize(PGconn *conn);
-static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid);
-static pg_int64 lo_hton64(pg_int64 host64);
-static pg_int64 lo_ntoh64(pg_int64 net64);
-
-/*
- * lo_open
- * opens an existing large object
- *
- * returns the file descriptor for use in later lo_* calls
- * return -1 upon failure.
- */
-int
-lo_open(PGconn *conn, Oid lobjId, int mode)
-{
- int fd;
- int result_len;
- PQArgBlock argv[2];
- PGresult *res;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = lobjId;
-
- argv[1].isint = 1;
- argv[1].len = 4;
- argv[1].u.integer = mode;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return fd;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_close
- * closes an existing large object
- *
- * returns 0 upon success
- * returns -1 upon failure.
- */
-int
-lo_close(PGconn *conn, int fd)
-{
- PQArgBlock argv[1];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
- res = PQfn(conn, conn->lobjfuncs->fn_lo_close,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_truncate
- * truncates an existing large object to the given size
- *
- * returns 0 upon success
- * returns -1 upon failure
- */
-int
-lo_truncate(PGconn *conn, int fd, size_t len)
-{
- PQArgBlock argv[2];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- /* Must check this on-the-fly because it's not there pre-8.3 */
- if (conn->lobjfuncs->fn_lo_truncate == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_truncate\n"));
- return -1;
- }
-
- /*
- * Long ago, somebody thought it'd be a good idea to declare this function
- * as taking size_t ... but the underlying backend function only accepts a
- * signed int32 length. So throw error if the given value overflows
- * int32. (A possible alternative is to automatically redirect the call
- * to lo_truncate64; but if the caller wanted to rely on that backend
- * function being available, he could have called lo_truncate64 for
- * himself.)
- */
- if (len > (size_t) INT_MAX)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("argument of lo_truncate exceeds integer range\n"));
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- argv[1].isint = 1;
- argv[1].len = 4;
- argv[1].u.integer = (int) len;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate,
- &retval, &result_len, 1, argv, 2);
-
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_truncate64
- * truncates an existing large object to the given size
- *
- * returns 0 upon success
- * returns -1 upon failure
- */
-int
-lo_truncate64(PGconn *conn, int fd, pg_int64 len)
-{
- PQArgBlock argv[2];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- if (conn->lobjfuncs->fn_lo_truncate64 == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_truncate64\n"));
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- len = lo_hton64(len);
- argv[1].isint = 0;
- argv[1].len = 8;
- argv[1].u.ptr = (int *) &len;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate64,
- &retval, &result_len, 1, argv, 2);
-
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_read
- * read len bytes of the large object into buf
- *
- * returns the number of bytes read, or -1 on failure.
- * the CALLER must have allocated enough space to hold the result returned
- */
-
-int
-lo_read(PGconn *conn, int fd, char *buf, size_t len)
-{
- PQArgBlock argv[2];
- PGresult *res;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- /*
- * Long ago, somebody thought it'd be a good idea to declare this function
- * as taking size_t ... but the underlying backend function only accepts a
- * signed int32 length. So throw error if the given value overflows
- * int32.
- */
- if (len > (size_t) INT_MAX)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("argument of lo_read exceeds integer range\n"));
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- argv[1].isint = 1;
- argv[1].len = 4;
- argv[1].u.integer = (int) len;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
- (void *) buf, &result_len, 0, argv, 2);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return result_len;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_write
- * write len bytes of buf into the large object fd
- *
- * returns the number of bytes written, or -1 on failure.
- */
-int
-lo_write(PGconn *conn, int fd, const char *buf, size_t len)
-{
- PQArgBlock argv[2];
- PGresult *res;
- int result_len;
- int retval;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- /*
- * Long ago, somebody thought it'd be a good idea to declare this function
- * as taking size_t ... but the underlying backend function only accepts a
- * signed int32 length. So throw error if the given value overflows
- * int32.
- */
- if (len > (size_t) INT_MAX)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("argument of lo_write exceeds integer range\n"));
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- argv[1].isint = 0;
- argv[1].len = (int) len;
- argv[1].u.ptr = (int *) buf;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_write,
- &retval, &result_len, 1, argv, 2);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_lseek
- * change the current read or write location on a large object
- */
-int
-lo_lseek(PGconn *conn, int fd, int offset, int whence)
-{
- PQArgBlock argv[3];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- argv[1].isint = 1;
- argv[1].len = 4;
- argv[1].u.integer = offset;
-
- argv[2].isint = 1;
- argv[2].len = 4;
- argv[2].u.integer = whence;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,
- &retval, &result_len, 1, argv, 3);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_lseek64
- * change the current read or write location on a large object
- */
-pg_int64
-lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
-{
- PQArgBlock argv[3];
- PGresult *res;
- pg_int64 retval;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- if (conn->lobjfuncs->fn_lo_lseek64 == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_lseek64\n"));
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- offset = lo_hton64(offset);
- argv[1].isint = 0;
- argv[1].len = 8;
- argv[1].u.ptr = (int *) &offset;
-
- argv[2].isint = 1;
- argv[2].len = 4;
- argv[2].u.integer = whence;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64,
- (void *) &retval, &result_len, 0, argv, 3);
- if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
- {
- PQclear(res);
- return lo_ntoh64(retval);
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_creat
- * create a new large object
- * the mode is ignored (once upon a time it had a use)
- *
- * returns the oid of the large object created or
- * InvalidOid upon failure
- */
-Oid
-lo_creat(PGconn *conn, int mode)
-{
- PQArgBlock argv[1];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return InvalidOid;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = mode;
- res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return (Oid) retval;
- }
- else
- {
- PQclear(res);
- return InvalidOid;
- }
-}
-
-/*
- * lo_create
- * create a new large object
- * if lobjId isn't InvalidOid, it specifies the OID to (attempt to) create
- *
- * returns the oid of the large object created or
- * InvalidOid upon failure
- */
-Oid
-lo_create(PGconn *conn, Oid lobjId)
-{
- PQArgBlock argv[1];
- PGresult *res;
- int retval;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return InvalidOid;
- }
-
- /* Must check this on-the-fly because it's not there pre-8.1 */
- if (conn->lobjfuncs->fn_lo_create == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_create\n"));
- return InvalidOid;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = lobjId;
- res = PQfn(conn, conn->lobjfuncs->fn_lo_create,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return (Oid) retval;
- }
- else
- {
- PQclear(res);
- return InvalidOid;
- }
-}
-
-
-/*
- * lo_tell
- * returns the current seek location of the large object
- */
-int
-lo_tell(PGconn *conn, int fd)
-{
- int retval;
- PQArgBlock argv[1];
- PGresult *res;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_tell64
- * returns the current seek location of the large object
- */
-pg_int64
-lo_tell64(PGconn *conn, int fd)
-{
- pg_int64 retval;
- PQArgBlock argv[1];
- PGresult *res;
- int result_len;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- if (conn->lobjfuncs->fn_lo_tell64 == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_tell64\n"));
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = fd;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_tell64,
- (void *) &retval, &result_len, 0, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
- {
- PQclear(res);
- return lo_ntoh64(retval);
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_unlink
- * delete a file
- */
-
-int
-lo_unlink(PGconn *conn, Oid lobjId)
-{
- PQArgBlock argv[1];
- PGresult *res;
- int result_len;
- int retval;
-
- if (conn == NULL || conn->lobjfuncs == NULL)
- {
- if (lo_initialize(conn) < 0)
- return -1;
- }
-
- argv[0].isint = 1;
- argv[0].len = 4;
- argv[0].u.integer = lobjId;
-
- res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,
- &retval, &result_len, 1, argv, 1);
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- PQclear(res);
- return retval;
- }
- else
- {
- PQclear(res);
- return -1;
- }
-}
-
-/*
- * lo_import -
- * imports a file as an (inversion) large object.
- *
- * returns the oid of that object upon success,
- * returns InvalidOid upon failure
- */
-
-Oid
-lo_import(PGconn *conn, const char *filename)
-{
- return lo_import_internal(conn, filename, InvalidOid);
-}
-
-/*
- * lo_import_with_oid -
- * imports a file as an (inversion) large object.
- * large object id can be specified.
- *
- * returns the oid of that object upon success,
- * returns InvalidOid upon failure
- */
-
-Oid
-lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId)
-{
- return lo_import_internal(conn, filename, lobjId);
-}
-
-static Oid
-lo_import_internal(PGconn *conn, const char *filename, Oid oid)
-{
- int fd;
- int nbytes,
- tmp;
- char buf[LO_BUFSIZE];
- Oid lobjOid;
- int lobj;
- char sebuf[256];
-
- /*
- * open the file to be read in
- */
- fd = open(filename, O_RDONLY | PG_BINARY, 0666);
- if (fd < 0)
- { /* error */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not open file \"%s\": %s\n"),
- filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
- return InvalidOid;
- }
-
- /*
- * create an inversion object
- */
- if (oid == InvalidOid)
- lobjOid = lo_creat(conn, INV_READ | INV_WRITE);
- else
- lobjOid = lo_create(conn, oid);
-
- if (lobjOid == InvalidOid)
- {
- /* we assume lo_create() already set a suitable error message */
- (void) close(fd);
- return InvalidOid;
- }
-
- lobj = lo_open(conn, lobjOid, INV_WRITE);
- if (lobj == -1)
- {
- /* we assume lo_open() already set a suitable error message */
- (void) close(fd);
- return InvalidOid;
- }
-
- /*
- * read in from the file and write to the large object
- */
- while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)
- {
- tmp = lo_write(conn, lobj, buf, nbytes);
- if (tmp != nbytes)
- {
- /*
- * If lo_write() failed, we are now in an aborted transaction so
- * there's no need for lo_close(); furthermore, if we tried it
- * we'd overwrite the useful error result with a useless one. So
- * just nail the doors shut and get out of town.
- */
- (void) close(fd);
- return InvalidOid;
- }
- }
-
- if (nbytes < 0)
- {
- /* We must do lo_close before setting the errorMessage */
- int save_errno = errno;
-
- (void) lo_close(conn, lobj);
- (void) close(fd);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not read from file \"%s\": %s\n"),
- filename,
- pqStrerror(save_errno, sebuf, sizeof(sebuf)));
- return InvalidOid;
- }
-
- (void) close(fd);
-
- if (lo_close(conn, lobj) != 0)
- {
- /* we assume lo_close() already set a suitable error message */
- return InvalidOid;
- }
-
- return lobjOid;
-}
-
-/*
- * lo_export -
- * exports an (inversion) large object.
- * returns -1 upon failure, 1 if OK
- */
-int
-lo_export(PGconn *conn, Oid lobjId, const char *filename)
-{
- int result = 1;
- int fd;
- int nbytes,
- tmp;
- char buf[LO_BUFSIZE];
- int lobj;
- char sebuf[256];
-
- /*
- * open the large object.
- */
- lobj = lo_open(conn, lobjId, INV_READ);
- if (lobj == -1)
- {
- /* we assume lo_open() already set a suitable error message */
- return -1;
- }
-
- /*
- * create the file to be written to
- */
- fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
- if (fd < 0)
- {
- /* We must do lo_close before setting the errorMessage */
- int save_errno = errno;
-
- (void) lo_close(conn, lobj);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not open file \"%s\": %s\n"),
- filename,
- pqStrerror(save_errno, sebuf, sizeof(sebuf)));
- return -1;
- }
-
- /*
- * read in from the large object and write to the file
- */
- while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)
- {
- tmp = write(fd, buf, nbytes);
- if (tmp != nbytes)
- {
- /* We must do lo_close before setting the errorMessage */
- int save_errno = errno;
-
- (void) lo_close(conn, lobj);
- (void) close(fd);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not write to file \"%s\": %s\n"),
- filename,
- pqStrerror(save_errno, sebuf, sizeof(sebuf)));
- return -1;
- }
- }
-
- /*
- * If lo_read() failed, we are now in an aborted transaction so there's no
- * need for lo_close(); furthermore, if we tried it we'd overwrite the
- * useful error result with a useless one. So skip lo_close() if we got a
- * failure result.
- */
- if (nbytes < 0 ||
- lo_close(conn, lobj) != 0)
- {
- /* assume lo_read() or lo_close() left a suitable error message */
- result = -1;
- }
-
- /* if we already failed, don't overwrite that msg with a close error */
- if (close(fd) && result >= 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not write to file \"%s\": %s\n"),
- filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
- result = -1;
- }
-
- return result;
-}
-
-
-/*
- * lo_initialize
- *
- * Initialize the large object interface for an existing connection.
- * We ask the backend about the functions OID's in pg_proc for all
- * functions that are required for large object operations.
- */
-static int
-lo_initialize(PGconn *conn)
-{
- PGresult *res;
- PGlobjfuncs *lobjfuncs;
- int n;
- const char *query;
- const char *fname;
- Oid foid;
-
- if (!conn)
- return -1;
-
- /*
- * Allocate the structure to hold the functions OID's
- */
- lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
- if (lobjfuncs == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return -1;
- }
- MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
-
- /*
- * Execute the query to get all the functions at once. In 7.3 and later
- * we need to be schema-safe. lo_create only exists in 8.1 and up.
- * lo_truncate only exists in 8.3 and up.
- */
- if (conn->sversion >= 70300)
- query = "select proname, oid from pg_catalog.pg_proc "
- "where proname in ("
- "'lo_open', "
- "'lo_close', "
- "'lo_creat', "
- "'lo_create', "
- "'lo_unlink', "
- "'lo_lseek', "
- "'lo_lseek64', "
- "'lo_tell', "
- "'lo_tell64', "
- "'lo_truncate', "
- "'lo_truncate64', "
- "'loread', "
- "'lowrite') "
- "and pronamespace = (select oid from pg_catalog.pg_namespace "
- "where nspname = 'pg_catalog')";
- else
- query = "select proname, oid from pg_proc "
- "where proname = 'lo_open' "
- "or proname = 'lo_close' "
- "or proname = 'lo_creat' "
- "or proname = 'lo_unlink' "
- "or proname = 'lo_lseek' "
- "or proname = 'lo_tell' "
- "or proname = 'loread' "
- "or proname = 'lowrite'";
-
- res = PQexec(conn, query);
- if (res == NULL)
- {
- free(lobjfuncs);
- return -1;
- }
-
- if (res->resultStatus != PGRES_TUPLES_OK)
- {
- free(lobjfuncs);
- PQclear(res);
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("query to initialize large object functions did not return data\n"));
- return -1;
- }
-
- /*
- * Examine the result and put the OID's into the struct
- */
- for (n = 0; n < PQntuples(res); n++)
- {
- fname = PQgetvalue(res, n, 0);
- foid = (Oid) atoi(PQgetvalue(res, n, 1));
- if (strcmp(fname, "lo_open") == 0)
- lobjfuncs->fn_lo_open = foid;
- else if (strcmp(fname, "lo_close") == 0)
- lobjfuncs->fn_lo_close = foid;
- else if (strcmp(fname, "lo_creat") == 0)
- lobjfuncs->fn_lo_creat = foid;
- else if (strcmp(fname, "lo_create") == 0)
- lobjfuncs->fn_lo_create = foid;
- else if (strcmp(fname, "lo_unlink") == 0)
- lobjfuncs->fn_lo_unlink = foid;
- else if (strcmp(fname, "lo_lseek") == 0)
- lobjfuncs->fn_lo_lseek = foid;
- else if (strcmp(fname, "lo_lseek64") == 0)
- lobjfuncs->fn_lo_lseek64 = foid;
- else if (strcmp(fname, "lo_tell") == 0)
- lobjfuncs->fn_lo_tell = foid;
- else if (strcmp(fname, "lo_tell64") == 0)
- lobjfuncs->fn_lo_tell64 = foid;
- else if (strcmp(fname, "lo_truncate") == 0)
- lobjfuncs->fn_lo_truncate = foid;
- else if (strcmp(fname, "lo_truncate64") == 0)
- lobjfuncs->fn_lo_truncate64 = foid;
- else if (strcmp(fname, "loread") == 0)
- lobjfuncs->fn_lo_read = foid;
- else if (strcmp(fname, "lowrite") == 0)
- lobjfuncs->fn_lo_write = foid;
- }
-
- PQclear(res);
-
- /*
- * Finally check that we got all required large object interface functions
- * (ones that have been added later than the stone age are instead checked
- * only if used)
- */
- if (lobjfuncs->fn_lo_open == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_open\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_close == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_close\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_creat == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_creat\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_unlink == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_unlink\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_lseek == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_lseek\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_tell == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lo_tell\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_read == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function loread\n"));
- free(lobjfuncs);
- return -1;
- }
- if (lobjfuncs->fn_lo_write == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("cannot determine OID of function lowrite\n"));
- free(lobjfuncs);
- return -1;
- }
-
- /*
- * Put the structure into the connection control
- */
- conn->lobjfuncs = lobjfuncs;
- return 0;
-}
-
-/*
- * lo_hton64
- * converts a 64-bit integer from host byte order to network byte order
- */
-static pg_int64
-lo_hton64(pg_int64 host64)
-{
- union
- {
- pg_int64 i64;
- uint32 i32[2];
- } swap;
- uint32 t;
-
- /* High order half first, since we're doing MSB-first */
- t = (uint32) (host64 >> 32);
- swap.i32[0] = htonl(t);
-
- /* Now the low order half */
- t = (uint32) host64;
- swap.i32[1] = htonl(t);
-
- return swap.i64;
-}
-
-/*
- * lo_ntoh64
- * converts a 64-bit integer from network byte order to host byte order
- */
-static pg_int64
-lo_ntoh64(pg_int64 net64)
-{
- union
- {
- pg_int64 i64;
- uint32 i32[2];
- } swap;
- pg_int64 result;
-
- swap.i64 = net64;
-
- result = (uint32) ntohl(swap.i32[0]);
- result <<= 32;
- result |= (uint32) ntohl(swap.i32[1]);
-
- return result;
-}
diff --git a/libpq/fe-misc.c b/libpq/fe-misc.c
deleted file mode 100644
index 32da8ca..0000000
--- a/libpq/fe-misc.c
+++ /dev/null
@@ -1,1267 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * FILE
- * fe-misc.c
- *
- * DESCRIPTION
- * miscellaneous useful functions
- *
- * The communication routines here are analogous to the ones in
- * backend/libpq/pqcomm.c and backend/libpq/pqcomprim.c, but operate
- * in the considerably different environment of the frontend libpq.
- * In particular, we work with a bare nonblock-mode socket, rather than
- * a stdio stream, so that we can avoid unwanted blocking of the application.
- *
- * XXX: MOVE DEBUG PRINTOUT TO HIGHER LEVEL. As is, block and restart
- * will cause repeat printouts.
- *
- * We must speak the same transmitted data representations as the backend
- * routines.
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-misc.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres_fe.h"
-
-#include <signal.h>
-#include <time.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <unistd.h>
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-#include "mb/pg_wchar.h"
-#include "pg_config_paths.h"
-
-
-static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn);
-static int pqSendSome(PGconn *conn, int len);
-static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
- time_t end_time);
-static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
-
-/*
- * PQlibVersion: return the libpq version number
- */
-int
-PQlibVersion(void)
-{
- return PG_VERSION_NUM;
-}
-
-/*
- * fputnbytes: print exactly N bytes to a file
- *
- * We avoid using %.*s here because it can misbehave if the data
- * is not valid in what libc thinks is the prevailing encoding.
- */
-static void
-fputnbytes(FILE *f, const char *str, size_t n)
-{
- while (n-- > 0)
- fputc(*str++, f);
-}
-
-
-/*
- * pqGetc: get 1 character from the connection
- *
- * All these routines return 0 on success, EOF on error.
- * Note that for the Get routines, EOF only means there is not enough
- * data in the buffer, not that there is necessarily a hard error.
- */
-int
-pqGetc(char *result, PGconn *conn)
-{
- if (conn->inCursor >= conn->inEnd)
- return EOF;
-
- *result = conn->inBuffer[conn->inCursor++];
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend> %c\n", *result);
-
- return 0;
-}
-
-
-/*
- * pqPutc: write 1 char to the current message
- */
-int
-pqPutc(char c, PGconn *conn)
-{
- if (pqPutMsgBytes(&c, 1, conn))
- return EOF;
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> %c\n", c);
-
- return 0;
-}
-
-
-/*
- * pqGets[_append]:
- * get a null-terminated string from the connection,
- * and store it in an expansible PQExpBuffer.
- * If we run out of memory, all of the string is still read,
- * but the excess characters are silently discarded.
- */
-static int
-pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
-{
- /* Copy conn data to locals for faster search loop */
- char *inBuffer = conn->inBuffer;
- int inCursor = conn->inCursor;
- int inEnd = conn->inEnd;
- int slen;
-
- while (inCursor < inEnd && inBuffer[inCursor])
- inCursor++;
-
- if (inCursor >= inEnd)
- return EOF;
-
- slen = inCursor - conn->inCursor;
-
- if (resetbuffer)
- resetPQExpBuffer(buf);
-
- appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen);
-
- conn->inCursor = ++inCursor;
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend> \"%s\"\n",
- buf->data);
-
- return 0;
-}
-
-int
-pqGets(PQExpBuffer buf, PGconn *conn)
-{
- return pqGets_internal(buf, conn, true);
-}
-
-int
-pqGets_append(PQExpBuffer buf, PGconn *conn)
-{
- return pqGets_internal(buf, conn, false);
-}
-
-
-/*
- * pqPuts: write a null-terminated string to the current message
- */
-int
-pqPuts(const char *s, PGconn *conn)
-{
- if (pqPutMsgBytes(s, strlen(s) + 1, conn))
- return EOF;
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
-
- return 0;
-}
-
-/*
- * pqGetnchar:
- * get a string of exactly len bytes in buffer s, no null termination
- */
-int
-pqGetnchar(char *s, size_t len, PGconn *conn)
-{
- if (len > (size_t) (conn->inEnd - conn->inCursor))
- return EOF;
-
- memcpy(s, conn->inBuffer + conn->inCursor, len);
- /* no terminating null */
-
- conn->inCursor += len;
-
- if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
- fputnbytes(conn->Pfdebug, s, len);
- fprintf(conn->Pfdebug, "\n");
- }
-
- return 0;
-}
-
-/*
- * pqSkipnchar:
- * skip over len bytes in input buffer.
- *
- * Note: this is primarily useful for its debug output, which should
- * be exactly the same as for pqGetnchar. We assume the data in question
- * will actually be used, but just isn't getting copied anywhere as yet.
- */
-int
-pqSkipnchar(size_t len, PGconn *conn)
-{
- if (len > (size_t) (conn->inEnd - conn->inCursor))
- return EOF;
-
- if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
- fputnbytes(conn->Pfdebug, conn->inBuffer + conn->inCursor, len);
- fprintf(conn->Pfdebug, "\n");
- }
-
- conn->inCursor += len;
-
- return 0;
-}
-
-/*
- * pqPutnchar:
- * write exactly len bytes to the current message
- */
-int
-pqPutnchar(const char *s, size_t len, PGconn *conn)
-{
- if (pqPutMsgBytes(s, len, conn))
- return EOF;
-
- if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "To backend> ");
- fputnbytes(conn->Pfdebug, s, len);
- fprintf(conn->Pfdebug, "\n");
- }
-
- return 0;
-}
-
-/*
- * pqGetInt
- * read a 2 or 4 byte integer and convert from network byte order
- * to local byte order
- */
-int
-pqGetInt(int *result, size_t bytes, PGconn *conn)
-{
- uint16 tmp2;
- uint32 tmp4;
-
- switch (bytes)
- {
- case 2:
- if (conn->inCursor + 2 > conn->inEnd)
- return EOF;
- memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
- conn->inCursor += 2;
- *result = (int) ntohs(tmp2);
- break;
- case 4:
- if (conn->inCursor + 4 > conn->inEnd)
- return EOF;
- memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
- conn->inCursor += 4;
- *result = (int) ntohl(tmp4);
- break;
- default:
- pqInternalNotice(&conn->noticeHooks,
- "integer of size %lu not supported by pqGetInt",
- (unsigned long) bytes);
- return EOF;
- }
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
-
- return 0;
-}
-
-/*
- * pqPutInt
- * write an integer of 2 or 4 bytes, converting from host byte order
- * to network byte order.
- */
-int
-pqPutInt(int value, size_t bytes, PGconn *conn)
-{
- uint16 tmp2;
- uint32 tmp4;
-
- switch (bytes)
- {
- case 2:
- tmp2 = htons((uint16) value);
- if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
- return EOF;
- break;
- case 4:
- tmp4 = htonl((uint32) value);
- if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
- return EOF;
- break;
- default:
- pqInternalNotice(&conn->noticeHooks,
- "integer of size %lu not supported by pqPutInt",
- (unsigned long) bytes);
- return EOF;
- }
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
-
- return 0;
-}
-
-/*
- * Make sure conn's output buffer can hold bytes_needed bytes (caller must
- * include already-stored data into the value!)
- *
- * Returns 0 on success, EOF if failed to enlarge buffer
- */
-int
-pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
-{
- int newsize = conn->outBufSize;
- char *newbuf;
-
- /* Quick exit if we have enough space */
- if (bytes_needed <= (size_t) newsize)
- return 0;
-
- /*
- * If we need to enlarge the buffer, we first try to double it in size; if
- * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
- * the malloc pool by repeated small enlargements.
- *
- * Note: tests for newsize > 0 are to catch integer overflow.
- */
- do
- {
- newsize *= 2;
- } while (newsize > 0 && bytes_needed > (size_t) newsize);
-
- if (newsize > 0 && bytes_needed <= (size_t) newsize)
- {
- newbuf = realloc(conn->outBuffer, newsize);
- if (newbuf)
- {
- /* realloc succeeded */
- conn->outBuffer = newbuf;
- conn->outBufSize = newsize;
- return 0;
- }
- }
-
- newsize = conn->outBufSize;
- do
- {
- newsize += 8192;
- } while (newsize > 0 && bytes_needed > (size_t) newsize);
-
- if (newsize > 0 && bytes_needed <= (size_t) newsize)
- {
- newbuf = realloc(conn->outBuffer, newsize);
- if (newbuf)
- {
- /* realloc succeeded */
- conn->outBuffer = newbuf;
- conn->outBufSize = newsize;
- return 0;
- }
- }
-
- /* realloc failed. Probably out of memory */
- printfPQExpBuffer(&conn->errorMessage,
- "cannot allocate memory for output buffer\n");
- return EOF;
-}
-
-/*
- * Make sure conn's input buffer can hold bytes_needed bytes (caller must
- * include already-stored data into the value!)
- *
- * Returns 0 on success, EOF if failed to enlarge buffer
- */
-int
-pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
-{
- int newsize = conn->inBufSize;
- char *newbuf;
-
- /* Quick exit if we have enough space */
- if (bytes_needed <= (size_t) newsize)
- return 0;
-
- /*
- * Before concluding that we need to enlarge the buffer, left-justify
- * whatever is in it and recheck. The caller's value of bytes_needed
- * includes any data to the left of inStart, but we can delete that in
- * preference to enlarging the buffer. It's slightly ugly to have this
- * function do this, but it's better than making callers worry about it.
- */
- bytes_needed -= conn->inStart;
-
- if (conn->inStart < conn->inEnd)
- {
- if (conn->inStart > 0)
- {
- memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
- conn->inEnd - conn->inStart);
- conn->inEnd -= conn->inStart;
- conn->inCursor -= conn->inStart;
- conn->inStart = 0;
- }
- }
- else
- {
- /* buffer is logically empty, reset it */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- }
-
- /* Recheck whether we have enough space */
- if (bytes_needed <= (size_t) newsize)
- return 0;
-
- /*
- * If we need to enlarge the buffer, we first try to double it in size; if
- * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
- * the malloc pool by repeated small enlargements.
- *
- * Note: tests for newsize > 0 are to catch integer overflow.
- */
- do
- {
- newsize *= 2;
- } while (newsize > 0 && bytes_needed > (size_t) newsize);
-
- if (newsize > 0 && bytes_needed <= (size_t) newsize)
- {
- newbuf = realloc(conn->inBuffer, newsize);
- if (newbuf)
- {
- /* realloc succeeded */
- conn->inBuffer = newbuf;
- conn->inBufSize = newsize;
- return 0;
- }
- }
-
- newsize = conn->inBufSize;
- do
- {
- newsize += 8192;
- } while (newsize > 0 && bytes_needed > (size_t) newsize);
-
- if (newsize > 0 && bytes_needed <= (size_t) newsize)
- {
- newbuf = realloc(conn->inBuffer, newsize);
- if (newbuf)
- {
- /* realloc succeeded */
- conn->inBuffer = newbuf;
- conn->inBufSize = newsize;
- return 0;
- }
- }
-
- /* realloc failed. Probably out of memory */
- printfPQExpBuffer(&conn->errorMessage,
- "cannot allocate memory for input buffer\n");
- return EOF;
-}
-
-/*
- * pqPutMsgStart: begin construction of a message to the server
- *
- * msg_type is the message type byte, or 0 for a message without type byte
- * (only startup messages have no type byte)
- *
- * force_len forces the message to have a length word; otherwise, we add
- * a length word if protocol 3.
- *
- * Returns 0 on success, EOF on error
- *
- * The idea here is that we construct the message in conn->outBuffer,
- * beginning just past any data already in outBuffer (ie, at
- * outBuffer+outCount). We enlarge the buffer as needed to hold the message.
- * When the message is complete, we fill in the length word (if needed) and
- * then advance outCount past the message, making it eligible to send.
- *
- * The state variable conn->outMsgStart points to the incomplete message's
- * length word: it is either outCount or outCount+1 depending on whether
- * there is a type byte. If we are sending a message without length word
- * (pre protocol 3.0 only), then outMsgStart is -1. The state variable
- * conn->outMsgEnd is the end of the data collected so far.
- */
-int
-pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
-{
- int lenPos;
- int endPos;
-
- /* allow room for message type byte */
- if (msg_type)
- endPos = conn->outCount + 1;
- else
- endPos = conn->outCount;
-
- /* do we want a length word? */
- if (force_len || PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
- {
- lenPos = endPos;
- /* allow room for message length */
- endPos += 4;
- }
- else
- lenPos = -1;
-
- /* make sure there is room for message header */
- if (pqCheckOutBufferSpace(endPos, conn))
- return EOF;
- /* okay, save the message type byte if any */
- if (msg_type)
- conn->outBuffer[conn->outCount] = msg_type;
- /* set up the message pointers */
- conn->outMsgStart = lenPos;
- conn->outMsgEnd = endPos;
- /* length word, if needed, will be filled in by pqPutMsgEnd */
-
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> Msg %c\n",
- msg_type ? msg_type : ' ');
-
- return 0;
-}
-
-/*
- * pqPutMsgBytes: add bytes to a partially-constructed message
- *
- * Returns 0 on success, EOF on error
- */
-static int
-pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
-{
- /* make sure there is room for it */
- if (pqCheckOutBufferSpace(conn->outMsgEnd + len, conn))
- return EOF;
- /* okay, save the data */
- memcpy(conn->outBuffer + conn->outMsgEnd, buf, len);
- conn->outMsgEnd += len;
- /* no Pfdebug call here, caller should do it */
- return 0;
-}
-
-/*
- * pqPutMsgEnd: finish constructing a message and possibly send it
- *
- * Returns 0 on success, EOF on error
- *
- * We don't actually send anything here unless we've accumulated at least
- * 8K worth of data (the typical size of a pipe buffer on Unix systems).
- * This avoids sending small partial packets. The caller must use pqFlush
- * when it's important to flush all the data out to the server.
- */
-int
-pqPutMsgEnd(PGconn *conn)
-{
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
- conn->outMsgEnd - conn->outCount);
-
- /* Fill in length word if needed */
- if (conn->outMsgStart >= 0)
- {
- uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
-
- msgLen = htonl(msgLen);
- memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
- }
-
- /* Make message eligible to send */
- conn->outCount = conn->outMsgEnd;
-
- if (conn->outCount >= 8192)
- {
- int toSend = conn->outCount - (conn->outCount % 8192);
-
- if (pqSendSome(conn, toSend) < 0)
- return EOF;
- /* in nonblock mode, don't complain if unable to send it all */
- }
-
- return 0;
-}
-
-/* ----------
- * pqReadData: read more data, if any is available
- * Possible return values:
- * 1: successfully loaded at least one more byte
- * 0: no data is presently available, but no error detected
- * -1: error detected (including EOF = connection closure);
- * conn->errorMessage set
- * NOTE: callers must not assume that pointers or indexes into conn->inBuffer
- * remain valid across this call!
- * ----------
- */
-int
-pqReadData(PGconn *conn)
-{
- int someread = 0;
- int nread;
-
- if (conn->sock == PGINVALID_SOCKET)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("connection not open\n"));
- return -1;
- }
-
- /* Left-justify any data in the buffer to make room */
- if (conn->inStart < conn->inEnd)
- {
- if (conn->inStart > 0)
- {
- memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
- conn->inEnd - conn->inStart);
- conn->inEnd -= conn->inStart;
- conn->inCursor -= conn->inStart;
- conn->inStart = 0;
- }
- }
- else
- {
- /* buffer is logically empty, reset it */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- }
-
- /*
- * If the buffer is fairly full, enlarge it. We need to be able to enlarge
- * the buffer in case a single message exceeds the initial buffer size. We
- * enlarge before filling the buffer entirely so as to avoid asking the
- * kernel for a partial packet. The magic constant here should be large
- * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe
- * buffer size, so...
- */
- if (conn->inBufSize - conn->inEnd < 8192)
- {
- if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
- {
- /*
- * We don't insist that the enlarge worked, but we need some room
- */
- if (conn->inBufSize - conn->inEnd < 100)
- return -1; /* errorMessage already set */
- }
- }
-
- /* OK, try to read some data */
-retry3:
- nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
- conn->inBufSize - conn->inEnd);
- if (nread < 0)
- {
- if (SOCK_ERRNO == EINTR)
- goto retry3;
- /* Some systems return EAGAIN/EWOULDBLOCK for no data */
-#ifdef EAGAIN
- if (SOCK_ERRNO == EAGAIN)
- return someread;
-#endif
-#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- if (SOCK_ERRNO == EWOULDBLOCK)
- return someread;
-#endif
- /* We might get ECONNRESET here if using TCP and backend died */
-#ifdef ECONNRESET
- if (SOCK_ERRNO == ECONNRESET)
- goto definitelyFailed;
-#endif
- /* pqsecure_read set the error message for us */
- return -1;
- }
- if (nread > 0)
- {
- conn->inEnd += nread;
-
- /*
- * Hack to deal with the fact that some kernels will only give us back
- * 1 packet per recv() call, even if we asked for more and there is
- * more available. If it looks like we are reading a long message,
- * loop back to recv() again immediately, until we run out of data or
- * buffer space. Without this, the block-and-restart behavior of
- * libpq's higher levels leads to O(N^2) performance on long messages.
- *
- * Since we left-justified the data above, conn->inEnd gives the
- * amount of data already read in the current message. We consider
- * the message "long" once we have acquired 32k ...
- */
- if (conn->inEnd > 32768 &&
- (conn->inBufSize - conn->inEnd) >= 8192)
- {
- someread = 1;
- goto retry3;
- }
- return 1;
- }
-
- if (someread)
- return 1; /* got a zero read after successful tries */
-
- /*
- * A return value of 0 could mean just that no data is now available, or
- * it could mean EOF --- that is, the server has closed the connection.
- * Since we have the socket in nonblock mode, the only way to tell the
- * difference is to see if select() is saying that the file is ready.
- * Grumble. Fortunately, we don't expect this path to be taken much,
- * since in normal practice we should not be trying to read data unless
- * the file selected for reading already.
- *
- * In SSL mode it's even worse: SSL_read() could say WANT_READ and then
- * data could arrive before we make the pqReadReady() test, but the second
- * SSL_read() could still say WANT_READ because the data received was not
- * a complete SSL record. So we must play dumb and assume there is more
- * data, relying on the SSL layer to detect true EOF.
- */
-
-#ifdef USE_SSL
- if (conn->ssl_in_use)
- return 0;
-#endif
-
- switch (pqReadReady(conn))
- {
- case 0:
- /* definitely no data available */
- return 0;
- case 1:
- /* ready for read */
- break;
- default:
- /* we override pqReadReady's message with something more useful */
- goto definitelyEOF;
- }
-
- /*
- * Still not sure that it's EOF, because some data could have just
- * arrived.
- */
-retry4:
- nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
- conn->inBufSize - conn->inEnd);
- if (nread < 0)
- {
- if (SOCK_ERRNO == EINTR)
- goto retry4;
- /* Some systems return EAGAIN/EWOULDBLOCK for no data */
-#ifdef EAGAIN
- if (SOCK_ERRNO == EAGAIN)
- return 0;
-#endif
-#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- if (SOCK_ERRNO == EWOULDBLOCK)
- return 0;
-#endif
- /* We might get ECONNRESET here if using TCP and backend died */
-#ifdef ECONNRESET
- if (SOCK_ERRNO == ECONNRESET)
- goto definitelyFailed;
-#endif
- /* pqsecure_read set the error message for us */
- return -1;
- }
- if (nread > 0)
- {
- conn->inEnd += nread;
- return 1;
- }
-
- /*
- * OK, we are getting a zero read even though select() says ready. This
- * means the connection has been closed. Cope.
- */
-definitelyEOF:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
-
- /* Come here if lower-level code already set a suitable errorMessage */
-definitelyFailed:
- /* Do *not* drop any already-read data; caller still wants it */
- pqDropConnection(conn, false);
- conn->status = CONNECTION_BAD; /* No more connection to backend */
- return -1;
-}
-
-/*
- * pqSendSome: send data waiting in the output buffer.
- *
- * len is how much to try to send (typically equal to outCount, but may
- * be less).
- *
- * Return 0 on success, -1 on failure and 1 when not all data could be sent
- * because the socket would block and the connection is non-blocking.
- */
-static int
-pqSendSome(PGconn *conn, int len)
-{
- char *ptr = conn->outBuffer;
- int remaining = conn->outCount;
- int result = 0;
-
- if (conn->sock == PGINVALID_SOCKET)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("connection not open\n"));
- /* Discard queued data; no chance it'll ever be sent */
- conn->outCount = 0;
- return -1;
- }
-
- /* while there's still data to send */
- while (len > 0)
- {
- int sent;
-
-#ifndef WIN32
- sent = pqsecure_write(conn, ptr, len);
-#else
-
- /*
- * Windows can fail on large sends, per KB article Q201213. The
- * failure-point appears to be different in different versions of
- * Windows, but 64k should always be safe.
- */
- sent = pqsecure_write(conn, ptr, Min(len, 65536));
-#endif
-
- if (sent < 0)
- {
- /* Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble */
- switch (SOCK_ERRNO)
- {
-#ifdef EAGAIN
- case EAGAIN:
- break;
-#endif
-#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- case EWOULDBLOCK:
- break;
-#endif
- case EINTR:
- continue;
-
- default:
- /* pqsecure_write set the error message for us */
-
- /*
- * We used to close the socket here, but that's a bad idea
- * since there might be unread data waiting (typically, a
- * NOTICE message from the backend telling us it's
- * committing hara-kiri...). Leave the socket open until
- * pqReadData finds no more data can be read. But abandon
- * attempt to send data.
- */
- conn->outCount = 0;
- return -1;
- }
- }
- else
- {
- ptr += sent;
- len -= sent;
- remaining -= sent;
- }
-
- if (len > 0)
- {
- /*
- * We didn't send it all, wait till we can send more.
- *
- * There are scenarios in which we can't send data because the
- * communications channel is full, but we cannot expect the server
- * to clear the channel eventually because it's blocked trying to
- * send data to us. (This can happen when we are sending a large
- * amount of COPY data, and the server has generated lots of
- * NOTICE responses.) To avoid a deadlock situation, we must be
- * prepared to accept and buffer incoming data before we try
- * again. Furthermore, it is possible that such incoming data
- * might not arrive until after we've gone to sleep. Therefore,
- * we wait for either read ready or write ready.
- *
- * In non-blocking mode, we don't wait here directly, but return 1
- * to indicate that data is still pending. The caller should wait
- * for both read and write ready conditions, and call
- * PQconsumeInput() on read ready, but just in case it doesn't, we
- * call pqReadData() ourselves before returning. That's not
- * enough if the data has not arrived yet, but it's the best we
- * can do, and works pretty well in practice. (The documentation
- * used to say that you only need to wait for write-ready, so
- * there are still plenty of applications like that out there.)
- */
- if (pqReadData(conn) < 0)
- {
- result = -1; /* error message already set up */
- break;
- }
-
- if (pqIsnonblocking(conn))
- {
- result = 1;
- break;
- }
-
- if (pqWait(TRUE, TRUE, conn))
- {
- result = -1;
- break;
- }
- }
- }
-
- /* shift the remaining contents of the buffer */
- if (remaining > 0)
- memmove(conn->outBuffer, ptr, remaining);
- conn->outCount = remaining;
-
- return result;
-}
-
-
-/*
- * pqFlush: send any data waiting in the output buffer
- *
- * Return 0 on success, -1 on failure and 1 when not all data could be sent
- * because the socket would block and the connection is non-blocking.
- */
-int
-pqFlush(PGconn *conn)
-{
- if (conn->Pfdebug)
- fflush(conn->Pfdebug);
-
- if (conn->outCount > 0)
- return pqSendSome(conn, conn->outCount);
-
- return 0;
-}
-
-
-/*
- * pqWait: wait until we can read or write the connection socket
- *
- * JAB: If SSL enabled and used and forRead, buffered bytes short-circuit the
- * call to select().
- *
- * We also stop waiting and return if the kernel flags an exception condition
- * on the socket. The actual error condition will be detected and reported
- * when the caller tries to read or write the socket.
- */
-int
-pqWait(int forRead, int forWrite, PGconn *conn)
-{
- return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
-}
-
-/*
- * pqWaitTimed: wait, but not past finish_time.
- *
- * If finish_time is exceeded then we return failure (EOF). This is like
- * the response for a kernel exception because we don't want the caller
- * to try to read/write in that case.
- *
- * finish_time = ((time_t) -1) disables the wait limit.
- */
-int
-pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
-{
- int result;
-
- result = pqSocketCheck(conn, forRead, forWrite, finish_time);
-
- if (result < 0)
- return EOF; /* errorMessage is already set */
-
- if (result == 0)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("timeout expired\n"));
- return EOF;
- }
-
- return 0;
-}
-
-/*
- * pqReadReady: is select() saying the file is ready to read?
- * Returns -1 on failure, 0 if not ready, 1 if ready.
- */
-int
-pqReadReady(PGconn *conn)
-{
- return pqSocketCheck(conn, 1, 0, (time_t) 0);
-}
-
-/*
- * pqWriteReady: is select() saying the file is ready to write?
- * Returns -1 on failure, 0 if not ready, 1 if ready.
- */
-int
-pqWriteReady(PGconn *conn)
-{
- return pqSocketCheck(conn, 0, 1, (time_t) 0);
-}
-
-/*
- * Checks a socket, using poll or select, for data to be read, written,
- * or both. Returns >0 if one or more conditions are met, 0 if it timed
- * out, -1 if an error occurred.
- *
- * If SSL is in use, the SSL buffer is checked prior to checking the socket
- * for read data directly.
- */
-static int
-pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
-{
- int result;
-
- if (!conn)
- return -1;
- if (conn->sock == PGINVALID_SOCKET)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid socket\n"));
- return -1;
- }
-
-#ifdef USE_SSL
- /* Check for SSL library buffering read bytes */
- if (forRead && conn->ssl_in_use && pgtls_read_pending(conn) > 0)
- {
- /* short-circuit the select */
- return 1;
- }
-#endif
-
- /* We will retry as long as we get EINTR */
- do
- result = pqSocketPoll(conn->sock, forRead, forWrite, end_time);
- while (result < 0 && SOCK_ERRNO == EINTR);
-
- if (result < 0)
- {
- char sebuf[256];
-
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("select() failed: %s\n"),
- SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
- }
-
- return result;
-}
-
-
-/*
- * Check a file descriptor for read and/or write data, possibly waiting.
- * If neither forRead nor forWrite are set, immediately return a timeout
- * condition (without waiting). Return >0 if condition is met, 0
- * if a timeout occurred, -1 if an error or interrupt occurred.
- *
- * Timeout is infinite if end_time is -1. Timeout is immediate (no blocking)
- * if end_time is 0 (or indeed, any time before now).
- */
-static int
-pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
-{
- /* We use poll(2) if available, otherwise select(2) */
-#ifdef HAVE_POLL
- struct pollfd input_fd;
- int timeout_ms;
-
- if (!forRead && !forWrite)
- return 0;
-
- input_fd.fd = sock;
- input_fd.events = POLLERR;
- input_fd.revents = 0;
-
- if (forRead)
- input_fd.events |= POLLIN;
- if (forWrite)
- input_fd.events |= POLLOUT;
-
- /* Compute appropriate timeout interval */
- if (end_time == ((time_t) -1))
- timeout_ms = -1;
- else
- {
- time_t now = time(NULL);
-
- if (end_time > now)
- timeout_ms = (end_time - now) * 1000;
- else
- timeout_ms = 0;
- }
-
- return poll(&input_fd, 1, timeout_ms);
-#else /* !HAVE_POLL */
-
- fd_set input_mask;
- fd_set output_mask;
- fd_set except_mask;
- struct timeval timeout;
- struct timeval *ptr_timeout;
-
- if (!forRead && !forWrite)
- return 0;
-
- FD_ZERO(&input_mask);
- FD_ZERO(&output_mask);
- FD_ZERO(&except_mask);
- if (forRead)
- FD_SET(sock, &input_mask);
-
- if (forWrite)
- FD_SET(sock, &output_mask);
- FD_SET(sock, &except_mask);
-
- /* Compute appropriate timeout interval */
- if (end_time == ((time_t) -1))
- ptr_timeout = NULL;
- else
- {
- time_t now = time(NULL);
-
- if (end_time > now)
- timeout.tv_sec = end_time - now;
- else
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- ptr_timeout = &timeout;
- }
-
- return select(sock + 1, &input_mask, &output_mask,
- &except_mask, ptr_timeout);
-#endif /* HAVE_POLL */
-}
-
-
-/*
- * A couple of "miscellaneous" multibyte related functions. They used
- * to be in fe-print.c but that file is doomed.
- */
-
-/*
- * returns the byte length of the character beginning at s, using the
- * specified encoding.
- */
-int
-PQmblen(const char *s, int encoding)
-{
- return pg_encoding_mblen(encoding, s);
-}
-
-/*
- * returns the display length of the character beginning at s, using the
- * specified encoding.
- */
-int
-PQdsplen(const char *s, int encoding)
-{
- return pg_encoding_dsplen(encoding, s);
-}
-
-/*
- * Get encoding id from environment variable PGCLIENTENCODING.
- */
-int
-PQenv2encoding(void)
-{
- char *str;
- int encoding = PG_SQL_ASCII;
-
- str = getenv("PGCLIENTENCODING");
- if (str && *str != '\0')
- {
- encoding = pg_char_to_encoding(str);
- if (encoding < 0)
- encoding = PG_SQL_ASCII;
- }
- return encoding;
-}
-
-
-#ifdef ENABLE_NLS
-
-static void
-libpq_binddomain()
-{
- static bool already_bound = false;
-
- if (!already_bound)
- {
- /* bindtextdomain() does not preserve errno */
-#ifdef WIN32
- int save_errno = GetLastError();
-#else
- int save_errno = errno;
-#endif
- const char *ldir;
-
- already_bound = true;
- /* No relocatable lookup here because the binary could be anywhere */
- ldir = getenv("PGLOCALEDIR");
- if (!ldir)
- ldir = LOCALEDIR;
- bindtextdomain(PG_TEXTDOMAIN("libpq"), ldir);
-#ifdef WIN32
- SetLastError(save_errno);
-#else
- errno = save_errno;
-#endif
- }
-}
-
-char *
-libpq_gettext(const char *msgid)
-{
- libpq_binddomain();
- return dgettext(PG_TEXTDOMAIN("libpq"), msgid);
-}
-
-char *
-libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n)
-{
- libpq_binddomain();
- return dngettext(PG_TEXTDOMAIN("libpq"), msgid, msgid_plural, n);
-}
-
-#endif /* ENABLE_NLS */
diff --git a/libpq/fe-print.c b/libpq/fe-print.c
deleted file mode 100644
index e596a51..0000000
--- a/libpq/fe-print.c
+++ /dev/null
@@ -1,761 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-print.c
- * functions for pretty-printing query results
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * These functions were formerly part of fe-exec.c, but they
- * didn't really belong there.
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-print.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include <signal.h>
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <unistd.h>
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-#else
-#ifndef WIN32
-#include <sys/termios.h>
-#endif
-#endif
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-
-
-static void do_field(const PQprintOpt *po, const PGresult *res,
- const int i, const int j, const int fs_len,
- char **fields,
- const int nFields, const char **fieldNames,
- unsigned char *fieldNotNum, int *fieldMax,
- const int fieldMaxLen, FILE *fout);
-static char *do_header(FILE *fout, const PQprintOpt *po, const int nFields,
- int *fieldMax, const char **fieldNames, unsigned char *fieldNotNum,
- const int fs_len, const PGresult *res);
-static void output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
- unsigned char *fieldNotNum, int *fieldMax, char *border,
- const int row_index);
-static void fill(int length, int max, char filler, FILE *fp);
-
-/*
- * PQprint()
- *
- * Format results of a query for printing.
- *
- * PQprintOpt is a typedef (structure) that contains
- * various flags and options. consult libpq-fe.h for
- * details
- *
- * This function should probably be removed sometime since psql
- * doesn't use it anymore. It is unclear to what extent this is used
- * by external clients, however.
- */
-void
-PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
-{
- int nFields;
-
- nFields = PQnfields(res);
-
- if (nFields > 0)
- { /* only print rows with at least 1 field. */
- int i,
- j;
- int nTups;
- int *fieldMax = NULL; /* in case we don't use them */
- unsigned char *fieldNotNum = NULL;
- char *border = NULL;
- char **fields = NULL;
- const char **fieldNames;
- int fieldMaxLen = 0;
- int numFieldName;
- int fs_len = strlen(po->fieldSep);
- int total_line_length = 0;
- int usePipe = 0;
- char *pagerenv;
-
-#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
- sigset_t osigset;
- bool sigpipe_masked = false;
- bool sigpipe_pending;
-#endif
-#if !defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
- pqsigfunc oldsigpipehandler = NULL;
-#endif
-
-#ifdef TIOCGWINSZ
- struct winsize screen_size;
-#else
- struct winsize
- {
- int ws_row;
- int ws_col;
- } screen_size;
-#endif
-
- nTups = PQntuples(res);
- if (!(fieldNames = (const char **) calloc(nFields, sizeof(char *))))
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
- if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1)))
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
- if (!(fieldMax = (int *) calloc(nFields, sizeof(int))))
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
- for (numFieldName = 0;
- po->fieldName && po->fieldName[numFieldName];
- numFieldName++)
- ;
- for (j = 0; j < nFields; j++)
- {
- int len;
- const char *s = (j < numFieldName && po->fieldName[j][0]) ?
- po->fieldName[j] : PQfname(res, j);
-
- fieldNames[j] = s;
- len = s ? strlen(s) : 0;
- fieldMax[j] = len;
- len += fs_len;
- if (len > fieldMaxLen)
- fieldMaxLen = len;
- total_line_length += len;
- }
-
- total_line_length += nFields * strlen(po->fieldSep) + 1;
-
- if (fout == NULL)
- fout = stdout;
- if (po->pager && fout == stdout && isatty(fileno(stdin)) &&
- isatty(fileno(stdout)))
- {
- /*
- * If we think there'll be more than one screen of output, try to
- * pipe to the pager program.
- */
-#ifdef TIOCGWINSZ
- if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
- screen_size.ws_col == 0 ||
- screen_size.ws_row == 0)
- {
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
- }
-#else
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
-#endif
- pagerenv = getenv("PAGER");
- /* if PAGER is unset, empty or all-white-space, don't use pager */
- if (pagerenv != NULL &&
- strspn(pagerenv, " \t\r\n") != strlen(pagerenv) &&
- !po->html3 &&
- ((po->expanded &&
- nTups * (nFields + 1) >= screen_size.ws_row) ||
- (!po->expanded &&
- nTups * (total_line_length / screen_size.ws_col + 1) *
- (1 + (po->standard != 0)) >= screen_size.ws_row -
- (po->header != 0) *
- (total_line_length / screen_size.ws_col + 1) * 2
- - (po->header != 0) * 2 /* row count and newline */
- )))
- {
- fout = popen(pagerenv, "w");
- if (fout)
- {
- usePipe = 1;
-#ifndef WIN32
-#ifdef ENABLE_THREAD_SAFETY
- if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
- sigpipe_masked = true;
-#else
- oldsigpipehandler = pqsignal(SIGPIPE, SIG_IGN);
-#endif /* ENABLE_THREAD_SAFETY */
-#endif /* WIN32 */
- }
- else
- fout = stdout;
- }
- }
-
- if (!po->expanded && (po->align || po->html3))
- {
- if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *))))
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
- }
- else if (po->header && !po->html3)
- {
- if (po->expanded)
- {
- if (po->align)
- fprintf(fout, libpq_gettext("%-*s%s Value\n"),
- fieldMaxLen - fs_len, libpq_gettext("Field"), po->fieldSep);
- else
- fprintf(fout, libpq_gettext("%s%sValue\n"), libpq_gettext("Field"), po->fieldSep);
- }
- else
- {
- int len = 0;
-
- for (j = 0; j < nFields; j++)
- {
- const char *s = fieldNames[j];
-
- fputs(s, fout);
- len += strlen(s) + fs_len;
- if ((j + 1) < nFields)
- fputs(po->fieldSep, fout);
- }
- fputc('\n', fout);
- for (len -= fs_len; len--; fputc('-', fout));
- fputc('\n', fout);
- }
- }
- if (po->expanded && po->html3)
- {
- if (po->caption)
- fprintf(fout, "<center><h2>%s</h2></center>\n", po->caption);
- else
- fprintf(fout,
- "<center><h2>"
- "Query retrieved %d rows * %d fields"
- "</h2></center>\n",
- nTups, nFields);
- }
- for (i = 0; i < nTups; i++)
- {
- if (po->expanded)
- {
- if (po->html3)
- fprintf(fout,
- "<table %s><caption align=\"top\">%d</caption>\n",
- po->tableOpt ? po->tableOpt : "", i);
- else
- fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
- }
- for (j = 0; j < nFields; j++)
- do_field(po, res, i, j, fs_len, fields, nFields,
- fieldNames, fieldNotNum,
- fieldMax, fieldMaxLen, fout);
- if (po->html3 && po->expanded)
- fputs("</table>\n", fout);
- }
- if (!po->expanded && (po->align || po->html3))
- {
- if (po->html3)
- {
- if (po->header)
- {
- if (po->caption)
- fprintf(fout,
- "<table %s><caption align=\"top\">%s</caption>\n",
- po->tableOpt ? po->tableOpt : "",
- po->caption);
- else
- fprintf(fout,
- "<table %s><caption align=\"top\">"
- "Retrieved %d rows * %d fields"
- "</caption>\n",
- po->tableOpt ? po->tableOpt : "", nTups, nFields);
- }
- else
- fprintf(fout, "<table %s>", po->tableOpt ? po->tableOpt : "");
- }
- if (po->header)
- border = do_header(fout, po, nFields, fieldMax, fieldNames,
- fieldNotNum, fs_len, res);
- for (i = 0; i < nTups; i++)
- output_row(fout, po, nFields, fields,
- fieldNotNum, fieldMax, border, i);
- free(fields);
- if (border)
- free(border);
- }
- if (po->header && !po->html3)
- fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
- (PQntuples(res) == 1) ? "" : "s");
- free(fieldMax);
- free(fieldNotNum);
- free((void *) fieldNames);
- if (usePipe)
- {
-#ifdef WIN32
- _pclose(fout);
-#else
- pclose(fout);
-
-#ifdef ENABLE_THREAD_SAFETY
- /* we can't easily verify if EPIPE occurred, so say it did */
- if (sigpipe_masked)
- pq_reset_sigpipe(&osigset, sigpipe_pending, true);
-#else
- pqsignal(SIGPIPE, oldsigpipehandler);
-#endif /* ENABLE_THREAD_SAFETY */
-#endif /* WIN32 */
- }
- if (po->html3 && !po->expanded)
- fputs("</table>\n", fout);
- }
-}
-
-
-static void
-do_field(const PQprintOpt *po, const PGresult *res,
- const int i, const int j, const int fs_len,
- char **fields,
- const int nFields, char const ** fieldNames,
- unsigned char *fieldNotNum, int *fieldMax,
- const int fieldMaxLen, FILE *fout)
-{
- const char *pval,
- *p;
- int plen;
- bool skipit;
-
- plen = PQgetlength(res, i, j);
- pval = PQgetvalue(res, i, j);
-
- if (plen < 1 || !pval || !*pval)
- {
- if (po->align || po->expanded)
- skipit = true;
- else
- {
- skipit = false;
- goto efield;
- }
- }
- else
- skipit = false;
-
- if (!skipit)
- {
- if (po->align && !fieldNotNum[j])
- {
- /* Detect whether field contains non-numeric data */
- char ch = '0';
-
- for (p = pval; *p; p += PQmblen(p, res->client_encoding))
- {
- ch = *p;
- if (!((ch >= '0' && ch <= '9') ||
- ch == '.' ||
- ch == 'E' ||
- ch == 'e' ||
- ch == ' ' ||
- ch == '-'))
- {
- fieldNotNum[j] = 1;
- break;
- }
- }
-
- /*
- * Above loop will believe E in first column is numeric; also, we
- * insist on a digit in the last column for a numeric. This test
- * is still not bulletproof but it handles most cases.
- */
- if (*pval == 'E' || *pval == 'e' ||
- !(ch >= '0' && ch <= '9'))
- fieldNotNum[j] = 1;
- }
-
- if (!po->expanded && (po->align || po->html3))
- {
- if (plen > fieldMax[j])
- fieldMax[j] = plen;
- if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
- strcpy(fields[i * nFields + j], pval);
- }
- else
- {
- if (po->expanded)
- {
- if (po->html3)
- fprintf(fout,
- "<tr><td align=\"left\"><b>%s</b></td>"
- "<td align=\"%s\">%s</td></tr>\n",
- fieldNames[j],
- fieldNotNum[j] ? "left" : "right",
- pval);
- else
- {
- if (po->align)
- fprintf(fout,
- "%-*s%s %s\n",
- fieldMaxLen - fs_len, fieldNames[j],
- po->fieldSep,
- pval);
- else
- fprintf(fout,
- "%s%s%s\n",
- fieldNames[j], po->fieldSep, pval);
- }
- }
- else
- {
- if (!po->html3)
- {
- fputs(pval, fout);
- efield:
- if ((j + 1) < nFields)
- fputs(po->fieldSep, fout);
- else
- fputc('\n', fout);
- }
- }
- }
- }
-}
-
-
-static char *
-do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
- const char **fieldNames, unsigned char *fieldNotNum,
- const int fs_len, const PGresult *res)
-{
- int j; /* for loop index */
- char *border = NULL;
-
- if (po->html3)
- fputs("<tr>", fout);
- else
- {
- int tot = 0;
- int n = 0;
- char *p = NULL;
-
- for (; n < nFields; n++)
- tot += fieldMax[n] + fs_len + (po->standard ? 2 : 0);
- if (po->standard)
- tot += fs_len * 2 + 2;
- border = malloc(tot + 1);
- if (!border)
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
- p = border;
- if (po->standard)
- {
- char *fs = po->fieldSep;
-
- while (*fs++)
- *p++ = '+';
- }
- for (j = 0; j < nFields; j++)
- {
- int len;
-
- for (len = fieldMax[j] + (po->standard ? 2 : 0); len--; *p++ = '-');
- if (po->standard || (j + 1) < nFields)
- {
- char *fs = po->fieldSep;
-
- while (*fs++)
- *p++ = '+';
- }
- }
- *p = '\0';
- if (po->standard)
- fprintf(fout, "%s\n", border);
- }
- if (po->standard)
- fputs(po->fieldSep, fout);
- for (j = 0; j < nFields; j++)
- {
- const char *s = PQfname(res, j);
-
- if (po->html3)
- {
- fprintf(fout, "<th align=\"%s\">%s</th>",
- fieldNotNum[j] ? "left" : "right", fieldNames[j]);
- }
- else
- {
- int n = strlen(s);
-
- if (n > fieldMax[j])
- fieldMax[j] = n;
- if (po->standard)
- fprintf(fout,
- fieldNotNum[j] ? " %-*s " : " %*s ",
- fieldMax[j], s);
- else
- fprintf(fout, fieldNotNum[j] ? "%-*s" : "%*s", fieldMax[j], s);
- if (po->standard || (j + 1) < nFields)
- fputs(po->fieldSep, fout);
- }
- }
- if (po->html3)
- fputs("</tr>\n", fout);
- else
- fprintf(fout, "\n%s\n", border);
- return border;
-}
-
-
-static void
-output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
- unsigned char *fieldNotNum, int *fieldMax, char *border,
- const int row_index)
-{
- int field_index; /* for loop index */
-
- if (po->html3)
- fputs("<tr>", fout);
- else if (po->standard)
- fputs(po->fieldSep, fout);
- for (field_index = 0; field_index < nFields; field_index++)
- {
- char *p = fields[row_index * nFields + field_index];
-
- if (po->html3)
- fprintf(fout, "<td align=\"%s\">%s</td>",
- fieldNotNum[field_index] ? "left" : "right", p ? p : "");
- else
- {
- fprintf(fout,
- fieldNotNum[field_index] ?
- (po->standard ? " %-*s " : "%-*s") :
- (po->standard ? " %*s " : "%*s"),
- fieldMax[field_index],
- p ? p : "");
- if (po->standard || field_index + 1 < nFields)
- fputs(po->fieldSep, fout);
- }
- if (p)
- free(p);
- }
- if (po->html3)
- fputs("</tr>", fout);
- else if (po->standard)
- fprintf(fout, "\n%s", border);
- fputc('\n', fout);
-}
-
-
-
-/*
- * really old printing routines
- */
-
-void
-PQdisplayTuples(const PGresult *res,
- FILE *fp, /* where to send the output */
- int fillAlign, /* pad the fields with spaces */
- const char *fieldSep, /* field separator */
- int printHeader, /* display headers? */
- int quiet
-)
-{
-#define DEFAULT_FIELD_SEP " "
-
- int i,
- j;
- int nFields;
- int nTuples;
- int *fLength = NULL;
-
- if (fieldSep == NULL)
- fieldSep = DEFAULT_FIELD_SEP;
-
- /* Get some useful info about the results */
- nFields = PQnfields(res);
- nTuples = PQntuples(res);
-
- if (fp == NULL)
- fp = stdout;
-
- /* Figure the field lengths to align to */
- /* will be somewhat time consuming for very large results */
- if (fillAlign)
- {
- fLength = (int *) malloc(nFields * sizeof(int));
- if (!fLength)
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
-
- for (j = 0; j < nFields; j++)
- {
- fLength[j] = strlen(PQfname(res, j));
- for (i = 0; i < nTuples; i++)
- {
- int flen = PQgetlength(res, i, j);
-
- if (flen > fLength[j])
- fLength[j] = flen;
- }
- }
- }
-
- if (printHeader)
- {
- /* first, print out the attribute names */
- for (i = 0; i < nFields; i++)
- {
- fputs(PQfname(res, i), fp);
- if (fillAlign)
- fill(strlen(PQfname(res, i)), fLength[i], ' ', fp);
- fputs(fieldSep, fp);
- }
- fprintf(fp, "\n");
-
- /* Underline the attribute names */
- for (i = 0; i < nFields; i++)
- {
- if (fillAlign)
- fill(0, fLength[i], '-', fp);
- fputs(fieldSep, fp);
- }
- fprintf(fp, "\n");
- }
-
- /* next, print out the instances */
- for (i = 0; i < nTuples; i++)
- {
- for (j = 0; j < nFields; j++)
- {
- fprintf(fp, "%s", PQgetvalue(res, i, j));
- if (fillAlign)
- fill(strlen(PQgetvalue(res, i, j)), fLength[j], ' ', fp);
- fputs(fieldSep, fp);
- }
- fprintf(fp, "\n");
- }
-
- if (!quiet)
- fprintf(fp, "\nQuery returned %d row%s.\n", PQntuples(res),
- (PQntuples(res) == 1) ? "" : "s");
-
- fflush(fp);
-
- if (fLength)
- free(fLength);
-}
-
-
-
-void
-PQprintTuples(const PGresult *res,
- FILE *fout, /* output stream */
- int PrintAttNames, /* print attribute names or not */
- int TerseOutput, /* delimiter bars or not? */
- int colWidth /* width of column, if 0, use variable width */
-)
-{
- int nFields;
- int nTups;
- int i,
- j;
- char formatString[80];
- char *tborder = NULL;
-
- nFields = PQnfields(res);
- nTups = PQntuples(res);
-
- if (colWidth > 0)
- sprintf(formatString, "%%s %%-%ds", colWidth);
- else
- sprintf(formatString, "%%s %%s");
-
- if (nFields > 0)
- { /* only print rows with at least 1 field. */
-
- if (!TerseOutput)
- {
- int width;
-
- width = nFields * 14;
- tborder = (char *) malloc(width + 1);
- if (!tborder)
- {
- fprintf(stderr, libpq_gettext("out of memory\n"));
- abort();
- }
- for (i = 0; i < width; i++)
- tborder[i] = '-';
- tborder[width] = '\0';
- fprintf(fout, "%s\n", tborder);
- }
-
- for (i = 0; i < nFields; i++)
- {
- if (PrintAttNames)
- {
- fprintf(fout, formatString,
- TerseOutput ? "" : "|",
- PQfname(res, i));
- }
- }
-
- if (PrintAttNames)
- {
- if (TerseOutput)
- fprintf(fout, "\n");
- else
- fprintf(fout, "|\n%s\n", tborder);
- }
-
- for (i = 0; i < nTups; i++)
- {
- for (j = 0; j < nFields; j++)
- {
- const char *pval = PQgetvalue(res, i, j);
-
- fprintf(fout, formatString,
- TerseOutput ? "" : "|",
- pval ? pval : "");
- }
- if (TerseOutput)
- fprintf(fout, "\n");
- else
- fprintf(fout, "|\n%s\n", tborder);
- }
- }
-
- if (tborder)
- free(tborder);
-}
-
-
-/* simply send out max-length number of filler characters to fp */
-
-static void
-fill(int length, int max, char filler, FILE *fp)
-{
- int count;
-
- count = max - length;
- while (count-- >= 0)
- putc(filler, fp);
-}
diff --git a/libpq/fe-protocol2.c b/libpq/fe-protocol2.c
deleted file mode 100644
index f1b90f3..0000000
--- a/libpq/fe-protocol2.c
+++ /dev/null
@@ -1,1623 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-protocol2.c
- * functions that are specific to frontend/backend protocol version 2
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-protocol2.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <fcntl.h>
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <unistd.h>
-#include <netinet/in.h>
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#include <arpa/inet.h>
-#endif
-
-
-static int getRowDescriptions(PGconn *conn);
-static int getAnotherTuple(PGconn *conn, bool binary);
-static int pqGetErrorNotice2(PGconn *conn, bool isError);
-static void checkXactStatus(PGconn *conn, const char *cmdTag);
-static int getNotify(PGconn *conn);
-
-
-/*
- * pqSetenvPoll
- *
- * Polls the process of passing the values of a standard set of environment
- * variables to the backend.
- */
-PostgresPollingStatusType
-pqSetenvPoll(PGconn *conn)
-{
- PGresult *res;
-
- if (conn == NULL || conn->status == CONNECTION_BAD)
- return PGRES_POLLING_FAILED;
-
- /* Check whether there are any data for us */
- switch (conn->setenv_state)
- {
- /* These are reading states */
- case SETENV_STATE_CLIENT_ENCODING_WAIT:
- case SETENV_STATE_OPTION_WAIT:
- case SETENV_STATE_QUERY1_WAIT:
- case SETENV_STATE_QUERY2_WAIT:
- {
- /* Load waiting data */
- int n = pqReadData(conn);
-
- if (n < 0)
- goto error_return;
- if (n == 0)
- return PGRES_POLLING_READING;
-
- break;
- }
-
- /* These are writing states, so we just proceed. */
- case SETENV_STATE_CLIENT_ENCODING_SEND:
- case SETENV_STATE_OPTION_SEND:
- case SETENV_STATE_QUERY1_SEND:
- case SETENV_STATE_QUERY2_SEND:
- break;
-
- /* Should we raise an error if called when not active? */
- case SETENV_STATE_IDLE:
- return PGRES_POLLING_OK;
-
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "invalid setenv state %c, "
- "probably indicative of memory corruption\n"
- ),
- conn->setenv_state);
- goto error_return;
- }
-
- /* We will loop here until there is nothing left to do in this call. */
- for (;;)
- {
- switch (conn->setenv_state)
- {
- /*
- * The _CLIENT_ENCODING_SEND code is slightly different from
- * _OPTION_SEND below (e.g., no getenv() call), which is why a
- * different state is used.
- */
- case SETENV_STATE_CLIENT_ENCODING_SEND:
- {
- char setQuery[100]; /* note length limit in
- * sprintf below */
- const char *val = conn->client_encoding_initial;
-
- if (val)
- {
- if (pg_strcasecmp(val, "default") == 0)
- sprintf(setQuery, "SET client_encoding = DEFAULT");
- else
- sprintf(setQuery, "SET client_encoding = '%.60s'",
- val);
-#ifdef CONNECTDEBUG
- fprintf(stderr,
- "Sending client_encoding with %s\n",
- setQuery);
-#endif
- if (!PQsendQuery(conn, setQuery))
- goto error_return;
-
- conn->setenv_state = SETENV_STATE_CLIENT_ENCODING_WAIT;
- }
- else
- conn->setenv_state = SETENV_STATE_OPTION_SEND;
- break;
- }
-
- case SETENV_STATE_OPTION_SEND:
- {
- /*
- * Send SET commands for stuff directed by Environment
- * Options. Note: we assume that SET commands won't start
- * transaction blocks, even in a 7.3 server with
- * autocommit off.
- */
- char setQuery[100]; /* note length limit in
- * sprintf below */
-
- if (conn->next_eo->envName)
- {
- const char *val;
-
- if ((val = getenv(conn->next_eo->envName)))
- {
- if (pg_strcasecmp(val, "default") == 0)
- sprintf(setQuery, "SET %s = DEFAULT",
- conn->next_eo->pgName);
- else
- sprintf(setQuery, "SET %s = '%.60s'",
- conn->next_eo->pgName, val);
-#ifdef CONNECTDEBUG
- fprintf(stderr,
- "Use environment variable %s to send %s\n",
- conn->next_eo->envName, setQuery);
-#endif
- if (!PQsendQuery(conn, setQuery))
- goto error_return;
-
- conn->setenv_state = SETENV_STATE_OPTION_WAIT;
- }
- else
- conn->next_eo++;
- }
- else
- {
- /* No more options to send, so move on to querying */
- conn->setenv_state = SETENV_STATE_QUERY1_SEND;
- }
- break;
- }
-
- case SETENV_STATE_CLIENT_ENCODING_WAIT:
- {
- if (PQisBusy(conn))
- return PGRES_POLLING_READING;
-
- res = PQgetResult(conn);
-
- if (res)
- {
- if (PQresultStatus(res) != PGRES_COMMAND_OK)
- {
- PQclear(res);
- goto error_return;
- }
- PQclear(res);
- /* Keep reading until PQgetResult returns NULL */
- }
- else
- {
- /* Query finished, so send the next option */
- conn->setenv_state = SETENV_STATE_OPTION_SEND;
- }
- break;
- }
-
- case SETENV_STATE_OPTION_WAIT:
- {
- if (PQisBusy(conn))
- return PGRES_POLLING_READING;
-
- res = PQgetResult(conn);
-
- if (res)
- {
- if (PQresultStatus(res) != PGRES_COMMAND_OK)
- {
- PQclear(res);
- goto error_return;
- }
- PQclear(res);
- /* Keep reading until PQgetResult returns NULL */
- }
- else
- {
- /* Query finished, so send the next option */
- conn->next_eo++;
- conn->setenv_state = SETENV_STATE_OPTION_SEND;
- }
- break;
- }
-
- case SETENV_STATE_QUERY1_SEND:
- {
- /*
- * Issue query to get information we need. Here we must
- * use begin/commit in case autocommit is off by default
- * in a 7.3 server.
- *
- * Note: version() exists in all protocol-2.0-supporting
- * backends. In 7.3 it would be safer to write
- * pg_catalog.version(), but we can't do that without
- * causing problems on older versions.
- */
- if (!PQsendQuery(conn, "begin; select version(); end"))
- goto error_return;
-
- conn->setenv_state = SETENV_STATE_QUERY1_WAIT;
- return PGRES_POLLING_READING;
- }
-
- case SETENV_STATE_QUERY1_WAIT:
- {
- if (PQisBusy(conn))
- return PGRES_POLLING_READING;
-
- res = PQgetResult(conn);
-
- if (res)
- {
- char *val;
-
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- /* ignore begin/commit command results */
- PQclear(res);
- continue;
- }
-
- if (PQresultStatus(res) != PGRES_TUPLES_OK ||
- PQntuples(res) != 1)
- {
- PQclear(res);
- goto error_return;
- }
-
- /*
- * Extract server version and save as if
- * ParameterStatus
- */
- val = PQgetvalue(res, 0, 0);
- if (val && strncmp(val, "PostgreSQL ", 11) == 0)
- {
- char *ptr;
-
- /* strip off PostgreSQL part */
- val += 11;
-
- /*
- * strip off platform part (scribbles on result,
- * naughty naughty)
- */
- ptr = strchr(val, ' ');
- if (ptr)
- *ptr = '\0';
-
- pqSaveParameterStatus(conn, "server_version",
- val);
- }
-
- PQclear(res);
- /* Keep reading until PQgetResult returns NULL */
- }
- else
- {
- /* Query finished, move to next */
- conn->setenv_state = SETENV_STATE_QUERY2_SEND;
- }
- break;
- }
-
- case SETENV_STATE_QUERY2_SEND:
- {
- const char *query;
-
- /*
- * pg_client_encoding does not exist in pre-7.2 servers.
- * So we need to be prepared for an error here. Do *not*
- * start a transaction block, except in 7.3 servers where
- * we need to prevent autocommit-off from starting a
- * transaction anyway.
- */
- if (conn->sversion >= 70300 &&
- conn->sversion < 70400)
- query = "begin; select pg_catalog.pg_client_encoding(); end";
- else
- query = "select pg_client_encoding()";
- if (!PQsendQuery(conn, query))
- goto error_return;
-
- conn->setenv_state = SETENV_STATE_QUERY2_WAIT;
- return PGRES_POLLING_READING;
- }
-
- case SETENV_STATE_QUERY2_WAIT:
- {
- if (PQisBusy(conn))
- return PGRES_POLLING_READING;
-
- res = PQgetResult(conn);
-
- if (res)
- {
- const char *val;
-
- if (PQresultStatus(res) == PGRES_COMMAND_OK)
- {
- /* ignore begin/commit command results */
- PQclear(res);
- continue;
- }
-
- if (PQresultStatus(res) == PGRES_TUPLES_OK &&
- PQntuples(res) == 1)
- {
- /* Extract client encoding and save it */
- val = PQgetvalue(res, 0, 0);
- if (val && *val) /* null should not happen, but */
- pqSaveParameterStatus(conn, "client_encoding",
- val);
- }
- else
- {
- /*
- * Error: presumably function not available, so
- * use PGCLIENTENCODING or SQL_ASCII as the
- * fallback.
- */
- val = getenv("PGCLIENTENCODING");
- if (val && *val)
- pqSaveParameterStatus(conn, "client_encoding",
- val);
- else
- pqSaveParameterStatus(conn, "client_encoding",
- "SQL_ASCII");
- }
-
- PQclear(res);
- /* Keep reading until PQgetResult returns NULL */
- }
- else
- {
- /* Query finished, so we're done */
- conn->setenv_state = SETENV_STATE_IDLE;
- return PGRES_POLLING_OK;
- }
- break;
- }
-
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("invalid state %c, "
- "probably indicative of memory corruption\n"),
- conn->setenv_state);
- goto error_return;
- }
- }
-
- /* Unreachable */
-
-error_return:
- conn->setenv_state = SETENV_STATE_IDLE;
- return PGRES_POLLING_FAILED;
-}
-
-
-/*
- * parseInput: if appropriate, parse input data from backend
- * until input is exhausted or a stopping state is reached.
- * Note that this function will NOT attempt to read more data from the backend.
- */
-void
-pqParseInput2(PGconn *conn)
-{
- char id;
-
- /*
- * Loop to parse successive complete messages available in the buffer.
- */
- for (;;)
- {
- /*
- * Quit if in COPY_OUT state: we expect raw data from the server until
- * PQendcopy is called. Don't try to parse it according to the normal
- * protocol. (This is bogus. The data lines ought to be part of the
- * protocol and have identifying leading characters.)
- */
- if (conn->asyncStatus == PGASYNC_COPY_OUT)
- return;
-
- /*
- * OK to try to read a message type code.
- */
- conn->inCursor = conn->inStart;
- if (pqGetc(&id, conn))
- return;
-
- /*
- * NOTIFY and NOTICE messages can happen in any state besides COPY
- * OUT; always process them right away.
- *
- * Most other messages should only be processed while in BUSY state.
- * (In particular, in READY state we hold off further parsing until
- * the application collects the current PGresult.)
- *
- * However, if the state is IDLE then we got trouble; we need to deal
- * with the unexpected message somehow.
- */
- if (id == 'A')
- {
- if (getNotify(conn))
- return;
- }
- else if (id == 'N')
- {
- if (pqGetErrorNotice2(conn, false))
- return;
- }
- else if (conn->asyncStatus != PGASYNC_BUSY)
- {
- /* If not IDLE state, just wait ... */
- if (conn->asyncStatus != PGASYNC_IDLE)
- return;
-
- /*
- * Unexpected message in IDLE state; need to recover somehow.
- * ERROR messages are displayed using the notice processor;
- * anything else is just dropped on the floor after displaying a
- * suitable warning notice. (An ERROR is very possibly the
- * backend telling us why it is about to close the connection, so
- * we don't want to just discard it...)
- */
- if (id == 'E')
- {
- if (pqGetErrorNotice2(conn, false /* treat as notice */ ))
- return;
- }
- else
- {
- pqInternalNotice(&conn->noticeHooks,
- "message type 0x%02x arrived from server while idle",
- id);
- /* Discard the unexpected message; good idea?? */
- conn->inStart = conn->inEnd;
- break;
- }
- }
- else
- {
- /*
- * In BUSY state, we can process everything.
- */
- switch (id)
- {
- case 'C': /* command complete */
- if (pqGets(&conn->workBuffer, conn))
- return;
- if (conn->result == NULL)
- {
- conn->result = PQmakeEmptyPGresult(conn,
- PGRES_COMMAND_OK);
- if (!conn->result)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- pqSaveErrorResult(conn);
- }
- }
- if (conn->result)
- {
- strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
- CMDSTATUS_LEN);
- }
- checkXactStatus(conn, conn->workBuffer.data);
- conn->asyncStatus = PGASYNC_READY;
- break;
- case 'E': /* error return */
- if (pqGetErrorNotice2(conn, true))
- return;
- conn->asyncStatus = PGASYNC_READY;
- break;
- case 'Z': /* backend is ready for new query */
- conn->asyncStatus = PGASYNC_IDLE;
- break;
- case 'I': /* empty query */
- /* read and throw away the closing '\0' */
- if (pqGetc(&id, conn))
- return;
- if (id != '\0')
- pqInternalNotice(&conn->noticeHooks,
- "unexpected character %c following empty query response (\"I\" message)",
- id);
- if (conn->result == NULL)
- {
- conn->result = PQmakeEmptyPGresult(conn,
- PGRES_EMPTY_QUERY);
- if (!conn->result)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- pqSaveErrorResult(conn);
- }
- }
- conn->asyncStatus = PGASYNC_READY;
- break;
- case 'K': /* secret key data from the backend */
-
- /*
- * This is expected only during backend startup, but it's
- * just as easy to handle it as part of the main loop.
- * Save the data and continue processing.
- */
- if (pqGetInt(&(conn->be_pid), 4, conn))
- return;
- if (pqGetInt(&(conn->be_key), 4, conn))
- return;
- break;
- case 'P': /* synchronous (normal) portal */
- if (pqGets(&conn->workBuffer, conn))
- return;
- /* We pretty much ignore this message type... */
- break;
- case 'T': /* row descriptions (start of query results) */
- if (conn->result == NULL)
- {
- /* First 'T' in a query sequence */
- if (getRowDescriptions(conn))
- return;
- /* getRowDescriptions() moves inStart itself */
- continue;
- }
- else
- {
- /*
- * A new 'T' message is treated as the start of
- * another PGresult. (It is not clear that this is
- * really possible with the current backend.) We stop
- * parsing until the application accepts the current
- * result.
- */
- conn->asyncStatus = PGASYNC_READY;
- return;
- }
- break;
- case 'D': /* ASCII data tuple */
- if (conn->result != NULL)
- {
- /* Read another tuple of a normal query response */
- if (getAnotherTuple(conn, FALSE))
- return;
- /* getAnotherTuple() moves inStart itself */
- continue;
- }
- else
- {
- pqInternalNotice(&conn->noticeHooks,
- "server sent data (\"D\" message) without prior row description (\"T\" message)");
- /* Discard the unexpected message; good idea?? */
- conn->inStart = conn->inEnd;
- return;
- }
- break;
- case 'B': /* Binary data tuple */
- if (conn->result != NULL)
- {
- /* Read another tuple of a normal query response */
- if (getAnotherTuple(conn, TRUE))
- return;
- /* getAnotherTuple() moves inStart itself */
- continue;
- }
- else
- {
- pqInternalNotice(&conn->noticeHooks,
- "server sent binary data (\"B\" message) without prior row description (\"T\" message)");
- /* Discard the unexpected message; good idea?? */
- conn->inStart = conn->inEnd;
- return;
- }
- break;
- case 'G': /* Start Copy In */
- conn->asyncStatus = PGASYNC_COPY_IN;
- break;
- case 'H': /* Start Copy Out */
- conn->asyncStatus = PGASYNC_COPY_OUT;
- break;
-
- /*
- * Don't need to process CopyBothResponse here because it
- * never arrives from the server during protocol 2.0.
- */
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "unexpected response from server; first received character was \"%c\"\n"),
- id);
- /* build an error result holding the error message */
- pqSaveErrorResult(conn);
- /* Discard the unexpected message; good idea?? */
- conn->inStart = conn->inEnd;
- conn->asyncStatus = PGASYNC_READY;
- return;
- } /* switch on protocol character */
- }
- /* Successfully consumed this message */
- conn->inStart = conn->inCursor;
- }
-}
-
-/*
- * parseInput subroutine to read a 'T' (row descriptions) message.
- * We build a PGresult structure containing the attribute data.
- * Returns: 0 if completed message, EOF if error or not enough data
- * received yet.
- *
- * Note that if we run out of data, we have to suspend and reprocess
- * the message after more data is received. Otherwise, conn->inStart
- * must get advanced past the processed data.
- */
-static int
-getRowDescriptions(PGconn *conn)
-{
- PGresult *result;
- int nfields;
- const char *errmsg;
- int i;
-
- result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
- if (!result)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
-
- /* parseInput already read the 'T' label. */
- /* the next two bytes are the number of fields */
- if (pqGetInt(&(result->numAttributes), 2, conn))
- goto EOFexit;
- nfields = result->numAttributes;
-
- /* allocate space for the attribute descriptors */
- if (nfields > 0)
- {
- result->attDescs = (PGresAttDesc *)
- pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
- if (!result->attDescs)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
- MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
- }
-
- /* get type info */
- for (i = 0; i < nfields; i++)
- {
- int typid;
- int typlen;
- int atttypmod;
-
- if (pqGets(&conn->workBuffer, conn) ||
- pqGetInt(&typid, 4, conn) ||
- pqGetInt(&typlen, 2, conn) ||
- pqGetInt(&atttypmod, 4, conn))
- goto EOFexit;
-
- /*
- * Since pqGetInt treats 2-byte integers as unsigned, we need to
- * coerce the result to signed form.
- */
- typlen = (int) ((int16) typlen);
-
- result->attDescs[i].name = pqResultStrdup(result,
- conn->workBuffer.data);
- if (!result->attDescs[i].name)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
- result->attDescs[i].tableid = 0;
- result->attDescs[i].columnid = 0;
- result->attDescs[i].format = 0;
- result->attDescs[i].typid = typid;
- result->attDescs[i].typlen = typlen;
- result->attDescs[i].atttypmod = atttypmod;
- }
-
- /* Success! */
- conn->result = result;
-
- /* Advance inStart to show that the "T" message has been processed. */
- conn->inStart = conn->inCursor;
-
- /*
- * We could perform additional setup for the new result set here, but for
- * now there's nothing else to do.
- */
-
- /* And we're done. */
- return 0;
-
-advance_and_error:
-
- /*
- * Discard the failed message. Unfortunately we don't know for sure where
- * the end is, so just throw away everything in the input buffer. This is
- * not very desirable but it's the best we can do in protocol v2.
- */
- conn->inStart = conn->inEnd;
-
- /*
- * Replace partially constructed result with an error result. First
- * discard the old result to try to win back some memory.
- */
- pqClearAsyncResult(conn);
-
- /*
- * If preceding code didn't provide an error message, assume "out of
- * memory" was meant. The advantage of having this special case is that
- * freeing the old result first greatly improves the odds that gettext()
- * will succeed in providing a translation.
- */
- if (!errmsg)
- errmsg = libpq_gettext("out of memory for query result");
-
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
-
- /*
- * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
- * do to recover...
- */
- conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
- conn->asyncStatus = PGASYNC_READY;
-
-EOFexit:
- if (result && result != conn->result)
- PQclear(result);
- return EOF;
-}
-
-/*
- * parseInput subroutine to read a 'B' or 'D' (row data) message.
- * We fill rowbuf with column pointers and then call the row processor.
- * Returns: 0 if completed message, EOF if error or not enough data
- * received yet.
- *
- * Note that if we run out of data, we have to suspend and reprocess
- * the message after more data is received. Otherwise, conn->inStart
- * must get advanced past the processed data.
- */
-static int
-getAnotherTuple(PGconn *conn, bool binary)
-{
- PGresult *result = conn->result;
- int nfields = result->numAttributes;
- const char *errmsg;
- PGdataValue *rowbuf;
-
- /* the backend sends us a bitmap of which attributes are null */
- char std_bitmap[64]; /* used unless it doesn't fit */
- char *bitmap = std_bitmap;
- int i;
- size_t nbytes; /* the number of bytes in bitmap */
- char bmap; /* One byte of the bitmap */
- int bitmap_index; /* Its index */
- int bitcnt; /* number of bits examined in current byte */
- int vlen; /* length of the current field value */
-
- /* Resize row buffer if needed */
- rowbuf = conn->rowBuf;
- if (nfields > conn->rowBufLen)
- {
- rowbuf = (PGdataValue *) realloc(rowbuf,
- nfields * sizeof(PGdataValue));
- if (!rowbuf)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
- conn->rowBuf = rowbuf;
- conn->rowBufLen = nfields;
- }
-
- /* Save format specifier */
- result->binary = binary;
-
- /*
- * If it's binary, fix the column format indicators. We assume the
- * backend will consistently send either B or D, not a mix.
- */
- if (binary)
- {
- for (i = 0; i < nfields; i++)
- result->attDescs[i].format = 1;
- }
-
- /* Get the null-value bitmap */
- nbytes = (nfields + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
- /* malloc() only for unusually large field counts... */
- if (nbytes > sizeof(std_bitmap))
- {
- bitmap = (char *) malloc(nbytes);
- if (!bitmap)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
- }
-
- if (pqGetnchar(bitmap, nbytes, conn))
- goto EOFexit;
-
- /* Scan the fields */
- bitmap_index = 0;
- bmap = bitmap[bitmap_index];
- bitcnt = 0;
-
- for (i = 0; i < nfields; i++)
- {
- /* get the value length */
- if (!(bmap & 0200))
- vlen = NULL_LEN;
- else if (pqGetInt(&vlen, 4, conn))
- goto EOFexit;
- else
- {
- if (!binary)
- vlen = vlen - 4;
- if (vlen < 0)
- vlen = 0;
- }
- rowbuf[i].len = vlen;
-
- /*
- * rowbuf[i].value always points to the next address in the data
- * buffer even if the value is NULL. This allows row processors to
- * estimate data sizes more easily.
- */
- rowbuf[i].value = conn->inBuffer + conn->inCursor;
-
- /* Skip over the data value */
- if (vlen > 0)
- {
- if (pqSkipnchar(vlen, conn))
- goto EOFexit;
- }
-
- /* advance the bitmap stuff */
- bitcnt++;
- if (bitcnt == BITS_PER_BYTE)
- {
- bitmap_index++;
- bmap = bitmap[bitmap_index];
- bitcnt = 0;
- }
- else
- bmap <<= 1;
- }
-
- /* Release bitmap now if we allocated it */
- if (bitmap != std_bitmap)
- free(bitmap);
- bitmap = NULL;
-
- /* Advance inStart to show that the "D" message has been processed. */
- conn->inStart = conn->inCursor;
-
- /* Process the collected row */
- errmsg = NULL;
- if (pqRowProcessor(conn, &errmsg))
- return 0; /* normal, successful exit */
-
- goto set_error_result; /* pqRowProcessor failed, report it */
-
-advance_and_error:
-
- /*
- * Discard the failed message. Unfortunately we don't know for sure where
- * the end is, so just throw away everything in the input buffer. This is
- * not very desirable but it's the best we can do in protocol v2.
- */
- conn->inStart = conn->inEnd;
-
-set_error_result:
-
- /*
- * Replace partially constructed result with an error result. First
- * discard the old result to try to win back some memory.
- */
- pqClearAsyncResult(conn);
-
- /*
- * If preceding code didn't provide an error message, assume "out of
- * memory" was meant. The advantage of having this special case is that
- * freeing the old result first greatly improves the odds that gettext()
- * will succeed in providing a translation.
- */
- if (!errmsg)
- errmsg = libpq_gettext("out of memory for query result");
-
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
-
- /*
- * XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
- * do to recover...
- */
- conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
- conn->asyncStatus = PGASYNC_READY;
-
-EOFexit:
- if (bitmap != NULL && bitmap != std_bitmap)
- free(bitmap);
- return EOF;
-}
-
-
-/*
- * Attempt to read an Error or Notice response message.
- * This is possible in several places, so we break it out as a subroutine.
- * Entry: 'E' or 'N' message type has already been consumed.
- * Exit: returns 0 if successfully consumed message.
- * returns EOF if not enough data.
- */
-static int
-pqGetErrorNotice2(PGconn *conn, bool isError)
-{
- PGresult *res = NULL;
- PQExpBufferData workBuf;
- char *startp;
- char *splitp;
-
- /*
- * Since the message might be pretty long, we create a temporary
- * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
- * for stuff that is expected to be short.
- */
- initPQExpBuffer(&workBuf);
- if (pqGets(&workBuf, conn))
- goto failure;
-
- /*
- * Make a PGresult to hold the message. We temporarily lie about the
- * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
- * conn->errorMessage.
- *
- * NB: This allocation can fail, if you run out of memory. The rest of the
- * function handles that gracefully, and we still try to set the error
- * message as the connection's error message.
- */
- res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
- if (res)
- {
- res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
- res->errMsg = pqResultStrdup(res, workBuf.data);
- }
-
- /*
- * Break the message into fields. We can't do very much here, but we can
- * split the severity code off, and remove trailing newlines. Also, we use
- * the heuristic that the primary message extends only to the first
- * newline --- anything after that is detail message. (In some cases it'd
- * be better classed as hint, but we can hardly be expected to guess that
- * here.)
- */
- while (workBuf.len > 0 && workBuf.data[workBuf.len - 1] == '\n')
- workBuf.data[--workBuf.len] = '\0';
- splitp = strstr(workBuf.data, ": ");
- if (splitp)
- {
- /* what comes before the colon is severity */
- *splitp = '\0';
- pqSaveMessageField(res, PG_DIAG_SEVERITY, workBuf.data);
- startp = splitp + 3;
- }
- else
- {
- /* can't find a colon? oh well... */
- startp = workBuf.data;
- }
- splitp = strchr(startp, '\n');
- if (splitp)
- {
- /* what comes before the newline is primary message */
- *splitp++ = '\0';
- pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, startp);
- /* the rest is detail; strip any leading whitespace */
- while (*splitp && isspace((unsigned char) *splitp))
- splitp++;
- pqSaveMessageField(res, PG_DIAG_MESSAGE_DETAIL, splitp);
- }
- else
- {
- /* single-line message, so all primary */
- pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, startp);
- }
-
- /*
- * Either save error as current async result, or just emit the notice.
- * Also, if it's an error and we were in a transaction block, assume the
- * server has now gone to error-in-transaction state.
- */
- if (isError)
- {
- pqClearAsyncResult(conn);
- conn->result = res;
- resetPQExpBuffer(&conn->errorMessage);
- if (res && !PQExpBufferDataBroken(workBuf) && res->errMsg)
- appendPQExpBufferStr(&conn->errorMessage, res->errMsg);
- else
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- if (conn->xactStatus == PQTRANS_INTRANS)
- conn->xactStatus = PQTRANS_INERROR;
- }
- else
- {
- if (res)
- {
- if (res->noticeHooks.noticeRec != NULL)
- (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
- PQclear(res);
- }
- }
-
- termPQExpBuffer(&workBuf);
- return 0;
-
-failure:
- if (res)
- PQclear(res);
- termPQExpBuffer(&workBuf);
- return EOF;
-}
-
-/*
- * checkXactStatus - attempt to track transaction-block status of server
- *
- * This is called each time we receive a command-complete message. By
- * watching for messages from BEGIN/COMMIT/ROLLBACK commands, we can do
- * a passable job of tracking the server's xact status. BUT: this does
- * not work at all on 7.3 servers with AUTOCOMMIT OFF. (Man, was that
- * feature ever a mistake.) Caveat user.
- *
- * The tags known here are all those used as far back as 7.0; is it worth
- * adding those from even-older servers?
- */
-static void
-checkXactStatus(PGconn *conn, const char *cmdTag)
-{
- if (strcmp(cmdTag, "BEGIN") == 0)
- conn->xactStatus = PQTRANS_INTRANS;
- else if (strcmp(cmdTag, "COMMIT") == 0)
- conn->xactStatus = PQTRANS_IDLE;
- else if (strcmp(cmdTag, "ROLLBACK") == 0)
- conn->xactStatus = PQTRANS_IDLE;
- else if (strcmp(cmdTag, "START TRANSACTION") == 0) /* 7.3 only */
- conn->xactStatus = PQTRANS_INTRANS;
-
- /*
- * Normally we get into INERROR state by detecting an Error message.
- * However, if we see one of these tags then we know for sure the server
- * is in abort state ...
- */
- else if (strcmp(cmdTag, "*ABORT STATE*") == 0) /* pre-7.3 only */
- conn->xactStatus = PQTRANS_INERROR;
-}
-
-/*
- * Attempt to read a Notify response message.
- * This is possible in several places, so we break it out as a subroutine.
- * Entry: 'A' message type and length have already been consumed.
- * Exit: returns 0 if successfully consumed Notify message.
- * returns EOF if not enough data.
- */
-static int
-getNotify(PGconn *conn)
-{
- int be_pid;
- int nmlen;
- PGnotify *newNotify;
-
- if (pqGetInt(&be_pid, 4, conn))
- return EOF;
- if (pqGets(&conn->workBuffer, conn))
- return EOF;
-
- /*
- * Store the relation name right after the PQnotify structure so it can
- * all be freed at once. We don't use NAMEDATALEN because we don't want
- * to tie this interface to a specific server name length.
- */
- nmlen = strlen(conn->workBuffer.data);
- newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + 1);
- if (newNotify)
- {
- newNotify->relname = (char *) newNotify + sizeof(PGnotify);
- strcpy(newNotify->relname, conn->workBuffer.data);
- /* fake up an empty-string extra field */
- newNotify->extra = newNotify->relname + nmlen;
- newNotify->be_pid = be_pid;
- newNotify->next = NULL;
- if (conn->notifyTail)
- conn->notifyTail->next = newNotify;
- else
- conn->notifyHead = newNotify;
- conn->notifyTail = newNotify;
- }
-
- return 0;
-}
-
-
-/*
- * PQgetCopyData - read a row of data from the backend during COPY OUT
- *
- * If successful, sets *buffer to point to a malloc'd row of data, and
- * returns row length (always > 0) as result.
- * Returns 0 if no row available yet (only possible if async is true),
- * -1 if end of copy (consult PQgetResult), or -2 if error (consult
- * PQerrorMessage).
- */
-int
-pqGetCopyData2(PGconn *conn, char **buffer, int async)
-{
- bool found;
- int msgLength;
-
- for (;;)
- {
- /*
- * Do we have a complete line of data?
- */
- conn->inCursor = conn->inStart;
- found = false;
- while (conn->inCursor < conn->inEnd)
- {
- char c = conn->inBuffer[conn->inCursor++];
-
- if (c == '\n')
- {
- found = true;
- break;
- }
- }
- if (!found)
- goto nodata;
- msgLength = conn->inCursor - conn->inStart;
-
- /*
- * If it's the end-of-data marker, consume it, exit COPY_OUT mode, and
- * let caller read status with PQgetResult().
- */
- if (msgLength == 3 &&
- strncmp(&conn->inBuffer[conn->inStart], "\\.\n", 3) == 0)
- {
- conn->inStart = conn->inCursor;
- conn->asyncStatus = PGASYNC_BUSY;
- return -1;
- }
-
- /*
- * Pass the line back to the caller.
- */
- *buffer = (char *) malloc(msgLength + 1);
- if (*buffer == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return -2;
- }
- memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
- (*buffer)[msgLength] = '\0'; /* Add terminating null */
-
- /* Mark message consumed */
- conn->inStart = conn->inCursor;
-
- return msgLength;
-
-nodata:
- /* Don't block if async read requested */
- if (async)
- return 0;
- /* Need to load more data */
- if (pqWait(TRUE, FALSE, conn) ||
- pqReadData(conn) < 0)
- return -2;
- }
-}
-
-
-/*
- * PQgetline - gets a newline-terminated string from the backend.
- *
- * See fe-exec.c for documentation.
- */
-int
-pqGetline2(PGconn *conn, char *s, int maxlen)
-{
- int result = 1; /* return value if buffer overflows */
-
- if (conn->sock == PGINVALID_SOCKET ||
- conn->asyncStatus != PGASYNC_COPY_OUT)
- {
- *s = '\0';
- return EOF;
- }
-
- /*
- * Since this is a purely synchronous routine, we don't bother to maintain
- * conn->inCursor; there is no need to back up.
- */
- while (maxlen > 1)
- {
- if (conn->inStart < conn->inEnd)
- {
- char c = conn->inBuffer[conn->inStart++];
-
- if (c == '\n')
- {
- result = 0; /* success exit */
- break;
- }
- *s++ = c;
- maxlen--;
- }
- else
- {
- /* need to load more data */
- if (pqWait(TRUE, FALSE, conn) ||
- pqReadData(conn) < 0)
- {
- result = EOF;
- break;
- }
- }
- }
- *s = '\0';
-
- return result;
-}
-
-/*
- * PQgetlineAsync - gets a COPY data row without blocking.
- *
- * See fe-exec.c for documentation.
- */
-int
-pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize)
-{
- int avail;
-
- if (conn->asyncStatus != PGASYNC_COPY_OUT)
- return -1; /* we are not doing a copy... */
-
- /*
- * Move data from libpq's buffer to the caller's. We want to accept data
- * only in units of whole lines, not partial lines. This ensures that we
- * can recognize the terminator line "\\.\n". (Otherwise, if it happened
- * to cross a packet/buffer boundary, we might hand the first one or two
- * characters off to the caller, which we shouldn't.)
- */
-
- conn->inCursor = conn->inStart;
-
- avail = bufsize;
- while (avail > 0 && conn->inCursor < conn->inEnd)
- {
- char c = conn->inBuffer[conn->inCursor++];
-
- *buffer++ = c;
- --avail;
- if (c == '\n')
- {
- /* Got a complete line; mark the data removed from libpq */
- conn->inStart = conn->inCursor;
- /* Is it the endmarker line? */
- if (bufsize - avail == 3 && buffer[-3] == '\\' && buffer[-2] == '.')
- return -1;
- /* No, return the data line to the caller */
- return bufsize - avail;
- }
- }
-
- /*
- * We don't have a complete line. We'd prefer to leave it in libpq's
- * buffer until the rest arrives, but there is a special case: what if the
- * line is longer than the buffer the caller is offering us? In that case
- * we'd better hand over a partial line, else we'd get into an infinite
- * loop. Do this in a way that ensures we can't misrecognize a terminator
- * line later: leave last 3 characters in libpq buffer.
- */
- if (avail == 0 && bufsize > 3)
- {
- conn->inStart = conn->inCursor - 3;
- return bufsize - 3;
- }
- return 0;
-}
-
-/*
- * PQendcopy
- *
- * See fe-exec.c for documentation.
- */
-int
-pqEndcopy2(PGconn *conn)
-{
- PGresult *result;
-
- if (conn->asyncStatus != PGASYNC_COPY_IN &&
- conn->asyncStatus != PGASYNC_COPY_OUT)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
- return 1;
- }
-
- /*
- * make sure no data is waiting to be sent, abort if we are non-blocking
- * and the flush fails
- */
- if (pqFlush(conn) && pqIsnonblocking(conn))
- return 1;
-
- /* non blocking connections may have to abort at this point. */
- if (pqIsnonblocking(conn) && PQisBusy(conn))
- return 1;
-
- /* Return to active duty */
- conn->asyncStatus = PGASYNC_BUSY;
- resetPQExpBuffer(&conn->errorMessage);
-
- /* Wait for the completion response */
- result = PQgetResult(conn);
-
- /* Expecting a successful result */
- if (result && result->resultStatus == PGRES_COMMAND_OK)
- {
- PQclear(result);
- return 0;
- }
-
- /*
- * Trouble. For backwards-compatibility reasons, we issue the error
- * message as if it were a notice (would be nice to get rid of this
- * silliness, but too many apps probably don't handle errors from
- * PQendcopy reasonably). Note that the app can still obtain the error
- * status from the PGconn object.
- */
- if (conn->errorMessage.len > 0)
- {
- /* We have to strip the trailing newline ... pain in neck... */
- char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
-
- if (svLast == '\n')
- conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
- pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
- conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
- }
-
- PQclear(result);
-
- /*
- * The worst case is that we've lost sync with the backend entirely due to
- * application screwup of the copy in/out protocol. To recover, reset the
- * connection (talk about using a sledgehammer...)
- */
- pqInternalNotice(&conn->noticeHooks,
- "lost synchronization with server, resetting connection");
-
- /*
- * Users doing non-blocking connections need to handle the reset
- * themselves, they'll need to check the connection status if we return an
- * error.
- */
- if (pqIsnonblocking(conn))
- PQresetStart(conn);
- else
- PQreset(conn);
-
- return 1;
-}
-
-
-/*
- * PQfn - Send a function call to the POSTGRES backend.
- *
- * See fe-exec.c for documentation.
- */
-PGresult *
-pqFunctionCall2(PGconn *conn, Oid fnid,
- int *result_buf, int *actual_result_len,
- int result_is_int,
- const PQArgBlock *args, int nargs)
-{
- bool needInput = false;
- ExecStatusType status = PGRES_FATAL_ERROR;
- char id;
- int i;
-
- /* PQfn already validated connection state */
-
- if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
- pqPuts(" ", conn) < 0 || /* dummy string */
- pqPutInt(fnid, 4, conn) != 0 || /* function id */
- pqPutInt(nargs, 4, conn) != 0) /* # of args */
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
-
- for (i = 0; i < nargs; ++i)
- { /* len.int4 + contents */
- if (pqPutInt(args[i].len, 4, conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
-
- if (args[i].isint)
- {
- if (pqPutInt(args[i].u.integer, 4, conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
- }
- else
- {
- if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
- }
- }
-
- if (pqPutMsgEnd(conn) < 0 ||
- pqFlush(conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
-
- for (;;)
- {
- if (needInput)
- {
- /* Wait for some data to arrive (or for the channel to close) */
- if (pqWait(TRUE, FALSE, conn) ||
- pqReadData(conn) < 0)
- break;
- }
-
- /*
- * Scan the message. If we run out of data, loop around to try again.
- */
- conn->inCursor = conn->inStart;
- needInput = true;
-
- if (pqGetc(&id, conn))
- continue;
-
- /*
- * We should see V or E response to the command, but might get N
- * and/or A notices first. We also need to swallow the final Z before
- * returning.
- */
- switch (id)
- {
- case 'V': /* function result */
- if (pqGetc(&id, conn))
- continue;
- if (id == 'G')
- {
- /* function returned nonempty value */
- if (pqGetInt(actual_result_len, 4, conn))
- continue;
- if (result_is_int)
- {
- if (pqGetInt(result_buf, 4, conn))
- continue;
- }
- else
- {
- if (pqGetnchar((char *) result_buf,
- *actual_result_len,
- conn))
- continue;
- }
- if (pqGetc(&id, conn)) /* get the last '0' */
- continue;
- }
- if (id == '0')
- {
- /* correctly finished function result message */
- status = PGRES_COMMAND_OK;
- }
- else
- {
- /* The backend violates the protocol. */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("protocol error: id=0x%x\n"),
- id);
- pqSaveErrorResult(conn);
- conn->inStart = conn->inCursor;
- return pqPrepareAsyncResult(conn);
- }
- break;
- case 'E': /* error return */
- if (pqGetErrorNotice2(conn, true))
- continue;
- status = PGRES_FATAL_ERROR;
- break;
- case 'A': /* notify message */
- /* handle notify and go back to processing return values */
- if (getNotify(conn))
- continue;
- break;
- case 'N': /* notice */
- /* handle notice and go back to processing return values */
- if (pqGetErrorNotice2(conn, false))
- continue;
- break;
- case 'Z': /* backend is ready for new query */
- /* consume the message and exit */
- conn->inStart = conn->inCursor;
- /* if we saved a result object (probably an error), use it */
- if (conn->result)
- return pqPrepareAsyncResult(conn);
- return PQmakeEmptyPGresult(conn, status);
- default:
- /* The backend violates the protocol. */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("protocol error: id=0x%x\n"),
- id);
- pqSaveErrorResult(conn);
- conn->inStart = conn->inCursor;
- return pqPrepareAsyncResult(conn);
- }
- /* Completed this message, keep going */
- conn->inStart = conn->inCursor;
- needInput = false;
- }
-
- /*
- * We fall out of the loop only upon failing to read data.
- * conn->errorMessage has been set by pqWait or pqReadData. We want to
- * append it to any already-received error message.
- */
- pqSaveErrorResult(conn);
- return pqPrepareAsyncResult(conn);
-}
-
-
-/*
- * Construct startup packet
- *
- * Returns a malloc'd packet buffer, or NULL if out of memory
- */
-char *
-pqBuildStartupPacket2(PGconn *conn, int *packetlen,
- const PQEnvironmentOption *options)
-{
- StartupPacket *startpacket;
-
- *packetlen = sizeof(StartupPacket);
- startpacket = (StartupPacket *) malloc(sizeof(StartupPacket));
- if (!startpacket)
- return NULL;
-
- MemSet(startpacket, 0, sizeof(StartupPacket));
-
- startpacket->protoVersion = htonl(conn->pversion);
-
- /* strncpy is safe here: postmaster will handle full fields correctly */
- strncpy(startpacket->user, conn->pguser, SM_USER);
- strncpy(startpacket->database, conn->dbName, SM_DATABASE);
- strncpy(startpacket->tty, conn->pgtty, SM_TTY);
-
- if (conn->pgoptions)
- strncpy(startpacket->options, conn->pgoptions, SM_OPTIONS);
-
- return (char *) startpacket;
-}
diff --git a/libpq/fe-protocol3.c b/libpq/fe-protocol3.c
deleted file mode 100644
index a8a987a..0000000
--- a/libpq/fe-protocol3.c
+++ /dev/null
@@ -1,2204 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-protocol3.c
- * functions that are specific to frontend/backend protocol version 3
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-protocol3.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <fcntl.h>
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-
-#include "mb/pg_wchar.h"
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <unistd.h>
-#include <netinet/in.h>
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#include <arpa/inet.h>
-#endif
-
-
-/*
- * This macro lists the backend message types that could be "long" (more
- * than a couple of kilobytes).
- */
-#define VALID_LONG_MESSAGE_TYPE(id) \
- ((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \
- (id) == 'E' || (id) == 'N' || (id) == 'A')
-
-
-static void handleSyncLoss(PGconn *conn, char id, int msgLength);
-static int getRowDescriptions(PGconn *conn, int msgLength);
-static int getParamDescriptions(PGconn *conn, int msgLength);
-static int getAnotherTuple(PGconn *conn, int msgLength);
-static int getParameterStatus(PGconn *conn);
-static int getNotify(PGconn *conn);
-static int getCopyStart(PGconn *conn, ExecStatusType copytype);
-static int getReadyForQuery(PGconn *conn);
-static void reportErrorPosition(PQExpBuffer msg, const char *query,
- int loc, int encoding);
-static int build_startup_packet(const PGconn *conn, char *packet,
- const PQEnvironmentOption *options);
-
-
-/*
- * parseInput: if appropriate, parse input data from backend
- * until input is exhausted or a stopping state is reached.
- * Note that this function will NOT attempt to read more data from the backend.
- */
-void
-pqParseInput3(PGconn *conn)
-{
- char id;
- int msgLength;
- int avail;
-
- /*
- * Loop to parse successive complete messages available in the buffer.
- */
- for (;;)
- {
- /*
- * Try to read a message. First get the type code and length. Return
- * if not enough data.
- */
- conn->inCursor = conn->inStart;
- if (pqGetc(&id, conn))
- return;
- if (pqGetInt(&msgLength, 4, conn))
- return;
-
- /*
- * Try to validate message type/length here. A length less than 4 is
- * definitely broken. Large lengths should only be believed for a few
- * message types.
- */
- if (msgLength < 4)
- {
- handleSyncLoss(conn, id, msgLength);
- return;
- }
- if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
- {
- handleSyncLoss(conn, id, msgLength);
- return;
- }
-
- /*
- * Can't process if message body isn't all here yet.
- */
- msgLength -= 4;
- avail = conn->inEnd - conn->inCursor;
- if (avail < msgLength)
- {
- /*
- * Before returning, enlarge the input buffer if needed to hold
- * the whole message. This is better than leaving it to
- * pqReadData because we can avoid multiple cycles of realloc()
- * when the message is large; also, we can implement a reasonable
- * recovery strategy if we are unable to make the buffer big
- * enough.
- */
- if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
- conn))
- {
- /*
- * XXX add some better recovery code... plan is to skip over
- * the message using its length, then report an error. For the
- * moment, just treat this like loss of sync (which indeed it
- * might be!)
- */
- handleSyncLoss(conn, id, msgLength);
- }
- return;
- }
-
- /*
- * NOTIFY and NOTICE messages can happen in any state; always process
- * them right away.
- *
- * Most other messages should only be processed while in BUSY state.
- * (In particular, in READY state we hold off further parsing until
- * the application collects the current PGresult.)
- *
- * However, if the state is IDLE then we got trouble; we need to deal
- * with the unexpected message somehow.
- *
- * ParameterStatus ('S') messages are a special case: in IDLE state we
- * must process 'em (this case could happen if a new value was adopted
- * from config file due to SIGHUP), but otherwise we hold off until
- * BUSY state.
- */
- if (id == 'A')
- {
- if (getNotify(conn))
- return;
- }
- else if (id == 'N')
- {
- if (pqGetErrorNotice3(conn, false))
- return;
- }
- else if (conn->asyncStatus != PGASYNC_BUSY)
- {
- /* If not IDLE state, just wait ... */
- if (conn->asyncStatus != PGASYNC_IDLE)
- return;
-
- /*
- * Unexpected message in IDLE state; need to recover somehow.
- * ERROR messages are handled using the notice processor;
- * ParameterStatus is handled normally; anything else is just
- * dropped on the floor after displaying a suitable warning
- * notice. (An ERROR is very possibly the backend telling us why
- * it is about to close the connection, so we don't want to just
- * discard it...)
- */
- if (id == 'E')
- {
- if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
- return;
- }
- else if (id == 'S')
- {
- if (getParameterStatus(conn))
- return;
- }
- else
- {
- pqInternalNotice(&conn->noticeHooks,
- "message type 0x%02x arrived from server while idle",
- id);
- /* Discard the unexpected message */
- conn->inCursor += msgLength;
- }
- }
- else
- {
- /*
- * In BUSY state, we can process everything.
- */
- switch (id)
- {
- case 'C': /* command complete */
- if (pqGets(&conn->workBuffer, conn))
- return;
- if (conn->result == NULL)
- {
- conn->result = PQmakeEmptyPGresult(conn,
- PGRES_COMMAND_OK);
- if (!conn->result)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- pqSaveErrorResult(conn);
- }
- }
- if (conn->result)
- strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
- CMDSTATUS_LEN);
- conn->asyncStatus = PGASYNC_READY;
- break;
- case 'E': /* error return */
- if (pqGetErrorNotice3(conn, true))
- return;
- conn->asyncStatus = PGASYNC_READY;
- break;
- case 'Z': /* backend is ready for new query */
- if (getReadyForQuery(conn))
- return;
- conn->asyncStatus = PGASYNC_IDLE;
- break;
- case 'I': /* empty query */
- if (conn->result == NULL)
- {
- conn->result = PQmakeEmptyPGresult(conn,
- PGRES_EMPTY_QUERY);
- if (!conn->result)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- pqSaveErrorResult(conn);
- }
- }
- conn->asyncStatus = PGASYNC_READY;
- break;
- case '1': /* Parse Complete */
- /* If we're doing PQprepare, we're done; else ignore */
- if (conn->queryclass == PGQUERY_PREPARE)
- {
- if (conn->result == NULL)
- {
- conn->result = PQmakeEmptyPGresult(conn,
- PGRES_COMMAND_OK);
- if (!conn->result)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- pqSaveErrorResult(conn);
- }
- }
- conn->asyncStatus = PGASYNC_READY;
- }
- break;
- case '2': /* Bind Complete */
- case '3': /* Close Complete */
- /* Nothing to do for these message types */
- break;
- case 'S': /* parameter status */
- if (getParameterStatus(conn))
- return;
- break;
- case 'K': /* secret key data from the backend */
-
- /*
- * This is expected only during backend startup, but it's
- * just as easy to handle it as part of the main loop.
- * Save the data and continue processing.
- */
- if (pqGetInt(&(conn->be_pid), 4, conn))
- return;
- if (pqGetInt(&(conn->be_key), 4, conn))
- return;
- break;
- case 'T': /* Row Description */
- if (conn->result != NULL &&
- conn->result->resultStatus == PGRES_FATAL_ERROR)
- {
- /*
- * We've already choked for some reason. Just discard
- * the data till we get to the end of the query.
- */
- conn->inCursor += msgLength;
- }
- else if (conn->result == NULL ||
- conn->queryclass == PGQUERY_DESCRIBE)
- {
- /* First 'T' in a query sequence */
- if (getRowDescriptions(conn, msgLength))
- return;
- /* getRowDescriptions() moves inStart itself */
- continue;
- }
- else
- {
- /*
- * A new 'T' message is treated as the start of
- * another PGresult. (It is not clear that this is
- * really possible with the current backend.) We stop
- * parsing until the application accepts the current
- * result.
- */
- conn->asyncStatus = PGASYNC_READY;
- return;
- }
- break;
- case 'n': /* No Data */
-
- /*
- * NoData indicates that we will not be seeing a
- * RowDescription message because the statement or portal
- * inquired about doesn't return rows.
- *
- * If we're doing a Describe, we have to pass something
- * back to the client, so set up a COMMAND_OK result,
- * instead of TUPLES_OK. Otherwise we can just ignore
- * this message.
- */
- if (conn->queryclass == PGQUERY_DESCRIBE)
- {
- if (conn->result == NULL)
- {
- conn->result = PQmakeEmptyPGresult(conn,
- PGRES_COMMAND_OK);
- if (!conn->result)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- pqSaveErrorResult(conn);
- }
- }
- conn->asyncStatus = PGASYNC_READY;
- }
- break;
- case 't': /* Parameter Description */
- if (getParamDescriptions(conn, msgLength))
- return;
- /* getParamDescriptions() moves inStart itself */
- continue;
- case 'D': /* Data Row */
- if (conn->result != NULL &&
- conn->result->resultStatus == PGRES_TUPLES_OK)
- {
- /* Read another tuple of a normal query response */
- if (getAnotherTuple(conn, msgLength))
- return;
- /* getAnotherTuple() moves inStart itself */
- continue;
- }
- else if (conn->result != NULL &&
- conn->result->resultStatus == PGRES_FATAL_ERROR)
- {
- /*
- * We've already choked for some reason. Just discard
- * tuples till we get to the end of the query.
- */
- conn->inCursor += msgLength;
- }
- else
- {
- /* Set up to report error at end of query */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
- pqSaveErrorResult(conn);
- /* Discard the unexpected message */
- conn->inCursor += msgLength;
- }
- break;
- case 'G': /* Start Copy In */
- if (getCopyStart(conn, PGRES_COPY_IN))
- return;
- conn->asyncStatus = PGASYNC_COPY_IN;
- break;
- case 'H': /* Start Copy Out */
- if (getCopyStart(conn, PGRES_COPY_OUT))
- return;
- conn->asyncStatus = PGASYNC_COPY_OUT;
- conn->copy_already_done = 0;
- break;
- case 'W': /* Start Copy Both */
- if (getCopyStart(conn, PGRES_COPY_BOTH))
- return;
- conn->asyncStatus = PGASYNC_COPY_BOTH;
- conn->copy_already_done = 0;
- break;
- case 'd': /* Copy Data */
-
- /*
- * If we see Copy Data, just silently drop it. This would
- * only occur if application exits COPY OUT mode too
- * early.
- */
- conn->inCursor += msgLength;
- break;
- case 'c': /* Copy Done */
-
- /*
- * If we see Copy Done, just silently drop it. This is
- * the normal case during PQendcopy. We will keep
- * swallowing data, expecting to see command-complete for
- * the COPY command.
- */
- break;
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "unexpected response from server; first received character was \"%c\"\n"),
- id);
- /* build an error result holding the error message */
- pqSaveErrorResult(conn);
- /* not sure if we will see more, so go to ready state */
- conn->asyncStatus = PGASYNC_READY;
- /* Discard the unexpected message */
- conn->inCursor += msgLength;
- break;
- } /* switch on protocol character */
- }
- /* Successfully consumed this message */
- if (conn->inCursor == conn->inStart + 5 + msgLength)
- {
- /* Normal case: parsing agrees with specified length */
- conn->inStart = conn->inCursor;
- }
- else
- {
- /* Trouble --- report it */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
- id);
- /* build an error result holding the error message */
- pqSaveErrorResult(conn);
- conn->asyncStatus = PGASYNC_READY;
- /* trust the specified message length as what to skip */
- conn->inStart += 5 + msgLength;
- }
- }
-}
-
-/*
- * handleSyncLoss: clean up after loss of message-boundary sync
- *
- * There isn't really a lot we can do here except abandon the connection.
- */
-static void
-handleSyncLoss(PGconn *conn, char id, int msgLength)
-{
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "lost synchronization with server: got message type \"%c\", length %d\n"),
- id, msgLength);
- /* build an error result holding the error message */
- pqSaveErrorResult(conn);
- conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
- /* flush input data since we're giving up on processing it */
- pqDropConnection(conn, true);
- conn->status = CONNECTION_BAD; /* No more connection to backend */
-}
-
-/*
- * parseInput subroutine to read a 'T' (row descriptions) message.
- * We'll build a new PGresult structure (unless called for a Describe
- * command for a prepared statement) containing the attribute data.
- * Returns: 0 if processed message successfully, EOF to suspend parsing
- * (the latter case is not actually used currently).
- * In the former case, conn->inStart has been advanced past the message.
- */
-static int
-getRowDescriptions(PGconn *conn, int msgLength)
-{
- PGresult *result;
- int nfields;
- const char *errmsg;
- int i;
-
- /*
- * When doing Describe for a prepared statement, there'll already be a
- * PGresult created by getParamDescriptions, and we should fill data into
- * that. Otherwise, create a new, empty PGresult.
- */
- if (conn->queryclass == PGQUERY_DESCRIBE)
- {
- if (conn->result)
- result = conn->result;
- else
- result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
- }
- else
- result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
- if (!result)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
-
- /* parseInput already read the 'T' label and message length. */
- /* the next two bytes are the number of fields */
- if (pqGetInt(&(result->numAttributes), 2, conn))
- {
- /* We should not run out of data here, so complain */
- errmsg = libpq_gettext("insufficient data in \"T\" message");
- goto advance_and_error;
- }
- nfields = result->numAttributes;
-
- /* allocate space for the attribute descriptors */
- if (nfields > 0)
- {
- result->attDescs = (PGresAttDesc *)
- pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
- if (!result->attDescs)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
- MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
- }
-
- /* result->binary is true only if ALL columns are binary */
- result->binary = (nfields > 0) ? 1 : 0;
-
- /* get type info */
- for (i = 0; i < nfields; i++)
- {
- int tableid;
- int columnid;
- int typid;
- int typlen;
- int atttypmod;
- int format;
-
- if (pqGets(&conn->workBuffer, conn) ||
- pqGetInt(&tableid, 4, conn) ||
- pqGetInt(&columnid, 2, conn) ||
- pqGetInt(&typid, 4, conn) ||
- pqGetInt(&typlen, 2, conn) ||
- pqGetInt(&atttypmod, 4, conn) ||
- pqGetInt(&format, 2, conn))
- {
- /* We should not run out of data here, so complain */
- errmsg = libpq_gettext("insufficient data in \"T\" message");
- goto advance_and_error;
- }
-
- /*
- * Since pqGetInt treats 2-byte integers as unsigned, we need to
- * coerce these results to signed form.
- */
- columnid = (int) ((int16) columnid);
- typlen = (int) ((int16) typlen);
- format = (int) ((int16) format);
-
- result->attDescs[i].name = pqResultStrdup(result,
- conn->workBuffer.data);
- if (!result->attDescs[i].name)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
- result->attDescs[i].tableid = tableid;
- result->attDescs[i].columnid = columnid;
- result->attDescs[i].format = format;
- result->attDescs[i].typid = typid;
- result->attDescs[i].typlen = typlen;
- result->attDescs[i].atttypmod = atttypmod;
-
- if (format != 1)
- result->binary = 0;
- }
-
- /* Sanity check that we absorbed all the data */
- if (conn->inCursor != conn->inStart + 5 + msgLength)
- {
- errmsg = libpq_gettext("extraneous data in \"T\" message");
- goto advance_and_error;
- }
-
- /* Success! */
- conn->result = result;
-
- /* Advance inStart to show that the "T" message has been processed. */
- conn->inStart = conn->inCursor;
-
- /*
- * If we're doing a Describe, we're done, and ready to pass the result
- * back to the client.
- */
- if (conn->queryclass == PGQUERY_DESCRIBE)
- {
- conn->asyncStatus = PGASYNC_READY;
- return 0;
- }
-
- /*
- * We could perform additional setup for the new result set here, but for
- * now there's nothing else to do.
- */
-
- /* And we're done. */
- return 0;
-
-advance_and_error:
- /* Discard unsaved result, if any */
- if (result && result != conn->result)
- PQclear(result);
-
- /* Discard the failed message by pretending we read it */
- conn->inStart += 5 + msgLength;
-
- /*
- * Replace partially constructed result with an error result. First
- * discard the old result to try to win back some memory.
- */
- pqClearAsyncResult(conn);
-
- /*
- * If preceding code didn't provide an error message, assume "out of
- * memory" was meant. The advantage of having this special case is that
- * freeing the old result first greatly improves the odds that gettext()
- * will succeed in providing a translation.
- */
- if (!errmsg)
- errmsg = libpq_gettext("out of memory for query result");
-
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
- pqSaveErrorResult(conn);
-
- /*
- * Return zero to allow input parsing to continue. Subsequent "D"
- * messages will be ignored until we get to end of data, since an error
- * result is already set up.
- */
- return 0;
-}
-
-/*
- * parseInput subroutine to read a 't' (ParameterDescription) message.
- * We'll build a new PGresult structure containing the parameter data.
- * Returns: 0 if completed message, EOF if not enough data yet.
- * In the former case, conn->inStart has been advanced past the message.
- *
- * Note that if we run out of data, we have to release the partially
- * constructed PGresult, and rebuild it again next time. Fortunately,
- * that shouldn't happen often, since 't' messages usually fit in a packet.
- */
-static int
-getParamDescriptions(PGconn *conn, int msgLength)
-{
- PGresult *result;
- const char *errmsg = NULL; /* means "out of memory", see below */
- int nparams;
- int i;
-
- result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
- if (!result)
- goto advance_and_error;
-
- /* parseInput already read the 't' label and message length. */
- /* the next two bytes are the number of parameters */
- if (pqGetInt(&(result->numParameters), 2, conn))
- goto not_enough_data;
- nparams = result->numParameters;
-
- /* allocate space for the parameter descriptors */
- if (nparams > 0)
- {
- result->paramDescs = (PGresParamDesc *)
- pqResultAlloc(result, nparams * sizeof(PGresParamDesc), TRUE);
- if (!result->paramDescs)
- goto advance_and_error;
- MemSet(result->paramDescs, 0, nparams * sizeof(PGresParamDesc));
- }
-
- /* get parameter info */
- for (i = 0; i < nparams; i++)
- {
- int typid;
-
- if (pqGetInt(&typid, 4, conn))
- goto not_enough_data;
- result->paramDescs[i].typid = typid;
- }
-
- /* Sanity check that we absorbed all the data */
- if (conn->inCursor != conn->inStart + 5 + msgLength)
- {
- errmsg = libpq_gettext("extraneous data in \"t\" message");
- goto advance_and_error;
- }
-
- /* Success! */
- conn->result = result;
-
- /* Advance inStart to show that the "t" message has been processed. */
- conn->inStart = conn->inCursor;
-
- return 0;
-
-not_enough_data:
- PQclear(result);
- return EOF;
-
-advance_and_error:
- /* Discard unsaved result, if any */
- if (result && result != conn->result)
- PQclear(result);
-
- /* Discard the failed message by pretending we read it */
- conn->inStart += 5 + msgLength;
-
- /*
- * Replace partially constructed result with an error result. First
- * discard the old result to try to win back some memory.
- */
- pqClearAsyncResult(conn);
-
- /*
- * If preceding code didn't provide an error message, assume "out of
- * memory" was meant. The advantage of having this special case is that
- * freeing the old result first greatly improves the odds that gettext()
- * will succeed in providing a translation.
- */
- if (!errmsg)
- errmsg = libpq_gettext("out of memory");
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
- pqSaveErrorResult(conn);
-
- /*
- * Return zero to allow input parsing to continue. Essentially, we've
- * replaced the COMMAND_OK result with an error result, but since this
- * doesn't affect the protocol state, it's fine.
- */
- return 0;
-}
-
-/*
- * parseInput subroutine to read a 'D' (row data) message.
- * We fill rowbuf with column pointers and then call the row processor.
- * Returns: 0 if processed message successfully, EOF to suspend parsing
- * (the latter case is not actually used currently).
- * In the former case, conn->inStart has been advanced past the message.
- */
-static int
-getAnotherTuple(PGconn *conn, int msgLength)
-{
- PGresult *result = conn->result;
- int nfields = result->numAttributes;
- const char *errmsg;
- PGdataValue *rowbuf;
- int tupnfields; /* # fields from tuple */
- int vlen; /* length of the current field value */
- int i;
-
- /* Get the field count and make sure it's what we expect */
- if (pqGetInt(&tupnfields, 2, conn))
- {
- /* We should not run out of data here, so complain */
- errmsg = libpq_gettext("insufficient data in \"D\" message");
- goto advance_and_error;
- }
-
- if (tupnfields != nfields)
- {
- errmsg = libpq_gettext("unexpected field count in \"D\" message");
- goto advance_and_error;
- }
-
- /* Resize row buffer if needed */
- rowbuf = conn->rowBuf;
- if (nfields > conn->rowBufLen)
- {
- rowbuf = (PGdataValue *) realloc(rowbuf,
- nfields * sizeof(PGdataValue));
- if (!rowbuf)
- {
- errmsg = NULL; /* means "out of memory", see below */
- goto advance_and_error;
- }
- conn->rowBuf = rowbuf;
- conn->rowBufLen = nfields;
- }
-
- /* Scan the fields */
- for (i = 0; i < nfields; i++)
- {
- /* get the value length */
- if (pqGetInt(&vlen, 4, conn))
- {
- /* We should not run out of data here, so complain */
- errmsg = libpq_gettext("insufficient data in \"D\" message");
- goto advance_and_error;
- }
- rowbuf[i].len = vlen;
-
- /*
- * rowbuf[i].value always points to the next address in the data
- * buffer even if the value is NULL. This allows row processors to
- * estimate data sizes more easily.
- */
- rowbuf[i].value = conn->inBuffer + conn->inCursor;
-
- /* Skip over the data value */
- if (vlen > 0)
- {
- if (pqSkipnchar(vlen, conn))
- {
- /* We should not run out of data here, so complain */
- errmsg = libpq_gettext("insufficient data in \"D\" message");
- goto advance_and_error;
- }
- }
- }
-
- /* Sanity check that we absorbed all the data */
- if (conn->inCursor != conn->inStart + 5 + msgLength)
- {
- errmsg = libpq_gettext("extraneous data in \"D\" message");
- goto advance_and_error;
- }
-
- /* Advance inStart to show that the "D" message has been processed. */
- conn->inStart = conn->inCursor;
-
- /* Process the collected row */
- errmsg = NULL;
- if (pqRowProcessor(conn, &errmsg))
- return 0; /* normal, successful exit */
-
- goto set_error_result; /* pqRowProcessor failed, report it */
-
-advance_and_error:
- /* Discard the failed message by pretending we read it */
- conn->inStart += 5 + msgLength;
-
-set_error_result:
-
- /*
- * Replace partially constructed result with an error result. First
- * discard the old result to try to win back some memory.
- */
- pqClearAsyncResult(conn);
-
- /*
- * If preceding code didn't provide an error message, assume "out of
- * memory" was meant. The advantage of having this special case is that
- * freeing the old result first greatly improves the odds that gettext()
- * will succeed in providing a translation.
- */
- if (!errmsg)
- errmsg = libpq_gettext("out of memory for query result");
-
- printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
- pqSaveErrorResult(conn);
-
- /*
- * Return zero to allow input parsing to continue. Subsequent "D"
- * messages will be ignored until we get to end of data, since an error
- * result is already set up.
- */
- return 0;
-}
-
-
-/*
- * Attempt to read an Error or Notice response message.
- * This is possible in several places, so we break it out as a subroutine.
- * Entry: 'E' or 'N' message type and length have already been consumed.
- * Exit: returns 0 if successfully consumed message.
- * returns EOF if not enough data.
- */
-int
-pqGetErrorNotice3(PGconn *conn, bool isError)
-{
- PGresult *res = NULL;
- bool have_position = false;
- PQExpBufferData workBuf;
- char id;
-
- /*
- * Since the fields might be pretty long, we create a temporary
- * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
- * for stuff that is expected to be short. We shouldn't use
- * conn->errorMessage either, since this might be only a notice.
- */
- initPQExpBuffer(&workBuf);
-
- /*
- * Make a PGresult to hold the accumulated fields. We temporarily lie
- * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
- * copy conn->errorMessage.
- *
- * NB: This allocation can fail, if you run out of memory. The rest of the
- * function handles that gracefully, and we still try to set the error
- * message as the connection's error message.
- */
- res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
- if (res)
- res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
-
- /*
- * Read the fields and save into res.
- *
- * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
- * we saw a PG_DIAG_STATEMENT_POSITION field.
- */
- for (;;)
- {
- if (pqGetc(&id, conn))
- goto fail;
- if (id == '\0')
- break; /* terminator found */
- if (pqGets(&workBuf, conn))
- goto fail;
- pqSaveMessageField(res, id, workBuf.data);
- if (id == PG_DIAG_SQLSTATE)
- strlcpy(conn->last_sqlstate, workBuf.data,
- sizeof(conn->last_sqlstate));
- else if (id == PG_DIAG_STATEMENT_POSITION)
- have_position = true;
- }
-
- /*
- * Save the active query text, if any, into res as well; but only if we
- * might need it for an error cursor display, which is only true if there
- * is a PG_DIAG_STATEMENT_POSITION field.
- */
- if (have_position && conn->last_query && res)
- res->errQuery = pqResultStrdup(res, conn->last_query);
-
- /*
- * Now build the "overall" error message for PQresultErrorMessage.
- */
- resetPQExpBuffer(&workBuf);
- pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
-
- /*
- * Either save error as current async result, or just emit the notice.
- */
- if (isError)
- {
- if (res)
- res->errMsg = pqResultStrdup(res, workBuf.data);
- pqClearAsyncResult(conn);
- conn->result = res;
- if (PQExpBufferDataBroken(workBuf))
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory"));
- else
- appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
- }
- else
- {
- /* if we couldn't allocate the result set, just discard the NOTICE */
- if (res)
- {
- /* We can cheat a little here and not copy the message. */
- res->errMsg = workBuf.data;
- if (res->noticeHooks.noticeRec != NULL)
- (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
- PQclear(res);
- }
- }
-
- termPQExpBuffer(&workBuf);
- return 0;
-
-fail:
- PQclear(res);
- termPQExpBuffer(&workBuf);
- return EOF;
-}
-
-/*
- * Construct an error message from the fields in the given PGresult,
- * appending it to the contents of "msg".
- */
-void
-pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
- PGVerbosity verbosity, PGContextVisibility show_context)
-{
- const char *val;
- const char *querytext = NULL;
- int querypos = 0;
-
- /* If we couldn't allocate a PGresult, just say "out of memory" */
- if (res == NULL)
- {
- appendPQExpBuffer(msg, libpq_gettext("out of memory\n"));
- return;
- }
-
- /*
- * If we don't have any broken-down fields, just return the base message.
- * This mainly applies if we're given a libpq-generated error result.
- */
- if (res->errFields == NULL)
- {
- if (res->errMsg && res->errMsg[0])
- appendPQExpBufferStr(msg, res->errMsg);
- else
- appendPQExpBuffer(msg, libpq_gettext("no error message available\n"));
- return;
- }
-
- /* Else build error message from relevant fields */
- val = PQresultErrorField(res, PG_DIAG_SEVERITY);
- if (val)
- appendPQExpBuffer(msg, "%s: ", val);
- if (verbosity == PQERRORS_VERBOSE)
- {
- val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
- if (val)
- appendPQExpBuffer(msg, "%s: ", val);
- }
- val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
- if (val)
- appendPQExpBufferStr(msg, val);
- val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
- if (val)
- {
- if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
- {
- /* emit position as a syntax cursor display */
- querytext = res->errQuery;
- querypos = atoi(val);
- }
- else
- {
- /* emit position as text addition to primary message */
- /* translator: %s represents a digit string */
- appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
- val);
- }
- }
- else
- {
- val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
- if (val)
- {
- querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
- if (verbosity != PQERRORS_TERSE && querytext != NULL)
- {
- /* emit position as a syntax cursor display */
- querypos = atoi(val);
- }
- else
- {
- /* emit position as text addition to primary message */
- /* translator: %s represents a digit string */
- appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
- val);
- }
- }
- }
- appendPQExpBufferChar(msg, '\n');
- if (verbosity != PQERRORS_TERSE)
- {
- if (querytext && querypos > 0)
- reportErrorPosition(msg, querytext, querypos,
- res->client_encoding);
- val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
- if (val)
- appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
- val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
- if (val)
- appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
- val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
- if (val)
- appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
- if (show_context == PQSHOW_CONTEXT_ALWAYS ||
- (show_context == PQSHOW_CONTEXT_ERRORS &&
- res->resultStatus == PGRES_FATAL_ERROR))
- {
- val = PQresultErrorField(res, PG_DIAG_CONTEXT);
- if (val)
- appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
- val);
- }
- }
- if (verbosity == PQERRORS_VERBOSE)
- {
- val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
- if (val)
- appendPQExpBuffer(msg,
- libpq_gettext("SCHEMA NAME: %s\n"), val);
- val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
- if (val)
- appendPQExpBuffer(msg,
- libpq_gettext("TABLE NAME: %s\n"), val);
- val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
- if (val)
- appendPQExpBuffer(msg,
- libpq_gettext("COLUMN NAME: %s\n"), val);
- val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
- if (val)
- appendPQExpBuffer(msg,
- libpq_gettext("DATATYPE NAME: %s\n"), val);
- val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
- if (val)
- appendPQExpBuffer(msg,
- libpq_gettext("CONSTRAINT NAME: %s\n"), val);
- }
- if (verbosity == PQERRORS_VERBOSE)
- {
- const char *valf;
- const char *vall;
-
- valf = PQresultErrorField(res, PG_DIAG_SOURCE_FILE);
- vall = PQresultErrorField(res, PG_DIAG_SOURCE_LINE);
- val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
- if (val || valf || vall)
- {
- appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
- if (val)
- appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
- if (valf && vall) /* unlikely we'd have just one */
- appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
- valf, vall);
- appendPQExpBufferChar(msg, '\n');
- }
- }
-}
-
-/*
- * Add an error-location display to the error message under construction.
- *
- * The cursor location is measured in logical characters; the query string
- * is presumed to be in the specified encoding.
- */
-static void
-reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
-{
-#define DISPLAY_SIZE 60 /* screen width limit, in screen cols */
-#define MIN_RIGHT_CUT 10 /* try to keep this far away from EOL */
-
- char *wquery;
- int slen,
- cno,
- i,
- *qidx,
- *scridx,
- qoffset,
- scroffset,
- ibeg,
- iend,
- loc_line;
- bool mb_encoding,
- beg_trunc,
- end_trunc;
-
- /* Convert loc from 1-based to 0-based; no-op if out of range */
- loc--;
- if (loc < 0)
- return;
-
- /* Need a writable copy of the query */
- wquery = strdup(query);
- if (wquery == NULL)
- return; /* fail silently if out of memory */
-
- /*
- * Each character might occupy multiple physical bytes in the string, and
- * in some Far Eastern character sets it might take more than one screen
- * column as well. We compute the starting byte offset and starting
- * screen column of each logical character, and store these in qidx[] and
- * scridx[] respectively.
- */
-
- /* we need a safe allocation size... */
- slen = strlen(wquery) + 1;
-
- qidx = (int *) malloc(slen * sizeof(int));
- if (qidx == NULL)
- {
- free(wquery);
- return;
- }
- scridx = (int *) malloc(slen * sizeof(int));
- if (scridx == NULL)
- {
- free(qidx);
- free(wquery);
- return;
- }
-
- /* We can optimize a bit if it's a single-byte encoding */
- mb_encoding = (pg_encoding_max_length(encoding) != 1);
-
- /*
- * Within the scanning loop, cno is the current character's logical
- * number, qoffset is its offset in wquery, and scroffset is its starting
- * logical screen column (all indexed from 0). "loc" is the logical
- * character number of the error location. We scan to determine loc_line
- * (the 1-based line number containing loc) and ibeg/iend (first character
- * number and last+1 character number of the line containing loc). Note
- * that qidx[] and scridx[] are filled only as far as iend.
- */
- qoffset = 0;
- scroffset = 0;
- loc_line = 1;
- ibeg = 0;
- iend = -1; /* -1 means not set yet */
-
- for (cno = 0; wquery[qoffset] != '\0'; cno++)
- {
- char ch = wquery[qoffset];
-
- qidx[cno] = qoffset;
- scridx[cno] = scroffset;
-
- /*
- * Replace tabs with spaces in the writable copy. (Later we might
- * want to think about coping with their variable screen width, but
- * not today.)
- */
- if (ch == '\t')
- wquery[qoffset] = ' ';
-
- /*
- * If end-of-line, count lines and mark positions. Each \r or \n
- * counts as a line except when \r \n appear together.
- */
- else if (ch == '\r' || ch == '\n')
- {
- if (cno < loc)
- {
- if (ch == '\r' ||
- cno == 0 ||
- wquery[qidx[cno - 1]] != '\r')
- loc_line++;
- /* extract beginning = last line start before loc. */
- ibeg = cno + 1;
- }
- else
- {
- /* set extract end. */
- iend = cno;
- /* done scanning. */
- break;
- }
- }
-
- /* Advance */
- if (mb_encoding)
- {
- int w;
-
- w = pg_encoding_dsplen(encoding, &wquery[qoffset]);
- /* treat any non-tab control chars as width 1 */
- if (w <= 0)
- w = 1;
- scroffset += w;
- qoffset += pg_encoding_mblen(encoding, &wquery[qoffset]);
- }
- else
- {
- /* We assume wide chars only exist in multibyte encodings */
- scroffset++;
- qoffset++;
- }
- }
- /* Fix up if we didn't find an end-of-line after loc */
- if (iend < 0)
- {
- iend = cno; /* query length in chars, +1 */
- qidx[iend] = qoffset;
- scridx[iend] = scroffset;
- }
-
- /* Print only if loc is within computed query length */
- if (loc <= cno)
- {
- /* If the line extracted is too long, we truncate it. */
- beg_trunc = false;
- end_trunc = false;
- if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
- {
- /*
- * We first truncate right if it is enough. This code might be
- * off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
- * character right there, but that should be okay.
- */
- if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
- {
- while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
- iend--;
- end_trunc = true;
- }
- else
- {
- /* Truncate right if not too close to loc. */
- while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
- {
- iend--;
- end_trunc = true;
- }
-
- /* Truncate left if still too long. */
- while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
- {
- ibeg++;
- beg_trunc = true;
- }
- }
- }
-
- /* truncate working copy at desired endpoint */
- wquery[qidx[iend]] = '\0';
-
- /* Begin building the finished message. */
- i = msg->len;
- appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line);
- if (beg_trunc)
- appendPQExpBufferStr(msg, "...");
-
- /*
- * While we have the prefix in the msg buffer, compute its screen
- * width.
- */
- scroffset = 0;
- for (; i < msg->len; i += pg_encoding_mblen(encoding, &msg->data[i]))
- {
- int w = pg_encoding_dsplen(encoding, &msg->data[i]);
-
- if (w <= 0)
- w = 1;
- scroffset += w;
- }
-
- /* Finish up the LINE message line. */
- appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]);
- if (end_trunc)
- appendPQExpBufferStr(msg, "...");
- appendPQExpBufferChar(msg, '\n');
-
- /* Now emit the cursor marker line. */
- scroffset += scridx[loc] - scridx[ibeg];
- for (i = 0; i < scroffset; i++)
- appendPQExpBufferChar(msg, ' ');
- appendPQExpBufferChar(msg, '^');
- appendPQExpBufferChar(msg, '\n');
- }
-
- /* Clean up. */
- free(scridx);
- free(qidx);
- free(wquery);
-}
-
-
-/*
- * Attempt to read a ParameterStatus message.
- * This is possible in several places, so we break it out as a subroutine.
- * Entry: 'S' message type and length have already been consumed.
- * Exit: returns 0 if successfully consumed message.
- * returns EOF if not enough data.
- */
-static int
-getParameterStatus(PGconn *conn)
-{
- PQExpBufferData valueBuf;
-
- /* Get the parameter name */
- if (pqGets(&conn->workBuffer, conn))
- return EOF;
- /* Get the parameter value (could be large) */
- initPQExpBuffer(&valueBuf);
- if (pqGets(&valueBuf, conn))
- {
- termPQExpBuffer(&valueBuf);
- return EOF;
- }
- /* And save it */
- pqSaveParameterStatus(conn, conn->workBuffer.data, valueBuf.data);
- termPQExpBuffer(&valueBuf);
- return 0;
-}
-
-
-/*
- * Attempt to read a Notify response message.
- * This is possible in several places, so we break it out as a subroutine.
- * Entry: 'A' message type and length have already been consumed.
- * Exit: returns 0 if successfully consumed Notify message.
- * returns EOF if not enough data.
- */
-static int
-getNotify(PGconn *conn)
-{
- int be_pid;
- char *svname;
- int nmlen;
- int extralen;
- PGnotify *newNotify;
-
- if (pqGetInt(&be_pid, 4, conn))
- return EOF;
- if (pqGets(&conn->workBuffer, conn))
- return EOF;
- /* must save name while getting extra string */
- svname = strdup(conn->workBuffer.data);
- if (!svname)
- return EOF;
- if (pqGets(&conn->workBuffer, conn))
- {
- free(svname);
- return EOF;
- }
-
- /*
- * Store the strings right after the PQnotify structure so it can all be
- * freed at once. We don't use NAMEDATALEN because we don't want to tie
- * this interface to a specific server name length.
- */
- nmlen = strlen(svname);
- extralen = strlen(conn->workBuffer.data);
- newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + extralen + 2);
- if (newNotify)
- {
- newNotify->relname = (char *) newNotify + sizeof(PGnotify);
- strcpy(newNotify->relname, svname);
- newNotify->extra = newNotify->relname + nmlen + 1;
- strcpy(newNotify->extra, conn->workBuffer.data);
- newNotify->be_pid = be_pid;
- newNotify->next = NULL;
- if (conn->notifyTail)
- conn->notifyTail->next = newNotify;
- else
- conn->notifyHead = newNotify;
- conn->notifyTail = newNotify;
- }
-
- free(svname);
- return 0;
-}
-
-/*
- * getCopyStart - process CopyInResponse, CopyOutResponse or
- * CopyBothResponse message
- *
- * parseInput already read the message type and length.
- */
-static int
-getCopyStart(PGconn *conn, ExecStatusType copytype)
-{
- PGresult *result;
- int nfields;
- int i;
-
- result = PQmakeEmptyPGresult(conn, copytype);
- if (!result)
- goto failure;
-
- if (pqGetc(&conn->copy_is_binary, conn))
- goto failure;
- result->binary = conn->copy_is_binary;
- /* the next two bytes are the number of fields */
- if (pqGetInt(&(result->numAttributes), 2, conn))
- goto failure;
- nfields = result->numAttributes;
-
- /* allocate space for the attribute descriptors */
- if (nfields > 0)
- {
- result->attDescs = (PGresAttDesc *)
- pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
- if (!result->attDescs)
- goto failure;
- MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
- }
-
- for (i = 0; i < nfields; i++)
- {
- int format;
-
- if (pqGetInt(&format, 2, conn))
- goto failure;
-
- /*
- * Since pqGetInt treats 2-byte integers as unsigned, we need to
- * coerce these results to signed form.
- */
- format = (int) ((int16) format);
- result->attDescs[i].format = format;
- }
-
- /* Success! */
- conn->result = result;
- return 0;
-
-failure:
- PQclear(result);
- return EOF;
-}
-
-/*
- * getReadyForQuery - process ReadyForQuery message
- */
-static int
-getReadyForQuery(PGconn *conn)
-{
- char xact_status;
-
- if (pqGetc(&xact_status, conn))
- return EOF;
- switch (xact_status)
- {
- case 'I':
- conn->xactStatus = PQTRANS_IDLE;
- break;
- case 'T':
- conn->xactStatus = PQTRANS_INTRANS;
- break;
- case 'E':
- conn->xactStatus = PQTRANS_INERROR;
- break;
- default:
- conn->xactStatus = PQTRANS_UNKNOWN;
- break;
- }
-
- return 0;
-}
-
-/*
- * getCopyDataMessage - fetch next CopyData message, process async messages
- *
- * Returns length word of CopyData message (> 0), or 0 if no complete
- * message available, -1 if end of copy, -2 if error.
- */
-static int
-getCopyDataMessage(PGconn *conn)
-{
- char id;
- int msgLength;
- int avail;
-
- for (;;)
- {
- /*
- * Do we have the next input message? To make life simpler for async
- * callers, we keep returning 0 until the next message is fully
- * available, even if it is not Copy Data.
- */
- conn->inCursor = conn->inStart;
- if (pqGetc(&id, conn))
- return 0;
- if (pqGetInt(&msgLength, 4, conn))
- return 0;
- if (msgLength < 4)
- {
- handleSyncLoss(conn, id, msgLength);
- return -2;
- }
- avail = conn->inEnd - conn->inCursor;
- if (avail < msgLength - 4)
- {
- /*
- * Before returning, enlarge the input buffer if needed to hold
- * the whole message. See notes in parseInput.
- */
- if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength - 4,
- conn))
- {
- /*
- * XXX add some better recovery code... plan is to skip over
- * the message using its length, then report an error. For the
- * moment, just treat this like loss of sync (which indeed it
- * might be!)
- */
- handleSyncLoss(conn, id, msgLength);
- return -2;
- }
- return 0;
- }
-
- /*
- * If it's a legitimate async message type, process it. (NOTIFY
- * messages are not currently possible here, but we handle them for
- * completeness.) Otherwise, if it's anything except Copy Data,
- * report end-of-copy.
- */
- switch (id)
- {
- case 'A': /* NOTIFY */
- if (getNotify(conn))
- return 0;
- break;
- case 'N': /* NOTICE */
- if (pqGetErrorNotice3(conn, false))
- return 0;
- break;
- case 'S': /* ParameterStatus */
- if (getParameterStatus(conn))
- return 0;
- break;
- case 'd': /* Copy Data, pass it back to caller */
- return msgLength;
- case 'c':
-
- /*
- * If this is a CopyDone message, exit COPY_OUT mode and let
- * caller read status with PQgetResult(). If we're in
- * COPY_BOTH mode, return to COPY_IN mode.
- */
- if (conn->asyncStatus == PGASYNC_COPY_BOTH)
- conn->asyncStatus = PGASYNC_COPY_IN;
- else
- conn->asyncStatus = PGASYNC_BUSY;
- return -1;
- default: /* treat as end of copy */
-
- /*
- * Any other message terminates either COPY_IN or COPY_BOTH
- * mode.
- */
- conn->asyncStatus = PGASYNC_BUSY;
- return -1;
- }
-
- /* Drop the processed message and loop around for another */
- conn->inStart = conn->inCursor;
- }
-}
-
-/*
- * PQgetCopyData - read a row of data from the backend during COPY OUT
- * or COPY BOTH
- *
- * If successful, sets *buffer to point to a malloc'd row of data, and
- * returns row length (always > 0) as result.
- * Returns 0 if no row available yet (only possible if async is true),
- * -1 if end of copy (consult PQgetResult), or -2 if error (consult
- * PQerrorMessage).
- */
-int
-pqGetCopyData3(PGconn *conn, char **buffer, int async)
-{
- int msgLength;
-
- for (;;)
- {
- /*
- * Collect the next input message. To make life simpler for async
- * callers, we keep returning 0 until the next message is fully
- * available, even if it is not Copy Data.
- */
- msgLength = getCopyDataMessage(conn);
- if (msgLength < 0)
- return msgLength; /* end-of-copy or error */
- if (msgLength == 0)
- {
- /* Don't block if async read requested */
- if (async)
- return 0;
- /* Need to load more data */
- if (pqWait(TRUE, FALSE, conn) ||
- pqReadData(conn) < 0)
- return -2;
- continue;
- }
-
- /*
- * Drop zero-length messages (shouldn't happen anyway). Otherwise
- * pass the data back to the caller.
- */
- msgLength -= 4;
- if (msgLength > 0)
- {
- *buffer = (char *) malloc(msgLength + 1);
- if (*buffer == NULL)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("out of memory\n"));
- return -2;
- }
- memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
- (*buffer)[msgLength] = '\0'; /* Add terminating null */
-
- /* Mark message consumed */
- conn->inStart = conn->inCursor + msgLength;
-
- return msgLength;
- }
-
- /* Empty, so drop it and loop around for another */
- conn->inStart = conn->inCursor;
- }
-}
-
-/*
- * PQgetline - gets a newline-terminated string from the backend.
- *
- * See fe-exec.c for documentation.
- */
-int
-pqGetline3(PGconn *conn, char *s, int maxlen)
-{
- int status;
-
- if (conn->sock == PGINVALID_SOCKET ||
- (conn->asyncStatus != PGASYNC_COPY_OUT &&
- conn->asyncStatus != PGASYNC_COPY_BOTH) ||
- conn->copy_is_binary)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PQgetline: not doing text COPY OUT\n"));
- *s = '\0';
- return EOF;
- }
-
- while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
- {
- /* need to load more data */
- if (pqWait(TRUE, FALSE, conn) ||
- pqReadData(conn) < 0)
- {
- *s = '\0';
- return EOF;
- }
- }
-
- if (status < 0)
- {
- /* End of copy detected; gin up old-style terminator */
- strcpy(s, "\\.");
- return 0;
- }
-
- /* Add null terminator, and strip trailing \n if present */
- if (s[status - 1] == '\n')
- {
- s[status - 1] = '\0';
- return 0;
- }
- else
- {
- s[status] = '\0';
- return 1;
- }
-}
-
-/*
- * PQgetlineAsync - gets a COPY data row without blocking.
- *
- * See fe-exec.c for documentation.
- */
-int
-pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
-{
- int msgLength;
- int avail;
-
- if (conn->asyncStatus != PGASYNC_COPY_OUT
- && conn->asyncStatus != PGASYNC_COPY_BOTH)
- return -1; /* we are not doing a copy... */
-
- /*
- * Recognize the next input message. To make life simpler for async
- * callers, we keep returning 0 until the next message is fully available
- * even if it is not Copy Data. This should keep PQendcopy from blocking.
- * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
- */
- msgLength = getCopyDataMessage(conn);
- if (msgLength < 0)
- return -1; /* end-of-copy or error */
- if (msgLength == 0)
- return 0; /* no data yet */
-
- /*
- * Move data from libpq's buffer to the caller's. In the case where a
- * prior call found the caller's buffer too small, we use
- * conn->copy_already_done to remember how much of the row was already
- * returned to the caller.
- */
- conn->inCursor += conn->copy_already_done;
- avail = msgLength - 4 - conn->copy_already_done;
- if (avail <= bufsize)
- {
- /* Able to consume the whole message */
- memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
- /* Mark message consumed */
- conn->inStart = conn->inCursor + avail;
- /* Reset state for next time */
- conn->copy_already_done = 0;
- return avail;
- }
- else
- {
- /* We must return a partial message */
- memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
- /* The message is NOT consumed from libpq's buffer */
- conn->copy_already_done += bufsize;
- return bufsize;
- }
-}
-
-/*
- * PQendcopy
- *
- * See fe-exec.c for documentation.
- */
-int
-pqEndcopy3(PGconn *conn)
-{
- PGresult *result;
-
- if (conn->asyncStatus != PGASYNC_COPY_IN &&
- conn->asyncStatus != PGASYNC_COPY_OUT &&
- conn->asyncStatus != PGASYNC_COPY_BOTH)
- {
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("no COPY in progress\n"));
- return 1;
- }
-
- /* Send the CopyDone message if needed */
- if (conn->asyncStatus == PGASYNC_COPY_IN ||
- conn->asyncStatus == PGASYNC_COPY_BOTH)
- {
- if (pqPutMsgStart('c', false, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return 1;
-
- /*
- * If we sent the COPY command in extended-query mode, we must issue a
- * Sync as well.
- */
- if (conn->queryclass != PGQUERY_SIMPLE)
- {
- if (pqPutMsgStart('S', false, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- return 1;
- }
- }
-
- /*
- * make sure no data is waiting to be sent, abort if we are non-blocking
- * and the flush fails
- */
- if (pqFlush(conn) && pqIsnonblocking(conn))
- return 1;
-
- /* Return to active duty */
- conn->asyncStatus = PGASYNC_BUSY;
- resetPQExpBuffer(&conn->errorMessage);
-
- /*
- * Non blocking connections may have to abort at this point. If everyone
- * played the game there should be no problem, but in error scenarios the
- * expected messages may not have arrived yet. (We are assuming that the
- * backend's packetizing will ensure that CommandComplete arrives along
- * with the CopyDone; are there corner cases where that doesn't happen?)
- */
- if (pqIsnonblocking(conn) && PQisBusy(conn))
- return 1;
-
- /* Wait for the completion response */
- result = PQgetResult(conn);
-
- /* Expecting a successful result */
- if (result && result->resultStatus == PGRES_COMMAND_OK)
- {
- PQclear(result);
- return 0;
- }
-
- /*
- * Trouble. For backwards-compatibility reasons, we issue the error
- * message as if it were a notice (would be nice to get rid of this
- * silliness, but too many apps probably don't handle errors from
- * PQendcopy reasonably). Note that the app can still obtain the error
- * status from the PGconn object.
- */
- if (conn->errorMessage.len > 0)
- {
- /* We have to strip the trailing newline ... pain in neck... */
- char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
-
- if (svLast == '\n')
- conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
- pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
- conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
- }
-
- PQclear(result);
-
- return 1;
-}
-
-
-/*
- * PQfn - Send a function call to the POSTGRES backend.
- *
- * See fe-exec.c for documentation.
- */
-PGresult *
-pqFunctionCall3(PGconn *conn, Oid fnid,
- int *result_buf, int *actual_result_len,
- int result_is_int,
- const PQArgBlock *args, int nargs)
-{
- bool needInput = false;
- ExecStatusType status = PGRES_FATAL_ERROR;
- char id;
- int msgLength;
- int avail;
- int i;
-
- /* PQfn already validated connection state */
-
- if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
- pqPutInt(fnid, 4, conn) < 0 || /* function id */
- pqPutInt(1, 2, conn) < 0 || /* # of format codes */
- pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
- pqPutInt(nargs, 2, conn) < 0) /* # of args */
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
-
- for (i = 0; i < nargs; ++i)
- { /* len.int4 + contents */
- if (pqPutInt(args[i].len, 4, conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
- if (args[i].len == -1)
- continue; /* it's NULL */
-
- if (args[i].isint)
- {
- if (pqPutInt(args[i].u.integer, args[i].len, conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
- }
- else
- {
- if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
- }
- }
-
- if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
-
- if (pqPutMsgEnd(conn) < 0 ||
- pqFlush(conn))
- {
- pqHandleSendFailure(conn);
- return NULL;
- }
-
- for (;;)
- {
- if (needInput)
- {
- /* Wait for some data to arrive (or for the channel to close) */
- if (pqWait(TRUE, FALSE, conn) ||
- pqReadData(conn) < 0)
- break;
- }
-
- /*
- * Scan the message. If we run out of data, loop around to try again.
- */
- needInput = true;
-
- conn->inCursor = conn->inStart;
- if (pqGetc(&id, conn))
- continue;
- if (pqGetInt(&msgLength, 4, conn))
- continue;
-
- /*
- * Try to validate message type/length here. A length less than 4 is
- * definitely broken. Large lengths should only be believed for a few
- * message types.
- */
- if (msgLength < 4)
- {
- handleSyncLoss(conn, id, msgLength);
- break;
- }
- if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
- {
- handleSyncLoss(conn, id, msgLength);
- break;
- }
-
- /*
- * Can't process if message body isn't all here yet.
- */
- msgLength -= 4;
- avail = conn->inEnd - conn->inCursor;
- if (avail < msgLength)
- {
- /*
- * Before looping, enlarge the input buffer if needed to hold the
- * whole message. See notes in parseInput.
- */
- if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
- conn))
- {
- /*
- * XXX add some better recovery code... plan is to skip over
- * the message using its length, then report an error. For the
- * moment, just treat this like loss of sync (which indeed it
- * might be!)
- */
- handleSyncLoss(conn, id, msgLength);
- break;
- }
- continue;
- }
-
- /*
- * We should see V or E response to the command, but might get N
- * and/or A notices first. We also need to swallow the final Z before
- * returning.
- */
- switch (id)
- {
- case 'V': /* function result */
- if (pqGetInt(actual_result_len, 4, conn))
- continue;
- if (*actual_result_len != -1)
- {
- if (result_is_int)
- {
- if (pqGetInt(result_buf, *actual_result_len, conn))
- continue;
- }
- else
- {
- if (pqGetnchar((char *) result_buf,
- *actual_result_len,
- conn))
- continue;
- }
- }
- /* correctly finished function result message */
- status = PGRES_COMMAND_OK;
- break;
- case 'E': /* error return */
- if (pqGetErrorNotice3(conn, true))
- continue;
- status = PGRES_FATAL_ERROR;
- break;
- case 'A': /* notify message */
- /* handle notify and go back to processing return values */
- if (getNotify(conn))
- continue;
- break;
- case 'N': /* notice */
- /* handle notice and go back to processing return values */
- if (pqGetErrorNotice3(conn, false))
- continue;
- break;
- case 'Z': /* backend is ready for new query */
- if (getReadyForQuery(conn))
- continue;
- /* consume the message and exit */
- conn->inStart += 5 + msgLength;
- /* if we saved a result object (probably an error), use it */
- if (conn->result)
- return pqPrepareAsyncResult(conn);
- return PQmakeEmptyPGresult(conn, status);
- case 'S': /* parameter status */
- if (getParameterStatus(conn))
- continue;
- break;
- default:
- /* The backend violates the protocol. */
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("protocol error: id=0x%x\n"),
- id);
- pqSaveErrorResult(conn);
- /* trust the specified message length as what to skip */
- conn->inStart += 5 + msgLength;
- return pqPrepareAsyncResult(conn);
- }
- /* Completed this message, keep going */
- /* trust the specified message length as what to skip */
- conn->inStart += 5 + msgLength;
- needInput = false;
- }
-
- /*
- * We fall out of the loop only upon failing to read data.
- * conn->errorMessage has been set by pqWait or pqReadData. We want to
- * append it to any already-received error message.
- */
- pqSaveErrorResult(conn);
- return pqPrepareAsyncResult(conn);
-}
-
-
-/*
- * Construct startup packet
- *
- * Returns a malloc'd packet buffer, or NULL if out of memory
- */
-char *
-pqBuildStartupPacket3(PGconn *conn, int *packetlen,
- const PQEnvironmentOption *options)
-{
- char *startpacket;
-
- *packetlen = build_startup_packet(conn, NULL, options);
- startpacket = (char *) malloc(*packetlen);
- if (!startpacket)
- return NULL;
- *packetlen = build_startup_packet(conn, startpacket, options);
- return startpacket;
-}
-
-/*
- * Build a startup packet given a filled-in PGconn structure.
- *
- * We need to figure out how much space is needed, then fill it in.
- * To avoid duplicate logic, this routine is called twice: the first time
- * (with packet == NULL) just counts the space needed, the second time
- * (with packet == allocated space) fills it in. Return value is the number
- * of bytes used.
- */
-static int
-build_startup_packet(const PGconn *conn, char *packet,
- const PQEnvironmentOption *options)
-{
- int packet_len = 0;
- const PQEnvironmentOption *next_eo;
- const char *val;
-
- /* Protocol version comes first. */
- if (packet)
- {
- ProtocolVersion pv = htonl(conn->pversion);
-
- memcpy(packet + packet_len, &pv, sizeof(ProtocolVersion));
- }
- packet_len += sizeof(ProtocolVersion);
-
- /* Add user name, database name, options */
-
-#define ADD_STARTUP_OPTION(optname, optval) \
- do { \
- if (packet) \
- strcpy(packet + packet_len, optname); \
- packet_len += strlen(optname) + 1; \
- if (packet) \
- strcpy(packet + packet_len, optval); \
- packet_len += strlen(optval) + 1; \
- } while(0)
-
- if (conn->pguser && conn->pguser[0])
- ADD_STARTUP_OPTION("user", conn->pguser);
- if (conn->dbName && conn->dbName[0])
- ADD_STARTUP_OPTION("database", conn->dbName);
- if (conn->replication && conn->replication[0])
- ADD_STARTUP_OPTION("replication", conn->replication);
- if (conn->pgoptions && conn->pgoptions[0])
- ADD_STARTUP_OPTION("options", conn->pgoptions);
- if (conn->send_appname)
- {
- /* Use appname if present, otherwise use fallback */
- val = conn->appname ? conn->appname : conn->fbappname;
- if (val && val[0])
- ADD_STARTUP_OPTION("application_name", val);
- }
-
- if (conn->client_encoding_initial && conn->client_encoding_initial[0])
- ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
-
- /* Add any environment-driven GUC settings needed */
- for (next_eo = options; next_eo->envName; next_eo++)
- {
- if ((val = getenv(next_eo->envName)) != NULL)
- {
- if (pg_strcasecmp(val, "default") != 0)
- ADD_STARTUP_OPTION(next_eo->pgName, val);
- }
- }
-
- /* Add trailing terminator */
- if (packet)
- packet[packet_len] = '\0';
- packet_len++;
-
- return packet_len;
-}
diff --git a/libpq/fe-secure.c b/libpq/fe-secure.c
deleted file mode 100644
index 94e47a5..0000000
--- a/libpq/fe-secure.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * fe-secure.c
- * functions related to setting up a secure connection to the backend.
- * Secure connections are expected to provide confidentiality,
- * message integrity and endpoint authentication.
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/interfaces/libpq/fe-secure.c
- *
- * NOTES
- *
- * We don't provide informational callbacks here (like
- * info_cb() in be-secure.c), since there's no good mechanism to
- * display such information to the user.
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres_fe.h"
-
-#include <signal.h>
-#include <fcntl.h>
-#include <ctype.h>
-
-#include "libpq-fe.h"
-#include "fe-auth.h"
-#include "libpq-int.h"
-
-#ifdef WIN32
-#include "win32.h"
-#else
-#include <sys/socket.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#include <arpa/inet.h>
-#endif
-
-#include <sys/stat.h>
-
-#ifdef ENABLE_THREAD_SAFETY
-#ifdef WIN32
-#include "pthread-win32.h"
-#else
-#include <pthread.h>
-#endif
-#endif
-
-/*
- * Macros to handle disabling and then restoring the state of SIGPIPE handling.
- * On Windows, these are all no-ops since there's no SIGPIPEs.
- */
-
-#ifndef WIN32
-
-#define SIGPIPE_MASKED(conn) ((conn)->sigpipe_so || (conn)->sigpipe_flag)
-
-#ifdef ENABLE_THREAD_SAFETY
-
-struct sigpipe_info
-{
- sigset_t oldsigmask;
- bool sigpipe_pending;
- bool got_epipe;
-};
-
-#define DECLARE_SIGPIPE_INFO(spinfo) struct sigpipe_info spinfo
-
-#define DISABLE_SIGPIPE(conn, spinfo, failaction) \
- do { \
- (spinfo).got_epipe = false; \
- if (!SIGPIPE_MASKED(conn)) \
- { \
- if (pq_block_sigpipe(&(spinfo).oldsigmask, \
- &(spinfo).sigpipe_pending) < 0) \
- failaction; \
- } \
- } while (0)
-
-#define REMEMBER_EPIPE(spinfo, cond) \
- do { \
- if (cond) \
- (spinfo).got_epipe = true; \
- } while (0)
-
-#define RESTORE_SIGPIPE(conn, spinfo) \
- do { \
- if (!SIGPIPE_MASKED(conn)) \
- pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
- (spinfo).got_epipe); \
- } while (0)
-#else /* !ENABLE_THREAD_SAFETY */
-
-#define DECLARE_SIGPIPE_INFO(spinfo) pqsigfunc spinfo = NULL
-
-#define DISABLE_SIGPIPE(conn, spinfo, failaction) \
- do { \
- if (!SIGPIPE_MASKED(conn)) \
- spinfo = pqsignal(SIGPIPE, SIG_IGN); \
- } while (0)
-
-#define REMEMBER_EPIPE(spinfo, cond)
-
-#define RESTORE_SIGPIPE(conn, spinfo) \
- do { \
- if (!SIGPIPE_MASKED(conn)) \
- pqsignal(SIGPIPE, spinfo); \
- } while (0)
-#endif /* ENABLE_THREAD_SAFETY */
-#else /* WIN32 */
-
-#define DECLARE_SIGPIPE_INFO(spinfo)
-#define DISABLE_SIGPIPE(conn, spinfo, failaction)
-#define REMEMBER_EPIPE(spinfo, cond)
-#define RESTORE_SIGPIPE(conn, spinfo)
-#endif /* WIN32 */
-
-/* ------------------------------------------------------------ */
-/* Procedures common to all secure sessions */
-/* ------------------------------------------------------------ */
-
-
-/*
- * Exported function to allow application to tell us it's already
- * initialized OpenSSL.
- */
-void
-PQinitSSL(int do_init)
-{
-#ifdef USE_SSL
- pgtls_init_library(do_init, do_init);
-#endif
-}
-
-/*
- * Exported function to allow application to tell us it's already
- * initialized OpenSSL and/or libcrypto.
- */
-void
-PQinitOpenSSL(int do_ssl, int do_crypto)
-{
-#ifdef USE_SSL
- pgtls_init_library(do_ssl, do_crypto);
-#endif
-}
-
-/*
- * Initialize global SSL context
- */
-int
-pqsecure_initialize(PGconn *conn)
-{
- int r = 0;
-
-#ifdef USE_SSL
- r = pgtls_init(conn);
-#endif
-
- return r;
-}
-
-/*
- * Begin or continue negotiating a secure session.
- */
-PostgresPollingStatusType
-pqsecure_open_client(PGconn *conn)
-{
-#ifdef USE_SSL
- return pgtls_open_client(conn);
-#else
- /* shouldn't get here */
- return PGRES_POLLING_FAILED;
-#endif
-}
-
-/*
- * Close secure session.
- */
-void
-pqsecure_close(PGconn *conn)
-{
-#ifdef USE_SSL
- if (conn->ssl_in_use)
- pgtls_close(conn);
-#endif
-}
-
-/*
- * Read data from a secure connection.
- *
- * On failure, this function is responsible for putting a suitable message
- * into conn->errorMessage. The caller must still inspect errno, but only
- * to determine whether to continue/retry after error.
- */
-ssize_t
-pqsecure_read(PGconn *conn, void *ptr, size_t len)
-{
- ssize_t n;
-
-#ifdef USE_SSL
- if (conn->ssl_in_use)
- {
- n = pgtls_read(conn, ptr, len);
- }
- else
-#endif
- {
- n = pqsecure_raw_read(conn, ptr, len);
- }
-
- return n;
-}
-
-ssize_t
-pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
-{
- ssize_t n;
- int result_errno = 0;
- char sebuf[256];
-
- n = recv(conn->sock, ptr, len, 0);
-
- if (n < 0)
- {
- result_errno = SOCK_ERRNO;
-
- /* Set error message if appropriate */
- switch (result_errno)
- {
-#ifdef EAGAIN
- case EAGAIN:
-#endif
-#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- case EWOULDBLOCK:
-#endif
- case EINTR:
- /* no error message, caller is expected to retry */
- break;
-
-#ifdef ECONNRESET
- case ECONNRESET:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
- break;
-#endif
-
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not receive data from server: %s\n"),
- SOCK_STRERROR(result_errno,
- sebuf, sizeof(sebuf)));
- break;
- }
- }
-
- /* ensure we return the intended errno to caller */
- SOCK_ERRNO_SET(result_errno);
-
- return n;
-}
-
-/*
- * Write data to a secure connection.
- *
- * On failure, this function is responsible for putting a suitable message
- * into conn->errorMessage. The caller must still inspect errno, but only
- * to determine whether to continue/retry after error.
- */
-ssize_t
-pqsecure_write(PGconn *conn, const void *ptr, size_t len)
-{
- ssize_t n;
-
-#ifdef USE_SSL
- if (conn->ssl_in_use)
- {
- n = pgtls_write(conn, ptr, len);
- }
- else
-#endif
- {
- n = pqsecure_raw_write(conn, ptr, len);
- }
-
- return n;
-}
-
-ssize_t
-pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
-{
- ssize_t n;
- int flags = 0;
- int result_errno = 0;
- char sebuf[256];
-
- DECLARE_SIGPIPE_INFO(spinfo);
-
-#ifdef MSG_NOSIGNAL
- if (conn->sigpipe_flag)
- flags |= MSG_NOSIGNAL;
-
-retry_masked:
-#endif /* MSG_NOSIGNAL */
-
- DISABLE_SIGPIPE(conn, spinfo, return -1);
-
- n = send(conn->sock, ptr, len, flags);
-
- if (n < 0)
- {
- result_errno = SOCK_ERRNO;
-
- /*
- * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
- * on this machine. So, clear sigpipe_flag so we don't try the flag
- * again, and retry the send().
- */
-#ifdef MSG_NOSIGNAL
- if (flags != 0 && result_errno == EINVAL)
- {
- conn->sigpipe_flag = false;
- flags = 0;
- goto retry_masked;
- }
-#endif /* MSG_NOSIGNAL */
-
- /* Set error message if appropriate */
- switch (result_errno)
- {
-#ifdef EAGAIN
- case EAGAIN:
-#endif
-#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- case EWOULDBLOCK:
-#endif
- case EINTR:
- /* no error message, caller is expected to retry */
- break;
-
- case EPIPE:
- /* Set flag for EPIPE */
- REMEMBER_EPIPE(spinfo, true);
- /* FALL THRU */
-
-#ifdef ECONNRESET
- case ECONNRESET:
-#endif
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext(
- "server closed the connection unexpectedly\n"
- "\tThis probably means the server terminated abnormally\n"
- "\tbefore or while processing the request.\n"));
- break;
-
- default:
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not send data to server: %s\n"),
- SOCK_STRERROR(result_errno,
- sebuf, sizeof(sebuf)));
- break;
- }
- }
-
- RESTORE_SIGPIPE(conn, spinfo);
-
- /* ensure we return the intended errno to caller */
- SOCK_ERRNO_SET(result_errno);
-
- return n;
-}
-
-/* Dummy versions of SSL info functions, when built without SSL support */
-#ifndef USE_SSL
-
-int
-PQsslInUse(PGconn *conn)
-{
- return 0;
-}
-
-void *
-PQgetssl(PGconn *conn)
-{
- return NULL;
-}
-
-void *
-PQsslStruct(PGconn *conn, const char *struct_name)
-{
- return NULL;
-}
-
-const char *
-PQsslAttribute(PGconn *conn, const char *attribute_name)
-{
- return NULL;
-}
-
-const char *const *
-PQsslAttributeNames(PGconn *conn)
-{
- static const char *const result[] = {NULL};
-
- return result;
-}
-#endif /* USE_SSL */
-
-
-#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
-
-/*
- * Block SIGPIPE for this thread. This prevents send()/write() from exiting
- * the application.
- */
-int
-pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
-{
- sigset_t sigpipe_sigset;
- sigset_t sigset;
-
- sigemptyset(&sigpipe_sigset);
- sigaddset(&sigpipe_sigset, SIGPIPE);
-
- /* Block SIGPIPE and save previous mask for later reset */
- SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
- if (SOCK_ERRNO)
- return -1;
-
- /* We can have a pending SIGPIPE only if it was blocked before */
- if (sigismember(osigset, SIGPIPE))
- {
- /* Is there a pending SIGPIPE? */
- if (sigpending(&sigset) != 0)
- return -1;
-
- if (sigismember(&sigset, SIGPIPE))
- *sigpipe_pending = true;
- else
- *sigpipe_pending = false;
- }
- else
- *sigpipe_pending = false;
-
- return 0;
-}
-
-/*
- * Discard any pending SIGPIPE and reset the signal mask.
- *
- * Note: we are effectively assuming here that the C library doesn't queue
- * up multiple SIGPIPE events. If it did, then we'd accidentally leave
- * ours in the queue when an event was already pending and we got another.
- * As long as it doesn't queue multiple events, we're OK because the caller
- * can't tell the difference.
- *
- * The caller should say got_epipe = FALSE if it is certain that it
- * didn't get an EPIPE error; in that case we'll skip the clear operation
- * and things are definitely OK, queuing or no. If it got one or might have
- * gotten one, pass got_epipe = TRUE.
- *
- * We do not want this to change errno, since if it did that could lose
- * the error code from a preceding send(). We essentially assume that if
- * we were able to do pq_block_sigpipe(), this can't fail.
- */
-void
-pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
-{
- int save_errno = SOCK_ERRNO;
- int signo;
- sigset_t sigset;
-
- /* Clear SIGPIPE only if none was pending */
- if (got_epipe && !sigpipe_pending)
- {
- if (sigpending(&sigset) == 0 &&
- sigismember(&sigset, SIGPIPE))
- {
- sigset_t sigpipe_sigset;
-
- sigemptyset(&sigpipe_sigset);
- sigaddset(&sigpipe_sigset, SIGPIPE);
-
- sigwait(&sigpipe_sigset, &signo);
- }
- }
-
- /* Restore saved block mask */
- pthread_sigmask(SIG_SETMASK, osigset, NULL);
-
- SOCK_ERRNO_SET(save_errno);
-}
-
-#endif /* ENABLE_THREAD_SAFETY && !WIN32 */
diff --git a/libpq/getpeereid.c b/libpq/getpeereid.c
deleted file mode 100644
index 5f8c0be..0000000
--- a/libpq/getpeereid.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * getpeereid.c
- * get peer userid for UNIX-domain socket connection
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- *
- * IDENTIFICATION
- * src/port/getpeereid.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "c.h"
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-#ifdef HAVE_UCRED_H
-#include <ucred.h>
-#endif
-#ifdef HAVE_SYS_UCRED_H
-#include <sys/ucred.h>
-#endif
-
-
-/*
- * BSD-style getpeereid() for platforms that lack it.
- */
-int
-getpeereid(int sock, uid_t *uid, gid_t *gid)
-{
-#if defined(SO_PEERCRED)
- /* Linux: use getsockopt(SO_PEERCRED) */
- struct ucred peercred;
- ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
- if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
- so_len != sizeof(peercred))
- return -1;
- *uid = peercred.uid;
- *gid = peercred.gid;
- return 0;
-#elif defined(LOCAL_PEERCRED)
- /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
- struct xucred peercred;
- ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
- if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
- so_len != sizeof(peercred) ||
- peercred.cr_version != XUCRED_VERSION)
- return -1;
- *uid = peercred.cr_uid;
- *gid = peercred.cr_gid;
- return 0;
-#elif defined(HAVE_GETPEERUCRED)
- /* Solaris: use getpeerucred() */
- ucred_t *ucred;
-
- ucred = NULL; /* must be initialized to NULL */
- if (getpeerucred(sock, &ucred) == -1)
- return -1;
-
- *uid = ucred_geteuid(ucred);
- *gid = ucred_getegid(ucred);
- ucred_free(ucred);
-
- if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1))
- return -1;
- return 0;
-#else
- /* No implementation available on this platform */
- errno = ENOSYS;
- return -1;
-#endif
-}
diff --git a/libpq/inet_net_ntop.c b/libpq/inet_net_ntop.c
deleted file mode 100644
index 047895e..0000000
--- a/libpq/inet_net_ntop.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1996,1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * src/backend/utils/adt/inet_net_ntop.c
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 marka Exp $";
-#endif
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#ifndef FRONTEND
-#include "utils/inet.h"
-#else
-/*
- * In a frontend build, we can't include inet.h, but we still need to have
- * sensible definitions of these two constants. Note that inet_net_ntop()
- * assumes that PGSQL_AF_INET is equal to AF_INET.
- */
-#define PGSQL_AF_INET (AF_INET + 0)
-#define PGSQL_AF_INET6 (AF_INET + 1)
-#endif
-
-
-#define NS_IN6ADDRSZ 16
-#define NS_INT16SZ 2
-
-#ifdef SPRINTF_CHAR
-#define SPRINTF(x) strlen(sprintf/**/x)
-#else
-#define SPRINTF(x) ((size_t)sprintf x)
-#endif
-
-static char *inet_net_ntop_ipv4(const u_char *src, int bits,
- char *dst, size_t size);
-static char *inet_net_ntop_ipv6(const u_char *src, int bits,
- char *dst, size_t size);
-
-
-/*
- * char *
- * inet_net_ntop(af, src, bits, dst, size)
- * convert host/network address from network to presentation format.
- * "src"'s size is determined from its "af".
- * return:
- * pointer to dst, or NULL if an error occurred (check errno).
- * note:
- * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
- * as called for by inet_net_pton() but it can be a host address with
- * an included netmask.
- * author:
- * Paul Vixie (ISC), October 1998
- */
-char *
-inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
-{
- /*
- * We need to cover both the address family constants used by the PG inet
- * type (PGSQL_AF_INET and PGSQL_AF_INET6) and those used by the system
- * libraries (AF_INET and AF_INET6). We can safely assume PGSQL_AF_INET
- * == AF_INET, but the INET6 constants are very likely to be different. If
- * AF_INET6 isn't defined, silently ignore it.
- */
- switch (af)
- {
- case PGSQL_AF_INET:
- return (inet_net_ntop_ipv4(src, bits, dst, size));
- case PGSQL_AF_INET6:
-#if defined(AF_INET6) && AF_INET6 != PGSQL_AF_INET6
- case AF_INET6:
-#endif
- return (inet_net_ntop_ipv6(src, bits, dst, size));
- default:
- errno = EAFNOSUPPORT;
- return (NULL);
- }
-}
-
-/*
- * static char *
- * inet_net_ntop_ipv4(src, bits, dst, size)
- * convert IPv4 network address from network to presentation format.
- * "src"'s size is determined from its "af".
- * return:
- * pointer to dst, or NULL if an error occurred (check errno).
- * note:
- * network byte order assumed. this means 192.5.5.240/28 has
- * 0b11110000 in its fourth octet.
- * author:
- * Paul Vixie (ISC), October 1998
- */
-static char *
-inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
-{
- char *odst = dst;
- char *t;
- int len = 4;
- int b;
-
- if (bits < 0 || bits > 32)
- {
- errno = EINVAL;
- return (NULL);
- }
-
- /* Always format all four octets, regardless of mask length. */
- for (b = len; b > 0; b--)
- {
- if (size <= sizeof ".255")
- goto emsgsize;
- t = dst;
- if (dst != odst)
- *dst++ = '.';
- dst += SPRINTF((dst, "%u", *src++));
- size -= (size_t) (dst - t);
- }
-
- /* don't print masklen if 32 bits */
- if (bits != 32)
- {
- if (size <= sizeof "/32")
- goto emsgsize;
- dst += SPRINTF((dst, "/%u", bits));
- }
-
- return (odst);
-
-emsgsize:
- errno = EMSGSIZE;
- return (NULL);
-}
-
-static int
-decoct(const u_char *src, int bytes, char *dst, size_t size)
-{
- char *odst = dst;
- char *t;
- int b;
-
- for (b = 1; b <= bytes; b++)
- {
- if (size <= sizeof "255.")
- return (0);
- t = dst;
- dst += SPRINTF((dst, "%u", *src++));
- if (b != bytes)
- {
- *dst++ = '.';
- *dst = '\0';
- }
- size -= (size_t) (dst - t);
- }
- return (dst - odst);
-}
-
-static char *
-inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
-{
- /*
- * Note that int32_t and int16_t need only be "at least" large enough to
- * contain a value of the specified size. On some systems, like Crays,
- * there is no such thing as an integer variable with 16 bits. Keep this
- * in mind if you think this function should have been coded to use
- * pointer overlays. All the world's not a VAX.
- */
- char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
- char *tp;
- struct
- {
- int base,
- len;
- } best, cur;
- u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
- int i;
-
- if ((bits < -1) || (bits > 128))
- {
- errno = EINVAL;
- return (NULL);
- }
-
- /*
- * Preprocess: Copy the input (bytewise) array into a wordwise array. Find
- * the longest run of 0x00's in src[] for :: shorthanding.
- */
- memset(words, '\0', sizeof words);
- for (i = 0; i < NS_IN6ADDRSZ; i++)
- words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
- best.base = -1;
- cur.base = -1;
- best.len = 0;
- cur.len = 0;
- for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
- {
- if (words[i] == 0)
- {
- if (cur.base == -1)
- cur.base = i, cur.len = 1;
- else
- cur.len++;
- }
- else
- {
- if (cur.base != -1)
- {
- if (best.base == -1 || cur.len > best.len)
- best = cur;
- cur.base = -1;
- }
- }
- }
- if (cur.base != -1)
- {
- if (best.base == -1 || cur.len > best.len)
- best = cur;
- }
- if (best.base != -1 && best.len < 2)
- best.base = -1;
-
- /*
- * Format the result.
- */
- tp = tmp;
- for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
- {
- /* Are we inside the best run of 0x00's? */
- if (best.base != -1 && i >= best.base &&
- i < (best.base + best.len))
- {
- if (i == best.base)
- *tp++ = ':';
- continue;
- }
- /* Are we following an initial run of 0x00s or any real hex? */
- if (i != 0)
- *tp++ = ':';
- /* Is this address an encapsulated IPv4? */
- if (i == 6 && best.base == 0 && (best.len == 6 ||
- (best.len == 7 && words[7] != 0x0001) ||
- (best.len == 5 && words[5] == 0xffff)))
- {
- int n;
-
- n = decoct(src + 12, 4, tp, sizeof tmp - (tp - tmp));
- if (n == 0)
- {
- errno = EMSGSIZE;
- return (NULL);
- }
- tp += strlen(tp);
- break;
- }
- tp += SPRINTF((tp, "%x", words[i]));
- }
-
- /* Was it a trailing run of 0x00's? */
- if (best.base != -1 && (best.base + best.len) ==
- (NS_IN6ADDRSZ / NS_INT16SZ))
- *tp++ = ':';
- *tp = '\0';
-
- if (bits != -1 && bits != 128)
- tp += SPRINTF((tp, "/%u", bits));
-
- /*
- * Check for overflow, copy, and we're done.
- */
- if ((size_t) (tp - tmp) > size)
- {
- errno = EMSGSIZE;
- return (NULL);
- }
- strcpy(dst, tmp);
- return (dst);
-}
diff --git a/libpq/ip.c b/libpq/ip.c
deleted file mode 100644
index 9591ed2..0000000
--- a/libpq/ip.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * ip.c
- * IPv6-aware network access.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/backend/libpq/ip.c
- *
- * This file and the IPV6 implementation were initially provided by
- * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
- * http://www.lbsd.net.
- *
- *-------------------------------------------------------------------------
- */
-
-/* This is intended to be used in both frontend and backend, so use c.h */
-#include "c.h"
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#include <arpa/inet.h>
-#include <sys/file.h>
-
-#include "libpq/ip.h"
-
-
-static int range_sockaddr_AF_INET(const struct sockaddr_in * addr,
- const struct sockaddr_in * netaddr,
- const struct sockaddr_in * netmask);
-
-#ifdef HAVE_IPV6
-static int range_sockaddr_AF_INET6(const struct sockaddr_in6 * addr,
- const struct sockaddr_in6 * netaddr,
- const struct sockaddr_in6 * netmask);
-#endif
-
-#ifdef HAVE_UNIX_SOCKETS
-static int getaddrinfo_unix(const char *path,
- const struct addrinfo * hintsp,
- struct addrinfo ** result);
-
-static int getnameinfo_unix(const struct sockaddr_un * sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags);
-#endif
-
-
-/*
- * pg_getaddrinfo_all - get address info for Unix, IPv4 and IPv6 sockets
- */
-int
-pg_getaddrinfo_all(const char *hostname, const char *servname,
- const struct addrinfo * hintp, struct addrinfo ** result)
-{
- int rc;
-
- /* not all versions of getaddrinfo() zero *result on failure */
- *result = NULL;
-
-#ifdef HAVE_UNIX_SOCKETS
- if (hintp->ai_family == AF_UNIX)
- return getaddrinfo_unix(servname, hintp, result);
-#endif
-
- /* NULL has special meaning to getaddrinfo(). */
- rc = getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
- servname, hintp, result);
-
- return rc;
-}
-
-
-/*
- * pg_freeaddrinfo_all - free addrinfo structures for IPv4, IPv6, or Unix
- *
- * Note: the ai_family field of the original hint structure must be passed
- * so that we can tell whether the addrinfo struct was built by the system's
- * getaddrinfo() routine or our own getaddrinfo_unix() routine. Some versions
- * of getaddrinfo() might be willing to return AF_UNIX addresses, so it's
- * not safe to look at ai_family in the addrinfo itself.
- */
-void
-pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai)
-{
-#ifdef HAVE_UNIX_SOCKETS
- if (hint_ai_family == AF_UNIX)
- {
- /* struct was built by getaddrinfo_unix (see pg_getaddrinfo_all) */
- while (ai != NULL)
- {
- struct addrinfo *p = ai;
-
- ai = ai->ai_next;
- free(p->ai_addr);
- free(p);
- }
- }
- else
-#endif /* HAVE_UNIX_SOCKETS */
- {
- /* struct was built by getaddrinfo() */
- if (ai != NULL)
- freeaddrinfo(ai);
- }
-}
-
-
-/*
- * pg_getnameinfo_all - get name info for Unix, IPv4 and IPv6 sockets
- *
- * The API of this routine differs from the standard getnameinfo() definition
- * in two ways: first, the addr parameter is declared as sockaddr_storage
- * rather than struct sockaddr, and second, the node and service fields are
- * guaranteed to be filled with something even on failure return.
- */
-int
-pg_getnameinfo_all(const struct sockaddr_storage * addr, int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags)
-{
- int rc;
-
-#ifdef HAVE_UNIX_SOCKETS
- if (addr && addr->ss_family == AF_UNIX)
- rc = getnameinfo_unix((const struct sockaddr_un *) addr, salen,
- node, nodelen,
- service, servicelen,
- flags);
- else
-#endif
- rc = getnameinfo((const struct sockaddr *) addr, salen,
- node, nodelen,
- service, servicelen,
- flags);
-
- if (rc != 0)
- {
- if (node)
- strlcpy(node, "???", nodelen);
- if (service)
- strlcpy(service, "???", servicelen);
- }
-
- return rc;
-}
-
-
-#if defined(HAVE_UNIX_SOCKETS)
-
-/* -------
- * getaddrinfo_unix - get unix socket info using IPv6-compatible API
- *
- * Bugs: only one addrinfo is set even though hintsp is NULL or
- * ai_socktype is 0
- * AI_CANONNAME is not supported.
- * -------
- */
-static int
-getaddrinfo_unix(const char *path, const struct addrinfo * hintsp,
- struct addrinfo ** result)
-{
- struct addrinfo hints;
- struct addrinfo *aip;
- struct sockaddr_un *unp;
-
- *result = NULL;
-
- MemSet(&hints, 0, sizeof(hints));
-
- if (strlen(path) >= sizeof(unp->sun_path))
- return EAI_FAIL;
-
- if (hintsp == NULL)
- {
- hints.ai_family = AF_UNIX;
- hints.ai_socktype = SOCK_STREAM;
- }
- else
- memcpy(&hints, hintsp, sizeof(hints));
-
- if (hints.ai_socktype == 0)
- hints.ai_socktype = SOCK_STREAM;
-
- if (hints.ai_family != AF_UNIX)
- {
- /* shouldn't have been called */
- return EAI_FAIL;
- }
-
- aip = calloc(1, sizeof(struct addrinfo));
- if (aip == NULL)
- return EAI_MEMORY;
-
- unp = calloc(1, sizeof(struct sockaddr_un));
- if (unp == NULL)
- {
- free(aip);
- return EAI_MEMORY;
- }
-
- aip->ai_family = AF_UNIX;
- aip->ai_socktype = hints.ai_socktype;
- aip->ai_protocol = hints.ai_protocol;
- aip->ai_next = NULL;
- aip->ai_canonname = NULL;
- *result = aip;
-
- unp->sun_family = AF_UNIX;
- aip->ai_addr = (struct sockaddr *) unp;
- aip->ai_addrlen = sizeof(struct sockaddr_un);
-
- strcpy(unp->sun_path, path);
-
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
- unp->sun_len = sizeof(struct sockaddr_un);
-#endif
-
- return 0;
-}
-
-/*
- * Convert an address to a hostname.
- */
-static int
-getnameinfo_unix(const struct sockaddr_un * sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags)
-{
- int ret = -1;
-
- /* Invalid arguments. */
- if (sa == NULL || sa->sun_family != AF_UNIX ||
- (node == NULL && service == NULL))
- return EAI_FAIL;
-
- if (node)
- {
- ret = snprintf(node, nodelen, "%s", "[local]");
- if (ret == -1 || ret > nodelen)
- return EAI_MEMORY;
- }
-
- if (service)
- {
- ret = snprintf(service, servicelen, "%s", sa->sun_path);
- if (ret == -1 || ret > servicelen)
- return EAI_MEMORY;
- }
-
- return 0;
-}
-#endif /* HAVE_UNIX_SOCKETS */
-
-
-/*
- * pg_range_sockaddr - is addr within the subnet specified by netaddr/netmask ?
- *
- * Note: caller must already have verified that all three addresses are
- * in the same address family; and AF_UNIX addresses are not supported.
- */
-int
-pg_range_sockaddr(const struct sockaddr_storage * addr,
- const struct sockaddr_storage * netaddr,
- const struct sockaddr_storage * netmask)
-{
- if (addr->ss_family == AF_INET)
- return range_sockaddr_AF_INET((const struct sockaddr_in *) addr,
- (const struct sockaddr_in *) netaddr,
- (const struct sockaddr_in *) netmask);
-#ifdef HAVE_IPV6
- else if (addr->ss_family == AF_INET6)
- return range_sockaddr_AF_INET6((const struct sockaddr_in6 *) addr,
- (const struct sockaddr_in6 *) netaddr,
- (const struct sockaddr_in6 *) netmask);
-#endif
- else
- return 0;
-}
-
-static int
-range_sockaddr_AF_INET(const struct sockaddr_in * addr,
- const struct sockaddr_in * netaddr,
- const struct sockaddr_in * netmask)
-{
- if (((addr->sin_addr.s_addr ^ netaddr->sin_addr.s_addr) &
- netmask->sin_addr.s_addr) == 0)
- return 1;
- else
- return 0;
-}
-
-
-#ifdef HAVE_IPV6
-
-static int
-range_sockaddr_AF_INET6(const struct sockaddr_in6 * addr,
- const struct sockaddr_in6 * netaddr,
- const struct sockaddr_in6 * netmask)
-{
- int i;
-
- for (i = 0; i < 16; i++)
- {
- if (((addr->sin6_addr.s6_addr[i] ^ netaddr->sin6_addr.s6_addr[i]) &
- netmask->sin6_addr.s6_addr[i]) != 0)
- return 0;
- }
-
- return 1;
-}
-#endif /* HAVE_IPV6 */
-
-/*
- * pg_sockaddr_cidr_mask - make a network mask of the appropriate family
- * and required number of significant bits
- *
- * numbits can be null, in which case the mask is fully set.
- *
- * The resulting mask is placed in *mask, which had better be big enough.
- *
- * Return value is 0 if okay, -1 if not.
- */
-int
-pg_sockaddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family)
-{
- long bits;
- char *endptr;
-
- if (numbits == NULL)
- {
- bits = (family == AF_INET) ? 32 : 128;
- }
- else
- {
- bits = strtol(numbits, &endptr, 10);
- if (*numbits == '\0' || *endptr != '\0')
- return -1;
- }
-
- switch (family)
- {
- case AF_INET:
- {
- struct sockaddr_in mask4;
- long maskl;
-
- if (bits < 0 || bits > 32)
- return -1;
- memset(&mask4, 0, sizeof(mask4));
- /* avoid "x << 32", which is not portable */
- if (bits > 0)
- maskl = (0xffffffffUL << (32 - (int) bits))
- & 0xffffffffUL;
- else
- maskl = 0;
- mask4.sin_addr.s_addr = htonl(maskl);
- memcpy(mask, &mask4, sizeof(mask4));
- break;
- }
-
-#ifdef HAVE_IPV6
- case AF_INET6:
- {
- struct sockaddr_in6 mask6;
- int i;
-
- if (bits < 0 || bits > 128)
- return -1;
- memset(&mask6, 0, sizeof(mask6));
- for (i = 0; i < 16; i++)
- {
- if (bits <= 0)
- mask6.sin6_addr.s6_addr[i] = 0;
- else if (bits >= 8)
- mask6.sin6_addr.s6_addr[i] = 0xff;
- else
- {
- mask6.sin6_addr.s6_addr[i] =
- (0xff << (8 - (int) bits)) & 0xff;
- }
- bits -= 8;
- }
- memcpy(mask, &mask6, sizeof(mask6));
- break;
- }
-#endif
- default:
- return -1;
- }
-
- mask->ss_family = family;
- return 0;
-}
-
-
-/*
- * Run the callback function for the addr/mask, after making sure the
- * mask is sane for the addr.
- */
-static void
-run_ifaddr_callback(PgIfAddrCallback callback, void *cb_data,
- struct sockaddr * addr, struct sockaddr * mask)
-{
- struct sockaddr_storage fullmask;
-
- if (!addr)
- return;
-
- /* Check that the mask is valid */
- if (mask)
- {
- if (mask->sa_family != addr->sa_family)
- {
- mask = NULL;
- }
- else if (mask->sa_family == AF_INET)
- {
- if (((struct sockaddr_in *) mask)->sin_addr.s_addr == INADDR_ANY)
- mask = NULL;
- }
-#ifdef HAVE_IPV6
- else if (mask->sa_family == AF_INET6)
- {
- if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) mask)->sin6_addr))
- mask = NULL;
- }
-#endif
- }
-
- /* If mask is invalid, generate our own fully-set mask */
- if (!mask)
- {
- pg_sockaddr_cidr_mask(&fullmask, NULL, addr->sa_family);
- mask = (struct sockaddr *) & fullmask;
- }
-
- (*callback) (addr, mask, cb_data);
-}
-
-#ifdef WIN32
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-/*
- * Enumerate the system's network interface addresses and call the callback
- * for each one. Returns 0 if successful, -1 if trouble.
- *
- * This version is for Win32. Uses the Winsock 2 functions (ie: ws2_32.dll)
- */
-int
-pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
-{
- INTERFACE_INFO *ptr,
- *ii = NULL;
- unsigned long length,
- i;
- unsigned long n_ii = 0;
- SOCKET sock;
- int error;
-
- sock = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
- if (sock == INVALID_SOCKET)
- return -1;
-
- while (n_ii < 1024)
- {
- n_ii += 64;
- ptr = realloc(ii, sizeof(INTERFACE_INFO) * n_ii);
- if (!ptr)
- {
- free(ii);
- closesocket(sock);
- errno = ENOMEM;
- return -1;
- }
-
- ii = ptr;
- if (WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0,
- ii, n_ii * sizeof(INTERFACE_INFO),
- &length, 0, 0) == SOCKET_ERROR)
- {
- error = WSAGetLastError();
- if (error == WSAEFAULT || error == WSAENOBUFS)
- continue; /* need to make the buffer bigger */
- closesocket(sock);
- free(ii);
- return -1;
- }
-
- break;
- }
-
- for (i = 0; i < length / sizeof(INTERFACE_INFO); ++i)
- run_ifaddr_callback(callback, cb_data,
- (struct sockaddr *) & ii[i].iiAddress,
- (struct sockaddr *) & ii[i].iiNetmask);
-
- closesocket(sock);
- free(ii);
- return 0;
-}
-#elif HAVE_GETIFADDRS /* && !WIN32 */
-
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
-
-/*
- * Enumerate the system's network interface addresses and call the callback
- * for each one. Returns 0 if successful, -1 if trouble.
- *
- * This version uses the getifaddrs() interface, which is available on
- * BSDs, AIX, and modern Linux.
- */
-int
-pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
-{
- struct ifaddrs *ifa,
- *l;
-
- if (getifaddrs(&ifa) < 0)
- return -1;
-
- for (l = ifa; l; l = l->ifa_next)
- run_ifaddr_callback(callback, cb_data,
- l->ifa_addr, l->ifa_netmask);
-
- freeifaddrs(ifa);
- return 0;
-}
-#else /* !HAVE_GETIFADDRS && !WIN32 */
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-/*
- * SIOCGIFCONF does not return IPv6 addresses on Solaris
- * and HP/UX. So we prefer SIOCGLIFCONF if it's available.
- *
- * On HP/UX, however, it *only* returns IPv6 addresses,
- * and the structs are named slightly differently too.
- * We'd have to do another call with SIOCGIFCONF to get the
- * IPv4 addresses as well. We don't currently bother, just
- * fall back to SIOCGIFCONF on HP/UX.
- */
-
-#if defined(SIOCGLIFCONF) && !defined(__hpux)
-
-/*
- * Enumerate the system's network interface addresses and call the callback
- * for each one. Returns 0 if successful, -1 if trouble.
- *
- * This version uses ioctl(SIOCGLIFCONF).
- */
-int
-pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
-{
- struct lifconf lifc;
- struct lifreq *lifr,
- lmask;
- struct sockaddr *addr,
- *mask;
- char *ptr,
- *buffer = NULL;
- size_t n_buffer = 1024;
- pgsocket sock,
- fd;
-
-#ifdef HAVE_IPV6
- pgsocket sock6;
-#endif
- int i,
- total;
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock == PGINVALID_SOCKET)
- return -1;
-
- while (n_buffer < 1024 * 100)
- {
- n_buffer += 1024;
- ptr = realloc(buffer, n_buffer);
- if (!ptr)
- {
- free(buffer);
- close(sock);
- errno = ENOMEM;
- return -1;
- }
-
- memset(&lifc, 0, sizeof(lifc));
- lifc.lifc_family = AF_UNSPEC;
- lifc.lifc_buf = buffer = ptr;
- lifc.lifc_len = n_buffer;
-
- if (ioctl(sock, SIOCGLIFCONF, &lifc) < 0)
- {
- if (errno == EINVAL)
- continue;
- free(buffer);
- close(sock);
- return -1;
- }
-
- /*
- * Some Unixes try to return as much data as possible, with no
- * indication of whether enough space allocated. Don't believe we have
- * it all unless there's lots of slop.
- */
- if (lifc.lifc_len < n_buffer - 1024)
- break;
- }
-
-#ifdef HAVE_IPV6
- /* We'll need an IPv6 socket too for the SIOCGLIFNETMASK ioctls */
- sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
- if (sock6 == PGINVALID_SOCKET)
- {
- free(buffer);
- close(sock);
- return -1;
- }
-#endif
-
- total = lifc.lifc_len / sizeof(struct lifreq);
- lifr = lifc.lifc_req;
- for (i = 0; i < total; ++i)
- {
- addr = (struct sockaddr *) & lifr[i].lifr_addr;
- memcpy(&lmask, &lifr[i], sizeof(struct lifreq));
-#ifdef HAVE_IPV6
- fd = (addr->sa_family == AF_INET6) ? sock6 : sock;
-#else
- fd = sock;
-#endif
- if (ioctl(fd, SIOCGLIFNETMASK, &lmask) < 0)
- mask = NULL;
- else
- mask = (struct sockaddr *) & lmask.lifr_addr;
- run_ifaddr_callback(callback, cb_data, addr, mask);
- }
-
- free(buffer);
- close(sock);
-#ifdef HAVE_IPV6
- close(sock6);
-#endif
- return 0;
-}
-#elif defined(SIOCGIFCONF)
-
-/*
- * Remaining Unixes use SIOCGIFCONF. Some only return IPv4 information
- * here, so this is the least preferred method. Note that there is no
- * standard way to iterate the struct ifreq returned in the array.
- * On some OSs the structures are padded large enough for any address,
- * on others you have to calculate the size of the struct ifreq.
- */
-
-/* Some OSs have _SIZEOF_ADDR_IFREQ, so just use that */
-#ifndef _SIZEOF_ADDR_IFREQ
-
-/* Calculate based on sockaddr.sa_len */
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-#define _SIZEOF_ADDR_IFREQ(ifr) \
- ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
- (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
- (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
-
-/* Padded ifreq structure, simple */
-#else
-#define _SIZEOF_ADDR_IFREQ(ifr) \
- sizeof (struct ifreq)
-#endif
-#endif /* !_SIZEOF_ADDR_IFREQ */
-
-/*
- * Enumerate the system's network interface addresses and call the callback
- * for each one. Returns 0 if successful, -1 if trouble.
- *
- * This version uses ioctl(SIOCGIFCONF).
- */
-int
-pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
-{
- struct ifconf ifc;
- struct ifreq *ifr,
- *end,
- addr,
- mask;
- char *ptr,
- *buffer = NULL;
- size_t n_buffer = 1024;
- pgsocket sock;
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock == PGINVALID_SOCKET)
- return -1;
-
- while (n_buffer < 1024 * 100)
- {
- n_buffer += 1024;
- ptr = realloc(buffer, n_buffer);
- if (!ptr)
- {
- free(buffer);
- close(sock);
- errno = ENOMEM;
- return -1;
- }
-
- memset(&ifc, 0, sizeof(ifc));
- ifc.ifc_buf = buffer = ptr;
- ifc.ifc_len = n_buffer;
-
- if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
- {
- if (errno == EINVAL)
- continue;
- free(buffer);
- close(sock);
- return -1;
- }
-
- /*
- * Some Unixes try to return as much data as possible, with no
- * indication of whether enough space allocated. Don't believe we have
- * it all unless there's lots of slop.
- */
- if (ifc.ifc_len < n_buffer - 1024)
- break;
- }
-
- end = (struct ifreq *) (buffer + ifc.ifc_len);
- for (ifr = ifc.ifc_req; ifr < end;)
- {
- memcpy(&addr, ifr, sizeof(addr));
- memcpy(&mask, ifr, sizeof(mask));
- if (ioctl(sock, SIOCGIFADDR, &addr, sizeof(addr)) == 0 &&
- ioctl(sock, SIOCGIFNETMASK, &mask, sizeof(mask)) == 0)
- run_ifaddr_callback(callback, cb_data,
- &addr.ifr_addr, &mask.ifr_addr);
- ifr = (struct ifreq *) ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr));
- }
-
- free(buffer);
- close(sock);
- return 0;
-}
-#else /* !defined(SIOCGIFCONF) */
-
-/*
- * Enumerate the system's network interface addresses and call the callback
- * for each one. Returns 0 if successful, -1 if trouble.
- *
- * This version is our fallback if there's no known way to get the
- * interface addresses. Just return the standard loopback addresses.
- */
-int
-pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
-{
- struct sockaddr_in addr;
- struct sockaddr_storage mask;
-
-#ifdef HAVE_IPV6
- struct sockaddr_in6 addr6;
-#endif
-
- /* addr 127.0.0.1/8 */
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = ntohl(0x7f000001);
- memset(&mask, 0, sizeof(mask));
- pg_sockaddr_cidr_mask(&mask, "8", AF_INET);
- run_ifaddr_callback(callback, cb_data,
- (struct sockaddr *) & addr,
- (struct sockaddr *) & mask);
-
-#ifdef HAVE_IPV6
- /* addr ::1/128 */
- memset(&addr6, 0, sizeof(addr6));
- addr6.sin6_family = AF_INET6;
- addr6.sin6_addr.s6_addr[15] = 1;
- memset(&mask, 0, sizeof(mask));
- pg_sockaddr_cidr_mask(&mask, "128", AF_INET6);
- run_ifaddr_callback(callback, cb_data,
- (struct sockaddr *) & addr6,
- (struct sockaddr *) & mask);
-#endif
-
- return 0;
-}
-#endif /* !defined(SIOCGIFCONF) */
-
-#endif /* !HAVE_GETIFADDRS */
diff --git a/libpq/libpq-events.c b/libpq/libpq-events.c
deleted file mode 100644
index 6db3e94..0000000
--- a/libpq/libpq-events.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * libpq-events.c
- * functions for supporting the libpq "events" API
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/interfaces/libpq/libpq-events.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include "libpq-fe.h"
-#include "libpq-int.h"
-
-
-/*
- * Registers an event proc with the given PGconn.
- *
- * The same proc can't be registered more than once in a PGconn. This
- * restriction is required because we use the proc address to identify
- * the event for purposes such as PQinstanceData().
- *
- * The name argument is used within error messages to aid in debugging.
- * A name must be supplied, but it needn't be unique. The string is
- * copied, so the passed value needn't be long-lived.
- *
- * The passThrough argument is an application specific pointer and can be set
- * to NULL if not required. It is passed through to the event proc whenever
- * the event proc is called, and is not otherwise touched by libpq.
- *
- * The function returns a non-zero if successful. If the function fails,
- * zero is returned.
- */
-int
-PQregisterEventProc(PGconn *conn, PGEventProc proc,
- const char *name, void *passThrough)
-{
- int i;
- PGEventRegister regevt;
-
- if (!proc || !conn || !name || !*name)
- return FALSE; /* bad arguments */
-
- for (i = 0; i < conn->nEvents; i++)
- {
- if (conn->events[i].proc == proc)
- return FALSE; /* already registered */
- }
-
- if (conn->nEvents >= conn->eventArraySize)
- {
- PGEvent *e;
- int newSize;
-
- newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8;
- if (conn->events)
- e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent));
- else
- e = (PGEvent *) malloc(newSize * sizeof(PGEvent));
-
- if (!e)
- return FALSE;
-
- conn->eventArraySize = newSize;
- conn->events = e;
- }
-
- conn->events[conn->nEvents].proc = proc;
- conn->events[conn->nEvents].name = strdup(name);
- if (!conn->events[conn->nEvents].name)
- return FALSE;
- conn->events[conn->nEvents].passThrough = passThrough;
- conn->events[conn->nEvents].data = NULL;
- conn->events[conn->nEvents].resultInitialized = FALSE;
- conn->nEvents++;
-
- regevt.conn = conn;
- if (!proc(PGEVT_REGISTER, &regevt, passThrough))
- {
- conn->nEvents--;
- free(conn->events[conn->nEvents].name);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * Set some "instance data" for an event within a PGconn.
- * Returns nonzero on success, zero on failure.
- */
-int
-PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
-{
- int i;
-
- if (!conn || !proc)
- return FALSE;
-
- for (i = 0; i < conn->nEvents; i++)
- {
- if (conn->events[i].proc == proc)
- {
- conn->events[i].data = data;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/*
- * Obtain the "instance data", if any, for the event.
- */
-void *
-PQinstanceData(const PGconn *conn, PGEventProc proc)
-{
- int i;
-
- if (!conn || !proc)
- return NULL;
-
- for (i = 0; i < conn->nEvents; i++)
- {
- if (conn->events[i].proc == proc)
- return conn->events[i].data;
- }
-
- return NULL;
-}
-
-/*
- * Set some "instance data" for an event within a PGresult.
- * Returns nonzero on success, zero on failure.
- */
-int
-PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
-{
- int i;
-
- if (!result || !proc)
- return FALSE;
-
- for (i = 0; i < result->nEvents; i++)
- {
- if (result->events[i].proc == proc)
- {
- result->events[i].data = data;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/*
- * Obtain the "instance data", if any, for the event.
- */
-void *
-PQresultInstanceData(const PGresult *result, PGEventProc proc)
-{
- int i;
-
- if (!result || !proc)
- return NULL;
-
- for (i = 0; i < result->nEvents; i++)
- if (result->events[i].proc == proc)
- return result->events[i].data;
-
- return NULL;
-}
-
-/*
- * Fire RESULTCREATE events for an application-created PGresult.
- *
- * The conn argument can be NULL if event procedures won't use it.
- */
-int
-PQfireResultCreateEvents(PGconn *conn, PGresult *res)
-{
- int i;
-
- if (!res)
- return FALSE;
-
- for (i = 0; i < res->nEvents; i++)
- {
- if (!res->events[i].resultInitialized)
- {
- PGEventResultCreate evt;
-
- evt.conn = conn;
- evt.result = res;
- if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
- res->events[i].passThrough))
- return FALSE;
-
- res->events[i].resultInitialized = TRUE;
- }
- }
-
- return TRUE;
-}
diff --git a/libpq/libpq-events.h b/libpq/libpq-events.h
deleted file mode 100644
index e2bdb28..0000000
--- a/libpq/libpq-events.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * libpq-events.h
- * This file contains definitions that are useful to applications
- * that invoke the libpq "events" API, but are not interesting to
- * ordinary users of libpq.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/interfaces/libpq/libpq-events.h
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef LIBPQ_EVENTS_H
-#define LIBPQ_EVENTS_H
-
-#include "libpq-fe.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* Callback Event Ids */
-typedef enum
-{
- PGEVT_REGISTER,
- PGEVT_CONNRESET,
- PGEVT_CONNDESTROY,
- PGEVT_RESULTCREATE,
- PGEVT_RESULTCOPY,
- PGEVT_RESULTDESTROY
-} PGEventId;
-
-typedef struct
-{
- PGconn *conn;
-} PGEventRegister;
-
-typedef struct
-{
- PGconn *conn;
-} PGEventConnReset;
-
-typedef struct
-{
- PGconn *conn;
-} PGEventConnDestroy;
-
-typedef struct
-{
- PGconn *conn;
- PGresult *result;
-} PGEventResultCreate;
-
-typedef struct
-{
- const PGresult *src;
- PGresult *dest;
-} PGEventResultCopy;
-
-typedef struct
-{
- PGresult *result;
-} PGEventResultDestroy;
-
-typedef int (*PGEventProc) (PGEventId evtId, void *evtInfo, void *passThrough);
-
-/* Registers an event proc with the given PGconn. */
-extern int PQregisterEventProc(PGconn *conn, PGEventProc proc,
- const char *name, void *passThrough);
-
-/* Sets the PGconn instance data for the provided proc to data. */
-extern int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data);
-
-/* Gets the PGconn instance data for the provided proc. */
-extern void *PQinstanceData(const PGconn *conn, PGEventProc proc);
-
-/* Sets the PGresult instance data for the provided proc to data. */
-extern int PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data);
-
-/* Gets the PGresult instance data for the provided proc. */
-extern void *PQresultInstanceData(const PGresult *result, PGEventProc proc);
-
-/* Fires RESULTCREATE events for an application-created PGresult. */
-extern int PQfireResultCreateEvents(PGconn *conn, PGresult *res);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBPQ_EVENTS_H */
diff --git a/libpq/libpq-fe.h b/libpq/libpq-fe.h
deleted file mode 100644
index 9ca0756..0000000
--- a/libpq/libpq-fe.h
+++ /dev/null
@@ -1,607 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * libpq-fe.h
- * This file contains definitions for structures and
- * externs for functions used by frontend postgres applications.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/interfaces/libpq/libpq-fe.h
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef LIBPQ_FE_H
-#define LIBPQ_FE_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include <stdio.h>
-
-/*
- * postgres_ext.h defines the backend's externally visible types,
- * such as Oid.
- */
-#include "postgres_ext.h"
-
-/*
- * Option flags for PQcopyResult
- */
-#define PG_COPYRES_ATTRS 0x01
-#define PG_COPYRES_TUPLES 0x02 /* Implies PG_COPYRES_ATTRS */
-#define PG_COPYRES_EVENTS 0x04
-#define PG_COPYRES_NOTICEHOOKS 0x08
-
-/* Application-visible enum types */
-
-/*
- * Although it is okay to add to these lists, values which become unused
- * should never be removed, nor should constants be redefined - that would
- * break compatibility with existing code.
- */
-
-typedef enum
-{
- CONNECTION_OK,
- CONNECTION_BAD,
- /* Non-blocking mode only below here */
-
- /*
- * The existence of these should never be relied upon - they should only
- * be used for user feedback or similar purposes.
- */
- CONNECTION_STARTED, /* Waiting for connection to be made. */
- CONNECTION_MADE, /* Connection OK; waiting to send. */
- CONNECTION_AWAITING_RESPONSE, /* Waiting for a response from the
- * postmaster. */
- CONNECTION_AUTH_OK, /* Received authentication; waiting for
- * backend startup. */
- CONNECTION_SETENV, /* Negotiating environment. */
- CONNECTION_SSL_STARTUP, /* Negotiating SSL. */
- CONNECTION_NEEDED /* Internal state: connect() needed */
-} ConnStatusType;
-
-typedef enum
-{
- PGRES_POLLING_FAILED = 0,
- PGRES_POLLING_READING, /* These two indicate that one may */
- PGRES_POLLING_WRITING, /* use select before polling again. */
- PGRES_POLLING_OK,
- PGRES_POLLING_ACTIVE /* unused; keep for awhile for backwards
- * compatibility */
-} PostgresPollingStatusType;
-
-typedef enum
-{
- PGRES_EMPTY_QUERY = 0, /* empty query string was executed */
- PGRES_COMMAND_OK, /* a query command that doesn't return
- * anything was executed properly by the
- * backend */
- PGRES_TUPLES_OK, /* a query command that returns tuples was
- * executed properly by the backend, PGresult
- * contains the result tuples */
- PGRES_COPY_OUT, /* Copy Out data transfer in progress */
- PGRES_COPY_IN, /* Copy In data transfer in progress */
- PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the
- * backend */
- PGRES_NONFATAL_ERROR, /* notice or warning message */
- PGRES_FATAL_ERROR, /* query failed */
- PGRES_COPY_BOTH, /* Copy In/Out data transfer in progress */
- PGRES_SINGLE_TUPLE /* single tuple from larger resultset */
-} ExecStatusType;
-
-typedef enum
-{
- PQTRANS_IDLE, /* connection idle */
- PQTRANS_ACTIVE, /* command in progress */
- PQTRANS_INTRANS, /* idle, within transaction block */
- PQTRANS_INERROR, /* idle, within failed transaction */
- PQTRANS_UNKNOWN /* cannot determine status */
-} PGTransactionStatusType;
-
-typedef enum
-{
- PQERRORS_TERSE, /* single-line error messages */
- PQERRORS_DEFAULT, /* recommended style */
- PQERRORS_VERBOSE /* all the facts, ma'am */
-} PGVerbosity;
-
-typedef enum
-{
- PQSHOW_CONTEXT_NEVER, /* never show CONTEXT field */
- PQSHOW_CONTEXT_ERRORS, /* show CONTEXT for errors only (default) */
- PQSHOW_CONTEXT_ALWAYS /* always show CONTEXT field */
-} PGContextVisibility;
-
-/*
- * PGPing - The ordering of this enum should not be altered because the
- * values are exposed externally via pg_isready.
- */
-
-typedef enum
-{
- PQPING_OK, /* server is accepting connections */
- PQPING_REJECT, /* server is alive but rejecting connections */
- PQPING_NO_RESPONSE, /* could not establish connection */
- PQPING_NO_ATTEMPT /* connection not attempted (bad params) */
-} PGPing;
-
-/* PGconn encapsulates a connection to the backend.
- * The contents of this struct are not supposed to be known to applications.
- */
-typedef struct pg_conn PGconn;
-
-/* PGresult encapsulates the result of a query (or more precisely, of a single
- * SQL command --- a query string given to PQsendQuery can contain multiple
- * commands and thus return multiple PGresult objects).
- * The contents of this struct are not supposed to be known to applications.
- */
-typedef struct pg_result PGresult;
-
-/* PGcancel encapsulates the information needed to cancel a running
- * query on an existing connection.
- * The contents of this struct are not supposed to be known to applications.
- */
-typedef struct pg_cancel PGcancel;
-
-/* PGnotify represents the occurrence of a NOTIFY message.
- * Ideally this would be an opaque typedef, but it's so simple that it's
- * unlikely to change.
- * NOTE: in Postgres 6.4 and later, the be_pid is the notifying backend's,
- * whereas in earlier versions it was always your own backend's PID.
- */
-typedef struct pgNotify
-{
- char *relname; /* notification condition name */
- int be_pid; /* process ID of notifying server process */
- char *extra; /* notification parameter */
- /* Fields below here are private to libpq; apps should not use 'em */
- struct pgNotify *next; /* list link */
-} PGnotify;
-
-/* Function types for notice-handling callbacks */
-typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
-typedef void (*PQnoticeProcessor) (void *arg, const char *message);
-
-/* Print options for PQprint() */
-typedef char pqbool;
-
-typedef struct _PQprintOpt
-{
- pqbool header; /* print output field headings and row count */
- pqbool align; /* fill align the fields */
- pqbool standard; /* old brain dead format */
- pqbool html3; /* output html tables */
- pqbool expanded; /* expand tables */
- pqbool pager; /* use pager for output if needed */
- char *fieldSep; /* field separator */
- char *tableOpt; /* insert to HTML <table ...> */
- char *caption; /* HTML <caption> */
- char **fieldName; /* null terminated array of replacement field
- * names */
-} PQprintOpt;
-
-/* ----------------
- * Structure for the conninfo parameter definitions returned by PQconndefaults
- * or PQconninfoParse.
- *
- * All fields except "val" point at static strings which must not be altered.
- * "val" is either NULL or a malloc'd current-value string. PQconninfoFree()
- * will release both the val strings and the PQconninfoOption array itself.
- * ----------------
- */
-typedef struct _PQconninfoOption
-{
- char *keyword; /* The keyword of the option */
- char *envvar; /* Fallback environment variable name */
- char *compiled; /* Fallback compiled in default value */
- char *val; /* Option's current value, or NULL */
- char *label; /* Label for field in connect dialog */
- char *dispchar; /* Indicates how to display this field in a
- * connect dialog. Values are: "" Display
- * entered value as is "*" Password field -
- * hide value "D" Debug option - don't show
- * by default */
- int dispsize; /* Field size in characters for dialog */
-} PQconninfoOption;
-
-/* ----------------
- * PQArgBlock -- structure for PQfn() arguments
- * ----------------
- */
-typedef struct
-{
- int len;
- int isint;
- union
- {
- int *ptr; /* can't use void (dec compiler barfs) */
- int integer;
- } u;
-} PQArgBlock;
-
-/* ----------------
- * PGresAttDesc -- Data about a single attribute (column) of a query result
- * ----------------
- */
-typedef struct pgresAttDesc
-{
- char *name; /* column name */
- Oid tableid; /* source table, if known */
- int columnid; /* source column, if known */
- int format; /* format code for value (text/binary) */
- Oid typid; /* type id */
- int typlen; /* type size */
- int atttypmod; /* type-specific modifier info */
-} PGresAttDesc;
-
-/* ----------------
- * Exported functions of libpq
- * ----------------
- */
-
-/* === in fe-connect.c === */
-
-/* make a new client connection to the backend */
-/* Asynchronous (non-blocking) */
-extern PGconn *PQconnectStart(const char *conninfo);
-extern PGconn *PQconnectStartParams(const char *const * keywords,
- const char *const * values, int expand_dbname);
-extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
-
-/* Synchronous (blocking) */
-extern PGconn *PQconnectdb(const char *conninfo);
-extern PGconn *PQconnectdbParams(const char *const * keywords,
- const char *const * values, int expand_dbname);
-extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
- const char *pgoptions, const char *pgtty,
- const char *dbName,
- const char *login, const char *pwd);
-
-#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) \
- PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL)
-
-/* close the current connection and free the PGconn data structure */
-extern void PQfinish(PGconn *conn);
-
-/* get info about connection options known to PQconnectdb */
-extern PQconninfoOption *PQconndefaults(void);
-
-/* parse connection options in same way as PQconnectdb */
-extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
-
-/* return the connection options used by a live connection */
-extern PQconninfoOption *PQconninfo(PGconn *conn);
-
-/* free the data structure returned by PQconndefaults() or PQconninfoParse() */
-extern void PQconninfoFree(PQconninfoOption *connOptions);
-
-/*
- * close the current connection and restablish a new one with the same
- * parameters
- */
-/* Asynchronous (non-blocking) */
-extern int PQresetStart(PGconn *conn);
-extern PostgresPollingStatusType PQresetPoll(PGconn *conn);
-
-/* Synchronous (blocking) */
-extern void PQreset(PGconn *conn);
-
-/* request a cancel structure */
-extern PGcancel *PQgetCancel(PGconn *conn);
-
-/* free a cancel structure */
-extern void PQfreeCancel(PGcancel *cancel);
-
-/* issue a cancel request */
-extern int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);
-
-/* backwards compatible version of PQcancel; not thread-safe */
-extern int PQrequestCancel(PGconn *conn);
-
-/* Accessor functions for PGconn objects */
-extern char *PQdb(const PGconn *conn);
-extern char *PQuser(const PGconn *conn);
-extern char *PQpass(const PGconn *conn);
-extern char *PQhost(const PGconn *conn);
-extern char *PQport(const PGconn *conn);
-extern char *PQtty(const PGconn *conn);
-extern char *PQoptions(const PGconn *conn);
-extern ConnStatusType PQstatus(const PGconn *conn);
-extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
-extern const char *PQparameterStatus(const PGconn *conn,
- const char *paramName);
-extern int PQprotocolVersion(const PGconn *conn);
-extern int PQserverVersion(const PGconn *conn);
-extern char *PQerrorMessage(const PGconn *conn);
-extern int PQsocket(const PGconn *conn);
-extern int PQbackendPID(const PGconn *conn);
-extern int PQconnectionNeedsPassword(const PGconn *conn);
-extern int PQconnectionUsedPassword(const PGconn *conn);
-extern int PQclientEncoding(const PGconn *conn);
-extern int PQsetClientEncoding(PGconn *conn, const char *encoding);
-
-/* SSL information functions */
-extern int PQsslInUse(PGconn *conn);
-extern void *PQsslStruct(PGconn *conn, const char *struct_name);
-extern const char *PQsslAttribute(PGconn *conn, const char *attribute_name);
-extern const char *const * PQsslAttributeNames(PGconn *conn);
-
-/* Get the OpenSSL structure associated with a connection. Returns NULL for
- * unencrypted connections or if any other TLS library is in use. */
-extern void *PQgetssl(PGconn *conn);
-
-/* Tell libpq whether it needs to initialize OpenSSL */
-extern void PQinitSSL(int do_init);
-
-/* More detailed way to tell libpq whether it needs to initialize OpenSSL */
-extern void PQinitOpenSSL(int do_ssl, int do_crypto);
-
-/* Set verbosity for PQerrorMessage and PQresultErrorMessage */
-extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity);
-
-/* Set CONTEXT visibility for PQerrorMessage and PQresultErrorMessage */
-extern PGContextVisibility PQsetErrorContextVisibility(PGconn *conn,
- PGContextVisibility show_context);
-
-/* Enable/disable tracing */
-extern void PQtrace(PGconn *conn, FILE *debug_port);
-extern void PQuntrace(PGconn *conn);
-
-/* Override default notice handling routines */
-extern PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn,
- PQnoticeReceiver proc,
- void *arg);
-extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
- PQnoticeProcessor proc,
- void *arg);
-
-/*
- * Used to set callback that prevents concurrent access to
- * non-thread safe functions that libpq needs.
- * The default implementation uses a libpq internal mutex.
- * Only required for multithreaded apps that use kerberos
- * both within their app and for postgresql connections.
- */
-typedef void (*pgthreadlock_t) (int acquire);
-
-extern pgthreadlock_t PQregisterThreadLock(pgthreadlock_t newhandler);
-
-/* === in fe-exec.c === */
-
-/* Simple synchronous query */
-extern PGresult *PQexec(PGconn *conn, const char *query);
-extern PGresult *PQexecParams(PGconn *conn,
- const char *command,
- int nParams,
- const Oid *paramTypes,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat);
-extern PGresult *PQprepare(PGconn *conn, const char *stmtName,
- const char *query, int nParams,
- const Oid *paramTypes);
-extern PGresult *PQexecPrepared(PGconn *conn,
- const char *stmtName,
- int nParams,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat);
-
-/* Interface for multiple-result or asynchronous queries */
-extern int PQsendQuery(PGconn *conn, const char *query);
-extern int PQsendQueryParams(PGconn *conn,
- const char *command,
- int nParams,
- const Oid *paramTypes,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat);
-extern int PQsendPrepare(PGconn *conn, const char *stmtName,
- const char *query, int nParams,
- const Oid *paramTypes);
-extern int PQsendQueryPrepared(PGconn *conn,
- const char *stmtName,
- int nParams,
- const char *const * paramValues,
- const int *paramLengths,
- const int *paramFormats,
- int resultFormat);
-extern int PQsetSingleRowMode(PGconn *conn);
-extern PGresult *PQgetResult(PGconn *conn);
-
-/* Routines for managing an asynchronous query */
-extern int PQisBusy(PGconn *conn);
-extern int PQconsumeInput(PGconn *conn);
-
-/* LISTEN/NOTIFY support */
-extern PGnotify *PQnotifies(PGconn *conn);
-
-/* Routines for copy in/out */
-extern int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
-extern int PQputCopyEnd(PGconn *conn, const char *errormsg);
-extern int PQgetCopyData(PGconn *conn, char **buffer, int async);
-
-/* Deprecated routines for copy in/out */
-extern int PQgetline(PGconn *conn, char *string, int length);
-extern int PQputline(PGconn *conn, const char *string);
-extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
-extern int PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
-extern int PQendcopy(PGconn *conn);
-
-/* Set blocking/nonblocking connection to the backend */
-extern int PQsetnonblocking(PGconn *conn, int arg);
-extern int PQisnonblocking(const PGconn *conn);
-extern int PQisthreadsafe(void);
-extern PGPing PQping(const char *conninfo);
-extern PGPing PQpingParams(const char *const * keywords,
- const char *const * values, int expand_dbname);
-
-/* Force the write buffer to be written (or at least try) */
-extern int PQflush(PGconn *conn);
-
-/*
- * "Fast path" interface --- not really recommended for application
- * use
- */
-extern PGresult *PQfn(PGconn *conn,
- int fnid,
- int *result_buf,
- int *result_len,
- int result_is_int,
- const PQArgBlock *args,
- int nargs);
-
-/* Accessor functions for PGresult objects */
-extern ExecStatusType PQresultStatus(const PGresult *res);
-extern char *PQresStatus(ExecStatusType status);
-extern char *PQresultErrorMessage(const PGresult *res);
-extern char *PQresultVerboseErrorMessage(const PGresult *res,
- PGVerbosity verbosity,
- PGContextVisibility show_context);
-extern char *PQresultErrorField(const PGresult *res, int fieldcode);
-extern int PQntuples(const PGresult *res);
-extern int PQnfields(const PGresult *res);
-extern int PQbinaryTuples(const PGresult *res);
-extern char *PQfname(const PGresult *res, int field_num);
-extern int PQfnumber(const PGresult *res, const char *field_name);
-extern Oid PQftable(const PGresult *res, int field_num);
-extern int PQftablecol(const PGresult *res, int field_num);
-extern int PQfformat(const PGresult *res, int field_num);
-extern Oid PQftype(const PGresult *res, int field_num);
-extern int PQfsize(const PGresult *res, int field_num);
-extern int PQfmod(const PGresult *res, int field_num);
-extern char *PQcmdStatus(PGresult *res);
-extern char *PQoidStatus(const PGresult *res); /* old and ugly */
-extern Oid PQoidValue(const PGresult *res); /* new and improved */
-extern char *PQcmdTuples(PGresult *res);
-extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
-extern int PQgetlength(const PGresult *res, int tup_num, int field_num);
-extern int PQgetisnull(const PGresult *res, int tup_num, int field_num);
-extern int PQnparams(const PGresult *res);
-extern Oid PQparamtype(const PGresult *res, int param_num);
-
-/* Describe prepared statements and portals */
-extern PGresult *PQdescribePrepared(PGconn *conn, const char *stmt);
-extern PGresult *PQdescribePortal(PGconn *conn, const char *portal);
-extern int PQsendDescribePrepared(PGconn *conn, const char *stmt);
-extern int PQsendDescribePortal(PGconn *conn, const char *portal);
-
-/* Delete a PGresult */
-extern void PQclear(PGresult *res);
-
-/* For freeing other alloc'd results, such as PGnotify structs */
-extern void PQfreemem(void *ptr);
-
-/* Exists for backward compatibility. bjm 2003-03-24 */
-#define PQfreeNotify(ptr) PQfreemem(ptr)
-
-/* Error when no password was given. */
-/* Note: depending on this is deprecated; use PQconnectionNeedsPassword(). */
-#define PQnoPasswordSupplied "fe_sendauth: no password supplied\n"
-
-/* Create and manipulate PGresults */
-extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
-extern PGresult *PQcopyResult(const PGresult *src, int flags);
-extern int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs);
-extern void *PQresultAlloc(PGresult *res, size_t nBytes);
-extern int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len);
-
-/* Quoting strings before inclusion in queries. */
-extern size_t PQescapeStringConn(PGconn *conn,
- char *to, const char *from, size_t length,
- int *error);
-extern char *PQescapeLiteral(PGconn *conn, const char *str, size_t len);
-extern char *PQescapeIdentifier(PGconn *conn, const char *str, size_t len);
-extern unsigned char *PQescapeByteaConn(PGconn *conn,
- const unsigned char *from, size_t from_length,
- size_t *to_length);
-extern unsigned char *PQunescapeBytea(const unsigned char *strtext,
- size_t *retbuflen);
-
-/* These forms are deprecated! */
-extern size_t PQescapeString(char *to, const char *from, size_t length);
-extern unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length,
- size_t *to_length);
-
-
-
-/* === in fe-print.c === */
-
-extern void PQprint(FILE *fout, /* output stream */
- const PGresult *res,
- const PQprintOpt *ps); /* option structure */
-
-/*
- * really old printing routines
- */
-extern void PQdisplayTuples(const PGresult *res,
- FILE *fp, /* where to send the output */
- int fillAlign, /* pad the fields with spaces */
- const char *fieldSep, /* field separator */
- int printHeader, /* display headers? */
- int quiet);
-
-extern void PQprintTuples(const PGresult *res,
- FILE *fout, /* output stream */
- int printAttName, /* print attribute names */
- int terseOutput, /* delimiter bars */
- int width); /* width of column, if 0, use variable width */
-
-
-/* === in fe-lobj.c === */
-
-/* Large-object access routines */
-extern int lo_open(PGconn *conn, Oid lobjId, int mode);
-extern int lo_close(PGconn *conn, int fd);
-extern int lo_read(PGconn *conn, int fd, char *buf, size_t len);
-extern int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
-extern int lo_lseek(PGconn *conn, int fd, int offset, int whence);
-extern pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
-extern Oid lo_creat(PGconn *conn, int mode);
-extern Oid lo_create(PGconn *conn, Oid lobjId);
-extern int lo_tell(PGconn *conn, int fd);
-extern pg_int64 lo_tell64(PGconn *conn, int fd);
-extern int lo_truncate(PGconn *conn, int fd, size_t len);
-extern int lo_truncate64(PGconn *conn, int fd, pg_int64 len);
-extern int lo_unlink(PGconn *conn, Oid lobjId);
-extern Oid lo_import(PGconn *conn, const char *filename);
-extern Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);
-extern int lo_export(PGconn *conn, Oid lobjId, const char *filename);
-
-/* === in fe-misc.c === */
-
-/* Get the version of the libpq library in use */
-extern int PQlibVersion(void);
-
-/* Determine length of multibyte encoded char at *s */
-extern int PQmblen(const char *s, int encoding);
-
-/* Determine display length of multibyte encoded char at *s */
-extern int PQdsplen(const char *s, int encoding);
-
-/* Get encoding id from environment variable PGCLIENTENCODING */
-extern int PQenv2encoding(void);
-
-/* === in fe-auth.c === */
-
-extern char *PQencryptPassword(const char *passwd, const char *user);
-
-/* === in encnames.c === */
-
-extern int pg_char_to_encoding(const char *name);
-extern const char *pg_encoding_to_char(int encoding);
-extern int pg_valid_server_encoding_id(int encoding);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBPQ_FE_H */
diff --git a/libpq/libpq-int.h b/libpq/libpq-int.h
deleted file mode 100644
index 9e4e625..0000000
--- a/libpq/libpq-int.h
+++ /dev/null
@@ -1,675 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * libpq-int.h
- * This file contains internal definitions meant to be used only by
- * the frontend libpq library, not by applications that call it.
- *
- * An application can include this file if it wants to bypass the
- * official API defined by libpq-fe.h, but code that does so is much
- * more likely to break across PostgreSQL releases than code that uses
- * only the official API.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/interfaces/libpq/libpq-int.h
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef LIBPQ_INT_H
-#define LIBPQ_INT_H
-
-/* We assume libpq-fe.h has already been included. */
-#include "postgres_fe.h"
-#include "libpq-events.h"
-
-#include <time.h>
-#include <sys/types.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-
-#ifdef ENABLE_THREAD_SAFETY
-#ifdef WIN32
-#include "pthread-win32.h"
-#else
-#include <pthread.h>
-#endif
-#include <signal.h>
-#endif
-
-/* include stuff common to fe and be */
-#include "getaddrinfo.h"
-#include "libpq/pqcomm.h"
-/* include stuff found in fe only */
-#include "pqexpbuffer.h"
-
-#ifdef ENABLE_GSS
-#if defined(HAVE_GSSAPI_H)
-#include <gssapi.h>
-#else
-#include <gssapi/gssapi.h>
-#endif
-#endif
-
-#ifdef ENABLE_SSPI
-#define SECURITY_WIN32
-#if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
-#include <ntsecapi.h>
-#endif
-#include <security.h>
-#undef SECURITY_WIN32
-
-#ifndef ENABLE_GSS
-/*
- * Define a fake structure compatible with GSSAPI on Unix.
- */
-typedef struct
-{
- void *value;
- int length;
-} gss_buffer_desc;
-#endif
-#endif /* ENABLE_SSPI */
-
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-
-#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE)
-#define USE_SSL_ENGINE
-#endif
-#endif /* USE_OPENSSL */
-
-/*
- * POSTGRES backend dependent Constants.
- */
-#define CMDSTATUS_LEN 64 /* should match COMPLETION_TAG_BUFSIZE */
-
-/*
- * PGresult and the subsidiary types PGresAttDesc, PGresAttValue
- * represent the result of a query (or more precisely, of a single SQL
- * command --- a query string given to PQexec can contain multiple commands).
- * Note we assume that a single command can return at most one tuple group,
- * hence there is no need for multiple descriptor sets.
- */
-
-/* Subsidiary-storage management structure for PGresult.
- * See space management routines in fe-exec.c for details.
- * Note that space[k] refers to the k'th byte starting from the physical
- * head of the block --- it's a union, not a struct!
- */
-typedef union pgresult_data PGresult_data;
-
-union pgresult_data
-{
- PGresult_data *next; /* link to next block, or NULL */
- char space[1]; /* dummy for accessing block as bytes */
-};
-
-/* Data about a single parameter of a prepared statement */
-typedef struct pgresParamDesc
-{
- Oid typid; /* type id */
-} PGresParamDesc;
-
-/*
- * Data for a single attribute of a single tuple
- *
- * We use char* for Attribute values.
- *
- * The value pointer always points to a null-terminated area; we add a
- * null (zero) byte after whatever the backend sends us. This is only
- * particularly useful for text values ... with a binary value, the
- * value might have embedded nulls, so the application can't use C string
- * operators on it. But we add a null anyway for consistency.
- * Note that the value itself does not contain a length word.
- *
- * A NULL attribute is a special case in two ways: its len field is NULL_LEN
- * and its value field points to null_field in the owning PGresult. All the
- * NULL attributes in a query result point to the same place (there's no need
- * to store a null string separately for each one).
- */
-
-#define NULL_LEN (-1) /* pg_result len for NULL value */
-
-typedef struct pgresAttValue
-{
- int len; /* length in bytes of the value */
- char *value; /* actual value, plus terminating zero byte */
-} PGresAttValue;
-
-/* Typedef for message-field list entries */
-typedef struct pgMessageField
-{
- struct pgMessageField *next; /* list link */
- char code; /* field code */
- char contents[FLEXIBLE_ARRAY_MEMBER]; /* value, nul-terminated */
-} PGMessageField;
-
-/* Fields needed for notice handling */
-typedef struct
-{
- PQnoticeReceiver noticeRec; /* notice message receiver */
- void *noticeRecArg;
- PQnoticeProcessor noticeProc; /* notice message processor */
- void *noticeProcArg;
-} PGNoticeHooks;
-
-typedef struct PGEvent
-{
- PGEventProc proc; /* the function to call on events */
- char *name; /* used only for error messages */
- void *passThrough; /* pointer supplied at registration time */
- void *data; /* optional state (instance) data */
- bool resultInitialized; /* T if RESULTCREATE/COPY succeeded */
-} PGEvent;
-
-struct pg_result
-{
- int ntups;
- int numAttributes;
- PGresAttDesc *attDescs;
- PGresAttValue **tuples; /* each PGresTuple is an array of
- * PGresAttValue's */
- int tupArrSize; /* allocated size of tuples array */
- int numParameters;
- PGresParamDesc *paramDescs;
- ExecStatusType resultStatus;
- char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the query */
- int binary; /* binary tuple values if binary == 1,
- * otherwise text */
-
- /*
- * These fields are copied from the originating PGconn, so that operations
- * on the PGresult don't have to reference the PGconn.
- */
- PGNoticeHooks noticeHooks;
- PGEvent *events;
- int nEvents;
- int client_encoding; /* encoding id */
-
- /*
- * Error information (all NULL if not an error result). errMsg is the
- * "overall" error message returned by PQresultErrorMessage. If we have
- * per-field info then it is stored in a linked list.
- */
- char *errMsg; /* error message, or NULL if no error */
- PGMessageField *errFields; /* message broken into fields */
- char *errQuery; /* text of triggering query, if available */
-
- /* All NULL attributes in the query result point to this null string */
- char null_field[1];
-
- /*
- * Space management information. Note that attDescs and error stuff, if
- * not null, point into allocated blocks. But tuples points to a
- * separately malloc'd block, so that we can realloc it.
- */
- PGresult_data *curBlock; /* most recently allocated block */
- int curOffset; /* start offset of free space in block */
- int spaceLeft; /* number of free bytes remaining in block */
-};
-
-/* PGAsyncStatusType defines the state of the query-execution state machine */
-typedef enum
-{
- PGASYNC_IDLE, /* nothing's happening, dude */
- PGASYNC_BUSY, /* query in progress */
- PGASYNC_READY, /* result ready for PQgetResult */
- PGASYNC_COPY_IN, /* Copy In data transfer in progress */
- PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
- PGASYNC_COPY_BOTH /* Copy In/Out data transfer in progress */
-} PGAsyncStatusType;
-
-/* PGQueryClass tracks which query protocol we are now executing */
-typedef enum
-{
- PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
- PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
- PGQUERY_PREPARE, /* Parse only (PQprepare) */
- PGQUERY_DESCRIBE /* Describe Statement or Portal */
-} PGQueryClass;
-
-/* PGSetenvStatusType defines the state of the PQSetenv state machine */
-/* (this is used only for 2.0-protocol connections) */
-typedef enum
-{
- SETENV_STATE_CLIENT_ENCODING_SEND, /* About to send an Environment Option */
- SETENV_STATE_CLIENT_ENCODING_WAIT, /* Waiting for above send to complete */
- SETENV_STATE_OPTION_SEND, /* About to send an Environment Option */
- SETENV_STATE_OPTION_WAIT, /* Waiting for above send to complete */
- SETENV_STATE_QUERY1_SEND, /* About to send a status query */
- SETENV_STATE_QUERY1_WAIT, /* Waiting for query to complete */
- SETENV_STATE_QUERY2_SEND, /* About to send a status query */
- SETENV_STATE_QUERY2_WAIT, /* Waiting for query to complete */
- SETENV_STATE_IDLE
-} PGSetenvStatusType;
-
-/* Typedef for the EnvironmentOptions[] array */
-typedef struct PQEnvironmentOption
-{
- const char *envName, /* name of an environment variable */
- *pgName; /* name of corresponding SET variable */
-} PQEnvironmentOption;
-
-/* Typedef for parameter-status list entries */
-typedef struct pgParameterStatus
-{
- struct pgParameterStatus *next; /* list link */
- char *name; /* parameter name */
- char *value; /* parameter value */
- /* Note: name and value are stored in same malloc block as struct is */
-} pgParameterStatus;
-
-/* large-object-access data ... allocated only if large-object code is used. */
-typedef struct pgLobjfuncs
-{
- Oid fn_lo_open; /* OID of backend function lo_open */
- Oid fn_lo_close; /* OID of backend function lo_close */
- Oid fn_lo_creat; /* OID of backend function lo_creat */
- Oid fn_lo_create; /* OID of backend function lo_create */
- Oid fn_lo_unlink; /* OID of backend function lo_unlink */
- Oid fn_lo_lseek; /* OID of backend function lo_lseek */
- Oid fn_lo_lseek64; /* OID of backend function lo_lseek64 */
- Oid fn_lo_tell; /* OID of backend function lo_tell */
- Oid fn_lo_tell64; /* OID of backend function lo_tell64 */
- Oid fn_lo_truncate; /* OID of backend function lo_truncate */
- Oid fn_lo_truncate64; /* OID of function lo_truncate64 */
- Oid fn_lo_read; /* OID of backend function LOread */
- Oid fn_lo_write; /* OID of backend function LOwrite */
-} PGlobjfuncs;
-
-/* PGdataValue represents a data field value being passed to a row processor.
- * It could be either text or binary data; text data is not zero-terminated.
- * A SQL NULL is represented by len < 0; then value is still valid but there
- * are no data bytes there.
- */
-typedef struct pgDataValue
-{
- int len; /* data length in bytes, or <0 if NULL */
- const char *value; /* data value, without zero-termination */
-} PGdataValue;
-
-/*
- * PGconn stores all the state data associated with a single connection
- * to a backend.
- */
-struct pg_conn
-{
- /* Saved values of connection options */
- char *pghost; /* the machine on which the server is running */
- char *pghostaddr; /* the numeric IP address of the machine on
- * which the server is running. Takes
- * precedence over above. */
- char *pgport; /* the server's communication port number */
- char *pgunixsocket; /* the directory of the server's Unix-domain
- * socket; if NULL, use DEFAULT_PGSOCKET_DIR */
- char *pgtty; /* tty on which the backend messages is
- * displayed (OBSOLETE, NOT USED) */
- char *connect_timeout; /* connection timeout (numeric string) */
- char *client_encoding_initial; /* encoding to use */
- char *pgoptions; /* options to start the backend with */
- char *appname; /* application name */
- char *fbappname; /* fallback application name */
- char *dbName; /* database name */
- char *replication; /* connect as the replication standby? */
- char *pguser; /* Postgres username and password, if any */
- char *pgpass;
- char *keepalives; /* use TCP keepalives? */
- char *keepalives_idle; /* time between TCP keepalives */
- char *keepalives_interval; /* time between TCP keepalive
- * retransmits */
- char *keepalives_count; /* maximum number of TCP keepalive
- * retransmits */
- char *sslmode; /* SSL mode (require,prefer,allow,disable) */
- char *sslcompression; /* SSL compression (0 or 1) */
- char *sslkey; /* client key filename */
- char *sslcert; /* client certificate filename */
- char *sslrootcert; /* root certificate filename */
- char *sslcrl; /* certificate revocation list filename */
- char *requirepeer; /* required peer credentials for local sockets */
-
-#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
- char *krbsrvname; /* Kerberos service name */
-#endif
-
- /* Optional file to write trace info to */
- FILE *Pfdebug;
-
- /* Callback procedures for notice message processing */
- PGNoticeHooks noticeHooks;
-
- /* Event procs registered via PQregisterEventProc */
- PGEvent *events; /* expandable array of event data */
- int nEvents; /* number of active events */
- int eventArraySize; /* allocated array size */
-
- /* Status indicators */
- ConnStatusType status;
- PGAsyncStatusType asyncStatus;
- PGTransactionStatusType xactStatus; /* never changes to ACTIVE */
- PGQueryClass queryclass;
- char *last_query; /* last SQL command, or NULL if unknown */
- char last_sqlstate[6]; /* last reported SQLSTATE */
- bool options_valid; /* true if OK to attempt connection */
- bool nonblocking; /* whether this connection is using nonblock
- * sending semantics */
- bool singleRowMode; /* return current query result row-by-row? */
- char copy_is_binary; /* 1 = copy binary, 0 = copy text */
- int copy_already_done; /* # bytes already returned in COPY
- * OUT */
- PGnotify *notifyHead; /* oldest unreported Notify msg */
- PGnotify *notifyTail; /* newest unreported Notify msg */
-
- /* Connection data */
- /* See PQconnectPoll() for how we use 'int' and not 'pgsocket'. */
- pgsocket sock; /* FD for socket, PGINVALID_SOCKET if
- * unconnected */
- SockAddr laddr; /* Local address */
- SockAddr raddr; /* Remote address */
- ProtocolVersion pversion; /* FE/BE protocol version in use */
- int sversion; /* server version, e.g. 70401 for 7.4.1 */
- bool auth_req_received; /* true if any type of auth req
- * received */
- bool password_needed; /* true if server demanded a password */
- bool dot_pgpass_used; /* true if used .pgpass */
- bool sigpipe_so; /* have we masked SIGPIPE via SO_NOSIGPIPE? */
- bool sigpipe_flag; /* can we mask SIGPIPE via MSG_NOSIGNAL? */
-
- /* Transient state needed while establishing connection */
- struct addrinfo *addrlist; /* list of possible backend addresses */
- struct addrinfo *addr_cur; /* the one currently being tried */
- int addrlist_family; /* needed to know how to free addrlist */
- PGSetenvStatusType setenv_state; /* for 2.0 protocol only */
- const PQEnvironmentOption *next_eo;
- bool send_appname; /* okay to send application_name? */
-
- /* Miscellaneous stuff */
- int be_pid; /* PID of backend --- needed for cancels */
- int be_key; /* key of backend --- needed for cancels */
- char md5Salt[4]; /* password salt received from backend */
- pgParameterStatus *pstatus; /* ParameterStatus data */
- int client_encoding; /* encoding id */
- bool std_strings; /* standard_conforming_strings */
- PGVerbosity verbosity; /* error/notice message verbosity */
- PGContextVisibility show_context; /* whether to show CONTEXT field */
- PGlobjfuncs *lobjfuncs; /* private state for large-object access fns */
-
- /* Buffer for data received from backend and not yet processed */
- char *inBuffer; /* currently allocated buffer */
- int inBufSize; /* allocated size of buffer */
- int inStart; /* offset to first unconsumed data in buffer */
- int inCursor; /* next byte to tentatively consume */
- int inEnd; /* offset to first position after avail data */
-
- /* Buffer for data not yet sent to backend */
- char *outBuffer; /* currently allocated buffer */
- int outBufSize; /* allocated size of buffer */
- int outCount; /* number of chars waiting in buffer */
-
- /* State for constructing messages in outBuffer */
- int outMsgStart; /* offset to msg start (length word); if -1,
- * msg has no length word */
- int outMsgEnd; /* offset to msg end (so far) */
-
- /* Row processor interface workspace */
- PGdataValue *rowBuf; /* array for passing values to rowProcessor */
- int rowBufLen; /* number of entries allocated in rowBuf */
-
- /* Status for asynchronous result construction */
- PGresult *result; /* result being constructed */
- PGresult *next_result; /* next result (used in single-row mode) */
-
- /* Assorted state for SSL, GSS, etc */
-
-#ifdef USE_SSL
- bool allow_ssl_try; /* Allowed to try SSL negotiation */
- bool wait_ssl_try; /* Delay SSL negotiation until after
- * attempting normal connection */
- bool ssl_in_use;
-#ifdef USE_OPENSSL
- SSL *ssl; /* SSL status, if have SSL connection */
- X509 *peer; /* X509 cert of server */
-#ifdef USE_SSL_ENGINE
- ENGINE *engine; /* SSL engine, if any */
-#else
- void *engine; /* dummy field to keep struct the same if
- * OpenSSL version changes */
-#endif
-#endif /* USE_OPENSSL */
-#endif /* USE_SSL */
-
-#ifdef ENABLE_GSS
- gss_ctx_id_t gctx; /* GSS context */
- gss_name_t gtarg_nam; /* GSS target name */
- gss_buffer_desc ginbuf; /* GSS input token */
- gss_buffer_desc goutbuf; /* GSS output token */
-#endif
-
-#ifdef ENABLE_SSPI
-#ifndef ENABLE_GSS
- gss_buffer_desc ginbuf; /* GSS input token */
-#else
- char *gsslib; /* What GSS librart to use ("gssapi" or
- * "sspi") */
-#endif
- CredHandle *sspicred; /* SSPI credentials handle */
- CtxtHandle *sspictx; /* SSPI context */
- char *sspitarget; /* SSPI target name */
- int usesspi; /* Indicate if SSPI is in use on the
- * connection */
-#endif
-
- /* Buffer for current error message */
- PQExpBufferData errorMessage; /* expansible string */
-
- /* Buffer for receiving various parts of messages */
- PQExpBufferData workBuffer; /* expansible string */
-};
-
-/* PGcancel stores all data necessary to cancel a connection. A copy of this
- * data is required to safely cancel a connection running on a different
- * thread.
- */
-struct pg_cancel
-{
- SockAddr raddr; /* Remote address */
- int be_pid; /* PID of backend --- needed for cancels */
- int be_key; /* key of backend --- needed for cancels */
-};
-
-
-/* String descriptions of the ExecStatusTypes.
- * direct use of this array is deprecated; call PQresStatus() instead.
- */
-extern char *const pgresStatus[];
-
-
-#ifdef USE_SSL
-
-#ifndef WIN32
-#define USER_CERT_FILE ".postgresql/postgresql.crt"
-#define USER_KEY_FILE ".postgresql/postgresql.key"
-#define ROOT_CERT_FILE ".postgresql/root.crt"
-#define ROOT_CRL_FILE ".postgresql/root.crl"
-#else
-/* On Windows, the "home" directory is already PostgreSQL-specific */
-#define USER_CERT_FILE "postgresql.crt"
-#define USER_KEY_FILE "postgresql.key"
-#define ROOT_CERT_FILE "root.crt"
-#define ROOT_CRL_FILE "root.crl"
-#endif
-
-#endif /* USE_SSL */
-
-/* ----------------
- * Internal functions of libpq
- * Functions declared here need to be visible across files of libpq,
- * but are not intended to be called by applications. We use the
- * convention "pqXXX" for internal functions, vs. the "PQxxx" names
- * used for application-visible routines.
- * ----------------
- */
-
-/* === in fe-connect.c === */
-
-extern void pqDropConnection(PGconn *conn, bool flushInput);
-extern int pqPacketSend(PGconn *conn, char pack_type,
- const void *buf, size_t buf_len);
-extern bool pqGetHomeDirectory(char *buf, int bufsize);
-
-#ifdef ENABLE_THREAD_SAFETY
-extern pgthreadlock_t pg_g_threadlock;
-
-#define PGTHREAD_ERROR(msg) \
- do { \
- fprintf(stderr, "%s\n", msg); \
- abort(); \
- } while (0)
-
-
-#define pglock_thread() pg_g_threadlock(true)
-#define pgunlock_thread() pg_g_threadlock(false)
-#else
-#define pglock_thread() ((void) 0)
-#define pgunlock_thread() ((void) 0)
-#endif
-
-/* === in fe-exec.c === */
-
-extern void pqSetResultError(PGresult *res, const char *msg);
-extern void pqCatenateResultError(PGresult *res, const char *msg);
-extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary);
-extern char *pqResultStrdup(PGresult *res, const char *str);
-extern void pqClearAsyncResult(PGconn *conn);
-extern void pqSaveErrorResult(PGconn *conn);
-extern PGresult *pqPrepareAsyncResult(PGconn *conn);
-extern void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2, 3);
-extern void pqSaveMessageField(PGresult *res, char code,
- const char *value);
-extern void pqSaveParameterStatus(PGconn *conn, const char *name,
- const char *value);
-extern int pqRowProcessor(PGconn *conn, const char **errmsgp);
-extern void pqHandleSendFailure(PGconn *conn);
-
-/* === in fe-protocol2.c === */
-
-extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn);
-
-extern char *pqBuildStartupPacket2(PGconn *conn, int *packetlen,
- const PQEnvironmentOption *options);
-extern void pqParseInput2(PGconn *conn);
-extern int pqGetCopyData2(PGconn *conn, char **buffer, int async);
-extern int pqGetline2(PGconn *conn, char *s, int maxlen);
-extern int pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize);
-extern int pqEndcopy2(PGconn *conn);
-extern PGresult *pqFunctionCall2(PGconn *conn, Oid fnid,
- int *result_buf, int *actual_result_len,
- int result_is_int,
- const PQArgBlock *args, int nargs);
-
-/* === in fe-protocol3.c === */
-
-extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
- const PQEnvironmentOption *options);
-extern void pqParseInput3(PGconn *conn);
-extern int pqGetErrorNotice3(PGconn *conn, bool isError);
-extern void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
- PGVerbosity verbosity, PGContextVisibility show_context);
-extern int pqGetCopyData3(PGconn *conn, char **buffer, int async);
-extern int pqGetline3(PGconn *conn, char *s, int maxlen);
-extern int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
-extern int pqEndcopy3(PGconn *conn);
-extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
- int *result_buf, int *actual_result_len,
- int result_is_int,
- const PQArgBlock *args, int nargs);
-
-/* === in fe-misc.c === */
-
- /*
- * "Get" and "Put" routines return 0 if successful, EOF if not. Note that for
- * Get, EOF merely means the buffer is exhausted, not that there is
- * necessarily any error.
- */
-extern int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn);
-extern int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn);
-extern int pqGetc(char *result, PGconn *conn);
-extern int pqPutc(char c, PGconn *conn);
-extern int pqGets(PQExpBuffer buf, PGconn *conn);
-extern int pqGets_append(PQExpBuffer buf, PGconn *conn);
-extern int pqPuts(const char *s, PGconn *conn);
-extern int pqGetnchar(char *s, size_t len, PGconn *conn);
-extern int pqSkipnchar(size_t len, PGconn *conn);
-extern int pqPutnchar(const char *s, size_t len, PGconn *conn);
-extern int pqGetInt(int *result, size_t bytes, PGconn *conn);
-extern int pqPutInt(int value, size_t bytes, PGconn *conn);
-extern int pqPutMsgStart(char msg_type, bool force_len, PGconn *conn);
-extern int pqPutMsgEnd(PGconn *conn);
-extern int pqReadData(PGconn *conn);
-extern int pqFlush(PGconn *conn);
-extern int pqWait(int forRead, int forWrite, PGconn *conn);
-extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
- time_t finish_time);
-extern int pqReadReady(PGconn *conn);
-extern int pqWriteReady(PGconn *conn);
-
-/* === in fe-secure.c === */
-
-extern int pqsecure_initialize(PGconn *);
-extern void pqsecure_destroy(void);
-extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
-extern void pqsecure_close(PGconn *);
-extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len);
-extern ssize_t pqsecure_write(PGconn *, const void *ptr, size_t len);
-extern ssize_t pqsecure_raw_read(PGconn *, void *ptr, size_t len);
-extern ssize_t pqsecure_raw_write(PGconn *, const void *ptr, size_t len);
-
-#if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
-extern int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
-extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending,
- bool got_epipe);
-#endif
-
-/*
- * The SSL implementation provides these functions (fe-secure-openssl.c)
- */
-extern void pgtls_init_library(bool do_ssl, int do_crypto);
-extern int pgtls_init(PGconn *conn);
-extern PostgresPollingStatusType pgtls_open_client(PGconn *conn);
-extern void pgtls_close(PGconn *conn);
-extern ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len);
-extern bool pgtls_read_pending(PGconn *conn);
-extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);
-
-/*
- * this is so that we can check if a connection is non-blocking internally
- * without the overhead of a function call
- */
-#define pqIsnonblocking(conn) ((conn)->nonblocking)
-
-#ifdef ENABLE_NLS
-extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1);
-extern char *libpq_ngettext(const char *msgid, const char *msgid_plural, unsigned long n) pg_attribute_format_arg(1) pg_attribute_format_arg(2);
-#else
-#define libpq_gettext(x) (x)
-#define libpq_ngettext(s, p, n) ((n) == 1 ? (s) : (p))
-#endif
-
-/*
- * These macros are needed to let error-handling code be portable between
- * Unix and Windows. (ugh)
- */
-#ifdef WIN32
-#define SOCK_ERRNO (WSAGetLastError())
-#define SOCK_STRERROR winsock_strerror
-#define SOCK_ERRNO_SET(e) WSASetLastError(e)
-#else
-#define SOCK_ERRNO errno
-#define SOCK_STRERROR pqStrerror
-#define SOCK_ERRNO_SET(e) (errno = (e))
-#endif
-
-#endif /* LIBPQ_INT_H */
diff --git a/libpq/libpq/.gitignore b/libpq/libpq/.gitignore
new file mode 100644
index 0000000..620b4c8
--- /dev/null
+++ b/libpq/libpq/.gitignore
@@ -0,0 +1,3 @@
+# Generated version.h.
+#
+version.h
diff --git a/libpq/libpq/buildfile b/libpq/libpq/buildfile
new file mode 100644
index 0000000..d77ccf7
--- /dev/null
+++ b/libpq/libpq/buildfile
@@ -0,0 +1,233 @@
+# file : libpq/buildfile
+# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
+# license : PostgreSQL Licenes; see accompanying COPYRIGHT file
+
+import imp_libs = libssl%lib{ssl}
+import imp_libs += libcrypto%lib{crypto}
+
+# Exclude source code of unused features (authentication methods, etc).
+#
+# @@ When it becomes possible (probably with ad hoc rules), generate
+# libpqdll.map and libpqdll.def on the fly from pq/exports.txt applying
+# regex replace to its lines and adding prologue/epilogue.
+#
+lib{pq}: {h }{* -version} \
+ {h }{ version} \
+ pq/{h c}{* -fe-gssapi-common -fe-secure-gssapi -*win32*} \
+ mb/{ c}{* } \
+ port/{h c}{* -strlcpy -getaddrinfo -inet_aton -*win32*} \
+ common/{ c}{* } \
+ include/{h }{** } \
+ {def }{libpqdll } \
+ {file}{libpqdll.map } \
+ pq/{file}{pg_service.conf.sample } \
+ $imp_libs
+
+tclass = $c.target.class
+tsys = $c.target.system
+
+bsd = ($tclass == 'bsd')
+macos = ($tclass == 'macos')
+windows = ($tclass == 'windows')
+
+lib{pq}: port/c{strlcpy}: include = (!$bsd && !$macos)
+
+lib{pq}: pq/{h c}{*win32* } \
+ port/{h c}{*win32* +getaddrinfo +inet_aton}: include = $windows
+
+# The version file is an internal one (it is only included from pg_config.h)
+# so we don't distribute nor install it (see below).
+#
+h{version}: in{version} $src_root/manifest
+
+# Build options.
+#
+# Note that the upstream package also defines a bunch of the VAL_* macros
+# (VAL_CONFIGURE, VAL_CC, etc) that are used in get_configdata(), if defined.
+# We will omit them for the sake of simplicity.
+#
+c.poptions += -DFRONTEND -DUNSAFE_STAT_OK -DSO_MAJOR_VERSION=$abi_major
+
+if! $windows
+ # Note that the upstream package uses -pthread compiler/linker option. It is
+ # currently unsupported by build2, so we use -D_REENTRANT and -lpthread
+ # preprocessor/linker options instead. We also omit -D_THREAD_SAFE (synonym
+ # for -D_REENTRANT) and Solaris-specific -D_POSIX_PTHREAD_SEMANTICS.
+ #
+ c.poptions += -D_REENTRANT
+else
+ # Note that the upstream package defines the WIN32 macro for VC only,
+ # relying on the fact that MinGW GCC defines it by default. However, the
+ # macro disappears from the default ones if to compile with -std=c9x (as we
+ # do). So we define it for both VC and MinGW GCC.
+ #
+ # It's tempting to move this definition to libpq/pg_config.h. However this
+ # header is not included into all files that use the macro, for example,
+ # libpq/port/open.c.
+ #
+ c.poptions += -DWIN32
+
+# Note that we need to add "-I$src_root" for the headers auto-generating
+# machinery to work properly.
+#
+c.poptions =+ "-I$out_root" "-I$src_root" "-I$src_base" "-I$src_base/port" \
+ "-I$src_base/pq" "-I$src_base/include"
+
+switch $tclass, $tsys
+{
+ case 'linux'
+ c.poptions += -D_GNU_SOURCE
+
+ case 'windows', 'mingw32'
+ {
+ c.poptions += -DBUILDING_DLL -DEXEC_BACKEND
+ c.poptions =+ "-I$src_base/include/port/win32"
+ }
+ case 'windows'
+ {
+ # Probably some of the *WIN* macro definitions are not really required,
+ # but let's keep all of them for good measure.
+ #
+ c.poptions += -DEXEC_BACKEND -D_WINDLL -D__WINDOWS__ -D__WIN32__ -D_MBCS \
+ -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
+
+ c.poptions =+ "-I$src_base/include/port/win32_msvc" \
+ "-I$src_base/include/port/win32"
+ }
+}
+
+# Define SYSCONFDIR macro. This path is used as a last resort for the
+# pg_service.conf file search (see pq/fe-connect.c for details).
+#
+# The whole idea feels utterly broken (hello cross-compilation) so we will
+# just do bare minimum and wait and see.
+#
+# @@ We should probably allow to configure this macros via configuration
+# variable config.libpq.sysconfdir.
+#
+# For the upstream package if the resulted sysconfdir path doesn't contain the
+# 'postgres' or 'pgsql' substring then the '/postgresql' suffix is
+# automatically appended (see the upstream INSTALL file for details). Note
+# that the same rule is applied for the datadir and docdir paths. Also if the
+# root directory is /usr, then the resulting sysconfdir path is
+# /etc/postgresql (rather than /usr/etc/postgresql).
+#
+# Let's do the same for the sysconfdir to increase the chance that libpq will
+# find the configuration file. Note that we don't install anything at this
+# path and don't amend the install.data and install.doc path variables. We
+# also use the same default path as the upstream package. Also note that on
+# Windows the default path doesn't make any sense so let's make it empty
+# instead.
+#
+if ($install.root != [null])
+{
+ root = $install.resolve($install.root)
+ sysconfdir = ($windows || $root != /usr ? $root/etc : /etc)
+
+ if! $regex.match("$sysconfdir", '.*(pgsql|postgresql).*')
+ sysconfdir = $sysconfdir/postgresql
+}
+else
+ sysconfdir = ($windows ? '' : /usr/local/pgsql/etc)
+
+# Escape backslashes and quotes in the directory path prior to representing it
+# as C string literals.
+#
+sd = $regex.replace($sysconfdir, '(\\|")', '\\\1')
+
+# If we ever enable National Language Support then we will need to define the
+# LOCALEDIR macro as well. It refers to the locale data directory and should
+# be $install.data/locale by default. We will also need to install this
+# directory (see configure script --enable-nls options and the libpq/po
+# directory in the upstream package for details).
+#
+pq/obj{fe-connect}: c.poptions += -DSYSCONFDIR="\"$sd\""
+
+switch $c.class
+{
+ case 'gcc'
+ {
+ # Omit -fexcess-precision=standard since -std=9x implies it.
+ #
+ c.coptions += -fno-strict-aliasing -fwrapv
+
+ # Disable warnings that pop up with -Wall -Wextra. Upstream doesn't seem
+ # to care about these and it is not easy to disable specific warnings in a
+ # way that works across compilers/version (some -Wno-* options are only
+ # recognized in newer versions).
+ #
+ c.coptions += -Wno-all -Wno-extra
+ }
+ case 'msvc'
+ {
+ c.coptions += /GF
+
+ # Disable warnings that pop up with /W3.
+ #
+ c.coptions += /wd4018 /wd4244 /wd4267
+ }
+}
+
+# On Windows the upstream package also adds the resource file to the library.
+# The file contains only the version information. First, libpq.rc is produced
+# from libpq.rc.in with the following command:
+#
+# sed -e 's/\(VERSION.*\),0 *$/\1,'`date '+%y%j' | \
+# sed 's/^0*//'`'/' libpq.rc.in >libpq.rc
+#
+# Then libpq.rc is compiled with:
+#
+# windres -i libpq.rc -o libpqrc.o
+#
+# Afterwards libpqrc.o is linked to the library.
+#
+# @@ Currently we don't have support for the first two steps.
+#
+switch $tclass, $tsys
+{
+ case 'windows', 'mingw32'
+ c.libs += -lsecur32 -lws2_32
+
+ case 'windows'
+ c.libs += secur32.lib ws2_32.lib advapi32.lib
+
+ case 'linux' | 'bsd'
+ {
+ # Make sure all symbols are resolvable.
+ #
+ c.loptions += -Wl,--no-undefined
+
+ c.loptions += "-Wl,--version-script=$src_base/libpqdll.map"
+
+ c.libs += -lpthread
+ }
+
+ default
+ c.libs += -lpthread
+}
+
+# Export options.
+#
+lib{pq}: cc.export.poptions = "-I$src_base" "-I$src_base/pq" \
+ "-I$src_base/include"
+
+# See bootstrap.build for details.
+#
+if $version.pre_release
+ lib{pq}: bin.lib.version = @"-$version.project_id"
+else
+ lib{pq}: bin.lib.version = @"-$abi_major" linux@"$abi_major.$abi_minor"
+
+# Install the bare minimum of headers not recreating subdirectories.
+#
+# Note that upstream also installs several 'unofficial API' headers, that we
+# won't install.
+#
+h{*}: install = false
+
+for h: pq/{libpq-fe libpq-events} include/postgres_ext pg_config_ext
+ h{$h}@./$path.directory($h): install = include/
+
+# Install the config file example as the upstream does.
+#
+pq/file{pg_service.conf.sample}@pq/: install = data/
diff --git a/libpq/libpq/common/base64.c b/libpq/libpq/common/base64.c
new file mode 120000
index 0000000..6883927
--- /dev/null
+++ b/libpq/libpq/common/base64.c
@@ -0,0 +1 @@
+../../../upstream/src/common/base64.c \ No newline at end of file
diff --git a/libpq/libpq/common/ip.c b/libpq/libpq/common/ip.c
new file mode 120000
index 0000000..48e8123
--- /dev/null
+++ b/libpq/libpq/common/ip.c
@@ -0,0 +1 @@
+../../../upstream/src/common/ip.c \ No newline at end of file
diff --git a/libpq/libpq/common/link-canary.c b/libpq/libpq/common/link-canary.c
new file mode 120000
index 0000000..cf578d8
--- /dev/null
+++ b/libpq/libpq/common/link-canary.c
@@ -0,0 +1 @@
+../../../upstream/src/common/link-canary.c \ No newline at end of file
diff --git a/libpq/libpq/common/md5.c b/libpq/libpq/common/md5.c
new file mode 120000
index 0000000..a2eae90
--- /dev/null
+++ b/libpq/libpq/common/md5.c
@@ -0,0 +1 @@
+../../../upstream/src/common/md5.c \ No newline at end of file
diff --git a/libpq/libpq/common/saslprep.c b/libpq/libpq/common/saslprep.c
new file mode 120000
index 0000000..5f5215d
--- /dev/null
+++ b/libpq/libpq/common/saslprep.c
@@ -0,0 +1 @@
+../../../upstream/src/common/saslprep.c \ No newline at end of file
diff --git a/libpq/libpq/common/scram-common.c b/libpq/libpq/common/scram-common.c
new file mode 120000
index 0000000..11927e2
--- /dev/null
+++ b/libpq/libpq/common/scram-common.c
@@ -0,0 +1 @@
+../../../upstream/src/common/scram-common.c \ No newline at end of file
diff --git a/libpq/libpq/common/sha2_openssl.c b/libpq/libpq/common/sha2_openssl.c
new file mode 120000
index 0000000..4d52df2
--- /dev/null
+++ b/libpq/libpq/common/sha2_openssl.c
@@ -0,0 +1 @@
+../../../upstream/src/common/sha2_openssl.c \ No newline at end of file
diff --git a/libpq/libpq/common/unicode_norm.c b/libpq/libpq/common/unicode_norm.c
new file mode 120000
index 0000000..fdb3f72
--- /dev/null
+++ b/libpq/libpq/common/unicode_norm.c
@@ -0,0 +1 @@
+../../../upstream/src/common/unicode_norm.c \ No newline at end of file
diff --git a/libpq/libpq/include/c.h b/libpq/libpq/include/c.h
new file mode 120000
index 0000000..6f95f77
--- /dev/null
+++ b/libpq/libpq/include/c.h
@@ -0,0 +1 @@
+../../../upstream/src/include/c.h \ No newline at end of file
diff --git a/libpq/libpq/include/common b/libpq/libpq/include/common
new file mode 120000
index 0000000..4379965
--- /dev/null
+++ b/libpq/libpq/include/common
@@ -0,0 +1 @@
+../../../upstream/src/include/common \ No newline at end of file
diff --git a/libpq/libpq/include/getaddrinfo.h b/libpq/libpq/include/getaddrinfo.h
new file mode 120000
index 0000000..7ab1ba8
--- /dev/null
+++ b/libpq/libpq/include/getaddrinfo.h
@@ -0,0 +1 @@
+../../../upstream/src/include/getaddrinfo.h \ No newline at end of file
diff --git a/libpq/libpq/include/libpq/libpq-fs.h b/libpq/libpq/include/libpq/libpq-fs.h
new file mode 120000
index 0000000..9030b6b
--- /dev/null
+++ b/libpq/libpq/include/libpq/libpq-fs.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/libpq/libpq-fs.h \ No newline at end of file
diff --git a/libpq/libpq/include/libpq/pqcomm.h b/libpq/libpq/include/libpq/pqcomm.h
new file mode 120000
index 0000000..69de3bc
--- /dev/null
+++ b/libpq/libpq/include/libpq/pqcomm.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/libpq/pqcomm.h \ No newline at end of file
diff --git a/libpq/libpq/include/mb/pg_wchar.h b/libpq/libpq/include/mb/pg_wchar.h
new file mode 120000
index 0000000..ed65657
--- /dev/null
+++ b/libpq/libpq/include/mb/pg_wchar.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/mb/pg_wchar.h \ No newline at end of file
diff --git a/libpq/libpq/include/pg_config_manual.h b/libpq/libpq/include/pg_config_manual.h
new file mode 120000
index 0000000..485eb76
--- /dev/null
+++ b/libpq/libpq/include/pg_config_manual.h
@@ -0,0 +1 @@
+../../../upstream/src/include/pg_config_manual.h \ No newline at end of file
diff --git a/libpq/libpq/include/port.h b/libpq/libpq/include/port.h
new file mode 120000
index 0000000..82aed06
--- /dev/null
+++ b/libpq/libpq/include/port.h
@@ -0,0 +1 @@
+../../../upstream/src/include/port.h \ No newline at end of file
diff --git a/libpq/libpq/include/port/darwin.h b/libpq/libpq/include/port/darwin.h
new file mode 120000
index 0000000..7844da8
--- /dev/null
+++ b/libpq/libpq/include/port/darwin.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/darwin.h \ No newline at end of file
diff --git a/libpq/libpq/include/port/freebsd.h b/libpq/libpq/include/port/freebsd.h
new file mode 120000
index 0000000..7685fa5
--- /dev/null
+++ b/libpq/libpq/include/port/freebsd.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/freebsd.h \ No newline at end of file
diff --git a/libpq/libpq/include/port/linux.h b/libpq/libpq/include/port/linux.h
new file mode 120000
index 0000000..3e054ce
--- /dev/null
+++ b/libpq/libpq/include/port/linux.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/linux.h \ No newline at end of file
diff --git a/libpq/libpq/include/port/pg_bswap.h b/libpq/libpq/include/port/pg_bswap.h
new file mode 120000
index 0000000..876bcb7
--- /dev/null
+++ b/libpq/libpq/include/port/pg_bswap.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/pg_bswap.h \ No newline at end of file
diff --git a/libpq/libpq/include/port/win32 b/libpq/libpq/include/port/win32
new file mode 120000
index 0000000..306f506
--- /dev/null
+++ b/libpq/libpq/include/port/win32
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/win32 \ No newline at end of file
diff --git a/libpq/libpq/include/port/win32.h b/libpq/libpq/include/port/win32.h
new file mode 120000
index 0000000..f48b8ef
--- /dev/null
+++ b/libpq/libpq/include/port/win32.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/win32.h \ No newline at end of file
diff --git a/libpq/libpq/include/port/win32_msvc b/libpq/libpq/include/port/win32_msvc
new file mode 120000
index 0000000..bf2a9ef
--- /dev/null
+++ b/libpq/libpq/include/port/win32_msvc
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/win32_msvc \ No newline at end of file
diff --git a/libpq/libpq/include/port/win32_port.h b/libpq/libpq/include/port/win32_port.h
new file mode 120000
index 0000000..c91e3e1
--- /dev/null
+++ b/libpq/libpq/include/port/win32_port.h
@@ -0,0 +1 @@
+../../../../upstream/src/include/port/win32_port.h \ No newline at end of file
diff --git a/libpq/libpq/include/postgres_ext.h b/libpq/libpq/include/postgres_ext.h
new file mode 120000
index 0000000..d0a22aa
--- /dev/null
+++ b/libpq/libpq/include/postgres_ext.h
@@ -0,0 +1 @@
+../../../upstream/src/include/postgres_ext.h \ No newline at end of file
diff --git a/libpq/libpq/include/postgres_fe.h b/libpq/libpq/include/postgres_fe.h
new file mode 120000
index 0000000..5277360
--- /dev/null
+++ b/libpq/libpq/include/postgres_fe.h
@@ -0,0 +1 @@
+../../../upstream/src/include/postgres_fe.h \ No newline at end of file
diff --git a/libpq/libpq/libpqdll.def b/libpq/libpq/libpqdll.def
new file mode 100644
index 0000000..d74056c
--- /dev/null
+++ b/libpq/libpq/libpqdll.def
@@ -0,0 +1,178 @@
+;LIBRARY LIBPQ
+EXPORTS
+ PQconnectdb @ 1
+ PQsetdbLogin @ 2
+ PQconndefaults @ 3
+ PQfinish @ 4
+ PQreset @ 5
+ PQrequestCancel @ 6
+ PQdb @ 7
+ PQuser @ 8
+ PQpass @ 9
+ PQhost @ 10
+ PQport @ 11
+ PQtty @ 12
+ PQoptions @ 13
+ PQstatus @ 14
+ PQerrorMessage @ 15
+ PQsocket @ 16
+ PQbackendPID @ 17
+ PQtrace @ 18
+ PQuntrace @ 19
+ PQsetNoticeProcessor @ 20
+ PQexec @ 21
+ PQnotifies @ 22
+ PQsendQuery @ 23
+ PQgetResult @ 24
+ PQisBusy @ 25
+ PQconsumeInput @ 26
+ PQgetline @ 27
+ PQputline @ 28
+ PQgetlineAsync @ 29
+ PQputnbytes @ 30
+ PQendcopy @ 31
+ PQfn @ 32
+ PQresultStatus @ 33
+ PQntuples @ 34
+ PQnfields @ 35
+ PQbinaryTuples @ 36
+ PQfname @ 37
+ PQfnumber @ 38
+ PQftype @ 39
+ PQfsize @ 40
+ PQfmod @ 41
+ PQcmdStatus @ 42
+ PQoidStatus @ 43
+ PQcmdTuples @ 44
+ PQgetvalue @ 45
+ PQgetlength @ 46
+ PQgetisnull @ 47
+ PQclear @ 48
+ PQmakeEmptyPGresult @ 49
+ PQprint @ 50
+ PQdisplayTuples @ 51
+ PQprintTuples @ 52
+ lo_open @ 53
+ lo_close @ 54
+ lo_read @ 55
+ lo_write @ 56
+ lo_lseek @ 57
+ lo_creat @ 58
+ lo_tell @ 59
+ lo_unlink @ 60
+ lo_import @ 61
+ lo_export @ 62
+ pgresStatus @ 63
+ PQmblen @ 64
+ PQresultErrorMessage @ 65
+ PQresStatus @ 66
+ termPQExpBuffer @ 67
+ appendPQExpBufferChar @ 68
+ initPQExpBuffer @ 69
+ resetPQExpBuffer @ 70
+ PQoidValue @ 71
+ PQclientEncoding @ 72
+ PQenv2encoding @ 73
+ appendBinaryPQExpBuffer @ 74
+ appendPQExpBufferStr @ 75
+ destroyPQExpBuffer @ 76
+ createPQExpBuffer @ 77
+ PQconninfoFree @ 78
+ PQconnectPoll @ 79
+ PQconnectStart @ 80
+ PQflush @ 81
+ PQisnonblocking @ 82
+ PQresetPoll @ 83
+ PQresetStart @ 84
+ PQsetClientEncoding @ 85
+ PQsetnonblocking @ 86
+ PQfreeNotify @ 87
+ PQescapeString @ 88
+ PQescapeBytea @ 89
+ printfPQExpBuffer @ 90
+ appendPQExpBuffer @ 91
+ pg_encoding_to_char @ 92
+ pg_utf_mblen @ 93
+ PQunescapeBytea @ 94
+ PQfreemem @ 95
+ PQtransactionStatus @ 96
+ PQparameterStatus @ 97
+ PQprotocolVersion @ 98
+ PQsetErrorVerbosity @ 99
+ PQsetNoticeReceiver @ 100
+ PQexecParams @ 101
+ PQsendQueryParams @ 102
+ PQputCopyData @ 103
+ PQputCopyEnd @ 104
+ PQgetCopyData @ 105
+ PQresultErrorField @ 106
+ PQftable @ 107
+ PQftablecol @ 108
+ PQfformat @ 109
+ PQexecPrepared @ 110
+ PQsendQueryPrepared @ 111
+ PQdsplen @ 112
+ PQserverVersion @ 113
+ PQgetssl @ 114
+ pg_char_to_encoding @ 115
+ pg_valid_server_encoding @ 116
+ pqsignal @ 117
+ PQprepare @ 118
+ PQsendPrepare @ 119
+ PQgetCancel @ 120
+ PQfreeCancel @ 121
+ PQcancel @ 122
+ lo_create @ 123
+ PQinitSSL @ 124
+ PQregisterThreadLock @ 125
+ PQescapeStringConn @ 126
+ PQescapeByteaConn @ 127
+ PQencryptPassword @ 128
+ PQisthreadsafe @ 129
+ enlargePQExpBuffer @ 130
+ PQnparams @ 131
+ PQparamtype @ 132
+ PQdescribePrepared @ 133
+ PQdescribePortal @ 134
+ PQsendDescribePrepared @ 135
+ PQsendDescribePortal @ 136
+ lo_truncate @ 137
+ PQconnectionUsedPassword @ 138
+ pg_valid_server_encoding_id @ 139
+ PQconnectionNeedsPassword @ 140
+ lo_import_with_oid @ 141
+ PQcopyResult @ 142
+ PQsetResultAttrs @ 143
+ PQsetvalue @ 144
+ PQresultAlloc @ 145
+ PQregisterEventProc @ 146
+ PQinstanceData @ 147
+ PQsetInstanceData @ 148
+ PQresultInstanceData @ 149
+ PQresultSetInstanceData @ 150
+ PQfireResultCreateEvents @ 151
+ PQconninfoParse @ 152
+ PQinitOpenSSL @ 153
+ PQescapeLiteral @ 154
+ PQescapeIdentifier @ 155
+ PQconnectdbParams @ 156
+ PQconnectStartParams @ 157
+ PQping @ 158
+ PQpingParams @ 159
+ PQlibVersion @ 160
+ PQsetSingleRowMode @ 161
+ lo_lseek64 @ 162
+ lo_tell64 @ 163
+ lo_truncate64 @ 164
+ PQconninfo @ 165
+ PQsslInUse @ 166
+ PQsslStruct @ 167
+ PQsslAttributeNames @ 168
+ PQsslAttribute @ 169
+ PQsetErrorContextVisibility @ 170
+ PQresultVerboseErrorMessage @ 171
+ PQencryptPasswordConn @ 172
+ PQresultMemorySize @ 173
+ PQhostaddr @ 174
+ PQgssEncInUse @ 175
+ PQgetgssctx @ 176
diff --git a/libpq/libpq/libpqdll.map b/libpq/libpq/libpqdll.map
new file mode 100644
index 0000000..893dc86
--- /dev/null
+++ b/libpq/libpq/libpqdll.map
@@ -0,0 +1,178 @@
+{ global:
+PQconnectdb;
+PQsetdbLogin;
+PQconndefaults;
+PQfinish;
+PQreset;
+PQrequestCancel;
+PQdb;
+PQuser;
+PQpass;
+PQhost;
+PQport;
+PQtty;
+PQoptions;
+PQstatus;
+PQerrorMessage;
+PQsocket;
+PQbackendPID;
+PQtrace;
+PQuntrace;
+PQsetNoticeProcessor;
+PQexec;
+PQnotifies;
+PQsendQuery;
+PQgetResult;
+PQisBusy;
+PQconsumeInput;
+PQgetline;
+PQputline;
+PQgetlineAsync;
+PQputnbytes;
+PQendcopy;
+PQfn;
+PQresultStatus;
+PQntuples;
+PQnfields;
+PQbinaryTuples;
+PQfname;
+PQfnumber;
+PQftype;
+PQfsize;
+PQfmod;
+PQcmdStatus;
+PQoidStatus;
+PQcmdTuples;
+PQgetvalue;
+PQgetlength;
+PQgetisnull;
+PQclear;
+PQmakeEmptyPGresult;
+PQprint;
+PQdisplayTuples;
+PQprintTuples;
+lo_open;
+lo_close;
+lo_read;
+lo_write;
+lo_lseek;
+lo_creat;
+lo_tell;
+lo_unlink;
+lo_import;
+lo_export;
+pgresStatus;
+PQmblen;
+PQresultErrorMessage;
+PQresStatus;
+termPQExpBuffer;
+appendPQExpBufferChar;
+initPQExpBuffer;
+resetPQExpBuffer;
+PQoidValue;
+PQclientEncoding;
+PQenv2encoding;
+appendBinaryPQExpBuffer;
+appendPQExpBufferStr;
+destroyPQExpBuffer;
+createPQExpBuffer;
+PQconninfoFree;
+PQconnectPoll;
+PQconnectStart;
+PQflush;
+PQisnonblocking;
+PQresetPoll;
+PQresetStart;
+PQsetClientEncoding;
+PQsetnonblocking;
+PQfreeNotify;
+PQescapeString;
+PQescapeBytea;
+printfPQExpBuffer;
+appendPQExpBuffer;
+pg_encoding_to_char;
+pg_utf_mblen;
+PQunescapeBytea;
+PQfreemem;
+PQtransactionStatus;
+PQparameterStatus;
+PQprotocolVersion;
+PQsetErrorVerbosity;
+PQsetNoticeReceiver;
+PQexecParams;
+PQsendQueryParams;
+PQputCopyData;
+PQputCopyEnd;
+PQgetCopyData;
+PQresultErrorField;
+PQftable;
+PQftablecol;
+PQfformat;
+PQexecPrepared;
+PQsendQueryPrepared;
+PQdsplen;
+PQserverVersion;
+PQgetssl;
+pg_char_to_encoding;
+pg_valid_server_encoding;
+pqsignal;
+PQprepare;
+PQsendPrepare;
+PQgetCancel;
+PQfreeCancel;
+PQcancel;
+lo_create;
+PQinitSSL;
+PQregisterThreadLock;
+PQescapeStringConn;
+PQescapeByteaConn;
+PQencryptPassword;
+PQisthreadsafe;
+enlargePQExpBuffer;
+PQnparams;
+PQparamtype;
+PQdescribePrepared;
+PQdescribePortal;
+PQsendDescribePrepared;
+PQsendDescribePortal;
+lo_truncate;
+PQconnectionUsedPassword;
+pg_valid_server_encoding_id;
+PQconnectionNeedsPassword;
+lo_import_with_oid;
+PQcopyResult;
+PQsetResultAttrs;
+PQsetvalue;
+PQresultAlloc;
+PQregisterEventProc;
+PQinstanceData;
+PQsetInstanceData;
+PQresultInstanceData;
+PQresultSetInstanceData;
+PQfireResultCreateEvents;
+PQconninfoParse;
+PQinitOpenSSL;
+PQescapeLiteral;
+PQescapeIdentifier;
+PQconnectdbParams;
+PQconnectStartParams;
+PQping;
+PQpingParams;
+PQlibVersion;
+PQsetSingleRowMode;
+lo_lseek64;
+lo_tell64;
+lo_truncate64;
+PQconninfo;
+PQsslInUse;
+PQsslStruct;
+PQsslAttributeNames;
+PQsslAttribute;
+PQsetErrorContextVisibility;
+PQresultVerboseErrorMessage;
+PQencryptPasswordConn;
+PQresultMemorySize;
+PQhostaddr;
+PQgssEncInUse;
+PQgetgssctx;
+ local: *; };
diff --git a/libpq/libpq/mb/encnames.c b/libpq/libpq/mb/encnames.c
new file mode 120000
index 0000000..c4e83b6
--- /dev/null
+++ b/libpq/libpq/mb/encnames.c
@@ -0,0 +1 @@
+../../../upstream/src/backend/utils/mb/encnames.c \ No newline at end of file
diff --git a/libpq/libpq/mb/wchar.c b/libpq/libpq/mb/wchar.c
new file mode 120000
index 0000000..fdacab3
--- /dev/null
+++ b/libpq/libpq/mb/wchar.c
@@ -0,0 +1 @@
+../../../upstream/src/backend/utils/mb/wchar.c \ No newline at end of file
diff --git a/libpq/postgresql/pg_config.h b/libpq/libpq/pg_config.h
index 4d38fba..12d418e 100644
--- a/libpq/postgresql/pg_config.h
+++ b/libpq/libpq/pg_config.h
@@ -1,12 +1,11 @@
-/* file : libpq/postgresql/pg_config.h -*- C -*-
+/* file : libpq/pg_config.h -*- C -*-
* copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
* license : PostgreSQL License; see accompanying COPYRIGHT file
*/
/*
- * For the semantics of the following macros refer to
- * libpq/postgresql/pg_config.h.in.orig and
- * libpq/postgresql/pg_config.h.win32.orig files.
+ * For the semantics of the following macros refer to pg_config.h.in.orig,
+ * pg_config.h.win32.orig, and the upstream's configure.in.
*
* Note that we will explicitly undefine macros that are present in the libpq
* source code but should not be defined. While this is not technically
@@ -17,14 +16,47 @@
#include <stddef.h> /* offsetof() */
+#include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */
+
/*
* Version.
*/
-#undef PG_MAJORVERSION
+#undef PG_VERSION
#undef PG_VERSION_NUM
+#undef PG_MAJORVERSION
#include <libpq/version.h>
/*
+ * Endianess.
+ */
+#ifdef __FreeBSD__
+# include <sys/endian.h> /* BYTE_ORDER */
+#else
+# if defined(_WIN32)
+# ifndef BYTE_ORDER
+# define BIG_ENDIAN 4321
+# define LITTLE_ENDIAN 1234
+# define BYTE_ORDER LITTLE_ENDIAN
+# endif
+# else
+# include <sys/param.h> /* BYTE_ORDER/__BYTE_ORDER */
+# ifndef BYTE_ORDER
+# ifdef __BYTE_ORDER
+# define BYTE_ORDER __BYTE_ORDER
+# define BIG_ENDIAN __BIG_ENDIAN
+# define LITTLE_ENDIAN __LITTLE_ENDIAN
+# else
+# error no BYTE_ORDER/__BYTE_ORDER define
+# endif
+# endif
+# endif
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+# define WORDS_BIGENDIAN 1
+#endif
+
+/*
* Types, type sizes and alignments.
*/
#define ALIGNOF_(type) offsetof (struct {char c; type m;}, m)
@@ -42,6 +74,9 @@
# if __SIZEOF_LONG__ == 8
# define HAVE_LONG_INT_64 1
# endif
+# ifdef __SIZEOF_LONG_LONG__
+# define HAVE_LONG_LONG_INT 1
+# endif
# if __SIZEOF_LONG_LONG__ == 8
# define HAVE_LONG_LONG_INT_64 1
# endif
@@ -51,12 +86,14 @@
# define MAXIMUM_ALIGNOF __SIZEOF_DOUBLE__
# endif
# ifdef __SIZEOF_INT128__
-# define PG_INT128_TYPE __int128
+# define PG_INT128_TYPE __int128
+# define ALIGNOF_PG_INT128_TYPE 16
# endif
# define PG_INT64_TYPE __INT64_TYPE__
# define ACCEPT_TYPE_ARG3 socklen_t
# define SIZEOF_SIZE_T __SIZEOF_SIZE_T__
#else
+# define HAVE_LONG_LONG_INT 1
# define HAVE_LONG_LONG_INT_64 1
# define MAXIMUM_ALIGNOF 8
# define PG_INT64_TYPE long long int
@@ -69,6 +106,7 @@
#endif
#define INT64_MODIFIER "ll"
+#define SIZEOF_BOOL 1
/*
* Specific for FreeBSD.
@@ -87,6 +125,13 @@
#endif
/*
+ * Specific for FreeBSD and Linux.
+ */
+#if defined(__FreeBSD__) || defined(__linux__)
+# define HAVE_STRCHRNUL 1
+#endif
+
+/*
* Specific for FreeBSD and Mac OS.
*/
#if defined(__FreeBSD__) || defined(__APPLE__)
@@ -113,6 +158,8 @@
#ifndef _WIN32
# define HAVE_CRYPT 1
# define HAVE_DECL_FDATASYNC 1
+# define HAVE_DECL_RTLD_GLOBAL 1
+# define HAVE_DECL_RTLD_NOW 1
# define HAVE_FDATASYNC 1
# define HAVE_GETADDRINFO 1
# define HAVE_GETIFADDRS 1
@@ -139,11 +186,16 @@
# define HAVE_UNIX_SOCKETS 1
# define HAVE_UNSETENV 1
# define USE_INTEGER_DATETIMES 1
+# define HAVE_DLOPEN 1
+# define HAVE_PREAD 1
+# define HAVE_PWRITE 1
/*
* Specific for Windows.
*/
#else
# define HAVE_DECL_FDATASYNC 0
+# define HAVE_DECL_RTLD_GLOBAL 0
+# define HAVE_DECL_RTLD_NOW 0
# define HAVE_DECL_POSIX_FADVISE 0
# define HAVE_GETTIMEOFDAY 1
# define HAVE_ISINF 1
@@ -164,8 +216,34 @@
#ifndef _MSC_VER
# define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1
# define HAVE__BUILTIN_UNREACHABLE 1
+# define HAVE__BUILTIN_BSWAP16 1
+# define HAVE__BUILTIN_BSWAP32 1
+# define HAVE__BUILTIN_BSWAP64 1
+# define HAVE__BUILTIN_OP_OVERFLOW 1
+#endif
+
+/*
+ * Relates to the enabled OpenSSL.
+ */
+#define USE_OPENSSL 1
+#define HAVE_OPENSSL_INIT_SSL 1
+#define HAVE_ASN1_STRING_GET0_DATA 1
+#define HAVE_BIO_GET_DATA 1
+#define HAVE_BIO_METH_NEW 1
+#define HAVE_SSL_CLEAR_OPTIONS 1
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+# define HAVE_CRYPTO_LOCK 1
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+# define HAVE_X509_GET_SIGNATURE_NID 1
#endif
+#define USE_OPENSSL_RANDOM 1
+#undef USE_DEV_URANDOM
+#undef USE_WIN32_RANDOM
+
/*
* Common for all supported OSes/compilers.
*/
@@ -174,12 +252,17 @@
#define HAVE_RINT 1
#define HAVE_DECL_SNPRINTF 1
#define HAVE_DECL_VSNPRINTF 1
+#define HAVE_DECL_STRNLEN 1
+#define HAVE_DECL_STRTOLL 1
+#define HAVE_DECL_STRTOULL 1
#define HAVE_FSEEKO 1
#define HAVE_FUNCNAME__FUNC 1
#define HAVE_IPV6 1
#define HAVE_STDINT_H 1
+#define HAVE_STDBOOL_H 1
#define HAVE_STRTOLL 1
#define HAVE_STRTOULL 1
+#define HAVE_STRTOF 1
#define HAVE_TOWLOWER 1
#define HAVE_WCSTOMBS 1
#define HAVE_SSL_GET_CURRENT_COMPRESSION 1
@@ -187,6 +270,7 @@
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
#define BLCKSZ 8192
+#define XLOG_BLCKSZ 8192
#define PG_KRB_SRVNAM "postgres"
#define PG_PRINTF_ATTRIBUTE printf
#define FLEXIBLE_ARRAY_MEMBER
@@ -205,12 +289,11 @@
*/
/*
- * The following features are disabled by default, so we also disable them.
+ * The following features are disabled.
*/
#undef USE_ASSERT_CHECKING
#undef ENABLE_NLS
#undef ENABLE_GSS
-#undef USE_OPENSSL
#undef USE_LDAP
/*
@@ -252,7 +335,7 @@
/*
* Something optimization-related for PowerPC machines (see
- * libpq/postgresql/pg_config_manual.h for more details).
+ * libpq/include/pg_config_manual.h for more details).
*/
#undef HAVE_PPC_LWARX_MUTEX_HINT
@@ -278,3 +361,9 @@
* <sys/ucred.h> (HAVE_SYS_UCRED_H macro).
*/
#undef HAVE_UCRED_H
+
+/*
+ * Meaningless as HAVE_STRTOULL and HAVE_STRTOULL are always defined.
+ */
+#undef HAVE___STRTOLL
+#undef HAVE___STRTOULL
diff --git a/libpq/libpq/pg_config.h.in.orig b/libpq/libpq/pg_config.h.in.orig
new file mode 120000
index 0000000..0232148
--- /dev/null
+++ b/libpq/libpq/pg_config.h.in.orig
@@ -0,0 +1 @@
+../../upstream/src/include/pg_config.h.in \ No newline at end of file
diff --git a/libpq/libpq/pg_config.h.win32.orig b/libpq/libpq/pg_config.h.win32.orig
new file mode 120000
index 0000000..9c4d1e1
--- /dev/null
+++ b/libpq/libpq/pg_config.h.win32.orig
@@ -0,0 +1 @@
+../../upstream/src/include/pg_config.h.win32 \ No newline at end of file
diff --git a/libpq/postgresql/pg_config_ext.h b/libpq/libpq/pg_config_ext.h
index f1fd0f5..e3a9abe 100644
--- a/libpq/postgresql/pg_config_ext.h
+++ b/libpq/libpq/pg_config_ext.h
@@ -1,12 +1,11 @@
-/* file : libpq/postgresql/pg_config_ext.h -*- C -*-
+/* file : libpq/pg_config_ext.h -*- C -*-
* copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
* license : PostgreSQL License; see accompanying COPYRIGHT file
*/
/*
- * For the semanics of the following macros refer to the
- * libpq/postgresql/pg_config_ext.h.in.orig and
- * libpq/postgresql/pg_config_ext.h.win32.orig file.
+ * For the semantics of the following macros refer to pg_config_ext.h.in.orig,
+ * pg_config_ext.h.win32.orig, and the upstream's configure.in.
*/
/*
diff --git a/libpq/libpq/pg_config_ext.h.in.orig b/libpq/libpq/pg_config_ext.h.in.orig
new file mode 120000
index 0000000..22f6198
--- /dev/null
+++ b/libpq/libpq/pg_config_ext.h.in.orig
@@ -0,0 +1 @@
+../../upstream/src/include/pg_config_ext.h.in \ No newline at end of file
diff --git a/libpq/libpq/pg_config_ext.h.win32.orig b/libpq/libpq/pg_config_ext.h.win32.orig
new file mode 120000
index 0000000..e401e39
--- /dev/null
+++ b/libpq/libpq/pg_config_ext.h.win32.orig
@@ -0,0 +1 @@
+../../upstream/src/include/pg_config_ext.h.win32 \ No newline at end of file
diff --git a/libpq/libpq/pg_config_os.h b/libpq/libpq/pg_config_os.h
new file mode 100644
index 0000000..e616265
--- /dev/null
+++ b/libpq/libpq/pg_config_os.h
@@ -0,0 +1,21 @@
+/* file : libpq/pg_config_os.h -*- C -*-
+ * copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
+ * license : PostgreSQL License; see accompanying COPYRIGHT file
+ */
+
+/*
+ * The upstream package makefile creates this file as a symlink to the
+ * target-specific header in src/include/port/.
+ */
+
+#if defined(__linux__)
+# include <include/port/linux.h>
+#elif defined(__FreeBSD__)
+# include <include/port/freebsd.h>
+#elif defined(__APPLE__)
+# include <include/port/darwin.h>
+#elif defined(_WIN32)
+# include <include/port/win32.h>
+#else
+# error this OS is not supported
+#endif
diff --git a/libpq/libpq/pg_config_paths.h b/libpq/libpq/pg_config_paths.h
new file mode 100644
index 0000000..2e67511
--- /dev/null
+++ b/libpq/libpq/pg_config_paths.h
@@ -0,0 +1,11 @@
+/* file : libpq/pg_config_paths.h -*- C -*-
+ * copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
+ * license : PostgreSQL License; see accompanying COPYRIGHT file
+ */
+
+/*
+ * The upstream package makefile creates this file on the fly, dumping a
+ * number of macro definitions. The libpq source files only use the SYSCONFDIR
+ * macro (for the configuration we package against) which we define via the -D
+ * preprocessor option (see buildfile for details).
+ */
diff --git a/libpq/libpq/port/chklocale.c b/libpq/libpq/port/chklocale.c
new file mode 120000
index 0000000..8447432
--- /dev/null
+++ b/libpq/libpq/port/chklocale.c
@@ -0,0 +1 @@
+../../../upstream/src/port/chklocale.c \ No newline at end of file
diff --git a/libpq/libpq/port/getaddrinfo.c b/libpq/libpq/port/getaddrinfo.c
new file mode 120000
index 0000000..ca07fe4
--- /dev/null
+++ b/libpq/libpq/port/getaddrinfo.c
@@ -0,0 +1 @@
+../../../upstream/src/port/getaddrinfo.c \ No newline at end of file
diff --git a/libpq/libpq/port/getpeereid.c b/libpq/libpq/port/getpeereid.c
new file mode 120000
index 0000000..88e09de
--- /dev/null
+++ b/libpq/libpq/port/getpeereid.c
@@ -0,0 +1 @@
+../../../upstream/src/port/getpeereid.c \ No newline at end of file
diff --git a/libpq/libpq/port/inet_aton.c b/libpq/libpq/port/inet_aton.c
new file mode 120000
index 0000000..dec85cf
--- /dev/null
+++ b/libpq/libpq/port/inet_aton.c
@@ -0,0 +1 @@
+../../../upstream/src/port/inet_aton.c \ No newline at end of file
diff --git a/libpq/libpq/port/inet_net_ntop.c b/libpq/libpq/port/inet_net_ntop.c
new file mode 120000
index 0000000..342abc2
--- /dev/null
+++ b/libpq/libpq/port/inet_net_ntop.c
@@ -0,0 +1 @@
+../../../upstream/src/port/inet_net_ntop.c \ No newline at end of file
diff --git a/libpq/libpq/port/noblock.c b/libpq/libpq/port/noblock.c
new file mode 120000
index 0000000..912f287
--- /dev/null
+++ b/libpq/libpq/port/noblock.c
@@ -0,0 +1 @@
+../../../upstream/src/port/noblock.c \ No newline at end of file
diff --git a/libpq/libpq/port/open.c b/libpq/libpq/port/open.c
new file mode 120000
index 0000000..6cac9e0
--- /dev/null
+++ b/libpq/libpq/port/open.c
@@ -0,0 +1 @@
+../../../upstream/src/port/open.c \ No newline at end of file
diff --git a/libpq/libpq/port/pg_strong_random.c b/libpq/libpq/port/pg_strong_random.c
new file mode 120000
index 0000000..911f1c2
--- /dev/null
+++ b/libpq/libpq/port/pg_strong_random.c
@@ -0,0 +1 @@
+../../../upstream/src/port/pg_strong_random.c \ No newline at end of file
diff --git a/libpq/libpq/port/pgsleep.c b/libpq/libpq/port/pgsleep.c
new file mode 120000
index 0000000..36040ee
--- /dev/null
+++ b/libpq/libpq/port/pgsleep.c
@@ -0,0 +1 @@
+../../../upstream/src/port/pgsleep.c \ No newline at end of file
diff --git a/libpq/libpq/port/pgstrcasecmp.c b/libpq/libpq/port/pgstrcasecmp.c
new file mode 120000
index 0000000..7e5b081
--- /dev/null
+++ b/libpq/libpq/port/pgstrcasecmp.c
@@ -0,0 +1 @@
+../../../upstream/src/port/pgstrcasecmp.c \ No newline at end of file
diff --git a/libpq/libpq/port/pthread-win32.h b/libpq/libpq/port/pthread-win32.h
new file mode 120000
index 0000000..a4a445d
--- /dev/null
+++ b/libpq/libpq/port/pthread-win32.h
@@ -0,0 +1 @@
+../../../upstream/src/port/pthread-win32.h \ No newline at end of file
diff --git a/libpq/libpq/port/snprintf.c b/libpq/libpq/port/snprintf.c
new file mode 120000
index 0000000..a73fb8e
--- /dev/null
+++ b/libpq/libpq/port/snprintf.c
@@ -0,0 +1 @@
+../../../upstream/src/port/snprintf.c \ No newline at end of file
diff --git a/libpq/libpq/port/strerror.c b/libpq/libpq/port/strerror.c
new file mode 120000
index 0000000..733a98c
--- /dev/null
+++ b/libpq/libpq/port/strerror.c
@@ -0,0 +1 @@
+../../../upstream/src/port/strerror.c \ No newline at end of file
diff --git a/libpq/libpq/port/strlcpy.c b/libpq/libpq/port/strlcpy.c
new file mode 120000
index 0000000..0f3db74
--- /dev/null
+++ b/libpq/libpq/port/strlcpy.c
@@ -0,0 +1 @@
+../../../upstream/src/port/strlcpy.c \ No newline at end of file
diff --git a/libpq/libpq/port/system.c b/libpq/libpq/port/system.c
new file mode 120000
index 0000000..80c33eb
--- /dev/null
+++ b/libpq/libpq/port/system.c
@@ -0,0 +1 @@
+../../../upstream/src/port/system.c \ No newline at end of file
diff --git a/libpq/libpq/port/thread.c b/libpq/libpq/port/thread.c
new file mode 120000
index 0000000..c8f5fbf
--- /dev/null
+++ b/libpq/libpq/port/thread.c
@@ -0,0 +1 @@
+../../../upstream/src/port/thread.c \ No newline at end of file
diff --git a/libpq/libpq/port/win32error.c b/libpq/libpq/port/win32error.c
new file mode 120000
index 0000000..02fd874
--- /dev/null
+++ b/libpq/libpq/port/win32error.c
@@ -0,0 +1 @@
+../../../upstream/src/port/win32error.c \ No newline at end of file
diff --git a/libpq/libpq/port/win32setlocale.c b/libpq/libpq/port/win32setlocale.c
new file mode 120000
index 0000000..ab72c17
--- /dev/null
+++ b/libpq/libpq/port/win32setlocale.c
@@ -0,0 +1 @@
+../../../upstream/src/port/win32setlocale.c \ No newline at end of file
diff --git a/libpq/libpq/pq b/libpq/libpq/pq
new file mode 120000
index 0000000..1f95366
--- /dev/null
+++ b/libpq/libpq/pq
@@ -0,0 +1 @@
+../../upstream/src/interfaces/libpq \ No newline at end of file
diff --git a/libpq/libpq/version.h.in b/libpq/libpq/version.h.in
new file mode 100644
index 0000000..0dec491
--- /dev/null
+++ b/libpq/libpq/version.h.in
@@ -0,0 +1,17 @@
+/* file : libpq/version.h.in -*- C -*-
+ * copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
+ * license : PostgreSQL License; see accompanying COPYRIGHT file
+ */
+
+#ifndef PG_MAJORVERSION /* Note: using the version macro itself. */
+
+#define PG_VERSION "$libpq.version.major$.$libpq.version.minor$"
+
+/*
+ * For example, 120001 for 12.1.
+ */
+#define PG_VERSION_NUM (10000 * $libpq.version.major$ + $libpq.version.minor$)
+
+#define PG_MAJORVERSION "$libpq.version.major$"
+
+#endif /* PG_MAJORVERSION */
diff --git a/manifest b/libpq/manifest
index 2523d34..211af02 100644
--- a/manifest
+++ b/libpq/manifest
@@ -3,7 +3,8 @@ name: libpq
# Note: remember to update doc-url below!
#
-version: 9.6.5+6
+version: 12.1.0-a.0.z
+upstream-version: 12.1
project: postgresql
summary: PostgreSQL C API client library
@@ -11,12 +12,14 @@ license: PostgreSQL License ; Permissive free software license.
topics: C, PostgreSQL, SQL, relational database
description-file: README
url: https://www.postgresql.org/
-doc-url: https://www.postgresql.org/docs/9.6/static/libpq.html
-src-url: https://git.build2.org/cgit/packaging/postgresql/libpq/tree/
+doc-url: https://www.postgresql.org/docs/12/libpq.html
+src-url: https://git.build2.org/cgit/packaging/postgresql/postgresql/tree/libpq/
package-url: https://git.build2.org/cgit/packaging/postgresql/
email: pgsql-general@postgresql.org ; Mailing list.
package-email: packaging@build2.org ; Mailing list.
build-email: builds@build2.org
builds: all
-depends: * build2 >= 0.11.0
-depends: * bpkg >= 0.11.0
+depends: * build2 >= 0.12.0
+depends: * bpkg >= 0.12.0
+depends: libcrypto >= 1.1.1
+depends: libssl >= 1.1.1
diff --git a/libpq/md5.c b/libpq/md5.c
deleted file mode 100644
index 5af54e6..0000000
--- a/libpq/md5.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * md5.c
- *
- * Implements the MD5 Message-Digest Algorithm as specified in
- * RFC 1321. This implementation is a simple one, in that it
- * needs every input byte to be buffered before doing any
- * calculations. I do not expect this file to be used for
- * general purpose MD5'ing of large amounts of data, only for
- * generating hashed passwords from limited input.
- *
- * Sverre H. Huseby <sverrehu@online.no>
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- * src/backend/libpq/md5.c
- */
-
-/* This is intended to be used in both frontend and backend, so use c.h */
-#include "c.h"
-
-#include "libpq/md5.h"
-
-
-/*
- * PRIVATE FUNCTIONS
- */
-
-
-/*
- * The returned array is allocated using malloc. the caller should free it
- * when it is no longer needed.
- */
-static uint8 *
-createPaddedCopyWithLength(const uint8 *b, uint32 *l)
-{
- uint8 *ret;
- uint32 q;
- uint32 len,
- newLen448;
- uint32 len_high,
- len_low; /* 64-bit value split into 32-bit sections */
-
- len = ((b == NULL) ? 0 : *l);
- newLen448 = len + 64 - (len % 64) - 8;
- if (newLen448 <= len)
- newLen448 += 64;
-
- *l = newLen448 + 8;
- if ((ret = (uint8 *) malloc(sizeof(uint8) * *l)) == NULL)
- return NULL;
-
- if (b != NULL)
- memcpy(ret, b, sizeof(uint8) * len);
-
- /* pad */
- ret[len] = 0x80;
- for (q = len + 1; q < newLen448; q++)
- ret[q] = 0x00;
-
- /* append length as a 64 bit bitcount */
- len_low = len;
- /* split into two 32-bit values */
- /* we only look at the bottom 32-bits */
- len_high = len >> 29;
- len_low <<= 3;
- q = newLen448;
- ret[q++] = (len_low & 0xff);
- len_low >>= 8;
- ret[q++] = (len_low & 0xff);
- len_low >>= 8;
- ret[q++] = (len_low & 0xff);
- len_low >>= 8;
- ret[q++] = (len_low & 0xff);
- ret[q++] = (len_high & 0xff);
- len_high >>= 8;
- ret[q++] = (len_high & 0xff);
- len_high >>= 8;
- ret[q++] = (len_high & 0xff);
- len_high >>= 8;
- ret[q] = (len_high & 0xff);
-
- return ret;
-}
-
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define ROT_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
-static void
-doTheRounds(uint32 X[16], uint32 state[4])
-{
- uint32 a,
- b,
- c,
- d;
-
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
-
- /* round 1 */
- a = b + ROT_LEFT((a + F(b, c, d) + X[0] + 0xd76aa478), 7); /* 1 */
- d = a + ROT_LEFT((d + F(a, b, c) + X[1] + 0xe8c7b756), 12); /* 2 */
- c = d + ROT_LEFT((c + F(d, a, b) + X[2] + 0x242070db), 17); /* 3 */
- b = c + ROT_LEFT((b + F(c, d, a) + X[3] + 0xc1bdceee), 22); /* 4 */
- a = b + ROT_LEFT((a + F(b, c, d) + X[4] + 0xf57c0faf), 7); /* 5 */
- d = a + ROT_LEFT((d + F(a, b, c) + X[5] + 0x4787c62a), 12); /* 6 */
- c = d + ROT_LEFT((c + F(d, a, b) + X[6] + 0xa8304613), 17); /* 7 */
- b = c + ROT_LEFT((b + F(c, d, a) + X[7] + 0xfd469501), 22); /* 8 */
- a = b + ROT_LEFT((a + F(b, c, d) + X[8] + 0x698098d8), 7); /* 9 */
- d = a + ROT_LEFT((d + F(a, b, c) + X[9] + 0x8b44f7af), 12); /* 10 */
- c = d + ROT_LEFT((c + F(d, a, b) + X[10] + 0xffff5bb1), 17); /* 11 */
- b = c + ROT_LEFT((b + F(c, d, a) + X[11] + 0x895cd7be), 22); /* 12 */
- a = b + ROT_LEFT((a + F(b, c, d) + X[12] + 0x6b901122), 7); /* 13 */
- d = a + ROT_LEFT((d + F(a, b, c) + X[13] + 0xfd987193), 12); /* 14 */
- c = d + ROT_LEFT((c + F(d, a, b) + X[14] + 0xa679438e), 17); /* 15 */
- b = c + ROT_LEFT((b + F(c, d, a) + X[15] + 0x49b40821), 22); /* 16 */
-
- /* round 2 */
- a = b + ROT_LEFT((a + G(b, c, d) + X[1] + 0xf61e2562), 5); /* 17 */
- d = a + ROT_LEFT((d + G(a, b, c) + X[6] + 0xc040b340), 9); /* 18 */
- c = d + ROT_LEFT((c + G(d, a, b) + X[11] + 0x265e5a51), 14); /* 19 */
- b = c + ROT_LEFT((b + G(c, d, a) + X[0] + 0xe9b6c7aa), 20); /* 20 */
- a = b + ROT_LEFT((a + G(b, c, d) + X[5] + 0xd62f105d), 5); /* 21 */
- d = a + ROT_LEFT((d + G(a, b, c) + X[10] + 0x02441453), 9); /* 22 */
- c = d + ROT_LEFT((c + G(d, a, b) + X[15] + 0xd8a1e681), 14); /* 23 */
- b = c + ROT_LEFT((b + G(c, d, a) + X[4] + 0xe7d3fbc8), 20); /* 24 */
- a = b + ROT_LEFT((a + G(b, c, d) + X[9] + 0x21e1cde6), 5); /* 25 */
- d = a + ROT_LEFT((d + G(a, b, c) + X[14] + 0xc33707d6), 9); /* 26 */
- c = d + ROT_LEFT((c + G(d, a, b) + X[3] + 0xf4d50d87), 14); /* 27 */
- b = c + ROT_LEFT((b + G(c, d, a) + X[8] + 0x455a14ed), 20); /* 28 */
- a = b + ROT_LEFT((a + G(b, c, d) + X[13] + 0xa9e3e905), 5); /* 29 */
- d = a + ROT_LEFT((d + G(a, b, c) + X[2] + 0xfcefa3f8), 9); /* 30 */
- c = d + ROT_LEFT((c + G(d, a, b) + X[7] + 0x676f02d9), 14); /* 31 */
- b = c + ROT_LEFT((b + G(c, d, a) + X[12] + 0x8d2a4c8a), 20); /* 32 */
-
- /* round 3 */
- a = b + ROT_LEFT((a + H(b, c, d) + X[5] + 0xfffa3942), 4); /* 33 */
- d = a + ROT_LEFT((d + H(a, b, c) + X[8] + 0x8771f681), 11); /* 34 */
- c = d + ROT_LEFT((c + H(d, a, b) + X[11] + 0x6d9d6122), 16); /* 35 */
- b = c + ROT_LEFT((b + H(c, d, a) + X[14] + 0xfde5380c), 23); /* 36 */
- a = b + ROT_LEFT((a + H(b, c, d) + X[1] + 0xa4beea44), 4); /* 37 */
- d = a + ROT_LEFT((d + H(a, b, c) + X[4] + 0x4bdecfa9), 11); /* 38 */
- c = d + ROT_LEFT((c + H(d, a, b) + X[7] + 0xf6bb4b60), 16); /* 39 */
- b = c + ROT_LEFT((b + H(c, d, a) + X[10] + 0xbebfbc70), 23); /* 40 */
- a = b + ROT_LEFT((a + H(b, c, d) + X[13] + 0x289b7ec6), 4); /* 41 */
- d = a + ROT_LEFT((d + H(a, b, c) + X[0] + 0xeaa127fa), 11); /* 42 */
- c = d + ROT_LEFT((c + H(d, a, b) + X[3] + 0xd4ef3085), 16); /* 43 */
- b = c + ROT_LEFT((b + H(c, d, a) + X[6] + 0x04881d05), 23); /* 44 */
- a = b + ROT_LEFT((a + H(b, c, d) + X[9] + 0xd9d4d039), 4); /* 45 */
- d = a + ROT_LEFT((d + H(a, b, c) + X[12] + 0xe6db99e5), 11); /* 46 */
- c = d + ROT_LEFT((c + H(d, a, b) + X[15] + 0x1fa27cf8), 16); /* 47 */
- b = c + ROT_LEFT((b + H(c, d, a) + X[2] + 0xc4ac5665), 23); /* 48 */
-
- /* round 4 */
- a = b + ROT_LEFT((a + I(b, c, d) + X[0] + 0xf4292244), 6); /* 49 */
- d = a + ROT_LEFT((d + I(a, b, c) + X[7] + 0x432aff97), 10); /* 50 */
- c = d + ROT_LEFT((c + I(d, a, b) + X[14] + 0xab9423a7), 15); /* 51 */
- b = c + ROT_LEFT((b + I(c, d, a) + X[5] + 0xfc93a039), 21); /* 52 */
- a = b + ROT_LEFT((a + I(b, c, d) + X[12] + 0x655b59c3), 6); /* 53 */
- d = a + ROT_LEFT((d + I(a, b, c) + X[3] + 0x8f0ccc92), 10); /* 54 */
- c = d + ROT_LEFT((c + I(d, a, b) + X[10] + 0xffeff47d), 15); /* 55 */
- b = c + ROT_LEFT((b + I(c, d, a) + X[1] + 0x85845dd1), 21); /* 56 */
- a = b + ROT_LEFT((a + I(b, c, d) + X[8] + 0x6fa87e4f), 6); /* 57 */
- d = a + ROT_LEFT((d + I(a, b, c) + X[15] + 0xfe2ce6e0), 10); /* 58 */
- c = d + ROT_LEFT((c + I(d, a, b) + X[6] + 0xa3014314), 15); /* 59 */
- b = c + ROT_LEFT((b + I(c, d, a) + X[13] + 0x4e0811a1), 21); /* 60 */
- a = b + ROT_LEFT((a + I(b, c, d) + X[4] + 0xf7537e82), 6); /* 61 */
- d = a + ROT_LEFT((d + I(a, b, c) + X[11] + 0xbd3af235), 10); /* 62 */
- c = d + ROT_LEFT((c + I(d, a, b) + X[2] + 0x2ad7d2bb), 15); /* 63 */
- b = c + ROT_LEFT((b + I(c, d, a) + X[9] + 0xeb86d391), 21); /* 64 */
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-}
-
-static int
-calculateDigestFromBuffer(const uint8 *b, uint32 len, uint8 sum[16])
-{
- register uint32 i,
- j,
- k,
- newI;
- uint32 l;
- uint8 *input;
- register uint32 *wbp;
- uint32 workBuff[16],
- state[4];
-
- l = len;
-
- state[0] = 0x67452301;
- state[1] = 0xEFCDAB89;
- state[2] = 0x98BADCFE;
- state[3] = 0x10325476;
-
- if ((input = createPaddedCopyWithLength(b, &l)) == NULL)
- return 0;
-
- for (i = 0;;)
- {
- if ((newI = i + 16 * 4) > l)
- break;
- k = i + 3;
- for (j = 0; j < 16; j++)
- {
- wbp = (workBuff + j);
- *wbp = input[k--];
- *wbp <<= 8;
- *wbp |= input[k--];
- *wbp <<= 8;
- *wbp |= input[k--];
- *wbp <<= 8;
- *wbp |= input[k];
- k += 7;
- }
- doTheRounds(workBuff, state);
- i = newI;
- }
- free(input);
-
- j = 0;
- for (i = 0; i < 4; i++)
- {
- k = state[i];
- sum[j++] = (k & 0xff);
- k >>= 8;
- sum[j++] = (k & 0xff);
- k >>= 8;
- sum[j++] = (k & 0xff);
- k >>= 8;
- sum[j++] = (k & 0xff);
- }
- return 1;
-}
-
-static void
-bytesToHex(uint8 b[16], char *s)
-{
- static const char *hex = "0123456789abcdef";
- int q,
- w;
-
- for (q = 0, w = 0; q < 16; q++)
- {
- s[w++] = hex[(b[q] >> 4) & 0x0F];
- s[w++] = hex[b[q] & 0x0F];
- }
- s[w] = '\0';
-}
-
-/*
- * PUBLIC FUNCTIONS
- */
-
-/*
- * pg_md5_hash
- *
- * Calculates the MD5 sum of the bytes in a buffer.
- *
- * SYNOPSIS #include "md5.h"
- * int pg_md5_hash(const void *buff, size_t len, char *hexsum)
- *
- * INPUT buff the buffer containing the bytes that you want
- * the MD5 sum of.
- * len number of bytes in the buffer.
- *
- * OUTPUT hexsum the MD5 sum as a '\0'-terminated string of
- * hexadecimal digits. an MD5 sum is 16 bytes long.
- * each byte is represented by two heaxadecimal
- * characters. you thus need to provide an array
- * of 33 characters, including the trailing '\0'.
- *
- * RETURNS false on failure (out of memory for internal buffers) or
- * true on success.
- *
- * STANDARDS MD5 is described in RFC 1321.
- *
- * AUTHOR Sverre H. Huseby <sverrehu@online.no>
- *
- */
-bool
-pg_md5_hash(const void *buff, size_t len, char *hexsum)
-{
- uint8 sum[16];
-
- if (!calculateDigestFromBuffer(buff, len, sum))
- return false;
-
- bytesToHex(sum, hexsum);
- return true;
-}
-
-bool
-pg_md5_binary(const void *buff, size_t len, void *outbuf)
-{
- if (!calculateDigestFromBuffer(buff, len, outbuf))
- return false;
- return true;
-}
-
-
-/*
- * Computes MD5 checksum of "passwd" (a null-terminated string) followed
- * by "salt" (which need not be null-terminated).
- *
- * Output format is "md5" followed by a 32-hex-digit MD5 checksum.
- * Hence, the output buffer "buf" must be at least 36 bytes long.
- *
- * Returns TRUE if okay, FALSE on error (out of memory).
- */
-bool
-pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
- char *buf)
-{
- size_t passwd_len = strlen(passwd);
-
- /* +1 here is just to avoid risk of unportable malloc(0) */
- char *crypt_buf = malloc(passwd_len + salt_len + 1);
- bool ret;
-
- if (!crypt_buf)
- return false;
-
- /*
- * Place salt at the end because it may be known by users trying to crack
- * the MD5 output.
- */
- memcpy(crypt_buf, passwd, passwd_len);
- memcpy(crypt_buf + passwd_len, salt, salt_len);
-
- strcpy(buf, "md5");
- ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3);
-
- free(crypt_buf);
-
- return ret;
-}
diff --git a/libpq/noblock.c b/libpq/noblock.c
deleted file mode 100644
index 959d3ad..0000000
--- a/libpq/noblock.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * noblock.c
- * set a file descriptor as blocking or non-blocking
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- * src/port/noblock.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "c.h"
-
-#include <fcntl.h>
-
-
-/*
- * Put socket into nonblock mode.
- * Returns true on success, false on failure.
- */
-bool
-pg_set_noblock(pgsocket sock)
-{
-#if !defined(WIN32)
- int flags;
-
- flags = fcntl(sock, F_GETFL);
- if (flags < 0)
- return false;
- if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) == -1)
- return false;
- return true;
-#else
- unsigned long ioctlsocket_ret = 1;
-
- /* Returns non-0 on failure, while fcntl() returns -1 on failure */
- return (ioctlsocket(sock, FIONBIO, &ioctlsocket_ret) == 0);
-#endif
-}
-
-/*
- * Put socket into blocking mode.
- * Returns true on success, false on failure.
- */
-bool
-pg_set_block(pgsocket sock)
-{
-#if !defined(WIN32)
- int flags;
-
- flags = fcntl(sock, F_GETFL);
- if (flags < 0)
- return false;
- if (fcntl(sock, F_SETFL, (flags & ~O_NONBLOCK)) == -1)
- return false;
- return true;
-#else
- unsigned long ioctlsocket_ret = 0;
-
- /* Returns non-0 on failure, while fcntl() returns -1 on failure */
- return (ioctlsocket(sock, FIONBIO, &ioctlsocket_ret) == 0);
-#endif
-}
diff --git a/libpq/non-bsd/strlcpy.c b/libpq/non-bsd/strlcpy.c
deleted file mode 100644
index 6aff65c..0000000
--- a/libpq/non-bsd/strlcpy.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * strlcpy.c
- * strncpy done right
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- *
- * IDENTIFICATION
- * src/port/strlcpy.c
- *
- * This file was taken from OpenBSD and is used on platforms that don't
- * provide strlcpy(). The OpenBSD copyright terms follow.
- *-------------------------------------------------------------------------
- */
-
-/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "c.h"
-
-
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- * Function creation history: http://www.gratisoft.us/todd/papers/strlcpy.html
- */
-size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0)
- {
- while (--n != 0)
- {
- if ((*d++ = *s++) == '\0')
- break;
- }
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0)
- {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return (s - src - 1); /* count does not include NUL */
-}
diff --git a/libpq/pg_service.conf.sample b/libpq/pg_service.conf.sample
deleted file mode 100644
index 5a1c083..0000000
--- a/libpq/pg_service.conf.sample
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Connection configuration file
-#
-# A service is a set of named connection parameters. You may specify
-# multiple services in this file. Each starts with a service name in
-# brackets. Subsequent lines have connection configuration parameters of
-# the pattern "param=value" or LDAP URLs starting with "ldap://"
-# to look up such parameters. A sample configuration for postgres is
-# included in this file. Lines beginning with '#' are comments.
-#
-# Copy this to your sysconf directory (typically /usr/local/pgsql/etc) and
-# rename it pg_service.conf.
-#
-#
-#[postgres]
-#dbname=postgres
-#user=postgres
diff --git a/libpq/pgstrcasecmp.c b/libpq/pgstrcasecmp.c
deleted file mode 100644
index ee87a65..0000000
--- a/libpq/pgstrcasecmp.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pgstrcasecmp.c
- * Portable SQL-like case-independent comparisons and conversions.
- *
- * SQL99 specifies Unicode-aware case normalization, which we don't yet
- * have the infrastructure for. Instead we use tolower() to provide a
- * locale-aware translation. However, there are some locales where this
- * is not right either (eg, Turkish may do strange things with 'i' and
- * 'I'). Our current compromise is to use tolower() for characters with
- * the high bit set, and use an ASCII-only downcasing for 7-bit
- * characters.
- *
- * NB: this code should match downcase_truncate_identifier() in scansup.c.
- *
- * We also provide strict ASCII-only case conversion functions, which can
- * be used to implement C/POSIX case folding semantics no matter what the
- * C library thinks the locale is.
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- * src/port/pgstrcasecmp.c
- *
- *-------------------------------------------------------------------------
- */
-#include "c.h"
-
-#include <ctype.h>
-
-
-/*
- * Case-independent comparison of two null-terminated strings.
- */
-int
-pg_strcasecmp(const char *s1, const char *s2)
-{
- for (;;)
- {
- unsigned char ch1 = (unsigned char) *s1++;
- unsigned char ch2 = (unsigned char) *s2++;
-
- if (ch1 != ch2)
- {
- if (ch1 >= 'A' && ch1 <= 'Z')
- ch1 += 'a' - 'A';
- else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
- ch1 = tolower(ch1);
-
- if (ch2 >= 'A' && ch2 <= 'Z')
- ch2 += 'a' - 'A';
- else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
- ch2 = tolower(ch2);
-
- if (ch1 != ch2)
- return (int) ch1 - (int) ch2;
- }
- if (ch1 == 0)
- break;
- }
- return 0;
-}
-
-/*
- * Case-independent comparison of two not-necessarily-null-terminated strings.
- * At most n bytes will be examined from each string.
- */
-int
-pg_strncasecmp(const char *s1, const char *s2, size_t n)
-{
- while (n-- > 0)
- {
- unsigned char ch1 = (unsigned char) *s1++;
- unsigned char ch2 = (unsigned char) *s2++;
-
- if (ch1 != ch2)
- {
- if (ch1 >= 'A' && ch1 <= 'Z')
- ch1 += 'a' - 'A';
- else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
- ch1 = tolower(ch1);
-
- if (ch2 >= 'A' && ch2 <= 'Z')
- ch2 += 'a' - 'A';
- else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
- ch2 = tolower(ch2);
-
- if (ch1 != ch2)
- return (int) ch1 - (int) ch2;
- }
- if (ch1 == 0)
- break;
- }
- return 0;
-}
-
-/*
- * Fold a character to upper case.
- *
- * Unlike some versions of toupper(), this is safe to apply to characters
- * that aren't lower case letters. Note however that the whole thing is
- * a bit bogus for multibyte character sets.
- */
-unsigned char
-pg_toupper(unsigned char ch)
-{
- if (ch >= 'a' && ch <= 'z')
- ch += 'A' - 'a';
- else if (IS_HIGHBIT_SET(ch) && islower(ch))
- ch = toupper(ch);
- return ch;
-}
-
-/*
- * Fold a character to lower case.
- *
- * Unlike some versions of tolower(), this is safe to apply to characters
- * that aren't upper case letters. Note however that the whole thing is
- * a bit bogus for multibyte character sets.
- */
-unsigned char
-pg_tolower(unsigned char ch)
-{
- if (ch >= 'A' && ch <= 'Z')
- ch += 'a' - 'A';
- else if (IS_HIGHBIT_SET(ch) && isupper(ch))
- ch = tolower(ch);
- return ch;
-}
-
-/*
- * Fold a character to upper case, following C/POSIX locale rules.
- */
-unsigned char
-pg_ascii_toupper(unsigned char ch)
-{
- if (ch >= 'a' && ch <= 'z')
- ch += 'A' - 'a';
- return ch;
-}
-
-/*
- * Fold a character to lower case, following C/POSIX locale rules.
- */
-unsigned char
-pg_ascii_tolower(unsigned char ch)
-{
- if (ch >= 'A' && ch <= 'Z')
- ch += 'a' - 'A';
- return ch;
-}
diff --git a/libpq/postgresql/c.h b/libpq/postgresql/c.h
deleted file mode 100644
index 726f0f3..0000000
--- a/libpq/postgresql/c.h
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * c.h
- * Fundamental C definitions. This is included by every .c file in
- * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate).
- *
- * Note that the definitions here are not intended to be exposed to clients
- * of the frontend interface libraries --- so we don't worry much about
- * polluting the namespace with lots of stuff...
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/c.h
- *
- *-------------------------------------------------------------------------
- */
-/*
- *----------------------------------------------------------------
- * TABLE OF CONTENTS
- *
- * When adding stuff to this file, please try to put stuff
- * into the relevant section, or add new sections as appropriate.
- *
- * section description
- * ------- ------------------------------------------------
- * 0) pg_config.h and standard system headers
- * 1) hacks to cope with non-ANSI C compilers
- * 2) bool, true, false, TRUE, FALSE, NULL
- * 3) standard system types
- * 4) IsValid macros for system types
- * 5) offsetof, lengthof, endof, alignment
- * 6) assertions
- * 7) widely useful macros
- * 8) random stuff
- * 9) system-specific hacks
- *
- * NOTE: since this file is included by both frontend and backend modules, it's
- * almost certainly wrong to put an "extern" declaration here. typedefs and
- * macros are the kind of thing that might go here.
- *
- *----------------------------------------------------------------
- */
-#ifndef C_H
-#define C_H
-
-#include "postgres_ext.h"
-
-/* Must undef pg_config_ext.h symbols before including pg_config.h */
-#undef PG_INT64_TYPE
-
-#include "pg_config.h"
-#include "pg_config_manual.h" /* must be after pg_config.h */
-
-/*
- * We always rely on the WIN32 macro being set by our build system,
- * but _WIN32 is the compiler pre-defined macro. So make sure we define
- * WIN32 whenever _WIN32 is set, to facilitate standalone building.
- */
-#if defined(_WIN32) && !defined(WIN32)
-#define WIN32
-#endif
-
-#if !defined(WIN32) && !defined(__CYGWIN__) /* win32 includes further down */
-#include "pg_config_os.h" /* must be before any system header files */
-#endif
-
-#if _MSC_VER >= 1400 || defined(HAVE_CRTDEFS_H)
-#define errcode __msvc_errcode
-#include <crtdefs.h>
-#undef errcode
-#endif
-
-/*
- * We have to include stdlib.h here because it defines many of these macros
- * on some platforms, and we only want our definitions used if stdlib.h doesn't
- * have its own. The same goes for stddef and stdarg if present.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stddef.h>
-#include <stdarg.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <sys/types.h>
-
-#include <errno.h>
-#if defined(WIN32) || defined(__CYGWIN__)
-#include <fcntl.h> /* ensure O_BINARY is available */
-#endif
-
-#if defined(WIN32) || defined(__CYGWIN__)
-/* We have to redefine some system functions after they are included above. */
-#include "pg_config_os.h"
-#endif
-
-/*
- * Force disable inlining if PG_FORCE_DISABLE_INLINE is defined. This is used
- * to work around compiler bugs and might also be useful for investigatory
- * purposes by defining the symbol in the platform's header..
- *
- * This is done early (in slightly the wrong section) as functionality later
- * in this file might want to rely on inline functions.
- */
-#ifdef PG_FORCE_DISABLE_INLINE
-#undef inline
-#define inline
-#endif
-
-/* Must be before gettext() games below */
-#include <locale.h>
-
-#define _(x) gettext(x)
-
-#ifdef ENABLE_NLS
-#include <libintl.h>
-#else
-#define gettext(x) (x)
-#define dgettext(d,x) (x)
-#define ngettext(s,p,n) ((n) == 1 ? (s) : (p))
-#define dngettext(d,s,p,n) ((n) == 1 ? (s) : (p))
-#endif
-
-/*
- * Use this to mark string constants as needing translation at some later
- * time, rather than immediately. This is useful for cases where you need
- * access to the original string and translated string, and for cases where
- * immediate translation is not possible, like when initializing global
- * variables.
- * http://www.gnu.org/software/autoconf/manual/gettext/Special-cases.html
- */
-#define gettext_noop(x) (x)
-
-
-/* ----------------------------------------------------------------
- * Section 1: hacks to cope with non-ANSI C compilers
- *
- * type prefixes (const, signed, volatile, inline) are handled in pg_config.h.
- * ----------------------------------------------------------------
- */
-
-/*
- * CppAsString
- * Convert the argument to a string, using the C preprocessor.
- * CppConcat
- * Concatenate two arguments together, using the C preprocessor.
- *
- * Note: There used to be support here for pre-ANSI C compilers that didn't
- * support # and ##. Nowadays, these macros are just for clarity and/or
- * backward compatibility with existing PostgreSQL code.
- */
-#define CppAsString(identifier) #identifier
-#define CppConcat(x, y) x##y
-
-/*
- * dummyret is used to set return values in macros that use ?: to make
- * assignments. gcc wants these to be void, other compilers like char
- */
-#ifdef __GNUC__ /* GNU cc */
-#define dummyret void
-#else
-#define dummyret char
-#endif
-
-/* Which __func__ symbol do we have, if any? */
-#ifdef HAVE_FUNCNAME__FUNC
-#define PG_FUNCNAME_MACRO __func__
-#else
-#ifdef HAVE_FUNCNAME__FUNCTION
-#define PG_FUNCNAME_MACRO __FUNCTION__
-#else
-#define PG_FUNCNAME_MACRO NULL
-#endif
-#endif
-
-/* ----------------------------------------------------------------
- * Section 2: bool, true, false, TRUE, FALSE, NULL
- * ----------------------------------------------------------------
- */
-
-/*
- * bool
- * Boolean value, either true or false.
- *
- * XXX for C++ compilers, we assume the compiler has a compatible
- * built-in definition of bool.
- */
-
-#ifndef __cplusplus
-
-#ifndef bool
-typedef char bool;
-#endif
-
-#ifndef true
-#define true ((bool) 1)
-#endif
-
-#ifndef false
-#define false ((bool) 0)
-#endif
-#endif /* not C++ */
-
-typedef bool *BoolPtr;
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/*
- * NULL
- * Null pointer.
- */
-#ifndef NULL
-#define NULL ((void *) 0)
-#endif
-
-
-/* ----------------------------------------------------------------
- * Section 3: standard system types
- * ----------------------------------------------------------------
- */
-
-/*
- * Pointer
- * Variable holding address of any memory resident object.
- *
- * XXX Pointer arithmetic is done with this, so it can't be void *
- * under "true" ANSI compilers.
- */
-typedef char *Pointer;
-
-/*
- * intN
- * Signed integer, EXACTLY N BITS IN SIZE,
- * used for numerical computations and the
- * frontend/backend protocol.
- */
-#ifndef HAVE_INT8
-typedef signed char int8; /* == 8 bits */
-typedef signed short int16; /* == 16 bits */
-typedef signed int int32; /* == 32 bits */
-#endif /* not HAVE_INT8 */
-
-/*
- * uintN
- * Unsigned integer, EXACTLY N BITS IN SIZE,
- * used for numerical computations and the
- * frontend/backend protocol.
- */
-#ifndef HAVE_UINT8
-typedef unsigned char uint8; /* == 8 bits */
-typedef unsigned short uint16; /* == 16 bits */
-typedef unsigned int uint32; /* == 32 bits */
-#endif /* not HAVE_UINT8 */
-
-/*
- * bitsN
- * Unit of bitwise operation, AT LEAST N BITS IN SIZE.
- */
-typedef uint8 bits8; /* >= 8 bits */
-typedef uint16 bits16; /* >= 16 bits */
-typedef uint32 bits32; /* >= 32 bits */
-
-/*
- * 64-bit integers
- */
-#ifdef HAVE_LONG_INT_64
-/* Plain "long int" fits, use it */
-
-#ifndef HAVE_INT64
-typedef long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long int uint64;
-#endif
-#elif defined(HAVE_LONG_LONG_INT_64)
-/* We have working support for "long long int", use that */
-
-#ifndef HAVE_INT64
-typedef long long int int64;
-#endif
-#ifndef HAVE_UINT64
-typedef unsigned long long int uint64;
-#endif
-#else
-/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
-#error must have a working 64-bit integer datatype
-#endif
-
-/* Decide if we need to decorate 64-bit constants */
-#ifdef HAVE_LL_CONSTANTS
-#define INT64CONST(x) ((int64) x##LL)
-#define UINT64CONST(x) ((uint64) x##ULL)
-#else
-#define INT64CONST(x) ((int64) x)
-#define UINT64CONST(x) ((uint64) x)
-#endif
-
-/* snprintf format strings to use for 64-bit integers */
-#define INT64_FORMAT "%" INT64_MODIFIER "d"
-#define UINT64_FORMAT "%" INT64_MODIFIER "u"
-
-/*
- * 128-bit signed and unsigned integers
- * There currently is only a limited support for the type. E.g. 128bit
- * literals and snprintf are not supported; but math is.
- */
-#if defined(PG_INT128_TYPE)
-#define HAVE_INT128
-typedef PG_INT128_TYPE int128;
-typedef unsigned PG_INT128_TYPE uint128;
-#endif
-
-/*
- * stdint.h limits aren't guaranteed to be present and aren't guaranteed to
- * have compatible types with our fixed width types. So just define our own.
- */
-#define PG_INT8_MIN (-0x7F-1)
-#define PG_INT8_MAX (0x7F)
-#define PG_UINT8_MAX (0xFF)
-#define PG_INT16_MIN (-0x7FFF-1)
-#define PG_INT16_MAX (0x7FFF)
-#define PG_UINT16_MAX (0xFFFF)
-#define PG_INT32_MIN (-0x7FFFFFFF-1)
-#define PG_INT32_MAX (0x7FFFFFFF)
-#define PG_UINT32_MAX (0xFFFFFFFF)
-#define PG_INT64_MIN (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
-#define PG_INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF)
-#define PG_UINT64_MAX UINT64CONST(0xFFFFFFFFFFFFFFFF)
-
-/* Select timestamp representation (float8 or int64) */
-#ifdef USE_INTEGER_DATETIMES
-#define HAVE_INT64_TIMESTAMP
-#endif
-
-/*
- * Size
- * Size of any memory resident object, as returned by sizeof.
- */
-typedef size_t Size;
-
-/*
- * Index
- * Index into any memory resident array.
- *
- * Note:
- * Indices are non negative.
- */
-typedef unsigned int Index;
-
-/*
- * Offset
- * Offset into any memory resident array.
- *
- * Note:
- * This differs from an Index in that an Index is always
- * non negative, whereas Offset may be negative.
- */
-typedef signed int Offset;
-
-/*
- * Common Postgres datatype names (as used in the catalogs)
- */
-typedef float float4;
-typedef double float8;
-
-/*
- * Oid, RegProcedure, TransactionId, SubTransactionId, MultiXactId,
- * CommandId
- */
-
-/* typedef Oid is in postgres_ext.h */
-
-/*
- * regproc is the type name used in the include/catalog headers, but
- * RegProcedure is the preferred name in C code.
- */
-typedef Oid regproc;
-typedef regproc RegProcedure;
-
-typedef uint32 TransactionId;
-
-typedef uint32 LocalTransactionId;
-
-typedef uint32 SubTransactionId;
-
-#define InvalidSubTransactionId ((SubTransactionId) 0)
-#define TopSubTransactionId ((SubTransactionId) 1)
-
-/* MultiXactId must be equivalent to TransactionId, to fit in t_xmax */
-typedef TransactionId MultiXactId;
-
-typedef uint32 MultiXactOffset;
-
-typedef uint32 CommandId;
-
-#define FirstCommandId ((CommandId) 0)
-#define InvalidCommandId (~(CommandId)0)
-
-/*
- * Array indexing support
- */
-#define MAXDIM 6
-typedef struct
-{
- int indx[MAXDIM];
-} IntArray;
-
-/* ----------------
- * Variable-length datatypes all share the 'struct varlena' header.
- *
- * NOTE: for TOASTable types, this is an oversimplification, since the value
- * may be compressed or moved out-of-line. However datatype-specific routines
- * are mostly content to deal with de-TOASTed values only, and of course
- * client-side routines should never see a TOASTed value. But even in a
- * de-TOASTed value, beware of touching vl_len_ directly, as its representation
- * is no longer convenient. It's recommended that code always use the VARDATA,
- * VARSIZE, and SET_VARSIZE macros instead of relying on direct mentions of
- * the struct fields. See postgres.h for details of the TOASTed form.
- * ----------------
- */
-struct varlena
-{
- char vl_len_[4]; /* Do not touch this field directly! */
- char vl_dat[FLEXIBLE_ARRAY_MEMBER]; /* Data content is here */
-};
-
-#define VARHDRSZ ((int32) sizeof(int32))
-
-/*
- * These widely-used datatypes are just a varlena header and the data bytes.
- * There is no terminating null or anything like that --- the data length is
- * always VARSIZE(ptr) - VARHDRSZ.
- */
-typedef struct varlena bytea;
-typedef struct varlena text;
-typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */
-typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */
-
-/*
- * Specialized array types. These are physically laid out just the same
- * as regular arrays (so that the regular array subscripting code works
- * with them). They exist as distinct types mostly for historical reasons:
- * they have nonstandard I/O behavior which we don't want to change for fear
- * of breaking applications that look at the system catalogs. There is also
- * an implementation issue for oidvector: it's part of the primary key for
- * pg_proc, and we can't use the normal btree array support routines for that
- * without circularity.
- */
-typedef struct
-{
- int32 vl_len_; /* these fields must match ArrayType! */
- int ndim; /* always 1 for int2vector */
- int32 dataoffset; /* always 0 for int2vector */
- Oid elemtype;
- int dim1;
- int lbound1;
- int16 values[FLEXIBLE_ARRAY_MEMBER];
-} int2vector;
-
-typedef struct
-{
- int32 vl_len_; /* these fields must match ArrayType! */
- int ndim; /* always 1 for oidvector */
- int32 dataoffset; /* always 0 for oidvector */
- Oid elemtype;
- int dim1;
- int lbound1;
- Oid values[FLEXIBLE_ARRAY_MEMBER];
-} oidvector;
-
-/*
- * Representation of a Name: effectively just a C string, but null-padded to
- * exactly NAMEDATALEN bytes. The use of a struct is historical.
- */
-typedef struct nameData
-{
- char data[NAMEDATALEN];
-} NameData;
-typedef NameData *Name;
-
-#define NameStr(name) ((name).data)
-
-/*
- * Support macros for escaping strings. escape_backslash should be TRUE
- * if generating a non-standard-conforming string. Prefixing a string
- * with ESCAPE_STRING_SYNTAX guarantees it is non-standard-conforming.
- * Beware of multiple evaluation of the "ch" argument!
- */
-#define SQL_STR_DOUBLE(ch, escape_backslash) \
- ((ch) == '\'' || ((ch) == '\\' && (escape_backslash)))
-
-#define ESCAPE_STRING_SYNTAX 'E'
-
-/* ----------------------------------------------------------------
- * Section 4: IsValid macros for system types
- * ----------------------------------------------------------------
- */
-/*
- * BoolIsValid
- * True iff bool is valid.
- */
-#define BoolIsValid(boolean) ((boolean) == false || (boolean) == true)
-
-/*
- * PointerIsValid
- * True iff pointer is valid.
- */
-#define PointerIsValid(pointer) ((const void*)(pointer) != NULL)
-
-/*
- * PointerIsAligned
- * True iff pointer is properly aligned to point to the given type.
- */
-#define PointerIsAligned(pointer, type) \
- (((uintptr_t)(pointer) % (sizeof (type))) == 0)
-
-#define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid))
-
-#define RegProcedureIsValid(p) OidIsValid(p)
-
-
-/* ----------------------------------------------------------------
- * Section 5: offsetof, lengthof, endof, alignment
- * ----------------------------------------------------------------
- */
-/*
- * offsetof
- * Offset of a structure/union field within that structure/union.
- *
- * XXX This is supposed to be part of stddef.h, but isn't on
- * some systems (like SunOS 4).
- */
-#ifndef offsetof
-#define offsetof(type, field) ((long) &((type *)0)->field)
-#endif /* offsetof */
-
-/*
- * lengthof
- * Number of elements in an array.
- */
-#define lengthof(array) (sizeof (array) / sizeof ((array)[0]))
-
-/*
- * endof
- * Address of the element one past the last in an array.
- */
-#define endof(array) (&(array)[lengthof(array)])
-
-/* ----------------
- * Alignment macros: align a length or address appropriately for a given type.
- * The fooALIGN() macros round up to a multiple of the required alignment,
- * while the fooALIGN_DOWN() macros round down. The latter are more useful
- * for problems like "how many X-sized structures will fit in a page?".
- *
- * NOTE: TYPEALIGN[_DOWN] will not work if ALIGNVAL is not a power of 2.
- * That case seems extremely unlikely to be needed in practice, however.
- * ----------------
- */
-
-#define TYPEALIGN(ALIGNVAL,LEN) \
- (((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) & ~((uintptr_t) ((ALIGNVAL) - 1)))
-
-#define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN))
-#define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN))
-#define LONGALIGN(LEN) TYPEALIGN(ALIGNOF_LONG, (LEN))
-#define DOUBLEALIGN(LEN) TYPEALIGN(ALIGNOF_DOUBLE, (LEN))
-#define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN))
-/* MAXALIGN covers only built-in types, not buffers */
-#define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN))
-#define CACHELINEALIGN(LEN) TYPEALIGN(PG_CACHE_LINE_SIZE, (LEN))
-
-#define TYPEALIGN_DOWN(ALIGNVAL,LEN) \
- (((uintptr_t) (LEN)) & ~((uintptr_t) ((ALIGNVAL) - 1)))
-
-#define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
-#define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
-#define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN))
-#define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN))
-#define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN))
-
-/*
- * The above macros will not work with types wider than uintptr_t, like with
- * uint64 on 32-bit platforms. That's not problem for the usual use where a
- * pointer or a length is aligned, but for the odd case that you need to
- * align something (potentially) wider, use TYPEALIGN64.
- */
-#define TYPEALIGN64(ALIGNVAL,LEN) \
- (((uint64) (LEN) + ((ALIGNVAL) - 1)) & ~((uint64) ((ALIGNVAL) - 1)))
-
-/* we don't currently need wider versions of the other ALIGN macros */
-#define MAXALIGN64(LEN) TYPEALIGN64(MAXIMUM_ALIGNOF, (LEN))
-
-/* ----------------
- * Attribute macros
- *
- * GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
- * GCC: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
- * Sunpro: https://docs.oracle.com/cd/E18659_01/html/821-1384/gjzke.html
- * XLC: http://www-01.ibm.com/support/knowledgecenter/SSGH2K_11.1.0/com.ibm.xlc111.aix.doc/language_ref/function_attributes.html
- * XLC: http://www-01.ibm.com/support/knowledgecenter/SSGH2K_11.1.0/com.ibm.xlc111.aix.doc/language_ref/type_attrib.html
- * ----------------
- */
-
-/* only GCC supports the unused attribute */
-#ifdef __GNUC__
-#define pg_attribute_unused() __attribute__((unused))
-#else
-#define pg_attribute_unused()
-#endif
-
-/* GCC and XLC support format attributes */
-#if defined(__GNUC__) || defined(__IBMC__)
-#define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
-#define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
-#else
-#define pg_attribute_format_arg(a)
-#define pg_attribute_printf(f,a)
-#endif
-
-/* GCC, Sunpro and XLC support aligned, packed and noreturn */
-#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
-#define pg_attribute_aligned(a) __attribute__((aligned(a)))
-#define pg_attribute_noreturn() __attribute__((noreturn))
-#define pg_attribute_packed() __attribute__((packed))
-#define HAVE_PG_ATTRIBUTE_NORETURN 1
-#else
-/*
- * NB: aligned and packed are not given default definitions because they
- * affect code functionality; they *must* be implemented by the compiler
- * if they are to be used.
- */
-#define pg_attribute_noreturn()
-#endif
-
-/* ----------------------------------------------------------------
- * Section 6: assertions
- * ----------------------------------------------------------------
- */
-
-/*
- * USE_ASSERT_CHECKING, if defined, turns on all the assertions.
- * - plai 9/5/90
- *
- * It should _NOT_ be defined in releases or in benchmark copies
- */
-
-/*
- * Assert() can be used in both frontend and backend code. In frontend code it
- * just calls the standard assert, if it's available. If use of assertions is
- * not configured, it does nothing.
- */
-#ifndef USE_ASSERT_CHECKING
-
-#define Assert(condition) ((void)true)
-#define AssertMacro(condition) ((void)true)
-#define AssertArg(condition) ((void)true)
-#define AssertState(condition) ((void)true)
-#define AssertPointerAlignment(ptr, bndr) ((void)true)
-#define Trap(condition, errorType) ((void)true)
-#define TrapMacro(condition, errorType) (true)
-
-#elif defined(FRONTEND)
-
-#include <assert.h>
-#define Assert(p) assert(p)
-#define AssertMacro(p) ((void) assert(p))
-#define AssertArg(condition) assert(condition)
-#define AssertState(condition) assert(condition)
-#define AssertPointerAlignment(ptr, bndr) ((void)true)
-#else /* USE_ASSERT_CHECKING && !FRONTEND */
-
-/*
- * Trap
- * Generates an exception if the given condition is true.
- */
-#define Trap(condition, errorType) \
- do { \
- if (condition) \
- ExceptionalCondition(CppAsString(condition), (errorType), \
- __FILE__, __LINE__); \
- } while (0)
-
-/*
- * TrapMacro is the same as Trap but it's intended for use in macros:
- *
- * #define foo(x) (AssertMacro(x != 0), bar(x))
- *
- * Isn't CPP fun?
- */
-#define TrapMacro(condition, errorType) \
- ((bool) (! (condition) || \
- (ExceptionalCondition(CppAsString(condition), (errorType), \
- __FILE__, __LINE__), 0)))
-
-#define Assert(condition) \
- Trap(!(condition), "FailedAssertion")
-
-#define AssertMacro(condition) \
- ((void) TrapMacro(!(condition), "FailedAssertion"))
-
-#define AssertArg(condition) \
- Trap(!(condition), "BadArgument")
-
-#define AssertState(condition) \
- Trap(!(condition), "BadState")
-
-/*
- * Check that `ptr' is `bndr' aligned.
- */
-#define AssertPointerAlignment(ptr, bndr) \
- Trap(TYPEALIGN(bndr, (uintptr_t)(ptr)) != (uintptr_t)(ptr), \
- "UnalignedPointer")
-
-#endif /* USE_ASSERT_CHECKING && !FRONTEND */
-
-/*
- * Macros to support compile-time assertion checks.
- *
- * If the "condition" (a compile-time-constant expression) evaluates to false,
- * throw a compile error using the "errmessage" (a string literal).
- *
- * gcc 4.6 and up supports _Static_assert(), but there are bizarre syntactic
- * placement restrictions. These macros make it safe to use as a statement
- * or in an expression, respectively.
- *
- * Otherwise we fall back on a kluge that assumes the compiler will complain
- * about a negative width for a struct bit-field. This will not include a
- * helpful error message, but it beats not getting an error at all.
- */
-#ifdef HAVE__STATIC_ASSERT
-#define StaticAssertStmt(condition, errmessage) \
- do { _Static_assert(condition, errmessage); } while(0)
-#define StaticAssertExpr(condition, errmessage) \
- ({ StaticAssertStmt(condition, errmessage); true; })
-#else /* !HAVE__STATIC_ASSERT */
-#define StaticAssertStmt(condition, errmessage) \
- ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; }))
-#define StaticAssertExpr(condition, errmessage) \
- StaticAssertStmt(condition, errmessage)
-#endif /* HAVE__STATIC_ASSERT */
-
-
-/*
- * Compile-time checks that a variable (or expression) has the specified type.
- *
- * AssertVariableIsOfType() can be used as a statement.
- * AssertVariableIsOfTypeMacro() is intended for use in macros, eg
- * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x))
- *
- * If we don't have __builtin_types_compatible_p, we can still assert that
- * the types have the same size. This is far from ideal (especially on 32-bit
- * platforms) but it provides at least some coverage.
- */
-#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
-#define AssertVariableIsOfType(varname, typename) \
- StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
- CppAsString(varname) " does not have type " CppAsString(typename))
-#define AssertVariableIsOfTypeMacro(varname, typename) \
- ((void) StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
- CppAsString(varname) " does not have type " CppAsString(typename)))
-#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
-#define AssertVariableIsOfType(varname, typename) \
- StaticAssertStmt(sizeof(varname) == sizeof(typename), \
- CppAsString(varname) " does not have type " CppAsString(typename))
-#define AssertVariableIsOfTypeMacro(varname, typename) \
- ((void) StaticAssertExpr(sizeof(varname) == sizeof(typename), \
- CppAsString(varname) " does not have type " CppAsString(typename)))
-#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */
-
-
-/* ----------------------------------------------------------------
- * Section 7: widely useful macros
- * ----------------------------------------------------------------
- */
-/*
- * Max
- * Return the maximum of two numbers.
- */
-#define Max(x, y) ((x) > (y) ? (x) : (y))
-
-/*
- * Min
- * Return the minimum of two numbers.
- */
-#define Min(x, y) ((x) < (y) ? (x) : (y))
-
-/*
- * Abs
- * Return the absolute value of the argument.
- */
-#define Abs(x) ((x) >= 0 ? (x) : -(x))
-
-/*
- * StrNCpy
- * Like standard library function strncpy(), except that result string
- * is guaranteed to be null-terminated --- that is, at most N-1 bytes
- * of the source string will be kept.
- * Also, the macro returns no result (too hard to do that without
- * evaluating the arguments multiple times, which seems worse).
- *
- * BTW: when you need to copy a non-null-terminated string (like a text
- * datum) and add a null, do not do it with StrNCpy(..., len+1). That
- * might seem to work, but it fetches one byte more than there is in the
- * text object. One fine day you'll have a SIGSEGV because there isn't
- * another byte before the end of memory. Don't laugh, we've had real
- * live bug reports from real live users over exactly this mistake.
- * Do it honestly with "memcpy(dst,src,len); dst[len] = '\0';", instead.
- */
-#define StrNCpy(dst,src,len) \
- do \
- { \
- char * _dst = (dst); \
- Size _len = (len); \
-\
- if (_len > 0) \
- { \
- strncpy(_dst, (src), _len); \
- _dst[_len-1] = '\0'; \
- } \
- } while (0)
-
-
-/* Get a bit mask of the bits set in non-long aligned addresses */
-#define LONG_ALIGN_MASK (sizeof(long) - 1)
-
-/*
- * MemSet
- * Exactly the same as standard library function memset(), but considerably
- * faster for zeroing small word-aligned structures (such as parsetree nodes).
- * This has to be a macro because the main point is to avoid function-call
- * overhead. However, we have also found that the loop is faster than
- * native libc memset() on some platforms, even those with assembler
- * memset() functions. More research needs to be done, perhaps with
- * MEMSET_LOOP_LIMIT tests in configure.
- */
-#define MemSet(start, val, len) \
- do \
- { \
- /* must be void* because we don't know if it is integer aligned yet */ \
- void *_vstart = (void *) (start); \
- int _val = (val); \
- Size _len = (len); \
-\
- if ((((uintptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \
- (_len & LONG_ALIGN_MASK) == 0 && \
- _val == 0 && \
- _len <= MEMSET_LOOP_LIMIT && \
- /* \
- * If MEMSET_LOOP_LIMIT == 0, optimizer should find \
- * the whole "if" false at compile time. \
- */ \
- MEMSET_LOOP_LIMIT != 0) \
- { \
- long *_start = (long *) _vstart; \
- long *_stop = (long *) ((char *) _start + _len); \
- while (_start < _stop) \
- *_start++ = 0; \
- } \
- else \
- memset(_vstart, _val, _len); \
- } while (0)
-
-/*
- * MemSetAligned is the same as MemSet except it omits the test to see if
- * "start" is word-aligned. This is okay to use if the caller knows a-priori
- * that the pointer is suitably aligned (typically, because he just got it
- * from palloc(), which always delivers a max-aligned pointer).
- */
-#define MemSetAligned(start, val, len) \
- do \
- { \
- long *_start = (long *) (start); \
- int _val = (val); \
- Size _len = (len); \
-\
- if ((_len & LONG_ALIGN_MASK) == 0 && \
- _val == 0 && \
- _len <= MEMSET_LOOP_LIMIT && \
- MEMSET_LOOP_LIMIT != 0) \
- { \
- long *_stop = (long *) ((char *) _start + _len); \
- while (_start < _stop) \
- *_start++ = 0; \
- } \
- else \
- memset(_start, _val, _len); \
- } while (0)
-
-
-/*
- * MemSetTest/MemSetLoop are a variant version that allow all the tests in
- * MemSet to be done at compile time in cases where "val" and "len" are
- * constants *and* we know the "start" pointer must be word-aligned.
- * If MemSetTest succeeds, then it is okay to use MemSetLoop, otherwise use
- * MemSetAligned. Beware of multiple evaluations of the arguments when using
- * this approach.
- */
-#define MemSetTest(val, len) \
- ( ((len) & LONG_ALIGN_MASK) == 0 && \
- (len) <= MEMSET_LOOP_LIMIT && \
- MEMSET_LOOP_LIMIT != 0 && \
- (val) == 0 )
-
-#define MemSetLoop(start, val, len) \
- do \
- { \
- long * _start = (long *) (start); \
- long * _stop = (long *) ((char *) _start + (Size) (len)); \
- \
- while (_start < _stop) \
- *_start++ = 0; \
- } while (0)
-
-
-/*
- * Mark a point as unreachable in a portable fashion. This should preferably
- * be something that the compiler understands, to aid code generation.
- * In assert-enabled builds, we prefer abort() for debugging reasons.
- */
-#if defined(HAVE__BUILTIN_UNREACHABLE) && !defined(USE_ASSERT_CHECKING)
-#define pg_unreachable() __builtin_unreachable()
-#elif defined(_MSC_VER) && !defined(USE_ASSERT_CHECKING)
-#define pg_unreachable() __assume(0)
-#else
-#define pg_unreachable() abort()
-#endif
-
-
-/* ----------------------------------------------------------------
- * Section 8: random stuff
- * ----------------------------------------------------------------
- */
-
-/* msb for char */
-#define HIGHBIT (0x80)
-#define IS_HIGHBIT_SET(ch) ((unsigned char)(ch) & HIGHBIT)
-
-#define STATUS_OK (0)
-#define STATUS_ERROR (-1)
-#define STATUS_EOF (-2)
-#define STATUS_FOUND (1)
-#define STATUS_WAITING (2)
-
-
-/*
- * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only
- * used in assert-enabled builds, to avoid compiler warnings about unused
- * variables in assert-disabled builds.
- */
-#ifdef USE_ASSERT_CHECKING
-#define PG_USED_FOR_ASSERTS_ONLY
-#else
-#define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
-#endif
-
-
-/* gettext domain name mangling */
-
-/*
- * To better support parallel installations of major PostgreSQL
- * versions as well as parallel installations of major library soname
- * versions, we mangle the gettext domain name by appending those
- * version numbers. The coding rule ought to be that wherever the
- * domain name is mentioned as a literal, it must be wrapped into
- * PG_TEXTDOMAIN(). The macros below do not work on non-literals; but
- * that is somewhat intentional because it avoids having to worry
- * about multiple states of premangling and postmangling as the values
- * are being passed around.
- *
- * Make sure this matches the installation rules in nls-global.mk.
- */
-
-/* need a second indirection because we want to stringize the macro value, not the name */
-#define CppAsString2(x) CppAsString(x)
-
-#ifdef SO_MAJOR_VERSION
-#define PG_TEXTDOMAIN(domain) (domain CppAsString2(SO_MAJOR_VERSION) "-" PG_MAJORVERSION)
-#else
-#define PG_TEXTDOMAIN(domain) (domain "-" PG_MAJORVERSION)
-#endif
-
-
-/* ----------------------------------------------------------------
- * Section 9: system-specific hacks
- *
- * This should be limited to things that absolutely have to be
- * included in every source file. The port-specific header file
- * is usually a better place for this sort of thing.
- * ----------------------------------------------------------------
- */
-
-/*
- * NOTE: this is also used for opening text files.
- * WIN32 treats Control-Z as EOF in files opened in text mode.
- * Therefore, we open files in binary mode on Win32 so we can read
- * literal control-Z. The other affect is that we see CRLF, but
- * that is OK because we can already handle those cleanly.
- */
-#if defined(WIN32) || defined(__CYGWIN__)
-#define PG_BINARY O_BINARY
-#define PG_BINARY_A "ab"
-#define PG_BINARY_R "rb"
-#define PG_BINARY_W "wb"
-#else
-#define PG_BINARY 0
-#define PG_BINARY_A "a"
-#define PG_BINARY_R "r"
-#define PG_BINARY_W "w"
-#endif
-
-/*
- * Provide prototypes for routines not present in a particular machine's
- * standard C library.
- */
-
-#if !HAVE_DECL_SNPRINTF
-extern int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4);
-#endif
-
-#if !HAVE_DECL_VSNPRINTF
-extern int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
-#endif
-
-#if !defined(HAVE_MEMMOVE) && !defined(memmove)
-#define memmove(d, s, c) bcopy(s, d, c)
-#endif
-
-/* no special DLL markers on most ports */
-#ifndef PGDLLIMPORT
-#define PGDLLIMPORT
-#endif
-#ifndef PGDLLEXPORT
-#define PGDLLEXPORT
-#endif
-
-/*
- * The following is used as the arg list for signal handlers. Any ports
- * that take something other than an int argument should override this in
- * their pg_config_os.h file. Note that variable names are required
- * because it is used in both the prototypes as well as the definitions.
- * Note also the long name. We expect that this won't collide with
- * other names causing compiler warnings.
- */
-
-#ifndef SIGNAL_ARGS
-#define SIGNAL_ARGS int postgres_signal_arg
-#endif
-
-/*
- * When there is no sigsetjmp, its functionality is provided by plain
- * setjmp. Incidentally, nothing provides setjmp's functionality in
- * that case. We now support the case only on Windows.
- */
-#ifdef WIN32
-#define sigjmp_buf jmp_buf
-#define sigsetjmp(x,y) setjmp(x)
-#define siglongjmp longjmp
-#endif
-
-#if defined(HAVE_FDATASYNC) && !HAVE_DECL_FDATASYNC
-extern int fdatasync(int fildes);
-#endif
-
-/* If strtoq() exists, rename it to the more standard strtoll() */
-#if defined(HAVE_LONG_LONG_INT_64) && !defined(HAVE_STRTOLL) && defined(HAVE_STRTOQ)
-#define strtoll strtoq
-#define HAVE_STRTOLL 1
-#endif
-
-/* If strtouq() exists, rename it to the more standard strtoull() */
-#if defined(HAVE_LONG_LONG_INT_64) && !defined(HAVE_STRTOULL) && defined(HAVE_STRTOUQ)
-#define strtoull strtouq
-#define HAVE_STRTOULL 1
-#endif
-
-/*
- * We assume if we have these two functions, we have their friends too, and
- * can use the wide-character functions.
- */
-#if defined(HAVE_WCSTOMBS) && defined(HAVE_TOWLOWER)
-#define USE_WIDE_UPPER_LOWER
-#endif
-
-/* EXEC_BACKEND defines */
-#ifdef EXEC_BACKEND
-#define NON_EXEC_STATIC
-#else
-#define NON_EXEC_STATIC static
-#endif
-
-/* /port compatibility functions */
-#include "port.h"
-
-#endif /* C_H */
diff --git a/libpq/postgresql/common/fe_memutils.h b/libpq/postgresql/common/fe_memutils.h
deleted file mode 100644
index b4ce3d4..0000000
--- a/libpq/postgresql/common/fe_memutils.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * fe_memutils.h
- * memory management support for frontend code
- *
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
- *
- * src/include/common/fe_memutils.h
- */
-#ifndef FE_MEMUTILS_H
-#define FE_MEMUTILS_H
-
-/*
- * Flags for pg_malloc_extended and palloc_extended, deliberately named
- * the same as the backend flags.
- */
-#define MCXT_ALLOC_HUGE 0x01 /* allow huge allocation (> 1 GB) not
- * actually used for frontends */
-#define MCXT_ALLOC_NO_OOM 0x02 /* no failure if out-of-memory */
-#define MCXT_ALLOC_ZERO 0x04 /* zero allocated memory */
-
-/*
- * "Safe" memory allocation functions --- these exit(1) on failure
- * (except pg_malloc_extended with MCXT_ALLOC_NO_OOM)
- */
-extern char *pg_strdup(const char *in);
-extern void *pg_malloc(size_t size);
-extern void *pg_malloc0(size_t size);
-extern void *pg_malloc_extended(size_t size, int flags);
-extern void *pg_realloc(void *pointer, size_t size);
-extern void pg_free(void *pointer);
-
-/* Equivalent functions, deliberately named the same as backend functions */
-extern char *pstrdup(const char *in);
-extern void *palloc(Size size);
-extern void *palloc0(Size size);
-extern void *palloc_extended(Size size, int flags);
-extern void *repalloc(void *pointer, Size size);
-extern void pfree(void *pointer);
-
-/* sprintf into a palloc'd buffer --- these are in psprintf.c */
-extern char *psprintf(const char *fmt,...) pg_attribute_printf(1, 2);
-extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0);
-
-#endif /* FE_MEMUTILS_H */
diff --git a/libpq/postgresql/getaddrinfo.h b/libpq/postgresql/getaddrinfo.h
deleted file mode 100644
index 46aad59..0000000
--- a/libpq/postgresql/getaddrinfo.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * getaddrinfo.h
- * Support getaddrinfo() on platforms that don't have it.
- *
- * Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO,
- * whether or not the library routine getaddrinfo() can be found. This
- * policy is needed because on some platforms a manually installed libbind.a
- * may provide getaddrinfo(), yet the system headers may not provide the
- * struct definitions needed to call it. To avoid conflict with the libbind
- * definition in such cases, we rename our routines to pg_xxx() via macros.
- *
- * This code will also work on platforms where struct addrinfo is defined
- * in the system headers but no getaddrinfo() can be located.
- *
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
- *
- * src/include/getaddrinfo.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef GETADDRINFO_H
-#define GETADDRINFO_H
-
-#include <sys/socket.h>
-#include <netdb.h>
-
-
-/* Various macros that ought to be in <netdb.h>, but might not be */
-
-#ifndef EAI_FAIL
-#ifndef WIN32
-#define EAI_BADFLAGS (-1)
-#define EAI_NONAME (-2)
-#define EAI_AGAIN (-3)
-#define EAI_FAIL (-4)
-#define EAI_FAMILY (-6)
-#define EAI_SOCKTYPE (-7)
-#define EAI_SERVICE (-8)
-#define EAI_MEMORY (-10)
-#define EAI_SYSTEM (-11)
-#else /* WIN32 */
-#ifdef WIN32_ONLY_COMPILER
-#ifndef WSA_NOT_ENOUGH_MEMORY
-#define WSA_NOT_ENOUGH_MEMORY (WSAENOBUFS)
-#endif
-#ifndef __BORLANDC__
-#define WSATYPE_NOT_FOUND (WSABASEERR+109)
-#endif
-#endif
-#define EAI_AGAIN WSATRY_AGAIN
-#define EAI_BADFLAGS WSAEINVAL
-#define EAI_FAIL WSANO_RECOVERY
-#define EAI_FAMILY WSAEAFNOSUPPORT
-#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
-#define EAI_NODATA WSANO_DATA
-#define EAI_NONAME WSAHOST_NOT_FOUND
-#define EAI_SERVICE WSATYPE_NOT_FOUND
-#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
-#endif /* !WIN32 */
-#endif /* !EAI_FAIL */
-
-#ifndef AI_PASSIVE
-#define AI_PASSIVE 0x0001
-#endif
-
-#ifndef AI_NUMERICHOST
-/*
- * some platforms don't support AI_NUMERICHOST; define as zero if using
- * the system version of getaddrinfo...
- */
-#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
-#define AI_NUMERICHOST 0
-#else
-#define AI_NUMERICHOST 0x0004
-#endif
-#endif
-
-#ifndef NI_NUMERICHOST
-#define NI_NUMERICHOST 1
-#endif
-#ifndef NI_NUMERICSERV
-#define NI_NUMERICSERV 2
-#endif
-#ifndef NI_NAMEREQD
-#define NI_NAMEREQD 4
-#endif
-
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-#ifndef NI_MAXSERV
-#define NI_MAXSERV 32
-#endif
-
-
-#ifndef HAVE_STRUCT_ADDRINFO
-
-#ifndef WIN32
-struct addrinfo
-{
- int ai_flags;
- int ai_family;
- int ai_socktype;
- int ai_protocol;
- size_t ai_addrlen;
- struct sockaddr *ai_addr;
- char *ai_canonname;
- struct addrinfo *ai_next;
-};
-#else
-/*
- * The order of the structure elements on Win32 doesn't match the
- * order specified in the standard, but we have to match it for
- * IPv6 to work.
- */
-struct addrinfo
-{
- int ai_flags;
- int ai_family;
- int ai_socktype;
- int ai_protocol;
- size_t ai_addrlen;
- char *ai_canonname;
- struct sockaddr *ai_addr;
- struct addrinfo *ai_next;
-};
-#endif
-#endif /* HAVE_STRUCT_ADDRINFO */
-
-
-#ifndef HAVE_GETADDRINFO
-
-/* Rename private copies per comments above */
-#ifdef getaddrinfo
-#undef getaddrinfo
-#endif
-#define getaddrinfo pg_getaddrinfo
-
-#ifdef freeaddrinfo
-#undef freeaddrinfo
-#endif
-#define freeaddrinfo pg_freeaddrinfo
-
-#ifdef gai_strerror
-#undef gai_strerror
-#endif
-#define gai_strerror pg_gai_strerror
-
-#ifdef getnameinfo
-#undef getnameinfo
-#endif
-#define getnameinfo pg_getnameinfo
-
-extern int getaddrinfo(const char *node, const char *service,
- const struct addrinfo * hints, struct addrinfo ** res);
-extern void freeaddrinfo(struct addrinfo * res);
-extern const char *gai_strerror(int errcode);
-extern int getnameinfo(const struct sockaddr * sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen, int flags);
-#endif /* HAVE_GETADDRINFO */
-
-#endif /* GETADDRINFO_H */
diff --git a/libpq/postgresql/libpq/ip.h b/libpq/postgresql/libpq/ip.h
deleted file mode 100644
index ce9bc6e..0000000
--- a/libpq/postgresql/libpq/ip.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * ip.h
- * Definitions for IPv6-aware network access.
- *
- * These definitions are used by both frontend and backend code. Be careful
- * what you include here!
- *
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
- *
- * src/include/libpq/ip.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef IP_H
-#define IP_H
-
-#include "getaddrinfo.h" /* pgrminclude ignore */
-#include "libpq/pqcomm.h" /* pgrminclude ignore */
-
-
-#ifdef HAVE_UNIX_SOCKETS
-#define IS_AF_UNIX(fam) ((fam) == AF_UNIX)
-#else
-#define IS_AF_UNIX(fam) (0)
-#endif
-
-typedef void (*PgIfAddrCallback) (struct sockaddr * addr,
- struct sockaddr * netmask,
- void *cb_data);
-
-extern int pg_getaddrinfo_all(const char *hostname, const char *servname,
- const struct addrinfo * hintp,
- struct addrinfo ** result);
-extern void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai);
-
-extern int pg_getnameinfo_all(const struct sockaddr_storage * addr, int salen,
- char *node, int nodelen,
- char *service, int servicelen,
- int flags);
-
-extern int pg_range_sockaddr(const struct sockaddr_storage * addr,
- const struct sockaddr_storage * netaddr,
- const struct sockaddr_storage * netmask);
-
-extern int pg_sockaddr_cidr_mask(struct sockaddr_storage * mask,
- char *numbits, int family);
-
-extern int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data);
-
-#endif /* IP_H */
diff --git a/libpq/postgresql/libpq/libpq-fs.h b/libpq/postgresql/libpq/libpq-fs.h
deleted file mode 100644
index 5134ce6..0000000
--- a/libpq/postgresql/libpq/libpq-fs.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * libpq-fs.h
- * definitions for using Inversion file system routines (ie, large objects)
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/libpq/libpq-fs.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef LIBPQ_FS_H
-#define LIBPQ_FS_H
-
-/*
- * Read/write mode flags for inversion (large object) calls
- */
-
-#define INV_WRITE 0x00020000
-#define INV_READ 0x00040000
-
-#endif /* LIBPQ_FS_H */
diff --git a/libpq/postgresql/libpq/md5.h b/libpq/postgresql/libpq/md5.h
deleted file mode 100644
index f3eec8b..0000000
--- a/libpq/postgresql/libpq/md5.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * md5.h
- * Interface to libpq/md5.c
- *
- * These definitions are needed by both frontend and backend code to work
- * with MD5-encrypted passwords.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/libpq/md5.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PG_MD5_H
-#define PG_MD5_H
-
-#define MD5_PASSWD_LEN 35
-
-#define isMD5(passwd) (strncmp(passwd, "md5", 3) == 0 && \
- strlen(passwd) == MD5_PASSWD_LEN)
-
-
-extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum);
-extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf);
-extern bool pg_md5_encrypt(const char *passwd, const char *salt,
- size_t salt_len, char *buf);
-
-#endif
diff --git a/libpq/postgresql/libpq/pqcomm.h b/libpq/postgresql/libpq/pqcomm.h
deleted file mode 100644
index 1d063d1..0000000
--- a/libpq/postgresql/libpq/pqcomm.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pqcomm.h
- * Definitions common to frontends and backends.
- *
- * NOTE: for historical reasons, this does not correspond to pqcomm.c.
- * pqcomm.c's routines are declared in libpq.h.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/libpq/pqcomm.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PQCOMM_H
-#define PQCOMM_H
-
-#include <sys/socket.h>
-#include <netdb.h>
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-#include <netinet/in.h>
-
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE
-
-#ifndef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
-#define ss_family __ss_family
-#else
-#error struct sockaddr_storage does not provide an ss_family member
-#endif
-#endif
-
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN
-#define ss_len __ss_len
-#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1
-#endif
-#else /* !HAVE_STRUCT_SOCKADDR_STORAGE */
-
-/* Define a struct sockaddr_storage if we don't have one. */
-
-struct sockaddr_storage
-{
- union
- {
- struct sockaddr sa; /* get the system-dependent fields */
- int64 ss_align; /* ensures struct is properly aligned */
- char ss_pad[128]; /* ensures struct has desired size */
- } ss_stuff;
-};
-
-#define ss_family ss_stuff.sa.sa_family
-/* It should have an ss_len field if sockaddr has sa_len. */
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-#define ss_len ss_stuff.sa.sa_len
-#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1
-#endif
-#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
-
-typedef struct
-{
- struct sockaddr_storage addr;
- ACCEPT_TYPE_ARG3 salen;
-} SockAddr;
-
-/* Configure the UNIX socket location for the well known port. */
-
-#define UNIXSOCK_PATH(path, port, sockdir) \
- snprintf(path, sizeof(path), "%s/.s.PGSQL.%d", \
- ((sockdir) && *(sockdir) != '\0') ? (sockdir) : \
- DEFAULT_PGSOCKET_DIR, \
- (port))
-
-/*
- * The maximum workable length of a socket path is what will fit into
- * struct sockaddr_un. This is usually only 100 or so bytes :-(.
- *
- * For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(),
- * then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes.
- * (Because the standard API for getaddrinfo doesn't allow it to complain in
- * a useful way when the socket pathname is too long, we have to test for
- * this explicitly, instead of just letting the subroutine return an error.)
- */
-#define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path)
-
-
-/*
- * These manipulate the frontend/backend protocol version number.
- *
- * The major number should be incremented for incompatible changes. The minor
- * number should be incremented for compatible changes (eg. additional
- * functionality).
- *
- * If a backend supports version m.n of the protocol it must actually support
- * versions m.[0..n]. Backend support for version m-1 can be dropped after a
- * `reasonable' length of time.
- *
- * A frontend isn't required to support anything other than the current
- * version.
- */
-
-#define PG_PROTOCOL_MAJOR(v) ((v) >> 16)
-#define PG_PROTOCOL_MINOR(v) ((v) & 0x0000ffff)
-#define PG_PROTOCOL(m,n) (((m) << 16) | (n))
-
-/* The earliest and latest frontend/backend protocol version supported. */
-
-#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(1,0)
-#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,0)
-
-typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
-
-typedef ProtocolVersion MsgType;
-
-
-/*
- * Packet lengths are 4 bytes in network byte order.
- *
- * The initial length is omitted from the packet layouts appearing below.
- */
-
-typedef uint32 PacketLen;
-
-
-/*
- * Old-style startup packet layout with fixed-width fields. This is used in
- * protocol 1.0 and 2.0, but not in later versions. Note that the fields
- * in this layout are '\0' terminated only if there is room.
- */
-
-#define SM_DATABASE 64
-#define SM_USER 32
-/* We append database name if db_user_namespace true. */
-#define SM_DATABASE_USER (SM_DATABASE+SM_USER+1) /* +1 for @ */
-#define SM_OPTIONS 64
-#define SM_UNUSED 64
-#define SM_TTY 64
-
-typedef struct StartupPacket
-{
- ProtocolVersion protoVersion; /* Protocol version */
- char database[SM_DATABASE]; /* Database name */
- /* Db_user_namespace appends dbname */
- char user[SM_USER]; /* User name */
- char options[SM_OPTIONS]; /* Optional additional args */
- char unused[SM_UNUSED]; /* Unused */
- char tty[SM_TTY]; /* Tty for debug output */
-} StartupPacket;
-
-extern bool Db_user_namespace;
-
-/*
- * In protocol 3.0 and later, the startup packet length is not fixed, but
- * we set an arbitrary limit on it anyway. This is just to prevent simple
- * denial-of-service attacks via sending enough data to run the server
- * out of memory.
- */
-#define MAX_STARTUP_PACKET_LENGTH 10000
-
-
-/* These are the authentication request codes sent by the backend. */
-
-#define AUTH_REQ_OK 0 /* User is authenticated */
-#define AUTH_REQ_KRB4 1 /* Kerberos V4. Not supported any more. */
-#define AUTH_REQ_KRB5 2 /* Kerberos V5. Not supported any more. */
-#define AUTH_REQ_PASSWORD 3 /* Password */
-#define AUTH_REQ_CRYPT 4 /* crypt password. Not supported any more. */
-#define AUTH_REQ_MD5 5 /* md5 password */
-#define AUTH_REQ_SCM_CREDS 6 /* transfer SCM credentials */
-#define AUTH_REQ_GSS 7 /* GSSAPI without wrap() */
-#define AUTH_REQ_GSS_CONT 8 /* Continue GSS exchanges */
-#define AUTH_REQ_SSPI 9 /* SSPI negotiate without wrap() */
-#define AUTH_REQ_SASL 10 /* SASL authentication. Not supported before
- * libpq version 10. */
-
-typedef uint32 AuthRequest;
-
-
-/*
- * A client can also send a cancel-current-operation request to the postmaster.
- * This is uglier than sending it directly to the client's backend, but it
- * avoids depending on out-of-band communication facilities.
- *
- * The cancel request code must not match any protocol version number
- * we're ever likely to use. This random choice should do.
- */
-#define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678)
-
-typedef struct CancelRequestPacket
-{
- /* Note that each field is stored in network byte order! */
- MsgType cancelRequestCode; /* code to identify a cancel request */
- uint32 backendPID; /* PID of client's backend */
- uint32 cancelAuthCode; /* secret key to authorize cancel */
-} CancelRequestPacket;
-
-
-/*
- * A client can also start by sending a SSL negotiation request, to get a
- * secure channel.
- */
-#define NEGOTIATE_SSL_CODE PG_PROTOCOL(1234,5679)
-
-#endif /* PQCOMM_H */
diff --git a/libpq/postgresql/mb/pg_wchar.h b/libpq/postgresql/mb/pg_wchar.h
deleted file mode 100644
index 24e8d0d..0000000
--- a/libpq/postgresql/mb/pg_wchar.h
+++ /dev/null
@@ -1,561 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pg_wchar.h
- * multibyte-character support
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/mb/pg_wchar.h
- *
- * NOTES
- * This is used both by the backend and by libpq, but should not be
- * included by libpq client programs. In particular, a libpq client
- * should not assume that the encoding IDs used by the version of libpq
- * it's linked to match up with the IDs declared here.
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PG_WCHAR_H
-#define PG_WCHAR_H
-
-/*
- * The pg_wchar type
- */
-typedef unsigned int pg_wchar;
-
-/*
- * Maximum byte length of multibyte characters in any backend encoding
- */
-#define MAX_MULTIBYTE_CHAR_LEN 4
-
-/*
- * various definitions for EUC
- */
-#define SS2 0x8e /* single shift 2 (JIS0201) */
-#define SS3 0x8f /* single shift 3 (JIS0212) */
-
-/*
- * SJIS validation macros
- */
-#define ISSJISHEAD(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xfc))
-#define ISSJISTAIL(c) (((c) >= 0x40 && (c) <= 0x7e) || ((c) >= 0x80 && (c) <= 0xfc))
-
-/*----------------------------------------------------
- * MULE Internal Encoding (MIC)
- *
- * This encoding follows the design used within XEmacs; it is meant to
- * subsume many externally-defined character sets. Each character includes
- * identification of the character set it belongs to, so the encoding is
- * general but somewhat bulky.
- *
- * Currently PostgreSQL supports 5 types of MULE character sets:
- *
- * 1) 1-byte ASCII characters. Each byte is below 0x80.
- *
- * 2) "Official" single byte charsets such as ISO-8859-1 (Latin1).
- * Each MULE character consists of 2 bytes: LC1 + C1, where LC1 is
- * an identifier for the charset (in the range 0x81 to 0x8d) and C1
- * is the character code (in the range 0xa0 to 0xff).
- *
- * 3) "Private" single byte charsets such as SISHENG. Each MULE
- * character consists of 3 bytes: LCPRV1 + LC12 + C1, where LCPRV1
- * is a private-charset flag, LC12 is an identifier for the charset,
- * and C1 is the character code (in the range 0xa0 to 0xff).
- * LCPRV1 is either 0x9a (if LC12 is in the range 0xa0 to 0xdf)
- * or 0x9b (if LC12 is in the range 0xe0 to 0xef).
- *
- * 4) "Official" multibyte charsets such as JIS X0208. Each MULE
- * character consists of 3 bytes: LC2 + C1 + C2, where LC2 is
- * an identifier for the charset (in the range 0x90 to 0x99) and C1
- * and C2 form the character code (each in the range 0xa0 to 0xff).
- *
- * 5) "Private" multibyte charsets such as CNS 11643-1992 Plane 3.
- * Each MULE character consists of 4 bytes: LCPRV2 + LC22 + C1 + C2,
- * where LCPRV2 is a private-charset flag, LC22 is an identifier for
- * the charset, and C1 and C2 form the character code (each in the range
- * 0xa0 to 0xff). LCPRV2 is either 0x9c (if LC22 is in the range 0xf0
- * to 0xf4) or 0x9d (if LC22 is in the range 0xf5 to 0xfe).
- *
- * "Official" encodings are those that have been assigned code numbers by
- * the XEmacs project; "private" encodings have Postgres-specific charset
- * identifiers.
- *
- * See the "XEmacs Internals Manual", available at http://www.xemacs.org,
- * for more details. Note that for historical reasons, Postgres'
- * private-charset flag values do not match what XEmacs says they should be,
- * so this isn't really exactly MULE (not that private charsets would be
- * interoperable anyway).
- *
- * Note that XEmacs's implementation is different from what emacs does.
- * We follow emacs's implementation, rather than XEmacs's.
- *----------------------------------------------------
- */
-
-/*
- * Charset identifiers (also called "leading bytes" in the MULE documentation)
- */
-
-/*
- * Charset IDs for official single byte encodings (0x81-0x8e)
- */
-#define LC_ISO8859_1 0x81 /* ISO8859 Latin 1 */
-#define LC_ISO8859_2 0x82 /* ISO8859 Latin 2 */
-#define LC_ISO8859_3 0x83 /* ISO8859 Latin 3 */
-#define LC_ISO8859_4 0x84 /* ISO8859 Latin 4 */
-#define LC_TIS620 0x85 /* Thai (not supported yet) */
-#define LC_ISO8859_7 0x86 /* Greek (not supported yet) */
-#define LC_ISO8859_6 0x87 /* Arabic (not supported yet) */
-#define LC_ISO8859_8 0x88 /* Hebrew (not supported yet) */
-#define LC_JISX0201K 0x89 /* Japanese 1 byte kana */
-#define LC_JISX0201R 0x8a /* Japanese 1 byte Roman */
-/* Note that 0x8b seems to be unused as of Emacs 20.7.
- * However, there might be a chance that 0x8b could be used
- * in later versions of Emacs.
- */
-#define LC_KOI8_R 0x8b /* Cyrillic KOI8-R */
-#define LC_ISO8859_5 0x8c /* ISO8859 Cyrillic */
-#define LC_ISO8859_9 0x8d /* ISO8859 Latin 5 (not supported yet) */
-#define LC_ISO8859_15 0x8e /* ISO8859 Latin 15 (not supported yet) */
-/* #define CONTROL_1 0x8f control characters (unused) */
-
-/* Is a leading byte for "official" single byte encodings? */
-#define IS_LC1(c) ((unsigned char)(c) >= 0x81 && (unsigned char)(c) <= 0x8d)
-
-/*
- * Charset IDs for official multibyte encodings (0x90-0x99)
- * 0x9a-0x9d are free. 0x9e and 0x9f are reserved.
- */
-#define LC_JISX0208_1978 0x90 /* Japanese Kanji, old JIS (not supported) */
-#define LC_GB2312_80 0x91 /* Chinese */
-#define LC_JISX0208 0x92 /* Japanese Kanji (JIS X 0208) */
-#define LC_KS5601 0x93 /* Korean */
-#define LC_JISX0212 0x94 /* Japanese Kanji (JIS X 0212) */
-#define LC_CNS11643_1 0x95 /* CNS 11643-1992 Plane 1 */
-#define LC_CNS11643_2 0x96 /* CNS 11643-1992 Plane 2 */
-#define LC_JISX0213_1 0x97/* Japanese Kanji (JIS X 0213 Plane 1) (not
- * supported) */
-#define LC_BIG5_1 0x98 /* Plane 1 Chinese traditional (not supported) */
-#define LC_BIG5_2 0x99 /* Plane 1 Chinese traditional (not supported) */
-
-/* Is a leading byte for "official" multibyte encodings? */
-#define IS_LC2(c) ((unsigned char)(c) >= 0x90 && (unsigned char)(c) <= 0x99)
-
-/*
- * Postgres-specific prefix bytes for "private" single byte encodings
- * (According to the MULE docs, we should be using 0x9e for this)
- */
-#define LCPRV1_A 0x9a
-#define LCPRV1_B 0x9b
-#define IS_LCPRV1(c) ((unsigned char)(c) == LCPRV1_A || (unsigned char)(c) == LCPRV1_B)
-#define IS_LCPRV1_A_RANGE(c) \
- ((unsigned char)(c) >= 0xa0 && (unsigned char)(c) <= 0xdf)
-#define IS_LCPRV1_B_RANGE(c) \
- ((unsigned char)(c) >= 0xe0 && (unsigned char)(c) <= 0xef)
-
-/*
- * Postgres-specific prefix bytes for "private" multibyte encodings
- * (According to the MULE docs, we should be using 0x9f for this)
- */
-#define LCPRV2_A 0x9c
-#define LCPRV2_B 0x9d
-#define IS_LCPRV2(c) ((unsigned char)(c) == LCPRV2_A || (unsigned char)(c) == LCPRV2_B)
-#define IS_LCPRV2_A_RANGE(c) \
- ((unsigned char)(c) >= 0xf0 && (unsigned char)(c) <= 0xf4)
-#define IS_LCPRV2_B_RANGE(c) \
- ((unsigned char)(c) >= 0xf5 && (unsigned char)(c) <= 0xfe)
-
-/*
- * Charset IDs for private single byte encodings (0xa0-0xef)
- */
-#define LC_SISHENG 0xa0/* Chinese SiSheng characters for
- * PinYin/ZhuYin (not supported) */
-#define LC_IPA 0xa1/* IPA (International Phonetic Association)
- * (not supported) */
-#define LC_VISCII_LOWER 0xa2/* Vietnamese VISCII1.1 lower-case (not
- * supported) */
-#define LC_VISCII_UPPER 0xa3/* Vietnamese VISCII1.1 upper-case (not
- * supported) */
-#define LC_ARABIC_DIGIT 0xa4 /* Arabic digit (not supported) */
-#define LC_ARABIC_1_COLUMN 0xa5 /* Arabic 1-column (not supported) */
-#define LC_ASCII_RIGHT_TO_LEFT 0xa6 /* ASCII (left half of ISO8859-1) with
- * right-to-left direction (not
- * supported) */
-#define LC_LAO 0xa7/* Lao characters (ISO10646 0E80..0EDF) (not
- * supported) */
-#define LC_ARABIC_2_COLUMN 0xa8 /* Arabic 1-column (not supported) */
-
-/*
- * Charset IDs for private multibyte encodings (0xf0-0xff)
- */
-#define LC_INDIAN_1_COLUMN 0xf0/* Indian charset for 1-column width glyphs
- * (not supported) */
-#define LC_TIBETAN_1_COLUMN 0xf1/* Tibetan 1-column width glyphs (not
- * supported) */
-#define LC_UNICODE_SUBSET_2 0xf2/* Unicode characters of the range
- * U+2500..U+33FF. (not supported) */
-#define LC_UNICODE_SUBSET_3 0xf3/* Unicode characters of the range
- * U+E000..U+FFFF. (not supported) */
-#define LC_UNICODE_SUBSET 0xf4/* Unicode characters of the range
- * U+0100..U+24FF. (not supported) */
-#define LC_ETHIOPIC 0xf5 /* Ethiopic characters (not supported) */
-#define LC_CNS11643_3 0xf6 /* CNS 11643-1992 Plane 3 */
-#define LC_CNS11643_4 0xf7 /* CNS 11643-1992 Plane 4 */
-#define LC_CNS11643_5 0xf8 /* CNS 11643-1992 Plane 5 */
-#define LC_CNS11643_6 0xf9 /* CNS 11643-1992 Plane 6 */
-#define LC_CNS11643_7 0xfa /* CNS 11643-1992 Plane 7 */
-#define LC_INDIAN_2_COLUMN 0xfb/* Indian charset for 2-column width glyphs
- * (not supported) */
-#define LC_TIBETAN 0xfc /* Tibetan (not supported) */
-/* #define FREE 0xfd free (unused) */
-/* #define FREE 0xfe free (unused) */
-/* #define FREE 0xff free (unused) */
-
-/*----------------------------------------------------
- * end of MULE stuff
- *----------------------------------------------------
- */
-
-/*
- * PostgreSQL encoding identifiers
- *
- * WARNING: the order of this enum must be same as order of entries
- * in the pg_enc2name_tbl[] array (in mb/encnames.c), and
- * in the pg_wchar_table[] array (in mb/wchar.c)!
- *
- * If you add some encoding don't forget to check
- * PG_ENCODING_BE_LAST macro.
- *
- * PG_SQL_ASCII is default encoding and must be = 0.
- *
- * XXX We must avoid renumbering any backend encoding until libpq's major
- * version number is increased beyond 5; it turns out that the backend
- * encoding IDs are effectively part of libpq's ABI as far as 8.2 initdb and
- * psql are concerned.
- */
-typedef enum pg_enc
-{
- PG_SQL_ASCII = 0, /* SQL/ASCII */
- PG_EUC_JP, /* EUC for Japanese */
- PG_EUC_CN, /* EUC for Chinese */
- PG_EUC_KR, /* EUC for Korean */
- PG_EUC_TW, /* EUC for Taiwan */
- PG_EUC_JIS_2004, /* EUC-JIS-2004 */
- PG_UTF8, /* Unicode UTF8 */
- PG_MULE_INTERNAL, /* Mule internal code */
- PG_LATIN1, /* ISO-8859-1 Latin 1 */
- PG_LATIN2, /* ISO-8859-2 Latin 2 */
- PG_LATIN3, /* ISO-8859-3 Latin 3 */
- PG_LATIN4, /* ISO-8859-4 Latin 4 */
- PG_LATIN5, /* ISO-8859-9 Latin 5 */
- PG_LATIN6, /* ISO-8859-10 Latin6 */
- PG_LATIN7, /* ISO-8859-13 Latin7 */
- PG_LATIN8, /* ISO-8859-14 Latin8 */
- PG_LATIN9, /* ISO-8859-15 Latin9 */
- PG_LATIN10, /* ISO-8859-16 Latin10 */
- PG_WIN1256, /* windows-1256 */
- PG_WIN1258, /* Windows-1258 */
- PG_WIN866, /* (MS-DOS CP866) */
- PG_WIN874, /* windows-874 */
- PG_KOI8R, /* KOI8-R */
- PG_WIN1251, /* windows-1251 */
- PG_WIN1252, /* windows-1252 */
- PG_ISO_8859_5, /* ISO-8859-5 */
- PG_ISO_8859_6, /* ISO-8859-6 */
- PG_ISO_8859_7, /* ISO-8859-7 */
- PG_ISO_8859_8, /* ISO-8859-8 */
- PG_WIN1250, /* windows-1250 */
- PG_WIN1253, /* windows-1253 */
- PG_WIN1254, /* windows-1254 */
- PG_WIN1255, /* windows-1255 */
- PG_WIN1257, /* windows-1257 */
- PG_KOI8U, /* KOI8-U */
- /* PG_ENCODING_BE_LAST points to the above entry */
-
- /* followings are for client encoding only */
- PG_SJIS, /* Shift JIS (Windows-932) */
- PG_BIG5, /* Big5 (Windows-950) */
- PG_GBK, /* GBK (Windows-936) */
- PG_UHC, /* UHC (Windows-949) */
- PG_GB18030, /* GB18030 */
- PG_JOHAB, /* EUC for Korean JOHAB */
- PG_SHIFT_JIS_2004, /* Shift-JIS-2004 */
- _PG_LAST_ENCODING_ /* mark only */
-
-} pg_enc;
-
-#define PG_ENCODING_BE_LAST PG_KOI8U
-
-/*
- * Please use these tests before access to pg_encconv_tbl[]
- * or to other places...
- */
-#define PG_VALID_BE_ENCODING(_enc) \
- ((_enc) >= 0 && (_enc) <= PG_ENCODING_BE_LAST)
-
-#define PG_ENCODING_IS_CLIENT_ONLY(_enc) \
- ((_enc) > PG_ENCODING_BE_LAST && (_enc) < _PG_LAST_ENCODING_)
-
-#define PG_VALID_ENCODING(_enc) \
- ((_enc) >= 0 && (_enc) < _PG_LAST_ENCODING_)
-
-/* On FE are possible all encodings */
-#define PG_VALID_FE_ENCODING(_enc) PG_VALID_ENCODING(_enc)
-
-/*
- * Table for mapping an encoding number to official encoding name and
- * possibly other subsidiary data. Be careful to check encoding number
- * before accessing a table entry!
- *
- * if (PG_VALID_ENCODING(encoding))
- * pg_enc2name_tbl[ encoding ];
- */
-typedef struct pg_enc2name
-{
- const char *name;
- pg_enc encoding;
-#ifdef WIN32
- unsigned codepage; /* codepage for WIN32 */
-#endif
-} pg_enc2name;
-
-extern const pg_enc2name pg_enc2name_tbl[];
-
-/*
- * Encoding names for gettext
- */
-typedef struct pg_enc2gettext
-{
- pg_enc encoding;
- const char *name;
-} pg_enc2gettext;
-
-extern const pg_enc2gettext pg_enc2gettext_tbl[];
-
-/*
- * pg_wchar stuff
- */
-typedef int (*mb2wchar_with_len_converter) (const unsigned char *from,
- pg_wchar *to,
- int len);
-
-typedef int (*wchar2mb_with_len_converter) (const pg_wchar *from,
- unsigned char *to,
- int len);
-
-typedef int (*mblen_converter) (const unsigned char *mbstr);
-
-typedef int (*mbdisplaylen_converter) (const unsigned char *mbstr);
-
-typedef bool (*mbcharacter_incrementer) (unsigned char *mbstr, int len);
-
-typedef int (*mbverifier) (const unsigned char *mbstr, int len);
-
-typedef struct
-{
- mb2wchar_with_len_converter mb2wchar_with_len; /* convert a multibyte
- * string to a wchar */
- wchar2mb_with_len_converter wchar2mb_with_len; /* convert a wchar
- * string to a multibyte */
- mblen_converter mblen; /* get byte length of a char */
- mbdisplaylen_converter dsplen; /* get display width of a char */
- mbverifier mbverify; /* verify multibyte sequence */
- int maxmblen; /* max bytes for a char in this encoding */
-} pg_wchar_tbl;
-
-extern const pg_wchar_tbl pg_wchar_table[];
-
-/*
- * Data structures for conversions between UTF-8 and other encodings
- * (UtfToLocal() and LocalToUtf()). In these data structures, characters of
- * either encoding are represented by uint32 words; hence we can only support
- * characters up to 4 bytes long. For example, the byte sequence 0xC2 0x89
- * would be represented by 0x0000C289, and 0xE8 0xA2 0xB4 by 0x00E8A2B4.
- *
- * Maps are arrays of these structs, which must be in order by the lookup key
- * (so that bsearch() can be used).
- *
- * UTF-8 to local code conversion map
- */
-typedef struct
-{
- uint32 utf; /* UTF-8 */
- uint32 code; /* local code */
-} pg_utf_to_local;
-
-/*
- * local code to UTF-8 conversion map
- */
-typedef struct
-{
- uint32 code; /* local code */
- uint32 utf; /* UTF-8 */
-} pg_local_to_utf;
-
-/*
- * UTF-8 to local code conversion map (for combined characters)
- */
-typedef struct
-{
- uint32 utf1; /* UTF-8 code 1 */
- uint32 utf2; /* UTF-8 code 2 */
- uint32 code; /* local code */
-} pg_utf_to_local_combined;
-
-/*
- * local code to UTF-8 conversion map (for combined characters)
- */
-typedef struct
-{
- uint32 code; /* local code */
- uint32 utf1; /* UTF-8 code 1 */
- uint32 utf2; /* UTF-8 code 2 */
-} pg_local_to_utf_combined;
-
-/*
- * callback function for algorithmic encoding conversions (in either direction)
- *
- * if function returns zero, it does not know how to convert the code
- */
-typedef uint32 (*utf_local_conversion_func) (uint32 code);
-
-/*
- * Support macro for encoding conversion functions to validate their
- * arguments. (This could be made more compact if we included fmgr.h
- * here, but we don't want to do that because this header file is also
- * used by frontends.)
- */
-#define CHECK_ENCODING_CONVERSION_ARGS(srcencoding,destencoding) \
- check_encoding_conversion_args(PG_GETARG_INT32(0), \
- PG_GETARG_INT32(1), \
- PG_GETARG_INT32(4), \
- (srcencoding), \
- (destencoding))
-
-
-/*
- * These functions are considered part of libpq's exported API and
- * are also declared in libpq-fe.h.
- */
-extern int pg_char_to_encoding(const char *name);
-extern const char *pg_encoding_to_char(int encoding);
-extern int pg_valid_server_encoding_id(int encoding);
-
-/*
- * Remaining functions are not considered part of libpq's API, though many
- * of them do exist inside libpq.
- */
-extern int pg_mb2wchar(const char *from, pg_wchar *to);
-extern int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len);
-extern int pg_encoding_mb2wchar_with_len(int encoding,
- const char *from, pg_wchar *to, int len);
-extern int pg_wchar2mb(const pg_wchar *from, char *to);
-extern int pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len);
-extern int pg_encoding_wchar2mb_with_len(int encoding,
- const pg_wchar *from, char *to, int len);
-extern int pg_char_and_wchar_strcmp(const char *s1, const pg_wchar *s2);
-extern int pg_wchar_strncmp(const pg_wchar *s1, const pg_wchar *s2, size_t n);
-extern int pg_char_and_wchar_strncmp(const char *s1, const pg_wchar *s2, size_t n);
-extern size_t pg_wchar_strlen(const pg_wchar *wstr);
-extern int pg_mblen(const char *mbstr);
-extern int pg_dsplen(const char *mbstr);
-extern int pg_encoding_mblen(int encoding, const char *mbstr);
-extern int pg_encoding_dsplen(int encoding, const char *mbstr);
-extern int pg_encoding_verifymb(int encoding, const char *mbstr, int len);
-extern int pg_mule_mblen(const unsigned char *mbstr);
-extern int pg_mic_mblen(const unsigned char *mbstr);
-extern int pg_mbstrlen(const char *mbstr);
-extern int pg_mbstrlen_with_len(const char *mbstr, int len);
-extern int pg_mbcliplen(const char *mbstr, int len, int limit);
-extern int pg_encoding_mbcliplen(int encoding, const char *mbstr,
- int len, int limit);
-extern int pg_mbcharcliplen(const char *mbstr, int len, int imit);
-extern int pg_encoding_max_length(int encoding);
-extern int pg_database_encoding_max_length(void);
-extern mbcharacter_incrementer pg_database_encoding_character_incrementer(void);
-
-extern int PrepareClientEncoding(int encoding);
-extern int SetClientEncoding(int encoding);
-extern void InitializeClientEncoding(void);
-extern int pg_get_client_encoding(void);
-extern const char *pg_get_client_encoding_name(void);
-
-extern void SetDatabaseEncoding(int encoding);
-extern int GetDatabaseEncoding(void);
-extern const char *GetDatabaseEncodingName(void);
-extern void SetMessageEncoding(int encoding);
-extern int GetMessageEncoding(void);
-
-#ifdef ENABLE_NLS
-extern int pg_bind_textdomain_codeset(const char *domainname);
-#endif
-
-extern int pg_valid_client_encoding(const char *name);
-extern int pg_valid_server_encoding(const char *name);
-
-extern unsigned char *unicode_to_utf8(pg_wchar c, unsigned char *utf8string);
-extern pg_wchar utf8_to_unicode(const unsigned char *c);
-extern int pg_utf_mblen(const unsigned char *);
-extern unsigned char *pg_do_encoding_conversion(unsigned char *src, int len,
- int src_encoding,
- int dest_encoding);
-
-extern char *pg_client_to_server(const char *s, int len);
-extern char *pg_server_to_client(const char *s, int len);
-extern char *pg_any_to_server(const char *s, int len, int encoding);
-extern char *pg_server_to_any(const char *s, int len, int encoding);
-
-extern unsigned short BIG5toCNS(unsigned short big5, unsigned char *lc);
-extern unsigned short CNStoBIG5(unsigned short cns, unsigned char lc);
-
-extern void UtfToLocal(const unsigned char *utf, int len,
- unsigned char *iso,
- const pg_utf_to_local *map, int mapsize,
- const pg_utf_to_local_combined *cmap, int cmapsize,
- utf_local_conversion_func conv_func,
- int encoding);
-extern void LocalToUtf(const unsigned char *iso, int len,
- unsigned char *utf,
- const pg_local_to_utf *map, int mapsize,
- const pg_local_to_utf_combined *cmap, int cmapsize,
- utf_local_conversion_func conv_func,
- int encoding);
-
-extern bool pg_verifymbstr(const char *mbstr, int len, bool noError);
-extern bool pg_verify_mbstr(int encoding, const char *mbstr, int len,
- bool noError);
-extern int pg_verify_mbstr_len(int encoding, const char *mbstr, int len,
- bool noError);
-
-extern void check_encoding_conversion_args(int src_encoding,
- int dest_encoding,
- int len,
- int expected_src_encoding,
- int expected_dest_encoding);
-
-extern void report_invalid_encoding(int encoding, const char *mbstr, int len) pg_attribute_noreturn();
-extern void report_untranslatable_char(int src_encoding, int dest_encoding,
- const char *mbstr, int len) pg_attribute_noreturn();
-
-extern void local2local(const unsigned char *l, unsigned char *p, int len,
- int src_encoding, int dest_encoding, const unsigned char *tab);
-extern void pg_ascii2mic(const unsigned char *l, unsigned char *p, int len);
-extern void pg_mic2ascii(const unsigned char *mic, unsigned char *p, int len);
-extern void latin2mic(const unsigned char *l, unsigned char *p, int len,
- int lc, int encoding);
-extern void mic2latin(const unsigned char *mic, unsigned char *p, int len,
- int lc, int encoding);
-extern void latin2mic_with_table(const unsigned char *l, unsigned char *p,
- int len, int lc, int encoding,
- const unsigned char *tab);
-extern void mic2latin_with_table(const unsigned char *mic, unsigned char *p,
- int len, int lc, int encoding,
- const unsigned char *tab);
-
-extern bool pg_utf8_islegal(const unsigned char *source, int length);
-
-#ifdef WIN32
-extern WCHAR *pgwin32_message_to_UTF16(const char *str, int len, int *utf16len);
-#endif
-
-#endif /* PG_WCHAR_H */
diff --git a/libpq/postgresql/pg_config.h.in.orig b/libpq/postgresql/pg_config.h.in.orig
deleted file mode 100644
index 7dbfa90..0000000
--- a/libpq/postgresql/pg_config.h.in.orig
+++ /dev/null
@@ -1,931 +0,0 @@
-/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */
-
-/* Define to the type of arg 1 of 'accept' */
-#undef ACCEPT_TYPE_ARG1
-
-/* Define to the type of arg 2 of 'accept' */
-#undef ACCEPT_TYPE_ARG2
-
-/* Define to the type of arg 3 of 'accept' */
-#undef ACCEPT_TYPE_ARG3
-
-/* Define to the return type of 'accept' */
-#undef ACCEPT_TYPE_RETURN
-
-/* Define if building universal (internal helper macro) */
-#undef AC_APPLE_UNIVERSAL_BUILD
-
-/* The normal alignment of `double', in bytes. */
-#undef ALIGNOF_DOUBLE
-
-/* The normal alignment of `int', in bytes. */
-#undef ALIGNOF_INT
-
-/* The normal alignment of `long', in bytes. */
-#undef ALIGNOF_LONG
-
-/* The normal alignment of `long long int', in bytes. */
-#undef ALIGNOF_LONG_LONG_INT
-
-/* The normal alignment of `short', in bytes. */
-#undef ALIGNOF_SHORT
-
-/* Size of a disk block --- this also limits the size of a tuple. You can set
- it bigger if you need bigger tuples (although TOAST should reduce the need
- to have large tuples, since fields can be spread across multiple tuples).
- BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
- currently 2^15 (32768). This is determined by the 15-bit widths of the
- lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
- Changing BLCKSZ requires an initdb. */
-#undef BLCKSZ
-
-/* Define to the default TCP port number on which the server listens and to
- which clients will try to connect. This can be overridden at run-time, but
- it's convenient if your clients have the right default compiled in.
- (--with-pgport=PORTNUM) */
-#undef DEF_PGPORT
-
-/* Define to the default TCP port number as a string constant. */
-#undef DEF_PGPORT_STR
-
-/* Define to build with GSSAPI support. (--with-gssapi) */
-#undef ENABLE_GSS
-
-/* Define to 1 if you want National Language Support. (--enable-nls) */
-#undef ENABLE_NLS
-
-/* Define to 1 to build client libraries as thread-safe code.
- (--enable-thread-safety) */
-#undef ENABLE_THREAD_SAFETY
-
-/* Define to nothing if C supports flexible array members, and to 1 if it does
- not. That way, with a declaration like `struct s { int n; double
- d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99
- compilers. When computing the size of such an object, don't use 'sizeof
- (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)'
- instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with
- MSVC and with C++ compilers. */
-#undef FLEXIBLE_ARRAY_MEMBER
-
-/* float4 values are passed by value if 'true', by reference if 'false' */
-#undef FLOAT4PASSBYVAL
-
-/* float8, int8, and related values are passed by value if 'true', by
- reference if 'false' */
-#undef FLOAT8PASSBYVAL
-
-/* Define to 1 if gettimeofday() takes only 1 argument. */
-#undef GETTIMEOFDAY_1ARG
-
-#ifdef GETTIMEOFDAY_1ARG
-# define gettimeofday(a,b) gettimeofday(a)
-#endif
-
-/* Define to 1 if you have the `append_history' function. */
-#undef HAVE_APPEND_HISTORY
-
-/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
-#undef HAVE_ASN1_STRING_GET0_DATA
-
-/* Define to 1 if you want to use atomics if available. */
-#undef HAVE_ATOMICS
-
-/* Define to 1 if you have the <atomic.h> header file. */
-#undef HAVE_ATOMIC_H
-
-/* Define to 1 if you have the `BIO_get_data' function. */
-#undef HAVE_BIO_GET_DATA
-
-/* Define to 1 if you have the `BIO_meth_new' function. */
-#undef HAVE_BIO_METH_NEW
-
-/* Define to 1 if you have the `cbrt' function. */
-#undef HAVE_CBRT
-
-/* Define to 1 if you have the `class' function. */
-#undef HAVE_CLASS
-
-/* Define to 1 if you have the <crtdefs.h> header file. */
-#undef HAVE_CRTDEFS_H
-
-/* Define to 1 if you have the `crypt' function. */
-#undef HAVE_CRYPT
-
-/* Define to 1 if you have the `CRYPTO_lock' function. */
-#undef HAVE_CRYPTO_LOCK
-
-/* Define to 1 if you have the <crypt.h> header file. */
-#undef HAVE_CRYPT_H
-
-/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
- don't. */
-#undef HAVE_DECL_FDATASYNC
-
-/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you
- don't. */
-#undef HAVE_DECL_F_FULLFSYNC
-
-/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you
- don't. */
-#undef HAVE_DECL_POSIX_FADVISE
-
-/* Define to 1 if you have the declaration of `snprintf', and to 0 if you
- don't. */
-#undef HAVE_DECL_SNPRINTF
-
-/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
- don't. */
-#undef HAVE_DECL_STRLCAT
-
-/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
- don't. */
-#undef HAVE_DECL_STRLCPY
-
-/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
- don't. */
-#undef HAVE_DECL_SYS_SIGLIST
-
-/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you
- don't. */
-#undef HAVE_DECL_VSNPRINTF
-
-/* Define to 1 if you have the <dld.h> header file. */
-#undef HAVE_DLD_H
-
-/* Define to 1 if you have the `dlopen' function. */
-#undef HAVE_DLOPEN
-
-/* Define to 1 if you have the <editline/history.h> header file. */
-#undef HAVE_EDITLINE_HISTORY_H
-
-/* Define to 1 if you have the <editline/readline.h> header file. */
-#undef HAVE_EDITLINE_READLINE_H
-
-/* Define to 1 if you have the `fdatasync' function. */
-#undef HAVE_FDATASYNC
-
-/* Define to 1 if you have the `fls' function. */
-#undef HAVE_FLS
-
-/* Define to 1 if you have the `fpclass' function. */
-#undef HAVE_FPCLASS
-
-/* Define to 1 if you have the `fp_class' function. */
-#undef HAVE_FP_CLASS
-
-/* Define to 1 if you have the `fp_class_d' function. */
-#undef HAVE_FP_CLASS_D
-
-/* Define to 1 if you have the <fp_class.h> header file. */
-#undef HAVE_FP_CLASS_H
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-#undef HAVE_FSEEKO
-
-/* Define to 1 if your compiler understands __func__. */
-#undef HAVE_FUNCNAME__FUNC
-
-/* Define to 1 if your compiler understands __FUNCTION__. */
-#undef HAVE_FUNCNAME__FUNCTION
-
-/* Define to 1 if you have __atomic_compare_exchange_n(int *, int *, int). */
-#undef HAVE_GCC__ATOMIC_INT32_CAS
-
-/* Define to 1 if you have __atomic_compare_exchange_n(int64 *, int *, int64).
- */
-#undef HAVE_GCC__ATOMIC_INT64_CAS
-
-/* Define to 1 if you have __sync_lock_test_and_set(char *) and friends. */
-#undef HAVE_GCC__SYNC_CHAR_TAS
-
-/* Define to 1 if you have __sync_compare_and_swap(int *, int, int). */
-#undef HAVE_GCC__SYNC_INT32_CAS
-
-/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */
-#undef HAVE_GCC__SYNC_INT32_TAS
-
-/* Define to 1 if you have __sync_compare_and_swap(int64 *, int64, int64). */
-#undef HAVE_GCC__SYNC_INT64_CAS
-
-/* Define to 1 if you have the `getaddrinfo' function. */
-#undef HAVE_GETADDRINFO
-
-/* Define to 1 if you have the `gethostbyname_r' function. */
-#undef HAVE_GETHOSTBYNAME_R
-
-/* Define to 1 if you have the `getifaddrs' function. */
-#undef HAVE_GETIFADDRS
-
-/* Define to 1 if you have the `getopt' function. */
-#undef HAVE_GETOPT
-
-/* Define to 1 if you have the <getopt.h> header file. */
-#undef HAVE_GETOPT_H
-
-/* Define to 1 if you have the `getopt_long' function. */
-#undef HAVE_GETOPT_LONG
-
-/* Define to 1 if you have the `getpeereid' function. */
-#undef HAVE_GETPEEREID
-
-/* Define to 1 if you have the `getpeerucred' function. */
-#undef HAVE_GETPEERUCRED
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#undef HAVE_GETPWUID_R
-
-/* Define to 1 if you have the `getrlimit' function. */
-#undef HAVE_GETRLIMIT
-
-/* Define to 1 if you have the `getrusage' function. */
-#undef HAVE_GETRUSAGE
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
-#undef HAVE_GSSAPI_GSSAPI_H
-
-/* Define to 1 if you have the <gssapi.h> header file. */
-#undef HAVE_GSSAPI_H
-
-/* Define to 1 if you have the <history.h> header file. */
-#undef HAVE_HISTORY_H
-
-/* Define to 1 if you have the `history_truncate_file' function. */
-#undef HAVE_HISTORY_TRUNCATE_FILE
-
-/* Define to 1 if you have the <ieeefp.h> header file. */
-#undef HAVE_IEEEFP_H
-
-/* Define to 1 if you have the <ifaddrs.h> header file. */
-#undef HAVE_IFADDRS_H
-
-/* Define to 1 if you have the `inet_aton' function. */
-#undef HAVE_INET_ATON
-
-/* Define to 1 if the system has the type `int64'. */
-#undef HAVE_INT64
-
-/* Define to 1 if the system has the type `int8'. */
-#undef HAVE_INT8
-
-/* Define to 1 if the system has the type `intptr_t'. */
-#undef HAVE_INTPTR_T
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the global variable 'int opterr'. */
-#undef HAVE_INT_OPTERR
-
-/* Define to 1 if you have the global variable 'int optreset'. */
-#undef HAVE_INT_OPTRESET
-
-/* Define to 1 if you have the global variable 'int timezone'. */
-#undef HAVE_INT_TIMEZONE
-
-/* Define to 1 if you have support for IPv6. */
-#undef HAVE_IPV6
-
-/* Define to 1 if you have isinf(). */
-#undef HAVE_ISINF
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#undef HAVE_LANGINFO_H
-
-/* Define to 1 if you have the <ldap.h> header file. */
-#undef HAVE_LDAP_H
-
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
-#undef HAVE_LIBCRYPTO
-
-/* Define to 1 if you have the `ldap' library (-lldap). */
-#undef HAVE_LIBLDAP
-
-/* Define to 1 if you have the `ldap_r' library (-lldap_r). */
-#undef HAVE_LIBLDAP_R
-
-/* Define to 1 if you have the `m' library (-lm). */
-#undef HAVE_LIBM
-
-/* Define to 1 if you have the `pam' library (-lpam). */
-#undef HAVE_LIBPAM
-
-/* Define if you have a function readline library */
-#undef HAVE_LIBREADLINE
-
-/* Define to 1 if you have the `selinux' library (-lselinux). */
-#undef HAVE_LIBSELINUX
-
-/* Define to 1 if you have the `ssl' library (-lssl). */
-#undef HAVE_LIBSSL
-
-/* Define to 1 if you have the `wldap32' library (-lwldap32). */
-#undef HAVE_LIBWLDAP32
-
-/* Define to 1 if you have the `xml2' library (-lxml2). */
-#undef HAVE_LIBXML2
-
-/* Define to 1 if you have the `xslt' library (-lxslt). */
-#undef HAVE_LIBXSLT
-
-/* Define to 1 if you have the `z' library (-lz). */
-#undef HAVE_LIBZ
-
-/* Define to 1 if constants of type 'long long int' should have the suffix LL.
- */
-#undef HAVE_LL_CONSTANTS
-
-/* Define to 1 if the system has the type `locale_t'. */
-#undef HAVE_LOCALE_T
-
-/* Define to 1 if `long int' works and is 64 bits. */
-#undef HAVE_LONG_INT_64
-
-/* Define to 1 if the system has the type `long long int'. */
-#undef HAVE_LONG_LONG_INT
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#undef HAVE_LONG_LONG_INT_64
-
-/* Define to 1 if you have the <mbarrier.h> header file. */
-#undef HAVE_MBARRIER_H
-
-/* Define to 1 if you have the `mbstowcs_l' function. */
-#undef HAVE_MBSTOWCS_L
-
-/* Define to 1 if you have the `memmove' function. */
-#undef HAVE_MEMMOVE
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */
-#undef HAVE_MINIDUMP_TYPE
-
-/* Define to 1 if you have the `mkdtemp' function. */
-#undef HAVE_MKDTEMP
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#undef HAVE_NETINET_IN_H
-
-/* Define to 1 if you have the <netinet/tcp.h> header file. */
-#undef HAVE_NETINET_TCP_H
-
-/* Define to 1 if you have the <net/if.h> header file. */
-#undef HAVE_NET_IF_H
-
-/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
-#undef HAVE_OPENSSL_INIT_SSL
-
-/* Define to 1 if you have the <ossp/uuid.h> header file. */
-#undef HAVE_OSSP_UUID_H
-
-/* Define to 1 if you have the <pam/pam_appl.h> header file. */
-#undef HAVE_PAM_PAM_APPL_H
-
-/* Define to 1 if you have the `poll' function. */
-#undef HAVE_POLL
-
-/* Define to 1 if you have the <poll.h> header file. */
-#undef HAVE_POLL_H
-
-/* Define to 1 if you have the `posix_fadvise' function. */
-#undef HAVE_POSIX_FADVISE
-
-/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */
-#undef HAVE_PPC_LWARX_MUTEX_HINT
-
-/* Define to 1 if you have the `pstat' function. */
-#undef HAVE_PSTAT
-
-/* Define to 1 if the PS_STRINGS thing exists. */
-#undef HAVE_PS_STRINGS
-
-/* Define if you have POSIX threads libraries and header files. */
-#undef HAVE_PTHREAD
-
-/* Define to 1 if you have the `pthread_is_threaded_np' function. */
-#undef HAVE_PTHREAD_IS_THREADED_NP
-
-/* Have PTHREAD_PRIO_INHERIT. */
-#undef HAVE_PTHREAD_PRIO_INHERIT
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#undef HAVE_PWD_H
-
-/* Define to 1 if you have the `random' function. */
-#undef HAVE_RANDOM
-
-/* Define to 1 if you have the `RAND_OpenSSL' function. */
-#undef HAVE_RAND_OPENSSL
-
-/* Define to 1 if you have the <readline.h> header file. */
-#undef HAVE_READLINE_H
-
-/* Define to 1 if you have the <readline/history.h> header file. */
-#undef HAVE_READLINE_HISTORY_H
-
-/* Define to 1 if you have the <readline/readline.h> header file. */
-#undef HAVE_READLINE_READLINE_H
-
-/* Define to 1 if you have the `readlink' function. */
-#undef HAVE_READLINK
-
-/* Define to 1 if you have the `rint' function. */
-#undef HAVE_RINT
-
-/* Define to 1 if you have the global variable
- 'rl_completion_append_character'. */
-#undef HAVE_RL_COMPLETION_APPEND_CHARACTER
-
-/* Define to 1 if you have the `rl_completion_matches' function. */
-#undef HAVE_RL_COMPLETION_MATCHES
-
-/* Define to 1 if you have the `rl_filename_completion_function' function. */
-#undef HAVE_RL_FILENAME_COMPLETION_FUNCTION
-
-/* Define to 1 if you have the `rl_reset_screen_size' function. */
-#undef HAVE_RL_RESET_SCREEN_SIZE
-
-/* Define to 1 if you have the <security/pam_appl.h> header file. */
-#undef HAVE_SECURITY_PAM_APPL_H
-
-/* Define to 1 if you have the `setproctitle' function. */
-#undef HAVE_SETPROCTITLE
-
-/* Define to 1 if you have the `setsid' function. */
-#undef HAVE_SETSID
-
-/* Define to 1 if you have the `shm_open' function. */
-#undef HAVE_SHM_OPEN
-
-/* Define to 1 if you have the `snprintf' function. */
-#undef HAVE_SNPRINTF
-
-/* Define to 1 if you have spinlocks. */
-#undef HAVE_SPINLOCKS
-
-/* Define to 1 if you have the `srandom' function. */
-#undef HAVE_SRANDOM
-
-/* Define to 1 if you have the `SSL_get_current_compression' function. */
-#undef HAVE_SSL_GET_CURRENT_COMPRESSION
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
-/* Define to 1 if you have the `strerror_r' function. */
-#undef HAVE_STRERROR_R
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strlcat' function. */
-#undef HAVE_STRLCAT
-
-/* Define to 1 if you have the `strlcpy' function. */
-#undef HAVE_STRLCPY
-
-/* Define to 1 if you have the `strtoll' function. */
-#undef HAVE_STRTOLL
-
-/* Define to 1 if you have the `strtoq' function. */
-#undef HAVE_STRTOQ
-
-/* Define to 1 if you have the `strtoull' function. */
-#undef HAVE_STRTOULL
-
-/* Define to 1 if you have the `strtouq' function. */
-#undef HAVE_STRTOUQ
-
-/* Define to 1 if the system has the type `struct addrinfo'. */
-#undef HAVE_STRUCT_ADDRINFO
-
-/* Define to 1 if the system has the type `struct cmsgcred'. */
-#undef HAVE_STRUCT_CMSGCRED
-
-/* Define to 1 if the system has the type `struct option'. */
-#undef HAVE_STRUCT_OPTION
-
-/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
-#undef HAVE_STRUCT_SOCKADDR_SA_LEN
-
-/* Define to 1 if the system has the type `struct sockaddr_storage'. */
-#undef HAVE_STRUCT_SOCKADDR_STORAGE
-
-/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
-#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
-
-/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */
-#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
-
-/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
-#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
-
-/* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */
-#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN
-
-/* Define to 1 if `tm_zone' is a member of `struct tm'. */
-#undef HAVE_STRUCT_TM_TM_ZONE
-
-/* Define to 1 if you have the `symlink' function. */
-#undef HAVE_SYMLINK
-
-/* Define to 1 if you have the `sync_file_range' function. */
-#undef HAVE_SYNC_FILE_RANGE
-
-/* Define to 1 if you have the syslog interface. */
-#undef HAVE_SYSLOG
-
-/* Define to 1 if you have the <sys/epoll.h> header file. */
-#undef HAVE_SYS_EPOLL_H
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#undef HAVE_SYS_IOCTL_H
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-#undef HAVE_SYS_IPC_H
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#undef HAVE_SYS_POLL_H
-
-/* Define to 1 if you have the <sys/pstat.h> header file. */
-#undef HAVE_SYS_PSTAT_H
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#undef HAVE_SYS_SELECT_H
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-#undef HAVE_SYS_SEM_H
-
-/* Define to 1 if you have the <sys/shm.h> header file. */
-#undef HAVE_SYS_SHM_H
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-#undef HAVE_SYS_SOCKIO_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/tas.h> header file. */
-#undef HAVE_SYS_TAS_H
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#undef HAVE_SYS_TIME_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/ucred.h> header file. */
-#undef HAVE_SYS_UCRED_H
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-#undef HAVE_SYS_UN_H
-
-/* Define to 1 if you have the <termios.h> header file. */
-#undef HAVE_TERMIOS_H
-
-/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
- `HAVE_STRUCT_TM_TM_ZONE' instead. */
-#undef HAVE_TM_ZONE
-
-/* Define to 1 if you have the `towlower' function. */
-#undef HAVE_TOWLOWER
-
-/* Define to 1 if you have the external array `tzname'. */
-#undef HAVE_TZNAME
-
-/* Define to 1 if you have the <ucred.h> header file. */
-#undef HAVE_UCRED_H
-
-/* Define to 1 if the system has the type `uint64'. */
-#undef HAVE_UINT64
-
-/* Define to 1 if the system has the type `uint8'. */
-#undef HAVE_UINT8
-
-/* Define to 1 if the system has the type `uintptr_t'. */
-#undef HAVE_UINTPTR_T
-
-/* Define to 1 if the system has the type `union semun'. */
-#undef HAVE_UNION_SEMUN
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have unix sockets. */
-#undef HAVE_UNIX_SOCKETS
-
-/* Define to 1 if you have the `unsetenv' function. */
-#undef HAVE_UNSETENV
-
-/* Define to 1 if the system has the type `unsigned long long int'. */
-#undef HAVE_UNSIGNED_LONG_LONG_INT
-
-/* Define to 1 if you have the `utime' function. */
-#undef HAVE_UTIME
-
-/* Define to 1 if you have the `utimes' function. */
-#undef HAVE_UTIMES
-
-/* Define to 1 if you have the <utime.h> header file. */
-#undef HAVE_UTIME_H
-
-/* Define to 1 if you have BSD UUID support. */
-#undef HAVE_UUID_BSD
-
-/* Define to 1 if you have E2FS UUID support. */
-#undef HAVE_UUID_E2FS
-
-/* Define to 1 if you have the <uuid.h> header file. */
-#undef HAVE_UUID_H
-
-/* Define to 1 if you have OSSP UUID support. */
-#undef HAVE_UUID_OSSP
-
-/* Define to 1 if you have the <uuid/uuid.h> header file. */
-#undef HAVE_UUID_UUID_H
-
-/* Define to 1 if you have the `vsnprintf' function. */
-#undef HAVE_VSNPRINTF
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#undef HAVE_WCHAR_H
-
-/* Define to 1 if you have the `wcstombs' function. */
-#undef HAVE_WCSTOMBS
-
-/* Define to 1 if you have the `wcstombs_l' function. */
-#undef HAVE_WCSTOMBS_L
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#undef HAVE_WCTYPE_H
-
-/* Define to 1 if you have the <winldap.h> header file. */
-#undef HAVE_WINLDAP_H
-
-/* Define to 1 if your compiler understands __builtin_bswap32. */
-#undef HAVE__BUILTIN_BSWAP32
-
-/* Define to 1 if your compiler understands __builtin_bswap64. */
-#undef HAVE__BUILTIN_BSWAP64
-
-/* Define to 1 if your compiler understands __builtin_constant_p. */
-#undef HAVE__BUILTIN_CONSTANT_P
-
-/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
-#undef HAVE__BUILTIN_TYPES_COMPATIBLE_P
-
-/* Define to 1 if your compiler understands __builtin_unreachable. */
-#undef HAVE__BUILTIN_UNREACHABLE
-
-/* Define to 1 if you have __cpuid. */
-#undef HAVE__CPUID
-
-/* Define to 1 if you have __get_cpuid. */
-#undef HAVE__GET_CPUID
-
-/* Define to 1 if your compiler understands _Static_assert. */
-#undef HAVE__STATIC_ASSERT
-
-/* Define to 1 if your compiler understands __VA_ARGS__ in macros. */
-#undef HAVE__VA_ARGS
-
-/* Define to the appropriate snprintf length modifier for 64-bit ints. */
-#undef INT64_MODIFIER
-
-/* Define to 1 if `locale_t' requires <xlocale.h>. */
-#undef LOCALE_T_IN_XLOCALE
-
-/* Define as the maximum alignment requirement of any C data type. */
-#undef MAXIMUM_ALIGNOF
-
-/* Define bytes to use libc memset(). */
-#undef MEMSET_LOOP_LIMIT
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define to the name of a signed 128-bit integer type. */
-#undef PG_INT128_TYPE
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
-
-/* Define to the name of the default PostgreSQL service principal in Kerberos
- (GSSAPI). (--with-krb-srvnam=NAME) */
-#undef PG_KRB_SRVNAM
-
-/* PostgreSQL major version as a string */
-#undef PG_MAJORVERSION
-
-/* Define to gnu_printf if compiler supports it, else printf. */
-#undef PG_PRINTF_ATTRIBUTE
-
-/* PostgreSQL version as a string */
-#undef PG_VERSION
-
-/* PostgreSQL version as a number */
-#undef PG_VERSION_NUM
-
-/* A string containing the version number, platform, and C compiler */
-#undef PG_VERSION_STR
-
-/* Define to 1 to allow profiling output to be saved separately for each
- process. */
-#undef PROFILE_PID_DIR
-
-/* Define to necessary symbol if this constant uses a non-standard name on
- your system. */
-#undef PTHREAD_CREATE_JOINABLE
-
-/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus,
- the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger
- than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be
- less than your OS' limit on file size. This is often 2 GB or 4GB in a
- 32-bit operating system, unless you have large file support enabled. By
- default, we make the limit 1 GB to avoid any possible integer-overflow
- problems within the OS. A limit smaller than necessary only means we divide
- a large relation into more chunks than necessary, so it seems best to err
- in the direction of a small limit. A power-of-2 value is recommended to
- save a few cycles in md.c, but is not absolutely required. Changing
- RELSEG_SIZE requires an initdb. */
-#undef RELSEG_SIZE
-
-/* The size of `long', as computed by sizeof. */
-#undef SIZEOF_LONG
-
-/* The size of `off_t', as computed by sizeof. */
-#undef SIZEOF_OFF_T
-
-/* The size of `size_t', as computed by sizeof. */
-#undef SIZEOF_SIZE_T
-
-/* The size of `void *', as computed by sizeof. */
-#undef SIZEOF_VOID_P
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Define to 1 if strerror_r() returns a int. */
-#undef STRERROR_R_INT
-
-/* Define to 1 if your <sys/time.h> declares `struct tm'. */
-#undef TM_IN_SYS_TIME
-
-/* Define to 1 to build with assertion checks. (--enable-cassert) */
-#undef USE_ASSERT_CHECKING
-
-/* Define to 1 to build with Bonjour support. (--with-bonjour) */
-#undef USE_BONJOUR
-
-/* Define to 1 to build with BSD Authentication support. (--with-bsd-auth) */
-#undef USE_BSD_AUTH
-
-/* Define to 1 if you want float4 values to be passed by value.
- (--enable-float4-byval) */
-#undef USE_FLOAT4_BYVAL
-
-/* Define to 1 if you want float8, int8, etc values to be passed by value.
- (--enable-float8-byval) */
-#undef USE_FLOAT8_BYVAL
-
-/* Define to 1 if you want 64-bit integer timestamp and interval support.
- (--enable-integer-datetimes) */
-#undef USE_INTEGER_DATETIMES
-
-/* Define to 1 to build with LDAP support. (--with-ldap) */
-#undef USE_LDAP
-
-/* Define to 1 to build with XML support. (--with-libxml) */
-#undef USE_LIBXML
-
-/* Define to 1 to use XSLT support when building contrib/xml2.
- (--with-libxslt) */
-#undef USE_LIBXSLT
-
-/* Define to select named POSIX semaphores. */
-#undef USE_NAMED_POSIX_SEMAPHORES
-
-/* Define to build with OpenSSL support. (--with-openssl) */
-#undef USE_OPENSSL
-
-/* Define to 1 to build with PAM support. (--with-pam) */
-#undef USE_PAM
-
-/* Use replacement snprintf() functions. */
-#undef USE_REPL_SNPRINTF
-
-/* Define to 1 to use Intel SSE 4.2 CRC instructions with a runtime check. */
-#undef USE_SLICING_BY_8_CRC32C
-
-/* Define to 1 use Intel SSE 4.2 CRC instructions. */
-#undef USE_SSE42_CRC32C
-
-/* Define to 1 to use Intel SSSE 4.2 CRC instructions with a runtime check. */
-#undef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
-
-/* Define to build with systemd support. (--with-systemd) */
-#undef USE_SYSTEMD
-
-/* Define to select SysV-style semaphores. */
-#undef USE_SYSV_SEMAPHORES
-
-/* Define to select SysV-style shared memory. */
-#undef USE_SYSV_SHARED_MEMORY
-
-/* Define to select unnamed POSIX semaphores. */
-#undef USE_UNNAMED_POSIX_SEMAPHORES
-
-/* Define to select Win32-style semaphores. */
-#undef USE_WIN32_SEMAPHORES
-
-/* Define to select Win32-style shared memory. */
-#undef USE_WIN32_SHARED_MEMORY
-
-/* Define to 1 if `wcstombs_l' requires <xlocale.h>. */
-#undef WCSTOMBS_L_IN_XLOCALE
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
- significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-# define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-# undef WORDS_BIGENDIAN
-# endif
-#endif
-
-/* Size of a WAL file block. This need have no particular relation to BLCKSZ.
- XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O,
- XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O
- buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb.
- */
-#undef XLOG_BLCKSZ
-
-/* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2
- and larger than XLOG_BLCKSZ (preferably, a great deal larger than
- XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */
-#undef XLOG_SEG_SIZE
-
-
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-#undef _LARGEFILE_SOURCE
-
-/* Define for large files, on AIX-style hosts. */
-#undef _LARGE_FILES
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#undef inline
-#endif
-
-/* Define to the type of a signed integer type wide enough to hold a pointer,
- if such a type exists, and if the system does not define it. */
-#undef intptr_t
-
-/* Define to empty if the C compiler does not understand signed types. */
-#undef signed
-
-/* Define to the type of an unsigned integer type wide enough to hold a
- pointer, if such a type exists, and if the system does not define it. */
-#undef uintptr_t
diff --git a/libpq/postgresql/pg_config.h.win32.orig b/libpq/postgresql/pg_config.h.win32.orig
deleted file mode 100644
index 0e17ccb..0000000
--- a/libpq/postgresql/pg_config.h.win32.orig
+++ /dev/null
@@ -1,682 +0,0 @@
-/* src/include/pg_config.h. Generated by configure. */
-/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */
-
-/* This file is generated from MingW ./configure, and with the following
- * changes to be valid for Visual C++ (and compatible):
- *
- * HAVE_CBRT, HAVE_FUNCNAME_FUNC, HAVE_GETOPT, HAVE_GETOPT_H, HAVE_INTTYPES_H,
- * HAVE_GETOPT_LONG, HAVE_LOCALE_T, HAVE_RINT, HAVE_STRINGS_H, HAVE_STRTOLL,
- * HAVE_STRTOULL, HAVE_STRUCT_OPTION, ENABLE_THREAD_SAFETY,
- * inline, USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
- */
-
-/* Define to the type of arg 1 of 'accept' */
-#define ACCEPT_TYPE_ARG1 unsigned int
-
-/* Define to the type of arg 2 of 'accept' */
-#define ACCEPT_TYPE_ARG2 struct sockaddr *
-
-/* Define to the type of arg 3 of 'accept' */
-#define ACCEPT_TYPE_ARG3 int
-
-/* Define to the return type of 'accept' */
-#define ACCEPT_TYPE_RETURN unsigned int PASCAL
-
-/* The alignment requirement of a `double'. */
-#define ALIGNOF_DOUBLE 8
-
-/* The alignment requirement of a `int'. */
-#define ALIGNOF_INT 4
-
-/* The alignment requirement of a `long'. */
-#define ALIGNOF_LONG 4
-
-/* The alignment requirement of a `long long int'. */
-#define ALIGNOF_LONG_LONG_INT 8
-
-/* The alignment requirement of a `short'. */
-#define ALIGNOF_SHORT 2
-
-/* Define to the default TCP port number on which the server listens and to
- which clients will try to connect. This can be overridden at run-time, but
- it's convenient if your clients have the right default compiled in.
- (--with-pgport=PORTNUM) */
-#define DEF_PGPORT 5432
-
-/* Define to the default TCP port number as a string constant. */
-#define DEF_PGPORT_STR "5432"
-
-/* Define to nothing if C supports flexible array members, and to 1 if it does
- not. That way, with a declaration like `struct s { int n; double
- d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99
- compilers. When computing the size of such an object, don't use 'sizeof
- (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)'
- instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with
- MSVC and with C++ compilers. */
-#define FLEXIBLE_ARRAY_MEMBER
-
-/* Define to 1 if you want National Language Support. (--enable-nls) */
-/* #undef ENABLE_NLS */
-
-/* Define to 1 to build client libraries as thread-safe code.
- (--enable-thread-safety) */
-#define ENABLE_THREAD_SAFETY 1
-
-/* Define to 1 if gettimeofday() takes only 1 argument. */
-/* #undef GETTIMEOFDAY_1ARG */
-
-#ifdef GETTIMEOFDAY_1ARG
-# define gettimeofday(a,b) gettimeofday(a)
-#endif
-
-/* Define to 1 if you have the `cbrt' function. */
-//#define HAVE_CBRT 1
-
-/* Define to 1 if you have the `class' function. */
-/* #undef HAVE_CLASS */
-
-/* Define to 1 if you have the `crypt' function. */
-/* #undef HAVE_CRYPT */
-
-/* Define to 1 if you have the <crypt.h> header file. */
-/* #undef HAVE_CRYPT_H */
-
-/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
- don't. */
-#define HAVE_DECL_FDATASYNC 0
-
-/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you
- don't. */
-#define HAVE_DECL_F_FULLFSYNC 0
-
-/* Define to 1 if you have the declaration of `snprintf', and to 0 if you
- don't. */
-#define HAVE_DECL_SNPRINTF 1
-
-/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you
- don't. */
-#define HAVE_DECL_VSNPRINTF 1
-
-/* Define to 1 if you have the <dld.h> header file. */
-/* #undef HAVE_DLD_H */
-
-/* Define to 1 if you have the `dlopen' function. */
-/* #undef HAVE_DLOPEN */
-
-/* Define to 1 if you have the <editline/history.h> header file. */
-/* #undef HAVE_EDITLINE_HISTORY_H */
-
-/* Define to 1 if you have the <editline/readline.h> header file. */
-/* #undef HAVE_EDITLINE_READLINE_H */
-
-/* Define to 1 if you have the `fcvt' function. */
-#define HAVE_FCVT 1
-
-/* Define to 1 if you have the `fdatasync' function. */
-/* #undef HAVE_FDATASYNC */
-
-/* Define to 1 if you have finite(). */
-#define HAVE_FINITE 1
-
-/* Define to 1 if you have the `fpclass' function. */
-/* #undef HAVE_FPCLASS */
-
-/* Define to 1 if you have the `fp_class' function. */
-/* #undef HAVE_FP_CLASS */
-
-/* Define to 1 if you have the `fp_class_d' function. */
-/* #undef HAVE_FP_CLASS_D */
-
-/* Define to 1 if you have the <fp_class.h> header file. */
-/* #undef HAVE_FP_CLASS_H */
-
-/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
-#define HAVE_FSEEKO 1
-
-/* Define to 1 if your compiler understands __func__. */
-//#define HAVE_FUNCNAME__FUNC 1
-
-/* Define to 1 if your compiler understands __FUNCTION__. */
-#define HAVE_FUNCNAME__FUNCTION 1
-
-/* Define to 1 if you have getaddrinfo(). */
-/* #undef HAVE_GETADDRINFO */
-
-/* Define to 1 if you have the `gethostbyname_r' function. */
-/* #undef HAVE_GETHOSTBYNAME_R */
-
-/* Define to 1 if you have the `getopt' function. */
-//#define HAVE_GETOPT 1
-
-/* Define to 1 if you have the <getopt.h> header file. */
-//#define HAVE_GETOPT_H 1
-
-/* Define to 1 if you have the `getopt_long' function. */
-//#define HAVE_GETOPT_LONG 1
-
-/* Define to 1 if you have the `getpeereid' function. */
-/* #undef HAVE_GETPEEREID */
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-/* #undef HAVE_GETPWUID_R */
-
-/* Define to 1 if you have the `getrusage' function. */
-/* #undef HAVE_GETRUSAGE */
-
-/* Define to 1 if you have the <history.h> header file. */
-/* #undef HAVE_HISTORY_H */
-
-/* Define to 1 if you have the <ieeefp.h> header file. */
-/* #undef HAVE_IEEEFP_H */
-
-/* Define to 1 if you have the `inet_aton' function. */
-/* #undef HAVE_INET_ATON */
-
-/* Define to 1 if the system has the type `int64'. */
-/* #undef HAVE_INT64 */
-
-/* Define to 1 if the system has the type `int8'. */
-/* #undef HAVE_INT8 */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-//#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the global variable 'int timezone'. */
-#define HAVE_INT_TIMEZONE 1
-
-/* Define to 1 if you have support for IPv6. */
-#define HAVE_IPV6 1
-
-/* Define to 1 if you have isinf(). */
-#define HAVE_ISINF 1
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-/* #undef HAVE_LANGINFO_H */
-
-/* Define to 1 if you have the <ldap.h> header file. */
-/* #undef HAVE_LDAP_H */
-
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
-/* #undef HAVE_LIBCRYPTO */
-
-/* Define to 1 if you have the `ldap' library (-lldap). */
-/* #undef HAVE_LIBLDAP */
-
-/* Define to 1 if you have the `pam' library (-lpam). */
-/* #undef HAVE_LIBPAM */
-
-/* Define if you have a function readline library */
-/* #undef HAVE_LIBREADLINE */
-
-/* Define to 1 if you have the `ssl' library (-lssl). */
-/* #undef HAVE_LIBSSL */
-
-/* Define to 1 if you have the `wldap32' library (-lwldap32). */
-/* #undef HAVE_LIBWLDAP32 */
-
-/* Define to 1 if you have the `z' library (-lz). */
-/* #undef HAVE_LIBZ */
-
-/* Define to 1 if constants of type 'long long int' should have the suffix LL.
- */
-#if (_MSC_VER > 1200)
-#define HAVE_LL_CONSTANTS 1
-#endif
-
-/* Define to 1 if the system has the type `locale_t'. */
-#define HAVE_LOCALE_T 1
-
-/* Define to 1 if `long int' works and is 64 bits. */
-/* #undef HAVE_LONG_INT_64 */
-
-/* Define to 1 if `long long int' works and is 64 bits. */
-#if (_MSC_VER > 1200)
-#define HAVE_LONG_LONG_INT_64
-#endif
-
-/* Define to 1 if you have the `mbstowcs_l' function. */
-#define HAVE_MBSTOWCS_L 1
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */
-#define HAVE_MINIDUMP_TYPE 1
-
-/* Define to 1 if you have the `mkdtemp' function. */
-/* #undef HAVE_MKDTEMP */
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the <netinet/tcp.h> header file. */
-/* #undef HAVE_NETINET_TCP_H */
-
-/* Define to 1 if you have the <pam/pam_appl.h> header file. */
-/* #undef HAVE_PAM_PAM_APPL_H */
-
-/* Define to 1 if you have the `poll' function. */
-/* #undef HAVE_POLL */
-
-/* Define to 1 if you have the <poll.h> header file. */
-/* #undef HAVE_POLL_H */
-
-/* Define to 1 if you have the `pstat' function. */
-/* #undef HAVE_PSTAT */
-
-/* Define to 1 if the PS_STRINGS thing exists. */
-/* #undef HAVE_PS_STRINGS */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `random' function. */
-/* #undef HAVE_RANDOM */
-
-/* Define to 1 if you have the <readline.h> header file. */
-/* #undef HAVE_READLINE_H */
-
-/* Define to 1 if you have the <readline/history.h> header file. */
-/* #undef HAVE_READLINE_HISTORY_H */
-
-/* Define to 1 if you have the <readline/readline.h> header file. */
-/* #undef HAVE_READLINE_READLINE_H */
-
-/* Define to 1 if you have the `readlink' function. */
-/* #undef HAVE_READLINK */
-
-/* Define to 1 if you have the `rint' function. */
-#if (_MSC_VER >= 1800)
-#define HAVE_RINT 1
-#endif
-
-
-/* Define to 1 if you have the global variable
- 'rl_completion_append_character'. */
-/* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */
-
-/* Define to 1 if you have the `rl_completion_matches' function. */
-/* #undef HAVE_RL_COMPLETION_MATCHES */
-
-/* Define to 1 if you have the `rl_filename_completion_function' function. */
-/* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */
-
-/* Define to 1 if you have the <security/pam_appl.h> header file. */
-/* #undef HAVE_SECURITY_PAM_APPL_H */
-
-/* Define to 1 if you have the `setproctitle' function. */
-/* #undef HAVE_SETPROCTITLE */
-
-/* Define to 1 if you have the `setsid' function. */
-/* #undef HAVE_SETSID */
-
-/* Define to 1 if you have the `snprintf' function. */
-/* #undef HAVE_SNPRINTF */
-
-/* Define to 1 if you have spinlocks. */
-#define HAVE_SPINLOCKS 1
-
-/* Define to 1 if you have atomics. */
-#define HAVE_ATOMICS 1
-
-/* Define to 1 if you have the `srandom' function. */
-/* #undef HAVE_SRANDOM */
-
-/* Define to 1 if you have the `SSL_get_current_compression' function. */
-#define HAVE_SSL_GET_CURRENT_COMPRESSION 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-/* #undef HAVE_STDINT_H */
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strerror' function. */
-#ifndef HAVE_STRERROR
-#define HAVE_STRERROR 1
-#endif
-
-/* Define to 1 if you have the `strerror_r' function. */
-/* #undef HAVE_STRERROR_R */
-
-/* Define to 1 if you have the <strings.h> header file. */
-/*#define HAVE_STRINGS_H 1 */
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strtoll' function. */
-//#define HAVE_STRTOLL 1
-
-/* Define to 1 if you have the `strtoq' function. */
-/* #undef HAVE_STRTOQ */
-
-/* Define to 1 if you have the `strtoull' function. */
-//#define HAVE_STRTOULL 1
-
-/* Define to 1 if you have the `strtouq' function. */
-/* #undef HAVE_STRTOUQ */
-
-/* Define to 1 if the system has the type `struct addrinfo'. */
-#if (_MSC_VER > 1200)
-#define HAVE_STRUCT_ADDRINFO 1
-#endif
-
-/* Define to 1 if the system has the type `struct cmsgcred'. */
-/* #undef HAVE_STRUCT_CMSGCRED */
-
-/* Define to 1 if the system has the type `struct option'. */
-//#define HAVE_STRUCT_OPTION 1
-
-/* Define to 1 if `sa_len' is member of `struct sockaddr'. */
-/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */
-
-/* Define to 1 if the system has the type `struct sockaddr_storage'. */
-#if (_MSC_VER > 1200)
-#define HAVE_STRUCT_SOCKADDR_STORAGE 1
-#endif
-
-/* Define to 1 if `ss_family' is member of `struct sockaddr_storage'. */
-#if (_MSC_VER > 1200)
-#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
-#endif
-
-/* Define to 1 if `ss_len' is member of `struct sockaddr_storage'. */
-/* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */
-
-/* Define to 1 if `__ss_family' is member of `struct sockaddr_storage'. */
-/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */
-
-/* Define to 1 if `__ss_len' is member of `struct sockaddr_storage'. */
-/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */
-
-/* Define to 1 if the system has the type `struct sockaddr_un'. */
-/* #undef HAVE_STRUCT_SOCKADDR_UN */
-
-/* Define to 1 if `tm_zone' is member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM_TM_ZONE */
-
-/* Define to 1 if you have the `symlink' function. */
-#define HAVE_SYMLINK 1
-
-/* Define to 1 if you have the `sync_file_range' function. */
-/* #undef HAVE_SYNC_FILE_RANGE */
-
-/* Define to 1 if you have the `sysconf' function. */
-/* #undef HAVE_SYSCONF */
-
-/* Define to 1 if you have the syslog interface. */
-/* #undef HAVE_SYSLOG */
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-/* #undef HAVE_SYS_IPC_H */
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-/* #undef HAVE_SYS_POLL_H */
-
-/* Define to 1 if you have the <sys/pstat.h> header file. */
-/* #undef HAVE_SYS_PSTAT_H */
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-/* #undef HAVE_SYS_SELECT_H */
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-/* #undef HAVE_SYS_SEM_H */
-
-/* Define to 1 if you have the <sys/shm.h> header file. */
-/* #undef HAVE_SYS_SHM_H */
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucred.h> header file. */
-/* #undef HAVE_SYS_UCRED_H */
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-/* #undef HAVE_SYS_UN_H */
-
-/* Define to 1 if you have the <termios.h> header file. */
-/* #undef HAVE_TERMIOS_H */
-
-/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
- `HAVE_STRUCT_TM_TM_ZONE' instead. */
-/* #undef HAVE_TM_ZONE */
-
-/* Define to 1 if you have the `towlower' function. */
-#define HAVE_TOWLOWER 1
-
-/* Define to 1 if you have the external array `tzname'. */
-/* #undef HAVE_TZNAME */
-
-/* Define to 1 if the system has the type `uint64'. */
-/* #undef HAVE_UINT64 */
-
-/* Define to 1 if the system has the type `uint8'. */
-/* #undef HAVE_UINT8 */
-
-/* Define to 1 if the system has the type `union semun'. */
-/* #undef HAVE_UNION_SEMUN */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have unix sockets. */
-/* #undef HAVE_UNIX_SOCKETS */
-
-/* Define to 1 if you have the `unsetenv' function. */
-/* #undef HAVE_UNSETENV */
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimes' function. */
-/* #undef HAVE_UTIMES */
-
-/* Define to 1 if you have the <utime.h> header file. */
-#define HAVE_UTIME_H 1
-
-/* Define to 1 if you have the `vsnprintf' function. */
-#define HAVE_VSNPRINTF 1
-
-/* Define to 1 if you have the <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define to 1 if you have the `wcstombs' function. */
-#define HAVE_WCSTOMBS 1
-
-/* Define to 1 if you have the `wcstombs_l' function. */
-#define HAVE_WCSTOMBS_L 1
-
-/* Define to 1 if you have the <wctype.h> header file. */
-#define HAVE_WCTYPE_H 1
-
-/* Define to 1 if you have the <winldap.h> header file. */
-/* #undef HAVE_WINLDAP_H */
-
-/* Define to 1 if your compiler understands __builtin_bswap32. */
-/* #undef HAVE__BUILTIN_BSWAP32 */
-
-/* Define to 1 if your compiler understands __builtin_bswap64. */
-/* #undef HAVE__BUILTIN_BSWAP64 */
-
-/* Define to 1 if your compiler understands __builtin_constant_p. */
-/* #undef HAVE__BUILTIN_CONSTANT_P */
-
-/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
-/* #undef HAVE__BUILTIN_TYPES_COMPATIBLE_P */
-
-/* Define to 1 if your compiler understands __builtin_unreachable. */
-/* #undef HAVE__BUILTIN_UNREACHABLE */
-
-/* Define to 1 if you have __cpuid. */
-#define HAVE__CPUID 1
-
-/* Define to 1 if you have __get_cpuid. */
-#undef HAVE__GET_CPUID
-
-/* Define to 1 if your compiler understands _Static_assert. */
-/* #undef HAVE__STATIC_ASSERT */
-
-/* Define to 1 if your compiler understands __VA_ARGS__ in macros. */
-#define HAVE__VA_ARGS 1
-
-/* Define to the appropriate snprintf length modifier for 64-bit ints. */
-#define INT64_MODIFIER "ll"
-
-/* Define to 1 if `locale_t' requires <xlocale.h>. */
-/* #undef LOCALE_T_IN_XLOCALE */
-
-/* Define to the location of locale files. */
-/* #undef LOCALEDIR */
-
-/* Define as the maximum alignment requirement of any C data type. */
-#define MAXIMUM_ALIGNOF 8
-
-/* Define bytes to use libc memset(). */
-#define MEMSET_LOOP_LIMIT 1024
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "PostgreSQL"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PostgreSQL 9.6.5"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "9.6.5"
-
-/* Define to the name of a signed 128-bit integer type. */
-#undef PG_INT128_TYPE
-
-/* Define to the name of a signed 64-bit integer type. */
-#define PG_INT64_TYPE long long int
-
-/* PostgreSQL version as a string */
-#define PG_VERSION "9.6.5"
-
-/* PostgreSQL version as a number */
-#define PG_VERSION_NUM 90605
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "postgresql"
-
-/* Define to the name of the default PostgreSQL service principal in Kerberos.
- (--with-krb-srvnam=NAME) */
-#define PG_KRB_SRVNAM "postgres"
-
-/* A string containing the version number, platform, and C compiler */
-#define PG_VERSION_STR "Uninitialized version string (win32)"
-
-/* The size of `long', as computed by sizeof. */
-#define SIZEOF_LONG 4
-
-/* The size of `size_t', as computed by sizeof. */
-#ifndef _WIN64
-#define SIZEOF_SIZE_T 4
-#else
-#define SIZEOF_SIZE_T 8
-#endif
-
-/* The size of `void *', as computed by sizeof. */
-#ifndef _WIN64
-#define SIZEOF_VOID_P 4
-#else
-#define SIZEOF_VOID_P 8
-#endif
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if strerror_r() returns a int. */
-/* #undef STRERROR_R_INT */
-
-/* Define to 1 if your <sys/time.h> declares `struct tm'. */
-/* #undef TM_IN_SYS_TIME */
-
-/* Define to 1 to build with assertion checks. (--enable-cassert) */
-/* #undef USE_ASSERT_CHECKING */
-
-/* Define to 1 to build with Bonjour support. (--with-bonjour) */
-/* #undef USE_BONJOUR */
-
-/* Define to 1 to build with BSD Authentication support. (--with-bsd-auth) */
-/* #undef USE_BSD_AUTH */
-
-/* Define to 1 if you want 64-bit integer timestamp and interval support.
- (--enable-integer-datetimes) */
-/* #undef USE_INTEGER_DATETIMES */
-
-/* Define to 1 to build with LDAP support. (--with-ldap) */
-/* #undef USE_LDAP */
-
-/* Define to select named POSIX semaphores. */
-/* #undef USE_NAMED_POSIX_SEMAPHORES */
-
-/* Define to build with OpenSSL support. (--with-openssl) */
-/* #undef USE_OPENSSL */
-
-/* Define to 1 to build with PAM support. (--with-pam) */
-/* #undef USE_PAM */
-
-/* Use replacement snprintf() functions. */
-#define USE_REPL_SNPRINTF 1
-
-/* Define to 1 to use Intel SSE 4.2 CRC instructions with a runtime check. */
-#if (_MSC_VER < 1500)
-#define USE_SLICING_BY_8_CRC32C 1
-#endif
-
-/* Define to 1 use Intel SSE 4.2 CRC instructions. */
-/* #undef USE_SSE42_CRC32C */
-
-/* Define to 1 to use Intel SSSE 4.2 CRC instructions with a runtime check. */
-#if (_MSC_VER >= 1500)
-#define USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
-#endif
-
-/* Define to select SysV-style semaphores. */
-/* #undef USE_SYSV_SEMAPHORES */
-
-/* Define to select SysV-style shared memory. */
-#define USE_SYSV_SHARED_MEMORY 1
-
-/* Define to select unnamed POSIX semaphores. */
-/* #undef USE_UNNAMED_POSIX_SEMAPHORES */
-
-/* Define to select Win32-style semaphores. */
-#define USE_WIN32_SEMAPHORES 1
-
-/* Define to 1 if `wcstombs_l' requires <xlocale.h>. */
-/* #undef WCSTOMBS_L_IN_XLOCALE */
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
-/* #undef _LARGEFILE_SOURCE */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#define inline __inline
-#endif
-
-/* Define to empty if the C compiler does not understand signed types. */
-/* #undef signed */
diff --git a/libpq/postgresql/pg_config_ext.h.in.orig b/libpq/postgresql/pg_config_ext.h.in.orig
deleted file mode 100644
index 8acadbd..0000000
--- a/libpq/postgresql/pg_config_ext.h.in.orig
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.in. This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#undef PG_INT64_TYPE
diff --git a/libpq/postgresql/pg_config_ext.h.win32.orig b/libpq/postgresql/pg_config_ext.h.win32.orig
deleted file mode 100644
index 65bbb5d..0000000
--- a/libpq/postgresql/pg_config_ext.h.win32.orig
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * src/include/pg_config_ext.h.win32. This is generated manually, not by
- * autoheader, since we want to limit which symbols get defined here.
- */
-
-/* Define to the name of a signed 64-bit integer type. */
-#define PG_INT64_TYPE long long int
diff --git a/libpq/postgresql/pg_config_manual.h b/libpq/postgresql/pg_config_manual.h
deleted file mode 100644
index 96885bb..0000000
--- a/libpq/postgresql/pg_config_manual.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*------------------------------------------------------------------------
- * PostgreSQL manual configuration settings
- *
- * This file contains various configuration symbols and limits. In
- * all cases, changing them is only useful in very rare situations or
- * for developers. If you edit any of these, be sure to do a *full*
- * rebuild (and an initdb if noted).
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/pg_config_manual.h
- *------------------------------------------------------------------------
- */
-
-/*
- * Maximum length for identifiers (e.g. table names, column names,
- * function names). Names actually are limited to one less byte than this,
- * because the length must include a trailing zero byte.
- *
- * Changing this requires an initdb.
- */
-#define NAMEDATALEN 64
-
-/*
- * Maximum number of arguments to a function.
- *
- * The minimum value is 8 (GIN indexes use 8-argument support functions).
- * The maximum possible value is around 600 (limited by index tuple size in
- * pg_proc's index; BLCKSZ larger than 8K would allow more). Values larger
- * than needed will waste memory and processing time, but do not directly
- * cost disk space.
- *
- * Changing this does not require an initdb, but it does require a full
- * backend recompile (including any user-defined C functions).
- */
-#define FUNC_MAX_ARGS 100
-
-/*
- * Maximum number of columns in an index. There is little point in making
- * this anything but a multiple of 32, because the main cost is associated
- * with index tuple header size (see access/itup.h).
- *
- * Changing this requires an initdb.
- */
-#define INDEX_MAX_KEYS 32
-
-/*
- * Set the upper and lower bounds of sequence values.
- */
-#define SEQ_MAXVALUE PG_INT64_MAX
-#define SEQ_MINVALUE (-SEQ_MAXVALUE)
-
-/*
- * When we don't have native spinlocks, we use semaphores to simulate them.
- * Decreasing this value reduces consumption of OS resources; increasing it
- * may improve performance, but supplying a real spinlock implementation is
- * probably far better.
- */
-#define NUM_SPINLOCK_SEMAPHORES 128
-
-/*
- * When we have neither spinlocks nor atomic operations support we're
- * implementing atomic operations on top of spinlock on top of semaphores. To
- * be safe against atomic operations while holding a spinlock separate
- * semaphores have to be used.
- */
-#define NUM_ATOMICS_SEMAPHORES 64
-
-/*
- * Define this if you want to allow the lo_import and lo_export SQL
- * functions to be executed by ordinary users. By default these
- * functions are only available to the Postgres superuser. CAUTION:
- * These functions are SECURITY HOLES since they can read and write
- * any file that the PostgreSQL server has permission to access. If
- * you turn this on, don't say we didn't warn you.
- */
-/* #define ALLOW_DANGEROUS_LO_FUNCTIONS */
-
-/*
- * MAXPGPATH: standard size of a pathname buffer in PostgreSQL (hence,
- * maximum usable pathname length is one less).
- *
- * We'd use a standard system header symbol for this, if there weren't
- * so many to choose from: MAXPATHLEN, MAX_PATH, PATH_MAX are all
- * defined by different "standards", and often have different values
- * on the same platform! So we just punt and use a reasonably
- * generous setting here.
- */
-#define MAXPGPATH 1024
-
-/*
- * PG_SOMAXCONN: maximum accept-queue length limit passed to
- * listen(2). You'd think we should use SOMAXCONN from
- * <sys/socket.h>, but on many systems that symbol is much smaller
- * than the kernel's actual limit. In any case, this symbol need be
- * twiddled only if you have a kernel that refuses large limit values,
- * rather than silently reducing the value to what it can handle
- * (which is what most if not all Unixen do).
- */
-#define PG_SOMAXCONN 10000
-
-/*
- * You can try changing this if you have a machine with bytes of
- * another size, but no guarantee...
- */
-#define BITS_PER_BYTE 8
-
-/*
- * Preferred alignment for disk I/O buffers. On some CPUs, copies between
- * user space and kernel space are significantly faster if the user buffer
- * is aligned on a larger-than-MAXALIGN boundary. Ideally this should be
- * a platform-dependent value, but for now we just hard-wire it.
- */
-#define ALIGNOF_BUFFER 32
-
-/*
- * Disable UNIX sockets for certain operating systems.
- */
-#if defined(WIN32)
-#undef HAVE_UNIX_SOCKETS
-#endif
-
-/*
- * Define this if your operating system supports link()
- */
-#if !defined(WIN32) && !defined(__CYGWIN__)
-#define HAVE_WORKING_LINK 1
-#endif
-
-/*
- * USE_POSIX_FADVISE controls whether Postgres will attempt to use the
- * posix_fadvise() kernel call. Usually the automatic configure tests are
- * sufficient, but some older Linux distributions had broken versions of
- * posix_fadvise(). If necessary you can remove the #define here.
- */
-#if HAVE_DECL_POSIX_FADVISE && defined(HAVE_POSIX_FADVISE)
-#define USE_POSIX_FADVISE
-#endif
-
-/*
- * USE_PREFETCH code should be compiled only if we have a way to implement
- * prefetching. (This is decoupled from USE_POSIX_FADVISE because there
- * might in future be support for alternative low-level prefetch APIs.)
- */
-#ifdef USE_POSIX_FADVISE
-#define USE_PREFETCH
-#endif
-
-/*
- * Default and maximum values for backend_flush_after, bgwriter_flush_after
- * and checkpoint_flush_after; measured in blocks. Currently, these are
- * enabled by default if sync_file_range() exists, ie, only on Linux. Perhaps
- * we could also enable by default if we have mmap and msync(MS_ASYNC)?
- */
-#ifdef HAVE_SYNC_FILE_RANGE
-#define DEFAULT_BACKEND_FLUSH_AFTER 0 /* never enabled by default */
-#define DEFAULT_BGWRITER_FLUSH_AFTER 64
-#define DEFAULT_CHECKPOINT_FLUSH_AFTER 32
-#else
-#define DEFAULT_BACKEND_FLUSH_AFTER 0
-#define DEFAULT_BGWRITER_FLUSH_AFTER 0
-#define DEFAULT_CHECKPOINT_FLUSH_AFTER 0
-#endif
-/* upper limit for all three variables */
-#define WRITEBACK_MAX_PENDING_FLUSHES 256
-
-/*
- * USE_SSL code should be compiled only when compiling with an SSL
- * implementation. (Currently, only OpenSSL is supported, but we might add
- * more implementations in the future.)
- */
-#ifdef USE_OPENSSL
-#define USE_SSL
-#endif
-
-/*
- * This is the default directory in which AF_UNIX socket files are
- * placed. Caution: changing this risks breaking your existing client
- * applications, which are likely to continue to look in the old
- * directory. But if you just hate the idea of sockets in /tmp,
- * here's where to twiddle it. You can also override this at runtime
- * with the postmaster's -k switch.
- */
-#define DEFAULT_PGSOCKET_DIR "/tmp"
-
-/*
- * This is the default event source for Windows event log.
- */
-#define DEFAULT_EVENT_SOURCE "PostgreSQL"
-
-/*
- * The random() function is expected to yield values between 0 and
- * MAX_RANDOM_VALUE. Currently, all known implementations yield
- * 0..2^31-1, so we just hardwire this constant. We could do a
- * configure test if it proves to be necessary. CAUTION: Think not to
- * replace this with RAND_MAX. RAND_MAX defines the maximum value of
- * the older rand() function, which is often different from --- and
- * considerably inferior to --- random().
- */
-#define MAX_RANDOM_VALUE PG_INT32_MAX
-
-/*
- * On PPC machines, decide whether to use the mutex hint bit in LWARX
- * instructions. Setting the hint bit will slightly improve spinlock
- * performance on POWER6 and later machines, but does nothing before that,
- * and will result in illegal-instruction failures on some pre-POWER4
- * machines. By default we use the hint bit when building for 64-bit PPC,
- * which should be safe in nearly all cases. You might want to override
- * this if you are building 32-bit code for a known-recent PPC machine.
- */
-#ifdef HAVE_PPC_LWARX_MUTEX_HINT /* must have assembler support in any case */
-#if defined(__ppc64__) || defined(__powerpc64__)
-#define USE_PPC_LWARX_MUTEX_HINT
-#endif
-#endif
-
-/*
- * On PPC machines, decide whether to use LWSYNC instructions in place of
- * ISYNC and SYNC. This provides slightly better performance, but will
- * result in illegal-instruction failures on some pre-POWER4 machines.
- * By default we use LWSYNC when building for 64-bit PPC, which should be
- * safe in nearly all cases.
- */
-#if defined(__ppc64__) || defined(__powerpc64__)
-#define USE_PPC_LWSYNC
-#endif
-
-/*
- * Assumed cache line size. This doesn't affect correctness, but can be used
- * for low-level optimizations. Currently, this is used to pad some data
- * structures in xlog.c, to ensure that highly-contended fields are on
- * different cache lines. Too small a value can hurt performance due to false
- * sharing, while the only downside of too large a value is a few bytes of
- * wasted memory. The default is 128, which should be large enough for all
- * supported platforms.
- */
-#define PG_CACHE_LINE_SIZE 128
-
-/*
- *------------------------------------------------------------------------
- * The following symbols are for enabling debugging code, not for
- * controlling user-visible features or resource limits.
- *------------------------------------------------------------------------
- */
-
-/*
- * Include Valgrind "client requests", mostly in the memory allocator, so
- * Valgrind understands PostgreSQL memory contexts. This permits detecting
- * memory errors that Valgrind would not detect on a vanilla build. See also
- * src/tools/valgrind.supp. "make installcheck" runs 20-30x longer under
- * Valgrind. Note that USE_VALGRIND slowed older versions of Valgrind by an
- * additional order of magnitude; Valgrind 3.8.1 does not have this problem.
- * The client requests fall in hot code paths, so USE_VALGRIND also slows
- * native execution by a few percentage points.
- *
- * You should normally use MEMORY_CONTEXT_CHECKING with USE_VALGRIND;
- * instrumentation of repalloc() is inferior without it.
- */
-/* #define USE_VALGRIND */
-
-/*
- * Define this to cause pfree()'d memory to be cleared immediately, to
- * facilitate catching bugs that refer to already-freed values.
- * Right now, this gets defined automatically if --enable-cassert.
- */
-#ifdef USE_ASSERT_CHECKING
-#define CLOBBER_FREED_MEMORY
-#endif
-
-/*
- * Define this to check memory allocation errors (scribbling on more
- * bytes than were allocated). Right now, this gets defined
- * automatically if --enable-cassert or USE_VALGRIND.
- */
-#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
-#define MEMORY_CONTEXT_CHECKING
-#endif
-
-/*
- * Define this to cause palloc()'d memory to be filled with random data, to
- * facilitate catching code that depends on the contents of uninitialized
- * memory. Caution: this is horrendously expensive.
- */
-/* #define RANDOMIZE_ALLOCATED_MEMORY */
-
-/*
- * Define this to force all parse and plan trees to be passed through
- * copyObject(), to facilitate catching errors and omissions in
- * copyObject().
- */
-/* #define COPY_PARSE_PLAN_TREES */
-
-/*
- * Define this to force all raw parse trees for DML statements to be scanned
- * by raw_expression_tree_walker(), to facilitate catching errors and
- * omissions in that function.
- */
-/* #define RAW_EXPRESSION_COVERAGE_TEST */
-
-/*
- * Enable debugging print statements for lock-related operations.
- */
-/* #define LOCK_DEBUG */
-
-/*
- * Enable debugging print statements for WAL-related operations; see
- * also the wal_debug GUC var.
- */
-/* #define WAL_DEBUG */
-
-/*
- * Enable tracing of resource consumption during sort operations;
- * see also the trace_sort GUC var. For 8.1 this is enabled by default.
- */
-#define TRACE_SORT 1
-
-/*
- * Enable tracing of syncscan operations (see also the trace_syncscan GUC var).
- */
-/* #define TRACE_SYNCSCAN */
-
-/*
- * Other debug #defines (documentation, anyone?)
- */
-/* #define HEAPDEBUGALL */
-/* #define ACLDEBUG */
diff --git a/libpq/postgresql/pg_config_paths.h b/libpq/postgresql/pg_config_paths.h
deleted file mode 100644
index 8b13789..0000000
--- a/libpq/postgresql/pg_config_paths.h
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libpq/postgresql/port.h b/libpq/postgresql/port.h
deleted file mode 100644
index a61e59c..0000000
--- a/libpq/postgresql/port.h
+++ /dev/null
@@ -1,477 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * port.h
- * Header for src/port/ compatibility functions.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/port.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PG_PORT_H
-#define PG_PORT_H
-
-#include <ctype.h>
-#include <netdb.h>
-#include <pwd.h>
-
-/* socket has a different definition on WIN32 */
-#ifndef WIN32
-typedef int pgsocket;
-
-#define PGINVALID_SOCKET (-1)
-#else
-typedef SOCKET pgsocket;
-
-#define PGINVALID_SOCKET INVALID_SOCKET
-#endif
-
-/* non-blocking */
-extern bool pg_set_noblock(pgsocket sock);
-extern bool pg_set_block(pgsocket sock);
-
-/* Portable path handling for Unix/Win32 (in path.c) */
-
-extern bool has_drive_prefix(const char *filename);
-extern char *first_dir_separator(const char *filename);
-extern char *last_dir_separator(const char *filename);
-extern char *first_path_var_separator(const char *pathlist);
-extern void join_path_components(char *ret_path,
- const char *head, const char *tail);
-extern void canonicalize_path(char *path);
-extern void make_native_path(char *path);
-extern void cleanup_path(char *path);
-extern bool path_contains_parent_reference(const char *path);
-extern bool path_is_relative_and_below_cwd(const char *path);
-extern bool path_is_prefix_of_path(const char *path1, const char *path2);
-extern char *make_absolute_path(const char *path);
-extern const char *get_progname(const char *argv0);
-extern void get_share_path(const char *my_exec_path, char *ret_path);
-extern void get_etc_path(const char *my_exec_path, char *ret_path);
-extern void get_include_path(const char *my_exec_path, char *ret_path);
-extern void get_pkginclude_path(const char *my_exec_path, char *ret_path);
-extern void get_includeserver_path(const char *my_exec_path, char *ret_path);
-extern void get_lib_path(const char *my_exec_path, char *ret_path);
-extern void get_pkglib_path(const char *my_exec_path, char *ret_path);
-extern void get_locale_path(const char *my_exec_path, char *ret_path);
-extern void get_doc_path(const char *my_exec_path, char *ret_path);
-extern void get_html_path(const char *my_exec_path, char *ret_path);
-extern void get_man_path(const char *my_exec_path, char *ret_path);
-extern bool get_home_path(char *ret_path);
-extern void get_parent_directory(char *path);
-
-/* common/pgfnames.c */
-extern char **pgfnames(const char *path);
-extern void pgfnames_cleanup(char **filenames);
-
-/*
- * is_absolute_path
- *
- * By making this a macro we avoid needing to include path.c in libpq.
- */
-#ifndef WIN32
-#define IS_DIR_SEP(ch) ((ch) == '/')
-
-#define is_absolute_path(filename) \
-( \
- IS_DIR_SEP((filename)[0]) \
-)
-#else
-#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\')
-
-/* See path_is_relative_and_below_cwd() for how we handle 'E:abc'. */
-#define is_absolute_path(filename) \
-( \
- IS_DIR_SEP((filename)[0]) || \
- (isalpha((unsigned char) ((filename)[0])) && (filename)[1] == ':' && \
- IS_DIR_SEP((filename)[2])) \
-)
-#endif
-
-/* Portable locale initialization (in exec.c) */
-extern void set_pglocale_pgservice(const char *argv0, const char *app);
-
-/* Portable way to find binaries (in exec.c) */
-extern int find_my_exec(const char *argv0, char *retpath);
-extern int find_other_exec(const char *argv0, const char *target,
- const char *versionstr, char *retpath);
-
-/* Windows security token manipulation (in exec.c) */
-#ifdef WIN32
-extern BOOL AddUserToTokenDacl(HANDLE hToken);
-#endif
-
-
-#if defined(WIN32) || defined(__CYGWIN__)
-#define EXE ".exe"
-#else
-#define EXE ""
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__)
-#define DEVNULL "nul"
-#else
-#define DEVNULL "/dev/null"
-#endif
-
-/* Portable delay handling */
-extern void pg_usleep(long microsec);
-
-/* Portable SQL-like case-independent comparisons and conversions */
-extern int pg_strcasecmp(const char *s1, const char *s2);
-extern int pg_strncasecmp(const char *s1, const char *s2, size_t n);
-extern unsigned char pg_toupper(unsigned char ch);
-extern unsigned char pg_tolower(unsigned char ch);
-extern unsigned char pg_ascii_toupper(unsigned char ch);
-extern unsigned char pg_ascii_tolower(unsigned char ch);
-
-#ifdef USE_REPL_SNPRINTF
-
-/*
- * Versions of libintl >= 0.13 try to replace printf() and friends with
- * macros to their own versions that understand the %$ format. We do the
- * same, so disable their macros, if they exist.
- */
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#ifdef snprintf
-#undef snprintf
-#endif
-#ifdef sprintf
-#undef sprintf
-#endif
-#ifdef vfprintf
-#undef vfprintf
-#endif
-#ifdef fprintf
-#undef fprintf
-#endif
-#ifdef printf
-#undef printf
-#endif
-
-extern int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
-extern int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4);
-extern int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2, 3);
-extern int pg_vfprintf(FILE *stream, const char *fmt, va_list args);
-extern int pg_fprintf(FILE *stream, const char *fmt,...) pg_attribute_printf(2, 3);
-extern int pg_printf(const char *fmt,...) pg_attribute_printf(1, 2);
-
-/*
- * The GCC-specific code below prevents the pg_attribute_printf above from
- * being replaced, and this is required because gcc doesn't know anything
- * about pg_printf.
- */
-#ifdef __GNUC__
-#define vsnprintf(...) pg_vsnprintf(__VA_ARGS__)
-#define snprintf(...) pg_snprintf(__VA_ARGS__)
-#define sprintf(...) pg_sprintf(__VA_ARGS__)
-#define vfprintf(...) pg_vfprintf(__VA_ARGS__)
-#define fprintf(...) pg_fprintf(__VA_ARGS__)
-#define printf(...) pg_printf(__VA_ARGS__)
-#else
-#define vsnprintf pg_vsnprintf
-#define snprintf pg_snprintf
-#define sprintf pg_sprintf
-#define vfprintf pg_vfprintf
-#define fprintf pg_fprintf
-#define printf pg_printf
-#endif
-#endif /* USE_REPL_SNPRINTF */
-
-#if defined(WIN32)
-/*
- * Versions of libintl >= 0.18? try to replace setlocale() with a macro
- * to their own versions. Remove the macro, if it exists, because it
- * ends up calling the wrong version when the backend and libintl use
- * different versions of msvcrt.
- */
-#if defined(setlocale)
-#undef setlocale
-#endif
-
-/*
- * Define our own wrapper macro around setlocale() to work around bugs in
- * Windows' native setlocale() function.
- */
-extern char *pgwin32_setlocale(int category, const char *locale);
-
-#define setlocale(a,b) pgwin32_setlocale(a,b)
-#endif /* WIN32 */
-
-/* Portable prompt handling */
-extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
-
-#ifdef WIN32
-#define PG_SIGNAL_COUNT 32
-#define kill(pid,sig) pgkill(pid,sig)
-extern int pgkill(int pid, int sig);
-#endif
-
-extern int pclose_check(FILE *stream);
-
-/* Global variable holding time zone information. */
-#if defined(WIN32) || defined(__CYGWIN__)
-#define TIMEZONE_GLOBAL _timezone
-#define TZNAME_GLOBAL _tzname
-#else
-#define TIMEZONE_GLOBAL timezone
-#define TZNAME_GLOBAL tzname
-#endif
-
-#if defined(WIN32) || defined(__CYGWIN__)
-/*
- * Win32 doesn't have reliable rename/unlink during concurrent access.
- */
-extern int pgrename(const char *from, const char *to);
-extern int pgunlink(const char *path);
-
-/* Include this first so later includes don't see these defines */
-#ifdef WIN32_ONLY_COMPILER
-#include <io.h>
-#endif
-
-#define rename(from, to) pgrename(from, to)
-#define unlink(path) pgunlink(path)
-#endif /* defined(WIN32) || defined(__CYGWIN__) */
-
-/*
- * Win32 also doesn't have symlinks, but we can emulate them with
- * junction points on newer Win32 versions.
- *
- * Cygwin has its own symlinks which work on Win95/98/ME where
- * junction points don't, so use those instead. We have no way of
- * knowing what type of system Cygwin binaries will be run on.
- * Note: Some CYGWIN includes might #define WIN32.
- */
-#if defined(WIN32) && !defined(__CYGWIN__)
-extern int pgsymlink(const char *oldpath, const char *newpath);
-extern int pgreadlink(const char *path, char *buf, size_t size);
-extern bool pgwin32_is_junction(char *path);
-
-#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
-#define readlink(path, buf, size) pgreadlink(path, buf, size)
-#endif
-
-extern bool rmtree(const char *path, bool rmtopdir);
-
-/*
- * stat() is not guaranteed to set the st_size field on win32, so we
- * redefine it to our own implementation that is.
- *
- * We must pull in sys/stat.h here so the system header definition
- * goes in first, and we redefine that, and not the other way around.
- *
- * Some frontends don't need the size from stat, so if UNSAFE_STAT_OK
- * is defined we don't bother with this.
- */
-#if defined(WIN32) && !defined(__CYGWIN__) && !defined(UNSAFE_STAT_OK)
-#include <sys/stat.h>
-extern int pgwin32_safestat(const char *path, struct stat * buf);
-
-#define stat(a,b) pgwin32_safestat(a,b)
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__)
-
-/*
- * open() and fopen() replacements to allow deletion of open files and
- * passing of other special options.
- */
-#define O_DIRECT 0x80000000
-extern int pgwin32_open(const char *, int,...);
-extern FILE *pgwin32_fopen(const char *, const char *);
-
-#ifndef FRONTEND
-#define open(a,b,c) pgwin32_open(a,b,c)
-#define fopen(a,b) pgwin32_fopen(a,b)
-#endif
-
-/*
- * Mingw-w64 headers #define popen and pclose to _popen and _pclose. We want
- * to use our popen wrapper, rather than plain _popen, so override that. For
- * consistency, use our version of pclose, too.
- */
-#ifdef popen
-#undef popen
-#endif
-#ifdef pclose
-#undef pclose
-#endif
-
-/*
- * system() and popen() replacements to enclose the command in an extra
- * pair of quotes.
- */
-extern int pgwin32_system(const char *command);
-extern FILE *pgwin32_popen(const char *command, const char *type);
-
-#define system(a) pgwin32_system(a)
-#define popen(a,b) pgwin32_popen(a,b)
-#define pclose(a) _pclose(a)
-
-/* New versions of MingW have gettimeofday, old mingw and msvc don't */
-#ifndef HAVE_GETTIMEOFDAY
-/* Last parameter not used */
-extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
-#endif
-#else /* !WIN32 */
-
-/*
- * Win32 requires a special close for sockets and pipes, while on Unix
- * close() does them all.
- */
-#define closesocket close
-#endif /* WIN32 */
-
-/*
- * On Windows, setvbuf() does not support _IOLBF mode, and interprets that
- * as _IOFBF. To add insult to injury, setvbuf(file, NULL, _IOFBF, 0)
- * crashes outright if "parameter validation" is enabled. Therefore, in
- * places where we'd like to select line-buffered mode, we fall back to
- * unbuffered mode instead on Windows. Always use PG_IOLBF not _IOLBF
- * directly in order to implement this behavior.
- */
-#ifndef WIN32
-#define PG_IOLBF _IOLBF
-#else
-#define PG_IOLBF _IONBF
-#endif
-
-/*
- * Default "extern" declarations or macro substitutes for library routines.
- * When necessary, these routines are provided by files in src/port/.
- */
-#ifndef HAVE_CRYPT
-extern char *crypt(const char *key, const char *setting);
-#endif
-
-/* WIN32 handled in port/win32.h */
-#ifndef WIN32
-#define pgoff_t off_t
-#ifdef __NetBSD__
-extern int fseeko(FILE *stream, off_t offset, int whence);
-extern off_t ftello(FILE *stream);
-#endif
-#endif
-
-extern double pg_erand48(unsigned short xseed[3]);
-extern long pg_lrand48(void);
-extern void pg_srand48(long seed);
-
-#ifndef HAVE_FLS
-extern int fls(int mask);
-#endif
-
-#ifndef HAVE_FSEEKO
-#define fseeko(a, b, c) fseek(a, b, c)
-#define ftello(a) ftell(a)
-#endif
-
-#if !defined(HAVE_GETPEEREID) && !defined(WIN32)
-extern int getpeereid(int sock, uid_t *uid, gid_t *gid);
-#endif
-
-#ifndef HAVE_ISINF
-extern int isinf(double x);
-#endif
-
-#ifndef HAVE_MKDTEMP
-extern char *mkdtemp(char *path);
-#endif
-
-#ifndef HAVE_RINT
-extern double rint(double x);
-#endif
-
-#ifndef HAVE_INET_ATON
-#include <netinet/in.h>
-#include <arpa/inet.h>
-extern int inet_aton(const char *cp, struct in_addr * addr);
-#endif
-
-#if !HAVE_DECL_STRLCAT
-extern size_t strlcat(char *dst, const char *src, size_t siz);
-#endif
-
-#if !HAVE_DECL_STRLCPY
-extern size_t strlcpy(char *dst, const char *src, size_t siz);
-#endif
-
-#if !defined(HAVE_RANDOM) && !defined(__BORLANDC__)
-extern long random(void);
-#endif
-
-#ifndef HAVE_UNSETENV
-extern void unsetenv(const char *name);
-#endif
-
-#ifndef HAVE_SRANDOM
-extern void srandom(unsigned int seed);
-#endif
-
-#ifndef HAVE_SSL_GET_CURRENT_COMPRESSION
-#define SSL_get_current_compression(x) 0
-#endif
-
-/* thread.h */
-extern char *pqStrerror(int errnum, char *strerrbuf, size_t buflen);
-
-#ifndef WIN32
-extern int pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer,
- size_t buflen, struct passwd ** result);
-#endif
-
-extern int pqGethostbyname(const char *name,
- struct hostent * resultbuf,
- char *buffer, size_t buflen,
- struct hostent ** result,
- int *herrno);
-
-extern void pg_qsort(void *base, size_t nel, size_t elsize,
- int (*cmp) (const void *, const void *));
-extern int pg_qsort_strcmp(const void *a, const void *b);
-
-#define qsort(a,b,c,d) pg_qsort(a,b,c,d)
-
-typedef int (*qsort_arg_comparator) (const void *a, const void *b, void *arg);
-
-extern void qsort_arg(void *base, size_t nel, size_t elsize,
- qsort_arg_comparator cmp, void *arg);
-
-/* port/chklocale.c */
-extern int pg_get_encoding_from_locale(const char *ctype, bool write_message);
-
-#if defined(WIN32) && !defined(FRONTEND)
-extern int pg_codepage_to_encoding(UINT cp);
-#endif
-
-/* port/inet_net_ntop.c */
-extern char *inet_net_ntop(int af, const void *src, int bits,
- char *dst, size_t size);
-
-/* port/pgcheckdir.c */
-extern int pg_check_dir(const char *dir);
-
-/* port/pgmkdirp.c */
-extern int pg_mkdir_p(char *path, int omode);
-
-/* port/pqsignal.c */
-typedef void (*pqsigfunc) (int signo);
-extern pqsigfunc pqsignal(int signo, pqsigfunc func);
-#ifndef WIN32
-extern pqsigfunc pqsignal_no_restart(int signo, pqsigfunc func);
-#else
-#define pqsignal_no_restart(signo, func) pqsignal(signo, func)
-#endif
-
-/* port/quotes.c */
-extern char *escape_single_quotes_ascii(const char *src);
-
-/* port/wait_error.c */
-extern char *wait_result_to_str(int exit_status);
-
-#endif /* PG_PORT_H */
diff --git a/libpq/postgresql/port/bsd/pg_config_os.h b/libpq/postgresql/port/bsd/pg_config_os.h
deleted file mode 100644
index e69de29..0000000
--- a/libpq/postgresql/port/bsd/pg_config_os.h
+++ /dev/null
diff --git a/libpq/postgresql/port/darwin/pg_config_os.h b/libpq/postgresql/port/darwin/pg_config_os.h
deleted file mode 100644
index 29c4b91..0000000
--- a/libpq/postgresql/port/darwin/pg_config_os.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* src/include/port/darwin.h */
-
-#define __darwin__ 1
-
-#if HAVE_DECL_F_FULLFSYNC /* not present before OS X 10.3 */
-#define HAVE_FSYNC_WRITETHROUGH
-
-#endif
diff --git a/libpq/postgresql/port/linux/pg_config_os.h b/libpq/postgresql/port/linux/pg_config_os.h
deleted file mode 100644
index 7a6e46c..0000000
--- a/libpq/postgresql/port/linux/pg_config_os.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* src/include/port/linux.h */
-
-/*
- * As of July 2007, all known versions of the Linux kernel will sometimes
- * return EIDRM for a shmctl() operation when EINVAL is correct (it happens
- * when the low-order 15 bits of the supplied shm ID match the slot number
- * assigned to a newer shmem segment). We deal with this by assuming that
- * EIDRM means EINVAL in PGSharedMemoryIsInUse(). This is reasonably safe
- * since in fact Linux has no excuse for ever returning EIDRM; it doesn't
- * track removed segments in a way that would allow distinguishing them from
- * private ones. But someday that code might get upgraded, and we'd have
- * to have a kernel version test here.
- */
-#define HAVE_LINUX_EIDRM_BUG
-
-/*
- * Set the default wal_sync_method to fdatasync. With recent Linux versions,
- * xlogdefs.h's normal rules will prefer open_datasync, which (a) doesn't
- * perform better and (b) causes outright failures on ext4 data=journal
- * filesystems, because those don't support O_DIRECT.
- */
-#define PLATFORM_DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
diff --git a/libpq/postgresql/port/win32/arpa/inet.h b/libpq/postgresql/port/win32/arpa/inet.h
deleted file mode 100644
index ad18031..0000000
--- a/libpq/postgresql/port/win32/arpa/inet.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* src/include/port/win32/arpa/inet.h */
-
-#include <sys/socket.h>
diff --git a/libpq/postgresql/port/win32/netdb.h b/libpq/postgresql/port/win32/netdb.h
deleted file mode 100644
index ad0627e..0000000
--- a/libpq/postgresql/port/win32/netdb.h
+++ /dev/null
@@ -1 +0,0 @@
-/* src/include/port/win32/netdb.h */
diff --git a/libpq/postgresql/port/win32/netinet/in.h b/libpq/postgresql/port/win32/netinet/in.h
deleted file mode 100644
index a4e22f8..0000000
--- a/libpq/postgresql/port/win32/netinet/in.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* src/include/port/win32/netinet/in.h */
-
-#include <sys/socket.h>
diff --git a/libpq/postgresql/port/win32/pg_config_os.h b/libpq/postgresql/port/win32/pg_config_os.h
deleted file mode 100644
index 4453c90..0000000
--- a/libpq/postgresql/port/win32/pg_config_os.h
+++ /dev/null
@@ -1,486 +0,0 @@
-/* src/include/port/win32.h */
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-#define WIN32_ONLY_COMPILER
-#endif
-
-/*
- * Make sure _WIN32_WINNT has the minimum required value.
- * Leave a higher value in place. When building with at least Visual
- * Studio 2015 the minimum requirement is Windows Vista (0x0600) to
- * get support for GetLocaleInfoEx() with locales. For everything else
- * the minimum version is Windows XP (0x0501).
- * Also for VS2015, add a define that stops compiler complaints about
- * using the old Winsock API.
- */
-#if defined(_MSC_VER) && _MSC_VER >= 1900
-#define _WINSOCK_DEPRECATED_NO_WARNINGS
-#define MIN_WINNT 0x0600
-#else
-#define MIN_WINNT 0x0501
-#endif
-
-#if defined(_WIN32_WINNT) && _WIN32_WINNT < MIN_WINNT
-#undef _WIN32_WINNT
-#endif
-
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT MIN_WINNT
-#endif
-
-/*
- * Always build with SSPI support. Keep it as a #define in case
- * we want a switch to disable it sometime in the future.
- */
-#ifndef __BORLANDC__
-#define ENABLE_SSPI 1
-#endif
-
-/* undefine and redefine after #include */
-#undef mkdir
-
-#undef ERROR
-
-/*
- * The Mingw64 headers choke if this is already defined - they
- * define it themselves.
- */
-#if !defined(__MINGW64_VERSION_MAJOR) || defined(WIN32_ONLY_COMPILER)
-#define _WINSOCKAPI_
-#endif
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#undef small
-#include <process.h>
-#include <signal.h>
-#include <errno.h>
-#include <direct.h>
-#ifndef __BORLANDC__
-#include <sys/utime.h> /* for non-unicode version */
-#endif
-#undef near
-
-/* Must be here to avoid conflicting with prototype in windows.h */
-#define mkdir(a,b) mkdir(a)
-
-#define ftruncate(a,b) chsize(a,b)
-
-/* Windows doesn't have fsync() as such, use _commit() */
-#define fsync(fd) _commit(fd)
-
-/*
- * For historical reasons, we allow setting wal_sync_method to
- * fsync_writethrough on Windows, even though it's really identical to fsync
- * (both code paths wind up at _commit()).
- */
-#define HAVE_FSYNC_WRITETHROUGH
-#define FSYNC_WRITETHROUGH_IS_FSYNC
-
-#define USES_WINSOCK
-
-/* defines for dynamic linking on Win32 platform
- *
- * http://support.microsoft.com/kb/132044
- * http://msdn.microsoft.com/en-us/library/8fskxacy(v=vs.80).aspx
- * http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx
- */
-
-#if defined(WIN32) || defined(__CYGWIN__)
-
-#ifdef BUILDING_DLL
-#define PGDLLIMPORT __declspec (dllexport)
-#else /* not BUILDING_DLL */
-#define PGDLLIMPORT __declspec (dllimport)
-#endif
-
-#ifdef _MSC_VER
-#define PGDLLEXPORT __declspec (dllexport)
-#else
-#define PGDLLEXPORT
-#endif
-#else /* not CYGWIN, not MSVC, not MingW */
-#define PGDLLIMPORT
-#define PGDLLEXPORT
-#endif
-
-
-/*
- * IPC defines
- */
-#undef HAVE_UNION_SEMUN
-#define HAVE_UNION_SEMUN 1
-
-#define IPC_RMID 256
-#define IPC_CREAT 512
-#define IPC_EXCL 1024
-#define IPC_PRIVATE 234564
-#define IPC_NOWAIT 2048
-#define IPC_STAT 4096
-
-#define EACCESS 2048
-#ifndef EIDRM
-#define EIDRM 4096
-#endif
-
-#define SETALL 8192
-#define GETNCNT 16384
-#define GETVAL 65536
-#define SETVAL 131072
-#define GETPID 262144
-
-
-/*
- * Signal stuff
- *
- * For WIN32, there is no wait() call so there are no wait() macros
- * to interpret the return value of system(). Instead, system()
- * return values < 0x100 are used for exit() termination, and higher
- * values are used to indicated non-exit() termination, which is
- * similar to a unix-style signal exit (think SIGSEGV ==
- * STATUS_ACCESS_VIOLATION). Return values are broken up into groups:
- *
- * http://msdn2.microsoft.com/en-gb/library/aa489609.aspx
- *
- * NT_SUCCESS 0 - 0x3FFFFFFF
- * NT_INFORMATION 0x40000000 - 0x7FFFFFFF
- * NT_WARNING 0x80000000 - 0xBFFFFFFF
- * NT_ERROR 0xC0000000 - 0xFFFFFFFF
- *
- * Effectively, we don't care on the severity of the return value from
- * system(), we just need to know if it was because of exit() or generated
- * by the system, and it seems values >= 0x100 are system-generated.
- * See this URL for a list of WIN32 STATUS_* values:
- *
- * Wine (URL used in our error messages) -
- * http://source.winehq.org/source/include/ntstatus.h
- * Descriptions - http://www.comp.nus.edu.sg/~wuyongzh/my_doc/ntstatus.txt
- * MS SDK - http://www.nologs.com/ntstatus.html
- *
- * It seems the exception lists are in both ntstatus.h and winnt.h, but
- * ntstatus.h has a more comprehensive list, and it only contains
- * exception values, rather than winnt, which contains lots of other
- * things:
- *
- * http://www.microsoft.com/msj/0197/exception/exception.aspx
- *
- * The ExceptionCode parameter is the number that the operating system
- * assigned to the exception. You can see a list of various exception codes
- * in WINNT.H by searching for #defines that start with "STATUS_". For
- * example, the code for the all-too-familiar STATUS_ACCESS_VIOLATION is
- * 0xC0000005. A more complete set of exception codes can be found in
- * NTSTATUS.H from the Windows NT DDK.
- *
- * Some day we might want to print descriptions for the most common
- * exceptions, rather than printing an include file name. We could use
- * RtlNtStatusToDosError() and pass to FormatMessage(), which can print
- * the text of error values, but MinGW does not support
- * RtlNtStatusToDosError().
- */
-#define WIFEXITED(w) (((w) & 0XFFFFFF00) == 0)
-#define WIFSIGNALED(w) (!WIFEXITED(w))
-#define WEXITSTATUS(w) (w)
-#define WTERMSIG(w) (w)
-
-#define sigmask(sig) ( 1 << ((sig)-1) )
-
-/* Signal function return values */
-#undef SIG_DFL
-#undef SIG_ERR
-#undef SIG_IGN
-#define SIG_DFL ((pqsigfunc)0)
-#define SIG_ERR ((pqsigfunc)-1)
-#define SIG_IGN ((pqsigfunc)1)
-
-/* Some extra signals */
-#define SIGHUP 1
-#define SIGQUIT 3
-#define SIGTRAP 5
-#define SIGABRT 22 /* Set to match W32 value -- not UNIX value */
-#define SIGKILL 9
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGSTOP 17
-#define SIGTSTP 18
-#define SIGCONT 19
-#define SIGCHLD 20
-#define SIGTTIN 21
-#define SIGTTOU 22 /* Same as SIGABRT -- no problem, I hope */
-#define SIGWINCH 28
-#ifndef __BORLANDC__
-#define SIGUSR1 30
-#define SIGUSR2 31
-#endif
-
-/*
- * New versions of mingw have gettimeofday() and also declare
- * struct timezone to support it.
- */
-#ifndef HAVE_GETTIMEOFDAY
-struct timezone
-{
- int tz_minuteswest; /* Minutes west of GMT. */
- int tz_dsttime; /* Nonzero if DST is ever in effect. */
-};
-#endif
-
-/* for setitimer in backend/port/win32/timer.c */
-#define ITIMER_REAL 0
-struct itimerval
-{
- struct timeval it_interval;
- struct timeval it_value;
-};
-
-int setitimer(int which, const struct itimerval * value, struct itimerval * ovalue);
-
-/*
- * WIN32 does not provide 64-bit off_t, but does provide the functions operating
- * with 64-bit offsets.
- */
-#define pgoff_t __int64
-#ifdef WIN32_ONLY_COMPILER
-#define fseeko(stream, offset, origin) _fseeki64(stream, offset, origin)
-#define ftello(stream) _ftelli64(stream)
-#else
-#ifndef fseeko
-#define fseeko(stream, offset, origin) fseeko64(stream, offset, origin)
-#endif
-#ifndef ftello
-#define ftello(stream) ftello64(stream)
-#endif
-#endif
-
-/*
- * Supplement to <sys/types.h>.
- *
- * Perl already has typedefs for uid_t and gid_t.
- */
-#ifndef PLPERL_HAVE_UID_GID
-typedef int uid_t;
-typedef int gid_t;
-#endif
-typedef long key_t;
-
-#ifdef WIN32_ONLY_COMPILER
-typedef int pid_t;
-#endif
-
-/*
- * Supplement to <sys/stat.h>.
- */
-#define lstat(path, sb) stat((path), (sb))
-
-/*
- * Supplement to <fcntl.h>.
- * This is the same value as _O_NOINHERIT in the MS header file. This is
- * to ensure that we don't collide with a future definition. It means
- * we cannot use _O_NOINHERIT ourselves.
- */
-#define O_DSYNC 0x0080
-
-/*
- * Supplement to <errno.h>.
- *
- * We redefine network-related Berkeley error symbols as the corresponding WSA
- * constants. This allows elog.c to recognize them as being in the Winsock
- * error code range and pass them off to pgwin32_socket_strerror(), since
- * Windows' version of plain strerror() won't cope. Note that this will break
- * if these names are used for anything else besides Windows Sockets errors.
- * See TranslateSocketError() when changing this list.
- */
-#undef EAGAIN
-#define EAGAIN WSAEWOULDBLOCK
-#undef EINTR
-#define EINTR WSAEINTR
-#undef EMSGSIZE
-#define EMSGSIZE WSAEMSGSIZE
-#undef EAFNOSUPPORT
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
-#undef EWOULDBLOCK
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#undef ECONNABORTED
-#define ECONNABORTED WSAECONNABORTED
-#undef ECONNRESET
-#define ECONNRESET WSAECONNRESET
-#undef EINPROGRESS
-#define EINPROGRESS WSAEINPROGRESS
-#undef EISCONN
-#define EISCONN WSAEISCONN
-#undef ENOBUFS
-#define ENOBUFS WSAENOBUFS
-#undef EPROTONOSUPPORT
-#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
-#undef ECONNREFUSED
-#define ECONNREFUSED WSAECONNREFUSED
-#undef ENOTSOCK
-#define ENOTSOCK WSAENOTSOCK
-#undef EOPNOTSUPP
-#define EOPNOTSUPP WSAEOPNOTSUPP
-#undef EADDRINUSE
-#define EADDRINUSE WSAEADDRINUSE
-#undef EADDRNOTAVAIL
-#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
-#undef EHOSTUNREACH
-#define EHOSTUNREACH WSAEHOSTUNREACH
-#undef ENOTCONN
-#define ENOTCONN WSAENOTCONN
-
-/*
- * Extended locale functions with gratuitous underscore prefixes.
- * (These APIs are nevertheless fully documented by Microsoft.)
- */
-#define locale_t _locale_t
-#define tolower_l _tolower_l
-#define toupper_l _toupper_l
-#define towlower_l _towlower_l
-#define towupper_l _towupper_l
-#define isdigit_l _isdigit_l
-#define iswdigit_l _iswdigit_l
-#define isalpha_l _isalpha_l
-#define iswalpha_l _iswalpha_l
-#define isalnum_l _isalnum_l
-#define iswalnum_l _iswalnum_l
-#define isupper_l _isupper_l
-#define iswupper_l _iswupper_l
-#define islower_l _islower_l
-#define iswlower_l _iswlower_l
-#define isgraph_l _isgraph_l
-#define iswgraph_l _iswgraph_l
-#define isprint_l _isprint_l
-#define iswprint_l _iswprint_l
-#define ispunct_l _ispunct_l
-#define iswpunct_l _iswpunct_l
-#define isspace_l _isspace_l
-#define iswspace_l _iswspace_l
-#define strcoll_l _strcoll_l
-#define strxfrm_l _strxfrm_l
-#define wcscoll_l _wcscoll_l
-#define wcstombs_l _wcstombs_l
-#define mbstowcs_l _mbstowcs_l
-
-
-/* In backend/port/win32/signal.c */
-extern PGDLLIMPORT volatile int pg_signal_queue;
-extern PGDLLIMPORT int pg_signal_mask;
-extern HANDLE pgwin32_signal_event;
-extern HANDLE pgwin32_initial_signal_pipe;
-
-#define UNBLOCKED_SIGNAL_QUEUE() (pg_signal_queue & ~pg_signal_mask)
-
-
-void pgwin32_signal_initialize(void);
-HANDLE pgwin32_create_signal_listener(pid_t pid);
-void pgwin32_dispatch_queued_signals(void);
-void pg_queue_signal(int signum);
-
-/* In backend/port/win32/socket.c */
-#ifndef FRONTEND
-#define socket(af, type, protocol) pgwin32_socket(af, type, protocol)
-#define bind(s, addr, addrlen) pgwin32_bind(s, addr, addrlen)
-#define listen(s, backlog) pgwin32_listen(s, backlog)
-#define accept(s, addr, addrlen) pgwin32_accept(s, addr, addrlen)
-#define connect(s, name, namelen) pgwin32_connect(s, name, namelen)
-#define select(n, r, w, e, timeout) pgwin32_select(n, r, w, e, timeout)
-#define recv(s, buf, len, flags) pgwin32_recv(s, buf, len, flags)
-#define send(s, buf, len, flags) pgwin32_send(s, buf, len, flags)
-
-SOCKET pgwin32_socket(int af, int type, int protocol);
-int pgwin32_bind(SOCKET s, struct sockaddr * addr, int addrlen);
-int pgwin32_listen(SOCKET s, int backlog);
-SOCKET pgwin32_accept(SOCKET s, struct sockaddr * addr, int *addrlen);
-int pgwin32_connect(SOCKET s, const struct sockaddr * name, int namelen);
-int pgwin32_select(int nfds, fd_set *readfs, fd_set *writefds, fd_set *exceptfds, const struct timeval * timeout);
-int pgwin32_recv(SOCKET s, char *buf, int len, int flags);
-int pgwin32_send(SOCKET s, const void *buf, int len, int flags);
-
-const char *pgwin32_socket_strerror(int err);
-int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
-
-extern int pgwin32_noblock;
-
-#endif
-
-/* in backend/port/win32_shmem.c */
-extern int pgwin32_ReserveSharedMemoryRegion(HANDLE);
-
-/* in backend/port/win32/crashdump.c */
-extern void pgwin32_install_crashdump_handler(void);
-
-/* in port/win32error.c */
-extern void _dosmaperr(unsigned long);
-
-/* in port/win32env.c */
-extern int pgwin32_putenv(const char *);
-extern void pgwin32_unsetenv(const char *);
-
-/* in port/win32security.c */
-extern int pgwin32_is_service(void);
-extern int pgwin32_is_admin(void);
-
-#define putenv(x) pgwin32_putenv(x)
-#define unsetenv(x) pgwin32_unsetenv(x)
-
-/* Things that exist in MingW headers, but need to be added to MSVC & BCC */
-#ifdef WIN32_ONLY_COMPILER
-
-#ifndef _WIN64
-typedef long ssize_t;
-#else
-typedef __int64 ssize_t;
-#endif
-
-#ifndef __BORLANDC__
-typedef unsigned short mode_t;
-
-#define S_IRUSR _S_IREAD
-#define S_IWUSR _S_IWRITE
-#define S_IXUSR _S_IEXEC
-#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
-/* see also S_IRGRP etc below */
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif /* __BORLANDC__ */
-
-#define F_OK 0
-#define W_OK 2
-#define R_OK 4
-
-#if (_MSC_VER < 1800)
-#define isinf(x) ((_fpclass(x) == _FPCLASS_PINF) || (_fpclass(x) == _FPCLASS_NINF))
-#define isnan(x) _isnan(x)
-#endif
-
-/* Pulled from Makefile.port in mingw */
-#define DLSUFFIX ".dll"
-
-#ifdef __BORLANDC__
-
-/* for port/dirent.c */
-#ifndef INVALID_FILE_ATTRIBUTES
-#define INVALID_FILE_ATTRIBUTES ((DWORD) -1)
-#endif
-
-/* for port/open.c */
-#ifndef O_RANDOM
-#define O_RANDOM 0x0010 /* File access is primarily random */
-#define O_SEQUENTIAL 0x0020 /* File access is primarily sequential */
-#define O_TEMPORARY 0x0040 /* Temporary file bit */
-#define O_SHORT_LIVED 0x1000 /* Temporary storage file, try not to flush */
-#define _O_SHORT_LIVED O_SHORT_LIVED
-#endif /* ifndef O_RANDOM */
-#endif /* __BORLANDC__ */
-#endif /* WIN32_ONLY_COMPILER */
-
-/* These aren't provided by either MingW or MSVC */
-#ifndef __BORLANDC__
-#define S_IRGRP 0
-#define S_IWGRP 0
-#define S_IXGRP 0
-#define S_IRWXG 0
-#define S_IROTH 0
-#define S_IWOTH 0
-#define S_IXOTH 0
-#define S_IRWXO 0
-
-#endif /* __BORLANDC__ */
diff --git a/libpq/postgresql/port/win32/pthread-win32.h b/libpq/postgresql/port/win32/pthread-win32.h
deleted file mode 100644
index 97ccc17..0000000
--- a/libpq/postgresql/port/win32/pthread-win32.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * src/port/pthread-win32.h
- */
-#ifndef __PTHREAD_H
-#define __PTHREAD_H
-
-typedef ULONG pthread_key_t;
-typedef CRITICAL_SECTION *pthread_mutex_t;
-typedef int pthread_once_t;
-
-DWORD pthread_self(void);
-
-void pthread_setspecific(pthread_key_t, void *);
-void *pthread_getspecific(pthread_key_t);
-
-int pthread_mutex_init(pthread_mutex_t *, void *attr);
-int pthread_mutex_lock(pthread_mutex_t *);
-
-/* blocking */
-int pthread_mutex_unlock(pthread_mutex_t *);
-
-#endif
diff --git a/libpq/postgresql/port/win32/pwd.h b/libpq/postgresql/port/win32/pwd.h
deleted file mode 100644
index b8c7178..0000000
--- a/libpq/postgresql/port/win32/pwd.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * src/include/port/win32/pwd.h
- */
diff --git a/libpq/postgresql/port/win32/sys/socket.h b/libpq/postgresql/port/win32/sys/socket.h
deleted file mode 100644
index edaee6a..0000000
--- a/libpq/postgresql/port/win32/sys/socket.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * src/include/port/win32/sys/socket.h
- */
-#ifndef WIN32_SYS_SOCKET_H
-#define WIN32_SYS_SOCKET_H
-
-/*
- * Unfortunately, <wingdi.h> of VC++ also defines ERROR.
- * To avoid the conflict, we include <windows.h> here and undefine ERROR
- * immediately.
- *
- * Note: Don't include <wingdi.h> directly. It causes compile errors.
- */
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-
-#undef ERROR
-#undef small
-
-/* Restore old ERROR value */
-#ifdef PGERROR
-#define ERROR PGERROR
-#endif
-
-/*
- * we can't use the windows gai_strerror{AW} functions because
- * they are defined inline in the MS header files. So we'll use our
- * own
- */
-#undef gai_strerror
-
-#endif /* WIN32_SYS_SOCKET_H */
diff --git a/libpq/postgresql/port/win32/sys/wait.h b/libpq/postgresql/port/win32/sys/wait.h
deleted file mode 100644
index eaeb566..0000000
--- a/libpq/postgresql/port/win32/sys/wait.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * src/include/port/win32/sys/wait.h
- */
diff --git a/libpq/postgresql/port/win32_msvc/sys/file.h b/libpq/postgresql/port/win32_msvc/sys/file.h
deleted file mode 100644
index 76be3e7..0000000
--- a/libpq/postgresql/port/win32_msvc/sys/file.h
+++ /dev/null
@@ -1 +0,0 @@
-/* src/include/port/win32_msvc/sys/file.h */
diff --git a/libpq/postgresql/port/win32_msvc/sys/param.h b/libpq/postgresql/port/win32_msvc/sys/param.h
deleted file mode 100644
index 160df3b..0000000
--- a/libpq/postgresql/port/win32_msvc/sys/param.h
+++ /dev/null
@@ -1 +0,0 @@
-/* src/include/port/win32_msvc/sys/param.h */
diff --git a/libpq/postgresql/port/win32_msvc/sys/time.h b/libpq/postgresql/port/win32_msvc/sys/time.h
deleted file mode 100644
index 9d943ec..0000000
--- a/libpq/postgresql/port/win32_msvc/sys/time.h
+++ /dev/null
@@ -1 +0,0 @@
-/* src/include/port/win32_msvc/sys/time.h */
diff --git a/libpq/postgresql/port/win32_msvc/unistd.h b/libpq/postgresql/port/win32_msvc/unistd.h
deleted file mode 100644
index b63f477..0000000
--- a/libpq/postgresql/port/win32_msvc/unistd.h
+++ /dev/null
@@ -1 +0,0 @@
-/* src/include/port/win32_msvc/unistd.h */
diff --git a/libpq/postgresql/postgres_ext.h b/libpq/postgresql/postgres_ext.h
deleted file mode 100644
index ae2f087..0000000
--- a/libpq/postgresql/postgres_ext.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * postgres_ext.h
- *
- * This file contains declarations of things that are visible everywhere
- * in PostgreSQL *and* are visible to clients of frontend interface libraries.
- * For example, the Oid type is part of the API of libpq and other libraries.
- *
- * Declarations which are specific to a particular interface should
- * go in the header file for that interface (such as libpq-fe.h). This
- * file is only for fundamental Postgres declarations.
- *
- * User-written C functions don't count as "external to Postgres."
- * Those function much as local modifications to the backend itself, and
- * use header files that are otherwise internal to Postgres to interface
- * with the backend.
- *
- * src/include/postgres_ext.h
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef POSTGRES_EXT_H
-#define POSTGRES_EXT_H
-
-#include "pg_config_ext.h"
-
-/*
- * Object ID is a fundamental type in Postgres.
- */
-typedef unsigned int Oid;
-
-#ifdef __cplusplus
-#define InvalidOid (Oid(0))
-#else
-#define InvalidOid ((Oid) 0)
-#endif
-
-#define OID_MAX UINT_MAX
-/* you will need to include <limits.h> to use the above #define */
-
-/* Define a signed 64-bit integer type for use in client API declarations. */
-typedef PG_INT64_TYPE pg_int64;
-
-
-/*
- * Identifiers of error message fields. Kept here to keep common
- * between frontend and backend, and also to export them to libpq
- * applications.
- */
-#define PG_DIAG_SEVERITY 'S'
-#define PG_DIAG_SEVERITY_NONLOCALIZED 'V'
-#define PG_DIAG_SQLSTATE 'C'
-#define PG_DIAG_MESSAGE_PRIMARY 'M'
-#define PG_DIAG_MESSAGE_DETAIL 'D'
-#define PG_DIAG_MESSAGE_HINT 'H'
-#define PG_DIAG_STATEMENT_POSITION 'P'
-#define PG_DIAG_INTERNAL_POSITION 'p'
-#define PG_DIAG_INTERNAL_QUERY 'q'
-#define PG_DIAG_CONTEXT 'W'
-#define PG_DIAG_SCHEMA_NAME 's'
-#define PG_DIAG_TABLE_NAME 't'
-#define PG_DIAG_COLUMN_NAME 'c'
-#define PG_DIAG_DATATYPE_NAME 'd'
-#define PG_DIAG_CONSTRAINT_NAME 'n'
-#define PG_DIAG_SOURCE_FILE 'F'
-#define PG_DIAG_SOURCE_LINE 'L'
-#define PG_DIAG_SOURCE_FUNCTION 'R'
-
-#endif /* POSTGRES_EXT_H */
diff --git a/libpq/postgresql/postgres_fe.h b/libpq/postgresql/postgres_fe.h
deleted file mode 100644
index 69c0ad8..0000000
--- a/libpq/postgresql/postgres_fe.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * postgres_fe.h
- * Primary include file for PostgreSQL client-side .c files
- *
- * This should be the first file included by PostgreSQL client libraries and
- * application programs --- but not by backend modules, which should include
- * postgres.h.
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1995, Regents of the University of California
- *
- * src/include/postgres_fe.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef POSTGRES_FE_H
-#define POSTGRES_FE_H
-
-#ifndef FRONTEND
-#define FRONTEND 1
-#endif
-
-#include "c.h"
-
-#include "common/fe_memutils.h"
-
-#endif /* POSTGRES_FE_H */
diff --git a/libpq/pqexpbuffer.c b/libpq/pqexpbuffer.c
deleted file mode 100644
index 8d82d5c..0000000
--- a/libpq/pqexpbuffer.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pqexpbuffer.c
- *
- * PQExpBuffer provides an indefinitely-extensible string data type.
- * It can be used to buffer either ordinary C strings (null-terminated text)
- * or arbitrary binary data. All storage is allocated with malloc().
- *
- * This module is essentially the same as the backend's StringInfo data type,
- * but it is intended for use in frontend libpq and client applications.
- * Thus, it does not rely on palloc() nor elog(), nor psprintf.c which
- * will exit() on error.
- *
- * It does rely on vsnprintf(); if configure finds that libc doesn't provide
- * a usable vsnprintf(), then a copy of our own implementation of it will
- * be linked into libpq.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/interfaces/libpq/pqexpbuffer.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres_fe.h"
-
-#include <limits.h>
-
-#include "pqexpbuffer.h"
-
-#ifdef WIN32
-#include "win32.h"
-#endif
-
-
-/* All "broken" PQExpBuffers point to this string. */
-static const char oom_buffer[1] = "";
-
-static bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args) pg_attribute_printf(2, 0);
-
-
-/*
- * markPQExpBufferBroken
- *
- * Put a PQExpBuffer in "broken" state if it isn't already.
- */
-static void
-markPQExpBufferBroken(PQExpBuffer str)
-{
- if (str->data != oom_buffer)
- free(str->data);
-
- /*
- * Casting away const here is a bit ugly, but it seems preferable to not
- * marking oom_buffer const. We want to do that to encourage the compiler
- * to put oom_buffer in read-only storage, so that anyone who tries to
- * scribble on a broken PQExpBuffer will get a failure.
- */
- str->data = (char *) oom_buffer;
- str->len = 0;
- str->maxlen = 0;
-}
-
-/*
- * createPQExpBuffer
- *
- * Create an empty 'PQExpBufferData' & return a pointer to it.
- */
-PQExpBuffer
-createPQExpBuffer(void)
-{
- PQExpBuffer res;
-
- res = (PQExpBuffer) malloc(sizeof(PQExpBufferData));
- if (res != NULL)
- initPQExpBuffer(res);
-
- return res;
-}
-
-/*
- * initPQExpBuffer
- *
- * Initialize a PQExpBufferData struct (with previously undefined contents)
- * to describe an empty string.
- */
-void
-initPQExpBuffer(PQExpBuffer str)
-{
- str->data = (char *) malloc(INITIAL_EXPBUFFER_SIZE);
- if (str->data == NULL)
- {
- str->data = (char *) oom_buffer; /* see comment above */
- str->maxlen = 0;
- str->len = 0;
- }
- else
- {
- str->maxlen = INITIAL_EXPBUFFER_SIZE;
- str->len = 0;
- str->data[0] = '\0';
- }
-}
-
-/*
- * destroyPQExpBuffer(str);
- *
- * free()s both the data buffer and the PQExpBufferData.
- * This is the inverse of createPQExpBuffer().
- */
-void
-destroyPQExpBuffer(PQExpBuffer str)
-{
- if (str)
- {
- termPQExpBuffer(str);
- free(str);
- }
-}
-
-/*
- * termPQExpBuffer(str)
- * free()s the data buffer but not the PQExpBufferData itself.
- * This is the inverse of initPQExpBuffer().
- */
-void
-termPQExpBuffer(PQExpBuffer str)
-{
- if (str->data != oom_buffer)
- free(str->data);
- /* just for luck, make the buffer validly empty. */
- str->data = (char *) oom_buffer; /* see comment above */
- str->maxlen = 0;
- str->len = 0;
-}
-
-/*
- * resetPQExpBuffer
- * Reset a PQExpBuffer to empty
- *
- * Note: if possible, a "broken" PQExpBuffer is returned to normal.
- */
-void
-resetPQExpBuffer(PQExpBuffer str)
-{
- if (str)
- {
- if (str->data != oom_buffer)
- {
- str->len = 0;
- str->data[0] = '\0';
- }
- else
- {
- /* try to reinitialize to valid state */
- initPQExpBuffer(str);
- }
- }
-}
-
-/*
- * enlargePQExpBuffer
- * Make sure there is enough space for 'needed' more bytes in the buffer
- * ('needed' does not include the terminating null).
- *
- * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case
- * the buffer is left in "broken" state.)
- */
-int
-enlargePQExpBuffer(PQExpBuffer str, size_t needed)
-{
- size_t newlen;
- char *newdata;
-
- if (PQExpBufferBroken(str))
- return 0; /* already failed */
-
- /*
- * Guard against ridiculous "needed" values, which can occur if we're fed
- * bogus data. Without this, we can get an overflow or infinite loop in
- * the following.
- */
- if (needed >= ((size_t) INT_MAX - str->len))
- {
- markPQExpBufferBroken(str);
- return 0;
- }
-
- needed += str->len + 1; /* total space required now */
-
- /* Because of the above test, we now have needed <= INT_MAX */
-
- if (needed <= str->maxlen)
- return 1; /* got enough space already */
-
- /*
- * We don't want to allocate just a little more space with each append;
- * for efficiency, double the buffer size each time it overflows.
- * Actually, we might need to more than double it if 'needed' is big...
- */
- newlen = (str->maxlen > 0) ? (2 * str->maxlen) : 64;
- while (needed > newlen)
- newlen = 2 * newlen;
-
- /*
- * Clamp to INT_MAX in case we went past it. Note we are assuming here
- * that INT_MAX <= UINT_MAX/2, else the above loop could overflow. We
- * will still have newlen >= needed.
- */
- if (newlen > (size_t) INT_MAX)
- newlen = (size_t) INT_MAX;
-
- newdata = (char *) realloc(str->data, newlen);
- if (newdata != NULL)
- {
- str->data = newdata;
- str->maxlen = newlen;
- return 1;
- }
-
- markPQExpBufferBroken(str);
- return 0;
-}
-
-/*
- * printfPQExpBuffer
- * Format text data under the control of fmt (an sprintf-like format string)
- * and insert it into str. More space is allocated to str if necessary.
- * This is a convenience routine that does the same thing as
- * resetPQExpBuffer() followed by appendPQExpBuffer().
- */
-void
-printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
-{
- va_list args;
- bool done;
-
- resetPQExpBuffer(str);
-
- if (PQExpBufferBroken(str))
- return; /* already failed */
-
- /* Loop in case we have to retry after enlarging the buffer. */
- do
- {
- va_start(args, fmt);
- done = appendPQExpBufferVA(str, fmt, args);
- va_end(args);
- } while (!done);
-}
-
-/*
- * appendPQExpBuffer
- *
- * Format text data under the control of fmt (an sprintf-like format string)
- * and append it to whatever is already in str. More space is allocated
- * to str if necessary. This is sort of like a combination of sprintf and
- * strcat.
- */
-void
-appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
-{
- va_list args;
- bool done;
-
- if (PQExpBufferBroken(str))
- return; /* already failed */
-
- /* Loop in case we have to retry after enlarging the buffer. */
- do
- {
- va_start(args, fmt);
- done = appendPQExpBufferVA(str, fmt, args);
- va_end(args);
- } while (!done);
-}
-
-/*
- * appendPQExpBufferVA
- * Shared guts of printfPQExpBuffer/appendPQExpBuffer.
- * Attempt to format data and append it to str. Returns true if done
- * (either successful or hard failure), false if need to retry.
- */
-static bool
-appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args)
-{
- size_t avail;
- size_t needed;
- int nprinted;
-
- /*
- * Try to format the given string into the available space; but if there's
- * hardly any space, don't bother trying, just enlarge the buffer first.
- */
- if (str->maxlen > str->len + 16)
- {
- /*
- * Note: we intentionally leave one byte unused, as a guard against
- * old broken versions of vsnprintf.
- */
- avail = str->maxlen - str->len - 1;
-
- errno = 0;
-
- nprinted = vsnprintf(str->data + str->len, avail, fmt, args);
-
- /*
- * If vsnprintf reports an error other than ENOMEM, fail.
- */
- if (nprinted < 0 && errno != 0 && errno != ENOMEM)
- {
- markPQExpBufferBroken(str);
- return true;
- }
-
- /*
- * Note: some versions of vsnprintf return the number of chars
- * actually stored, not the total space needed as C99 specifies. And
- * at least one returns -1 on failure. Be conservative about
- * believing whether the print worked.
- */
- if (nprinted >= 0 && (size_t) nprinted < avail - 1)
- {
- /* Success. Note nprinted does not include trailing null. */
- str->len += nprinted;
- return true;
- }
-
- if (nprinted >= 0 && (size_t) nprinted > avail)
- {
- /*
- * This appears to be a C99-compliant vsnprintf, so believe its
- * estimate of the required space. (If it's wrong, the logic will
- * still work, but we may loop multiple times.) Note that the
- * space needed should be only nprinted+1 bytes, but we'd better
- * allocate one more than that so that the test above will succeed
- * next time.
- *
- * In the corner case where the required space just barely
- * overflows, fail.
- */
- if (nprinted > INT_MAX - 2)
- {
- markPQExpBufferBroken(str);
- return true;
- }
- needed = nprinted + 2;
- }
- else
- {
- /*
- * Buffer overrun, and we don't know how much space is needed.
- * Estimate twice the previous buffer size, but not more than
- * INT_MAX.
- */
- if (avail >= INT_MAX / 2)
- needed = INT_MAX;
- else
- needed = avail * 2;
- }
- }
- else
- {
- /*
- * We have to guess at how much to enlarge, since we're skipping the
- * formatting work.
- */
- needed = 32;
- }
-
- /* Increase the buffer size and try again. */
- if (!enlargePQExpBuffer(str, needed))
- return true; /* oops, out of memory */
-
- return false;
-}
-
-/*
- * appendPQExpBufferStr
- * Append the given string to a PQExpBuffer, allocating more space
- * if necessary.
- */
-void
-appendPQExpBufferStr(PQExpBuffer str, const char *data)
-{
- appendBinaryPQExpBuffer(str, data, strlen(data));
-}
-
-/*
- * appendPQExpBufferChar
- * Append a single byte to str.
- * Like appendPQExpBuffer(str, "%c", ch) but much faster.
- */
-void
-appendPQExpBufferChar(PQExpBuffer str, char ch)
-{
- /* Make more room if needed */
- if (!enlargePQExpBuffer(str, 1))
- return;
-
- /* OK, append the character */
- str->data[str->len] = ch;
- str->len++;
- str->data[str->len] = '\0';
-}
-
-/*
- * appendBinaryPQExpBuffer
- *
- * Append arbitrary binary data to a PQExpBuffer, allocating more space
- * if necessary.
- */
-void
-appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
-{
- /* Make more room if needed */
- if (!enlargePQExpBuffer(str, datalen))
- return;
-
- /* OK, append the data */
- memcpy(str->data + str->len, data, datalen);
- str->len += datalen;
-
- /*
- * Keep a trailing null in place, even though it's probably useless for
- * binary data...
- */
- str->data[str->len] = '\0';
-}
diff --git a/libpq/pqexpbuffer.h b/libpq/pqexpbuffer.h
deleted file mode 100644
index ce87cd5..0000000
--- a/libpq/pqexpbuffer.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pqexpbuffer.h
- * Declarations/definitions for "PQExpBuffer" functions.
- *
- * PQExpBuffer provides an indefinitely-extensible string data type.
- * It can be used to buffer either ordinary C strings (null-terminated text)
- * or arbitrary binary data. All storage is allocated with malloc().
- *
- * This module is essentially the same as the backend's StringInfo data type,
- * but it is intended for use in frontend libpq and client applications.
- * Thus, it does not rely on palloc() nor elog().
- *
- * It does rely on vsnprintf(); if configure finds that libc doesn't provide
- * a usable vsnprintf(), then a copy of our own implementation of it will
- * be linked into libpq.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/interfaces/libpq/pqexpbuffer.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PQEXPBUFFER_H
-#define PQEXPBUFFER_H
-
-/*-------------------------
- * PQExpBufferData holds information about an extensible string.
- * data is the current buffer for the string (allocated with malloc).
- * len is the current string length. There is guaranteed to be
- * a terminating '\0' at data[len], although this is not very
- * useful when the string holds binary data rather than text.
- * maxlen is the allocated size in bytes of 'data', i.e. the maximum
- * string size (including the terminating '\0' char) that we can
- * currently store in 'data' without having to reallocate
- * more space. We must always have maxlen > len.
- *
- * An exception occurs if we failed to allocate enough memory for the string
- * buffer. In that case data points to a statically allocated empty string,
- * and len = maxlen = 0.
- *-------------------------
- */
-typedef struct PQExpBufferData
-{
- char *data;
- size_t len;
- size_t maxlen;
-} PQExpBufferData;
-
-typedef PQExpBufferData *PQExpBuffer;
-
-/*------------------------
- * Test for a broken (out of memory) PQExpBuffer.
- * When a buffer is "broken", all operations except resetting or deleting it
- * are no-ops.
- *------------------------
- */
-#define PQExpBufferBroken(str) \
- ((str) == NULL || (str)->maxlen == 0)
-
-/*------------------------
- * Same, but for use when using a static or local PQExpBufferData struct.
- * For that, a null-pointer test is useless and may draw compiler warnings.
- *------------------------
- */
-#define PQExpBufferDataBroken(buf) \
- ((buf).maxlen == 0)
-
-/*------------------------
- * Initial size of the data buffer in a PQExpBuffer.
- * NB: this must be large enough to hold error messages that might
- * be returned by PQrequestCancel().
- *------------------------
- */
-#define INITIAL_EXPBUFFER_SIZE 256
-
-/*------------------------
- * There are two ways to create a PQExpBuffer object initially:
- *
- * PQExpBuffer stringptr = createPQExpBuffer();
- * Both the PQExpBufferData and the data buffer are malloc'd.
- *
- * PQExpBufferData string;
- * initPQExpBuffer(&string);
- * The data buffer is malloc'd but the PQExpBufferData is presupplied.
- * This is appropriate if the PQExpBufferData is a field of another
- * struct.
- *-------------------------
- */
-
-/*------------------------
- * createPQExpBuffer
- * Create an empty 'PQExpBufferData' & return a pointer to it.
- */
-extern PQExpBuffer createPQExpBuffer(void);
-
-/*------------------------
- * initPQExpBuffer
- * Initialize a PQExpBufferData struct (with previously undefined contents)
- * to describe an empty string.
- */
-extern void initPQExpBuffer(PQExpBuffer str);
-
-/*------------------------
- * To destroy a PQExpBuffer, use either:
- *
- * destroyPQExpBuffer(str);
- * free()s both the data buffer and the PQExpBufferData.
- * This is the inverse of createPQExpBuffer().
- *
- * termPQExpBuffer(str)
- * free()s the data buffer but not the PQExpBufferData itself.
- * This is the inverse of initPQExpBuffer().
- *
- * NOTE: some routines build up a string using PQExpBuffer, and then
- * release the PQExpBufferData but return the data string itself to their
- * caller. At that point the data string looks like a plain malloc'd
- * string.
- */
-extern void destroyPQExpBuffer(PQExpBuffer str);
-extern void termPQExpBuffer(PQExpBuffer str);
-
-/*------------------------
- * resetPQExpBuffer
- * Reset a PQExpBuffer to empty
- *
- * Note: if possible, a "broken" PQExpBuffer is returned to normal.
- */
-extern void resetPQExpBuffer(PQExpBuffer str);
-
-/*------------------------
- * enlargePQExpBuffer
- * Make sure there is enough space for 'needed' more bytes in the buffer
- * ('needed' does not include the terminating null).
- *
- * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case
- * the buffer is left in "broken" state.)
- */
-extern int enlargePQExpBuffer(PQExpBuffer str, size_t needed);
-
-/*------------------------
- * printfPQExpBuffer
- * Format text data under the control of fmt (an sprintf-like format string)
- * and insert it into str. More space is allocated to str if necessary.
- * This is a convenience routine that does the same thing as
- * resetPQExpBuffer() followed by appendPQExpBuffer().
- */
-extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3);
-
-/*------------------------
- * appendPQExpBuffer
- * Format text data under the control of fmt (an sprintf-like format string)
- * and append it to whatever is already in str. More space is allocated
- * to str if necessary. This is sort of like a combination of sprintf and
- * strcat.
- */
-extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3);
-
-/*------------------------
- * appendPQExpBufferStr
- * Append the given string to a PQExpBuffer, allocating more space
- * if necessary.
- */
-extern void appendPQExpBufferStr(PQExpBuffer str, const char *data);
-
-/*------------------------
- * appendPQExpBufferChar
- * Append a single byte to str.
- * Like appendPQExpBuffer(str, "%c", ch) but much faster.
- */
-extern void appendPQExpBufferChar(PQExpBuffer str, char ch);
-
-/*------------------------
- * appendBinaryPQExpBuffer
- * Append arbitrary binary data to a PQExpBuffer, allocating more space
- * if necessary.
- */
-extern void appendBinaryPQExpBuffer(PQExpBuffer str,
- const char *data, size_t datalen);
-
-#endif /* PQEXPBUFFER_H */
diff --git a/libpq/pqsignal.c b/libpq/pqsignal.c
deleted file mode 100644
index 07797f9..0000000
--- a/libpq/pqsignal.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pqsignal.c
- * reliable BSD-style signal(2) routine stolen from RWW who stole it
- * from Stevens...
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/port/pqsignal.c
- *
- * We now assume that all Unix-oid systems have POSIX sigaction(2)
- * with support for restartable signals (SA_RESTART). We used to also
- * support BSD-style signal(2), but there really shouldn't be anything
- * out there anymore that doesn't have the POSIX API.
- *
- * Windows, of course, is resolutely in a class by itself. In the backend,
- * we don't use this file at all; src/backend/port/win32/signal.c provides
- * pqsignal() for the backend environment. Frontend programs can use
- * this version of pqsignal() if they wish, but beware that this does
- * not provide restartable signals on Windows.
- *
- * ------------------------------------------------------------------------
- */
-
-#include "c.h"
-
-#include <signal.h>
-
-#if !defined(WIN32) || defined(FRONTEND)
-
-/*
- * Set up a signal handler, with SA_RESTART, for signal "signo"
- *
- * Returns the previous handler.
- */
-pqsigfunc
-pqsignal(int signo, pqsigfunc func)
-{
-#ifndef WIN32
- struct sigaction act,
- oact;
-
- act.sa_handler = func;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_RESTART;
-#ifdef SA_NOCLDSTOP
- if (signo == SIGCHLD)
- act.sa_flags |= SA_NOCLDSTOP;
-#endif
- if (sigaction(signo, &act, &oact) < 0)
- return SIG_ERR;
- return oact.sa_handler;
-#else /* WIN32 */
- return signal(signo, func);
-#endif
-}
-
-/*
- * Set up a signal handler, without SA_RESTART, for signal "signo"
- *
- * Returns the previous handler.
- *
- * On Windows, this would be identical to pqsignal(), so don't bother.
- */
-#ifndef WIN32
-
-pqsigfunc
-pqsignal_no_restart(int signo, pqsigfunc func)
-{
- struct sigaction act,
- oact;
-
- act.sa_handler = func;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
-#ifdef SA_NOCLDSTOP
- if (signo == SIGCHLD)
- act.sa_flags |= SA_NOCLDSTOP;
-#endif
- if (sigaction(signo, &act, &oact) < 0)
- return SIG_ERR;
- return oact.sa_handler;
-}
-
-#endif /* !WIN32 */
-
-#endif /* !defined(WIN32) || defined(FRONTEND) */
diff --git a/tests/.gitignore b/libpq/tests/.gitignore
index 2e508a9..2e508a9 100644
--- a/tests/.gitignore
+++ b/libpq/tests/.gitignore
diff --git a/tests/build/.gitignore b/libpq/tests/build/.gitignore
index 4a730a3..4a730a3 100644
--- a/tests/build/.gitignore
+++ b/libpq/tests/build/.gitignore
diff --git a/tests/build/bootstrap.build b/libpq/tests/build/bootstrap.build
index 6212d9b..6212d9b 100644
--- a/tests/build/bootstrap.build
+++ b/libpq/tests/build/bootstrap.build
diff --git a/tests/build/root.build b/libpq/tests/build/root.build
index aeccdd9..e374ddd 100644
--- a/tests/build/root.build
+++ b/libpq/tests/build/root.build
@@ -2,8 +2,6 @@
# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
# license : PostgreSQL License; see accompanying COPYRIGHT file
-c.std = 99
-
using c
h{*}: extension = h
diff --git a/tests/buildfile b/libpq/tests/buildfile
index 098486c..098486c 100644
--- a/tests/buildfile
+++ b/libpq/tests/buildfile
diff --git a/tests/conninfo/buildfile b/libpq/tests/conninfo/buildfile
index 1a600e9..d9d4bab 100644
--- a/tests/conninfo/buildfile
+++ b/libpq/tests/conninfo/buildfile
@@ -2,8 +2,8 @@
# copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
# license : PostgreSQL License; see accompanying COPYRIGHT file
-# Here we reproduce the original libpq test. See the src/interfaces/libpq/test
-# directory of the original package for details.
+# Here we reproduce the upstream's libpq test. See the
+# src/interfaces/libpq/test/ in the upstream package for details.
#
import libs = libpq%lib{pq}
diff --git a/tests/conninfo/driver.c b/libpq/tests/conninfo/driver.c
index 65d9269..1a13af2 100644
--- a/tests/conninfo/driver.c
+++ b/libpq/tests/conninfo/driver.c
@@ -4,7 +4,7 @@
*/
/*
- * Include the original package test and rename it's main() function to test()
+ * Include the upstream package test and rename it's main() function to test()
* (see below for details).
*/
#define main test
@@ -25,7 +25,7 @@
/*
* Usage: argv[0]
*
- * Read connection info strings from STDIN and call original test main()
+ * Read connection info strings from STDIN and call upstream test main()
* function for each of them. The function prints the parsed connection info to
* stdout on success or error message to stderr on failure.
*/
diff --git a/tests/conninfo/expected.out b/libpq/tests/conninfo/expected.out
index d375e82..d375e82 100644
--- a/tests/conninfo/expected.out
+++ b/libpq/tests/conninfo/expected.out
diff --git a/libpq/tests/conninfo/postgres_fe.h b/libpq/tests/conninfo/postgres_fe.h
new file mode 100644
index 0000000..0dd2ed2
--- /dev/null
+++ b/libpq/tests/conninfo/postgres_fe.h
@@ -0,0 +1,19 @@
+/* file : tests/conninfo/postgres_fe.h
+ * copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
+ * license : PostgreSQL License; see accompanying COPYRIGHT file
+ */
+
+/*
+ * The upstream's uri-regress.c includes src/include/postgres_fe.h that is
+ * located in libpq/include/ in our source tree. This file is not installed,
+ * so to keep the test as a subproject and be able to test against the
+ * installed libpq library we replace it with the header stub, containing the
+ * bare minimum that is required the test to compile.
+ */
+#ifndef TESTS_CONNINFO_POSTGRES_FE_H
+#define TESTS_CONNINFO_POSTGRES_FE_H
+
+#include <stdbool.h>
+#include <string.h>
+
+#endif /* TESTS_CONNINFO_POSTGRES_FE_H */
diff --git a/tests/conninfo/regress.in b/libpq/tests/conninfo/regress.in
index de034f3..de034f3 100644
--- a/tests/conninfo/regress.in
+++ b/libpq/tests/conninfo/regress.in
diff --git a/tests/conninfo/testscript b/libpq/tests/conninfo/testscript
index bf278ae..bf278ae 100644
--- a/tests/conninfo/testscript
+++ b/libpq/tests/conninfo/testscript
diff --git a/libpq/tests/conninfo/uri-regress.c b/libpq/tests/conninfo/uri-regress.c
new file mode 120000
index 0000000..fbab965
--- /dev/null
+++ b/libpq/tests/conninfo/uri-regress.c
@@ -0,0 +1 @@
+../../../upstream/src/interfaces/libpq/test/uri-regress.c \ No newline at end of file
diff --git a/libpq/thread.c b/libpq/thread.c
deleted file mode 100644
index ed908ba..0000000
--- a/libpq/thread.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * thread.c
- *
- * Prototypes and macros around system calls, used to help make
- * threaded libraries reentrant and safe to use from threaded applications.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- * src/port/thread.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "c.h"
-
-#include <pwd.h>
-
-
-/*
- * Threading sometimes requires specially-named versions of functions
- * that return data in static buffers, like strerror_r() instead of
- * strerror(). Other operating systems use pthread_setspecific()
- * and pthread_getspecific() internally to allow standard library
- * functions to return static data to threaded applications. And some
- * operating systems have neither.
- *
- * Additional confusion exists because many operating systems that
- * use pthread_setspecific/pthread_getspecific() also have *_r versions
- * of standard library functions for compatibility with operating systems
- * that require them. However, internally, these *_r functions merely
- * call the thread-safe standard library functions.
- *
- * For example, BSD/OS 4.3 uses Bind 8.2.3 for getpwuid(). Internally,
- * getpwuid() calls pthread_setspecific/pthread_getspecific() to return
- * static data to the caller in a thread-safe manner. However, BSD/OS
- * also has getpwuid_r(), which merely calls getpwuid() and shifts
- * around the arguments to match the getpwuid_r() function declaration.
- * Therefore, while BSD/OS has getpwuid_r(), it isn't required. It also
- * doesn't have strerror_r(), so we can't fall back to only using *_r
- * functions for threaded programs.
- *
- * The current setup is to try threading in this order:
- *
- * use *_r function names if they exit
- * (*_THREADSAFE=yes)
- * use non-*_r functions if they are thread-safe
- *
- * One thread-safe solution for gethostbyname() might be to use getaddrinfo().
- *
- * Run src/test/thread to test if your operating system has thread-safe
- * non-*_r functions.
- */
-
-
-/*
- * Wrapper around strerror and strerror_r to use the former if it is
- * available and also return a more useful value (the error string).
- */
-char *
-pqStrerror(int errnum, char *strerrbuf, size_t buflen)
-{
-#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_STRERROR_R)
- /* reentrant strerror_r is available */
-#ifdef STRERROR_R_INT
- /* SUSv3 version */
- if (strerror_r(errnum, strerrbuf, buflen) == 0)
- return strerrbuf;
- else
- return "Unknown error";
-#else
- /* GNU libc */
- return strerror_r(errnum, strerrbuf, buflen);
-#endif
-#else
- /* no strerror_r() available, just use strerror */
- strlcpy(strerrbuf, strerror(errnum), buflen);
-
- return strerrbuf;
-#endif
-}
-
-/*
- * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
- * behaviour, if that function is not available or required.
- *
- * Per POSIX, the possible cases are:
- * success: returns zero, *result is non-NULL
- * uid not found: returns zero, *result is NULL
- * error during lookup: returns an errno code, *result is NULL
- * (caller should *not* assume that the errno variable is set)
- */
-#ifndef WIN32
-int
-pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer,
- size_t buflen, struct passwd ** result)
-{
-#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETPWUID_R)
- return getpwuid_r(uid, resultbuf, buffer, buflen, result);
-#else
- /* no getpwuid_r() available, just use getpwuid() */
- errno = 0;
- *result = getpwuid(uid);
- /* paranoia: ensure we return zero on success */
- return (*result == NULL) ? errno : 0;
-#endif
-}
-#endif
-
-/*
- * Wrapper around gethostbyname() or gethostbyname_r() to mimic
- * POSIX gethostbyname_r() behaviour, if it is not available or required.
- * This function is called _only_ by our getaddinfo() portability function.
- */
-#ifndef HAVE_GETADDRINFO
-int
-pqGethostbyname(const char *name,
- struct hostent * resultbuf,
- char *buffer, size_t buflen,
- struct hostent ** result,
- int *herrno)
-{
-#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
-
- /*
- * broken (well early POSIX draft) gethostbyname_r() which returns 'struct
- * hostent *'
- */
- *result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno);
- return (*result == NULL) ? -1 : 0;
-#else
-
- /* no gethostbyname_r(), just use gethostbyname() */
- *result = gethostbyname(name);
-
- if (*result != NULL)
- *herrno = h_errno;
-
- if (*result != NULL)
- return 0;
- else
- return -1;
-#endif
-}
-
-#endif
diff --git a/libpq/version.h.in b/libpq/version.h.in
deleted file mode 100644
index af772da..0000000
--- a/libpq/version.h.in
+++ /dev/null
@@ -1,26 +0,0 @@
-/* file : libpq/version.h.in -*- C -*-
- * copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
- * license : PostgreSQL License; see accompanying COPYRIGHT file
- */
-
-#ifndef PG_MAJORVERSION /* Note: using the version macro itself. */
-
-/*
- * Note that staring PostgreSQL 10 the release version schema changed (see
- * build/bootstrap.build for details).
- */
-#if $libpq.version.major$ < 10
-# define PG_MAJORVERSION "$libpq.version.major$.$libpq.version.minor$"
-#else
-# error "change PG_MAJORVERSION macro definition"
-# define PG_MAJORVERSION "$libpq.version.major$"
-#endif
-
-/*
- * Is valid for both old and new version schemes (see above).
- */
-#define PG_VERSION_NUM (10000 * $libpq.version.major$ + \
- 100 * $libpq.version.minor$ + \
- $libpq.version.patch$)
-
-#endif /* PG_MAJORVERSION */
diff --git a/libpq/wchar.c b/libpq/wchar.c
deleted file mode 100644
index fd51eed..0000000
--- a/libpq/wchar.c
+++ /dev/null
@@ -1,2054 +0,0 @@
-/*
- * conversion functions between pg_wchar and multibyte streams.
- * Tatsuo Ishii
- * src/backend/utils/mb/wchar.c
- *
- */
-/* can be used in either frontend or backend */
-#ifdef FRONTEND
-#include "postgres_fe.h"
-#else
-#include "postgres.h"
-#endif
-
-#include "mb/pg_wchar.h"
-
-
-/*
- * conversion to pg_wchar is done by "table driven."
- * to add an encoding support, define mb2wchar_with_len(), mblen(), dsplen()
- * for the particular encoding. Note that if the encoding is only
- * supported in the client, you don't need to define
- * mb2wchar_with_len() function (SJIS is the case).
- *
- * These functions generally assume that their input is validly formed.
- * The "verifier" functions, further down in the file, have to be more
- * paranoid. We expect that mblen() does not need to examine more than
- * the first byte of the character to discover the correct length.
- *
- * Note: for the display output of psql to work properly, the return values
- * of the dsplen functions must conform to the Unicode standard. In particular
- * the NUL character is zero width and control characters are generally
- * width -1. It is recommended that non-ASCII encodings refer their ASCII
- * subset to the ASCII routines to ensure consistency.
- */
-
-/*
- * SQL/ASCII
- */
-static int
-pg_ascii2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- *to++ = *from++;
- len--;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-static int
-pg_ascii_mblen(const unsigned char *s)
-{
- return 1;
-}
-
-static int
-pg_ascii_dsplen(const unsigned char *s)
-{
- if (*s == '\0')
- return 0;
- if (*s < 0x20 || *s == 0x7f)
- return -1;
-
- return 1;
-}
-
-/*
- * EUC
- */
-static int
-pg_euc2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- if (*from == SS2 && len >= 2) /* JIS X 0201 (so called "1 byte
- * KANA") */
- {
- from++;
- *to = (SS2 << 8) | *from++;
- len -= 2;
- }
- else if (*from == SS3 && len >= 3) /* JIS X 0212 KANJI */
- {
- from++;
- *to = (SS3 << 16) | (*from++ << 8);
- *to |= *from++;
- len -= 3;
- }
- else if (IS_HIGHBIT_SET(*from) && len >= 2) /* JIS X 0208 KANJI */
- {
- *to = *from++ << 8;
- *to |= *from++;
- len -= 2;
- }
- else /* must be ASCII */
- {
- *to = *from++;
- len--;
- }
- to++;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-static inline int
-pg_euc_mblen(const unsigned char *s)
-{
- int len;
-
- if (*s == SS2)
- len = 2;
- else if (*s == SS3)
- len = 3;
- else if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = 1;
- return len;
-}
-
-static inline int
-pg_euc_dsplen(const unsigned char *s)
-{
- int len;
-
- if (*s == SS2)
- len = 2;
- else if (*s == SS3)
- len = 2;
- else if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = pg_ascii_dsplen(s);
- return len;
-}
-
-/*
- * EUC_JP
- */
-static int
-pg_eucjp2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- return pg_euc2wchar_with_len(from, to, len);
-}
-
-static int
-pg_eucjp_mblen(const unsigned char *s)
-{
- return pg_euc_mblen(s);
-}
-
-static int
-pg_eucjp_dsplen(const unsigned char *s)
-{
- int len;
-
- if (*s == SS2)
- len = 1;
- else if (*s == SS3)
- len = 2;
- else if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = pg_ascii_dsplen(s);
- return len;
-}
-
-/*
- * EUC_KR
- */
-static int
-pg_euckr2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- return pg_euc2wchar_with_len(from, to, len);
-}
-
-static int
-pg_euckr_mblen(const unsigned char *s)
-{
- return pg_euc_mblen(s);
-}
-
-static int
-pg_euckr_dsplen(const unsigned char *s)
-{
- return pg_euc_dsplen(s);
-}
-
-/*
- * EUC_CN
- *
- */
-static int
-pg_euccn2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- if (*from == SS2 && len >= 3) /* code set 2 (unused?) */
- {
- from++;
- *to = (SS2 << 16) | (*from++ << 8);
- *to |= *from++;
- len -= 3;
- }
- else if (*from == SS3 && len >= 3) /* code set 3 (unused ?) */
- {
- from++;
- *to = (SS3 << 16) | (*from++ << 8);
- *to |= *from++;
- len -= 3;
- }
- else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 1 */
- {
- *to = *from++ << 8;
- *to |= *from++;
- len -= 2;
- }
- else
- {
- *to = *from++;
- len--;
- }
- to++;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-static int
-pg_euccn_mblen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = 1;
- return len;
-}
-
-static int
-pg_euccn_dsplen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = pg_ascii_dsplen(s);
- return len;
-}
-
-/*
- * EUC_TW
- *
- */
-static int
-pg_euctw2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- if (*from == SS2 && len >= 4) /* code set 2 */
- {
- from++;
- *to = (((uint32) SS2) << 24) | (*from++ << 16);
- *to |= *from++ << 8;
- *to |= *from++;
- len -= 4;
- }
- else if (*from == SS3 && len >= 3) /* code set 3 (unused?) */
- {
- from++;
- *to = (SS3 << 16) | (*from++ << 8);
- *to |= *from++;
- len -= 3;
- }
- else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 2 */
- {
- *to = *from++ << 8;
- *to |= *from++;
- len -= 2;
- }
- else
- {
- *to = *from++;
- len--;
- }
- to++;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-static int
-pg_euctw_mblen(const unsigned char *s)
-{
- int len;
-
- if (*s == SS2)
- len = 4;
- else if (*s == SS3)
- len = 3;
- else if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = 1;
- return len;
-}
-
-static int
-pg_euctw_dsplen(const unsigned char *s)
-{
- int len;
-
- if (*s == SS2)
- len = 2;
- else if (*s == SS3)
- len = 2;
- else if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = pg_ascii_dsplen(s);
- return len;
-}
-
-/*
- * Convert pg_wchar to EUC_* encoding.
- * caller must allocate enough space for "to", including a trailing zero!
- * len: length of from.
- * "from" not necessarily null terminated.
- */
-static int
-pg_wchar2euc_with_len(const pg_wchar *from, unsigned char *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- unsigned char c;
-
- if ((c = (*from >> 24)))
- {
- *to++ = c;
- *to++ = (*from >> 16) & 0xff;
- *to++ = (*from >> 8) & 0xff;
- *to++ = *from & 0xff;
- cnt += 4;
- }
- else if ((c = (*from >> 16)))
- {
- *to++ = c;
- *to++ = (*from >> 8) & 0xff;
- *to++ = *from & 0xff;
- cnt += 3;
- }
- else if ((c = (*from >> 8)))
- {
- *to++ = c;
- *to++ = *from & 0xff;
- cnt += 2;
- }
- else
- {
- *to++ = *from;
- cnt++;
- }
- from++;
- len--;
- }
- *to = 0;
- return cnt;
-}
-
-
-/*
- * JOHAB
- */
-static int
-pg_johab_mblen(const unsigned char *s)
-{
- return pg_euc_mblen(s);
-}
-
-static int
-pg_johab_dsplen(const unsigned char *s)
-{
- return pg_euc_dsplen(s);
-}
-
-/*
- * convert UTF8 string to pg_wchar (UCS-4)
- * caller must allocate enough space for "to", including a trailing zero!
- * len: length of from.
- * "from" not necessarily null terminated.
- */
-static int
-pg_utf2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- int cnt = 0;
- uint32 c1,
- c2,
- c3,
- c4;
-
- while (len > 0 && *from)
- {
- if ((*from & 0x80) == 0)
- {
- *to = *from++;
- len--;
- }
- else if ((*from & 0xe0) == 0xc0)
- {
- if (len < 2)
- break; /* drop trailing incomplete char */
- c1 = *from++ & 0x1f;
- c2 = *from++ & 0x3f;
- *to = (c1 << 6) | c2;
- len -= 2;
- }
- else if ((*from & 0xf0) == 0xe0)
- {
- if (len < 3)
- break; /* drop trailing incomplete char */
- c1 = *from++ & 0x0f;
- c2 = *from++ & 0x3f;
- c3 = *from++ & 0x3f;
- *to = (c1 << 12) | (c2 << 6) | c3;
- len -= 3;
- }
- else if ((*from & 0xf8) == 0xf0)
- {
- if (len < 4)
- break; /* drop trailing incomplete char */
- c1 = *from++ & 0x07;
- c2 = *from++ & 0x3f;
- c3 = *from++ & 0x3f;
- c4 = *from++ & 0x3f;
- *to = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
- len -= 4;
- }
- else
- {
- /* treat a bogus char as length 1; not ours to raise error */
- *to = *from++;
- len--;
- }
- to++;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-
-/*
- * Map a Unicode code point to UTF-8. utf8string must have 4 bytes of
- * space allocated.
- */
-unsigned char *
-unicode_to_utf8(pg_wchar c, unsigned char *utf8string)
-{
- if (c <= 0x7F)
- {
- utf8string[0] = c;
- }
- else if (c <= 0x7FF)
- {
- utf8string[0] = 0xC0 | ((c >> 6) & 0x1F);
- utf8string[1] = 0x80 | (c & 0x3F);
- }
- else if (c <= 0xFFFF)
- {
- utf8string[0] = 0xE0 | ((c >> 12) & 0x0F);
- utf8string[1] = 0x80 | ((c >> 6) & 0x3F);
- utf8string[2] = 0x80 | (c & 0x3F);
- }
- else
- {
- utf8string[0] = 0xF0 | ((c >> 18) & 0x07);
- utf8string[1] = 0x80 | ((c >> 12) & 0x3F);
- utf8string[2] = 0x80 | ((c >> 6) & 0x3F);
- utf8string[3] = 0x80 | (c & 0x3F);
- }
-
- return utf8string;
-}
-
-/*
- * Trivial conversion from pg_wchar to UTF-8.
- * caller should allocate enough space for "to"
- * len: length of from.
- * "from" not necessarily null terminated.
- */
-static int
-pg_wchar2utf_with_len(const pg_wchar *from, unsigned char *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- int char_len;
-
- unicode_to_utf8(*from, to);
- char_len = pg_utf_mblen(to);
- cnt += char_len;
- to += char_len;
- from++;
- len--;
- }
- *to = 0;
- return cnt;
-}
-
-/*
- * Return the byte length of a UTF8 character pointed to by s
- *
- * Note: in the current implementation we do not support UTF8 sequences
- * of more than 4 bytes; hence do NOT return a value larger than 4.
- * We return "1" for any leading byte that is either flat-out illegal or
- * indicates a length larger than we support.
- *
- * pg_utf2wchar_with_len(), utf8_to_unicode(), pg_utf8_islegal(), and perhaps
- * other places would need to be fixed to change this.
- */
-int
-pg_utf_mblen(const unsigned char *s)
-{
- int len;
-
- if ((*s & 0x80) == 0)
- len = 1;
- else if ((*s & 0xe0) == 0xc0)
- len = 2;
- else if ((*s & 0xf0) == 0xe0)
- len = 3;
- else if ((*s & 0xf8) == 0xf0)
- len = 4;
-#ifdef NOT_USED
- else if ((*s & 0xfc) == 0xf8)
- len = 5;
- else if ((*s & 0xfe) == 0xfc)
- len = 6;
-#endif
- else
- len = 1;
- return len;
-}
-
-/*
- * This is an implementation of wcwidth() and wcswidth() as defined in
- * "The Single UNIX Specification, Version 2, The Open Group, 1997"
- * <http://www.UNIX-systems.org/online.html>
- *
- * Markus Kuhn -- 2001-09-08 -- public domain
- *
- * customised for PostgreSQL
- *
- * original available at : http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
- */
-
-struct mbinterval
-{
- unsigned short first;
- unsigned short last;
-};
-
-/* auxiliary function for binary search in interval table */
-static int
-mbbisearch(pg_wchar ucs, const struct mbinterval * table, int max)
-{
- int min = 0;
- int mid;
-
- if (ucs < table[0].first || ucs > table[max].last)
- return 0;
- while (max >= min)
- {
- mid = (min + max) / 2;
- if (ucs > table[mid].last)
- min = mid + 1;
- else if (ucs < table[mid].first)
- max = mid - 1;
- else
- return 1;
- }
-
- return 0;
-}
-
-
-/* The following functions define the column width of an ISO 10646
- * character as follows:
- *
- * - The null character (U+0000) has a column width of 0.
- *
- * - Other C0/C1 control characters and DEL will lead to a return
- * value of -1.
- *
- * - Non-spacing and enclosing combining characters (general
- * category code Mn or Me in the Unicode database) have a
- * column width of 0.
- *
- * - Other format characters (general category code Cf in the Unicode
- * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
- *
- * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
- * have a column width of 0.
- *
- * - Spacing characters in the East Asian Wide (W) or East Asian
- * FullWidth (F) category as defined in Unicode Technical
- * Report #11 have a column width of 2.
- *
- * - All remaining characters (including all printable
- * ISO 8859-1 and WGL4 characters, Unicode control characters,
- * etc.) have a column width of 1.
- *
- * This implementation assumes that wchar_t characters are encoded
- * in ISO 10646.
- */
-
-static int
-ucs_wcwidth(pg_wchar ucs)
-{
- /* sorted list of non-overlapping intervals of non-spacing characters */
- static const struct mbinterval combining[] = {
- {0x0300, 0x034E}, {0x0360, 0x0362}, {0x0483, 0x0486},
- {0x0488, 0x0489}, {0x0591, 0x05A1}, {0x05A3, 0x05B9},
- {0x05BB, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
- {0x05C4, 0x05C4}, {0x064B, 0x0655}, {0x0670, 0x0670},
- {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
- {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
- {0x07A6, 0x07B0}, {0x0901, 0x0902}, {0x093C, 0x093C},
- {0x0941, 0x0948}, {0x094D, 0x094D}, {0x0951, 0x0954},
- {0x0962, 0x0963}, {0x0981, 0x0981}, {0x09BC, 0x09BC},
- {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, {0x09E2, 0x09E3},
- {0x0A02, 0x0A02}, {0x0A3C, 0x0A3C}, {0x0A41, 0x0A42},
- {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A70, 0x0A71},
- {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, {0x0AC1, 0x0AC5},
- {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, {0x0B01, 0x0B01},
- {0x0B3C, 0x0B3C}, {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43},
- {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B82, 0x0B82},
- {0x0BC0, 0x0BC0}, {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40},
- {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
- {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
- {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, {0x0DCA, 0x0DCA},
- {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0E31, 0x0E31},
- {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0x0EB1, 0x0EB1},
- {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, {0x0EC8, 0x0ECD},
- {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37},
- {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, {0x0F80, 0x0F84},
- {0x0F86, 0x0F87}, {0x0F90, 0x0F97}, {0x0F99, 0x0FBC},
- {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, {0x1032, 0x1032},
- {0x1036, 0x1037}, {0x1039, 0x1039}, {0x1058, 0x1059},
- {0x1160, 0x11FF}, {0x17B7, 0x17BD}, {0x17C6, 0x17C6},
- {0x17C9, 0x17D3}, {0x180B, 0x180E}, {0x18A9, 0x18A9},
- {0x200B, 0x200F}, {0x202A, 0x202E}, {0x206A, 0x206F},
- {0x20D0, 0x20E3}, {0x302A, 0x302F}, {0x3099, 0x309A},
- {0xFB1E, 0xFB1E}, {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF},
- {0xFFF9, 0xFFFB}
- };
-
- /* test for 8-bit control characters */
- if (ucs == 0)
- return 0;
-
- if (ucs < 0x20 || (ucs >= 0x7f && ucs < 0xa0) || ucs > 0x0010ffff)
- return -1;
-
- /* binary search in table of non-spacing characters */
- if (mbbisearch(ucs, combining,
- sizeof(combining) / sizeof(struct mbinterval) - 1))
- return 0;
-
- /*
- * if we arrive here, ucs is not a combining or C0/C1 control character
- */
-
- return 1 +
- (ucs >= 0x1100 &&
- (ucs <= 0x115f || /* Hangul Jamo init. consonants */
- (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
- ucs != 0x303f) || /* CJK ... Yi */
- (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
- (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility
- * Ideographs */
- (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
- (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
- (ucs >= 0xffe0 && ucs <= 0xffe6) ||
- (ucs >= 0x20000 && ucs <= 0x2ffff)));
-}
-
-/*
- * Convert a UTF-8 character to a Unicode code point.
- * This is a one-character version of pg_utf2wchar_with_len.
- *
- * No error checks here, c must point to a long-enough string.
- */
-pg_wchar
-utf8_to_unicode(const unsigned char *c)
-{
- if ((*c & 0x80) == 0)
- return (pg_wchar) c[0];
- else if ((*c & 0xe0) == 0xc0)
- return (pg_wchar) (((c[0] & 0x1f) << 6) |
- (c[1] & 0x3f));
- else if ((*c & 0xf0) == 0xe0)
- return (pg_wchar) (((c[0] & 0x0f) << 12) |
- ((c[1] & 0x3f) << 6) |
- (c[2] & 0x3f));
- else if ((*c & 0xf8) == 0xf0)
- return (pg_wchar) (((c[0] & 0x07) << 18) |
- ((c[1] & 0x3f) << 12) |
- ((c[2] & 0x3f) << 6) |
- (c[3] & 0x3f));
- else
- /* that is an invalid code on purpose */
- return 0xffffffff;
-}
-
-static int
-pg_utf_dsplen(const unsigned char *s)
-{
- return ucs_wcwidth(utf8_to_unicode(s));
-}
-
-/*
- * convert mule internal code to pg_wchar
- * caller should allocate enough space for "to"
- * len: length of from.
- * "from" not necessarily null terminated.
- */
-static int
-pg_mule2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- if (IS_LC1(*from) && len >= 2)
- {
- *to = *from++ << 16;
- *to |= *from++;
- len -= 2;
- }
- else if (IS_LCPRV1(*from) && len >= 3)
- {
- from++;
- *to = *from++ << 16;
- *to |= *from++;
- len -= 3;
- }
- else if (IS_LC2(*from) && len >= 3)
- {
- *to = *from++ << 16;
- *to |= *from++ << 8;
- *to |= *from++;
- len -= 3;
- }
- else if (IS_LCPRV2(*from) && len >= 4)
- {
- from++;
- *to = *from++ << 16;
- *to |= *from++ << 8;
- *to |= *from++;
- len -= 4;
- }
- else
- { /* assume ASCII */
- *to = (unsigned char) *from++;
- len--;
- }
- to++;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-/*
- * convert pg_wchar to mule internal code
- * caller should allocate enough space for "to"
- * len: length of from.
- * "from" not necessarily null terminated.
- */
-static int
-pg_wchar2mule_with_len(const pg_wchar *from, unsigned char *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- unsigned char lb;
-
- lb = (*from >> 16) & 0xff;
- if (IS_LC1(lb))
- {
- *to++ = lb;
- *to++ = *from & 0xff;
- cnt += 2;
- }
- else if (IS_LC2(lb))
- {
- *to++ = lb;
- *to++ = (*from >> 8) & 0xff;
- *to++ = *from & 0xff;
- cnt += 3;
- }
- else if (IS_LCPRV1_A_RANGE(lb))
- {
- *to++ = LCPRV1_A;
- *to++ = lb;
- *to++ = *from & 0xff;
- cnt += 3;
- }
- else if (IS_LCPRV1_B_RANGE(lb))
- {
- *to++ = LCPRV1_B;
- *to++ = lb;
- *to++ = *from & 0xff;
- cnt += 3;
- }
- else if (IS_LCPRV2_A_RANGE(lb))
- {
- *to++ = LCPRV2_A;
- *to++ = lb;
- *to++ = (*from >> 8) & 0xff;
- *to++ = *from & 0xff;
- cnt += 4;
- }
- else if (IS_LCPRV2_B_RANGE(lb))
- {
- *to++ = LCPRV2_B;
- *to++ = lb;
- *to++ = (*from >> 8) & 0xff;
- *to++ = *from & 0xff;
- cnt += 4;
- }
- else
- {
- *to++ = *from & 0xff;
- cnt += 1;
- }
- from++;
- len--;
- }
- *to = 0;
- return cnt;
-}
-
-int
-pg_mule_mblen(const unsigned char *s)
-{
- int len;
-
- if (IS_LC1(*s))
- len = 2;
- else if (IS_LCPRV1(*s))
- len = 3;
- else if (IS_LC2(*s))
- len = 3;
- else if (IS_LCPRV2(*s))
- len = 4;
- else
- len = 1; /* assume ASCII */
- return len;
-}
-
-static int
-pg_mule_dsplen(const unsigned char *s)
-{
- int len;
-
- /*
- * Note: it's not really appropriate to assume that all multibyte charsets
- * are double-wide on screen. But this seems an okay approximation for
- * the MULE charsets we currently support.
- */
-
- if (IS_LC1(*s))
- len = 1;
- else if (IS_LCPRV1(*s))
- len = 1;
- else if (IS_LC2(*s))
- len = 2;
- else if (IS_LCPRV2(*s))
- len = 2;
- else
- len = 1; /* assume ASCII */
-
- return len;
-}
-
-/*
- * ISO8859-1
- */
-static int
-pg_latin12wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- *to++ = *from++;
- len--;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-/*
- * Trivial conversion from pg_wchar to single byte encoding. Just ignores
- * high bits.
- * caller should allocate enough space for "to"
- * len: length of from.
- * "from" not necessarily null terminated.
- */
-static int
-pg_wchar2single_with_len(const pg_wchar *from, unsigned char *to, int len)
-{
- int cnt = 0;
-
- while (len > 0 && *from)
- {
- *to++ = *from++;
- len--;
- cnt++;
- }
- *to = 0;
- return cnt;
-}
-
-static int
-pg_latin1_mblen(const unsigned char *s)
-{
- return 1;
-}
-
-static int
-pg_latin1_dsplen(const unsigned char *s)
-{
- return pg_ascii_dsplen(s);
-}
-
-/*
- * SJIS
- */
-static int
-pg_sjis_mblen(const unsigned char *s)
-{
- int len;
-
- if (*s >= 0xa1 && *s <= 0xdf)
- len = 1; /* 1 byte kana? */
- else if (IS_HIGHBIT_SET(*s))
- len = 2; /* kanji? */
- else
- len = 1; /* should be ASCII */
- return len;
-}
-
-static int
-pg_sjis_dsplen(const unsigned char *s)
-{
- int len;
-
- if (*s >= 0xa1 && *s <= 0xdf)
- len = 1; /* 1 byte kana? */
- else if (IS_HIGHBIT_SET(*s))
- len = 2; /* kanji? */
- else
- len = pg_ascii_dsplen(s); /* should be ASCII */
- return len;
-}
-
-/*
- * Big5
- */
-static int
-pg_big5_mblen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2; /* kanji? */
- else
- len = 1; /* should be ASCII */
- return len;
-}
-
-static int
-pg_big5_dsplen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2; /* kanji? */
- else
- len = pg_ascii_dsplen(s); /* should be ASCII */
- return len;
-}
-
-/*
- * GBK
- */
-static int
-pg_gbk_mblen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2; /* kanji? */
- else
- len = 1; /* should be ASCII */
- return len;
-}
-
-static int
-pg_gbk_dsplen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2; /* kanji? */
- else
- len = pg_ascii_dsplen(s); /* should be ASCII */
- return len;
-}
-
-/*
- * UHC
- */
-static int
-pg_uhc_mblen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2; /* 2byte? */
- else
- len = 1; /* should be ASCII */
- return len;
-}
-
-static int
-pg_uhc_dsplen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2; /* 2byte? */
- else
- len = pg_ascii_dsplen(s); /* should be ASCII */
- return len;
-}
-
-/*
- * GB18030
- * Added by Bill Huang <bhuang@redhat.com>,<bill_huanghb@ybb.ne.jp>
- */
-static int
-pg_gb18030_mblen(const unsigned char *s)
-{
- int len;
-
- if (!IS_HIGHBIT_SET(*s))
- len = 1; /* ASCII */
- else if (*(s + 1) >= 0x30 && *(s + 1) <= 0x39)
- len = 4;
- else
- len = 2;
- return len;
-}
-
-static int
-pg_gb18030_dsplen(const unsigned char *s)
-{
- int len;
-
- if (IS_HIGHBIT_SET(*s))
- len = 2;
- else
- len = pg_ascii_dsplen(s); /* ASCII */
- return len;
-}
-
-/*
- *-------------------------------------------------------------------
- * multibyte sequence validators
- *
- * These functions accept "s", a pointer to the first byte of a string,
- * and "len", the remaining length of the string. If there is a validly
- * encoded character beginning at *s, return its length in bytes; else
- * return -1.
- *
- * The functions can assume that len > 0 and that *s != '\0', but they must
- * test for and reject zeroes in any additional bytes of a multibyte character.
- *
- * Note that this definition allows the function for a single-byte
- * encoding to be just "return 1".
- *-------------------------------------------------------------------
- */
-
-static int
-pg_ascii_verifier(const unsigned char *s, int len)
-{
- return 1;
-}
-
-#define IS_EUC_RANGE_VALID(c) ((c) >= 0xa1 && (c) <= 0xfe)
-
-static int
-pg_eucjp_verifier(const unsigned char *s, int len)
-{
- int l;
- unsigned char c1,
- c2;
-
- c1 = *s++;
-
- switch (c1)
- {
- case SS2: /* JIS X 0201 */
- l = 2;
- if (l > len)
- return -1;
- c2 = *s++;
- if (c2 < 0xa1 || c2 > 0xdf)
- return -1;
- break;
-
- case SS3: /* JIS X 0212 */
- l = 3;
- if (l > len)
- return -1;
- c2 = *s++;
- if (!IS_EUC_RANGE_VALID(c2))
- return -1;
- c2 = *s++;
- if (!IS_EUC_RANGE_VALID(c2))
- return -1;
- break;
-
- default:
- if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
- {
- l = 2;
- if (l > len)
- return -1;
- if (!IS_EUC_RANGE_VALID(c1))
- return -1;
- c2 = *s++;
- if (!IS_EUC_RANGE_VALID(c2))
- return -1;
- }
- else
- /* must be ASCII */
- {
- l = 1;
- }
- break;
- }
-
- return l;
-}
-
-static int
-pg_euckr_verifier(const unsigned char *s, int len)
-{
- int l;
- unsigned char c1,
- c2;
-
- c1 = *s++;
-
- if (IS_HIGHBIT_SET(c1))
- {
- l = 2;
- if (l > len)
- return -1;
- if (!IS_EUC_RANGE_VALID(c1))
- return -1;
- c2 = *s++;
- if (!IS_EUC_RANGE_VALID(c2))
- return -1;
- }
- else
- /* must be ASCII */
- {
- l = 1;
- }
-
- return l;
-}
-
-/* EUC-CN byte sequences are exactly same as EUC-KR */
-#define pg_euccn_verifier pg_euckr_verifier
-
-static int
-pg_euctw_verifier(const unsigned char *s, int len)
-{
- int l;
- unsigned char c1,
- c2;
-
- c1 = *s++;
-
- switch (c1)
- {
- case SS2: /* CNS 11643 Plane 1-7 */
- l = 4;
- if (l > len)
- return -1;
- c2 = *s++;
- if (c2 < 0xa1 || c2 > 0xa7)
- return -1;
- c2 = *s++;
- if (!IS_EUC_RANGE_VALID(c2))
- return -1;
- c2 = *s++;
- if (!IS_EUC_RANGE_VALID(c2))
- return -1;
- break;
-
- case SS3: /* unused */
- return -1;
-
- default:
- if (IS_HIGHBIT_SET(c1)) /* CNS 11643 Plane 1 */
- {
- l = 2;
- if (l > len)
- return -1;
- /* no further range check on c1? */
- c2 = *s++;
- if (!IS_EUC_RANGE_VALID(c2))
- return -1;
- }
- else
- /* must be ASCII */
- {
- l = 1;
- }
- break;
- }
- return l;
-}
-
-static int
-pg_johab_verifier(const unsigned char *s, int len)
-{
- int l,
- mbl;
- unsigned char c;
-
- l = mbl = pg_johab_mblen(s);
-
- if (len < l)
- return -1;
-
- if (!IS_HIGHBIT_SET(*s))
- return mbl;
-
- while (--l > 0)
- {
- c = *++s;
- if (!IS_EUC_RANGE_VALID(c))
- return -1;
- }
- return mbl;
-}
-
-static int
-pg_mule_verifier(const unsigned char *s, int len)
-{
- int l,
- mbl;
- unsigned char c;
-
- l = mbl = pg_mule_mblen(s);
-
- if (len < l)
- return -1;
-
- while (--l > 0)
- {
- c = *++s;
- if (!IS_HIGHBIT_SET(c))
- return -1;
- }
- return mbl;
-}
-
-static int
-pg_latin1_verifier(const unsigned char *s, int len)
-{
- return 1;
-}
-
-static int
-pg_sjis_verifier(const unsigned char *s, int len)
-{
- int l,
- mbl;
- unsigned char c1,
- c2;
-
- l = mbl = pg_sjis_mblen(s);
-
- if (len < l)
- return -1;
-
- if (l == 1) /* pg_sjis_mblen already verified it */
- return mbl;
-
- c1 = *s++;
- c2 = *s;
- if (!ISSJISHEAD(c1) || !ISSJISTAIL(c2))
- return -1;
- return mbl;
-}
-
-static int
-pg_big5_verifier(const unsigned char *s, int len)
-{
- int l,
- mbl;
-
- l = mbl = pg_big5_mblen(s);
-
- if (len < l)
- return -1;
-
- while (--l > 0)
- {
- if (*++s == '\0')
- return -1;
- }
-
- return mbl;
-}
-
-static int
-pg_gbk_verifier(const unsigned char *s, int len)
-{
- int l,
- mbl;
-
- l = mbl = pg_gbk_mblen(s);
-
- if (len < l)
- return -1;
-
- while (--l > 0)
- {
- if (*++s == '\0')
- return -1;
- }
-
- return mbl;
-}
-
-static int
-pg_uhc_verifier(const unsigned char *s, int len)
-{
- int l,
- mbl;
-
- l = mbl = pg_uhc_mblen(s);
-
- if (len < l)
- return -1;
-
- while (--l > 0)
- {
- if (*++s == '\0')
- return -1;
- }
-
- return mbl;
-}
-
-static int
-pg_gb18030_verifier(const unsigned char *s, int len)
-{
- int l;
-
- if (!IS_HIGHBIT_SET(*s))
- l = 1; /* ASCII */
- else if (len >= 4 && *(s + 1) >= 0x30 && *(s + 1) <= 0x39)
- {
- /* Should be 4-byte, validate remaining bytes */
- if (*s >= 0x81 && *s <= 0xfe &&
- *(s + 2) >= 0x81 && *(s + 2) <= 0xfe &&
- *(s + 3) >= 0x30 && *(s + 3) <= 0x39)
- l = 4;
- else
- l = -1;
- }
- else if (len >= 2 && *s >= 0x81 && *s <= 0xfe)
- {
- /* Should be 2-byte, validate */
- if ((*(s + 1) >= 0x40 && *(s + 1) <= 0x7e) ||
- (*(s + 1) >= 0x80 && *(s + 1) <= 0xfe))
- l = 2;
- else
- l = -1;
- }
- else
- l = -1;
- return l;
-}
-
-static int
-pg_utf8_verifier(const unsigned char *s, int len)
-{
- int l = pg_utf_mblen(s);
-
- if (len < l)
- return -1;
-
- if (!pg_utf8_islegal(s, l))
- return -1;
-
- return l;
-}
-
-/*
- * Check for validity of a single UTF-8 encoded character
- *
- * This directly implements the rules in RFC3629. The bizarre-looking
- * restrictions on the second byte are meant to ensure that there isn't
- * more than one encoding of a given Unicode character point; that is,
- * you may not use a longer-than-necessary byte sequence with high order
- * zero bits to represent a character that would fit in fewer bytes.
- * To do otherwise is to create security hazards (eg, create an apparent
- * non-ASCII character that decodes to plain ASCII).
- *
- * length is assumed to have been obtained by pg_utf_mblen(), and the
- * caller must have checked that that many bytes are present in the buffer.
- */
-bool
-pg_utf8_islegal(const unsigned char *source, int length)
-{
- unsigned char a;
-
- switch (length)
- {
- default:
- /* reject lengths 5 and 6 for now */
- return false;
- case 4:
- a = source[3];
- if (a < 0x80 || a > 0xBF)
- return false;
- /* FALL THRU */
- case 3:
- a = source[2];
- if (a < 0x80 || a > 0xBF)
- return false;
- /* FALL THRU */
- case 2:
- a = source[1];
- switch (*source)
- {
- case 0xE0:
- if (a < 0xA0 || a > 0xBF)
- return false;
- break;
- case 0xED:
- if (a < 0x80 || a > 0x9F)
- return false;
- break;
- case 0xF0:
- if (a < 0x90 || a > 0xBF)
- return false;
- break;
- case 0xF4:
- if (a < 0x80 || a > 0x8F)
- return false;
- break;
- default:
- if (a < 0x80 || a > 0xBF)
- return false;
- break;
- }
- /* FALL THRU */
- case 1:
- a = *source;
- if (a >= 0x80 && a < 0xC2)
- return false;
- if (a > 0xF4)
- return false;
- break;
- }
- return true;
-}
-
-#ifndef FRONTEND
-
-/*
- * Generic character incrementer function.
- *
- * Not knowing anything about the properties of the encoding in use, we just
- * keep incrementing the last byte until we get a validly-encoded result,
- * or we run out of values to try. We don't bother to try incrementing
- * higher-order bytes, so there's no growth in runtime for wider characters.
- * (If we did try to do that, we'd need to consider the likelihood that 255
- * is not a valid final byte in the encoding.)
- */
-static bool
-pg_generic_charinc(unsigned char *charptr, int len)
-{
- unsigned char *lastbyte = charptr + len - 1;
- mbverifier mbverify;
-
- /* We can just invoke the character verifier directly. */
- mbverify = pg_wchar_table[GetDatabaseEncoding()].mbverify;
-
- while (*lastbyte < (unsigned char) 255)
- {
- (*lastbyte)++;
- if ((*mbverify) (charptr, len) == len)
- return true;
- }
-
- return false;
-}
-
-/*
- * UTF-8 character incrementer function.
- *
- * For a one-byte character less than 0x7F, we just increment the byte.
- *
- * For a multibyte character, every byte but the first must fall between 0x80
- * and 0xBF; and the first byte must be between 0xC0 and 0xF4. We increment
- * the last byte that's not already at its maximum value. If we can't find a
- * byte that's less than the maximum allowable value, we simply fail. We also
- * need some special-case logic to skip regions used for surrogate pair
- * handling, as those should not occur in valid UTF-8.
- *
- * Note that we don't reset lower-order bytes back to their minimums, since
- * we can't afford to make an exhaustive search (see make_greater_string).
- */
-static bool
-pg_utf8_increment(unsigned char *charptr, int length)
-{
- unsigned char a;
- unsigned char limit;
-
- switch (length)
- {
- default:
- /* reject lengths 5 and 6 for now */
- return false;
- case 4:
- a = charptr[3];
- if (a < 0xBF)
- {
- charptr[3]++;
- break;
- }
- /* FALL THRU */
- case 3:
- a = charptr[2];
- if (a < 0xBF)
- {
- charptr[2]++;
- break;
- }
- /* FALL THRU */
- case 2:
- a = charptr[1];
- switch (*charptr)
- {
- case 0xED:
- limit = 0x9F;
- break;
- case 0xF4:
- limit = 0x8F;
- break;
- default:
- limit = 0xBF;
- break;
- }
- if (a < limit)
- {
- charptr[1]++;
- break;
- }
- /* FALL THRU */
- case 1:
- a = *charptr;
- if (a == 0x7F || a == 0xDF || a == 0xEF || a == 0xF4)
- return false;
- charptr[0]++;
- break;
- }
-
- return true;
-}
-
-/*
- * EUC-JP character incrementer function.
- *
- * If the sequence starts with SS2 (0x8e), it must be a two-byte sequence
- * representing JIS X 0201 characters with the second byte ranging between
- * 0xa1 and 0xdf. We just increment the last byte if it's less than 0xdf,
- * and otherwise rewrite the whole sequence to 0xa1 0xa1.
- *
- * If the sequence starts with SS3 (0x8f), it must be a three-byte sequence
- * in which the last two bytes range between 0xa1 and 0xfe. The last byte
- * is incremented if possible, otherwise the second-to-last byte.
- *
- * If the sequence starts with a value other than the above and its MSB
- * is set, it must be a two-byte sequence representing JIS X 0208 characters
- * with both bytes ranging between 0xa1 and 0xfe. The last byte is
- * incremented if possible, otherwise the second-to-last byte.
- *
- * Otherwise, the sequence is a single-byte ASCII character. It is
- * incremented up to 0x7f.
- */
-static bool
-pg_eucjp_increment(unsigned char *charptr, int length)
-{
- unsigned char c1,
- c2;
- int i;
-
- c1 = *charptr;
-
- switch (c1)
- {
- case SS2: /* JIS X 0201 */
- if (length != 2)
- return false;
-
- c2 = charptr[1];
-
- if (c2 >= 0xdf)
- charptr[0] = charptr[1] = 0xa1;
- else if (c2 < 0xa1)
- charptr[1] = 0xa1;
- else
- charptr[1]++;
- break;
-
- case SS3: /* JIS X 0212 */
- if (length != 3)
- return false;
-
- for (i = 2; i > 0; i--)
- {
- c2 = charptr[i];
- if (c2 < 0xa1)
- {
- charptr[i] = 0xa1;
- return true;
- }
- else if (c2 < 0xfe)
- {
- charptr[i]++;
- return true;
- }
- }
-
- /* Out of 3-byte code region */
- return false;
-
- default:
- if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
- {
- if (length != 2)
- return false;
-
- for (i = 1; i >= 0; i--)
- {
- c2 = charptr[i];
- if (c2 < 0xa1)
- {
- charptr[i] = 0xa1;
- return true;
- }
- else if (c2 < 0xfe)
- {
- charptr[i]++;
- return true;
- }
- }
-
- /* Out of 2 byte code region */
- return false;
- }
- else
- { /* ASCII, single byte */
- if (c1 > 0x7e)
- return false;
- (*charptr)++;
- }
- break;
- }
-
- return true;
-}
-#endif /* !FRONTEND */
-
-
-/*
- *-------------------------------------------------------------------
- * encoding info table
- * XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
- *-------------------------------------------------------------------
- */
-const pg_wchar_tbl pg_wchar_table[] = {
- {pg_ascii2wchar_with_len, pg_wchar2single_with_len, pg_ascii_mblen, pg_ascii_dsplen, pg_ascii_verifier, 1}, /* PG_SQL_ASCII */
- {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3}, /* PG_EUC_JP */
- {pg_euccn2wchar_with_len, pg_wchar2euc_with_len, pg_euccn_mblen, pg_euccn_dsplen, pg_euccn_verifier, 2}, /* PG_EUC_CN */
- {pg_euckr2wchar_with_len, pg_wchar2euc_with_len, pg_euckr_mblen, pg_euckr_dsplen, pg_euckr_verifier, 3}, /* PG_EUC_KR */
- {pg_euctw2wchar_with_len, pg_wchar2euc_with_len, pg_euctw_mblen, pg_euctw_dsplen, pg_euctw_verifier, 4}, /* PG_EUC_TW */
- {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3}, /* PG_EUC_JIS_2004 */
- {pg_utf2wchar_with_len, pg_wchar2utf_with_len, pg_utf_mblen, pg_utf_dsplen, pg_utf8_verifier, 4}, /* PG_UTF8 */
- {pg_mule2wchar_with_len, pg_wchar2mule_with_len, pg_mule_mblen, pg_mule_dsplen, pg_mule_verifier, 4}, /* PG_MULE_INTERNAL */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN1 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN2 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN3 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN4 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN5 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN6 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN7 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN8 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN9 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN10 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1256 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1258 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN866 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN874 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_KOI8R */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1251 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1252 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-5 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-6 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-7 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-8 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1250 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1253 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1254 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1255 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1257 */
- {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_KOI8U */
- {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2}, /* PG_SJIS */
- {0, 0, pg_big5_mblen, pg_big5_dsplen, pg_big5_verifier, 2}, /* PG_BIG5 */
- {0, 0, pg_gbk_mblen, pg_gbk_dsplen, pg_gbk_verifier, 2}, /* PG_GBK */
- {0, 0, pg_uhc_mblen, pg_uhc_dsplen, pg_uhc_verifier, 2}, /* PG_UHC */
- {0, 0, pg_gb18030_mblen, pg_gb18030_dsplen, pg_gb18030_verifier, 4}, /* PG_GB18030 */
- {0, 0, pg_johab_mblen, pg_johab_dsplen, pg_johab_verifier, 3}, /* PG_JOHAB */
- {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2} /* PG_SHIFT_JIS_2004 */
-};
-
-/* returns the byte length of a word for mule internal code */
-int
-pg_mic_mblen(const unsigned char *mbstr)
-{
- return pg_mule_mblen(mbstr);
-}
-
-/*
- * Returns the byte length of a multibyte character.
- */
-int
-pg_encoding_mblen(int encoding, const char *mbstr)
-{
- return (PG_VALID_ENCODING(encoding) ?
- ((*pg_wchar_table[encoding].mblen) ((const unsigned char *) mbstr)) :
- ((*pg_wchar_table[PG_SQL_ASCII].mblen) ((const unsigned char *) mbstr)));
-}
-
-/*
- * Returns the display length of a multibyte character.
- */
-int
-pg_encoding_dsplen(int encoding, const char *mbstr)
-{
- return (PG_VALID_ENCODING(encoding) ?
- ((*pg_wchar_table[encoding].dsplen) ((const unsigned char *) mbstr)) :
- ((*pg_wchar_table[PG_SQL_ASCII].dsplen) ((const unsigned char *) mbstr)));
-}
-
-/*
- * Verify the first multibyte character of the given string.
- * Return its byte length if good, -1 if bad. (See comments above for
- * full details of the mbverify API.)
- */
-int
-pg_encoding_verifymb(int encoding, const char *mbstr, int len)
-{
- return (PG_VALID_ENCODING(encoding) ?
- ((*pg_wchar_table[encoding].mbverify) ((const unsigned char *) mbstr, len)) :
- ((*pg_wchar_table[PG_SQL_ASCII].mbverify) ((const unsigned char *) mbstr, len)));
-}
-
-/*
- * fetch maximum length of a given encoding
- */
-int
-pg_encoding_max_length(int encoding)
-{
- Assert(PG_VALID_ENCODING(encoding));
-
- return pg_wchar_table[encoding].maxmblen;
-}
-
-#ifndef FRONTEND
-
-/*
- * fetch maximum length of the encoding for the current database
- */
-int
-pg_database_encoding_max_length(void)
-{
- return pg_wchar_table[GetDatabaseEncoding()].maxmblen;
-}
-
-/*
- * get the character incrementer for the encoding for the current database
- */
-mbcharacter_incrementer
-pg_database_encoding_character_incrementer(void)
-{
- /*
- * Eventually it might be best to add a field to pg_wchar_table[], but for
- * now we just use a switch.
- */
- switch (GetDatabaseEncoding())
- {
- case PG_UTF8:
- return pg_utf8_increment;
-
- case PG_EUC_JP:
- return pg_eucjp_increment;
-
- default:
- return pg_generic_charinc;
- }
-}
-
-/*
- * Verify mbstr to make sure that it is validly encoded in the current
- * database encoding. Otherwise same as pg_verify_mbstr().
- */
-bool
-pg_verifymbstr(const char *mbstr, int len, bool noError)
-{
- return
- pg_verify_mbstr_len(GetDatabaseEncoding(), mbstr, len, noError) >= 0;
-}
-
-/*
- * Verify mbstr to make sure that it is validly encoded in the specified
- * encoding.
- */
-bool
-pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
-{
- return pg_verify_mbstr_len(encoding, mbstr, len, noError) >= 0;
-}
-
-/*
- * Verify mbstr to make sure that it is validly encoded in the specified
- * encoding.
- *
- * mbstr is not necessarily zero terminated; length of mbstr is
- * specified by len.
- *
- * If OK, return length of string in the encoding.
- * If a problem is found, return -1 when noError is
- * true; when noError is false, ereport() a descriptive message.
- */
-int
-pg_verify_mbstr_len(int encoding, const char *mbstr, int len, bool noError)
-{
- mbverifier mbverify;
- int mb_len;
-
- Assert(PG_VALID_ENCODING(encoding));
-
- /*
- * In single-byte encodings, we need only reject nulls (\0).
- */
- if (pg_encoding_max_length(encoding) <= 1)
- {
- const char *nullpos = memchr(mbstr, 0, len);
-
- if (nullpos == NULL)
- return len;
- if (noError)
- return -1;
- report_invalid_encoding(encoding, nullpos, 1);
- }
-
- /* fetch function pointer just once */
- mbverify = pg_wchar_table[encoding].mbverify;
-
- mb_len = 0;
-
- while (len > 0)
- {
- int l;
-
- /* fast path for ASCII-subset characters */
- if (!IS_HIGHBIT_SET(*mbstr))
- {
- if (*mbstr != '\0')
- {
- mb_len++;
- mbstr++;
- len--;
- continue;
- }
- if (noError)
- return -1;
- report_invalid_encoding(encoding, mbstr, len);
- }
-
- l = (*mbverify) ((const unsigned char *) mbstr, len);
-
- if (l < 0)
- {
- if (noError)
- return -1;
- report_invalid_encoding(encoding, mbstr, len);
- }
-
- mbstr += l;
- len -= l;
- mb_len++;
- }
- return mb_len;
-}
-
-/*
- * check_encoding_conversion_args: check arguments of a conversion function
- *
- * "expected" arguments can be either an encoding ID or -1 to indicate that
- * the caller will check whether it accepts the ID.
- *
- * Note: the errors here are not really user-facing, so elog instead of
- * ereport seems sufficient. Also, we trust that the "expected" encoding
- * arguments are valid encoding IDs, but we don't trust the actuals.
- */
-void
-check_encoding_conversion_args(int src_encoding,
- int dest_encoding,
- int len,
- int expected_src_encoding,
- int expected_dest_encoding)
-{
- if (!PG_VALID_ENCODING(src_encoding))
- elog(ERROR, "invalid source encoding ID: %d", src_encoding);
- if (src_encoding != expected_src_encoding && expected_src_encoding >= 0)
- elog(ERROR, "expected source encoding \"%s\", but got \"%s\"",
- pg_enc2name_tbl[expected_src_encoding].name,
- pg_enc2name_tbl[src_encoding].name);
- if (!PG_VALID_ENCODING(dest_encoding))
- elog(ERROR, "invalid destination encoding ID: %d", dest_encoding);
- if (dest_encoding != expected_dest_encoding && expected_dest_encoding >= 0)
- elog(ERROR, "expected destination encoding \"%s\", but got \"%s\"",
- pg_enc2name_tbl[expected_dest_encoding].name,
- pg_enc2name_tbl[dest_encoding].name);
- if (len < 0)
- elog(ERROR, "encoding conversion length must not be negative");
-}
-
-/*
- * report_invalid_encoding: complain about invalid multibyte character
- *
- * note: len is remaining length of string, not length of character;
- * len must be greater than zero, as we always examine the first byte.
- */
-void
-report_invalid_encoding(int encoding, const char *mbstr, int len)
-{
- int l = pg_encoding_mblen(encoding, mbstr);
- char buf[8 * 5 + 1];
- char *p = buf;
- int j,
- jlimit;
-
- jlimit = Min(l, len);
- jlimit = Min(jlimit, 8); /* prevent buffer overrun */
-
- for (j = 0; j < jlimit; j++)
- {
- p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
- if (j < jlimit - 1)
- p += sprintf(p, " ");
- }
-
- ereport(ERROR,
- (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
- errmsg("invalid byte sequence for encoding \"%s\": %s",
- pg_enc2name_tbl[encoding].name,
- buf)));
-}
-
-/*
- * report_untranslatable_char: complain about untranslatable character
- *
- * note: len is remaining length of string, not length of character;
- * len must be greater than zero, as we always examine the first byte.
- */
-void
-report_untranslatable_char(int src_encoding, int dest_encoding,
- const char *mbstr, int len)
-{
- int l = pg_encoding_mblen(src_encoding, mbstr);
- char buf[8 * 5 + 1];
- char *p = buf;
- int j,
- jlimit;
-
- jlimit = Min(l, len);
- jlimit = Min(jlimit, 8); /* prevent buffer overrun */
-
- for (j = 0; j < jlimit; j++)
- {
- p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
- if (j < jlimit - 1)
- p += sprintf(p, " ");
- }
-
- ereport(ERROR,
- (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
- errmsg("character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"",
- buf,
- pg_enc2name_tbl[src_encoding].name,
- pg_enc2name_tbl[dest_encoding].name)));
-}
-
-#endif /* !FRONTEND */
diff --git a/libpq/win32/crypt.c b/libpq/win32/crypt.c
deleted file mode 100644
index 6a902ef..0000000
--- a/libpq/win32/crypt.c
+++ /dev/null
@@ -1,1085 +0,0 @@
-/* src/port/crypt.c */
-/* $NetBSD: crypt.c,v 1.18 2001/03/01 14:37:35 wiz Exp $ */
-
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Tom Truscott.
- *
- * 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. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)crypt.c 8.1.1.1 (Berkeley) 8/18/93";
-#else
-__RCSID("$NetBSD: crypt.c,v 1.18 2001/03/01 14:37:35 wiz Exp $");
-#endif
-#endif /* not lint */
-
-#include "c.h"
-
-#include <limits.h>
-
-#ifndef WIN32
-#include <unistd.h>
-#endif
-
-static int des_setkey(const char *key);
-static int des_cipher(const char *in, char *out, long salt, int num_iter);
-
-/*
- * UNIX password, and DES, encryption.
- * By Tom Truscott, trt@rti.rti.org,
- * from algorithms by Robert W. Baldwin and James Gillogly.
- *
- * References:
- * "Mathematical Cryptology for Computer Scientists and Mathematicians,"
- * by Wayne Patterson, 1987, ISBN 0-8476-7438-X.
- *
- * "Password Security: A Case History," R. Morris and Ken Thompson,
- * Communications of the ACM, vol. 22, pp. 594-597, Nov. 1979.
- *
- * "DES will be Totally Insecure within Ten Years," M.E. Hellman,
- * IEEE Spectrum, vol. 16, pp. 32-39, July 1979.
- */
-
-/* ===== Configuration ==================== */
-
-/*
- * define "MUST_ALIGN" if your compiler cannot load/store
- * long integers at arbitrary (e.g. odd) memory locations.
- * (Either that or never pass unaligned addresses to des_cipher!)
- */
-/* #define MUST_ALIGN */
-
-#ifdef CHAR_BITS
-#if CHAR_BITS != 8
-#error C_block structure assumes 8 bit characters
-#endif
-#endif
-
-/*
- * define "B64" to be the declaration for a 64 bit integer.
- * XXX this feature is currently unused, see "endian" comment below.
- */
-/* #define B64 int64 */
-
-/*
- * define "LARGEDATA" to get faster permutations, by using about 72 kilobytes
- * of lookup tables. This speeds up des_setkey() and des_cipher(), but has
- * little effect on crypt().
- */
-/* #define LARGEDATA */
-
-/* compile with "-DSTATIC=void" when profiling */
-#ifndef STATIC
-#define STATIC static void
-#endif
-
-/*
- * Define the "int32_t" type for integral type with a width of at least
- * 32 bits.
- */
-typedef int int32_t;
-
-/* ==================================== */
-
-#define _PASSWORD_EFMT1 '_' /* extended encryption format */
-
-/*
- * Cipher-block representation (Bob Baldwin):
- *
- * DES operates on groups of 64 bits, numbered 1..64 (sigh). One
- * representation is to store one bit per byte in an array of bytes. Bit N of
- * the NBS spec is stored as the LSB of the Nth byte (index N-1) in the array.
- * Another representation stores the 64 bits in 8 bytes, with bits 1..8 in the
- * first byte, 9..16 in the second, and so on. The DES spec apparently has
- * bit 1 in the MSB of the first byte, but that is particularly noxious so we
- * bit-reverse each byte so that bit 1 is the LSB of the first byte, bit 8 is
- * the MSB of the first byte. Specifically, the 64-bit input data and key are
- * converted to LSB format, and the output 64-bit block is converted back into
- * MSB format.
- *
- * DES operates internally on groups of 32 bits which are expanded to 48 bits
- * by permutation E and shrunk back to 32 bits by the S boxes. To speed up
- * the computation, the expansion is applied only once, the expanded
- * representation is maintained during the encryption, and a compression
- * permutation is applied only at the end. To speed up the S-box lookups,
- * the 48 bits are maintained as eight 6 bit groups, one per byte, which
- * directly feed the eight S-boxes. Within each byte, the 6 bits are the
- * most significant ones. The low two bits of each byte are zero. (Thus,
- * bit 1 of the 48 bit E expansion is stored as the "4"-valued bit of the
- * first byte in the eight byte representation, bit 2 of the 48 bit value is
- * the "8"-valued bit, and so on.) In fact, a combined "SPE"-box lookup is
- * used, in which the output is the 64 bit result of an S-box lookup which
- * has been permuted by P and expanded by E, and is ready for use in the next
- * iteration. Two 32-bit wide tables, SPE[0] and SPE[1], are used for this
- * lookup. Since each byte in the 48 bit path is a multiple of four, indexed
- * lookup of SPE[0] and SPE[1] is simple and fast. The key schedule and
- * "salt" are also converted to this 8*(6+2) format. The SPE table size is
- * 8*64*8 = 4K bytes.
- *
- * To speed up bit-parallel operations (such as XOR), the 8 byte
- * representation is "union"ed with 32 bit values "i0" and "i1", and, on
- * machines which support it, a 64 bit value "b64". This data structure,
- * "C_block", has two problems. First, alignment restrictions must be
- * honored. Second, the byte-order (e.g. little-endian or big-endian) of
- * the architecture becomes visible.
- *
- * The byte-order problem is unfortunate, since on the one hand it is good
- * to have a machine-independent C_block representation (bits 1..8 in the
- * first byte, etc.), and on the other hand it is good for the LSB of the
- * first byte to be the LSB of i0. We cannot have both these things, so we
- * currently use the "little-endian" representation and avoid any multi-byte
- * operations that depend on byte order. This largely precludes use of the
- * 64-bit datatype since the relative order of i0 and i1 are unknown. It
- * also inhibits grouping the SPE table to look up 12 bits at a time. (The
- * 12 bits can be stored in a 16-bit field with 3 low-order zeroes and 1
- * high-order zero, providing fast indexing into a 64-bit wide SPE.) On the
- * other hand, 64-bit datatypes are currently rare, and a 12-bit SPE lookup
- * requires a 128 kilobyte table, so perhaps this is not a big loss.
- *
- * Permutation representation (Jim Gillogly):
- *
- * A transformation is defined by its effect on each of the 8 bytes of the
- * 64-bit input. For each byte we give a 64-bit output that has the bits in
- * the input distributed appropriately. The transformation is then the OR
- * of the 8 sets of 64-bits. This uses 8*256*8 = 16K bytes of storage for
- * each transformation. Unless LARGEDATA is defined, however, a more compact
- * table is used which looks up 16 4-bit "chunks" rather than 8 8-bit chunks.
- * The smaller table uses 16*16*8 = 2K bytes for each transformation. This
- * is slower but tolerable, particularly for password encryption in which
- * the SPE transformation is iterated many times. The small tables total 9K
- * bytes, the large tables total 72K bytes.
- *
- * The transformations used are:
- * IE3264: MSB->LSB conversion, initial permutation, and expansion.
- * This is done by collecting the 32 even-numbered bits and applying
- * a 32->64 bit transformation, and then collecting the 32 odd-numbered
- * bits and applying the same transformation. Since there are only
- * 32 input bits, the IE3264 transformation table is half the size of
- * the usual table.
- * CF6464: Compression, final permutation, and LSB->MSB conversion.
- * This is done by two trivial 48->32 bit compressions to obtain
- * a 64-bit block (the bit numbering is given in the "CIFP" table)
- * followed by a 64->64 bit "cleanup" transformation. (It would
- * be possible to group the bits in the 64-bit block so that 2
- * identical 32->32 bit transformations could be used instead,
- * saving a factor of 4 in space and possibly 2 in time, but
- * byte-ordering and other complications rear their ugly head.
- * Similar opportunities/problems arise in the key schedule
- * transforms.)
- * PC1ROT: MSB->LSB, PC1 permutation, rotate, and PC2 permutation.
- * This admittedly baroque 64->64 bit transformation is used to
- * produce the first code (in 8*(6+2) format) of the key schedule.
- * PC2ROT[0]: Inverse PC2 permutation, rotate, and PC2 permutation.
- * It would be possible to define 15 more transformations, each
- * with a different rotation, to generate the entire key schedule.
- * To save space, however, we instead permute each code into the
- * next by using a transformation that "undoes" the PC2 permutation,
- * rotates the code, and then applies PC2. Unfortunately, PC2
- * transforms 56 bits into 48 bits, dropping 8 bits, so PC2 is not
- * invertible. We get around that problem by using a modified PC2
- * which retains the 8 otherwise-lost bits in the unused low-order
- * bits of each byte. The low-order bits are cleared when the
- * codes are stored into the key schedule.
- * PC2ROT[1]: Same as PC2ROT[0], but with two rotations.
- * This is faster than applying PC2ROT[0] twice,
- *
- * The Bell Labs "salt" (Bob Baldwin):
- *
- * The salting is a simple permutation applied to the 48-bit result of E.
- * Specifically, if bit i (1 <= i <= 24) of the salt is set then bits i and
- * i+24 of the result are swapped. The salt is thus a 24 bit number, with
- * 16777216 possible values. (The original salt was 12 bits and could not
- * swap bits 13..24 with 36..48.)
- *
- * It is possible, but ugly, to warp the SPE table to account for the salt
- * permutation. Fortunately, the conditional bit swapping requires only
- * about four machine instructions and can be done on-the-fly with about an
- * 8% performance penalty.
- */
-
-typedef union
-{
- unsigned char b[8];
- struct
- {
- int32_t i0;
- int32_t i1;
- } b32;
-#if defined(B64)
- B64 b64;
-#endif
-} C_block;
-
-/*
- * Convert twenty-four-bit long in host-order
- * to six bits (and 2 low-order zeroes) per char little-endian format.
- */
-#define TO_SIX_BIT(rslt, src) { \
- C_block cvt; \
- cvt.b[0] = src; src >>= 6; \
- cvt.b[1] = src; src >>= 6; \
- cvt.b[2] = src; src >>= 6; \
- cvt.b[3] = src; \
- rslt = (cvt.b32.i0 & 0x3f3f3f3fL) << 2; \
- }
-
-/*
- * These macros may someday permit efficient use of 64-bit integers.
- */
-#define ZERO(d,d0,d1) d0 = 0, d1 = 0
-#define LOAD(d,d0,d1,bl) d0 = (bl).b32.i0, d1 = (bl).b32.i1
-#define LOADREG(d,d0,d1,s,s0,s1) d0 = s0, d1 = s1
-#define OR(d,d0,d1,bl) d0 |= (bl).b32.i0, d1 |= (bl).b32.i1
-#define STORE(s,s0,s1,bl) (bl).b32.i0 = s0, (bl).b32.i1 = s1
-#define DCL_BLOCK(d,d0,d1) int32_t d0, d1
-
-#if defined(LARGEDATA)
- /* Waste memory like crazy. Also, do permutations in line */
-#define LGCHUNKBITS 3
-#define CHUNKBITS (1<<LGCHUNKBITS)
-#define PERM6464(d,d0,d1,cpp,p) \
- LOAD(d,d0,d1,(p)[(0<<CHUNKBITS)+(cpp)[0]]); \
- OR (d,d0,d1,(p)[(1<<CHUNKBITS)+(cpp)[1]]); \
- OR (d,d0,d1,(p)[(2<<CHUNKBITS)+(cpp)[2]]); \
- OR (d,d0,d1,(p)[(3<<CHUNKBITS)+(cpp)[3]]); \
- OR (d,d0,d1,(p)[(4<<CHUNKBITS)+(cpp)[4]]); \
- OR (d,d0,d1,(p)[(5<<CHUNKBITS)+(cpp)[5]]); \
- OR (d,d0,d1,(p)[(6<<CHUNKBITS)+(cpp)[6]]); \
- OR (d,d0,d1,(p)[(7<<CHUNKBITS)+(cpp)[7]]);
-#define PERM3264(d,d0,d1,cpp,p) \
- LOAD(d,d0,d1,(p)[(0<<CHUNKBITS)+(cpp)[0]]); \
- OR (d,d0,d1,(p)[(1<<CHUNKBITS)+(cpp)[1]]); \
- OR (d,d0,d1,(p)[(2<<CHUNKBITS)+(cpp)[2]]); \
- OR (d,d0,d1,(p)[(3<<CHUNKBITS)+(cpp)[3]]);
-#else
- /* "small data" */
-#define LGCHUNKBITS 2
-#define CHUNKBITS (1<<LGCHUNKBITS)
-#define PERM6464(d,d0,d1,cpp,p) \
- { C_block tblk; permute(cpp,&tblk,p,8); LOAD (d,d0,d1,tblk); }
-#define PERM3264(d,d0,d1,cpp,p) \
- { C_block tblk; permute(cpp,&tblk,p,4); LOAD (d,d0,d1,tblk); }
-#endif /* LARGEDATA */
-
-STATIC init_des(void);
-STATIC init_perm(C_block[64 / CHUNKBITS][1 << CHUNKBITS], unsigned char[64], int, int);
-
-#ifndef LARGEDATA
-STATIC permute(unsigned char *, C_block *, C_block *, int);
-#endif
-#ifdef DEBUG
-STATIC prtab(char *, unsigned char *, int);
-#endif
-
-
-#ifndef LARGEDATA
-STATIC
-permute(cp, out, p, chars_in)
-unsigned char *cp;
-C_block *out;
-C_block *p;
-int chars_in;
-{
- DCL_BLOCK(D, D0, D1);
- C_block *tp;
- int t;
-
- ZERO(D, D0, D1);
- do
- {
- t = *cp++;
- tp = &p[t & 0xf];
- OR(D, D0, D1, *tp);
- p += (1 << CHUNKBITS);
- tp = &p[t >> 4];
- OR(D, D0, D1, *tp);
- p += (1 << CHUNKBITS);
- } while (--chars_in > 0);
- STORE(D, D0, D1, *out);
-}
-#endif /* LARGEDATA */
-
-
-/* ===== (mostly) Standard DES Tables ==================== */
-
-static const unsigned char IP[] = { /* initial permutation */
- 58, 50, 42, 34, 26, 18, 10, 2,
- 60, 52, 44, 36, 28, 20, 12, 4,
- 62, 54, 46, 38, 30, 22, 14, 6,
- 64, 56, 48, 40, 32, 24, 16, 8,
- 57, 49, 41, 33, 25, 17, 9, 1,
- 59, 51, 43, 35, 27, 19, 11, 3,
- 61, 53, 45, 37, 29, 21, 13, 5,
- 63, 55, 47, 39, 31, 23, 15, 7,
-};
-
-/* The final permutation is the inverse of IP - no table is necessary */
-
-static const unsigned char ExpandTr[] = { /* expansion operation */
- 32, 1, 2, 3, 4, 5,
- 4, 5, 6, 7, 8, 9,
- 8, 9, 10, 11, 12, 13,
- 12, 13, 14, 15, 16, 17,
- 16, 17, 18, 19, 20, 21,
- 20, 21, 22, 23, 24, 25,
- 24, 25, 26, 27, 28, 29,
- 28, 29, 30, 31, 32, 1,
-};
-
-static const unsigned char PC1[] = { /* permuted choice table 1 */
- 57, 49, 41, 33, 25, 17, 9,
- 1, 58, 50, 42, 34, 26, 18,
- 10, 2, 59, 51, 43, 35, 27,
- 19, 11, 3, 60, 52, 44, 36,
-
- 63, 55, 47, 39, 31, 23, 15,
- 7, 62, 54, 46, 38, 30, 22,
- 14, 6, 61, 53, 45, 37, 29,
- 21, 13, 5, 28, 20, 12, 4,
-};
-
-static const unsigned char Rotates[] = { /* PC1 rotation schedule */
- 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
-};
-
-/* note: each "row" of PC2 is left-padded with bits that make it invertible */
-static const unsigned char PC2[] = { /* permuted choice table 2 */
- 9, 18, 14, 17, 11, 24, 1, 5,
- 22, 25, 3, 28, 15, 6, 21, 10,
- 35, 38, 23, 19, 12, 4, 26, 8,
- 43, 54, 16, 7, 27, 20, 13, 2,
-
- 0, 0, 41, 52, 31, 37, 47, 55,
- 0, 0, 30, 40, 51, 45, 33, 48,
- 0, 0, 44, 49, 39, 56, 34, 53,
- 0, 0, 46, 42, 50, 36, 29, 32,
-};
-
-static const unsigned char S[8][64] = { /* 48->32 bit substitution tables */
- /* S[1] */
- {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
- 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
- 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
- 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},
- /* S[2] */
- {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
- 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
- 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
- 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},
- /* S[3] */
- {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
- 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
- 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
- 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},
- /* S[4] */
- {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
- 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
- 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
- 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},
- /* S[5] */
- {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
- 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
- 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
- 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},
- /* S[6] */
- {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
- 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
- 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
- 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},
- /* S[7] */
- {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
- 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
- 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
- 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},
- /* S[8] */
- {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
- 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
- 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
- 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}
-};
-
-static const unsigned char P32Tr[] = { /* 32-bit permutation function */
- 16, 7, 20, 21,
- 29, 12, 28, 17,
- 1, 15, 23, 26,
- 5, 18, 31, 10,
- 2, 8, 24, 14,
- 32, 27, 3, 9,
- 19, 13, 30, 6,
- 22, 11, 4, 25,
-};
-
-static const unsigned char CIFP[] = { /* compressed/interleaved permutation */
- 1, 2, 3, 4, 17, 18, 19, 20,
- 5, 6, 7, 8, 21, 22, 23, 24,
- 9, 10, 11, 12, 25, 26, 27, 28,
- 13, 14, 15, 16, 29, 30, 31, 32,
-
- 33, 34, 35, 36, 49, 50, 51, 52,
- 37, 38, 39, 40, 53, 54, 55, 56,
- 41, 42, 43, 44, 57, 58, 59, 60,
- 45, 46, 47, 48, 61, 62, 63, 64,
-};
-
-static const unsigned char itoa64[] = /* 0..63 => ascii-64 */
-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-
-/* ===== Tables that are initialized at run time ==================== */
-
-
-static unsigned char a64toi[128]; /* ascii-64 => 0..63 */
-
-/* Initial key schedule permutation */
-static C_block PC1ROT[64 / CHUNKBITS][1 << CHUNKBITS];
-
-/* Subsequent key schedule rotation permutations */
-static C_block PC2ROT[2][64 / CHUNKBITS][1 << CHUNKBITS];
-
-/* Initial permutation/expansion table */
-static C_block IE3264[32 / CHUNKBITS][1 << CHUNKBITS];
-
-/* Table that combines the S, P, and E operations. */
-static int32_t SPE[2][8][64];
-
-/* compressed/interleaved => final permutation table */
-static C_block CF6464[64 / CHUNKBITS][1 << CHUNKBITS];
-
-
-/* ==================================== */
-
-
-static C_block constdatablock; /* encryption constant */
-static char cryptresult[1 + 4 + 4 + 11 + 1]; /* encrypted result */
-
-extern char *__md5crypt(const char *, const char *); /* XXX */
-extern char *__bcrypt(const char *, const char *); /* XXX */
-
-
-/*
- * Return a pointer to static data consisting of the "setting"
- * followed by an encryption produced by the "key" and "setting".
- */
-char *
-crypt(key, setting)
-const char *key;
-const char *setting;
-{
- char *encp;
- int32_t i;
- int t;
- int32_t salt;
- int num_iter,
- salt_size;
- C_block keyblock,
- rsltblock;
-
-#if 0
- /* Non-DES encryption schemes hook in here. */
- if (setting[0] == _PASSWORD_NONDES)
- {
- switch (setting[1])
- {
- case '2':
- return (__bcrypt(key, setting));
- case '1':
- default:
- return (__md5crypt(key, setting));
- }
- }
-#endif
-
- for (i = 0; i < 8; i++)
- {
- if ((t = 2 * (unsigned char) (*key)) != 0)
- key++;
- keyblock.b[i] = t;
- }
- if (des_setkey((char *) keyblock.b)) /* also initializes "a64toi" */
- return (NULL);
-
- encp = &cryptresult[0];
- switch (*setting)
- {
- case _PASSWORD_EFMT1:
-
- /*
- * Involve the rest of the password 8 characters at a time.
- */
- while (*key)
- {
- if (des_cipher((char *) (void *) &keyblock,
- (char *) (void *) &keyblock, 0L, 1))
- return (NULL);
- for (i = 0; i < 8; i++)
- {
- if ((t = 2 * (unsigned char) (*key)) != 0)
- key++;
- keyblock.b[i] ^= t;
- }
- if (des_setkey((char *) keyblock.b))
- return (NULL);
- }
-
- *encp++ = *setting++;
-
- /* get iteration count */
- num_iter = 0;
- for (i = 4; --i >= 0;)
- {
- if ((t = (unsigned char) setting[i]) == '\0')
- t = '.';
- encp[i] = t;
- num_iter = (num_iter << 6) | a64toi[t];
- }
- setting += 4;
- encp += 4;
- salt_size = 4;
- break;
- default:
- num_iter = 25;
- salt_size = 2;
- }
-
- salt = 0;
- for (i = salt_size; --i >= 0;)
- {
- if ((t = (unsigned char) setting[i]) == '\0')
- t = '.';
- encp[i] = t;
- salt = (salt << 6) | a64toi[t];
- }
- encp += salt_size;
- if (des_cipher((char *) (void *) &constdatablock,
- (char *) (void *) &rsltblock, salt, num_iter))
- return (NULL);
-
- /*
- * Encode the 64 cipher bits as 11 ascii characters.
- */
- i = ((int32_t) ((rsltblock.b[0] << 8) | rsltblock.b[1]) << 8) |
- rsltblock.b[2];
- encp[3] = itoa64[i & 0x3f];
- i >>= 6;
- encp[2] = itoa64[i & 0x3f];
- i >>= 6;
- encp[1] = itoa64[i & 0x3f];
- i >>= 6;
- encp[0] = itoa64[i];
- encp += 4;
- i = ((int32_t) ((rsltblock.b[3] << 8) | rsltblock.b[4]) << 8) |
- rsltblock.b[5];
- encp[3] = itoa64[i & 0x3f];
- i >>= 6;
- encp[2] = itoa64[i & 0x3f];
- i >>= 6;
- encp[1] = itoa64[i & 0x3f];
- i >>= 6;
- encp[0] = itoa64[i];
- encp += 4;
- i = ((int32_t) ((rsltblock.b[6]) << 8) | rsltblock.b[7]) << 2;
- encp[2] = itoa64[i & 0x3f];
- i >>= 6;
- encp[1] = itoa64[i & 0x3f];
- i >>= 6;
- encp[0] = itoa64[i];
-
- encp[3] = 0;
-
- return (cryptresult);
-}
-
-
-/*
- * The Key Schedule, filled in by des_setkey() or setkey().
- */
-#define KS_SIZE 16
-static C_block KS[KS_SIZE];
-
-static volatile int des_ready = 0;
-
-/*
- * Set up the key schedule from the key.
- */
-static int
-des_setkey(key)
-const char *key;
-{
- DCL_BLOCK(K, K0, K1);
- C_block *ptabp;
- int i;
-
- if (!des_ready)
- init_des();
-
- PERM6464(K, K0, K1, (unsigned char *) key, (C_block *) PC1ROT);
- key = (char *) &KS[0];
- STORE(K & ~0x03030303L, K0 & ~0x03030303L, K1, *(C_block *) key);
- for (i = 1; i < 16; i++)
- {
- key += sizeof(C_block);
- STORE(K, K0, K1, *(C_block *) key);
- ptabp = (C_block *) PC2ROT[Rotates[i] - 1];
- PERM6464(K, K0, K1, (unsigned char *) key, ptabp);
- STORE(K & ~0x03030303L, K0 & ~0x03030303L, K1, *(C_block *) key);
- }
- return (0);
-}
-
-/*
- * Encrypt (or decrypt if num_iter < 0) the 8 chars at "in" with abs(num_iter)
- * iterations of DES, using the given 24-bit salt and the pre-computed key
- * schedule, and store the resulting 8 chars at "out" (in == out is permitted).
- *
- * NOTE: the performance of this routine is critically dependent on your
- * compiler and machine architecture.
- */
-static int
-des_cipher(in, out, salt, num_iter)
-const char *in;
-char *out;
-long salt;
-int num_iter;
-{
- /* variables that we want in registers, most important first */
-#if defined(pdp11)
- int j;
-#endif
- int32_t L0,
- L1,
- R0,
- R1,
- k;
- C_block *kp;
- int ks_inc,
- loop_count;
- C_block B;
-
- L0 = salt;
- TO_SIX_BIT(salt, L0); /* convert to 4*(6+2) format */
-
-#if defined(__vax__) || defined(pdp11)
- salt = ~salt; /* "x &~ y" is faster than "x & y". */
-#define SALT (~salt)
-#else
-#define SALT salt
-#endif
-
-#if defined(MUST_ALIGN)
- B.b[0] = in[0];
- B.b[1] = in[1];
- B.b[2] = in[2];
- B.b[3] = in[3];
- B.b[4] = in[4];
- B.b[5] = in[5];
- B.b[6] = in[6];
- B.b[7] = in[7];
- LOAD(L, L0, L1, B);
-#else
- LOAD(L, L0, L1, *(C_block *) in);
-#endif
- LOADREG(R, R0, R1, L, L0, L1);
- L0 &= 0x55555555L;
- L1 &= 0x55555555L;
- L0 = (L0 << 1) | L1; /* L0 is the even-numbered input bits */
- R0 &= 0xaaaaaaaaL;
- R1 = (R1 >> 1) & 0x55555555L;
- L1 = R0 | R1; /* L1 is the odd-numbered input bits */
- STORE(L, L0, L1, B);
- PERM3264(L, L0, L1, B.b, (C_block *) IE3264); /* even bits */
- PERM3264(R, R0, R1, B.b + 4, (C_block *) IE3264); /* odd bits */
-
- if (num_iter >= 0)
- { /* encryption */
- kp = &KS[0];
- ks_inc = sizeof(*kp);
- }
- else
- { /* decryption */
- num_iter = -num_iter;
- kp = &KS[KS_SIZE - 1];
- ks_inc = -(long) sizeof(*kp);
- }
-
- while (--num_iter >= 0)
- {
- loop_count = 8;
- do
- {
-
-#define SPTAB(t, i) \
- (*(int32_t *)((unsigned char *)(t) + (i)*(sizeof(int32_t)/4)))
-#if defined(gould)
- /* use this if B.b[i] is evaluated just once ... */
-#define DOXOR(x,y,i) x^=SPTAB(SPE[0][i],B.b[i]); y^=SPTAB(SPE[1][i],B.b[i]);
-#else
-#if defined(pdp11)
- /* use this if your "long" int indexing is slow */
-#define DOXOR(x,y,i) j=B.b[i]; x^=SPTAB(SPE[0][i],j); y^=SPTAB(SPE[1][i],j);
-#else
- /* use this if "k" is allocated to a register ... */
-#define DOXOR(x,y,i) k=B.b[i]; x^=SPTAB(SPE[0][i],k); y^=SPTAB(SPE[1][i],k);
-#endif
-#endif
-
-#define CRUNCH(p0, p1, q0, q1) \
- k = ((q0) ^ (q1)) & SALT; \
- B.b32.i0 = k ^ (q0) ^ kp->b32.i0; \
- B.b32.i1 = k ^ (q1) ^ kp->b32.i1; \
- kp = (C_block *)((char *)kp+ks_inc); \
- \
- DOXOR(p0, p1, 0); \
- DOXOR(p0, p1, 1); \
- DOXOR(p0, p1, 2); \
- DOXOR(p0, p1, 3); \
- DOXOR(p0, p1, 4); \
- DOXOR(p0, p1, 5); \
- DOXOR(p0, p1, 6); \
- DOXOR(p0, p1, 7);
-
- CRUNCH(L0, L1, R0, R1);
- CRUNCH(R0, R1, L0, L1);
- } while (--loop_count != 0);
- kp = (C_block *) ((char *) kp - (ks_inc * KS_SIZE));
-
-
- /* swap L and R */
- L0 ^= R0;
- L1 ^= R1;
- R0 ^= L0;
- R1 ^= L1;
- L0 ^= R0;
- L1 ^= R1;
- }
-
- /* store the encrypted (or decrypted) result */
- L0 = ((L0 >> 3) & 0x0f0f0f0fL) | ((L1 << 1) & 0xf0f0f0f0L);
- L1 = ((R0 >> 3) & 0x0f0f0f0fL) | ((R1 << 1) & 0xf0f0f0f0L);
- STORE(L, L0, L1, B);
- PERM6464(L, L0, L1, B.b, (C_block *) CF6464);
-#if defined(MUST_ALIGN)
- STORE(L, L0, L1, B);
- out[0] = B.b[0];
- out[1] = B.b[1];
- out[2] = B.b[2];
- out[3] = B.b[3];
- out[4] = B.b[4];
- out[5] = B.b[5];
- out[6] = B.b[6];
- out[7] = B.b[7];
-#else
- STORE(L, L0, L1, *(C_block *) out);
-#endif
- return (0);
-}
-
-
-/*
- * Initialize various tables. This need only be done once. It could even be
- * done at compile time, if the compiler were capable of that sort of thing.
- */
-STATIC
-init_des()
-{
- int i,
- j;
- int32_t k;
- int tableno;
- static unsigned char perm[64],
- tmp32[32]; /* "static" for speed */
-
-/* static volatile long init_start = 0; not used */
-
- /*
- * table that converts chars "./0-9A-Za-z"to integers 0-63.
- */
- for (i = 0; i < 64; i++)
- a64toi[itoa64[i]] = i;
-
- /*
- * PC1ROT - bit reverse, then PC1, then Rotate, then PC2.
- */
- for (i = 0; i < 64; i++)
- perm[i] = 0;
- for (i = 0; i < 64; i++)
- {
- if ((k = PC2[i]) == 0)
- continue;
- k += Rotates[0] - 1;
- if ((k % 28) < Rotates[0])
- k -= 28;
- k = PC1[k];
- if (k > 0)
- {
- k--;
- k = (k | 07) - (k & 07);
- k++;
- }
- perm[i] = k;
- }
-#ifdef DEBUG
- prtab("pc1tab", perm, 8);
-#endif
- init_perm(PC1ROT, perm, 8, 8);
-
- /*
- * PC2ROT - PC2 inverse, then Rotate (once or twice), then PC2.
- */
- for (j = 0; j < 2; j++)
- {
- unsigned char pc2inv[64];
-
- for (i = 0; i < 64; i++)
- perm[i] = pc2inv[i] = 0;
- for (i = 0; i < 64; i++)
- {
- if ((k = PC2[i]) == 0)
- continue;
- pc2inv[k - 1] = i + 1;
- }
- for (i = 0; i < 64; i++)
- {
- if ((k = PC2[i]) == 0)
- continue;
- k += j;
- if ((k % 28) <= j)
- k -= 28;
- perm[i] = pc2inv[k];
- }
-#ifdef DEBUG
- prtab("pc2tab", perm, 8);
-#endif
- init_perm(PC2ROT[j], perm, 8, 8);
- }
-
- /*
- * Bit reverse, then initial permutation, then expansion.
- */
- for (i = 0; i < 8; i++)
- {
- for (j = 0; j < 8; j++)
- {
- k = (j < 2) ? 0 : IP[ExpandTr[i * 6 + j - 2] - 1];
- if (k > 32)
- k -= 32;
- else if (k > 0)
- k--;
- if (k > 0)
- {
- k--;
- k = (k | 07) - (k & 07);
- k++;
- }
- perm[i * 8 + j] = k;
- }
- }
-#ifdef DEBUG
- prtab("ietab", perm, 8);
-#endif
- init_perm(IE3264, perm, 4, 8);
-
- /*
- * Compression, then final permutation, then bit reverse.
- */
- for (i = 0; i < 64; i++)
- {
- k = IP[CIFP[i] - 1];
- if (k > 0)
- {
- k--;
- k = (k | 07) - (k & 07);
- k++;
- }
- perm[k - 1] = i + 1;
- }
-#ifdef DEBUG
- prtab("cftab", perm, 8);
-#endif
- init_perm(CF6464, perm, 8, 8);
-
- /*
- * SPE table
- */
- for (i = 0; i < 48; i++)
- perm[i] = P32Tr[ExpandTr[i] - 1];
- for (tableno = 0; tableno < 8; tableno++)
- {
- for (j = 0; j < 64; j++)
- {
- k = (((j >> 0) & 01) << 5) |
- (((j >> 1) & 01) << 3) |
- (((j >> 2) & 01) << 2) |
- (((j >> 3) & 01) << 1) |
- (((j >> 4) & 01) << 0) |
- (((j >> 5) & 01) << 4);
- k = S[tableno][k];
- k = (((k >> 3) & 01) << 0) |
- (((k >> 2) & 01) << 1) |
- (((k >> 1) & 01) << 2) |
- (((k >> 0) & 01) << 3);
- for (i = 0; i < 32; i++)
- tmp32[i] = 0;
- for (i = 0; i < 4; i++)
- tmp32[4 * tableno + i] = (k >> i) & 01;
- k = 0;
- for (i = 24; --i >= 0;)
- k = (k << 1) | tmp32[perm[i] - 1];
- TO_SIX_BIT(SPE[0][tableno][j], k);
- k = 0;
- for (i = 24; --i >= 0;)
- k = (k << 1) | tmp32[perm[i + 24] - 1];
- TO_SIX_BIT(SPE[1][tableno][j], k);
- }
- }
-
- des_ready = 1;
-}
-
-/*
- * Initialize "perm" to represent transformation "p", which rearranges
- * (perhaps with expansion and/or contraction) one packed array of bits
- * (of size "chars_in" characters) into another array (of size "chars_out"
- * characters).
- *
- * "perm" must be all-zeroes on entry to this routine.
- */
-STATIC
-init_perm(perm, p, chars_in, chars_out)
-C_block perm[64 / CHUNKBITS][1 << CHUNKBITS];
-unsigned char p[64];
-int chars_in,
- chars_out;
-{
- int i,
- j,
- k,
- l;
-
- for (k = 0; k < chars_out * 8; k++)
- { /* each output bit position */
- l = p[k] - 1; /* where this bit comes from */
- if (l < 0)
- continue; /* output bit is always 0 */
- i = l >> LGCHUNKBITS; /* which chunk this bit comes from */
- l = 1 << (l & (CHUNKBITS - 1)); /* mask for this bit */
- for (j = 0; j < (1 << CHUNKBITS); j++)
- { /* each chunk value */
- if ((j & l) != 0)
- perm[i][j].b[k >> 3] |= 1 << (k & 07);
- }
- }
-}
-
-/*
- * "setkey" routine (for backwards compatibility)
- */
-#ifdef NOT_USED
-int
-setkey(key)
-const char *key;
-{
- int i,
- j,
- k;
- C_block keyblock;
-
- for (i = 0; i < 8; i++)
- {
- k = 0;
- for (j = 0; j < 8; j++)
- {
- k <<= 1;
- k |= (unsigned char) *key++;
- }
- keyblock.b[i] = k;
- }
- return (des_setkey((char *) keyblock.b));
-}
-
-/*
- * "encrypt" routine (for backwards compatibility)
- */
-static int
-encrypt(block, flag)
-char *block;
-int flag;
-{
- int i,
- j,
- k;
- C_block cblock;
-
- for (i = 0; i < 8; i++)
- {
- k = 0;
- for (j = 0; j < 8; j++)
- {
- k <<= 1;
- k |= (unsigned char) *block++;
- }
- cblock.b[i] = k;
- }
- if (des_cipher((char *) &cblock, (char *) &cblock, 0L, (flag ? -1 : 1)))
- return (1);
- for (i = 7; i >= 0; i--)
- {
- k = cblock.b[i];
- for (j = 7; j >= 0; j--)
- {
- *--block = k & 01;
- k >>= 1;
- }
- }
- return (0);
-}
-#endif
-
-#ifdef DEBUG
-STATIC
-prtab(s, t, num_rows)
-char *s;
-unsigned char *t;
-int num_rows;
-{
- int i,
- j;
-
- (void) printf("%s:\n", s);
- for (i = 0; i < num_rows; i++)
- {
- for (j = 0; j < 8; j++)
- (void) printf("%3d", t[i * 8 + j]);
- (void) printf("\n");
- }
- (void) printf("\n");
-}
-
-#endif
diff --git a/libpq/win32/getaddrinfo.c b/libpq/win32/getaddrinfo.c
deleted file mode 100644
index 90c1b87..0000000
--- a/libpq/win32/getaddrinfo.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * getaddrinfo.c
- * Support getaddrinfo() on platforms that don't have it.
- *
- * We also supply getnameinfo() here, assuming that the platform will have
- * it if and only if it has getaddrinfo(). If this proves false on some
- * platform, we'll need to split this file and provide a separate configure
- * test for getnameinfo().
- *
- * Windows may or may not have these routines, so we handle Windows specially
- * by dynamically checking for their existence. If they already exist, we
- * use the Windows native routines, but if not, we use our own.
- *
- *
- * Copyright (c) 2003-2016, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- * src/port/getaddrinfo.c
- *
- *-------------------------------------------------------------------------
- */
-
-/* This is intended to be used in both frontend and backend, so use c.h */
-#include "c.h"
-
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "getaddrinfo.h"
-#include "libpq/pqcomm.h" /* needed for struct sockaddr_storage */
-
-
-#ifdef WIN32
-/*
- * The native routines may or may not exist on the Windows platform we are on,
- * so we dynamically look up the routines, and call them via function pointers.
- * Here we need to declare what the function pointers look like
- */
-typedef int (__stdcall * getaddrinfo_ptr_t) (const char *nodename,
- const char *servname,
- const struct addrinfo * hints,
- struct addrinfo ** res);
-
-typedef void (__stdcall * freeaddrinfo_ptr_t) (struct addrinfo * ai);
-
-typedef int (__stdcall * getnameinfo_ptr_t) (const struct sockaddr * sa,
- int salen,
- char *host, int hostlen,
- char *serv, int servlen,
- int flags);
-
-/* static pointers to the native routines, so we only do the lookup once. */
-static getaddrinfo_ptr_t getaddrinfo_ptr = NULL;
-static freeaddrinfo_ptr_t freeaddrinfo_ptr = NULL;
-static getnameinfo_ptr_t getnameinfo_ptr = NULL;
-
-
-static bool
-haveNativeWindowsIPv6routines(void)
-{
- void *hLibrary = NULL;
- static bool alreadyLookedForIpv6routines = false;
-
- if (alreadyLookedForIpv6routines)
- return (getaddrinfo_ptr != NULL);
-
- /*
- * For Windows XP and Windows 2003 (and longhorn/vista), the IPv6 routines
- * are present in the WinSock 2 library (ws2_32.dll). Try that first
- */
-
- hLibrary = LoadLibraryA("ws2_32");
-
- if (hLibrary == NULL || GetProcAddress(hLibrary, "getaddrinfo") == NULL)
- {
- /*
- * Well, ws2_32 doesn't exist, or more likely doesn't have
- * getaddrinfo.
- */
- if (hLibrary != NULL)
- FreeLibrary(hLibrary);
-
- /*
- * In Windows 2000, there was only the IPv6 Technology Preview look in
- * the IPv6 WinSock library (wship6.dll).
- */
-
- hLibrary = LoadLibraryA("wship6");
- }
-
- /* If hLibrary is null, we couldn't find a dll with functions */
- if (hLibrary != NULL)
- {
- /* We found a dll, so now get the addresses of the routines */
-
- getaddrinfo_ptr = (getaddrinfo_ptr_t) GetProcAddress(hLibrary,
- "getaddrinfo");
- freeaddrinfo_ptr = (freeaddrinfo_ptr_t) GetProcAddress(hLibrary,
- "freeaddrinfo");
- getnameinfo_ptr = (getnameinfo_ptr_t) GetProcAddress(hLibrary,
- "getnameinfo");
-
- /*
- * If any one of the routines is missing, let's play it safe and
- * ignore them all
- */
- if (getaddrinfo_ptr == NULL ||
- freeaddrinfo_ptr == NULL ||
- getnameinfo_ptr == NULL)
- {
- FreeLibrary(hLibrary);
- hLibrary = NULL;
- getaddrinfo_ptr = NULL;
- freeaddrinfo_ptr = NULL;
- getnameinfo_ptr = NULL;
- }
- }
-
- alreadyLookedForIpv6routines = true;
- return (getaddrinfo_ptr != NULL);
-}
-#endif
-
-
-/*
- * get address info for ipv4 sockets.
- *
- * Bugs: - only one addrinfo is set even though hintp is NULL or
- * ai_socktype is 0
- * - AI_CANONNAME is not supported.
- * - servname can only be a number, not text.
- */
-int
-getaddrinfo(const char *node, const char *service,
- const struct addrinfo * hintp,
- struct addrinfo ** res)
-{
- struct addrinfo *ai;
- struct sockaddr_in sin,
- *psin;
- struct addrinfo hints;
-
-#ifdef WIN32
-
- /*
- * If Windows has native IPv6 support, use the native Windows routine.
- * Otherwise, fall through and use our own code.
- */
- if (haveNativeWindowsIPv6routines())
- return (*getaddrinfo_ptr) (node, service, hintp, res);
-#endif
-
- if (hintp == NULL)
- {
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
- }
- else
- memcpy(&hints, hintp, sizeof(hints));
-
- if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC)
- return EAI_FAMILY;
-
- if (hints.ai_socktype == 0)
- hints.ai_socktype = SOCK_STREAM;
-
- if (!node && !service)
- return EAI_NONAME;
-
- memset(&sin, 0, sizeof(sin));
-
- sin.sin_family = AF_INET;
-
- if (node)
- {
- if (node[0] == '\0')
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- else if (hints.ai_flags & AI_NUMERICHOST)
- {
- if (!inet_aton(node, &sin.sin_addr))
- return EAI_NONAME;
- }
- else
- {
- struct hostent *hp;
-
-#ifdef FRONTEND
- struct hostent hpstr;
- char buf[BUFSIZ];
- int herrno = 0;
-
- pqGethostbyname(node, &hpstr, buf, sizeof(buf),
- &hp, &herrno);
-#else
- hp = gethostbyname(node);
-#endif
- if (hp == NULL)
- {
- switch (h_errno)
- {
- case HOST_NOT_FOUND:
- case NO_DATA:
- return EAI_NONAME;
- case TRY_AGAIN:
- return EAI_AGAIN;
- case NO_RECOVERY:
- default:
- return EAI_FAIL;
- }
- }
- if (hp->h_addrtype != AF_INET)
- return EAI_FAIL;
-
- memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
- }
- }
- else
- {
- if (hints.ai_flags & AI_PASSIVE)
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- else
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- }
-
- if (service)
- sin.sin_port = htons((unsigned short) atoi(service));
-
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
- sin.sin_len = sizeof(sin);
-#endif
-
- ai = malloc(sizeof(*ai));
- if (!ai)
- return EAI_MEMORY;
-
- psin = malloc(sizeof(*psin));
- if (!psin)
- {
- free(ai);
- return EAI_MEMORY;
- }
-
- memcpy(psin, &sin, sizeof(*psin));
-
- ai->ai_flags = 0;
- ai->ai_family = AF_INET;
- ai->ai_socktype = hints.ai_socktype;
- ai->ai_protocol = hints.ai_protocol;
- ai->ai_addrlen = sizeof(*psin);
- ai->ai_addr = (struct sockaddr *) psin;
- ai->ai_canonname = NULL;
- ai->ai_next = NULL;
-
- *res = ai;
-
- return 0;
-}
-
-
-void
-freeaddrinfo(struct addrinfo * res)
-{
- if (res)
- {
-#ifdef WIN32
-
- /*
- * If Windows has native IPv6 support, use the native Windows routine.
- * Otherwise, fall through and use our own code.
- */
- if (haveNativeWindowsIPv6routines())
- {
- (*freeaddrinfo_ptr) (res);
- return;
- }
-#endif
-
- if (res->ai_addr)
- free(res->ai_addr);
- free(res);
- }
-}
-
-
-const char *
-gai_strerror(int errcode)
-{
-#ifdef HAVE_HSTRERROR
- int hcode;
-
- switch (errcode)
- {
- case EAI_NONAME:
- hcode = HOST_NOT_FOUND;
- break;
- case EAI_AGAIN:
- hcode = TRY_AGAIN;
- break;
- case EAI_FAIL:
- default:
- hcode = NO_RECOVERY;
- break;
- }
-
- return hstrerror(hcode);
-#else /* !HAVE_HSTRERROR */
-
- switch (errcode)
- {
- case EAI_NONAME:
- return "Unknown host";
- case EAI_AGAIN:
- return "Host name lookup failure";
- /* Errors below are probably WIN32 only */
-#ifdef EAI_BADFLAGS
- case EAI_BADFLAGS:
- return "Invalid argument";
-#endif
-#ifdef EAI_FAMILY
- case EAI_FAMILY:
- return "Address family not supported";
-#endif
-#ifdef EAI_MEMORY
- case EAI_MEMORY:
- return "Not enough memory";
-#endif
-#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME /* MSVC/WIN64 duplicate */
- case EAI_NODATA:
- return "No host data of that type was found";
-#endif
-#ifdef EAI_SERVICE
- case EAI_SERVICE:
- return "Class type not found";
-#endif
-#ifdef EAI_SOCKTYPE
- case EAI_SOCKTYPE:
- return "Socket type not supported";
-#endif
- default:
- return "Unknown server error";
- }
-#endif /* HAVE_HSTRERROR */
-}
-
-/*
- * Convert an ipv4 address to a hostname.
- *
- * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV behavior.
- * It will never resolve a hostname.
- * - No IPv6 support.
- */
-int
-getnameinfo(const struct sockaddr * sa, int salen,
- char *node, int nodelen,
- char *service, int servicelen, int flags)
-{
-#ifdef WIN32
-
- /*
- * If Windows has native IPv6 support, use the native Windows routine.
- * Otherwise, fall through and use our own code.
- */
- if (haveNativeWindowsIPv6routines())
- return (*getnameinfo_ptr) (sa, salen, node, nodelen,
- service, servicelen, flags);
-#endif
-
- /* Invalid arguments. */
- if (sa == NULL || (node == NULL && service == NULL))
- return EAI_FAIL;
-
-#ifdef HAVE_IPV6
- if (sa->sa_family == AF_INET6)
- return EAI_FAMILY;
-#endif
-
- /* Unsupported flags. */
- if (flags & NI_NAMEREQD)
- return EAI_AGAIN;
-
- if (node)
- {
- if (sa->sa_family == AF_INET)
- {
- if (inet_net_ntop(AF_INET, &((struct sockaddr_in *) sa)->sin_addr,
- sa->sa_family == AF_INET ? 32 : 128,
- node, nodelen) == NULL)
- return EAI_MEMORY;
- }
- else
- return EAI_MEMORY;
- }
-
- if (service)
- {
- int ret = -1;
-
- if (sa->sa_family == AF_INET)
- {
- ret = snprintf(service, servicelen, "%d",
- ntohs(((struct sockaddr_in *) sa)->sin_port));
- }
- if (ret == -1 || ret >= servicelen)
- return EAI_MEMORY;
- }
-
- return 0;
-}
diff --git a/libpq/win32/inet_aton.c b/libpq/win32/inet_aton.c
deleted file mode 100644
index 27e8aaa..0000000
--- a/libpq/win32/inet_aton.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* src/port/inet_aton.c
- *
- * This inet_aton() function was taken from the GNU C library and
- * incorporated into Postgres for those systems which do not have this
- * routine in their standard C libraries.
- *
- * The function was been extracted whole from the file inet_aton.c in
- * Release 5.3.12 of the Linux C library, which is derived from the
- * GNU C library, by Bryan Henderson in October 1996. The copyright
- * notice from that file is below.
- */
-
-/*
- * Copyright (c) 1983, 1990, 1993
- * The Regents of the University of California. 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.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 "c.h"
-
-#include <netinet/in.h>
-#include <ctype.h>
-
-/*
- * Check whether "cp" is a valid ascii representation
- * of an Internet address and convert to a binary address.
- * Returns 1 if the address is valid, 0 if not.
- * This replaces inet_addr, the return value from which
- * cannot distinguish between failure and a local broadcast address.
- */
-int
-inet_aton(const char *cp, struct in_addr * addr)
-{
- unsigned int val;
- int base,
- n;
- char c;
- u_int parts[4];
- u_int *pp = parts;
-
- for (;;)
- {
- /*
- * Collect number up to ``.''. Values are specified as for C: 0x=hex,
- * 0=octal, other=decimal.
- */
- val = 0;
- base = 10;
- if (*cp == '0')
- {
- if (*++cp == 'x' || *cp == 'X')
- base = 16, cp++;
- else
- base = 8;
- }
- while ((c = *cp) != '\0')
- {
- if (isdigit((unsigned char) c))
- {
- val = (val * base) + (c - '0');
- cp++;
- continue;
- }
- if (base == 16 && isxdigit((unsigned char) c))
- {
- val = (val << 4) +
- (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
- cp++;
- continue;
- }
- break;
- }
- if (*cp == '.')
- {
- /*
- * Internet format: a.b.c.d a.b.c (with c treated as 16-bits)
- * a.b (with b treated as 24 bits)
- */
- if (pp >= parts + 3 || val > 0xff)
- return 0;
- *pp++ = val, cp++;
- }
- else
- break;
- }
-
- /*
- * Check for trailing junk.
- */
- while (*cp)
- if (!isspace((unsigned char) *cp++))
- return 0;
-
- /*
- * Concoct the address according to the number of parts specified.
- */
- n = pp - parts + 1;
- switch (n)
- {
-
- case 1: /* a -- 32 bits */
- break;
-
- case 2: /* a.b -- 8.24 bits */
- if (val > 0xffffff)
- return 0;
- val |= parts[0] << 24;
- break;
-
- case 3: /* a.b.c -- 8.8.16 bits */
- if (val > 0xffff)
- return 0;
- val |= (parts[0] << 24) | (parts[1] << 16);
- break;
-
- case 4: /* a.b.c.d -- 8.8.8.8 bits */
- if (val > 0xff)
- return 0;
- val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
- break;
- }
- if (addr)
- addr->s_addr = htonl(val);
- return 1;
-}
diff --git a/libpq/win32/libpq.rc.in b/libpq/win32/libpq.rc.in
deleted file mode 100644
index da97574..0000000
--- a/libpq/win32/libpq.rc.in
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <winver.h>
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 9,6,5,0
- PRODUCTVERSION 9,6,5,0
- FILEFLAGSMASK 0x3fL
- FILEFLAGS 0
- FILEOS VOS__WINDOWS32
- FILETYPE VFT_DLL
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904B0"
- BEGIN
- VALUE "CompanyName", "\0"
- VALUE "FileDescription", "PostgreSQL Access Library\0"
- VALUE "FileVersion", "9.6.5\0"
- VALUE "InternalName", "libpq\0"
- VALUE "LegalCopyright", "Copyright (C) 2016\0"
- VALUE "LegalTrademarks", "\0"
- VALUE "OriginalFilename", "libpq.dll\0"
- VALUE "ProductName", "PostgreSQL\0"
- VALUE "ProductVersion", "9.6.5\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
diff --git a/libpq/win32/libpqdll.def b/libpq/win32/libpqdll.def
deleted file mode 100644
index 810d4be..0000000
--- a/libpq/win32/libpqdll.def
+++ /dev/null
@@ -1,174 +0,0 @@
-; DEF file for win32.mak release build and for Makefile.shlib (MinGW)
-; LIBRARY LIBPQ.dll
-EXPORTS
- PQconnectdb @ 1
- PQsetdbLogin @ 2
- PQconndefaults @ 3
- PQfinish @ 4
- PQreset @ 5
- PQrequestCancel @ 6
- PQdb @ 7
- PQuser @ 8
- PQpass @ 9
- PQhost @ 10
- PQport @ 11
- PQtty @ 12
- PQoptions @ 13
- PQstatus @ 14
- PQerrorMessage @ 15
- PQsocket @ 16
- PQbackendPID @ 17
- PQtrace @ 18
- PQuntrace @ 19
- PQsetNoticeProcessor @ 20
- PQexec @ 21
- PQnotifies @ 22
- PQsendQuery @ 23
- PQgetResult @ 24
- PQisBusy @ 25
- PQconsumeInput @ 26
- PQgetline @ 27
- PQputline @ 28
- PQgetlineAsync @ 29
- PQputnbytes @ 30
- PQendcopy @ 31
- PQfn @ 32
- PQresultStatus @ 33
- PQntuples @ 34
- PQnfields @ 35
- PQbinaryTuples @ 36
- PQfname @ 37
- PQfnumber @ 38
- PQftype @ 39
- PQfsize @ 40
- PQfmod @ 41
- PQcmdStatus @ 42
- PQoidStatus @ 43
- PQcmdTuples @ 44
- PQgetvalue @ 45
- PQgetlength @ 46
- PQgetisnull @ 47
- PQclear @ 48
- PQmakeEmptyPGresult @ 49
- PQprint @ 50
- PQdisplayTuples @ 51
- PQprintTuples @ 52
- lo_open @ 53
- lo_close @ 54
- lo_read @ 55
- lo_write @ 56
- lo_lseek @ 57
- lo_creat @ 58
- lo_tell @ 59
- lo_unlink @ 60
- lo_import @ 61
- lo_export @ 62
- pgresStatus @ 63
- PQmblen @ 64
- PQresultErrorMessage @ 65
- PQresStatus @ 66
- termPQExpBuffer @ 67
- appendPQExpBufferChar @ 68
- initPQExpBuffer @ 69
- resetPQExpBuffer @ 70
- PQoidValue @ 71
- PQclientEncoding @ 72
- PQenv2encoding @ 73
- appendBinaryPQExpBuffer @ 74
- appendPQExpBufferStr @ 75
- destroyPQExpBuffer @ 76
- createPQExpBuffer @ 77
- PQconninfoFree @ 78
- PQconnectPoll @ 79
- PQconnectStart @ 80
- PQflush @ 81
- PQisnonblocking @ 82
- PQresetPoll @ 83
- PQresetStart @ 84
- PQsetClientEncoding @ 85
- PQsetnonblocking @ 86
- PQfreeNotify @ 87
- PQescapeString @ 88
- PQescapeBytea @ 89
- printfPQExpBuffer @ 90
- appendPQExpBuffer @ 91
- pg_encoding_to_char @ 92
- pg_utf_mblen @ 93
- PQunescapeBytea @ 94
- PQfreemem @ 95
- PQtransactionStatus @ 96
- PQparameterStatus @ 97
- PQprotocolVersion @ 98
- PQsetErrorVerbosity @ 99
- PQsetNoticeReceiver @ 100
- PQexecParams @ 101
- PQsendQueryParams @ 102
- PQputCopyData @ 103
- PQputCopyEnd @ 104
- PQgetCopyData @ 105
- PQresultErrorField @ 106
- PQftable @ 107
- PQftablecol @ 108
- PQfformat @ 109
- PQexecPrepared @ 110
- PQsendQueryPrepared @ 111
- PQdsplen @ 112
- PQserverVersion @ 113
- PQgetssl @ 114
- pg_char_to_encoding @ 115
- pg_valid_server_encoding @ 116
- pqsignal @ 117
- PQprepare @ 118
- PQsendPrepare @ 119
- PQgetCancel @ 120
- PQfreeCancel @ 121
- PQcancel @ 122
- lo_create @ 123
- PQinitSSL @ 124
- PQregisterThreadLock @ 125
- PQescapeStringConn @ 126
- PQescapeByteaConn @ 127
- PQencryptPassword @ 128
- PQisthreadsafe @ 129
- enlargePQExpBuffer @ 130
- PQnparams @ 131
- PQparamtype @ 132
- PQdescribePrepared @ 133
- PQdescribePortal @ 134
- PQsendDescribePrepared @ 135
- PQsendDescribePortal @ 136
- lo_truncate @ 137
- PQconnectionUsedPassword @ 138
- pg_valid_server_encoding_id @ 139
- PQconnectionNeedsPassword @ 140
- lo_import_with_oid @ 141
- PQcopyResult @ 142
- PQsetResultAttrs @ 143
- PQsetvalue @ 144
- PQresultAlloc @ 145
- PQregisterEventProc @ 146
- PQinstanceData @ 147
- PQsetInstanceData @ 148
- PQresultInstanceData @ 149
- PQresultSetInstanceData @ 150
- PQfireResultCreateEvents @ 151
- PQconninfoParse @ 152
- PQinitOpenSSL @ 153
- PQescapeLiteral @ 154
- PQescapeIdentifier @ 155
- PQconnectdbParams @ 156
- PQconnectStartParams @ 157
- PQping @ 158
- PQpingParams @ 159
- PQlibVersion @ 160
- PQsetSingleRowMode @ 161
- lo_lseek64 @ 162
- lo_tell64 @ 163
- lo_truncate64 @ 164
- PQconninfo @ 165
- PQsslInUse @ 166
- PQsslStruct @ 167
- PQsslAttributeNames @ 168
- PQsslAttribute @ 169
- PQsetErrorContextVisibility @ 170
- PQresultVerboseErrorMessage @ 171
diff --git a/libpq/win32/libpqdll.def.orig b/libpq/win32/libpqdll.def.orig
deleted file mode 100644
index 0c9e8e4..0000000
--- a/libpq/win32/libpqdll.def.orig
+++ /dev/null
@@ -1,174 +0,0 @@
-; DEF file for win32.mak release build and for Makefile.shlib (MinGW)
-LIBRARY LIBPQ.dll
-EXPORTS
- PQconnectdb @ 1
- PQsetdbLogin @ 2
- PQconndefaults @ 3
- PQfinish @ 4
- PQreset @ 5
- PQrequestCancel @ 6
- PQdb @ 7
- PQuser @ 8
- PQpass @ 9
- PQhost @ 10
- PQport @ 11
- PQtty @ 12
- PQoptions @ 13
- PQstatus @ 14
- PQerrorMessage @ 15
- PQsocket @ 16
- PQbackendPID @ 17
- PQtrace @ 18
- PQuntrace @ 19
- PQsetNoticeProcessor @ 20
- PQexec @ 21
- PQnotifies @ 22
- PQsendQuery @ 23
- PQgetResult @ 24
- PQisBusy @ 25
- PQconsumeInput @ 26
- PQgetline @ 27
- PQputline @ 28
- PQgetlineAsync @ 29
- PQputnbytes @ 30
- PQendcopy @ 31
- PQfn @ 32
- PQresultStatus @ 33
- PQntuples @ 34
- PQnfields @ 35
- PQbinaryTuples @ 36
- PQfname @ 37
- PQfnumber @ 38
- PQftype @ 39
- PQfsize @ 40
- PQfmod @ 41
- PQcmdStatus @ 42
- PQoidStatus @ 43
- PQcmdTuples @ 44
- PQgetvalue @ 45
- PQgetlength @ 46
- PQgetisnull @ 47
- PQclear @ 48
- PQmakeEmptyPGresult @ 49
- PQprint @ 50
- PQdisplayTuples @ 51
- PQprintTuples @ 52
- lo_open @ 53
- lo_close @ 54
- lo_read @ 55
- lo_write @ 56
- lo_lseek @ 57
- lo_creat @ 58
- lo_tell @ 59
- lo_unlink @ 60
- lo_import @ 61
- lo_export @ 62
- pgresStatus @ 63
- PQmblen @ 64
- PQresultErrorMessage @ 65
- PQresStatus @ 66
- termPQExpBuffer @ 67
- appendPQExpBufferChar @ 68
- initPQExpBuffer @ 69
- resetPQExpBuffer @ 70
- PQoidValue @ 71
- PQclientEncoding @ 72
- PQenv2encoding @ 73
- appendBinaryPQExpBuffer @ 74
- appendPQExpBufferStr @ 75
- destroyPQExpBuffer @ 76
- createPQExpBuffer @ 77
- PQconninfoFree @ 78
- PQconnectPoll @ 79
- PQconnectStart @ 80
- PQflush @ 81
- PQisnonblocking @ 82
- PQresetPoll @ 83
- PQresetStart @ 84
- PQsetClientEncoding @ 85
- PQsetnonblocking @ 86
- PQfreeNotify @ 87
- PQescapeString @ 88
- PQescapeBytea @ 89
- printfPQExpBuffer @ 90
- appendPQExpBuffer @ 91
- pg_encoding_to_char @ 92
- pg_utf_mblen @ 93
- PQunescapeBytea @ 94
- PQfreemem @ 95
- PQtransactionStatus @ 96
- PQparameterStatus @ 97
- PQprotocolVersion @ 98
- PQsetErrorVerbosity @ 99
- PQsetNoticeReceiver @ 100
- PQexecParams @ 101
- PQsendQueryParams @ 102
- PQputCopyData @ 103
- PQputCopyEnd @ 104
- PQgetCopyData @ 105
- PQresultErrorField @ 106
- PQftable @ 107
- PQftablecol @ 108
- PQfformat @ 109
- PQexecPrepared @ 110
- PQsendQueryPrepared @ 111
- PQdsplen @ 112
- PQserverVersion @ 113
- PQgetssl @ 114
- pg_char_to_encoding @ 115
- pg_valid_server_encoding @ 116
- pqsignal @ 117
- PQprepare @ 118
- PQsendPrepare @ 119
- PQgetCancel @ 120
- PQfreeCancel @ 121
- PQcancel @ 122
- lo_create @ 123
- PQinitSSL @ 124
- PQregisterThreadLock @ 125
- PQescapeStringConn @ 126
- PQescapeByteaConn @ 127
- PQencryptPassword @ 128
- PQisthreadsafe @ 129
- enlargePQExpBuffer @ 130
- PQnparams @ 131
- PQparamtype @ 132
- PQdescribePrepared @ 133
- PQdescribePortal @ 134
- PQsendDescribePrepared @ 135
- PQsendDescribePortal @ 136
- lo_truncate @ 137
- PQconnectionUsedPassword @ 138
- pg_valid_server_encoding_id @ 139
- PQconnectionNeedsPassword @ 140
- lo_import_with_oid @ 141
- PQcopyResult @ 142
- PQsetResultAttrs @ 143
- PQsetvalue @ 144
- PQresultAlloc @ 145
- PQregisterEventProc @ 146
- PQinstanceData @ 147
- PQsetInstanceData @ 148
- PQresultInstanceData @ 149
- PQresultSetInstanceData @ 150
- PQfireResultCreateEvents @ 151
- PQconninfoParse @ 152
- PQinitOpenSSL @ 153
- PQescapeLiteral @ 154
- PQescapeIdentifier @ 155
- PQconnectdbParams @ 156
- PQconnectStartParams @ 157
- PQping @ 158
- PQpingParams @ 159
- PQlibVersion @ 160
- PQsetSingleRowMode @ 161
- lo_lseek64 @ 162
- lo_tell64 @ 163
- lo_truncate64 @ 164
- PQconninfo @ 165
- PQsslInUse @ 166
- PQsslStruct @ 167
- PQsslAttributeNames @ 168
- PQsslAttribute @ 169
- PQsetErrorContextVisibility @ 170
- PQresultVerboseErrorMessage @ 171
diff --git a/libpq/win32/open.c b/libpq/win32/open.c
deleted file mode 100644
index 717375d..0000000
--- a/libpq/win32/open.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * open.c
- * Win32 open() replacement
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- * src/port/open.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifdef WIN32
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include <windows.h>
-#include <fcntl.h>
-#include <assert.h>
-
-
-static int
-openFlagsToCreateFileFlags(int openFlags)
-{
- switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
- {
- /* O_EXCL is meaningless without O_CREAT */
- case 0:
- case O_EXCL:
- return OPEN_EXISTING;
-
- case O_CREAT:
- return OPEN_ALWAYS;
-
- /* O_EXCL is meaningless without O_CREAT */
- case O_TRUNC:
- case O_TRUNC | O_EXCL:
- return TRUNCATE_EXISTING;
-
- case O_CREAT | O_TRUNC:
- return CREATE_ALWAYS;
-
- /* O_TRUNC is meaningless with O_CREAT */
- case O_CREAT | O_EXCL:
- case O_CREAT | O_TRUNC | O_EXCL:
- return CREATE_NEW;
- }
-
- /* will never get here */
- return 0;
-}
-
-/*
- * - file attribute setting, based on fileMode?
- */
-int
-pgwin32_open(const char *fileName, int fileFlags,...)
-{
- int fd;
- HANDLE h = INVALID_HANDLE_VALUE;
- SECURITY_ATTRIBUTES sa;
- int loops = 0;
-
- /* Check that we can handle the request */
- assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
- (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
- _O_SHORT_LIVED | O_DSYNC | O_DIRECT |
- (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
-
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
-
- while ((h = CreateFile(fileName,
- /* cannot use O_RDONLY, as it == 0 */
- (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
- ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
- /* These flags allow concurrent rename/unlink */
- (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
- &sa,
- openFlagsToCreateFileFlags(fileFlags),
- FILE_ATTRIBUTE_NORMAL |
- ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
- ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
- ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
- ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
- ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
- ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
- NULL)) == INVALID_HANDLE_VALUE)
- {
- /*
- * Sharing violation or locking error can indicate antivirus, backup
- * or similar software that's locking the file. Try again for 30
- * seconds before giving up.
- */
- DWORD err = GetLastError();
-
- if (err == ERROR_SHARING_VIOLATION ||
- err == ERROR_LOCK_VIOLATION)
- {
- pg_usleep(100000);
- loops++;
-
-#ifndef FRONTEND
- if (loops == 50)
- ereport(LOG,
- (errmsg("could not open file \"%s\": %s", fileName,
- (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
- errdetail("Continuing to retry for 30 seconds."),
- errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
-#endif
-
- if (loops < 300)
- continue;
- }
-
- _dosmaperr(err);
- return -1;
- }
-
- /* _open_osfhandle will, on error, set errno accordingly */
- if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
- CloseHandle(h); /* will not affect errno */
- else if (fileFlags & (O_TEXT | O_BINARY) &&
- _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
- {
- _close(fd);
- return -1;
- }
-
- return fd;
-}
-
-FILE *
-pgwin32_fopen(const char *fileName, const char *mode)
-{
- int openmode = 0;
- int fd;
-
- if (strstr(mode, "r+"))
- openmode |= O_RDWR;
- else if (strchr(mode, 'r'))
- openmode |= O_RDONLY;
- if (strstr(mode, "w+"))
- openmode |= O_RDWR | O_CREAT | O_TRUNC;
- else if (strchr(mode, 'w'))
- openmode |= O_WRONLY | O_CREAT | O_TRUNC;
- if (strchr(mode, 'a'))
- openmode |= O_WRONLY | O_CREAT | O_APPEND;
-
- if (strchr(mode, 'b'))
- openmode |= O_BINARY;
- if (strchr(mode, 't'))
- openmode |= O_TEXT;
-
- fd = pgwin32_open(fileName, openmode);
- if (fd == -1)
- return NULL;
- return _fdopen(fd, mode);
-}
-
-#endif
diff --git a/libpq/win32/pgsleep.c b/libpq/win32/pgsleep.c
deleted file mode 100644
index ecefe04..0000000
--- a/libpq/win32/pgsleep.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pgsleep.c
- * Portable delay handling.
- *
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- * src/port/pgsleep.c
- *
- *-------------------------------------------------------------------------
- */
-#include "c.h"
-
-#include <unistd.h>
-#include <sys/time.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/*
- * In a Windows backend, we don't use this implementation, but rather
- * the signal-aware version in src/backend/port/win32/signal.c.
- */
-#if defined(FRONTEND) || !defined(WIN32)
-
-/*
- * pg_usleep --- delay the specified number of microseconds.
- *
- * NOTE: although the delay is specified in microseconds, the effective
- * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect
- * the requested delay to be rounded up to the next resolution boundary.
- *
- * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
- *
- * CAUTION: the behavior when a signal arrives during the sleep is platform
- * dependent. On most Unix-ish platforms, a signal does not terminate the
- * sleep; but on some, it will (the Windows implementation also allows signals
- * to terminate pg_usleep). And there are platforms where not only does a
- * signal not terminate the sleep, but it actually resets the timeout counter
- * so that the sleep effectively starts over! It is therefore rather hazardous
- * to use this for long sleeps; a continuing stream of signal events could
- * prevent the sleep from ever terminating. Better practice for long sleeps
- * is to use WaitLatch() with a timeout.
- */
-void
-pg_usleep(long microsec)
-{
- if (microsec > 0)
- {
-#ifndef WIN32
- struct timeval delay;
-
- delay.tv_sec = microsec / 1000000L;
- delay.tv_usec = microsec % 1000000L;
- (void) select(0, NULL, NULL, NULL, &delay);
-#else
- SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
-#endif
- }
-}
-
-#endif /* defined(FRONTEND) || !defined(WIN32) */
diff --git a/libpq/win32/pthread-win32.c b/libpq/win32/pthread-win32.c
deleted file mode 100644
index 68dfefc..0000000
--- a/libpq/win32/pthread-win32.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-------------------------------------------------------------------------
-*
-* pthread-win32.c
-* partial pthread implementation for win32
-*
-* Copyright (c) 2004-2016, PostgreSQL Global Development Group
-* IDENTIFICATION
-* src/interfaces/libpq/pthread-win32.c
-*
-*-------------------------------------------------------------------------
-*/
-
-#include "postgres_fe.h"
-
-#include <windows.h>
-#include "pthread-win32.h"
-
-DWORD
-pthread_self(void)
-{
- return GetCurrentThreadId();
-}
-
-void
-pthread_setspecific(pthread_key_t key, void *val)
-{
-}
-
-void *
-pthread_getspecific(pthread_key_t key)
-{
- return NULL;
-}
-
-int
-pthread_mutex_init(pthread_mutex_t *mp, void *attr)
-{
- *mp = (CRITICAL_SECTION *) malloc(sizeof(CRITICAL_SECTION));
- if (!*mp)
- return 1;
- InitializeCriticalSection(*mp);
- return 0;
-}
-
-int
-pthread_mutex_lock(pthread_mutex_t *mp)
-{
- if (!*mp)
- return 1;
- EnterCriticalSection(*mp);
- return 0;
-}
-
-int
-pthread_mutex_unlock(pthread_mutex_t *mp)
-{
- if (!*mp)
- return 1;
- LeaveCriticalSection(*mp);
- return 0;
-}
diff --git a/libpq/win32/pthread-win32.h b/libpq/win32/pthread-win32.h
deleted file mode 100644
index 97ccc17..0000000
--- a/libpq/win32/pthread-win32.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * src/port/pthread-win32.h
- */
-#ifndef __PTHREAD_H
-#define __PTHREAD_H
-
-typedef ULONG pthread_key_t;
-typedef CRITICAL_SECTION *pthread_mutex_t;
-typedef int pthread_once_t;
-
-DWORD pthread_self(void);
-
-void pthread_setspecific(pthread_key_t, void *);
-void *pthread_getspecific(pthread_key_t);
-
-int pthread_mutex_init(pthread_mutex_t *, void *attr);
-int pthread_mutex_lock(pthread_mutex_t *);
-
-/* blocking */
-int pthread_mutex_unlock(pthread_mutex_t *);
-
-#endif
diff --git a/libpq/win32/snprintf.c b/libpq/win32/snprintf.c
deleted file mode 100644
index 62b23b0..0000000
--- a/libpq/win32/snprintf.c
+++ /dev/null
@@ -1,1141 +0,0 @@
-/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. 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.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
- *
- * src/port/snprintf.c
- */
-
-#include "c.h"
-
-#include <ctype.h>
-#ifdef _MSC_VER
-#include <float.h> /* for _isnan */
-#endif
-#include <limits.h>
-#include <math.h>
-#ifndef WIN32
-#include <sys/ioctl.h>
-#endif
-#include <sys/param.h>
-
-#ifndef NL_ARGMAX
-#define NL_ARGMAX 16
-#endif
-
-
-/*
- * SNPRINTF, VSNPRINTF and friends
- *
- * These versions have been grabbed off the net. They have been
- * cleaned up to compile properly and support for most of the Single Unix
- * Specification has been added. Remaining unimplemented features are:
- *
- * 1. No locale support: the radix character is always '.' and the '
- * (single quote) format flag is ignored.
- *
- * 2. No support for the "%n" format specification.
- *
- * 3. No support for wide characters ("lc" and "ls" formats).
- *
- * 4. No support for "long double" ("Lf" and related formats).
- *
- * 5. Space and '#' flags are not implemented.
- *
- *
- * The result values of these functions are not the same across different
- * platforms. This implementation is compatible with the Single Unix Spec:
- *
- * 1. -1 is returned only if processing is abandoned due to an invalid
- * parameter, such as incorrect format string. (Although not required by
- * the spec, this happens only when no characters have yet been transmitted
- * to the destination.)
- *
- * 2. For snprintf and sprintf, 0 is returned if str == NULL or count == 0;
- * no data has been stored.
- *
- * 3. Otherwise, the number of bytes actually transmitted to the destination
- * is returned (excluding the trailing '\0' for snprintf and sprintf).
- *
- * For snprintf with nonzero count, the result cannot be more than count-1
- * (a trailing '\0' is always stored); it is not possible to distinguish
- * buffer overrun from exact fit. This is unlike some implementations that
- * return the number of bytes that would have been needed for the complete
- * result string.
- */
-
-/**************************************************************
- * Original:
- * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
- * A bombproof version of doprnt (dopr) included.
- * Sigh. This sort of thing is always nasty do deal with. Note that
- * the version here does not include floating point. (now it does ... tgl)
- **************************************************************/
-
-/* Prevent recursion */
-#undef vsnprintf
-#undef snprintf
-#undef sprintf
-#undef vfprintf
-#undef fprintf
-#undef printf
-
-/* Info about where the formatted output is going */
-typedef struct
-{
- char *bufptr; /* next buffer output position */
- char *bufstart; /* first buffer element */
- char *bufend; /* last buffer element, or NULL */
- /* bufend == NULL is for sprintf, where we assume buf is big enough */
- FILE *stream; /* eventual output destination, or NULL */
- int nchars; /* # chars already sent to stream */
- bool failed; /* call is a failure; errno is set */
-} PrintfTarget;
-
-/*
- * Info about the type and value of a formatting parameter. Note that we
- * don't currently support "long double", "wint_t", or "wchar_t *" data,
- * nor the '%n' formatting code; else we'd need more types. Also, at this
- * level we need not worry about signed vs unsigned values.
- */
-typedef enum
-{
- ATYPE_NONE = 0,
- ATYPE_INT,
- ATYPE_LONG,
- ATYPE_LONGLONG,
- ATYPE_DOUBLE,
- ATYPE_CHARPTR
-} PrintfArgType;
-
-typedef union
-{
- int i;
- long l;
- int64 ll;
- double d;
- char *cptr;
-} PrintfArgValue;
-
-
-static void flushbuffer(PrintfTarget *target);
-static void dopr(PrintfTarget *target, const char *format, va_list args);
-
-
-int
-pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
-{
- PrintfTarget target;
-
- if (str == NULL || count == 0)
- return 0;
- target.bufstart = target.bufptr = str;
- target.bufend = str + count - 1;
- target.stream = NULL;
- /* target.nchars is unused in this case */
- target.failed = false;
- dopr(&target, fmt, args);
- *(target.bufptr) = '\0';
- return target.failed ? -1 : (target.bufptr - target.bufstart);
-}
-
-int
-pg_snprintf(char *str, size_t count, const char *fmt,...)
-{
- int len;
- va_list args;
-
- va_start(args, fmt);
- len = pg_vsnprintf(str, count, fmt, args);
- va_end(args);
- return len;
-}
-
-static int
-pg_vsprintf(char *str, const char *fmt, va_list args)
-{
- PrintfTarget target;
-
- if (str == NULL)
- return 0;
- target.bufstart = target.bufptr = str;
- target.bufend = NULL;
- target.stream = NULL;
- /* target.nchars is unused in this case */
- target.failed = false;
- dopr(&target, fmt, args);
- *(target.bufptr) = '\0';
- return target.failed ? -1 : (target.bufptr - target.bufstart);
-}
-
-int
-pg_sprintf(char *str, const char *fmt,...)
-{
- int len;
- va_list args;
-
- va_start(args, fmt);
- len = pg_vsprintf(str, fmt, args);
- va_end(args);
- return len;
-}
-
-int
-pg_vfprintf(FILE *stream, const char *fmt, va_list args)
-{
- PrintfTarget target;
- char buffer[1024]; /* size is arbitrary */
-
- if (stream == NULL)
- {
- errno = EINVAL;
- return -1;
- }
- target.bufstart = target.bufptr = buffer;
- target.bufend = buffer + sizeof(buffer) - 1;
- target.stream = stream;
- target.nchars = 0;
- target.failed = false;
- dopr(&target, fmt, args);
- /* dump any remaining buffer contents */
- flushbuffer(&target);
- return target.failed ? -1 : target.nchars;
-}
-
-int
-pg_fprintf(FILE *stream, const char *fmt,...)
-{
- int len;
- va_list args;
-
- va_start(args, fmt);
- len = pg_vfprintf(stream, fmt, args);
- va_end(args);
- return len;
-}
-
-int
-pg_printf(const char *fmt,...)
-{
- int len;
- va_list args;
-
- va_start(args, fmt);
- len = pg_vfprintf(stdout, fmt, args);
- va_end(args);
- return len;
-}
-
-/*
- * Attempt to write the entire buffer to target->stream; discard the entire
- * buffer in any case. Call this only when target->stream is defined.
- */
-static void
-flushbuffer(PrintfTarget *target)
-{
- size_t nc = target->bufptr - target->bufstart;
-
- if (!target->failed && nc > 0)
- {
- size_t written;
-
- written = fwrite(target->bufstart, 1, nc, target->stream);
- target->nchars += written;
- if (written != nc)
- target->failed = true;
- }
- target->bufptr = target->bufstart;
-}
-
-
-static void fmtstr(char *value, int leftjust, int minlen, int maxwidth,
- int pointflag, PrintfTarget *target);
-static void fmtptr(void *value, PrintfTarget *target);
-static void fmtint(int64 value, char type, int forcesign,
- int leftjust, int minlen, int zpad, int precision, int pointflag,
- PrintfTarget *target);
-static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target);
-static void fmtfloat(double value, char type, int forcesign,
- int leftjust, int minlen, int zpad, int precision, int pointflag,
- PrintfTarget *target);
-static void dostr(const char *str, int slen, PrintfTarget *target);
-static void dopr_outch(int c, PrintfTarget *target);
-static int adjust_sign(int is_negative, int forcesign, int *signvalue);
-static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen);
-static void leading_pad(int zpad, int *signvalue, int *padlen,
- PrintfTarget *target);
-static void trailing_pad(int *padlen, PrintfTarget *target);
-
-
-/*
- * dopr(): poor man's version of doprintf
- */
-static void
-dopr(PrintfTarget *target, const char *format, va_list args)
-{
- const char *format_start = format;
- int ch;
- bool have_dollar;
- bool have_non_dollar;
- bool have_star;
- bool afterstar;
- int accum;
- int longlongflag;
- int longflag;
- int pointflag;
- int leftjust;
- int fieldwidth;
- int precision;
- int zpad;
- int forcesign;
- int last_dollar;
- int fmtpos;
- int cvalue;
- int64 numvalue;
- double fvalue;
- char *strvalue;
- int i;
- PrintfArgType argtypes[NL_ARGMAX + 1];
- PrintfArgValue argvalues[NL_ARGMAX + 1];
-
- /*
- * Parse the format string to determine whether there are %n$ format
- * specs, and identify the types and order of the format parameters.
- */
- have_dollar = have_non_dollar = false;
- last_dollar = 0;
- MemSet(argtypes, 0, sizeof(argtypes));
-
- while ((ch = *format++) != '\0')
- {
- if (ch != '%')
- continue;
- longflag = longlongflag = pointflag = 0;
- fmtpos = accum = 0;
- afterstar = false;
-nextch1:
- ch = *format++;
- if (ch == '\0')
- break; /* illegal, but we don't complain */
- switch (ch)
- {
- case '-':
- case '+':
- goto nextch1;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- accum = accum * 10 + (ch - '0');
- goto nextch1;
- case '.':
- pointflag = 1;
- accum = 0;
- goto nextch1;
- case '*':
- if (afterstar)
- have_non_dollar = true; /* multiple stars */
- afterstar = true;
- accum = 0;
- goto nextch1;
- case '$':
- have_dollar = true;
- if (accum <= 0 || accum > NL_ARGMAX)
- goto bad_format;
- if (afterstar)
- {
- if (argtypes[accum] &&
- argtypes[accum] != ATYPE_INT)
- goto bad_format;
- argtypes[accum] = ATYPE_INT;
- last_dollar = Max(last_dollar, accum);
- afterstar = false;
- }
- else
- fmtpos = accum;
- accum = 0;
- goto nextch1;
- case 'l':
- if (longflag)
- longlongflag = 1;
- else
- longflag = 1;
- goto nextch1;
- case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
- longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
- longlongflag = 1;
-#else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
- /* assume size_t is same size as int */
-#endif
- goto nextch1;
- case 'h':
- case '\'':
- /* ignore these */
- goto nextch1;
- case 'd':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- if (fmtpos)
- {
- PrintfArgType atype;
-
- if (longlongflag)
- atype = ATYPE_LONGLONG;
- else if (longflag)
- atype = ATYPE_LONG;
- else
- atype = ATYPE_INT;
- if (argtypes[fmtpos] &&
- argtypes[fmtpos] != atype)
- goto bad_format;
- argtypes[fmtpos] = atype;
- last_dollar = Max(last_dollar, fmtpos);
- }
- else
- have_non_dollar = true;
- break;
- case 'c':
- if (fmtpos)
- {
- if (argtypes[fmtpos] &&
- argtypes[fmtpos] != ATYPE_INT)
- goto bad_format;
- argtypes[fmtpos] = ATYPE_INT;
- last_dollar = Max(last_dollar, fmtpos);
- }
- else
- have_non_dollar = true;
- break;
- case 's':
- case 'p':
- if (fmtpos)
- {
- if (argtypes[fmtpos] &&
- argtypes[fmtpos] != ATYPE_CHARPTR)
- goto bad_format;
- argtypes[fmtpos] = ATYPE_CHARPTR;
- last_dollar = Max(last_dollar, fmtpos);
- }
- else
- have_non_dollar = true;
- break;
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- if (fmtpos)
- {
- if (argtypes[fmtpos] &&
- argtypes[fmtpos] != ATYPE_DOUBLE)
- goto bad_format;
- argtypes[fmtpos] = ATYPE_DOUBLE;
- last_dollar = Max(last_dollar, fmtpos);
- }
- else
- have_non_dollar = true;
- break;
- case '%':
- break;
- }
-
- /*
- * If we finish the spec with afterstar still set, there's a
- * non-dollar star in there.
- */
- if (afterstar)
- have_non_dollar = true;
- }
-
- /* Per spec, you use either all dollar or all not. */
- if (have_dollar && have_non_dollar)
- goto bad_format;
-
- /*
- * In dollar mode, collect the arguments in physical order.
- */
- for (i = 1; i <= last_dollar; i++)
- {
- switch (argtypes[i])
- {
- case ATYPE_NONE:
- goto bad_format;
- case ATYPE_INT:
- argvalues[i].i = va_arg(args, int);
- break;
- case ATYPE_LONG:
- argvalues[i].l = va_arg(args, long);
- break;
- case ATYPE_LONGLONG:
- argvalues[i].ll = va_arg(args, int64);
- break;
- case ATYPE_DOUBLE:
- argvalues[i].d = va_arg(args, double);
- break;
- case ATYPE_CHARPTR:
- argvalues[i].cptr = va_arg(args, char *);
- break;
- }
- }
-
- /*
- * At last we can parse the format for real.
- */
- format = format_start;
- while ((ch = *format++) != '\0')
- {
- if (target->failed)
- break;
-
- if (ch != '%')
- {
- dopr_outch(ch, target);
- continue;
- }
- fieldwidth = precision = zpad = leftjust = forcesign = 0;
- longflag = longlongflag = pointflag = 0;
- fmtpos = accum = 0;
- have_star = afterstar = false;
-nextch2:
- ch = *format++;
- if (ch == '\0')
- break; /* illegal, but we don't complain */
- switch (ch)
- {
- case '-':
- leftjust = 1;
- goto nextch2;
- case '+':
- forcesign = 1;
- goto nextch2;
- case '0':
- /* set zero padding if no nonzero digits yet */
- if (accum == 0 && !pointflag)
- zpad = '0';
- /* FALL THRU */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- accum = accum * 10 + (ch - '0');
- goto nextch2;
- case '.':
- if (have_star)
- have_star = false;
- else
- fieldwidth = accum;
- pointflag = 1;
- accum = 0;
- goto nextch2;
- case '*':
- if (have_dollar)
- {
- /* process value after reading n$ */
- afterstar = true;
- }
- else
- {
- /* fetch and process value now */
- int starval = va_arg(args, int);
-
- if (pointflag)
- {
- precision = starval;
- if (precision < 0)
- {
- precision = 0;
- pointflag = 0;
- }
- }
- else
- {
- fieldwidth = starval;
- if (fieldwidth < 0)
- {
- leftjust = 1;
- fieldwidth = -fieldwidth;
- }
- }
- }
- have_star = true;
- accum = 0;
- goto nextch2;
- case '$':
- if (afterstar)
- {
- /* fetch and process star value */
- int starval = argvalues[accum].i;
-
- if (pointflag)
- {
- precision = starval;
- if (precision < 0)
- {
- precision = 0;
- pointflag = 0;
- }
- }
- else
- {
- fieldwidth = starval;
- if (fieldwidth < 0)
- {
- leftjust = 1;
- fieldwidth = -fieldwidth;
- }
- }
- afterstar = false;
- }
- else
- fmtpos = accum;
- accum = 0;
- goto nextch2;
- case 'l':
- if (longflag)
- longlongflag = 1;
- else
- longflag = 1;
- goto nextch2;
- case 'z':
-#if SIZEOF_SIZE_T == 8
-#ifdef HAVE_LONG_INT_64
- longflag = 1;
-#elif defined(HAVE_LONG_LONG_INT_64)
- longlongflag = 1;
-#else
-#error "Don't know how to print 64bit integers"
-#endif
-#else
- /* assume size_t is same size as int */
-#endif
- goto nextch2;
- case 'h':
- case '\'':
- /* ignore these */
- goto nextch2;
- case 'd':
- case 'i':
- if (!have_star)
- {
- if (pointflag)
- precision = accum;
- else
- fieldwidth = accum;
- }
- if (have_dollar)
- {
- if (longlongflag)
- numvalue = argvalues[fmtpos].ll;
- else if (longflag)
- numvalue = argvalues[fmtpos].l;
- else
- numvalue = argvalues[fmtpos].i;
- }
- else
- {
- if (longlongflag)
- numvalue = va_arg(args, int64);
- else if (longflag)
- numvalue = va_arg(args, long);
- else
- numvalue = va_arg(args, int);
- }
- fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
- precision, pointflag, target);
- break;
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- if (!have_star)
- {
- if (pointflag)
- precision = accum;
- else
- fieldwidth = accum;
- }
- if (have_dollar)
- {
- if (longlongflag)
- numvalue = (uint64) argvalues[fmtpos].ll;
- else if (longflag)
- numvalue = (unsigned long) argvalues[fmtpos].l;
- else
- numvalue = (unsigned int) argvalues[fmtpos].i;
- }
- else
- {
- if (longlongflag)
- numvalue = (uint64) va_arg(args, int64);
- else if (longflag)
- numvalue = (unsigned long) va_arg(args, long);
- else
- numvalue = (unsigned int) va_arg(args, int);
- }
- fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
- precision, pointflag, target);
- break;
- case 'c':
- if (!have_star)
- {
- if (pointflag)
- precision = accum;
- else
- fieldwidth = accum;
- }
- if (have_dollar)
- cvalue = (unsigned char) argvalues[fmtpos].i;
- else
- cvalue = (unsigned char) va_arg(args, int);
- fmtchar(cvalue, leftjust, fieldwidth, target);
- break;
- case 's':
- if (!have_star)
- {
- if (pointflag)
- precision = accum;
- else
- fieldwidth = accum;
- }
- if (have_dollar)
- strvalue = argvalues[fmtpos].cptr;
- else
- strvalue = va_arg(args, char *);
- fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
- target);
- break;
- case 'p':
- /* fieldwidth/leftjust are ignored ... */
- if (have_dollar)
- strvalue = argvalues[fmtpos].cptr;
- else
- strvalue = va_arg(args, char *);
- fmtptr((void *) strvalue, target);
- break;
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- if (!have_star)
- {
- if (pointflag)
- precision = accum;
- else
- fieldwidth = accum;
- }
- if (have_dollar)
- fvalue = argvalues[fmtpos].d;
- else
- fvalue = va_arg(args, double);
- fmtfloat(fvalue, ch, forcesign, leftjust,
- fieldwidth, zpad,
- precision, pointflag,
- target);
- break;
- case '%':
- dopr_outch('%', target);
- break;
- }
- }
-
- return;
-
-bad_format:
- errno = EINVAL;
- target->failed = true;
-}
-
-static size_t
-pg_strnlen(const char *str, size_t maxlen)
-{
- const char *p = str;
-
- while (maxlen-- > 0 && *p)
- p++;
- return p - str;
-}
-
-static void
-fmtstr(char *value, int leftjust, int minlen, int maxwidth,
- int pointflag, PrintfTarget *target)
-{
- int padlen,
- vallen; /* amount to pad */
-
- /*
- * If a maxwidth (precision) is specified, we must not fetch more bytes
- * than that.
- */
- if (pointflag)
- vallen = pg_strnlen(value, maxwidth);
- else
- vallen = strlen(value);
-
- adjust_padlen(minlen, vallen, leftjust, &padlen);
-
- while (padlen > 0)
- {
- dopr_outch(' ', target);
- --padlen;
- }
-
- dostr(value, vallen, target);
-
- trailing_pad(&padlen, target);
-}
-
-static void
-fmtptr(void *value, PrintfTarget *target)
-{
- int vallen;
- char convert[64];
-
- /* we rely on regular C library's sprintf to do the basic conversion */
- vallen = sprintf(convert, "%p", value);
- if (vallen < 0)
- target->failed = true;
- else
- dostr(convert, vallen, target);
-}
-
-static void
-fmtint(int64 value, char type, int forcesign, int leftjust,
- int minlen, int zpad, int precision, int pointflag,
- PrintfTarget *target)
-{
- uint64 base;
- int dosign;
- const char *cvt = "0123456789abcdef";
- int signvalue = 0;
- char convert[64];
- int vallen = 0;
- int padlen = 0; /* amount to pad */
- int zeropad; /* extra leading zeroes */
-
- switch (type)
- {
- case 'd':
- case 'i':
- base = 10;
- dosign = 1;
- break;
- case 'o':
- base = 8;
- dosign = 0;
- break;
- case 'u':
- base = 10;
- dosign = 0;
- break;
- case 'x':
- base = 16;
- dosign = 0;
- break;
- case 'X':
- cvt = "0123456789ABCDEF";
- base = 16;
- dosign = 0;
- break;
- default:
- return; /* keep compiler quiet */
- }
-
- /* Handle +/- */
- if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
- value = -value;
-
- /*
- * SUS: the result of converting 0 with an explicit precision of 0 is no
- * characters
- */
- if (value == 0 && pointflag && precision == 0)
- vallen = 0;
- else
- {
- /* make integer string */
- uint64 uvalue = (uint64) value;
-
- do
- {
- convert[vallen++] = cvt[uvalue % base];
- uvalue = uvalue / base;
- } while (uvalue);
- }
-
- zeropad = Max(0, precision - vallen);
-
- adjust_padlen(minlen, vallen + zeropad, leftjust, &padlen);
-
- leading_pad(zpad, &signvalue, &padlen, target);
-
- while (zeropad-- > 0)
- dopr_outch('0', target);
-
- while (vallen > 0)
- dopr_outch(convert[--vallen], target);
-
- trailing_pad(&padlen, target);
-}
-
-static void
-fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
-{
- int padlen = 0; /* amount to pad */
-
- adjust_padlen(minlen, 1, leftjust, &padlen);
-
- while (padlen > 0)
- {
- dopr_outch(' ', target);
- --padlen;
- }
-
- dopr_outch(value, target);
-
- trailing_pad(&padlen, target);
-}
-
-static void
-fmtfloat(double value, char type, int forcesign, int leftjust,
- int minlen, int zpad, int precision, int pointflag,
- PrintfTarget *target)
-{
- int signvalue = 0;
- int prec;
- int vallen;
- char fmt[32];
- char convert[1024];
- int zeropadlen = 0; /* amount to pad with zeroes */
- int padlen = 0; /* amount to pad with spaces */
-
- /*
- * We rely on the regular C library's sprintf to do the basic conversion,
- * then handle padding considerations here.
- *
- * The dynamic range of "double" is about 1E+-308 for IEEE math, and not
- * too wildly more than that with other hardware. In "f" format, sprintf
- * could therefore generate at most 308 characters to the left of the
- * decimal point; while we need to allow the precision to get as high as
- * 308+17 to ensure that we don't truncate significant digits from very
- * small values. To handle both these extremes, we use a buffer of 1024
- * bytes and limit requested precision to 350 digits; this should prevent
- * buffer overrun even with non-IEEE math. If the original precision
- * request was more than 350, separately pad with zeroes.
- */
- if (precision < 0) /* cover possible overflow of "accum" */
- precision = 0;
- prec = Min(precision, 350);
-
- if (pointflag)
- {
- if (sprintf(fmt, "%%.%d%c", prec, type) < 0)
- goto fail;
- zeropadlen = precision - prec;
- }
- else if (sprintf(fmt, "%%%c", type) < 0)
- goto fail;
-
- if (!isnan(value) && adjust_sign((value < 0), forcesign, &signvalue))
- value = -value;
-
- vallen = sprintf(convert, fmt, value);
- if (vallen < 0)
- goto fail;
-
- /* If it's infinity or NaN, forget about doing any zero-padding */
- if (zeropadlen > 0 && !isdigit((unsigned char) convert[vallen - 1]))
- zeropadlen = 0;
-
- adjust_padlen(minlen, vallen + zeropadlen, leftjust, &padlen);
-
- leading_pad(zpad, &signvalue, &padlen, target);
-
- if (zeropadlen > 0)
- {
- /* If 'e' or 'E' format, inject zeroes before the exponent */
- char *epos = strrchr(convert, 'e');
-
- if (!epos)
- epos = strrchr(convert, 'E');
- if (epos)
- {
- /* pad after exponent */
- dostr(convert, epos - convert, target);
- while (zeropadlen-- > 0)
- dopr_outch('0', target);
- dostr(epos, vallen - (epos - convert), target);
- }
- else
- {
- /* no exponent, pad after the digits */
- dostr(convert, vallen, target);
- while (zeropadlen-- > 0)
- dopr_outch('0', target);
- }
- }
- else
- {
- /* no zero padding, just emit the number as-is */
- dostr(convert, vallen, target);
- }
-
- trailing_pad(&padlen, target);
- return;
-
-fail:
- target->failed = true;
-}
-
-static void
-dostr(const char *str, int slen, PrintfTarget *target)
-{
- while (slen > 0)
- {
- int avail;
-
- if (target->bufend != NULL)
- avail = target->bufend - target->bufptr;
- else
- avail = slen;
- if (avail <= 0)
- {
- /* buffer full, can we dump to stream? */
- if (target->stream == NULL)
- return; /* no, lose the data */
- flushbuffer(target);
- continue;
- }
- avail = Min(avail, slen);
- memmove(target->bufptr, str, avail);
- target->bufptr += avail;
- str += avail;
- slen -= avail;
- }
-}
-
-static void
-dopr_outch(int c, PrintfTarget *target)
-{
- if (target->bufend != NULL && target->bufptr >= target->bufend)
- {
- /* buffer full, can we dump to stream? */
- if (target->stream == NULL)
- return; /* no, lose the data */
- flushbuffer(target);
- }
- *(target->bufptr++) = c;
-}
-
-
-static int
-adjust_sign(int is_negative, int forcesign, int *signvalue)
-{
- if (is_negative)
- {
- *signvalue = '-';
- return true;
- }
- else if (forcesign)
- *signvalue = '+';
- return false;
-}
-
-
-static void
-adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
-{
- *padlen = minlen - vallen;
- if (*padlen < 0)
- *padlen = 0;
- if (leftjust)
- *padlen = -(*padlen);
-}
-
-
-static void
-leading_pad(int zpad, int *signvalue, int *padlen, PrintfTarget *target)
-{
- if (*padlen > 0 && zpad)
- {
- if (*signvalue)
- {
- dopr_outch(*signvalue, target);
- --(*padlen);
- *signvalue = 0;
- }
- while (*padlen > 0)
- {
- dopr_outch(zpad, target);
- --(*padlen);
- }
- }
- while (*padlen > (*signvalue != 0))
- {
- dopr_outch(' ', target);
- --(*padlen);
- }
- if (*signvalue)
- {
- dopr_outch(*signvalue, target);
- if (*padlen > 0)
- --(*padlen);
- else if (*padlen < 0)
- ++(*padlen);
- }
-}
-
-
-static void
-trailing_pad(int *padlen, PrintfTarget *target)
-{
- while (*padlen < 0)
- {
- dopr_outch(' ', target);
- ++(*padlen);
- }
-}
diff --git a/libpq/win32/system.c b/libpq/win32/system.c
deleted file mode 100644
index 15b6e37..0000000
--- a/libpq/win32/system.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * system.c
- * Win32 system() and popen() replacements
- *
- *
- * Win32 needs double quotes at the beginning and end of system()
- * strings. If not, it gets confused with multiple quoted strings.
- * It also requires double-quotes around the executable name and
- * any files used for redirection. Filter other args through
- * appendShellString() to quote them.
- *
- * Generated using Win32 "CMD /?":
- *
- * 1. If all of the following conditions are met, then quote characters
- * on the command line are preserved:
- *
- * - no /S switch
- * - exactly two quote characters
- * - no special characters between the two quote characters, where special
- * is one of: &<>()@^|
- * - there are one or more whitespace characters between the two quote
- * characters
- * - the string between the two quote characters is the name of an
- * executable file.
- *
- * 2. Otherwise, old behavior is to see if the first character is a quote
- * character and if so, strip the leading character and remove the last
- * quote character on the command line, preserving any text after the last
- * quote character.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- * src/port/system.c
- *
- *-------------------------------------------------------------------------
- */
-int a;
-
-#if defined(WIN32) && !defined(__CYGWIN__)
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-#include <windows.h>
-#include <fcntl.h>
-
-#undef system
-#undef popen
-
-int
-pgwin32_system(const char *command)
-{
- size_t cmdlen = strlen(command);
- char *buf;
- int save_errno;
- int res;
-
- /*
- * Create a malloc'd copy of the command string, enclosed with an extra
- * pair of quotes
- */
- buf = malloc(cmdlen + 2 + 1);
- if (buf == NULL)
- {
- errno = ENOMEM;
- return -1;
- }
- buf[0] = '"';
- memcpy(&buf[1], command, cmdlen);
- buf[cmdlen + 1] = '"';
- buf[cmdlen + 2] = '\0';
-
- res = system(buf);
-
- save_errno = errno;
- free(buf);
- errno = save_errno;
-
- return res;
-}
-
-
-FILE *
-pgwin32_popen(const char *command, const char *type)
-{
- size_t cmdlen = strlen(command);
- char *buf;
- int save_errno;
- FILE *res;
-
- /*
- * Create a malloc'd copy of the command string, enclosed with an extra
- * pair of quotes
- */
- buf = malloc(cmdlen + 2 + 1);
- if (buf == NULL)
- {
- errno = ENOMEM;
- return NULL;
- }
- buf[0] = '"';
- memcpy(&buf[1], command, cmdlen);
- buf[cmdlen + 1] = '"';
- buf[cmdlen + 2] = '\0';
-
- res = _popen(buf, type);
-
- save_errno = errno;
- free(buf);
- errno = save_errno;
-
- return res;
-}
-
-#endif
diff --git a/libpq/win32/win32.c b/libpq/win32/win32.c
deleted file mode 100644
index 1b7ad37..0000000
--- a/libpq/win32/win32.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * src/interfaces/libpq/win32.c
- *
- *
- * FILE
- * win32.c
- *
- * DESCRIPTION
- * Win32 support functions.
- *
- * Contains table and functions for looking up win32 socket error
- * descriptions. But will/may contain other win32 helper functions
- * for libpq.
- *
- * The error constants are taken from the Frambak Bakfram LGSOCKET
- * library guys who in turn took them from the Winsock FAQ.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- */
-
-/* Make stuff compile faster by excluding not used stuff */
-
-#define VC_EXTRALEAN
-#ifndef __MINGW32__
-#define NOGDI
-#endif
-#define NOCRYPT
-
-#include "postgres_fe.h"
-
-#include "win32.h"
-
-/* Declared here to avoid pulling in all includes, which causes name collisions */
-#ifdef ENABLE_NLS
-extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1);
-#else
-#define libpq_gettext(x) (x)
-#endif
-
-
-static struct WSErrorEntry
-{
- DWORD error;
- const char *description;
-} WSErrors[] =
-
-{
- {
- 0, "No error"
- },
- {
- WSAEINTR, "Interrupted system call"
- },
- {
- WSAEBADF, "Bad file number"
- },
- {
- WSAEACCES, "Permission denied"
- },
- {
- WSAEFAULT, "Bad address"
- },
- {
- WSAEINVAL, "Invalid argument"
- },
- {
- WSAEMFILE, "Too many open sockets"
- },
- {
- WSAEWOULDBLOCK, "Operation would block"
- },
- {
- WSAEINPROGRESS, "Operation now in progress"
- },
- {
- WSAEALREADY, "Operation already in progress"
- },
- {
- WSAENOTSOCK, "Socket operation on non-socket"
- },
- {
- WSAEDESTADDRREQ, "Destination address required"
- },
- {
- WSAEMSGSIZE, "Message too long"
- },
- {
- WSAEPROTOTYPE, "Protocol wrong type for socket"
- },
- {
- WSAENOPROTOOPT, "Bad protocol option"
- },
- {
- WSAEPROTONOSUPPORT, "Protocol not supported"
- },
- {
- WSAESOCKTNOSUPPORT, "Socket type not supported"
- },
- {
- WSAEOPNOTSUPP, "Operation not supported on socket"
- },
- {
- WSAEPFNOSUPPORT, "Protocol family not supported"
- },
- {
- WSAEAFNOSUPPORT, "Address family not supported"
- },
- {
- WSAEADDRINUSE, "Address already in use"
- },
- {
- WSAEADDRNOTAVAIL, "Cannot assign requested address"
- },
- {
- WSAENETDOWN, "Network is down"
- },
- {
- WSAENETUNREACH, "Network is unreachable"
- },
- {
- WSAENETRESET, "Net connection reset"
- },
- {
- WSAECONNABORTED, "Software caused connection abort"
- },
- {
- WSAECONNRESET, "Connection reset by peer"
- },
- {
- WSAENOBUFS, "No buffer space available"
- },
- {
- WSAEISCONN, "Socket is already connected"
- },
- {
- WSAENOTCONN, "Socket is not connected"
- },
- {
- WSAESHUTDOWN, "Cannot send after socket shutdown"
- },
- {
- WSAETOOMANYREFS, "Too many references, cannot splice"
- },
- {
- WSAETIMEDOUT, "Connection timed out"
- },
- {
- WSAECONNREFUSED, "Connection refused"
- },
- {
- WSAELOOP, "Too many levels of symbolic links"
- },
- {
- WSAENAMETOOLONG, "File name too long"
- },
- {
- WSAEHOSTDOWN, "Host is down"
- },
- {
- WSAEHOSTUNREACH, "No route to host"
- },
- {
- WSAENOTEMPTY, "Directory not empty"
- },
- {
- WSAEPROCLIM, "Too many processes"
- },
- {
- WSAEUSERS, "Too many users"
- },
- {
- WSAEDQUOT, "Disc quota exceeded"
- },
- {
- WSAESTALE, "Stale NFS file handle"
- },
- {
- WSAEREMOTE, "Too many levels of remote in path"
- },
- {
- WSASYSNOTREADY, "Network system is unavailable"
- },
- {
- WSAVERNOTSUPPORTED, "Winsock version out of range"
- },
- {
- WSANOTINITIALISED, "WSAStartup not yet called"
- },
- {
- WSAEDISCON, "Graceful shutdown in progress"
- },
- {
- WSAHOST_NOT_FOUND, "Host not found"
- },
- {
- WSATRY_AGAIN, "NA Host not found / SERVFAIL"
- },
- {
- WSANO_RECOVERY, "Non recoverable FORMERR||REFUSED||NOTIMP"
- },
- {
- WSANO_DATA, "No host data of that type was found"
- },
- {
- 0, 0
- } /* End of table */
-};
-
-
-/*
- * Returns 0 if not found, linear but who cares, at this moment
- * we're already in pain :)
- */
-
-static int
-LookupWSErrorMessage(DWORD err, char *dest)
-{
- struct WSErrorEntry *e;
-
- for (e = WSErrors; e->description; e++)
- {
- if (e->error == err)
- {
- strcpy(dest, e->description);
- return 1;
- }
- }
- return 0;
-}
-
-
-struct MessageDLL
-{
- const char *dll_name;
- void *handle;
- int loaded; /* BOOL */
-} dlls[] =
-
-{
- {
- "netmsg.dll", 0, 0
- },
- {
- "winsock.dll", 0, 0
- },
- {
- "ws2_32.dll", 0, 0
- },
- {
- "wsock32n.dll", 0, 0
- },
- {
- "mswsock.dll", 0, 0
- },
- {
- "ws2help.dll", 0, 0
- },
- {
- "ws2thk.dll", 0, 0
- },
- {
- 0, 0, 1
- } /* Last one, no dll, always loaded */
-};
-
-#define DLLS_SIZE (sizeof(dlls)/sizeof(struct MessageDLL))
-
-/*
- * Returns a description of the socket error by first trying
- * to find it in the lookup table, and if that fails, tries
- * to load any of the winsock dlls to find that message.
- * The DLL thing works from Nt4 (spX ?) up, but some special
- * versions of winsock might have this as well (seen on Win98 SE
- * special install) / Magnus Naeslund (mag@fbab.net)
- *
- */
-
-const char *
-winsock_strerror(int err, char *strerrbuf, size_t buflen)
-{
- unsigned long flags;
- int offs,
- i;
- int success = LookupWSErrorMessage(err, strerrbuf);
-
- for (i = 0; !success && i < DLLS_SIZE; i++)
- {
-
- if (!dlls[i].loaded)
- {
- dlls[i].loaded = 1; /* Only load once */
- dlls[i].handle = (void *) LoadLibraryEx(
- dlls[i].dll_name,
- 0,
- LOAD_LIBRARY_AS_DATAFILE);
- }
-
- if (dlls[i].dll_name && !dlls[i].handle)
- continue; /* Didn't load */
-
- flags = FORMAT_MESSAGE_FROM_SYSTEM
- | FORMAT_MESSAGE_IGNORE_INSERTS
- | (dlls[i].handle ? FORMAT_MESSAGE_FROM_HMODULE : 0);
-
- success = 0 != FormatMessage(
- flags,
- dlls[i].handle, err,
- MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
- strerrbuf, buflen - 64,
- 0
- );
- }
-
- if (!success)
- sprintf(strerrbuf, libpq_gettext("unrecognized socket error: 0x%08X/%d"), err, err);
- else
- {
- strerrbuf[buflen - 1] = '\0';
- offs = strlen(strerrbuf);
- if (offs > (int) buflen - 64)
- offs = buflen - 64;
- sprintf(strerrbuf + offs, " (0x%08X/%d)", err, err);
- }
- return strerrbuf;
-}
diff --git a/libpq/win32/win32.h b/libpq/win32/win32.h
deleted file mode 100644
index be00ea7..0000000
--- a/libpq/win32/win32.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * src/interfaces/libpq/win32.h
- */
-#ifndef __win32_h_included
-#define __win32_h_included
-
-/*
- * Some compatibility functions
- */
-#ifdef __BORLANDC__
-#define _timeb timeb
-#define _ftime(a) ftime(a)
-#define _errno errno
-#define popen(a,b) _popen(a,b)
-#else
-/* open provided elsewhere */
-#define close(a) _close(a)
-#define read(a,b,c) _read(a,b,c)
-#define write(a,b,c) _write(a,b,c)
-#endif
-
-#undef EAGAIN /* doesn't apply on sockets */
-#undef EINTR
-#define EINTR WSAEINTR
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#endif
-#ifndef ECONNRESET
-#define ECONNRESET WSAECONNRESET
-#endif
-#ifndef EINPROGRESS
-#define EINPROGRESS WSAEINPROGRESS
-#endif
-
-/*
- * support for handling Windows Socket errors
- */
-extern const char *winsock_strerror(int err, char *strerrbuf, size_t buflen);
-
-#endif
diff --git a/libpq/win32/win32error.c b/libpq/win32/win32error.c
deleted file mode 100644
index cf65225..0000000
--- a/libpq/win32/win32error.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * win32error.c
- * Map win32 error codes to errno values
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- * src/port/win32error.c
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef FRONTEND
-#include "postgres.h"
-#else
-#include "postgres_fe.h"
-#endif
-
-static const struct
-{
- DWORD winerr;
- int doserr;
-} doserrors[] =
-
-{
- {
- ERROR_INVALID_FUNCTION, EINVAL
- },
- {
- ERROR_FILE_NOT_FOUND, ENOENT
- },
- {
- ERROR_PATH_NOT_FOUND, ENOENT
- },
- {
- ERROR_TOO_MANY_OPEN_FILES, EMFILE
- },
- {
- ERROR_ACCESS_DENIED, EACCES
- },
- {
- ERROR_INVALID_HANDLE, EBADF
- },
- {
- ERROR_ARENA_TRASHED, ENOMEM
- },
- {
- ERROR_NOT_ENOUGH_MEMORY, ENOMEM
- },
- {
- ERROR_INVALID_BLOCK, ENOMEM
- },
- {
- ERROR_BAD_ENVIRONMENT, E2BIG
- },
- {
- ERROR_BAD_FORMAT, ENOEXEC
- },
- {
- ERROR_INVALID_ACCESS, EINVAL
- },
- {
- ERROR_INVALID_DATA, EINVAL
- },
- {
- ERROR_INVALID_DRIVE, ENOENT
- },
- {
- ERROR_CURRENT_DIRECTORY, EACCES
- },
- {
- ERROR_NOT_SAME_DEVICE, EXDEV
- },
- {
- ERROR_NO_MORE_FILES, ENOENT
- },
- {
- ERROR_LOCK_VIOLATION, EACCES
- },
- {
- ERROR_SHARING_VIOLATION, EACCES
- },
- {
- ERROR_BAD_NETPATH, ENOENT
- },
- {
- ERROR_NETWORK_ACCESS_DENIED, EACCES
- },
- {
- ERROR_BAD_NET_NAME, ENOENT
- },
- {
- ERROR_FILE_EXISTS, EEXIST
- },
- {
- ERROR_CANNOT_MAKE, EACCES
- },
- {
- ERROR_FAIL_I24, EACCES
- },
- {
- ERROR_INVALID_PARAMETER, EINVAL
- },
- {
- ERROR_NO_PROC_SLOTS, EAGAIN
- },
- {
- ERROR_DRIVE_LOCKED, EACCES
- },
- {
- ERROR_BROKEN_PIPE, EPIPE
- },
- {
- ERROR_DISK_FULL, ENOSPC
- },
- {
- ERROR_INVALID_TARGET_HANDLE, EBADF
- },
- {
- ERROR_INVALID_HANDLE, EINVAL
- },
- {
- ERROR_WAIT_NO_CHILDREN, ECHILD
- },
- {
- ERROR_CHILD_NOT_COMPLETE, ECHILD
- },
- {
- ERROR_DIRECT_ACCESS_HANDLE, EBADF
- },
- {
- ERROR_NEGATIVE_SEEK, EINVAL
- },
- {
- ERROR_SEEK_ON_DEVICE, EACCES
- },
- {
- ERROR_DIR_NOT_EMPTY, ENOTEMPTY
- },
- {
- ERROR_NOT_LOCKED, EACCES
- },
- {
- ERROR_BAD_PATHNAME, ENOENT
- },
- {
- ERROR_MAX_THRDS_REACHED, EAGAIN
- },
- {
- ERROR_LOCK_FAILED, EACCES
- },
- {
- ERROR_ALREADY_EXISTS, EEXIST
- },
- {
- ERROR_FILENAME_EXCED_RANGE, ENOENT
- },
- {
- ERROR_NESTING_NOT_ALLOWED, EAGAIN
- },
- {
- ERROR_NOT_ENOUGH_QUOTA, ENOMEM
- }
-};
-
-void
-_dosmaperr(unsigned long e)
-{
- int i;
-
- if (e == 0)
- {
- errno = 0;
- return;
- }
-
- for (i = 0; i < lengthof(doserrors); i++)
- {
- if (doserrors[i].winerr == e)
- {
- int doserr = doserrors[i].doserr;
-
-#ifndef FRONTEND
- ereport(DEBUG5,
- (errmsg_internal("mapped win32 error code %lu to %d",
- e, doserr)));
-#elif FRONTEND_DEBUG
- fprintf(stderr, "mapped win32 error code %lu to %d", e, doserr);
-#endif
- errno = doserr;
- return;
- }
- }
-
-#ifndef FRONTEND
- ereport(LOG,
- (errmsg_internal("unrecognized win32 error code: %lu",
- e)));
-#else
- fprintf(stderr, "unrecognized win32 error code: %lu", e);
-#endif
-
- errno = EINVAL;
- return;
-}
diff --git a/libpq/win32/win32setlocale.c b/libpq/win32/win32setlocale.c
deleted file mode 100644
index 4abc7aa..0000000
--- a/libpq/win32/win32setlocale.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * win32setlocale.c
- * Wrapper to work around bugs in Windows setlocale() implementation
- *
- * Copyright (c) 2011-2016, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- * src/port/win32setlocale.c
- *
- *
- * The setlocale() function in Windows is broken in two ways. First, it
- * has a problem with locale names that have a dot in the country name. For
- * example:
- *
- * "Chinese (Traditional)_Hong Kong S.A.R..950"
- *
- * For some reason, setlocale() doesn't accept that as argument, even though
- * setlocale(LC_ALL, NULL) returns exactly that. Fortunately, it accepts
- * various alternative names for such countries, so to work around the broken
- * setlocale() function, we map the troublemaking locale names to accepted
- * aliases, before calling setlocale().
- *
- * The second problem is that the locale name for "Norwegian (Bokm&aring;l)"
- * contains a non-ASCII character. That's problematic, because it's not clear
- * what encoding the locale name itself is supposed to be in, when you
- * haven't yet set a locale. Also, it causes problems when the cluster
- * contains databases with different encodings, as the locale name is stored
- * in the pg_database system catalog. To work around that, when setlocale()
- * returns that locale name, map it to a pure-ASCII alias for the same
- * locale.
- *-------------------------------------------------------------------------
- */
-
-#include "c.h"
-
-#undef setlocale
-
-struct locale_map
-{
- /*
- * String in locale name to replace. Can be a single string (end is NULL),
- * or separate start and end strings. If two strings are given, the locale
- * name must contain both of them, and everything between them is
- * replaced. This is used for a poor-man's regexp search, allowing
- * replacement of "start.*end".
- */
- const char *locale_name_start;
- const char *locale_name_end;
-
- const char *replacement; /* string to replace the match with */
-};
-
-/*
- * Mappings applied before calling setlocale(), to the argument.
- */
-static const struct locale_map locale_map_argument[] = {
- /*
- * "HKG" is listed here:
- * http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.71%29.aspx
- * (Country/Region Strings).
- *
- * "ARE" is the ISO-3166 three-letter code for U.A.E. It is not on the
- * above list, but seems to work anyway.
- */
- {"Hong Kong S.A.R.", NULL, "HKG"},
- {"U.A.E.", NULL, "ARE"},
-
- /*
- * The ISO-3166 country code for Macau S.A.R. is MAC, but Windows doesn't
- * seem to recognize that. And Macau isn't listed in the table of accepted
- * abbreviations linked above. Fortunately, "ZHM" seems to be accepted as
- * an alias for "Chinese (Traditional)_Macau S.A.R..950". I'm not sure
- * where "ZHM" comes from, must be some legacy naming scheme. But hey, it
- * works.
- *
- * Note that unlike HKG and ARE, ZHM is an alias for the *whole* locale
- * name, not just the country part.
- *
- * Some versions of Windows spell it "Macau", others "Macao".
- */
- {"Chinese (Traditional)_Macau S.A.R..950", NULL, "ZHM"},
- {"Chinese_Macau S.A.R..950", NULL, "ZHM"},
- {"Chinese (Traditional)_Macao S.A.R..950", NULL, "ZHM"},
- {"Chinese_Macao S.A.R..950", NULL, "ZHM"},
- {NULL, NULL, NULL}
-};
-
-/*
- * Mappings applied after calling setlocale(), to its return value.
- */
-static const struct locale_map locale_map_result[] = {
- /*
- * "Norwegian (Bokm&aring;l)" locale name contains the a-ring character.
- * Map it to a pure-ASCII alias.
- *
- * It's not clear what encoding setlocale() uses when it returns the
- * locale name, so to play it safe, we search for "Norwegian (Bok*l)".
- */
- {"Norwegian (Bokm", "l)_Norway", "Norwegian_Norway"},
- {NULL, NULL, NULL}
-};
-
-#define MAX_LOCALE_NAME_LEN 100
-
-static const char *
-map_locale(const struct locale_map * map, const char *locale)
-{
- static char aliasbuf[MAX_LOCALE_NAME_LEN];
- int i;
-
- /* Check if the locale name matches any of the problematic ones. */
- for (i = 0; map[i].locale_name_start != NULL; i++)
- {
- const char *needle_start = map[i].locale_name_start;
- const char *needle_end = map[i].locale_name_end;
- const char *replacement = map[i].replacement;
- char *match;
- char *match_start = NULL;
- char *match_end = NULL;
-
- match = strstr(locale, needle_start);
- if (match)
- {
- /*
- * Found a match for the first part. If this was a two-part
- * replacement, find the second part.
- */
- match_start = match;
- if (needle_end)
- {
- match = strstr(match_start + strlen(needle_start), needle_end);
- if (match)
- match_end = match + strlen(needle_end);
- else
- match_start = NULL;
- }
- else
- match_end = match_start + strlen(needle_start);
- }
-
- if (match_start)
- {
- /* Found a match. Replace the matched string. */
- int matchpos = match_start - locale;
- int replacementlen = strlen(replacement);
- char *rest = match_end;
- int restlen = strlen(rest);
-
- /* check that the result fits in the static buffer */
- if (matchpos + replacementlen + restlen + 1 > MAX_LOCALE_NAME_LEN)
- return NULL;
-
- memcpy(&aliasbuf[0], &locale[0], matchpos);
- memcpy(&aliasbuf[matchpos], replacement, replacementlen);
- /* includes null terminator */
- memcpy(&aliasbuf[matchpos + replacementlen], rest, restlen + 1);
-
- return aliasbuf;
- }
- }
-
- /* no match, just return the original string */
- return locale;
-}
-
-char *
-pgwin32_setlocale(int category, const char *locale)
-{
- const char *argument;
- char *result;
-
- if (locale == NULL)
- argument = NULL;
- else
- argument = map_locale(locale_map_argument, locale);
-
- /* Call the real setlocale() function */
- result = setlocale(category, argument);
-
- /*
- * setlocale() is specified to return a "char *" that the caller is
- * forbidden to modify, so casting away the "const" is innocuous.
- */
- if (result)
- result = (char *) map_locale(locale_map_result, result);
-
- return result;
-}
diff --git a/packages.manifest b/packages.manifest
new file mode 100644
index 0000000..f05ada7
--- /dev/null
+++ b/packages.manifest
@@ -0,0 +1,2 @@
+: 1
+location: libpq/
diff --git a/repositories.manifest b/repositories.manifest
new file mode 100644
index 0000000..2ec8d99
--- /dev/null
+++ b/repositories.manifest
@@ -0,0 +1,6 @@
+: 1
+summary: PostgreSQL build2 package repository
+
+:
+role: prerequisite
+location: ../../openssl/openssl.git##HEAD
diff --git a/tests/conninfo/postgres_fe.h b/tests/conninfo/postgres_fe.h
deleted file mode 100644
index 61cb7c4..0000000
--- a/tests/conninfo/postgres_fe.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* file : tests/conninfo/postgres_fe.h
- * copyright : Copyright (c) 2016-2019 Code Synthesis Ltd
- * license : PostgreSQL License; see accompanying COPYRIGHT file
- */
-
-/*
- * The original uri-regress.c includes src/include/postgres_fe.h that is
- * located in libpq/postgresql/ directory in our source tree. This file is not
- * installed, so to keep the test as a subproject and be able to test against
- * the installed libpq library we replace it with the header stub, containing
- * the bare minimum that is required the test to compile.
- */
-#ifndef TESTS_CONNINFO_POSTGRES_FE_H
-#define TESTS_CONNINFO_POSTGRES_FE_H
-
-#include <stdbool.h>
-#include <string.h>
-
-#endif /* TESTS_CONNINFO_POSTGRES_FE_H */
diff --git a/tests/conninfo/uri-regress.c b/tests/conninfo/uri-regress.c
deleted file mode 100644
index bf1d970..0000000
--- a/tests/conninfo/uri-regress.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * uri-regress.c
- * A test program for libpq URI format
- *
- * This is a helper for libpq conninfo regression testing. It takes a single
- * conninfo string as a parameter, parses it using PQconninfoParse, and then
- * prints out the values from the parsed PQconninfoOption struct that differ
- * from the defaults (obtained from PQconndefaults).
- *
- * Portions Copyright (c) 2012-2016, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- * src/interfaces/libpq/test/uri-regress.c
- */
-
-#include "postgres_fe.h"
-
-#include "libpq-fe.h"
-
-int
-main(int argc, char *argv[])
-{
- PQconninfoOption *opts;
- PQconninfoOption *defs;
- PQconninfoOption *opt;
- PQconninfoOption *def;
- char *errmsg = NULL;
- bool local = true;
-
- if (argc != 2)
- return 1;
-
- opts = PQconninfoParse(argv[1], &errmsg);
- if (opts == NULL)
- {
- fprintf(stderr, "uri-regress: %s", errmsg);
- return 1;
- }
-
- defs = PQconndefaults();
- if (defs == NULL)
- {
- fprintf(stderr, "uri-regress: cannot fetch default options\n");
- return 1;
- }
-
- /*
- * Loop on the options, and print the value of each if not the default.
- *
- * XXX this coding assumes that PQconninfoOption structs always have the
- * keywords in the same order.
- */
- for (opt = opts, def = defs; opt->keyword; ++opt, ++def)
- {
- if (opt->val != NULL)
- {
- if (def->val == NULL || strcmp(opt->val, def->val) != 0)
- printf("%s='%s' ", opt->keyword, opt->val);
-
- /*
- * Try to detect if this is a Unix-domain socket or inet. This is
- * a bit grotty but it's the same thing that libpq itself does.
- *
- * Note that we directly test for '/' instead of using
- * is_absolute_path, as that would be considerably more messy.
- * This would fail on Windows, but that platform doesn't have
- * Unix-domain sockets anyway.
- */
- if (*opt->val &&
- (strcmp(opt->keyword, "hostaddr") == 0 ||
- (strcmp(opt->keyword, "host") == 0 && *opt->val != '/')))
- {
- local = false;
- }
- }
- }
-
- if (local)
- printf("(local)\n");
- else
- printf("(inet)\n");
-
- return 0;
-}
diff --git a/upstream b/upstream
new file mode 160000
+Subproject 578a551f82f7ad746b36d98c401bdc92c136d66