postgresql: update to version 9.5.4 and major rework 3220/head
authorDaniel Golle <daniel@makrotopia.org>
Fri, 23 Sep 2016 14:41:49 +0000 (16:41 +0200)
committerDaniel Golle <daniel@makrotopia.org>
Fri, 23 Sep 2016 18:03:05 +0000 (20:03 +0200)
 * convert package build to use host-build for ecpg, pg_config and zic
 * introduce /lib/functions/postgresql.sh to be used by packages
   requiring a postgres database to exist as well as postgres' init
 * no longer require shadow-su, patch pg_ctl to setuid() ifself instead
 * auto-create database directory if there is enough free space
 * auto-create databases configured in UCI
 * remove some dead uci config options
 * grab maintainership

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
libs/postgresql/Makefile
libs/postgresql/files/postgresql.config
libs/postgresql/files/postgresql.init
libs/postgresql/files/postgresql.sh [new file with mode: 0644]
libs/postgresql/patches/900-pg_ctl-setuid.patch [new file with mode: 0644]

index 174159cff9ff75054eb753a4f7935e23434663a6..a1564dc3dfc7b25f4e8651c24da257b75d533167 100644 (file)
@@ -8,9 +8,9 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=postgresql
-PKG_VERSION:=9.5.1
+PKG_VERSION:=9.5.4
 PKG_RELEASE:=1
-PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
 PKG_LICENSE:=PostgreSQL
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
@@ -18,18 +18,20 @@ PKG_SOURCE_URL:=\
        http://ftp9.us.postgresql.org/pub/mirrors/postgresql/source/v$(PKG_VERSION) \
        http://ftp.be.postgresql.org/postgresql/source/v$(PKG_VERSION) \
        ftp://ftp-archives.postgresql.org/pub/source/v$(PKG_VERSION)
-PKG_MD5SUM:=11e037afaa4bd0c90bb3c3d955e2b401
+PKG_MD5SUM:=cf5e571164ad66028ecd7dd8819e3765470d45bcd440d258b686be7e69c76ed0
 PKG_BUILD_PARALLEL:=1
 PKG_USE_MIPS16:=0
 PKG_FIXUP:=autoreconf
 PKG_MACRO_PATHS:=config
+PKG_BUILD_DEPENDS += postgresql/host
 
+include $(INCLUDE_DIR)/host-build.mk
 include $(INCLUDE_DIR)/package.mk
 
 define Package/libpq
   SECTION:=libs
   CATEGORY:=Libraries
-  DEPENDS:=+zlib +libreadline +libpthread +libncurses
+  DEPENDS:=+zlib +libreadline +libpthread +libncursesw
   TITLE:=PostgreSQL client library
   URL:=http://www.postgresql.org/
   SUBMENU:=database
@@ -42,7 +44,7 @@ endef
 define Package/pgsql-cli
   SECTION:=utils
   CATEGORY:=Utilities
-  DEPENDS:=+libpq +USE_UCLIBC:librt +shadow-utils +shadow-su
+  DEPENDS:=+libpq +librt
   TITLE:=Command Line Interface (CLI) to PostgreSQL databases
   URL:=http://www.postgresql.org/
   SUBMENU:=database
@@ -55,7 +57,7 @@ endef
 define Package/pgsql-server
   SECTION:=utils
   CATEGORY:=Utilities
-  DEPENDS:=+libpq +USE_UCLIBC:librt
+  DEPENDS:=+libpq +librt
   TITLE:=PostgreSQL databases Server
   URL:=http://www.postgresql.org/
   SUBMENU:=database
@@ -81,27 +83,8 @@ endif
 
 TARGET_CONFIGURE_OPTS+=$(PGSQL_CONFIG_VARS)
 
-# Need a native ecpg ,pg_config, and zic for build
-define Build/Configure
-       (cd $(PKG_BUILD_DIR); rm -f config.cache; \
-               $(PGSQL_CONFIG_VARS) \
-               ./configure \
-                       --prefix=/usr \
-                       --exec-prefix=/usr \
-                       --bindir=/usr/bin \
-                       --datadir=/usr/share \
-                       --includedir=/usr/include \
-                       --infodir=/usr/share/info \
-                       --libdir=/usr/lib \
-                       --libexecdir=/usr/lib \
-                       --localstatedir=/var \
-                       --mandir=/usr/share/man \
-                       --sbindir=/usr/sbin \
-                       --sysconfdir=/etc \
+HOST_CONFIGURE_ARGS += \
                        $(DISABLE_NLS) \
-                       --enable-shared \
-                       --enable-static \
-                       --disable-integer-datetimes \
                        --disable-rpath \
                        --without-bonjour \
                        --without-gssapi \
@@ -113,52 +96,9 @@ define Build/Configure
                        --without-readline \
                        --without-tcl \
                        --with-zlib="yes" \
-                       --enable-depend \
-                       --with-system-timezone=/tmp \
-       );
-       $(MAKE) -C $(PKG_BUILD_DIR)/src/interfaces/ecpg/preproc clean
-       $(MAKE) -C $(PKG_BUILD_DIR)/src/interfaces/ecpg/preproc CC="$(HOSTCC)"
-       mv $(PKG_BUILD_DIR)/src/interfaces/ecpg/preproc/ecpg \
-               $(PKG_BUILD_DIR)/src/interfaces/ecpg/preproc/ecpg.host
-       $(MAKE) -C $(PKG_BUILD_DIR)/src/timezone clean
-       $(MAKE) -C $(PKG_BUILD_DIR)/src/timezone CC="$(HOSTCC)"
-       mv $(PKG_BUILD_DIR)/src/timezone/zic $(PKG_BUILD_DIR)/host-zic
-       $(INSTALL_DIR) $(STAGING_DIR)/host/bin/
-       $(CP) $(PKG_BUILD_DIR)/host-zic $(STAGING_DIR)/host/bin/zic
-       $(MAKE) -C $(PKG_BUILD_DIR)/src/bin/pg_config clean
-       $(MAKE) -C $(PKG_BUILD_DIR)/src/bin/pg_config CC="$(HOSTCC)"
-       mv $(PKG_BUILD_DIR)/src/bin/pg_config/pg_config \
-               $(PKG_BUILD_DIR)/src/bin/pg_config/pg_config.host
-       $(MAKE) -C $(PKG_BUILD_DIR) distclean
-
-       (cd $(PKG_BUILD_DIR); rm -f config.cache; \
-               $(TARGET_CONFIGURE_OPTS) \
-               CFLAGS="$(TARGET_CFLAGS)" \
-               CPPFLAGS="$$$$CPPFLAGS $(TARGET_CPPFLAGS)" \
-               LDFLAGS="$(TARGET_LDFLAGS)" \
-               ./configure \
-                       --target=$(GNU_TARGET_NAME) \
-                       --host=$(GNU_TARGET_NAME) \
-                       --build=$(GNU_HOST_NAME) \
-                       --program-prefix="" \
-                       --program-suffix="" \
-                       --prefix=/usr \
-                       --exec-prefix=/usr \
-                       --bindir=/usr/bin \
-                       --datadir=/usr/share \
-                       --includedir=/usr/include \
-                       --infodir=/usr/share/info \
-                       --libdir=/usr/lib \
-                       --libexecdir=/usr/lib \
-                       --localstatedir=/var \
-                       --mandir=/usr/share/man \
-                       --sbindir=/usr/sbin \
-                       --sysconfdir=/etc \
-                       $(DISABLE_NLS) \
-                       $(DISABLE_LARGEFILE) \
-                       --enable-shared \
-                       --enable-static \
-                       --disable-integer-datetimes \
+                       --enable-depend
+
+CONFIGURE_ARGS += \
                        --disable-rpath \
                        --without-bonjour \
                        --without-gssapi \
@@ -170,9 +110,26 @@ define Build/Configure
                        --without-tcl \
                        --with-zlib="yes" \
                        --enable-depend \
-                       $(if $(CONFIG_TARGET_avr32),--disable-spinlocks) \
-       );
-       $(SED) 's@ECPG = ../../preproc/ecpg@ECPG = ../../preproc/ecpg.host@' $(PKG_BUILD_DIR)/src/interfaces/ecpg/test/Makefile.regress
+                       $(if $(CONFIG_TARGET_avr32),--disable-spinlocks)
+
+# Need a native ecpg ,pg_config, and zic for build
+define Host/Compile
+       $(MAKE) -C $(HOST_BUILD_DIR)/src/interfaces/ecpg/preproc CC="$(HOSTCC)"
+       $(MAKE) -C $(HOST_BUILD_DIR)/src/timezone CC="$(HOSTCC)"
+       $(MAKE) -C $(HOST_BUILD_DIR)/src/bin/pg_config CC="$(HOSTCC)"
+endef
+
+define Host/Install
+       $(INSTALL_DIR) $(STAGING_DIR)/usr/bin/
+       $(INSTALL_BIN) $(HOST_BUILD_DIR)/src/bin/pg_config/pg_config $(STAGING_DIR)/usr/bin/
+       $(INSTALL_DIR) $(STAGING_DIR)/host/bin/
+       $(INSTALL_BIN) $(HOST_BUILD_DIR)/src/interfaces/ecpg/preproc/ecpg $(STAGING_DIR)/host/bin/
+       $(INSTALL_BIN) $(HOST_BUILD_DIR)/src/timezone/zic $(STAGING_DIR)/host/bin/
+endef
+
+define Build/Configure
+       $(Build/Configure/Default)
+       $(SED) 's@ECPG = ../../preproc/ecpg@ECPG = $(STAGING_DIR)/host/bin/ecpg@' $(PKG_BUILD_DIR)/src/interfaces/ecpg/test/Makefile.regress
 endef
 
 TARGET_CFLAGS += $(FPIC) -lpthread
@@ -201,22 +158,25 @@ endef
 
 define Package/pgsql-server/install
        $(INSTALL_DIR) $(1)/usr/bin
-       $(INSTALL_DIR) $(1)/usr/share/postgresql
-       $(INSTALL_DIR) $(1)/usr/lib
-       $(INSTALL_DIR) $(1)/etc/init.d
-       $(INSTALL_DIR) $(1)/etc/config
        $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin
        ln -sf postgres $(1)/usr/bin/postmaster
 
-       $(INSTALL_BIN) ./files/postgresql.init $(1)/etc/init.d/postgresql
-
+       $(INSTALL_DIR) $(1)/usr/share/postgresql
        $(CP) $(PKG_INSTALL_DIR)/usr/share/postgresql/* \
                $(1)/usr/share/postgresql
 
-       $(INSTALL_DATA) ./files/postgresql.config $(1)/etc/config/postgresql
-
+       $(INSTALL_DIR) $(1)/usr/lib
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/postgresql \
                $(1)/usr/lib
+
+       $(INSTALL_DIR) $(1)/lib/functions
+       $(INSTALL_BIN) ./files/postgresql.sh $(1)/lib/functions/
+
+       $(INSTALL_DIR) $(1)/etc/config
+       $(INSTALL_DATA) ./files/postgresql.config $(1)/etc/config/postgresql
+
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_BIN) ./files/postgresql.init $(1)/etc/init.d/postgresql
 endef
 
 define Package/pgsql-server/conffiles
@@ -225,7 +185,6 @@ endef
 
 define Build/InstallDev
        $(INSTALL_DIR) $(1)/usr/bin
-       $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/bin/pg_config/pg_config.host $(1)/usr/bin/pg_config
        $(INSTALL_DIR) $(1)/usr/include
        $(CP) $(PKG_INSTALL_DIR)/usr/include/libpq $(1)/usr/include/
        $(CP) $(PKG_INSTALL_DIR)/usr/include/libpq-fe.h $(1)/usr/include/
@@ -236,10 +195,9 @@ define Build/InstallDev
        $(CP) $(PKG_INSTALL_DIR)/usr/include/postgresql $(1)/usr/include/
        $(INSTALL_DIR) $(1)/usr/lib
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/libpq.{a,so*} $(1)/usr/lib/
-       $(CP) $(PKG_BUILD_DIR)/src/interfaces/ecpg/preproc/ecpg.host $(1)/usr/bin/ecpg
-       $(CP) $(PKG_BUILD_DIR)/host-zic $(1)/usr/bin/zic
 endef
 
+$(eval $(call HostBuild))
 $(eval $(call BuildPackage,libpq))
 $(eval $(call BuildPackage,pgsql-cli))
 $(eval $(call BuildPackage,pgsql-server))
index df17c1279efcb767dbeb1aa4edccb28a8ce94894..4760bf1d5881239d7869bae417e764cd42745d76 100644 (file)
@@ -1,5 +1,2 @@
 config postgresql config
-       option PGUSER   postgres
        option PGDATA   /var/postgresql/data
-       option PGLOG    /var/postgresql/data/postgresql.log
-       option PG_CTL   /usr/bin/pg_ctl
index 458e8c00f8387e729e89b4a1c9e1437ae1f1a81f..d17264e8ffc8d299ff44e41954ee49dc4bb95309 100644 (file)
@@ -26,48 +26,47 @@ cleanup() {
 }
 
 start_service() {
+       . /lib/functions/postgresql.sh
+
        config_load "postgresql"
        config_get pgdata config PGDATA
-       config_get pguser config PGUSER
-       config_get pgctl config PG_CTL
        config_get pgopts config PGOPTS
 
        user_exists postgres 5432 || user_add postgres 5432
        group_exists postgres 5432 || group_add postgres 5432
 
+       fix_perms
+       fix_hosts
+
        if [ ! -d "${pgdata}" ]; then
-               echo "Create the data directory (${pgdata}) and try again"
-               return 1
+               pg_init_data ${pgdata}
+               [ $? -gt 0 ] && return 1
        fi
 
-       fix_perms
-       fix_hosts
+       cleanup "${pgdata}"
 
        procd_open_instance
-
-       procd_set_param user ${pguser}
+       procd_set_param user postgres
        procd_set_param command $PROG
        procd_append_param command -D "${pgdata}"
        [ -n "${pgopts}" ] && procd_append_param command -o "${pgopts}"
-
        procd_set_param respawn retry=60
        procd_close_instance
+
+       procd_open_instance
+       procd_set_param user postgres
+       procd_set_param command /lib/functions/postgresql.sh init "${pgdata}"
+       procd_close_instance
 }
 
 reload_service() {
        config_load "postgresql"
        config_get pgdata config PGDATA
-       config_get pguser config PGUSER
-       config_get pgctl config PG_CTL
-       ${pgctl} reload -U ${pguser} -D '${pgdata}' -s
+       /usr/bin/pg_ctl reload -U postgres -D "${pgdata}" -s
 }
 
 status() {
        config_load "postgresql"
        config_get pgdata config PGDATA
-       config_get pguser config PGUSER
-       config_get pgctl config PG_CTL
-       echo "status postgres..."
-       ${pgctl} status -U ${pguser} -D '${pgdata}'
-       echo "ok"
+       /usr/bin/pg_ctl status -U postgres -D "${pgdata}"
 }
diff --git a/libs/postgresql/files/postgresql.sh b/libs/postgresql/files/postgresql.sh
new file mode 100644 (file)
index 0000000..78b6ab8
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+PSQL="/usr/bin/psql"
+
+free_megs() {
+       fsdir=$1
+       while [ ! -d "$fsdir" ]; do
+               fsdir=$(dirname $fsdir)
+       done
+       df -m $fsdir | while read fs bl us av cap mnt; do [ "$av" = "Available" ] || echo $av; done
+}
+
+pg_init_data() {
+       # make sure we got at least 50MB of free space
+       [ $(free_megs $1) -lt 50 ] && return 1
+       pg_ctl initdb -U postgres -D $1
+}
+
+pg_server_ready() {
+       t=0
+       while [ $t -le 90 ]; do
+               pg_ctl status -U postgres -D $1 2>/dev/null >/dev/null && return 0
+               t=$((t+1))
+               sleep 1
+       done
+       return 1
+}
+
+# $1: dbname, $2: username, $3: password
+pg_require_db() {
+       pg_test_db $@ && return 0
+       ( echo "CREATE DATABASE $1;"
+       echo -n "CREATE USER $2"
+       [ "$3" ] && echo -n " WITH PASSWORD '$3'"
+       echo ";"
+       echo "GRANT ALL PRIVILEGES ON DATABASE \"$1\" to $2;" ) |
+               $PSQL -U postgres -d template1 -e
+       return $?
+}
+
+pg_test_db() {
+       PGPASSWORD=$3
+       echo "SHOW ALL;" | $PSQL -U $2 -d $1 -q 2>/dev/null >/dev/null
+       return $?
+}
+
+uci_require_db() {
+       local dbname dbuser dbpass
+       config_get dbname $1 name
+       config_get dbuser $1 user
+       config_get dbpass $1 pass
+       pg_require_db $dbname $dbuser $dbpass
+}
+
+[ "$1" = "init" ] && {
+       . /lib/functions.sh
+       pg_server_ready $2 || exit 1
+       config_load postgresql
+       config_foreach uci_require_db postgres-db
+}
diff --git a/libs/postgresql/patches/900-pg_ctl-setuid.patch b/libs/postgresql/patches/900-pg_ctl-setuid.patch
new file mode 100644 (file)
index 0000000..71ca271
--- /dev/null
@@ -0,0 +1,109 @@
+Index: postgresql-9.5.4/src/bin/pg_ctl/pg_ctl.c
+===================================================================
+--- postgresql-9.5.4.orig/src/bin/pg_ctl/pg_ctl.c
++++ postgresql-9.5.4/src/bin/pg_ctl/pg_ctl.c
+@@ -95,6 +95,7 @@ static char *event_source = NULL;
+ static char *register_servicename = "PostgreSQL";             /* FIXME: + version ID? */
+ static char *register_username = NULL;
+ static char *register_password = NULL;
++static char *username = "";
+ static char *argv0 = NULL;
+ static bool allow_core_files = false;
+ static time_t start_time;
+@@ -2114,6 +2115,9 @@ do_help(void)
+ #endif
+       printf(_("  -s, --silent           only print errors, no informational messages\n"));
+       printf(_("  -t, --timeout=SECS     seconds to wait when using -w option\n"));
++#if !defined(WIN32) && !defined(__CYGWIN__)
++      printf(_("  -U USERNAME            user name of account PostgreSQL server is running as\n"));
++#endif
+       printf(_("  -V, --version          output version information, then exit\n"));
+       printf(_("  -w                     wait until operation completes\n"));
+       printf(_("  -W                     do not wait until operation completes\n"));
+@@ -2310,6 +2314,7 @@ main(int argc, char **argv)
+               {"pgdata", required_argument, NULL, 'D'},
+               {"silent", no_argument, NULL, 's'},
+               {"timeout", required_argument, NULL, 't'},
++              {"username", required_argument, NULL, 'U'},
+               {"core-files", no_argument, NULL, 'c'},
+               {NULL, 0, NULL, 0}
+       };
+@@ -2350,20 +2355,6 @@ main(int argc, char **argv)
+               }
+       }
+-      /*
+-       * Disallow running as root, to forestall any possible security holes.
+-       */
+-#ifndef WIN32
+-      if (geteuid() == 0)
+-      {
+-              write_stderr(_("%s: cannot be run as root\n"
+-                                         "Please log in (using, e.g., \"su\") as the "
+-                                         "(unprivileged) user that will\n"
+-                                         "own the server process.\n"),
+-                                       progname);
+-              exit(1);
+-      }
+-#endif
+       env_wait = getenv("PGCTLTIMEOUT");
+       if (env_wait != NULL)
+@@ -2449,11 +2440,15 @@ main(int argc, char **argv)
+                                       wait_seconds_arg = true;
+                                       break;
+                               case 'U':
++#if defined(WIN32) || defined(__CYGWIN__)
+                                       if (strchr(optarg, '\\'))
+                                               register_username = pg_strdup(optarg);
+                                       else
+                                               /* Prepend .\ for local accounts */
+                                               register_username = psprintf(".\\%s", optarg);
++#else
++                                      username = pg_strdup(optarg);
++#endif
+                                       break;
+                               case 'w':
+                                       do_wait = true;
+@@ -2535,6 +2530,41 @@ main(int argc, char **argv)
+               exit(1);
+       }
++      /*
++       * Disallow running as root, to forestall any possible security holes.
++       */
++#if !defined(WIN32) && !defined(__CYGWIN__)
++      if (geteuid() == 0)
++      {
++              struct passwd *p;
++              if (!username || !strlen(username)) {
++                      fprintf(stderr,
++                                      _("%s: when run as root, username needs to be provided\n"),
++                                      progname);
++                      exit(1);
++              }
++              p = getpwnam(username);
++              if (!p) {
++                      fprintf(stderr,
++                                      _("%s: invalid username: %s\n"),
++                                      progname, username);
++                      exit(1);
++              }
++              if (!p->pw_uid) {
++                      fprintf(stderr,
++                                      _("%s: user needs to be non-root\n"),
++                                      progname);
++                      exit(1);
++              }
++              if (setgid(p->pw_gid) || setuid(p->pw_uid)) {
++                      fprintf(stderr,
++                                      _("%s: failed to set user id %d: %d (%s)\n"),
++                                      progname, p->pw_uid, errno, strerror(errno));
++                      exit(1);
++              }
++      }
++#endif
++
+       /* Note we put any -D switch into the env var above */
+       pg_config = getenv("PGDATA");
+       if (pg_config)