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_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/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)
 
Datum pg_ls_logdir (PG_FUNCTION_ARGS)
 
Datum pg_ls_waldir (PG_FUNCTION_ARGS)
 

Function Documentation

◆ convert_and_check_filename()

static char* convert_and_check_filename ( text arg)
static

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

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

◆ pg_ls_dir()

Datum pg_ls_dir ( PG_FUNCTION_ARGS  )

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

444 {
445  FuncCallContext *funcctx;
446  struct dirent *de;
447  directory_fctx *fctx;
448  MemoryContext oldcontext;
449 
450  if (SRF_IS_FIRSTCALL())
451  {
452  bool missing_ok = false;
453  bool include_dot_dirs = false;
454 
455  /* check the optional arguments */
456  if (PG_NARGS() == 3)
457  {
458  if (!PG_ARGISNULL(1))
459  missing_ok = PG_GETARG_BOOL(1);
460  if (!PG_ARGISNULL(2))
461  include_dot_dirs = PG_GETARG_BOOL(2);
462  }
463 
464  funcctx = SRF_FIRSTCALL_INIT();
465  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
466 
467  fctx = palloc(sizeof(directory_fctx));
469 
470  fctx->include_dot_dirs = include_dot_dirs;
471  fctx->dirdesc = AllocateDir(fctx->location);
472 
473  if (!fctx->dirdesc)
474  {
475  if (missing_ok && errno == ENOENT)
476  {
477  MemoryContextSwitchTo(oldcontext);
478  SRF_RETURN_DONE(funcctx);
479  }
480  else
481  ereport(ERROR,
483  errmsg("could not open directory \"%s\": %m",
484  fctx->location)));
485  }
486  funcctx->user_fctx = fctx;
487  MemoryContextSwitchTo(oldcontext);
488  }
489 
490  funcctx = SRF_PERCALL_SETUP();
491  fctx = (directory_fctx *) funcctx->user_fctx;
492 
493  while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
494  {
495  if (!fctx->include_dot_dirs &&
496  (strcmp(de->d_name, ".") == 0 ||
497  strcmp(de->d_name, "..") == 0))
498  continue;
499 
501  }
502 
503  FreeDir(fctx->dirdesc);
504 
505  SRF_RETURN_DONE(funcctx);
506 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:57
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:244
bool include_dot_dirs
Definition: genfile.c:40
Definition: dirent.h:9
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
#define ERROR
Definition: elog.h:43
DIR * dirdesc
Definition: adminpack.c:60
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2600
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2666
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
#define PG_NARGS()
Definition: fmgr.h:173
char * location
Definition: adminpack.c:59
void * user_fctx
Definition: funcapi.h:91
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2718
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296

◆ pg_ls_dir_1arg()

Datum pg_ls_dir_1arg ( PG_FUNCTION_ARGS  )

Definition at line 516 of file genfile.c.

References pg_ls_dir().

517 {
518  return pg_ls_dir(fcinfo);
519 }
Datum pg_ls_dir(PG_FUNCTION_ARGS)
Definition: genfile.c:443

◆ pg_ls_dir_files()

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

Definition at line 523 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_logdir(), and pg_ls_waldir().

524 {
525  FuncCallContext *funcctx;
526  struct dirent *de;
527  directory_fctx *fctx;
528 
529  if (SRF_IS_FIRSTCALL())
530  {
531  MemoryContext oldcontext;
532  TupleDesc tupdesc;
533 
534  funcctx = SRF_FIRSTCALL_INIT();
535  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
536 
537  fctx = palloc(sizeof(directory_fctx));
538 
539  tupdesc = CreateTemplateTupleDesc(3, false);
540  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
541  TEXTOID, -1, 0);
542  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "size",
543  INT8OID, -1, 0);
544  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "modification",
545  TIMESTAMPTZOID, -1, 0);
546  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
547 
548  fctx->location = pstrdup(dir);
549  fctx->dirdesc = AllocateDir(fctx->location);
550 
551  if (!fctx->dirdesc)
552  ereport(ERROR,
554  errmsg("could not open directory \"%s\": %m",
555  fctx->location)));
556 
557  funcctx->user_fctx = fctx;
558  MemoryContextSwitchTo(oldcontext);
559  }
560 
561  funcctx = SRF_PERCALL_SETUP();
562  fctx = (directory_fctx *) funcctx->user_fctx;
563 
564  while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
565  {
566  Datum values[3];
567  bool nulls[3];
568  char path[MAXPGPATH * 2];
569  struct stat attrib;
570  HeapTuple tuple;
571 
572  /* Skip hidden files */
573  if (de->d_name[0] == '.')
574  continue;
575 
576  /* Get the file info */
577  snprintf(path, sizeof(path), "%s/%s", fctx->location, de->d_name);
578  if (stat(path, &attrib) < 0)
579  ereport(ERROR,
581  errmsg("could not stat directory \"%s\": %m", dir)));
582 
583  /* Ignore anything but regular files */
584  if (!S_ISREG(attrib.st_mode))
585  continue;
586 
587  values[0] = CStringGetTextDatum(de->d_name);
588  values[1] = Int64GetDatum((int64) attrib.st_size);
589  values[2] = TimestampTzGetDatum(time_t_to_timestamptz(attrib.st_mtime));
590  memset(nulls, 0, sizeof(nulls));
591 
592  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
593  SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
594  }
595 
596  FreeDir(fctx->dirdesc);
597  SRF_RETURN_DONE(funcctx);
598 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
char * pstrdup(const char *in)
Definition: mcxt.c:1161
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
Definition: dirent.h:9
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
TupleDesc tuple_desc
Definition: funcapi.h:121
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
#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:1109
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2600
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1876
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:600
#define ereport(elevel, rest)
Definition: elog.h:122
#define S_ISREG(m)
Definition: win32_port.h:310
#define stat(a, b)
Definition: win32_port.h:266
uintptr_t Datum
Definition: postgres.h:365
TimestampTz time_t_to_timestamptz(pg_time_t tm)
Definition: timestamp.c:1670
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2666
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:231
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:45
char * location
Definition: adminpack.c:59
static Datum values[MAXATTR]
Definition: bootstrap.c:164
void * user_fctx
Definition: funcapi.h:91
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char d_name[MAX_PATH]
Definition: dirent.h:14
int16 AttrNumber
Definition: attnum.h:21
int FreeDir(DIR *dir)
Definition: fd.c:2718
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296

◆ pg_ls_logdir()

Datum pg_ls_logdir ( PG_FUNCTION_ARGS  )

Definition at line 602 of file genfile.c.

References Log_directory, and pg_ls_dir_files().

603 {
604  return pg_ls_dir_files(fcinfo, Log_directory);
605 }
char * Log_directory
Definition: syslogger.c:67
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
Definition: genfile.c:523

◆ pg_ls_waldir()

Datum pg_ls_waldir ( PG_FUNCTION_ARGS  )

Definition at line 609 of file genfile.c.

References pg_ls_dir_files(), and XLOGDIR.

610 {
611  return pg_ls_dir_files(fcinfo, XLOGDIR);
612 }
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
Definition: genfile.c:523
#define XLOGDIR

◆ pg_read_binary_file()

Datum pg_read_binary_file ( PG_FUNCTION_ARGS  )

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

289 {
290  text *filename_t = PG_GETARG_TEXT_PP(0);
291  int64 seek_offset = 0;
292  int64 bytes_to_read = -1;
293  bool missing_ok = false;
294  char *filename;
295  bytea *result;
296 
297  /* handle optional arguments */
298  if (PG_NARGS() >= 3)
299  {
300  seek_offset = PG_GETARG_INT64(1);
301  bytes_to_read = PG_GETARG_INT64(2);
302 
303  if (bytes_to_read < 0)
304  ereport(ERROR,
305  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
306  errmsg("requested length cannot be negative")));
307  }
308  if (PG_NARGS() >= 4)
309  missing_ok = PG_GETARG_BOOL(3);
310 
311  filename = convert_and_check_filename(filename_t);
312 
313  result = read_binary_file(filename, seek_offset,
314  bytes_to_read, missing_ok);
315  if (result)
316  PG_RETURN_BYTEA_P(result);
317  else
318  PG_RETURN_NULL();
319 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:57
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:244
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:335
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
#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:109
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_NARGS()
Definition: fmgr.h:173
static char * filename
Definition: pg_dumpall.c:87
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:516
#define PG_GETARG_INT64(n)
Definition: fmgr.h:252
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ pg_read_binary_file_all()

Datum pg_read_binary_file_all ( PG_FUNCTION_ARGS  )

Definition at line 349 of file genfile.c.

References pg_read_binary_file().

350 {
351  return pg_read_binary_file(fcinfo);
352 }
Datum pg_read_binary_file(PG_FUNCTION_ARGS)
Definition: genfile.c:288

◆ pg_read_binary_file_off_len()

Datum pg_read_binary_file_off_len ( PG_FUNCTION_ARGS  )

Definition at line 343 of file genfile.c.

References pg_read_binary_file().

344 {
345  return pg_read_binary_file(fcinfo);
346 }
Datum pg_read_binary_file(PG_FUNCTION_ARGS)
Definition: genfile.c:288

◆ pg_read_file()

Datum pg_read_file ( PG_FUNCTION_ARGS  )

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

208 {
209  text *filename_t = PG_GETARG_TEXT_PP(0);
210  int64 seek_offset = 0;
211  int64 bytes_to_read = -1;
212  bool missing_ok = false;
213  char *filename;
214  text *result;
215 
216  if (!superuser())
217  ereport(ERROR,
218  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
219  (errmsg("must be superuser to read files with adminpack 1.0"),
220  errhint("Consider using pg_file_read(), which is part of core, instead."))));
221 
222  /* handle optional arguments */
223  if (PG_NARGS() >= 3)
224  {
225  seek_offset = PG_GETARG_INT64(1);
226  bytes_to_read = PG_GETARG_INT64(2);
227 
228  if (bytes_to_read < 0)
229  ereport(ERROR,
230  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
231  errmsg("requested length cannot be negative")));
232  }
233  if (PG_NARGS() >= 4)
234  missing_ok = PG_GETARG_BOOL(3);
235 
236  filename = convert_and_check_filename(filename_t);
237 
238  result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok);
239  if (result)
240  PG_RETURN_TEXT_P(result);
241  else
242  PG_RETURN_NULL();
243 }
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:57
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:244
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:336
#define PG_NARGS()
Definition: fmgr.h:173
static char * filename
Definition: pg_dumpall.c:87
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:516
static text * read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read, bool missing_ok)
Definition: genfile.c:182
#define PG_GETARG_INT64(n)
Definition: fmgr.h:252
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ pg_read_file_all()

Datum pg_read_file_all ( PG_FUNCTION_ARGS  )

Definition at line 337 of file genfile.c.

References pg_read_file_v2().

338 {
339  return pg_read_file_v2(fcinfo);
340 }
Datum pg_read_file_v2(PG_FUNCTION_ARGS)
Definition: genfile.c:252

◆ pg_read_file_off_len()

Datum pg_read_file_off_len ( PG_FUNCTION_ARGS  )

Definition at line 331 of file genfile.c.

References pg_read_file_v2().

332 {
333  return pg_read_file_v2(fcinfo);
334 }
Datum pg_read_file_v2(PG_FUNCTION_ARGS)
Definition: genfile.c:252

◆ pg_read_file_v2()

Datum pg_read_file_v2 ( PG_FUNCTION_ARGS  )

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

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

◆ pg_stat_file()

Datum pg_stat_file ( PG_FUNCTION_ARGS  )

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

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

◆ pg_stat_file_1arg()

Datum pg_stat_file_1arg ( PG_FUNCTION_ARGS  )

Definition at line 434 of file genfile.c.

References pg_stat_file().

435 {
436  return pg_stat_file(fcinfo);
437 }
Datum pg_stat_file(PG_FUNCTION_ARGS)
Definition: genfile.c:358

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

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

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

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