From cc09e6549f2bd2142b154d7d9802fb7a0abc643e Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Mon, 4 Mar 2024 12:39:22 +0100 Subject: [PATCH] Remove the adminpack contrib extension The adminpack extension was only used to support pgAdmin III, which in turn was declared EOL many years ago. Removing the extension also allows us to remove functions from core as well which were only used to support old version of adminpack. Reviewed-by: Tom Lane Reviewed-by: Nathan Bossart Reviewed-by: Bharath Rupireddy Discussion: https://postgr.es/m/CALj2ACUmL5TraYBUBqDZBi1C+Re8_=SekqGYqYprj_W8wygQ8w@mail.gmail.com --- contrib/Makefile | 1 - contrib/adminpack/.gitignore | 4 - contrib/adminpack/Makefile | 24 - contrib/adminpack/adminpack--1.0--1.1.sql | 6 - contrib/adminpack/adminpack--1.0.sql | 53 -- contrib/adminpack/adminpack--1.1--2.0.sql | 51 -- contrib/adminpack/adminpack--2.0--2.1.sql | 17 - contrib/adminpack/adminpack.c | 591 ---------------------- contrib/adminpack/adminpack.control | 6 - contrib/adminpack/expected/adminpack.out | 172 ------- contrib/adminpack/meson.build | 35 -- contrib/adminpack/sql/adminpack.sql | 76 --- contrib/meson.build | 1 - doc/src/sgml/adminpack.sgml | 159 ------ doc/src/sgml/contrib.sgml | 1 - doc/src/sgml/filelist.sgml | 1 - src/backend/storage/ipc/signalfuncs.c | 29 +- src/backend/utils/adt/genfile.c | 46 -- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_proc.dat | 7 - 20 files changed, 2 insertions(+), 1280 deletions(-) delete mode 100644 contrib/adminpack/.gitignore delete mode 100644 contrib/adminpack/Makefile delete mode 100644 contrib/adminpack/adminpack--1.0--1.1.sql delete mode 100644 contrib/adminpack/adminpack--1.0.sql delete mode 100644 contrib/adminpack/adminpack--1.1--2.0.sql delete mode 100644 contrib/adminpack/adminpack--2.0--2.1.sql delete mode 100644 contrib/adminpack/adminpack.c delete mode 100644 contrib/adminpack/adminpack.control delete mode 100644 contrib/adminpack/expected/adminpack.out delete mode 100644 contrib/adminpack/meson.build delete mode 100644 contrib/adminpack/sql/adminpack.sql delete mode 100644 doc/src/sgml/adminpack.sgml diff --git a/contrib/Makefile b/contrib/Makefile index da4e2316a3..abd780f277 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -5,7 +5,6 @@ top_builddir = .. include $(top_builddir)/src/Makefile.global SUBDIRS = \ - adminpack \ amcheck \ auth_delay \ auto_explain \ diff --git a/contrib/adminpack/.gitignore b/contrib/adminpack/.gitignore deleted file mode 100644 index 5dcb3ff972..0000000000 --- a/contrib/adminpack/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Generated subdirectories -/log/ -/results/ -/tmp_check/ diff --git a/contrib/adminpack/Makefile b/contrib/adminpack/Makefile deleted file mode 100644 index 851504f4ae..0000000000 --- a/contrib/adminpack/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# contrib/adminpack/Makefile - -MODULE_big = adminpack -OBJS = \ - $(WIN32RES) \ - adminpack.o - -EXTENSION = adminpack -DATA = adminpack--1.0.sql adminpack--1.0--1.1.sql adminpack--1.1--2.0.sql\ - adminpack--2.0--2.1.sql -PGFILEDESC = "adminpack - support functions for pgAdmin" - -REGRESS = adminpack - -ifdef USE_PGXS -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) -else -subdir = contrib/adminpack -top_builddir = ../.. -include $(top_builddir)/src/Makefile.global -include $(top_srcdir)/contrib/contrib-global.mk -endif diff --git a/contrib/adminpack/adminpack--1.0--1.1.sql b/contrib/adminpack/adminpack--1.0--1.1.sql deleted file mode 100644 index bb581653e0..0000000000 --- a/contrib/adminpack/adminpack--1.0--1.1.sql +++ /dev/null @@ -1,6 +0,0 @@ -/* contrib/adminpack/adminpack--1.0--1.1.sql */ - --- complain if script is sourced in psql, rather than via ALTER EXTENSION -\echo Use "ALTER EXTENSION adminpack UPDATE TO '1.1'" to load this file. \quit - -REVOKE EXECUTE ON FUNCTION pg_catalog.pg_logfile_rotate() FROM PUBLIC; diff --git a/contrib/adminpack/adminpack--1.0.sql b/contrib/adminpack/adminpack--1.0.sql deleted file mode 100644 index f76f5c3cdf..0000000000 --- a/contrib/adminpack/adminpack--1.0.sql +++ /dev/null @@ -1,53 +0,0 @@ -/* contrib/adminpack/adminpack--1.0.sql */ - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION adminpack" to load this file. \quit - -/* *********************************************** - * Administrative functions for PostgreSQL - * *********************************************** */ - -/* generic file access functions */ - -CREATE FUNCTION pg_catalog.pg_file_write(text, text, bool) -RETURNS bigint -AS 'MODULE_PATHNAME', 'pg_file_write' -LANGUAGE C VOLATILE STRICT; - -CREATE FUNCTION pg_catalog.pg_file_rename(text, text, text) -RETURNS bool -AS 'MODULE_PATHNAME', 'pg_file_rename' -LANGUAGE C VOLATILE; - -CREATE FUNCTION pg_catalog.pg_file_rename(text, text) -RETURNS bool -AS 'SELECT pg_catalog.pg_file_rename($1, $2, NULL::pg_catalog.text);' -LANGUAGE SQL VOLATILE STRICT; - -CREATE FUNCTION pg_catalog.pg_file_unlink(text) -RETURNS bool -AS 'MODULE_PATHNAME', 'pg_file_unlink' -LANGUAGE C VOLATILE STRICT; - -CREATE FUNCTION pg_catalog.pg_logdir_ls() -RETURNS setof record -AS 'MODULE_PATHNAME', 'pg_logdir_ls' -LANGUAGE C VOLATILE STRICT; - - -/* Renaming of existing backend functions for pgAdmin compatibility */ - -CREATE FUNCTION pg_catalog.pg_file_read(text, bigint, bigint) -RETURNS text -AS 'pg_read_file' -LANGUAGE INTERNAL VOLATILE STRICT; - -CREATE FUNCTION pg_catalog.pg_file_length(text) -RETURNS bigint -AS 'SELECT size FROM pg_catalog.pg_stat_file($1)' -LANGUAGE SQL VOLATILE STRICT; - -CREATE FUNCTION pg_catalog.pg_logfile_rotate() -RETURNS int4 -AS 'pg_rotate_logfile' -LANGUAGE INTERNAL VOLATILE STRICT; diff --git a/contrib/adminpack/adminpack--1.1--2.0.sql b/contrib/adminpack/adminpack--1.1--2.0.sql deleted file mode 100644 index ceaeafa378..0000000000 --- a/contrib/adminpack/adminpack--1.1--2.0.sql +++ /dev/null @@ -1,51 +0,0 @@ -/* contrib/adminpack/adminpack--1.1--2.0.sql */ - --- complain if script is sourced in psql, rather than via ALTER EXTENSION -\echo Use "ALTER EXTENSION adminpack UPDATE TO '2.0'" to load this file. \quit - -/* *********************************************** - * Administrative functions for PostgreSQL - * *********************************************** */ - -/* generic file access functions */ - -CREATE OR REPLACE FUNCTION pg_catalog.pg_file_write(text, text, bool) -RETURNS bigint -AS 'MODULE_PATHNAME', 'pg_file_write_v1_1' -LANGUAGE C VOLATILE STRICT; - -REVOKE EXECUTE ON FUNCTION pg_catalog.pg_file_write(text, text, bool) FROM PUBLIC; - -CREATE OR REPLACE FUNCTION pg_catalog.pg_file_rename(text, text, text) -RETURNS bool -AS 'MODULE_PATHNAME', 'pg_file_rename_v1_1' -LANGUAGE C VOLATILE; - -REVOKE EXECUTE ON FUNCTION pg_catalog.pg_file_rename(text, text, text) FROM PUBLIC; - -CREATE OR REPLACE FUNCTION pg_catalog.pg_file_rename(text, text) -RETURNS bool -AS 'SELECT pg_catalog.pg_file_rename($1, $2, NULL::pg_catalog.text);' -LANGUAGE SQL VOLATILE STRICT; - -CREATE OR REPLACE FUNCTION pg_catalog.pg_file_unlink(text) -RETURNS bool -AS 'MODULE_PATHNAME', 'pg_file_unlink_v1_1' -LANGUAGE C VOLATILE STRICT; - -REVOKE EXECUTE ON FUNCTION pg_catalog.pg_file_unlink(text) FROM PUBLIC; - -CREATE OR REPLACE FUNCTION pg_catalog.pg_logdir_ls() -RETURNS setof record -AS 'MODULE_PATHNAME', 'pg_logdir_ls_v1_1' -LANGUAGE C VOLATILE STRICT; - -REVOKE EXECUTE ON FUNCTION pg_catalog.pg_logdir_ls() FROM PUBLIC; - -/* These functions are now in the backend and callers should update to use those */ - -DROP FUNCTION pg_file_read(text, bigint, bigint); - -DROP FUNCTION pg_file_length(text); - -DROP FUNCTION pg_logfile_rotate(); diff --git a/contrib/adminpack/adminpack--2.0--2.1.sql b/contrib/adminpack/adminpack--2.0--2.1.sql deleted file mode 100644 index 1c6712e816..0000000000 --- a/contrib/adminpack/adminpack--2.0--2.1.sql +++ /dev/null @@ -1,17 +0,0 @@ -/* contrib/adminpack/adminpack--2.0--2.1.sql */ - --- complain if script is sourced in psql, rather than via ALTER EXTENSION -\echo Use "ALTER EXTENSION adminpack UPDATE TO '2.1'" to load this file. \quit - -/* *********************************************** - * Administrative functions for PostgreSQL - * *********************************************** */ - -/* generic file access functions */ - -CREATE OR REPLACE FUNCTION pg_catalog.pg_file_sync(text) -RETURNS void -AS 'MODULE_PATHNAME', 'pg_file_sync' -LANGUAGE C VOLATILE STRICT; - -REVOKE EXECUTE ON FUNCTION pg_catalog.pg_file_sync(text) FROM PUBLIC; diff --git a/contrib/adminpack/adminpack.c b/contrib/adminpack/adminpack.c deleted file mode 100644 index 1d8b2bbe25..0000000000 --- a/contrib/adminpack/adminpack.c +++ /dev/null @@ -1,591 +0,0 @@ -/*------------------------------------------------------------------------- - * - * adminpack.c - * - * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group - * - * Author: Andreas Pflug - * - * IDENTIFICATION - * contrib/adminpack/adminpack.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include -#include -#include - -#include "catalog/pg_authid.h" -#include "catalog/pg_type.h" -#include "funcapi.h" -#include "miscadmin.h" -#include "postmaster/syslogger.h" -#include "storage/fd.h" -#include "utils/acl.h" -#include "utils/builtins.h" -#include "utils/datetime.h" - - -#ifdef WIN32 - -#ifdef rename -#undef rename -#endif - -#ifdef unlink -#undef unlink -#endif -#endif - -PG_MODULE_MAGIC; - -PG_FUNCTION_INFO_V1(pg_file_write); -PG_FUNCTION_INFO_V1(pg_file_write_v1_1); -PG_FUNCTION_INFO_V1(pg_file_sync); -PG_FUNCTION_INFO_V1(pg_file_rename); -PG_FUNCTION_INFO_V1(pg_file_rename_v1_1); -PG_FUNCTION_INFO_V1(pg_file_unlink); -PG_FUNCTION_INFO_V1(pg_file_unlink_v1_1); -PG_FUNCTION_INFO_V1(pg_logdir_ls); -PG_FUNCTION_INFO_V1(pg_logdir_ls_v1_1); - -static int64 pg_file_write_internal(text *file, text *data, bool replace); -static bool pg_file_rename_internal(text *file1, text *file2, text *file3); -static Datum pg_logdir_ls_internal(FunctionCallInfo fcinfo); - - -/*----------------------- - * some helper functions - */ - -/* - * Convert a "text" filename argument to C string, and check it's allowable. - * - * Filename may be absolute or relative to the DataDir, but we only allow - * absolute paths that match DataDir. - */ -static char * -convert_and_check_filename(text *arg) -{ - char *filename = text_to_cstring(arg); - - canonicalize_path(filename); /* filename can change length here */ - - /* - * Members of the 'pg_write_server_files' role are allowed to access any - * files on the server as the PG user, so no need to do any further checks - * here. - */ - if (has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES)) - return filename; - - /* - * User isn't a member of the pg_write_server_files role, so check if it's - * allowable - */ - if (is_absolute_path(filename)) - { - /* Allow absolute paths if within DataDir */ - if (!path_is_prefix_of_path(DataDir, filename)) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("absolute path not allowed"))); - } - else if (!path_is_relative_and_below_cwd(filename)) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("path must be in or below the data directory"))); - - return filename; -} - - -/* - * check for superuser, bark if not. - */ -static void -requireSuperuser(void) -{ - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("only superuser may access generic file functions"))); -} - - - -/* ------------------------------------ - * pg_file_write - old version - * - * The superuser() check here must be kept as the library might be upgraded - * without the extension being upgraded, meaning that in pre-1.1 installations - * these functions could be called by any user. - */ -Datum -pg_file_write(PG_FUNCTION_ARGS) -{ - text *file = PG_GETARG_TEXT_PP(0); - text *data = PG_GETARG_TEXT_PP(1); - bool replace = PG_GETARG_BOOL(2); - int64 count = 0; - - requireSuperuser(); - - count = pg_file_write_internal(file, data, replace); - - PG_RETURN_INT64(count); -} - -/* ------------------------------------ - * pg_file_write_v1_1 - Version 1.1 - * - * As of adminpack version 1.1, we no longer need to check if the user - * is a superuser because we REVOKE EXECUTE on the function from PUBLIC. - * Users can then grant access to it based on their policies. - * - * Otherwise identical to pg_file_write (above). - */ -Datum -pg_file_write_v1_1(PG_FUNCTION_ARGS) -{ - text *file = PG_GETARG_TEXT_PP(0); - text *data = PG_GETARG_TEXT_PP(1); - bool replace = PG_GETARG_BOOL(2); - int64 count = 0; - - count = pg_file_write_internal(file, data, replace); - - PG_RETURN_INT64(count); -} - -/* ------------------------------------ - * pg_file_write_internal - Workhorse for pg_file_write functions. - * - * This handles the actual work for pg_file_write. - */ -static int64 -pg_file_write_internal(text *file, text *data, bool replace) -{ - FILE *f; - char *filename; - int64 count = 0; - - filename = convert_and_check_filename(file); - - if (!replace) - { - struct stat fst; - - if (stat(filename, &fst) >= 0) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_FILE), - errmsg("file \"%s\" exists", filename))); - - f = AllocateFile(filename, "wb"); - } - else - f = AllocateFile(filename, "ab"); - - if (!f) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not open file \"%s\" for writing: %m", - filename))); - - count = fwrite(VARDATA_ANY(data), 1, VARSIZE_ANY_EXHDR(data), f); - if (count != VARSIZE_ANY_EXHDR(data) || FreeFile(f)) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not write file \"%s\": %m", filename))); - - return (count); -} - -/* ------------------------------------ - * pg_file_sync - * - * We REVOKE EXECUTE on the function from PUBLIC. - * Users can then grant access to it based on their policies. - */ -Datum -pg_file_sync(PG_FUNCTION_ARGS) -{ - char *filename; - struct stat fst; - - filename = convert_and_check_filename(PG_GETARG_TEXT_PP(0)); - - if (stat(filename, &fst) < 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not stat file \"%s\": %m", filename))); - - fsync_fname_ext(filename, S_ISDIR(fst.st_mode), false, ERROR); - - PG_RETURN_VOID(); -} - -/* ------------------------------------ - * pg_file_rename - old version - * - * The superuser() check here must be kept as the library might be upgraded - * without the extension being upgraded, meaning that in pre-1.1 installations - * these functions could be called by any user. - */ -Datum -pg_file_rename(PG_FUNCTION_ARGS) -{ - text *file1; - text *file2; - text *file3; - bool result; - - requireSuperuser(); - - if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) - PG_RETURN_NULL(); - - file1 = PG_GETARG_TEXT_PP(0); - file2 = PG_GETARG_TEXT_PP(1); - - if (PG_ARGISNULL(2)) - file3 = NULL; - else - file3 = PG_GETARG_TEXT_PP(2); - - result = pg_file_rename_internal(file1, file2, file3); - - PG_RETURN_BOOL(result); -} - -/* ------------------------------------ - * pg_file_rename_v1_1 - Version 1.1 - * - * As of adminpack version 1.1, we no longer need to check if the user - * is a superuser because we REVOKE EXECUTE on the function from PUBLIC. - * Users can then grant access to it based on their policies. - * - * Otherwise identical to pg_file_write (above). - */ -Datum -pg_file_rename_v1_1(PG_FUNCTION_ARGS) -{ - text *file1; - text *file2; - text *file3; - bool result; - - if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) - PG_RETURN_NULL(); - - file1 = PG_GETARG_TEXT_PP(0); - file2 = PG_GETARG_TEXT_PP(1); - - if (PG_ARGISNULL(2)) - file3 = NULL; - else - file3 = PG_GETARG_TEXT_PP(2); - - result = pg_file_rename_internal(file1, file2, file3); - - PG_RETURN_BOOL(result); -} - -/* ------------------------------------ - * pg_file_rename_internal - Workhorse for pg_file_rename functions. - * - * This handles the actual work for pg_file_rename. - */ -static bool -pg_file_rename_internal(text *file1, text *file2, text *file3) -{ - char *fn1, - *fn2, - *fn3; - int rc; - - fn1 = convert_and_check_filename(file1); - fn2 = convert_and_check_filename(file2); - - if (file3 == NULL) - fn3 = NULL; - else - fn3 = convert_and_check_filename(file3); - - if (access(fn1, W_OK) < 0) - { - ereport(WARNING, - (errcode_for_file_access(), - errmsg("file \"%s\" is not accessible: %m", fn1))); - - return false; - } - - if (fn3 && access(fn2, W_OK) < 0) - { - ereport(WARNING, - (errcode_for_file_access(), - errmsg("file \"%s\" is not accessible: %m", fn2))); - - return false; - } - - rc = access(fn3 ? fn3 : fn2, W_OK); - if (rc >= 0 || errno != ENOENT) - { - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_FILE), - errmsg("cannot rename to target file \"%s\"", - fn3 ? fn3 : fn2))); - } - - if (fn3) - { - if (rename(fn2, fn3) != 0) - { - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not rename \"%s\" to \"%s\": %m", - fn2, fn3))); - } - if (rename(fn1, fn2) != 0) - { - ereport(WARNING, - (errcode_for_file_access(), - errmsg("could not rename \"%s\" to \"%s\": %m", - fn1, fn2))); - - if (rename(fn3, fn2) != 0) - { - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not rename \"%s\" back to \"%s\": %m", - fn3, fn2))); - } - else - { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FILE), - errmsg("renaming \"%s\" to \"%s\" was reverted", - fn2, fn3))); - } - } - } - else if (rename(fn1, fn2) != 0) - { - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not rename \"%s\" to \"%s\": %m", fn1, fn2))); - } - - return true; -} - - -/* ------------------------------------ - * pg_file_unlink - old version - * - * The superuser() check here must be kept as the library might be upgraded - * without the extension being upgraded, meaning that in pre-1.1 installations - * these functions could be called by any user. - */ -Datum -pg_file_unlink(PG_FUNCTION_ARGS) -{ - char *filename; - - requireSuperuser(); - - filename = convert_and_check_filename(PG_GETARG_TEXT_PP(0)); - - if (access(filename, W_OK) < 0) - { - if (errno == ENOENT) - PG_RETURN_BOOL(false); - else - ereport(ERROR, - (errcode_for_file_access(), - errmsg("file \"%s\" is not accessible: %m", filename))); - } - - if (unlink(filename) < 0) - { - ereport(WARNING, - (errcode_for_file_access(), - errmsg("could not unlink file \"%s\": %m", filename))); - - PG_RETURN_BOOL(false); - } - PG_RETURN_BOOL(true); -} - - -/* ------------------------------------ - * pg_file_unlink_v1_1 - Version 1.1 - * - * As of adminpack version 1.1, we no longer need to check if the user - * is a superuser because we REVOKE EXECUTE on the function from PUBLIC. - * Users can then grant access to it based on their policies. - * - * Otherwise identical to pg_file_unlink (above). - */ -Datum -pg_file_unlink_v1_1(PG_FUNCTION_ARGS) -{ - char *filename; - - filename = convert_and_check_filename(PG_GETARG_TEXT_PP(0)); - - if (access(filename, W_OK) < 0) - { - if (errno == ENOENT) - PG_RETURN_BOOL(false); - else - ereport(ERROR, - (errcode_for_file_access(), - errmsg("file \"%s\" is not accessible: %m", filename))); - } - - if (unlink(filename) < 0) - { - ereport(WARNING, - (errcode_for_file_access(), - errmsg("could not unlink file \"%s\": %m", filename))); - - PG_RETURN_BOOL(false); - } - PG_RETURN_BOOL(true); -} - -/* ------------------------------------ - * pg_logdir_ls - Old version - * - * The superuser() check here must be kept as the library might be upgraded - * without the extension being upgraded, meaning that in pre-1.1 installations - * these functions could be called by any user. - */ -Datum -pg_logdir_ls(PG_FUNCTION_ARGS) -{ - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("only superuser can list the log directory"))); - - return (pg_logdir_ls_internal(fcinfo)); -} - -/* ------------------------------------ - * pg_logdir_ls_v1_1 - Version 1.1 - * - * As of adminpack version 1.1, we no longer need to check if the user - * is a superuser because we REVOKE EXECUTE on the function from PUBLIC. - * Users can then grant access to it based on their policies. - * - * Otherwise identical to pg_logdir_ls (above). - */ -Datum -pg_logdir_ls_v1_1(PG_FUNCTION_ARGS) -{ - return (pg_logdir_ls_internal(fcinfo)); -} - -static Datum -pg_logdir_ls_internal(FunctionCallInfo fcinfo) -{ - ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; - bool randomAccess; - TupleDesc tupdesc; - Tuplestorestate *tupstore; - AttInMetadata *attinmeta; - DIR *dirdesc; - struct dirent *de; - MemoryContext oldcontext; - - if (strcmp(Log_filename, "postgresql-%Y-%m-%d_%H%M%S.log") != 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'"))); - - /* check to see if caller supports us returning a tuplestore */ - if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("set-valued function called in context that cannot accept a set"))); - if (!(rsinfo->allowedModes & SFRM_Materialize)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("materialize mode required, but it is not allowed in this context"))); - - /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */ - oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory); - - tupdesc = CreateTemplateTupleDesc(2); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime", - TIMESTAMPOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename", - TEXTOID, -1, 0); - - randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0; - tupstore = tuplestore_begin_heap(randomAccess, false, work_mem); - rsinfo->returnMode = SFRM_Materialize; - rsinfo->setResult = tupstore; - rsinfo->setDesc = tupdesc; - - MemoryContextSwitchTo(oldcontext); - - attinmeta = TupleDescGetAttInMetadata(tupdesc); - - dirdesc = AllocateDir(Log_directory); - while ((de = ReadDir(dirdesc, Log_directory)) != NULL) - { - char *values[2]; - HeapTuple tuple; - char timestampbuf[32]; - char *field[MAXDATEFIELDS]; - char lowstr[MAXDATELEN + 1]; - int dtype; - int nf, - ftype[MAXDATEFIELDS]; - fsec_t fsec; - int tz = 0; - struct pg_tm date; - DateTimeErrorExtra extra; - - /* - * Default format: postgresql-YYYY-MM-DD_HHMMSS.log - */ - if (strlen(de->d_name) != 32 - || strncmp(de->d_name, "postgresql-", 11) != 0 - || de->d_name[21] != '_' - || strcmp(de->d_name + 28, ".log") != 0) - continue; - - /* extract timestamp portion of filename */ - strcpy(timestampbuf, de->d_name + 11); - timestampbuf[17] = '\0'; - - /* parse and decode expected timestamp to verify it's OK format */ - if (ParseDateTime(timestampbuf, lowstr, MAXDATELEN, field, ftype, MAXDATEFIELDS, &nf)) - continue; - - if (DecodeDateTime(field, ftype, nf, - &dtype, &date, &fsec, &tz, &extra)) - continue; - - /* Seems the timestamp is OK; prepare and return tuple */ - - values[0] = timestampbuf; - values[1] = psprintf("%s/%s", Log_directory, de->d_name); - - tuple = BuildTupleFromCStrings(attinmeta, values); - - tuplestore_puttuple(tupstore, tuple); - } - - FreeDir(dirdesc); - return (Datum) 0; -} diff --git a/contrib/adminpack/adminpack.control b/contrib/adminpack/adminpack.control deleted file mode 100644 index ae35d22156..0000000000 --- a/contrib/adminpack/adminpack.control +++ /dev/null @@ -1,6 +0,0 @@ -# adminpack extension -comment = 'administrative functions for PostgreSQL' -default_version = '2.1' -module_pathname = '$libdir/adminpack' -relocatable = false -schema = pg_catalog diff --git a/contrib/adminpack/expected/adminpack.out b/contrib/adminpack/expected/adminpack.out deleted file mode 100644 index f419a5ea1d..0000000000 --- a/contrib/adminpack/expected/adminpack.out +++ /dev/null @@ -1,172 +0,0 @@ -CREATE EXTENSION adminpack; --- create new file -SELECT pg_file_write('test_file1', 'test1', false); - pg_file_write ---------------- - 5 -(1 row) - -SELECT pg_read_file('test_file1'); - pg_read_file --------------- - test1 -(1 row) - --- append -SELECT pg_file_write('test_file1', 'test1', true); - pg_file_write ---------------- - 5 -(1 row) - -SELECT pg_read_file('test_file1'); - pg_read_file --------------- - test1test1 -(1 row) - --- error, already exists -SELECT pg_file_write('test_file1', 'test1', false); -ERROR: file "test_file1" exists -SELECT pg_read_file('test_file1'); - pg_read_file --------------- - test1test1 -(1 row) - --- disallowed file paths for non-superusers and users who are --- not members of pg_write_server_files -CREATE ROLE regress_adminpack_user1; -GRANT pg_read_all_settings TO regress_adminpack_user1; -GRANT EXECUTE ON FUNCTION pg_file_write(text,text,bool) TO regress_adminpack_user1; -SET ROLE regress_adminpack_user1; -SELECT pg_file_write('../test_file0', 'test0', false); -ERROR: path must be in or below the data directory -SELECT pg_file_write('/tmp/test_file0', 'test0', false); -ERROR: absolute path not allowed -SELECT pg_file_write(current_setting('data_directory') || '/test_file4', 'test4', false); - pg_file_write ---------------- - 5 -(1 row) - -SELECT pg_file_write(current_setting('data_directory') || '/../test_file4', 'test4', false); -ERROR: absolute path not allowed -RESET ROLE; -REVOKE EXECUTE ON FUNCTION pg_file_write(text,text,bool) FROM regress_adminpack_user1; -REVOKE pg_read_all_settings FROM regress_adminpack_user1; -DROP ROLE regress_adminpack_user1; --- sync -SELECT pg_file_sync('test_file1'); -- sync file - pg_file_sync --------------- - -(1 row) - -SELECT pg_file_sync('pg_stat'); -- sync directory - pg_file_sync --------------- - -(1 row) - -SELECT pg_file_sync('test_file2'); -- not there -ERROR: could not stat file "test_file2": No such file or directory --- rename file -SELECT pg_file_rename('test_file1', 'test_file2'); - pg_file_rename ----------------- - t -(1 row) - -SELECT pg_read_file('test_file1'); -- not there -ERROR: could not open file "test_file1" for reading: No such file or directory -SELECT pg_read_file('test_file2'); - pg_read_file --------------- - test1test1 -(1 row) - --- error -SELECT pg_file_rename('test_file1', 'test_file2'); -WARNING: file "test_file1" is not accessible: No such file or directory - pg_file_rename ----------------- - f -(1 row) - --- rename file and archive -SELECT pg_file_write('test_file3', 'test3', false); - pg_file_write ---------------- - 5 -(1 row) - -SELECT pg_file_rename('test_file2', 'test_file3', 'test_file3_archive'); - pg_file_rename ----------------- - t -(1 row) - -SELECT pg_read_file('test_file2'); -- not there -ERROR: could not open file "test_file2" for reading: No such file or directory -SELECT pg_read_file('test_file3'); - pg_read_file --------------- - test1test1 -(1 row) - -SELECT pg_read_file('test_file3_archive'); - pg_read_file --------------- - test3 -(1 row) - --- unlink -SELECT pg_file_unlink('test_file1'); -- does not exist - pg_file_unlink ----------------- - f -(1 row) - -SELECT pg_file_unlink('test_file2'); -- does not exist - pg_file_unlink ----------------- - f -(1 row) - -SELECT pg_file_unlink('test_file3'); - pg_file_unlink ----------------- - t -(1 row) - -SELECT pg_file_unlink('test_file3_archive'); - pg_file_unlink ----------------- - t -(1 row) - -SELECT pg_file_unlink('test_file4'); - pg_file_unlink ----------------- - t -(1 row) - --- superuser checks -CREATE USER regress_adminpack_user1; -SET ROLE regress_adminpack_user1; -SELECT pg_file_write('test_file0', 'test0', false); -ERROR: permission denied for function pg_file_write -SELECT pg_file_sync('test_file0'); -ERROR: permission denied for function pg_file_sync -SELECT pg_file_rename('test_file0', 'test_file0'); -ERROR: permission denied for function pg_file_rename -CONTEXT: SQL function "pg_file_rename" statement 1 -SELECT pg_file_unlink('test_file0'); -ERROR: permission denied for function pg_file_unlink -SELECT pg_logdir_ls(); -ERROR: permission denied for function pg_logdir_ls -RESET ROLE; -DROP USER regress_adminpack_user1; --- no further tests for pg_logdir_ls() because it depends on the --- server's logging setup diff --git a/contrib/adminpack/meson.build b/contrib/adminpack/meson.build deleted file mode 100644 index e5bcc9d99b..0000000000 --- a/contrib/adminpack/meson.build +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group - -adminpack_sources = files( - 'adminpack.c', -) - -if host_system == 'windows' - adminpack_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ - '--NAME', 'adminpack', - '--FILEDESC', 'adminpack - support functions for pgAdmin',]) -endif - -adminpack = shared_module('adminpack', - adminpack_sources, - kwargs: contrib_mod_args, -) -contrib_targets += adminpack - -install_data( - 'adminpack.control', - 'adminpack--1.0.sql', - 'adminpack--1.0--1.1.sql', - 'adminpack--1.1--2.0.sql', - 'adminpack--2.0--2.1.sql', - kwargs: contrib_data_args, -) - -tests += { - 'name': 'adminpack', - 'sd': meson.current_source_dir(), - 'bd': meson.current_build_dir(), - 'regress': { - 'sql': ['adminpack'], - }, -} diff --git a/contrib/adminpack/sql/adminpack.sql b/contrib/adminpack/sql/adminpack.sql deleted file mode 100644 index 5776c9af0d..0000000000 --- a/contrib/adminpack/sql/adminpack.sql +++ /dev/null @@ -1,76 +0,0 @@ -CREATE EXTENSION adminpack; - --- create new file -SELECT pg_file_write('test_file1', 'test1', false); -SELECT pg_read_file('test_file1'); - --- append -SELECT pg_file_write('test_file1', 'test1', true); -SELECT pg_read_file('test_file1'); - --- error, already exists -SELECT pg_file_write('test_file1', 'test1', false); -SELECT pg_read_file('test_file1'); - --- disallowed file paths for non-superusers and users who are --- not members of pg_write_server_files -CREATE ROLE regress_adminpack_user1; - -GRANT pg_read_all_settings TO regress_adminpack_user1; -GRANT EXECUTE ON FUNCTION pg_file_write(text,text,bool) TO regress_adminpack_user1; - -SET ROLE regress_adminpack_user1; -SELECT pg_file_write('../test_file0', 'test0', false); -SELECT pg_file_write('/tmp/test_file0', 'test0', false); -SELECT pg_file_write(current_setting('data_directory') || '/test_file4', 'test4', false); -SELECT pg_file_write(current_setting('data_directory') || '/../test_file4', 'test4', false); -RESET ROLE; -REVOKE EXECUTE ON FUNCTION pg_file_write(text,text,bool) FROM regress_adminpack_user1; -REVOKE pg_read_all_settings FROM regress_adminpack_user1; -DROP ROLE regress_adminpack_user1; - --- sync -SELECT pg_file_sync('test_file1'); -- sync file -SELECT pg_file_sync('pg_stat'); -- sync directory -SELECT pg_file_sync('test_file2'); -- not there - --- rename file -SELECT pg_file_rename('test_file1', 'test_file2'); -SELECT pg_read_file('test_file1'); -- not there -SELECT pg_read_file('test_file2'); - --- error -SELECT pg_file_rename('test_file1', 'test_file2'); - --- rename file and archive -SELECT pg_file_write('test_file3', 'test3', false); -SELECT pg_file_rename('test_file2', 'test_file3', 'test_file3_archive'); -SELECT pg_read_file('test_file2'); -- not there -SELECT pg_read_file('test_file3'); -SELECT pg_read_file('test_file3_archive'); - - --- unlink -SELECT pg_file_unlink('test_file1'); -- does not exist -SELECT pg_file_unlink('test_file2'); -- does not exist -SELECT pg_file_unlink('test_file3'); -SELECT pg_file_unlink('test_file3_archive'); -SELECT pg_file_unlink('test_file4'); - - --- superuser checks -CREATE USER regress_adminpack_user1; -SET ROLE regress_adminpack_user1; - -SELECT pg_file_write('test_file0', 'test0', false); -SELECT pg_file_sync('test_file0'); -SELECT pg_file_rename('test_file0', 'test_file0'); -SELECT pg_file_unlink('test_file0'); -SELECT pg_logdir_ls(); - -RESET ROLE; -DROP USER regress_adminpack_user1; - - --- no further tests for pg_logdir_ls() because it depends on the --- server's logging setup diff --git a/contrib/meson.build b/contrib/meson.build index c12dc906ca..14a8906865 100644 --- a/contrib/meson.build +++ b/contrib/meson.build @@ -12,7 +12,6 @@ contrib_doc_args = { 'install_dir': contrib_doc_dir, } -subdir('adminpack') subdir('amcheck') subdir('auth_delay') subdir('auto_explain') diff --git a/doc/src/sgml/adminpack.sgml b/doc/src/sgml/adminpack.sgml deleted file mode 100644 index 04f3b52379..0000000000 --- a/doc/src/sgml/adminpack.sgml +++ /dev/null @@ -1,159 +0,0 @@ - - - - adminpack — pgAdmin support toolpack - - - adminpack - - - - adminpack provides a number of support functions which - pgAdmin and other administration and management tools can - use to provide additional functionality, such as remote management - of server log files. - Use of all these functions is only allowed to database superusers by default, but may be - allowed to other users by using the GRANT command. - - - - The functions shown in provide - write access to files on the machine hosting the server. (See also the - functions in , which - provide read-only access.) - Only files within the database cluster directory can be accessed, unless the - user is a superuser or given privileges of one of the - pg_read_server_files or - pg_write_server_files roles, as appropriate for the - function, but either a relative or absolute path is allowable. - - - - <filename>adminpack</filename> Functions - - - - - Function - - - Description - - - - - - - - pg_catalog.pg_file_write ( filename text, data text, append boolean ) - bigint - - - Writes, or appends to, a text file. - - - - - - pg_catalog.pg_file_sync ( filename text ) - void - - - Flushes a file or directory to disk. - - - - - - pg_catalog.pg_file_rename ( oldname text, newname text , archivename text ) - boolean - - - Renames a file. - - - - - - pg_catalog.pg_file_unlink ( filename text ) - boolean - - - Removes a file. - - - - - - pg_catalog.pg_logdir_ls () - setof record - - - Lists the log files in the log_directory directory. - - - - -
- - - pg_file_write - - - pg_file_write writes the specified data into - the file named by filename. If append is - false, the file must not already exist. If append is true, - the file can already exist, and will be appended to if so. - Returns the number of bytes written. - - - - pg_file_sync - - - pg_file_sync fsyncs the specified file or directory - named by filename. An error is thrown - on failure (e.g., the specified file is not present). Note that - has no effect on this function, - and therefore a PANIC-level error will not be raised even on failure to - flush database files. - - - - pg_file_rename - - - pg_file_rename renames a file. If archivename - is omitted or NULL, it simply renames oldname - to newname (which must not already exist). - If archivename is provided, it first - renames newname to archivename (which must - not already exist), and then renames oldname - to newname. In event of failure of the second rename step, - it will try to rename archivename back - to newname before reporting the error. - Returns true on success, false if the source file(s) are not present or - not writable; other cases throw errors. - - - - pg_file_unlink - - - pg_file_unlink removes the specified file. - Returns true on success, false if the specified file is not present - or the unlink() call fails; other cases throw errors. - - - - pg_logdir_ls - - - pg_logdir_ls returns the start timestamps and path - names of all the log files in the - directory. The parameter must have its - default setting (postgresql-%Y-%m-%d_%H%M%S.log) to use this - function. - - -
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index ab7e38b52a..44639a8dca 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -127,7 +127,6 @@ CREATE EXTENSION extension_name; component for details. - &adminpack; &amcheck; &auth-delay; &auto-explain; diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index bb4926b887..e0dca81cb2 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -113,7 +113,6 @@ - diff --git a/src/backend/storage/ipc/signalfuncs.c b/src/backend/storage/ipc/signalfuncs.c index 792e80ff90..88e9bf8125 100644 --- a/src/backend/storage/ipc/signalfuncs.c +++ b/src/backend/storage/ipc/signalfuncs.c @@ -270,33 +270,6 @@ pg_reload_conf(PG_FUNCTION_ARGS) } -/* - * Rotate log file - * - * This function is kept to support adminpack 1.0. - */ -Datum -pg_rotate_logfile(PG_FUNCTION_ARGS) -{ - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to rotate log files with adminpack 1.0"), - /* translator: %s is a SQL function name */ - errhint("Consider using %s, which is part of core, instead.", - "pg_logfile_rotate()"))); - - if (!Logging_collector) - { - ereport(WARNING, - (errmsg("rotation not possible because log collection not active"))); - PG_RETURN_BOOL(false); - } - - SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE); - PG_RETURN_BOOL(true); -} - /* * Rotate log file * @@ -304,7 +277,7 @@ pg_rotate_logfile(PG_FUNCTION_ARGS) * GRANT system. */ Datum -pg_rotate_logfile_v2(PG_FUNCTION_ARGS) +pg_rotate_logfile(PG_FUNCTION_ARGS) { if (!Logging_collector) { diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c index ca19903ac6..0d82557417 100644 --- a/src/backend/utils/adt/genfile.c +++ b/src/backend/utils/adt/genfile.c @@ -227,52 +227,6 @@ read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read, return NULL; } -/* - * Read a section of a file, returning it as text - * - * This function is kept to support adminpack 1.0. - */ -Datum -pg_read_file(PG_FUNCTION_ARGS) -{ - text *filename_t = PG_GETARG_TEXT_PP(0); - int64 seek_offset = 0; - int64 bytes_to_read = -1; - bool missing_ok = false; - char *filename; - text *result; - - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to read files with adminpack 1.0"), - /* translator: %s is a SQL function name */ - errhint("Consider using %s, which is part of core, instead.", - "pg_read_file()"))); - - /* handle optional arguments */ - if (PG_NARGS() >= 3) - { - seek_offset = PG_GETARG_INT64(1); - bytes_to_read = PG_GETARG_INT64(2); - - if (bytes_to_read < 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("requested length cannot be negative"))); - } - if (PG_NARGS() >= 4) - missing_ok = PG_GETARG_BOOL(3); - - filename = convert_and_check_filename(filename_t); - - result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok); - if (result) - PG_RETURN_TEXT_P(result); - else - PG_RETURN_NULL(); -} - /* * Read a section of a file, returning it as text * diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 7faa6a9bb7..208ffbe2a3 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202402291 +#define CATALOG_VERSION_NO 202403041 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 9c120fc2b7..291ed876fc 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6545,9 +6545,6 @@ proargtypes => '', prosrc => 'pg_reload_conf' }, { oid => '2622', descr => 'rotate log file', proname => 'pg_rotate_logfile', provolatile => 'v', prorettype => 'bool', - proargtypes => '', prosrc => 'pg_rotate_logfile_v2' }, -{ oid => '4099', descr => 'rotate log file - old version for adminpack 1.0', - proname => 'pg_rotate_logfile_old', provolatile => 'v', prorettype => 'bool', proargtypes => '', prosrc => 'pg_rotate_logfile' }, { oid => '3800', descr => 'current logging collector file location', proname => 'pg_current_logfile', proisstrict => 'f', provolatile => 'v', @@ -6578,10 +6575,6 @@ proname => 'pg_read_file', provolatile => 'v', prorettype => 'text', proargtypes => 'text int8 int8 bool', prosrc => 'pg_read_file_off_len_missing' }, -{ oid => '4100', - descr => 'read text from a file - old version for adminpack 1.0', - proname => 'pg_read_file_old', provolatile => 'v', prorettype => 'text', - proargtypes => 'text int8 int8', prosrc => 'pg_read_file' }, { oid => '3826', descr => 'read text from a file', proname => 'pg_read_file', provolatile => 'v', prorettype => 'text', proargtypes => 'text', prosrc => 'pg_read_file_all' },