Index: doc/src/sgml/func.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v retrieving revision 1.272 diff -c -r1.272 func.sgml *** doc/src/sgml/func.sgml 26 Jul 2005 16:38:25 -0000 1.272 --- doc/src/sgml/func.sgml 30 Jul 2005 13:33:30 -0000 *************** *** 9051,9056 **** --- 9051,9059 ---- pg_cancel_backend + + pg_reload_conf + signal *************** *** 9058,9064 **** ! The function shown in sends control signals to other server processes. Use of this function is restricted to superusers. --- 9061,9067 ---- ! The functions shown in sends control signals to other server processes. Use of this function is restricted to superusers. *************** *** 9080,9100 **** int Cancel a backend's current query ! This function returns 1 if successful, 0 if not successful. The process ID (pid) of an active backend can be found from the procpid column in the pg_stat_activity view, or by listing the postgres processes on the server with ps. ! ! ! pg_start_backup ! pg_stop_backup --- 9083,9111 ---- int Cancel a backend's current query + + + pg_reload_conf() + + int + Triggers the server processes to reload configuration files + ! These functions return 1 if successful, 0 if not successful. The process ID (pid) of an active backend can be found from the procpid column in the pg_stat_activity view, or by listing the postgres processes on the server with ps. ! ! pg_reload_conf sends a SIGHUP event to the ! postmaster, and thus triggers a reload of the configuration files ! in all backend processes. ! pg_stop_backup *************** *** 9161,9166 **** --- 9172,9376 ---- For details about proper usage of these functions, see . + + + The functions shown in provide native file access to + files on the machine hosting the server. They are restricted to + the cluster directory or the logfile directory. + Use of these functions is restricted to superusers. + + + + Generic File Access Functions + + + Name Return Type Description + + + + + + + pg_file_stat(filename_text) + + record + Retrieves file stats + + + + pg_file_length(filename_text) + + int8 + Returns the file length + + + + pg_file_read(filename_text, + offset_int8,length_int8) + + text + Returns the contents of a text file + + + + pg_file_write(filename_text,offset_int8>,append_bool) + + int8 + Writes text to a file + + + + pg_file_rename(oldname_text,newname_text) + + bool + Renames a file + + + + pg_file_rename(oldname_text,newname_text,archivname_text) + + bool + Renames a file and its archive file + + + + pg_file_unlink(filename_text) + + bool + Returns the file length + + + + pg_dir_ls(dirname_text,fullpath_bool) + + setof text + Returns the file length + + + +
+ + + pg_file_stat + + + + pg_file_stat() returns a record that contains the + length, creation timestamp, last accessed timestamp, last modified + timestamp and and a flag indicating a directory. + + + + pg_file_length + + + pg_file_length() returns the length of the given file. + + + + pg_file_read + + + pg_file_read() returns a part of a textfile, starting + at the offset giving length bytes. + + + pg_file_write + + + pg_file_write() writes text to a file at the given + offset. If the append flag is false, the file may not exist. If + the append file is set, the file must exist and be accessible. + + + + pg_file_rename + + + pg_file_rename(oldname_text,newname_text) is used to + rename a file to a new name. + + + pg_file_rename(oldname_text,newname_text,archivname_text) is used to + rename a file and its backup file to new names. The + oldname and newname files must exist, while the archivname file + may not exist when this command is issued.This can be used + to replace important files in a relatively safe way, because the + function will try to do the whole renaming or nothing at all. + Example: + + select pg_file_rename('postgresql.conf.tmp', 'postgresql.conf', 'postgresql.conf.bak'); + + will replace postgresql.conf with a new version which was + previously written to the temporary file postgresql.conf.tmp, + saving the former version as postgresql.conf.bak. + + + + pg_file_unlink + + + pg_file_unlink() unlinks the file. + + + pg_dir_ls lists all filenames in the named directory. + + + + The functions shown in allow access to the server + logfile, if the stderr log output is redirected. + Use of these functions is restricted to superusers. + + + + Backend Logfile Functions + + + Name Return Type Description + + + + + + + pg_logfile_rotate() + + int + Trigger logfile rotation + + + + pg_logdir_ls() + + setof record + lists all logfiles in the pg_log subdirectory + + + +
+ + + pg_logfile_rotate + + + pg_logfile_rotate issues a logfile rotation trigger, + which forces the server to close the current logfile and open a + fresh one. + + + + pg_logdir_ls + + + pg_logdir_ls lists all files in the pg_log + subdirectory. For each log file, a record consisting of a + timestamp of its creation time and a complete path to the file is + returned. For convenience, the view pg_logdir_ls wraps the + function. + + Index: doc/src/sgml/runtime.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/runtime.sgml,v retrieving revision 1.339 diff -c -r1.339 runtime.sgml *** doc/src/sgml/runtime.sgml 23 Jul 2005 21:05:45 -0000 1.339 --- doc/src/sgml/runtime.sgml 30 Jul 2005 14:27:20 -0000 *************** *** 669,674 **** --- 669,688 ----
+ + + disable_remote_admin (boolean) + + disable_remote_admin configuration parameter + + + + Disables remote administration functions that modifies files on the server. + While these functions are only available to the database superuser, setting this + parameter will disable them completely. + + + Index: src/backend/catalog/system_views.sql =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/system_views.sql,v retrieving revision 1.17 diff -c -r1.17 system_views.sql *** src/backend/catalog/system_views.sql 26 Jul 2005 16:38:26 -0000 1.17 --- src/backend/catalog/system_views.sql 30 Jul 2005 13:33:30 -0000 *************** *** 330,332 **** --- 330,337 ---- pg_stat_get_db_blocks_hit(D.oid) AS blks_read, pg_stat_get_db_blocks_hit(D.oid) AS blks_hit FROM pg_database D; + + CREATE VIEW pg_logdir_ls AS + SELECT * + FROM pg_logdir_ls() AS A + (filetime timestamp, filename text); Index: src/backend/postmaster/postmaster.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/postmaster.c,v retrieving revision 1.461 diff -c -r1.461 postmaster.c *** src/backend/postmaster/postmaster.c 29 Jul 2005 19:30:04 -0000 1.461 --- src/backend/postmaster/postmaster.c 30 Jul 2005 13:39:55 -0000 *************** *** 3393,3398 **** --- 3393,3403 ---- } } + if (CheckPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE) && SysLoggerPID != 0) + { + kill(SysLoggerPID, SIGUSR1); + } + PG_SETMASK(&UnBlockSig); errno = save_errno; Index: src/backend/postmaster/syslogger.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/syslogger.c,v retrieving revision 1.18 diff -c -r1.18 syslogger.c *** src/backend/postmaster/syslogger.c 21 Jul 2005 18:06:12 -0000 1.18 --- src/backend/postmaster/syslogger.c 30 Jul 2005 13:33:30 -0000 *************** *** 101,106 **** --- 101,107 ---- * Flags set by interrupt handlers for later service in the main loop. */ static volatile sig_atomic_t got_SIGHUP = false; + static volatile sig_atomic_t rotation_requested = false; /* Local subroutines */ *************** *** 117,122 **** --- 118,124 ---- static char *logfile_getname(pg_time_t timestamp); static void set_next_rotation_time(void); static void sigHupHandler(SIGNAL_ARGS); + static void sigUsr1Handler(SIGNAL_ARGS); /* *************** *** 200,206 **** pqsignal(SIGQUIT, SIG_IGN); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); ! pqsignal(SIGUSR1, SIG_IGN); pqsignal(SIGUSR2, SIG_IGN); /* --- 202,208 ---- pqsignal(SIGQUIT, SIG_IGN); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); ! pqsignal(SIGUSR1, sigUsr1Handler); /* request log rotation */ pqsignal(SIGUSR2, SIG_IGN); /* *************** *** 235,241 **** /* main worker loop */ for (;;) { - bool rotation_requested = false; bool time_based_rotation = false; #ifndef WIN32 --- 237,242 ---- *************** *** 726,731 **** --- 727,734 ---- char *filename; FILE *fh; + rotation_requested = false; + /* * When doing a time-based rotation, invent the new logfile name based * on the planned rotation time, not current time, to avoid "slippage" *************** *** 876,878 **** --- 879,888 ---- { got_SIGHUP = true; } + + /* SIGUSR1: set flag to rotate logfile */ + static void + sigUsr1Handler(SIGNAL_ARGS) + { + rotation_requested = true; + } Index: src/backend/utils/adt/Makefile =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/Makefile,v retrieving revision 1.58 diff -c -r1.58 Makefile *** src/backend/utils/adt/Makefile 29 Jul 2005 14:46:57 -0000 1.58 --- src/backend/utils/adt/Makefile 30 Jul 2005 13:38:05 -0000 *************** *** 24,30 **** tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \ network.o mac.o inet_net_ntop.o inet_net_pton.o \ ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \ ! ascii.o quote.o pgstatfuncs.o encode.o dbsize.o like.o: like.c like_match.c --- 24,30 ---- tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \ network.o mac.o inet_net_ntop.o inet_net_pton.o \ ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \ ! ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o like.o: like.c like_match.c Index: src/backend/utils/adt/misc.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/misc.c,v retrieving revision 1.45 diff -c -r1.45 misc.c *** src/backend/utils/adt/misc.c 4 Jul 2005 04:51:50 -0000 1.45 --- src/backend/utils/adt/misc.c 30 Jul 2005 13:39:10 -0000 *************** *** 17,31 **** --- 17,37 ---- #include #include #include + #include + #include #include "commands/dbcommands.h" #include "miscadmin.h" #include "storage/procarray.h" + #include "storage/pmsignal.h" #include "storage/fd.h" #include "utils/builtins.h" + #include "utils/datetime.h" + #include "utils/elog.h" #include "funcapi.h" #include "catalog/pg_type.h" #include "catalog/pg_tablespace.h" + #include "postmaster/syslogger.h" #define atooid(x) ((Oid) strtoul((x), NULL, 10)) *************** *** 107,112 **** --- 113,276 ---- PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0), SIGINT)); } + + Datum + pg_reload_conf(PG_FUNCTION_ARGS) + { + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("only superuser can signal the postmaster")))); + + if (kill(PostmasterPid, SIGHUP)) + { + ereport(WARNING, + (errmsg("failed to send signal to postmaster: %m"))); + + PG_RETURN_INT32(0); + } + + PG_RETURN_INT32(1); + } + + + /* + * Rotate log file + */ + Datum + pg_logfile_rotate(PG_FUNCTION_ARGS) + { + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("only superuser can rotate log files")))); + + if (!Redirect_stderr) + { + ereport(NOTICE, + (errcode(ERRCODE_WARNING), + errmsg("no logfile configured; rotation not supported"))); + PG_RETURN_INT32(0); + } + + SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE); + + PG_RETURN_INT32(0); + } + + typedef struct + { + char *location; + DIR *dirdesc; + } directory_fctx; + + /* + * scan log directory for log files + */ + Datum pg_logdir_ls(PG_FUNCTION_ARGS) + { + FuncCallContext *funcctx; + struct dirent *de; + directory_fctx *fctx; + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("only superuser can list the log directory")))); + + if (memcmp(Log_filename, "postgresql-%Y-%m-%d_%H%M%S.log", 30) != 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + (errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'")))); + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldcontext; + TupleDesc tupdesc; + + funcctx=SRF_FIRSTCALL_INIT(); + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + fctx = palloc(sizeof(directory_fctx)); + if (is_absolute_path(Log_directory)) + fctx->location = Log_directory; + else + { + fctx->location = palloc(strlen(DataDir) + strlen(Log_directory) +2); + sprintf(fctx->location, "%s/%s", DataDir, Log_directory); + } + tupdesc = CreateTemplateTupleDesc(2, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime", + TIMESTAMPOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename", + TEXTOID, -1, 0); + + funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); + + fctx->dirdesc = AllocateDir(fctx->location); + + if (!fctx->dirdesc) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("%s is not browsable: %m", fctx->location))); + + funcctx->user_fctx = fctx; + MemoryContextSwitchTo(oldcontext); + } + + funcctx=SRF_PERCALL_SETUP(); + fctx = (directory_fctx*) funcctx->user_fctx; + + if (!fctx->dirdesc) /* not a readable directory */ + SRF_RETURN_DONE(funcctx); + + while ((de = readdir(fctx->dirdesc)) != NULL) + { + char *values[2]; + HeapTuple tuple; + + char *field[MAXDATEFIELDS]; + char lowstr[MAXDATELEN + 1]; + int dtype; + int nf, ftype[MAXDATEFIELDS]; + fsec_t fsec; + int tz = 0; + struct pg_tm date; + + /* + * Default format: + * postgresql-YYYY-MM-DD_HHMMSS.log + */ + if (strlen(de->d_name) != 32 + || memcmp(de->d_name, "postgresql-", 11) + || de->d_name[21] != '_' + || strcmp(de->d_name + 28, ".log")) + continue; + + values[1] = palloc(strlen(fctx->location) + strlen(de->d_name) + 2); + sprintf(values[1], "%s/%s", fctx->location, de->d_name); + + values[0] = de->d_name + 11; /* timestamp */ + values[0][17] = 0; + + /* parse and decode expected timestamp */ + if (ParseDateTime(values[0], lowstr, sizeof(lowstr), field, ftype, MAXDATEFIELDS, &nf)) + continue; + + if (DecodeDateTime(field, ftype, nf, &dtype, &date, &fsec, &tz)) + continue; + + /* Seems the format fits the expected format; feed it into the tuple */ + + tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); + + SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); + } + + FreeDir(fctx->dirdesc); + SRF_RETURN_DONE(funcctx); + } + #ifdef NOT_USED /* Disabled in 8.0 due to reliability concerns; FIXME someday */ Index: src/backend/utils/misc/guc.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/misc/guc.c,v retrieving revision 1.279 diff -c -r1.279 guc.c *** src/backend/utils/misc/guc.c 29 Jul 2005 19:30:07 -0000 1.279 --- src/backend/utils/misc/guc.c 30 Jul 2005 14:10:17 -0000 *************** *** 85,90 **** --- 85,91 ---- extern int CommitSiblings; extern char *default_tablespace; extern bool fullPageWrites; + extern bool disableRemoteAdmin; static const char *assign_log_destination(const char *value, bool doit, GucSource source); *************** *** 930,935 **** --- 931,945 ---- false, NULL, NULL }, + { + {"disable_remote_admin", PGC_POSTMASTER, FILE_LOCATIONS, + gettext_noop("prevents remote administration functions from writing data"), + NULL + }, + &disableRemoteAdmin, + false, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL Index: src/backend/utils/misc/postgresql.conf.sample =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/misc/postgresql.conf.sample,v retrieving revision 1.154 diff -c -r1.154 postgresql.conf.sample *** src/backend/utils/misc/postgresql.conf.sample 23 Jul 2005 21:05:47 -0000 1.154 --- src/backend/utils/misc/postgresql.conf.sample 30 Jul 2005 14:17:51 -0000 *************** *** 39,44 **** --- 39,48 ---- # If external_pid_file is not explicitly set, no extra pid file is written. # external_pid_file = '(none)' # write an extra pid file + # Setting disable_remote_admin will prevent the configuration functions that + # can modify files on the database server. When enabled these functions + # are still restricted to superuser only. + # disable_remote_admin = off #--------------------------------------------------------------------------- # CONNECTIONS AND AUTHENTICATION Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v retrieving revision 1.379 diff -c -r1.379 pg_proc.h *** src/include/catalog/pg_proc.h 29 Jul 2005 14:47:01 -0000 1.379 --- src/include/catalog/pg_proc.h 30 Jul 2005 13:58:00 -0000 *************** *** 3048,3053 **** --- 3048,3079 ---- DESCR("Prepare for taking an online backup"); DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 f f t f v 0 25 "" _null_ _null_ _null_ pg_stop_backup - _null_ )); DESCR("Finish taking an online backup"); + DATA(insert OID = 1079 ( pg_reload_conf PGNSP PGUID 12 f f t f v 0 23 "" _null_ _null_ _null_ pg_reload_conf - _null_ )); + DESCR("Reloads configuration files"); + + DATA(insert OID = 1136 ( pg_logfile_rotate PGNSP PGUID 12 f f t f v 0 23 "" _null_ _null_ _null_ pg_logfile_rotate - _null_ )); + DESCR("rotate log file"); + DATA(insert OID = 1137 ( pg_logdir_ls PGNSP PGUID 12 f f t t v 0 2249 "" _null_ _null_ _null_ pg_logdir_ls - _null_ )); + DESCR("list all available log files"); + + + DATA(insert OID = 2621 ( pg_file_stat PGNSP PGUID 12 f f t f v 1 2249 "25" _null_ _null_ _null_ pg_file_stat - _null_ )); + DESCR("retrieve file stats"); + DATA(insert OID = 2622 ( pg_file_length PGNSP PGUID 14 f f t f v 1 20 "25" _null_ _null_ _null_ "SELECT len FROM pg_file_stat($1) AS s(len int8, c timestamp, a timestamp, m timestamp, i bool)" - _null_ )); + DESCR("returns length of a file"); + DATA(insert OID = 2623 ( pg_file_read PGNSP PGUID 12 f f t f v 3 25 "25 20 20" _null_ _null_ _null_ pg_file_read - _null_ )); + DESCR("reads text from a file"); + DATA(insert OID = 2624 ( pg_file_write PGNSP PGUID 12 f f t f v 3 20 "25 25 16" _null_ _null_ _null_ pg_file_write - _null_ )); + DESCR("writes text to a file"); + DATA(insert OID = 2625 ( pg_file_rename PGNSP PGUID 12 f f f f v 3 16 "25 25 25" _null_ _null_ _null_ pg_file_rename - _null_ )); + DESCR("renames a file and its backup file"); + DATA(insert OID = 2626 ( pg_file_rename PGNSP PGUID 12 f f f t v 2 16 "25 25" _null_ _null_ _null_ pg_file_rename - _null_ )); + DESCR("renames a file"); + DATA(insert OID = 2627 ( pg_file_unlink PGNSP PGUID 12 f f t f v 1 16 "25" _null_ _null_ _null_ pg_file_unlink - _null_ )); + DESCR("unlinks a file"); + DATA(insert OID = 2628 ( pg_dir_ls PGNSP PGUID 12 f f t t v 2 25 "25 16" _null_ _null_ _null_ pg_dir_ls - _null_ )); + DESCR("lists all filenames from a directory"); + /* Aggregates (moved here from pg_aggregate for 7.3) */ Index: src/include/storage/pmsignal.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/storage/pmsignal.h,v retrieving revision 1.12 diff -c -r1.12 pmsignal.h *** src/include/storage/pmsignal.h 28 Jun 2005 19:51:25 -0000 1.12 --- src/include/storage/pmsignal.h 30 Jul 2005 13:33:30 -0000 *************** *** 25,31 **** PMSIGNAL_PASSWORD_CHANGE, /* pg_auth file has changed */ PMSIGNAL_WAKEN_CHILDREN, /* send a SIGUSR1 signal to all backends */ PMSIGNAL_WAKEN_ARCHIVER, /* send a NOTIFY signal to xlog archiver */ ! NUM_PMSIGNALS /* Must be last value of enum! */ } PMSignalReason; --- 25,31 ---- PMSIGNAL_PASSWORD_CHANGE, /* pg_auth file has changed */ PMSIGNAL_WAKEN_CHILDREN, /* send a SIGUSR1 signal to all backends */ PMSIGNAL_WAKEN_ARCHIVER, /* send a NOTIFY signal to xlog archiver */ ! PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */ NUM_PMSIGNALS /* Must be last value of enum! */ } PMSignalReason; Index: src/include/utils/builtins.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/utils/builtins.h,v retrieving revision 1.262 diff -c -r1.262 builtins.h *** src/include/utils/builtins.h 29 Jul 2005 14:47:04 -0000 1.262 --- src/include/utils/builtins.h 30 Jul 2005 13:41:17 -0000 *************** *** 363,368 **** --- 363,376 ---- extern Datum float84gt(PG_FUNCTION_ARGS); extern Datum float84ge(PG_FUNCTION_ARGS); + /* genfile.c */ + extern Datum pg_file_stat(PG_FUNCTION_ARGS); + extern Datum pg_file_read(PG_FUNCTION_ARGS); + extern Datum pg_file_write(PG_FUNCTION_ARGS); + extern Datum pg_file_rename(PG_FUNCTION_ARGS); + extern Datum pg_file_unlink(PG_FUNCTION_ARGS); + extern Datum pg_dir_ls(PG_FUNCTION_ARGS); + /* dbsize.c */ extern Datum pg_tablespace_size_oid(PG_FUNCTION_ARGS); extern Datum pg_tablespace_size_name(PG_FUNCTION_ARGS); *************** *** 379,385 **** --- 387,396 ---- extern Datum nonnullvalue(PG_FUNCTION_ARGS); extern Datum current_database(PG_FUNCTION_ARGS); extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); + extern Datum pg_reload_conf(PG_FUNCTION_ARGS); extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS); + extern Datum pg_logfile_rotate(PG_FUNCTION_ARGS); + extern Datum pg_logdir_ls(PG_FUNCTION_ARGS); /* not_in.c */ extern Datum int4notin(PG_FUNCTION_ARGS);