PostgreSQL Source Code  git master
genfile.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * genfile.c
4  * Functions for direct access to files
5  *
6  *
7  * Copyright (c) 2004-2018, PostgreSQL Global Development Group
8  *
9  * Author: Andreas Pflug <pgadmin@pse-consulting.de>
10  *
11  * IDENTIFICATION
12  * src/backend/utils/adt/genfile.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 
18 #include <sys/file.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <dirent.h>
22 
23 #include "access/htup_details.h"
24 #include "access/xlog_internal.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_type.h"
27 #include "funcapi.h"
28 #include "mb/pg_wchar.h"
29 #include "miscadmin.h"
30 #include "postmaster/syslogger.h"
31 #include "storage/fd.h"
32 #include "utils/builtins.h"
33 #include "utils/memutils.h"
34 #include "utils/timestamp.h"
35 
36 typedef struct
37 {
38  char *location;
39  DIR *dirdesc;
42 
43 
44 /*
45  * Convert a "text" filename argument to C string, and check it's allowable.
46  *
47  * Filename may be absolute or relative to the DataDir, but we only allow
48  * absolute paths that match DataDir or Log_directory.
49  *
50  * This does a privilege check against the 'pg_read_server_files' role, so
51  * this function is really only appropriate for callers who are only checking
52  * 'read' access. Do not use this function if you are looking for a check
53  * for 'write' or 'program' access without updating it to access the type
54  * of check as an argument and checking the appropriate role membership.
55  */
56 static char *
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 }
99 
100 
101 /*
102  * Read a section of a file, returning it as bytea
103  *
104  * Caller is responsible for all permissions checking.
105  *
106  * We read the whole of the file when bytes_to_read is negative.
107  */
108 static bytea *
109 read_binary_file(const char *filename, int64 seek_offset, int64 bytes_to_read,
110  bool missing_ok)
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 }
176 
177 /*
178  * Similar to read_binary_file, but we verify that the contents are valid
179  * in the database encoding.
180  */
181 static text *
182 read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read,
183  bool missing_ok)
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 }
200 
201 /*
202  * Read a section of a file, returning it as text
203  *
204  * This function is kept to support adminpack 1.0.
205  */
206 Datum
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 }
244 
245 /*
246  * Read a section of a file, returning it as text
247  *
248  * No superuser check done here- instead privileges are handled by the
249  * GRANT system.
250  */
251 Datum
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 }
283 
284 /*
285  * Read a section of a file, returning it as bytea
286  */
287 Datum
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 }
320 
321 
322 /*
323  * Wrapper functions for the 1 and 3 argument variants of pg_read_file_v2()
324  * and pg_binary_read_file().
325  *
326  * These are necessary to pass the sanity check in opr_sanity, which checks
327  * that all built-in functions that share the implementing C function take
328  * the same number of arguments.
329  */
330 Datum
332 {
333  return pg_read_file_v2(fcinfo);
334 }
335 
336 Datum
338 {
339  return pg_read_file_v2(fcinfo);
340 }
341 
342 Datum
344 {
345  return pg_read_binary_file(fcinfo);
346 }
347 
348 Datum
350 {
351  return pg_read_binary_file(fcinfo);
352 }
353 
354 /*
355  * stat a file
356  */
357 Datum
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 }
425 
426 /*
427  * stat a file (1 argument version)
428  *
429  * note: this wrapper is necessary to pass the sanity check in opr_sanity,
430  * which checks that all built-in functions that share the implementing C
431  * function take the same number of arguments
432  */
433 Datum
435 {
436  return pg_stat_file(fcinfo);
437 }
438 
439 /*
440  * List a directory (returns the filenames only)
441  */
442 Datum
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 }
507 
508 /*
509  * List a directory (1 argument version)
510  *
511  * note: this wrapper is necessary to pass the sanity check in opr_sanity,
512  * which checks that all built-in functions that share the implementing C
513  * function take the same number of arguments.
514  */
515 Datum
517 {
518  return pg_ls_dir(fcinfo);
519 }
520 
521 /* Generic function to return a directory listing of files */
522 static Datum
523 pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
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 }
599 
600 /* Function to return the list of files in the log directory */
601 Datum
603 {
604  return pg_ls_dir_files(fcinfo, Log_directory);
605 }
606 
607 /* Function to return the list of files in the WAL directory */
608 Datum
610 {
611  return pg_ls_dir_files(fcinfo, XLOGDIR);
612 }
Datum pg_ls_logdir(PG_FUNCTION_ARGS)
Definition: genfile.c:602
static char * convert_and_check_filename(text *arg)
Definition: genfile.c:57
int errhint(const char *fmt,...)
Definition: elog.c:987
#define VARDATA(PTR)
Definition: postgres.h:302
char * Log_directory
Definition: syslogger.c:67
Oid GetUserId(void)
Definition: miscinit.c:379
#define VARSIZE(PTR)
Definition: postgres.h:303
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:438
#define VARHDRSZ
Definition: c.h:522
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Datum pg_read_file_all(PG_FUNCTION_ARGS)
Definition: genfile.c:337
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void canonicalize_path(char *path)
Definition: path.c:254
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
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
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:244
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:335
bool include_dot_dirs
Definition: genfile.c:40
Definition: dirent.h:9
#define PG_BINARY_R
Definition: c.h:1082
bool path_contains_parent_reference(const char *path)
Definition: path.c:376
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
TupleDesc tuple_desc
Definition: funcapi.h:121
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
Definition: genfile.c:523
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
void pfree(void *pointer)
Definition: mcxt.c:1031
Datum pg_read_binary_file_off_len(PG_FUNCTION_ARGS)
Definition: genfile.c:343
Datum pg_stat_file(PG_FUNCTION_ARGS)
Definition: genfile.c:358
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
Datum pg_read_file_off_len(PG_FUNCTION_ARGS)
Definition: genfile.c:331
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32
#define MAXPGPATH
DIR * dirdesc
Definition: adminpack.c:60
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1109
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
int errcode_for_file_access(void)
Definition: elog.c:598
#define is_absolute_path(filename)
Definition: port.h:86
bool path_is_relative_and_below_cwd(const char *path)
Definition: path.c:405
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2346
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
Datum pg_read_binary_file(PG_FUNCTION_ARGS)
Definition: genfile.c:288
#define S_ISREG(m)
Definition: win32_port.h:310
Datum pg_ls_dir_1arg(PG_FUNCTION_ARGS)
Definition: genfile.c:516
#define MaxAllocSize
Definition: memutils.h:40
#define stat(a, b)
Definition: win32_port.h:266
Datum pg_ls_dir(PG_FUNCTION_ARGS)
Definition: genfile.c:443
#define XLOGDIR
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 fseeko(stream, offset, origin)
Definition: win32_port.h:212
#define BoolGetDatum(X)
Definition: postgres.h:385
Datum pg_read_file_v2(PG_FUNCTION_ARGS)
Definition: genfile.c:252
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4857
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:336
Datum pg_read_file(PG_FUNCTION_ARGS)
Definition: genfile.c:207
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
Datum pg_read_binary_file_all(PG_FUNCTION_ARGS)
Definition: genfile.c:349
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2666
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
size_t Size
Definition: c.h:433
Datum pg_stat_file_1arg(PG_FUNCTION_ARGS)
Definition: genfile.c:434
#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
char * location
Definition: adminpack.c:59
int FreeFile(FILE *file)
Definition: fd.c:2538
static Datum values[MAXATTR]
Definition: bootstrap.c:164
char * text_to_cstring(const text *t)
Definition: varlena.c:182
static char * filename
Definition: pg_dumpall.c:87
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
void * arg
char * DataDir
Definition: globals.c:63
Definition: c.h:516
#define PG_FUNCTION_ARGS
Definition: fmgr.h:163
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1866
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:327
char d_name[MAX_PATH]
Definition: dirent.h:14
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
int16 AttrNumber
Definition: attnum.h:21
#define PG_RETURN_NULL()
Definition: fmgr.h:310
int FreeDir(DIR *dir)
Definition: fd.c:2718
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
Datum pg_ls_waldir(PG_FUNCTION_ARGS)
Definition: genfile.c:609
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296