Skip to content

Commit 9cd92d1

Browse files
committed
Add pg_ls_tmpdir function
This lists the contents of a temporary directory associated to a given tablespace, useful to get information about on-disk consumption caused by temporary files used by a session query. By default, pg_default is scanned, and a tablespace can be specified as argument. This function is intended to be used by monitoring tools, and, unlike pg_ls_dir(), access to them can be granted to non-superusers so that those monitoring tools can observe the principle of least privilege. Access is also given by default to members of pg_monitor. Author: Nathan Bossart Reviewed-by: Laurenz Albe Discussion: https://postgr.es/m/92F458A2-6459-44B8-A7F2-2ADD3225046A@amazon.com
1 parent d73f4c7 commit 9cd92d1

File tree

5 files changed

+97
-8
lines changed

5 files changed

+97
-8
lines changed

doc/src/sgml/func.sgml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20355,6 +20355,20 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
2035520355
role and may be granted to other non-superuser roles.
2035620356
</entry>
2035720357
</row>
20358+
<row>
20359+
<entry>
20360+
<literal><function>pg_ls_tmpdir(<optional><parameter>tablespace</parameter> <type>oid</type></optional>)</function></literal>
20361+
</entry>
20362+
<entry><type>setof record</type></entry>
20363+
<entry>
20364+
List the name, size, and last modification time of files in the
20365+
temporary directory for <parameter>tablespace</parameter>. If
20366+
<parameter>tablespace</parameter> is not provided, the
20367+
<literal>pg_default</literal> tablespace is used. Access is granted
20368+
to members of the <literal>pg_monitor</literal> role and may be
20369+
granted to other non-superuser roles.
20370+
</entry>
20371+
</row>
2035820372
<row>
2035920373
<entry>
2036020374
<literal><function>pg_read_file(<parameter>filename</parameter> <type>text</type> [, <parameter>offset</parameter> <type>bigint</type>, <parameter>length</parameter> <type>bigint</type> [, <parameter>missing_ok</parameter> <type>boolean</type>] ])</function></literal>
@@ -20428,6 +20442,19 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
2042820442
<command>GRANT</command>.
2042920443
</para>
2043020444

20445+
<indexterm>
20446+
<primary>pg_ls_tmpdir</primary>
20447+
</indexterm>
20448+
<para>
20449+
<function>pg_ls_tmpdir</function> returns the name, size, and last modified
20450+
time (mtime) of each file in the temporary file directory for the specified
20451+
<parameter>tablespace</parameter>. If <parameter>tablespace</parameter> is
20452+
not provided, the <literal>pg_default</literal> tablespace is used. By
20453+
default only superusers and members of the <literal>pg_monitor</literal>
20454+
role can use this function. Access may be granted to others using
20455+
<command>GRANT</command>.
20456+
</para>
20457+
2043120458
<indexterm>
2043220459
<primary>pg_read_file</primary>
2043320460
</indexterm>

src/backend/catalog/system_views.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,8 @@ REVOKE EXECUTE ON FUNCTION lo_export(oid, text) FROM public;
11501150

11511151
REVOKE EXECUTE ON FUNCTION pg_ls_logdir() FROM public;
11521152
REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public;
1153+
REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir() FROM public;
1154+
REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir(oid) FROM public;
11531155

11541156
REVOKE EXECUTE ON FUNCTION pg_read_file(text) FROM public;
11551157
REVOKE EXECUTE ON FUNCTION pg_read_file(text,bigint,bigint) FROM public;
@@ -1170,6 +1172,8 @@ REVOKE EXECUTE ON FUNCTION pg_ls_dir(text,boolean,boolean) FROM public;
11701172
--
11711173
GRANT EXECUTE ON FUNCTION pg_ls_logdir() TO pg_monitor;
11721174
GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor;
1175+
GRANT EXECUTE ON FUNCTION pg_ls_tmpdir() TO pg_monitor;
1176+
GRANT EXECUTE ON FUNCTION pg_ls_tmpdir(oid) TO pg_monitor;
11731177

11741178
GRANT pg_read_all_settings TO pg_monitor;
11751179
GRANT pg_read_all_stats TO pg_monitor;

src/backend/utils/adt/genfile.c

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "access/htup_details.h"
2424
#include "access/xlog_internal.h"
2525
#include "catalog/pg_authid.h"
26+
#include "catalog/pg_tablespace_d.h"
2627
#include "catalog/pg_type.h"
2728
#include "funcapi.h"
2829
#include "mb/pg_wchar.h"
@@ -31,6 +32,7 @@
3132
#include "storage/fd.h"
3233
#include "utils/builtins.h"
3334
#include "utils/memutils.h"
35+
#include "utils/syscache.h"
3436
#include "utils/timestamp.h"
3537

3638
typedef struct
@@ -520,7 +522,7 @@ pg_ls_dir_1arg(PG_FUNCTION_ARGS)
520522

521523
/* Generic function to return a directory listing of files */
522524
static Datum
523-
pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
525+
pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
524526
{
525527
FuncCallContext *funcctx;
526528
struct dirent *de;
@@ -549,10 +551,18 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
549551
fctx->dirdesc = AllocateDir(fctx->location);
550552

551553
if (!fctx->dirdesc)
552-
ereport(ERROR,
553-
(errcode_for_file_access(),
554-
errmsg("could not open directory \"%s\": %m",
555-
fctx->location)));
554+
{
555+
if (missing_ok && errno == ENOENT)
556+
{
557+
MemoryContextSwitchTo(oldcontext);
558+
SRF_RETURN_DONE(funcctx);
559+
}
560+
else
561+
ereport(ERROR,
562+
(errcode_for_file_access(),
563+
errmsg("could not open directory \"%s\": %m",
564+
fctx->location)));
565+
}
556566

557567
funcctx->user_fctx = fctx;
558568
MemoryContextSwitchTo(oldcontext);
@@ -601,12 +611,50 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
601611
Datum
602612
pg_ls_logdir(PG_FUNCTION_ARGS)
603613
{
604-
return pg_ls_dir_files(fcinfo, Log_directory);
614+
return pg_ls_dir_files(fcinfo, Log_directory, false);
605615
}
606616

607617
/* Function to return the list of files in the WAL directory */
608618
Datum
609619
pg_ls_waldir(PG_FUNCTION_ARGS)
610620
{
611-
return pg_ls_dir_files(fcinfo, XLOGDIR);
621+
return pg_ls_dir_files(fcinfo, XLOGDIR, false);
622+
}
623+
624+
/*
625+
* Generic function to return the list of files in pgsql_tmp
626+
*/
627+
static Datum
628+
pg_ls_tmpdir(FunctionCallInfo fcinfo, Oid tblspc)
629+
{
630+
char path[MAXPGPATH];
631+
632+
if (!SearchSysCacheExists1(TABLESPACEOID, ObjectIdGetDatum(tblspc)))
633+
ereport(ERROR,
634+
(errcode(ERRCODE_UNDEFINED_OBJECT),
635+
errmsg("tablespace with OID %u does not exist",
636+
tblspc)));
637+
638+
TempTablespacePath(path, tblspc);
639+
return pg_ls_dir_files(fcinfo, path, true);
640+
}
641+
642+
/*
643+
* Function to return the list of temporary files in the pg_default tablespace's
644+
* pgsql_tmp directory
645+
*/
646+
Datum
647+
pg_ls_tmpdir_noargs(PG_FUNCTION_ARGS)
648+
{
649+
return pg_ls_tmpdir(fcinfo, DEFAULTTABLESPACE_OID);
650+
}
651+
652+
/*
653+
* Function to return the list of temporary files in the specified tablespace's
654+
* pgsql_tmp directory
655+
*/
656+
Datum
657+
pg_ls_tmpdir_1arg(PG_FUNCTION_ARGS)
658+
{
659+
return pg_ls_tmpdir(fcinfo, PG_GETARG_OID(0));
612660
}

src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 201809301
56+
#define CATALOG_VERSION_NO 201810051
5757

5858
#endif

src/include/catalog/pg_proc.dat

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10199,6 +10199,16 @@
1019910199
provolatile => 'v', prorettype => 'record', proargtypes => '',
1020010200
proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
1020110201
proargnames => '{name,size,modification}', prosrc => 'pg_ls_waldir' },
10202+
{ oid => '5029', descr => 'list files in the pgsql_tmp directory',
10203+
proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
10204+
provolatile => 'v', prorettype => 'record', proargtypes => '',
10205+
proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
10206+
proargnames => '{name,size,modification}', prosrc => 'pg_ls_tmpdir_noargs' },
10207+
{ oid => '5030', descr => 'list files in the pgsql_tmp directory',
10208+
proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
10209+
provolatile => 'v', prorettype => 'record', proargtypes => 'oid',
10210+
proallargtypes => '{oid,text,int8,timestamptz}', proargmodes => '{i,o,o,o}',
10211+
proargnames => '{tablespace,name,size,modification}', prosrc => 'pg_ls_tmpdir_1arg' },
1020210212

1020310213
# hash partitioning constraint function
1020410214
{ oid => '5028', descr => 'hash partition CHECK constraint',

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy