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/acl.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.

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 53 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().

54 {
55  char *filename;
56 
57  filename = text_to_cstring(arg);
58  canonicalize_path(filename); /* filename can change length here */
59 
60  /*
61  * Members of the 'pg_read_server_files' role are allowed to access any
62  * files on the server as the PG user, so no need to do any further checks
63  * here.
64  */
65  if (is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_SERVER_FILES))
66  return filename;
67 
68  /* User isn't a member of the default role, so check if it's allowable */
69  if (is_absolute_path(filename))
70  {
71  /* Disallow '/a/b/data/..' */
72  if (path_contains_parent_reference(filename))
73  ereport(ERROR,
74  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
75  errmsg("reference to parent directory (\"..\") not allowed")));
76 
77  /*
78  * Allow absolute paths if within DataDir or Log_directory, even
79  * though Log_directory might be outside DataDir.
80  */
81  if (!path_is_prefix_of_path(DataDir, filename) &&
84  ereport(ERROR,
85  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
86  errmsg("absolute path not allowed")));
87  }
88  else if (!path_is_relative_and_below_cwd(filename))
89  ereport(ERROR,
90  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
91  errmsg("path must be in or below the current directory")));
92 
93  return filename;
94 }
char * Log_directory
Definition: syslogger.c:72
Oid GetUserId(void)
Definition: miscinit.c:448
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:610
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,...)
Definition: elog.h:144
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4916
char * text_to_cstring(const text *t)
Definition: varlena.c:205
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:824
char * DataDir
Definition: globals.c:62

◆ pg_ls_archive_statusdir()

Datum pg_ls_archive_statusdir ( PG_FUNCTION_ARGS  )

Definition at line 681 of file genfile.c.

References pg_ls_dir_files(), and XLOGDIR.

682 {
683  return pg_ls_dir_files(fcinfo, XLOGDIR "/archive_status", true);
684 }
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:538
#define XLOGDIR

◆ pg_ls_dir()

Datum pg_ls_dir ( PG_FUNCTION_ARGS  )

Definition at line 441 of file genfile.c.

References AllocateDir(), ReturnSetInfo::allowedModes, convert_and_check_filename(), CreateTemplateTupleDesc(), CStringGetTextDatum, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, FreeDir(), IsA, MemoryContextSwitchTo(), PG_ARGISNULL, PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_NARGS, ReadDir(), ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, TupleDescInitEntry(), tuplestore_begin_heap(), tuplestore_putvalues(), values, and work_mem.

Referenced by pg_ls_dir_1arg().

442 {
443  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
444  char *location;
445  bool missing_ok = false;
446  bool include_dot_dirs = false;
447  bool randomAccess;
448  TupleDesc tupdesc;
449  Tuplestorestate *tupstore;
450  DIR *dirdesc;
451  struct dirent *de;
452  MemoryContext oldcontext;
453 
455 
456  /* check the optional arguments */
457  if (PG_NARGS() == 3)
458  {
459  if (!PG_ARGISNULL(1))
460  missing_ok = PG_GETARG_BOOL(1);
461  if (!PG_ARGISNULL(2))
462  include_dot_dirs = PG_GETARG_BOOL(2);
463  }
464 
465  /* check to see if caller supports us returning a tuplestore */
466  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
467  ereport(ERROR,
468  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
469  errmsg("set-valued function called in context that cannot accept a set")));
470  if (!(rsinfo->allowedModes & SFRM_Materialize))
471  ereport(ERROR,
472  (errcode(ERRCODE_SYNTAX_ERROR),
473  errmsg("materialize mode required, but it is not allowed in this context")));
474 
475  /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
477 
478  tupdesc = CreateTemplateTupleDesc(1);
479  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_ls_dir", TEXTOID, -1, 0);
480 
481  randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
482  tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
483  rsinfo->returnMode = SFRM_Materialize;
484  rsinfo->setResult = tupstore;
485  rsinfo->setDesc = tupdesc;
486 
487  MemoryContextSwitchTo(oldcontext);
488 
489  dirdesc = AllocateDir(location);
490  if (!dirdesc)
491  {
492  /* Return empty tuplestore if appropriate */
493  if (missing_ok && errno == ENOENT)
494  return (Datum) 0;
495  /* Otherwise, we can let ReadDir() throw the error */
496  }
497 
498  while ((de = ReadDir(dirdesc, location)) != NULL)
499  {
500  Datum values[1];
501  bool nulls[1];
502 
503  if (!include_dot_dirs &&
504  (strcmp(de->d_name, ".") == 0 ||
505  strcmp(de->d_name, "..") == 0))
506  continue;
507 
508  values[0] = CStringGetTextDatum(de->d_name);
509  nulls[0] = false;
510 
511  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
512  }
513 
514  FreeDir(dirdesc);
515  return (Datum) 0;
516 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:53
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
Definition: dirent.h:9
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
uintptr_t Datum
Definition: postgres.h:367
int work_mem
Definition: globals.c:121
#define ereport(elevel,...)
Definition: elog.h:144
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2647
#define PG_NARGS()
Definition: fmgr.h:203
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Tuplestorestate * setResult
Definition: execnodes.h:310
static Datum values[MAXATTR]
Definition: bootstrap.c:167
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define CStringGetTextDatum(s)
Definition: builtins.h:87
int16 AttrNumber
Definition: attnum.h:21
int FreeDir(DIR *dir)
Definition: fd.c:2699

◆ pg_ls_dir_1arg()

Datum pg_ls_dir_1arg ( PG_FUNCTION_ARGS  )

Definition at line 526 of file genfile.c.

References pg_ls_dir().

527 {
528  return pg_ls_dir(fcinfo);
529 }
Datum pg_ls_dir(PG_FUNCTION_ARGS)
Definition: genfile.c:441

◆ pg_ls_dir_files()

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

Definition at line 538 of file genfile.c.

References AllocateDir(), ReturnSetInfo::allowedModes, CStringGetTextDatum, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elog, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, FreeDir(), get_call_result_type(), Int64GetDatum(), IsA, MAXPGPATH, MemoryContextSwitchTo(), ReadDir(), FunctionCallInfoBaseData::resultinfo, ReturnSetInfo::returnMode, S_ISREG, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, snprintf, stat, time_t_to_timestamptz(), TimestampTzGetDatum, tuplestore_begin_heap(), tuplestore_putvalues(), TYPEFUNC_COMPOSITE, values, and work_mem.

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

539 {
540  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
541  bool randomAccess;
542  TupleDesc tupdesc;
543  Tuplestorestate *tupstore;
544  DIR *dirdesc;
545  struct dirent *de;
546  MemoryContext oldcontext;
547 
548  /* check to see if caller supports us returning a tuplestore */
549  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
550  ereport(ERROR,
551  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
552  errmsg("set-valued function called in context that cannot accept a set")));
553  if (!(rsinfo->allowedModes & SFRM_Materialize))
554  ereport(ERROR,
555  (errcode(ERRCODE_SYNTAX_ERROR),
556  errmsg("materialize mode required, but it is not allowed in this context")));
557 
558  /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
560 
561  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
562  elog(ERROR, "return type must be a row type");
563 
564  randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
565  tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
566  rsinfo->returnMode = SFRM_Materialize;
567  rsinfo->setResult = tupstore;
568  rsinfo->setDesc = tupdesc;
569 
570  MemoryContextSwitchTo(oldcontext);
571 
572  /*
573  * Now walk the directory. Note that we must do this within a single SRF
574  * call, not leave the directory open across multiple calls, since we
575  * can't count on the SRF being run to completion.
576  */
577  dirdesc = AllocateDir(dir);
578  if (!dirdesc)
579  {
580  /* Return empty tuplestore if appropriate */
581  if (missing_ok && errno == ENOENT)
582  return (Datum) 0;
583  /* Otherwise, we can let ReadDir() throw the error */
584  }
585 
586  while ((de = ReadDir(dirdesc, dir)) != NULL)
587  {
588  Datum values[3];
589  bool nulls[3];
590  char path[MAXPGPATH * 2];
591  struct stat attrib;
592 
593  /* Skip hidden files */
594  if (de->d_name[0] == '.')
595  continue;
596 
597  /* Get the file info */
598  snprintf(path, sizeof(path), "%s/%s", dir, de->d_name);
599  if (stat(path, &attrib) < 0)
600  {
601  /* Ignore concurrently-deleted files, else complain */
602  if (errno == ENOENT)
603  continue;
604  ereport(ERROR,
606  errmsg("could not stat file \"%s\": %m", path)));
607  }
608 
609  /* Ignore anything but regular files */
610  if (!S_ISREG(attrib.st_mode))
611  continue;
612 
613  values[0] = CStringGetTextDatum(de->d_name);
614  values[1] = Int64GetDatum((int64) attrib.st_size);
615  values[2] = TimestampTzGetDatum(time_t_to_timestamptz(attrib.st_mtime));
616  memset(nulls, 0, sizeof(nulls));
617 
618  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
619  }
620 
621  FreeDir(dirdesc);
622  return (Datum) 0;
623 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
Definition: dirent.h:9
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
fmNodePtr resultinfo
Definition: fmgr.h:89
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:633
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1701
#define S_ISREG(m)
Definition: win32_port.h:299
#define stat(a, b)
Definition: win32_port.h:255
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
uintptr_t Datum
Definition: postgres.h:367
int work_mem
Definition: globals.c:121
TimestampTz time_t_to_timestamptz(pg_time_t tm)
Definition: timestamp.c:1703
#define ereport(elevel,...)
Definition: elog.h:144
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2647
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Tuplestorestate * setResult
Definition: execnodes.h:310
static Datum values[MAXATTR]
Definition: bootstrap.c:167
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
#define CStringGetTextDatum(s)
Definition: builtins.h:87
#define snprintf
Definition: port.h:193
int FreeDir(DIR *dir)
Definition: fd.c:2699

◆ pg_ls_logdir()

Datum pg_ls_logdir ( PG_FUNCTION_ARGS  )

Definition at line 627 of file genfile.c.

References Log_directory, and pg_ls_dir_files().

628 {
629  return pg_ls_dir_files(fcinfo, Log_directory, false);
630 }
char * Log_directory
Definition: syslogger.c:72
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:538

◆ pg_ls_tmpdir()

static Datum pg_ls_tmpdir ( FunctionCallInfo  fcinfo,
Oid  tblspc 
)
static

Definition at line 643 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().

644 {
645  char path[MAXPGPATH];
646 
648  ereport(ERROR,
649  (errcode(ERRCODE_UNDEFINED_OBJECT),
650  errmsg("tablespace with OID %u does not exist",
651  tblspc)));
652 
653  TempTablespacePath(path, tblspc);
654  return pg_ls_dir_files(fcinfo, path, true);
655 }
int errcode(int sqlerrcode)
Definition: elog.c:610
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1628
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:538
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ pg_ls_tmpdir_1arg()

Datum pg_ls_tmpdir_1arg ( PG_FUNCTION_ARGS  )

Definition at line 672 of file genfile.c.

References PG_GETARG_OID, and pg_ls_tmpdir().

673 {
674  return pg_ls_tmpdir(fcinfo, PG_GETARG_OID(0));
675 }
static Datum pg_ls_tmpdir(FunctionCallInfo fcinfo, Oid tblspc)
Definition: genfile.c:643
#define PG_GETARG_OID(n)
Definition: fmgr.h:275

◆ pg_ls_tmpdir_noargs()

Datum pg_ls_tmpdir_noargs ( PG_FUNCTION_ARGS  )

Definition at line 662 of file genfile.c.

References pg_ls_tmpdir().

663 {
664  return pg_ls_tmpdir(fcinfo, DEFAULTTABLESPACE_OID);
665 }
static Datum pg_ls_tmpdir(FunctionCallInfo fcinfo, Oid tblspc)
Definition: genfile.c:643

◆ pg_ls_waldir()

Datum pg_ls_waldir ( PG_FUNCTION_ARGS  )

Definition at line 634 of file genfile.c.

References pg_ls_dir_files(), and XLOGDIR.

635 {
636  return pg_ls_dir_files(fcinfo, XLOGDIR, false);
637 }
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
Definition: genfile.c:538
#define XLOGDIR

◆ pg_read_binary_file()

Datum pg_read_binary_file ( PG_FUNCTION_ARGS  )

Definition at line 286 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().

287 {
288  text *filename_t = PG_GETARG_TEXT_PP(0);
289  int64 seek_offset = 0;
290  int64 bytes_to_read = -1;
291  bool missing_ok = false;
292  char *filename;
293  bytea *result;
294 
295  /* handle optional arguments */
296  if (PG_NARGS() >= 3)
297  {
298  seek_offset = PG_GETARG_INT64(1);
299  bytes_to_read = PG_GETARG_INT64(2);
300 
301  if (bytes_to_read < 0)
302  ereport(ERROR,
303  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
304  errmsg("requested length cannot be negative")));
305  }
306  if (PG_NARGS() >= 4)
307  missing_ok = PG_GETARG_BOOL(3);
308 
309  filename = convert_and_check_filename(filename_t);
310 
311  result = read_binary_file(filename, seek_offset,
312  bytes_to_read, missing_ok);
313  if (result)
314  PG_RETURN_BYTEA_P(result);
315  else
316  PG_RETURN_NULL();
317 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:53
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:369
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
#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:105
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_NARGS()
Definition: fmgr.h:203
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: c.h:555
#define PG_GETARG_INT64(n)
Definition: fmgr.h:282
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ pg_read_binary_file_all()

Datum pg_read_binary_file_all ( 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:286

◆ pg_read_binary_file_off_len()

Datum pg_read_binary_file_off_len ( PG_FUNCTION_ARGS  )

Definition at line 341 of file genfile.c.

References pg_read_binary_file().

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

◆ pg_read_file()

Datum pg_read_file ( PG_FUNCTION_ARGS  )

Definition at line 203 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().

204 {
205  text *filename_t = PG_GETARG_TEXT_PP(0);
206  int64 seek_offset = 0;
207  int64 bytes_to_read = -1;
208  bool missing_ok = false;
209  char *filename;
210  text *result;
211 
212  if (!superuser())
213  ereport(ERROR,
214  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
215  errmsg("must be superuser to read files with adminpack 1.0"),
216  /* translator: %s is a SQL function name */
217  errhint("Consider using %s, which is part of core, instead.",
218  "pg_file_read()")));
219 
220  /* handle optional arguments */
221  if (PG_NARGS() >= 3)
222  {
223  seek_offset = PG_GETARG_INT64(1);
224  bytes_to_read = PG_GETARG_INT64(2);
225 
226  if (bytes_to_read < 0)
227  ereport(ERROR,
228  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
229  errmsg("requested length cannot be negative")));
230  }
231  if (PG_NARGS() >= 4)
232  missing_ok = PG_GETARG_BOOL(3);
233 
234  filename = convert_and_check_filename(filename_t);
235 
236  result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok);
237  if (result)
238  PG_RETURN_TEXT_P(result);
239  else
240  PG_RETURN_NULL();
241 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:53
int errhint(const char *fmt,...)
Definition: elog.c:1071
int errcode(int sqlerrcode)
Definition: elog.c:610
bool superuser(void)
Definition: superuser.c:46
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
#define PG_NARGS()
Definition: fmgr.h:203
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: c.h:555
static text * read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:178
#define PG_GETARG_INT64(n)
Definition: fmgr.h:282
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ pg_read_file_all()

Datum pg_read_file_all ( 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:250

◆ pg_read_file_off_len()

Datum pg_read_file_off_len ( PG_FUNCTION_ARGS  )

Definition at line 329 of file genfile.c.

References pg_read_file_v2().

330 {
331  return pg_read_file_v2(fcinfo);
332 }
Datum pg_read_file_v2(PG_FUNCTION_ARGS)
Definition: genfile.c:250

◆ pg_read_file_v2()

Datum pg_read_file_v2 ( PG_FUNCTION_ARGS  )

Definition at line 250 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().

251 {
252  text *filename_t = PG_GETARG_TEXT_PP(0);
253  int64 seek_offset = 0;
254  int64 bytes_to_read = -1;
255  bool missing_ok = false;
256  char *filename;
257  text *result;
258 
259  /* handle optional arguments */
260  if (PG_NARGS() >= 3)
261  {
262  seek_offset = PG_GETARG_INT64(1);
263  bytes_to_read = PG_GETARG_INT64(2);
264 
265  if (bytes_to_read < 0)
266  ereport(ERROR,
267  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
268  errmsg("requested length cannot be negative")));
269  }
270  if (PG_NARGS() >= 4)
271  missing_ok = PG_GETARG_BOOL(3);
272 
273  filename = convert_and_check_filename(filename_t);
274 
275  result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok);
276  if (result)
277  PG_RETURN_TEXT_P(result);
278  else
279  PG_RETURN_NULL();
280 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:53
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
#define PG_NARGS()
Definition: fmgr.h:203
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: c.h:555
static text * read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:178
#define PG_GETARG_INT64(n)
Definition: fmgr.h:282
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ pg_stat_file()

Datum pg_stat_file ( PG_FUNCTION_ARGS  )

Definition at line 356 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().

357 {
358  text *filename_t = PG_GETARG_TEXT_PP(0);
359  char *filename;
360  struct stat fst;
361  Datum values[6];
362  bool isnull[6];
363  HeapTuple tuple;
364  TupleDesc tupdesc;
365  bool missing_ok = false;
366 
367  /* check the optional argument */
368  if (PG_NARGS() == 2)
369  missing_ok = PG_GETARG_BOOL(1);
370 
371  filename = convert_and_check_filename(filename_t);
372 
373  if (stat(filename, &fst) < 0)
374  {
375  if (missing_ok && errno == ENOENT)
376  PG_RETURN_NULL();
377  else
378  ereport(ERROR,
380  errmsg("could not stat file \"%s\": %m", filename)));
381  }
382 
383  /*
384  * This record type had better match the output parameters declared for me
385  * in pg_proc.h.
386  */
387  tupdesc = CreateTemplateTupleDesc(6);
388  TupleDescInitEntry(tupdesc, (AttrNumber) 1,
389  "size", INT8OID, -1, 0);
390  TupleDescInitEntry(tupdesc, (AttrNumber) 2,
391  "access", TIMESTAMPTZOID, -1, 0);
392  TupleDescInitEntry(tupdesc, (AttrNumber) 3,
393  "modification", TIMESTAMPTZOID, -1, 0);
394  TupleDescInitEntry(tupdesc, (AttrNumber) 4,
395  "change", TIMESTAMPTZOID, -1, 0);
396  TupleDescInitEntry(tupdesc, (AttrNumber) 5,
397  "creation", TIMESTAMPTZOID, -1, 0);
398  TupleDescInitEntry(tupdesc, (AttrNumber) 6,
399  "isdir", BOOLOID, -1, 0);
400  BlessTupleDesc(tupdesc);
401 
402  memset(isnull, false, sizeof(isnull));
403 
404  values[0] = Int64GetDatum((int64) fst.st_size);
405  values[1] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_atime));
406  values[2] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_mtime));
407  /* Unix has file status change time, while Win32 has creation time */
408 #if !defined(WIN32) && !defined(__CYGWIN__)
409  values[3] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_ctime));
410  isnull[4] = true;
411 #else
412  isnull[3] = true;
413  values[4] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_ctime));
414 #endif
415  values[5] = BoolGetDatum(S_ISDIR(fst.st_mode));
416 
417  tuple = heap_form_tuple(tupdesc, values, isnull);
418 
419  pfree(filename);
420 
422 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:53
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:274
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
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:2052
int errcode_for_file_access(void)
Definition: elog.c:633
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1701
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
#define stat(a, b)
Definition: win32_port.h:255
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352
TimestampTz time_t_to_timestamptz(pg_time_t tm)
Definition: timestamp.c:1703
#define BoolGetDatum(X)
Definition: postgres.h:402
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_NARGS()
Definition: fmgr.h:203
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:220
#define S_ISDIR(m)
Definition: win32_port.h:296
static Datum values[MAXATTR]
Definition: bootstrap.c:167
static char * filename
Definition: pg_dumpall.c:90
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: c.h:555
int16 AttrNumber
Definition: attnum.h:21
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ pg_stat_file_1arg()

Datum pg_stat_file_1arg ( PG_FUNCTION_ARGS  )

Definition at line 432 of file genfile.c.

References pg_stat_file().

433 {
434  return pg_stat_file(fcinfo);
435 }
Datum pg_stat_file(PG_FUNCTION_ARGS)
Definition: genfile.c:356

◆ 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 105 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().

107 {
108  bytea *buf;
109  size_t nbytes;
110  FILE *file;
111 
112  if (bytes_to_read < 0)
113  {
114  if (seek_offset < 0)
115  bytes_to_read = -seek_offset;
116  else
117  {
118  struct stat fst;
119 
120  if (stat(filename, &fst) < 0)
121  {
122  if (missing_ok && errno == ENOENT)
123  return NULL;
124  else
125  ereport(ERROR,
127  errmsg("could not stat file \"%s\": %m", filename)));
128  }
129 
130  bytes_to_read = fst.st_size - seek_offset;
131  }
132  }
133 
134  /* not sure why anyone thought that int64 length was a good idea */
135  if (bytes_to_read > (MaxAllocSize - VARHDRSZ))
136  ereport(ERROR,
137  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
138  errmsg("requested length too large")));
139 
140  if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
141  {
142  if (missing_ok && errno == ENOENT)
143  return NULL;
144  else
145  ereport(ERROR,
147  errmsg("could not open file \"%s\" for reading: %m",
148  filename)));
149  }
150 
151  if (fseeko(file, (off_t) seek_offset,
152  (seek_offset >= 0) ? SEEK_SET : SEEK_END) != 0)
153  ereport(ERROR,
155  errmsg("could not seek in file \"%s\": %m", filename)));
156 
157  buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
158 
159  nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
160 
161  if (ferror(file))
162  ereport(ERROR,
164  errmsg("could not read file \"%s\": %m", filename)));
165 
166  SET_VARSIZE(buf, nbytes + VARHDRSZ);
167 
168  FreeFile(file);
169 
170  return buf;
171 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARHDRSZ
Definition: c.h:561
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_BINARY_R
Definition: c.h:1236
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
int errcode_for_file_access(void)
Definition: elog.c:633
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2320
#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
#define ereport(elevel,...)
Definition: elog.h:144
size_t Size
Definition: c.h:466
int FreeFile(FILE *file)
Definition: fd.c:2519
static char * filename
Definition: pg_dumpall.c:90
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: c.h:555
#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 178 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().

180 {
181  bytea *buf;
182 
183  buf = read_binary_file(filename, seek_offset, bytes_to_read, missing_ok);
184 
185  if (buf != NULL)
186  {
187  /* Make sure the input is valid */
188  pg_verifymbstr(VARDATA(buf), VARSIZE(buf) - VARHDRSZ, false);
189 
190  /* OK, we can cast it to text safely */
191  return (text *) buf;
192  }
193  else
194  return NULL;
195 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:561
static bytea * read_binary_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:105
static char * buf
Definition: pg_test_fsync.c:67
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1446
static char * filename
Definition: pg_dumpall.c:90
Definition: c.h:555