Since pg11 pg_read_file() and friends can be used with absolute paths as long as the user is superuser or explicitly granted the role pg_read_server_files.
I noticed that when trying to read a virtual file, e.g.:
SELECT pg_read_file('/proc/self/status');
the returned result is a zero length string.
However this works fine:
SELECT pg_read_file('/proc/self/status', 127, 128);
The reason for that is pg_read_file_v2() sets bytes_to_read=-1 if no offset and
length are supplied as arguments when it is called. It passes bytes_to_read down
to read_binary_file().
When the latter function sees bytes_to_read < 0 it tries to read the entire file
by getting the file size via stat, which returns 0 for a virtual file size.
The attached patch fixes this for me. I think it ought to be backpatched through
pg11.
Comments?
Joe
--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index ceaa618..101df3a 100644
*** a/src/backend/utils/adt/genfile.c
--- b/src/backend/utils/adt/genfile.c
***************
*** 36,41 ****
--- 36,42 ----
#include "utils/syscache.h"
#include "utils/timestamp.h"
+ #define READBUF_SIZE 4096
/*
* Convert a "text" filename argument to C string, and check it's allowable.
*************** read_binary_file(const char *filename, i
*** 106,112 ****
bool missing_ok)
{
bytea *buf;
! size_t nbytes;
FILE *file;
if (bytes_to_read < 0)
--- 107,113 ----
bool missing_ok)
{
bytea *buf;
! size_t nbytes = 0;
FILE *file;
if (bytes_to_read < 0)
*************** read_binary_file(const char *filename, i
*** 154,162 ****
(errcode_for_file_access(),
errmsg("could not seek in file \"%s\": %m", filename)));
! buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
! nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
if (ferror(file))
ereport(ERROR,
--- 155,187 ----
(errcode_for_file_access(),
errmsg("could not seek in file \"%s\": %m", filename)));
! if (bytes_to_read > 0)
! {
! buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
! nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
! }
! else
! {
! /* bytes_to_read can be <= zero if the file is a virtual file */
! StringInfoData sbuf;
! size_t rbytes = 0;
! char rbuf[READBUF_SIZE];
!
! initStringInfo(&sbuf);
! while (!feof(file))
! {
! memset(rbuf, '\0', READBUF_SIZE);
! rbytes = fread(rbuf, 1, (size_t) READBUF_SIZE, file);
! nbytes += rbytes;
!
! appendStringInfoString(&sbuf, rbuf);
! }
!
! Assert(nbytes == sbuf.len);
! buf = (bytea *) palloc((Size) nbytes + VARHDRSZ);
! memcpy(VARDATA(buf), sbuf.data, nbytes);
! }
if (ferror(file))
ereport(ERROR,
signature.asc
Description: OpenPGP digital signature
