PostgreSQL Source Code  git master
genfile.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "access/htup_details.h"
#include "access/xlog_internal.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_tablespace_d.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "postmaster/syslogger.h"
#include "storage/fd.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
Include dependency graph for genfile.c:

Go to the source code of this file.

Data Structures

struct  directory_fctx
 

Functions

static char * convert_and_check_filename (text *arg)
 
static bytearead_binary_file (const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
 
static textread_text_file (const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
 
Datum pg_read_file (PG_FUNCTION_ARGS)
 
Datum pg_read_file_v2 (PG_FUNCTION_ARGS)
 
Datum pg_read_binary_file (PG_FUNCTION_ARGS)
 
Datum pg_read_file_off_len (PG_FUNCTION_ARGS)
 
Datum pg_read_file_all (PG_FUNCTION_ARGS)
 
Datum pg_read_binary_file_off_len (PG_FUNCTION_ARGS)
 
Datum pg_read_binary_file_all (PG_FUNCTION_ARGS)
 
Datum pg_stat_file (PG_FUNCTION_ARGS)
 
Datum pg_stat_file_1arg (PG_FUNCTION_ARGS)
 
Datum pg_ls_dir (PG_FUNCTION_ARGS)
 
Datum pg_ls_dir_1arg (PG_FUNCTION_ARGS)
 
static Datum pg_ls_dir_files (FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
 
Datum pg_ls_logdir (PG_FUNCTION_ARGS)
 
Datum pg_ls_waldir (PG_FUNCTION_ARGS)
 
static Datum pg_ls_tmpdir (FunctionCallInfo fcinfo, Oid tblspc)
 
Datum pg_ls_tmpdir_noargs (PG_FUNCTION_ARGS)
 
Datum pg_ls_tmpdir_1arg (PG_FUNCTION_ARGS)
 
Datum pg_ls_archive_statusdir (PG_FUNCTION_ARGS)
 

Function Documentation

◆ convert_and_check_filename()

static char* convert_and_check_filename ( text arg)
static

Definition at line 59 of file genfile.c.

References canonicalize_path(), DataDir, ereport, errcode(), errmsg(), ERROR, filename, GetUserId(), is_absolute_path, is_member_of_role(), Log_directory, path_contains_parent_reference(), path_is_prefix_of_path(), path_is_relative_and_below_cwd(), and text_to_cstring().

Referenced by pg_ls_dir(), pg_read_binary_file(), pg_read_file(), pg_read_file_v2(), and pg_stat_file().

60 {
61  char *filename;
62 
63  filename = text_to_cstring(arg);
64  canonicalize_path(filename); /* filename can change length here */
65 
66  /*
67  * Members of the 'pg_read_server_files' role are allowed to access any
68  * files on the server as the PG user, so no need to do any further checks
69  * here.
70  */
71  if (is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_SERVER_FILES))
72  return filename;
73 
74  /* User isn't a member of the default role, so check if it's allowable */
75  if (is_absolute_path(filename))
76  {
77  /* Disallow '/a/b/data/..' */
78  if (path_contains_parent_reference(filename))
79  ereport(ERROR,
80  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
81  (errmsg("reference to parent directory (\"..\") not allowed"))));
82 
83  /*
84  * Allow absolute paths if within DataDir or Log_directory, even
85  * though Log_directory might be outside DataDir.
86  */
87  if (!path_is_prefix_of_path(DataDir, filename) &&
90  ereport(ERROR,
91  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
92  (errmsg("absolute path not allowed"))));
93  }
94  else if (!path_is_relative_and_below_cwd(filename))
95  ereport(ERROR,
96  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
97  (errmsg("path must be in or below the current directory"))));
98 
99  return filename;
100 }
char * Log_directory
Definition: syslogger.c:72
Oid GetUserId(void)
Definition: miscinit.c:380
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:438
void canonicalize_path(char *path)
Definition: path.c:254
int errcode(int sqlerrcode)
Definition: elog.c:570
bool path_contains_parent_reference(const char *path)
Definition: path.c:376
#define ERROR
Definition: elog.h:43
#define is_absolute_path(filename)
Definition: port.h:86
bool path_is_relative_and_below_cwd(const char *path)
Definition: path.c:405
#define ereport(elevel, rest)
Definition: elog.h:141
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4932
char * text_to_cstring(const text *t)
Definition: varlena.c:204
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:784
char * DataDir
Definition: globals.c:62

◆ pg_ls_archive_statusdir()

Datum pg_ls_archive_statusdir ( PG_FUNCTION_ARGS  )

Definition at line 668 of file genfile.c.

References pg_ls_dir_files(), and XLOGDIR.

669 {
670  return pg_ls_dir_files(fcinfo, XLOGDIR "/archive_status", true);
671 }
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:527
#define XLOGDIR

◆ pg_ls_dir()

Datum pg_ls_dir ( PG_FUNCTION_ARGS  )

Definition at line 447 of file genfile.c.

References AllocateDir(), convert_and_check_filename(), CStringGetTextDatum, dirent::d_name, directory_fctx::dirdesc, ereport, errcode_for_file_access(), errmsg(), ERROR, FreeDir(), directory_fctx::include_dot_dirs, directory_fctx::location, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), PG_ARGISNULL, PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_NARGS, ReadDir(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and FuncCallContext::user_fctx.

Referenced by pg_ls_dir_1arg().

448 {
449  FuncCallContext *funcctx;
450  struct dirent *de;
451  directory_fctx *fctx;
452  MemoryContext oldcontext;
453 
454  if (SRF_IS_FIRSTCALL())
455  {
456  bool missing_ok = false;
457  bool include_dot_dirs = false;
458 
459  /* check the optional arguments */
460  if (PG_NARGS() == 3)
461  {
462  if (!PG_ARGISNULL(1))
463  missing_ok = PG_GETARG_BOOL(1);
464  if (!PG_ARGISNULL(2))
465  include_dot_dirs = PG_GETARG_BOOL(2);
466  }
467 
468  funcctx = SRF_FIRSTCALL_INIT();
469  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
470 
471  fctx = palloc(sizeof(directory_fctx));
473 
474  fctx->include_dot_dirs = include_dot_dirs;
475  fctx->dirdesc = AllocateDir(fctx->location);
476 
477  if (!fctx->dirdesc)
478  {
479  if (missing_ok && errno == ENOENT)
480  {
481  MemoryContextSwitchTo(oldcontext);
482  SRF_RETURN_DONE(funcctx);
483  }
484  else
485  ereport(ERROR,
487  errmsg("could not open directory \"%s\": %m",
488  fctx->location)));
489  }
490  funcctx->user_fctx = fctx;
491  MemoryContextSwitchTo(oldcontext);
492  }
493 
494  funcctx = SRF_PERCALL_SETUP();
495  fctx = (directory_fctx *) funcctx->user_fctx;
496 
497  while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
498  {
499  if (!fctx->include_dot_dirs &&
500  (strcmp(de->d_name, ".") == 0 ||
501  strcmp(de->d_name, "..") == 0))
502  continue;
503 
505  }
506 
507  FreeDir(fctx->dirdesc);
508 
509  SRF_RETURN_DONE(funcctx);
510 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:59
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:283
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
bool include_dot_dirs
Definition: genfile.c:42
Definition: dirent.h:9
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:287
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:289
#define ERROR
Definition: elog.h:43
DIR * dirdesc
Definition: adminpack.c:60
int errcode_for_file_access(void)
Definition: elog.c:593
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2466
#define ereport(elevel, rest)
Definition: elog.h:141
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2532
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:102
#define PG_NARGS()
Definition: fmgr.h:198
char * location
Definition: adminpack.c:59
void * user_fctx
Definition: funcapi.h:83
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define CStringGetTextDatum(s)
Definition: builtins.h:83
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2584
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:307
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:285

◆ pg_ls_dir_1arg()

Datum pg_ls_dir_1arg ( PG_FUNCTION_ARGS  )

Definition at line 520 of file genfile.c.

References pg_ls_dir().

521 {
522  return pg_ls_dir(fcinfo);
523 }
Datum pg_ls_dir(PG_FUNCTION_ARGS)
Definition: genfile.c:447

◆ pg_ls_dir_files()

static Datum pg_ls_dir_files ( FunctionCallInfo  fcinfo,
const char *  dir,
bool  missing_ok 
)
static

Definition at line 527 of file genfile.c.

References AllocateDir(), BlessTupleDesc(), CreateTemplateTupleDesc(), CStringGetTextDatum, dirent::d_name, directory_fctx::dirdesc, ereport, errcode_for_file_access(), errmsg(), ERROR, FreeDir(), heap_form_tuple(), HeapTupleGetDatum, Int64GetDatum(), directory_fctx::location, MAXPGPATH, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), pstrdup(), ReadDir(), S_ISREG, snprintf, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, stat, time_t_to_timestamptz(), TimestampTzGetDatum, FuncCallContext::tuple_desc, TupleDescInitEntry(), FuncCallContext::user_fctx, and values.

Referenced by pg_ls_archive_statusdir(), pg_ls_logdir(), pg_ls_tmpdir(), and pg_ls_waldir().

528 {
529  FuncCallContext *funcctx;
530  struct dirent *de;
531  directory_fctx *fctx;
532 
533  if (SRF_IS_FIRSTCALL())
534  {
535  MemoryContext oldcontext;
536  TupleDesc tupdesc;
537 
538  funcctx = SRF_FIRSTCALL_INIT();
539  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
540 
541  fctx = palloc(sizeof(directory_fctx));
542 
543  tupdesc = CreateTemplateTupleDesc(3);
544  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
545  TEXTOID, -1, 0);
546  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "size",
547  INT8OID, -1, 0);
548  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "modification",
549  TIMESTAMPTZOID, -1, 0);
550  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
551 
552  fctx->location = pstrdup(dir);
553  fctx->dirdesc = AllocateDir(fctx->location);
554 
555  if (!fctx->dirdesc)
556  {
557  if (missing_ok && errno == ENOENT)
558  {
559  MemoryContextSwitchTo(oldcontext);
560  SRF_RETURN_DONE(funcctx);
561  }
562  else
563  ereport(ERROR,
565  errmsg("could not open directory \"%s\": %m",
566  fctx->location)));
567  }
568 
569  funcctx->user_fctx = fctx;
570  MemoryContextSwitchTo(oldcontext);
571  }
572 
573  funcctx = SRF_PERCALL_SETUP();
574  fctx = (directory_fctx *) funcctx->user_fctx;
575 
576  while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
577  {
578  Datum values[3];
579  bool nulls[3];
580  char path[MAXPGPATH * 2];
581  struct stat attrib;
582  HeapTuple tuple;
583 
584  /* Skip hidden files */
585  if (de->d_name[0] == '.')
586  continue;
587 
588  /* Get the file info */
589  snprintf(path, sizeof(path), "%s/%s", fctx->location, de->d_name);
590  if (stat(path, &attrib) < 0)
591  ereport(ERROR,
593  errmsg("could not stat directory \"%s\": %m", dir)));
594 
595  /* Ignore anything but regular files */
596  if (!S_ISREG(attrib.st_mode))
597  continue;
598 
599  values[0] = CStringGetTextDatum(de->d_name);
600  values[1] = Int64GetDatum((int64) attrib.st_size);
601  values[2] = TimestampTzGetDatum(time_t_to_timestamptz(attrib.st_mtime));
602  memset(nulls, 0, sizeof(nulls));
603 
604  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
605  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
606  }
607 
608  FreeDir(fctx->dirdesc);
609  SRF_RETURN_DONE(funcctx);
610 }
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:283
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
Definition: dirent.h:9
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:287
TupleDesc tuple_desc
Definition: funcapi.h:113
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:289
#define ERROR
Definition: elog.h:43
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32
#define MAXPGPATH
DIR * dirdesc
Definition: adminpack.c:60
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2048
int errcode_for_file_access(void)
Definition: elog.c:593
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2466
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1699
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
#define ereport(elevel, rest)
Definition: elog.h:141
#define S_ISREG(m)
Definition: win32_port.h:299
#define stat(a, b)
Definition: win32_port.h:255
uintptr_t Datum
Definition: postgres.h:367
TimestampTz time_t_to_timestamptz(pg_time_t tm)
Definition: timestamp.c:1703
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2532
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:102
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
char * location
Definition: adminpack.c:59
static Datum values[MAXATTR]
Definition: bootstrap.c:167
void * user_fctx
Definition: funcapi.h:83
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define CStringGetTextDatum(s)
Definition: builtins.h:83
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int16 AttrNumber
Definition: attnum.h:21
int FreeDir(DIR *dir)
Definition: fd.c:2584
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:307
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:285

◆ pg_ls_logdir()

Datum pg_ls_logdir ( PG_FUNCTION_ARGS  )

Definition at line 614 of file genfile.c.

References Log_directory, and pg_ls_dir_files().

615 {
616  return pg_ls_dir_files(fcinfo, Log_directory, false);
617 }
char * Log_directory
Definition: syslogger.c:72
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:527

◆ pg_ls_tmpdir()

static Datum pg_ls_tmpdir ( FunctionCallInfo  fcinfo,
Oid  tblspc 
)
static

Definition at line 630 of file genfile.c.

References ereport, errcode(), errmsg(), ERROR, MAXPGPATH, ObjectIdGetDatum, pg_ls_dir_files(), SearchSysCacheExists1, TABLESPACEOID, and TempTablespacePath().

Referenced by pg_ls_tmpdir_1arg(), and pg_ls_tmpdir_noargs().

631 {
632  char path[MAXPGPATH];
633 
635  ereport(ERROR,
636  (errcode(ERRCODE_UNDEFINED_OBJECT),
637  errmsg("tablespace with OID %u does not exist",
638  tblspc)));
639 
640  TempTablespacePath(path, tblspc);
641  return pg_ls_dir_files(fcinfo, path, true);
642 }
int errcode(int sqlerrcode)
Definition: elog.c:570
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1515
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define ereport(elevel, rest)
Definition: elog.h:141
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:527
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ pg_ls_tmpdir_1arg()

Datum pg_ls_tmpdir_1arg ( PG_FUNCTION_ARGS  )

Definition at line 659 of file genfile.c.

References PG_GETARG_OID, and pg_ls_tmpdir().

660 {
661  return pg_ls_tmpdir(fcinfo, PG_GETARG_OID(0));
662 }
static Datum pg_ls_tmpdir(FunctionCallInfo fcinfo, Oid tblspc)
Definition: genfile.c:630
#define PG_GETARG_OID(n)
Definition: fmgr.h:270

◆ pg_ls_tmpdir_noargs()

Datum pg_ls_tmpdir_noargs ( PG_FUNCTION_ARGS  )

Definition at line 649 of file genfile.c.

References pg_ls_tmpdir().

650 {
651  return pg_ls_tmpdir(fcinfo, DEFAULTTABLESPACE_OID);
652 }
static Datum pg_ls_tmpdir(FunctionCallInfo fcinfo, Oid tblspc)
Definition: genfile.c:630

◆ pg_ls_waldir()

Datum pg_ls_waldir ( PG_FUNCTION_ARGS  )

Definition at line 621 of file genfile.c.

References pg_ls_dir_files(), and XLOGDIR.

622 {
623  return pg_ls_dir_files(fcinfo, XLOGDIR, false);
624 }
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:527
#define XLOGDIR

◆ pg_read_binary_file()

Datum pg_read_binary_file ( PG_FUNCTION_ARGS  )

Definition at line 292 of file genfile.c.

References convert_and_check_filename(), ereport, errcode(), errmsg(), ERROR, filename, PG_GETARG_BOOL, PG_GETARG_INT64, PG_GETARG_TEXT_PP, PG_NARGS, PG_RETURN_BYTEA_P, PG_RETURN_NULL, and read_binary_file().

Referenced by pg_read_binary_file_all(), and pg_read_binary_file_off_len().

293 {
294  text *filename_t = PG_GETARG_TEXT_PP(0);
295  int64 seek_offset = 0;
296  int64 bytes_to_read = -1;
297  bool missing_ok = false;
298  char *filename;
299  bytea *result;
300 
301  /* handle optional arguments */
302  if (PG_NARGS() >= 3)
303  {
304  seek_offset = PG_GETARG_INT64(1);
305  bytes_to_read = PG_GETARG_INT64(2);
306 
307  if (bytes_to_read < 0)
308  ereport(ERROR,
309  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
310  errmsg("requested length cannot be negative")));
311  }
312  if (PG_NARGS() >= 4)
313  missing_ok = PG_GETARG_BOOL(3);
314 
315  filename = convert_and_check_filename(filename_t);
316 
317  result = read_binary_file(filename, seek_offset,
318  bytes_to_read, missing_ok);
319  if (result)
320  PG_RETURN_BYTEA_P(result);
321  else
322  PG_RETURN_NULL();
323 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:59
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define ERROR
Definition: elog.h:43
static bytea * read_binary_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:111
#define ereport(elevel, rest)
Definition: elog.h:141
#define PG_NARGS()
Definition: fmgr.h:198
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ pg_read_binary_file_all()

Datum pg_read_binary_file_all ( PG_FUNCTION_ARGS  )

Definition at line 353 of file genfile.c.

References pg_read_binary_file().

354 {
355  return pg_read_binary_file(fcinfo);
356 }
Datum pg_read_binary_file(PG_FUNCTION_ARGS)
Definition: genfile.c:292

◆ pg_read_binary_file_off_len()

Datum pg_read_binary_file_off_len ( PG_FUNCTION_ARGS  )

Definition at line 347 of file genfile.c.

References pg_read_binary_file().

348 {
349  return pg_read_binary_file(fcinfo);
350 }
Datum pg_read_binary_file(PG_FUNCTION_ARGS)
Definition: genfile.c:292

◆ pg_read_file()

Datum pg_read_file ( PG_FUNCTION_ARGS  )

Definition at line 209 of file genfile.c.

References convert_and_check_filename(), ereport, errcode(), errhint(), errmsg(), ERROR, filename, PG_GETARG_BOOL, PG_GETARG_INT64, PG_GETARG_TEXT_PP, PG_NARGS, PG_RETURN_NULL, PG_RETURN_TEXT_P, read_text_file(), and superuser().

210 {
211  text *filename_t = PG_GETARG_TEXT_PP(0);
212  int64 seek_offset = 0;
213  int64 bytes_to_read = -1;
214  bool missing_ok = false;
215  char *filename;
216  text *result;
217 
218  if (!superuser())
219  ereport(ERROR,
220  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
221  (errmsg("must be superuser to read files with adminpack 1.0"),
222  /* translator: %s is a SQL function name */
223  errhint("Consider using %s, which is part of core, instead.",
224  "pg_file_read()"))));
225 
226  /* handle optional arguments */
227  if (PG_NARGS() >= 3)
228  {
229  seek_offset = PG_GETARG_INT64(1);
230  bytes_to_read = PG_GETARG_INT64(2);
231 
232  if (bytes_to_read < 0)
233  ereport(ERROR,
234  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
235  errmsg("requested length cannot be negative")));
236  }
237  if (PG_NARGS() >= 4)
238  missing_ok = PG_GETARG_BOOL(3);
239 
240  filename = convert_and_check_filename(filename_t);
241 
242  result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok);
243  if (result)
244  PG_RETURN_TEXT_P(result);
245  else
246  PG_RETURN_NULL();
247 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:59
int errhint(const char *fmt,...)
Definition: elog.c:974
int errcode(int sqlerrcode)
Definition: elog.c:570
bool superuser(void)
Definition: superuser.c:47
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define PG_NARGS()
Definition: fmgr.h:198
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
static text * read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:184
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ pg_read_file_all()

Datum pg_read_file_all ( PG_FUNCTION_ARGS  )

Definition at line 341 of file genfile.c.

References pg_read_file_v2().

342 {
343  return pg_read_file_v2(fcinfo);
344 }
Datum pg_read_file_v2(PG_FUNCTION_ARGS)
Definition: genfile.c:256

◆ pg_read_file_off_len()

Datum pg_read_file_off_len ( PG_FUNCTION_ARGS  )

Definition at line 335 of file genfile.c.

References pg_read_file_v2().

336 {
337  return pg_read_file_v2(fcinfo);
338 }
Datum pg_read_file_v2(PG_FUNCTION_ARGS)
Definition: genfile.c:256

◆ pg_read_file_v2()

Datum pg_read_file_v2 ( PG_FUNCTION_ARGS  )

Definition at line 256 of file genfile.c.

References convert_and_check_filename(), ereport, errcode(), errmsg(), ERROR, filename, PG_GETARG_BOOL, PG_GETARG_INT64, PG_GETARG_TEXT_PP, PG_NARGS, PG_RETURN_NULL, PG_RETURN_TEXT_P, and read_text_file().

Referenced by pg_read_file_all(), and pg_read_file_off_len().

257 {
258  text *filename_t = PG_GETARG_TEXT_PP(0);
259  int64 seek_offset = 0;
260  int64 bytes_to_read = -1;
261  bool missing_ok = false;
262  char *filename;
263  text *result;
264 
265  /* handle optional arguments */
266  if (PG_NARGS() >= 3)
267  {
268  seek_offset = PG_GETARG_INT64(1);
269  bytes_to_read = PG_GETARG_INT64(2);
270 
271  if (bytes_to_read < 0)
272  ereport(ERROR,
273  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
274  errmsg("requested length cannot be negative")));
275  }
276  if (PG_NARGS() >= 4)
277  missing_ok = PG_GETARG_BOOL(3);
278 
279  filename = convert_and_check_filename(filename_t);
280 
281  result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok);
282  if (result)
283  PG_RETURN_TEXT_P(result);
284  else
285  PG_RETURN_NULL();
286 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:59
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
#define PG_NARGS()
Definition: fmgr.h:198
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
static text * read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:184
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ pg_stat_file()

Datum pg_stat_file ( PG_FUNCTION_ARGS  )

Definition at line 362 of file genfile.c.

References BlessTupleDesc(), BoolGetDatum, convert_and_check_filename(), CreateTemplateTupleDesc(), ereport, errcode_for_file_access(), errmsg(), ERROR, filename, heap_form_tuple(), HeapTupleGetDatum, Int64GetDatum(), pfree(), PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_NARGS, PG_RETURN_DATUM, PG_RETURN_NULL, S_ISDIR, stat, time_t_to_timestamptz(), TimestampTzGetDatum, TupleDescInitEntry(), and values.

Referenced by pg_stat_file_1arg().

363 {
364  text *filename_t = PG_GETARG_TEXT_PP(0);
365  char *filename;
366  struct stat fst;
367  Datum values[6];
368  bool isnull[6];
369  HeapTuple tuple;
370  TupleDesc tupdesc;
371  bool missing_ok = false;
372 
373  /* check the optional argument */
374  if (PG_NARGS() == 2)
375  missing_ok = PG_GETARG_BOOL(1);
376 
377  filename = convert_and_check_filename(filename_t);
378 
379  if (stat(filename, &fst) < 0)
380  {
381  if (missing_ok && errno == ENOENT)
382  PG_RETURN_NULL();
383  else
384  ereport(ERROR,
386  errmsg("could not stat file \"%s\": %m", filename)));
387  }
388 
389  /*
390  * This record type had better match the output parameters declared for me
391  * in pg_proc.h.
392  */
393  tupdesc = CreateTemplateTupleDesc(6);
394  TupleDescInitEntry(tupdesc, (AttrNumber) 1,
395  "size", INT8OID, -1, 0);
396  TupleDescInitEntry(tupdesc, (AttrNumber) 2,
397  "access", TIMESTAMPTZOID, -1, 0);
398  TupleDescInitEntry(tupdesc, (AttrNumber) 3,
399  "modification", TIMESTAMPTZOID, -1, 0);
400  TupleDescInitEntry(tupdesc, (AttrNumber) 4,
401  "change", TIMESTAMPTZOID, -1, 0);
402  TupleDescInitEntry(tupdesc, (AttrNumber) 5,
403  "creation", TIMESTAMPTZOID, -1, 0);
404  TupleDescInitEntry(tupdesc, (AttrNumber) 6,
405  "isdir", BOOLOID, -1, 0);
406  BlessTupleDesc(tupdesc);
407 
408  memset(isnull, false, sizeof(isnull));
409 
410  values[0] = Int64GetDatum((int64) fst.st_size);
411  values[1] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_atime));
412  values[2] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_mtime));
413  /* Unix has file status change time, while Win32 has creation time */
414 #if !defined(WIN32) && !defined(__CYGWIN__)
415  values[3] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_ctime));
416  isnull[4] = true;
417 #else
418  isnull[3] = true;
419  values[4] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_ctime));
420 #endif
421  values[5] = BoolGetDatum(S_ISDIR(fst.st_mode));
422 
423  tuple = heap_form_tuple(tupdesc, values, isnull);
424 
425  pfree(filename);
426 
428 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:59
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2048
int errcode_for_file_access(void)
Definition: elog.c:593
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1699
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
#define ereport(elevel, rest)
Definition: elog.h:141
#define stat(a, b)
Definition: win32_port.h:255
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
TimestampTz time_t_to_timestamptz(pg_time_t tm)
Definition: timestamp.c:1703
#define BoolGetDatum(X)
Definition: postgres.h:402
#define PG_NARGS()
Definition: fmgr.h:198
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
#define S_ISDIR(m)
Definition: win32_port.h:296
static Datum values[MAXATTR]
Definition: bootstrap.c:167
static char * filename
Definition: pg_dumpall.c:91
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
int16 AttrNumber
Definition: attnum.h:21
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ pg_stat_file_1arg()

Datum pg_stat_file_1arg ( PG_FUNCTION_ARGS  )

Definition at line 438 of file genfile.c.

References pg_stat_file().

439 {
440  return pg_stat_file(fcinfo);
441 }
Datum pg_stat_file(PG_FUNCTION_ARGS)
Definition: genfile.c:362

◆ read_binary_file()

static bytea* read_binary_file ( const char *  filename,
int64  seek_offset,
int64  bytes_to_read,
bool  missing_ok 
)
static

Definition at line 111 of file genfile.c.

References AllocateFile(), buf, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FreeFile(), fseeko, MaxAllocSize, palloc(), PG_BINARY_R, SET_VARSIZE, stat, VARDATA, and VARHDRSZ.

Referenced by pg_read_binary_file(), and read_text_file().

113 {
114  bytea *buf;
115  size_t nbytes;
116  FILE *file;
117 
118  if (bytes_to_read < 0)
119  {
120  if (seek_offset < 0)
121  bytes_to_read = -seek_offset;
122  else
123  {
124  struct stat fst;
125 
126  if (stat(filename, &fst) < 0)
127  {
128  if (missing_ok && errno == ENOENT)
129  return NULL;
130  else
131  ereport(ERROR,
133  errmsg("could not stat file \"%s\": %m", filename)));
134  }
135 
136  bytes_to_read = fst.st_size - seek_offset;
137  }
138  }
139 
140  /* not sure why anyone thought that int64 length was a good idea */
141  if (bytes_to_read > (MaxAllocSize - VARHDRSZ))
142  ereport(ERROR,
143  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
144  errmsg("requested length too large")));
145 
146  if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
147  {
148  if (missing_ok && errno == ENOENT)
149  return NULL;
150  else
151  ereport(ERROR,
153  errmsg("could not open file \"%s\" for reading: %m",
154  filename)));
155  }
156 
157  if (fseeko(file, (off_t) seek_offset,
158  (seek_offset >= 0) ? SEEK_SET : SEEK_END) != 0)
159  ereport(ERROR,
161  errmsg("could not seek in file \"%s\": %m", filename)));
162 
163  buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
164 
165  nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
166 
167  if (ferror(file))
168  ereport(ERROR,
170  errmsg("could not read file \"%s\": %m", filename)));
171 
172  SET_VARSIZE(buf, nbytes + VARHDRSZ);
173 
174  FreeFile(file);
175 
176  return buf;
177 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARHDRSZ
Definition: c.h:555
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_BINARY_R
Definition: c.h:1193
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:68
int errcode_for_file_access(void)
Definition: elog.c:593
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2205
#define ereport(elevel, rest)
Definition: elog.h:141
#define MaxAllocSize
Definition: memutils.h:40
#define stat(a, b)
Definition: win32_port.h:255
#define fseeko(stream, offset, origin)
Definition: win32_port.h:201
size_t Size
Definition: c.h:466
int FreeFile(FILE *file)
Definition: fd.c:2404
static char * filename
Definition: pg_dumpall.c:91
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329

◆ read_text_file()

static text* read_text_file ( const char *  filename,
int64  seek_offset,
int64  bytes_to_read,
bool  missing_ok 
)
static

Definition at line 184 of file genfile.c.

References buf, pg_verifymbstr(), read_binary_file(), VARDATA, VARHDRSZ, and VARSIZE.

Referenced by pg_read_file(), and pg_read_file_v2().

186 {
187  bytea *buf;
188 
189  buf = read_binary_file(filename, seek_offset, bytes_to_read, missing_ok);
190 
191  if (buf != NULL)
192  {
193  /* Make sure the input is valid */
194  pg_verifymbstr(VARDATA(buf), VARSIZE(buf) - VARHDRSZ, false);
195 
196  /* OK, we can cast it to text safely */
197  return (text *) buf;
198  }
199  else
200  return NULL;
201 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:555
static bytea * read_binary_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:111
static char * buf
Definition: pg_test_fsync.c:68
static char * filename
Definition: pg_dumpall.c:91
Definition: c.h:549
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1914