LCOV - differential code coverage report
Current view: top level - contrib/adminpack - adminpack.c (source / functions) Coverage Total Hit UNC UIC UBC CBC EUB
Current: Differential Code Coverage HEAD vs 15 Lines: 45.7 % 173 79 1 7 86 79 8
Current Date: 2023-04-08 17:13:01 Functions: 70.8 % 24 17 1 6 17
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 0.0 % 1 0 1
Legend: Lines: hit not hit (240..) days: 45.9 % 172 79 7 86 79 7
Function coverage date bins:
(240..) days: 70.8 % 24 17 1 6 17

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * adminpack.c
                                  4                 :  *
                                  5                 :  *
                                  6                 :  * Copyright (c) 2002-2023, PostgreSQL Global Development Group
                                  7                 :  *
                                  8                 :  * Author: Andreas Pflug <pgadmin@pse-consulting.de>
                                  9                 :  *
                                 10                 :  * IDENTIFICATION
                                 11                 :  *    contrib/adminpack/adminpack.c
                                 12                 :  *
                                 13                 :  *-------------------------------------------------------------------------
                                 14                 :  */
                                 15                 : #include "postgres.h"
                                 16                 : 
                                 17                 : #include <sys/file.h>
                                 18                 : #include <sys/stat.h>
                                 19                 : #include <unistd.h>
                                 20                 : 
                                 21                 : #include "catalog/pg_authid.h"
                                 22                 : #include "catalog/pg_type.h"
                                 23                 : #include "funcapi.h"
                                 24                 : #include "miscadmin.h"
                                 25                 : #include "postmaster/syslogger.h"
                                 26                 : #include "storage/fd.h"
                                 27                 : #include "utils/acl.h"
                                 28                 : #include "utils/builtins.h"
                                 29                 : #include "utils/datetime.h"
                                 30                 : 
                                 31                 : 
                                 32                 : #ifdef WIN32
                                 33                 : 
                                 34                 : #ifdef rename
                                 35                 : #undef rename
                                 36                 : #endif
                                 37                 : 
                                 38                 : #ifdef unlink
                                 39                 : #undef unlink
                                 40                 : #endif
                                 41                 : #endif
                                 42                 : 
 6158 tgl                        43 CBC           1 : PG_MODULE_MAGIC;
                                 44                 : 
                                 45               1 : PG_FUNCTION_INFO_V1(pg_file_write);
 1829 sfrost                     46               4 : PG_FUNCTION_INFO_V1(pg_file_write_v1_1);
 1171 fujii                      47               2 : PG_FUNCTION_INFO_V1(pg_file_sync);
 6158 tgl                        48               1 : PG_FUNCTION_INFO_V1(pg_file_rename);
 1829 sfrost                     49               2 : PG_FUNCTION_INFO_V1(pg_file_rename_v1_1);
 6158 tgl                        50               1 : PG_FUNCTION_INFO_V1(pg_file_unlink);
 1829 sfrost                     51               2 : PG_FUNCTION_INFO_V1(pg_file_unlink_v1_1);
 6158 tgl                        52               1 : PG_FUNCTION_INFO_V1(pg_logdir_ls);
 1829 sfrost                     53               1 : PG_FUNCTION_INFO_V1(pg_logdir_ls_v1_1);
                                 54                 : 
                                 55                 : static int64 pg_file_write_internal(text *file, text *data, bool replace);
                                 56                 : static bool pg_file_rename_internal(text *file1, text *file2, text *file3);
                                 57                 : static Datum pg_logdir_ls_internal(FunctionCallInfo fcinfo);
                                 58                 : 
                                 59                 : 
                                 60                 : /*-----------------------
                                 61                 :  * some helper functions
                                 62                 :  */
                                 63                 : 
                                 64                 : /*
                                 65                 :  * Convert a "text" filename argument to C string, and check it's allowable.
                                 66                 :  *
                                 67                 :  * Filename may be absolute or relative to the DataDir, but we only allow
                                 68                 :  * absolute paths that match DataDir.
                                 69                 :  */
                                 70                 : static char *
 1150 michael                    71              23 : convert_and_check_filename(text *arg)
                                 72                 : {
 5493 tgl                        73              23 :     char       *filename = text_to_cstring(arg);
                                 74                 : 
 5998                            75              23 :     canonicalize_path(filename);    /* filename can change length here */
                                 76                 : 
                                 77                 :     /*
                                 78                 :      * Members of the 'pg_write_server_files' role are allowed to access any
                                 79                 :      * files on the server as the PG user, so no need to do any further checks
                                 80                 :      * here.
                                 81                 :      */
  377 mail                       82              23 :     if (has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
 1829 sfrost                     83              19 :         return filename;
                                 84                 : 
                                 85                 :     /*
                                 86                 :      * User isn't a member of the pg_write_server_files role, so check if it's
                                 87                 :      * allowable
                                 88                 :      */
 6158 tgl                        89               4 :     if (is_absolute_path(filename))
                                 90                 :     {
                                 91                 :         /* Allow absolute paths if within DataDir */
 1150 michael                    92               3 :         if (!path_is_prefix_of_path(DataDir, filename))
 4439 bruce                      93               2 :             ereport(ERROR,
                                 94                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 95                 :                      errmsg("absolute path not allowed")));
                                 96                 :     }
                                 97               1 :     else if (!path_is_relative_and_below_cwd(filename))
                                 98               1 :         ereport(ERROR,
                                 99                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                100                 :                  errmsg("path must be in or below the data directory")));
                                101                 : 
                                102               1 :     return filename;
                                103                 : }
                                104                 : 
                                105                 : 
                                106                 : /*
                                107                 :  * check for superuser, bark if not.
                                108                 :  */
                                109                 : static void
 6158 tgl                       110 UBC           0 : requireSuperuser(void)
                                111                 : {
                                112               0 :     if (!superuser())
 6031 bruce                     113               0 :         ereport(ERROR,
                                114                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                115                 :                  errmsg("only superuser may access generic file functions")));
 6158 tgl                       116               0 : }
                                117                 : 
                                118                 : 
                                119                 : 
                                120                 : /* ------------------------------------
                                121                 :  * pg_file_write - old version
                                122                 :  *
                                123                 :  * The superuser() check here must be kept as the library might be upgraded
                                124                 :  * without the extension being upgraded, meaning that in pre-1.1 installations
                                125                 :  * these functions could be called by any user.
                                126                 :  */
                                127                 : Datum
 6031 bruce                     128               0 : pg_file_write(PG_FUNCTION_ARGS)
                                129                 : {
 1829 sfrost                    130               0 :     text       *file = PG_GETARG_TEXT_PP(0);
                                131               0 :     text       *data = PG_GETARG_TEXT_PP(1);
                                132               0 :     bool        replace = PG_GETARG_BOOL(2);
 6031 bruce                     133               0 :     int64       count = 0;
                                134                 : 
 6158 tgl                       135               0 :     requireSuperuser();
                                136                 : 
 1829 sfrost                    137               0 :     count = pg_file_write_internal(file, data, replace);
                                138                 : 
                                139               0 :     PG_RETURN_INT64(count);
                                140                 : }
                                141                 : 
                                142                 : /* ------------------------------------
                                143                 :  * pg_file_write_v1_1 - Version 1.1
                                144                 :  *
                                145                 :  * As of adminpack version 1.1, we no longer need to check if the user
                                146                 :  * is a superuser because we REVOKE EXECUTE on the function from PUBLIC.
                                147                 :  * Users can then grant access to it based on their policies.
                                148                 :  *
                                149                 :  * Otherwise identical to pg_file_write (above).
                                150                 :  */
                                151                 : Datum
 1829 sfrost                    152 CBC           8 : pg_file_write_v1_1(PG_FUNCTION_ARGS)
                                153                 : {
                                154               8 :     text       *file = PG_GETARG_TEXT_PP(0);
                                155               8 :     text       *data = PG_GETARG_TEXT_PP(1);
                                156               8 :     bool        replace = PG_GETARG_BOOL(2);
                                157               8 :     int64       count = 0;
                                158                 : 
                                159               8 :     count = pg_file_write_internal(file, data, replace);
                                160                 : 
                                161               4 :     PG_RETURN_INT64(count);
                                162                 : }
                                163                 : 
                                164                 : /* ------------------------------------
                                165                 :  * pg_file_write_internal - Workhorse for pg_file_write functions.
                                166                 :  *
                                167                 :  * This handles the actual work for pg_file_write.
                                168                 :  */
                                169                 : static int64
                                170               8 : pg_file_write_internal(text *file, text *data, bool replace)
                                171                 : {
                                172                 :     FILE       *f;
                                173                 :     char       *filename;
                                174               8 :     int64       count = 0;
                                175                 : 
 1150 michael                   176               8 :     filename = convert_and_check_filename(file);
                                177                 : 
 1829 sfrost                    178               5 :     if (!replace)
                                179                 :     {
                                180                 :         struct stat fst;
                                181                 : 
 6158 tgl                       182               4 :         if (stat(filename, &fst) >= 0)
 6031 bruce                     183               1 :             ereport(ERROR,
                                184                 :                     (errcode(ERRCODE_DUPLICATE_FILE),
                                185                 :                      errmsg("file \"%s\" exists", filename)));
                                186                 : 
 2219 noah                      187               3 :         f = AllocateFile(filename, "wb");
                                188                 :     }
                                189                 :     else
                                190               1 :         f = AllocateFile(filename, "ab");
                                191                 : 
 6158 tgl                       192               4 :     if (!f)
 6158 tgl                       193 UBC           0 :         ereport(ERROR,
                                194                 :                 (errcode_for_file_access(),
                                195                 :                  errmsg("could not open file \"%s\" for writing: %m",
                                196                 :                         filename)));
                                197                 : 
 2219 noah                      198 CBC           4 :     count = fwrite(VARDATA_ANY(data), 1, VARSIZE_ANY_EXHDR(data), f);
                                199               4 :     if (count != VARSIZE_ANY_EXHDR(data) || FreeFile(f))
 2219 noah                      200 UBC           0 :         ereport(ERROR,
                                201                 :                 (errcode_for_file_access(),
                                202                 :                  errmsg("could not write file \"%s\": %m", filename)));
                                203                 : 
 1829 sfrost                    204 CBC           4 :     return (count);
                                205                 : }
                                206                 : 
                                207                 : /* ------------------------------------
                                208                 :  * pg_file_sync
                                209                 :  *
                                210                 :  * We REVOKE EXECUTE on the function from PUBLIC.
                                211                 :  * Users can then grant access to it based on their policies.
                                212                 :  */
                                213                 : Datum
 1171 fujii                     214               3 : pg_file_sync(PG_FUNCTION_ARGS)
                                215                 : {
                                216                 :     char       *filename;
                                217                 :     struct stat fst;
                                218                 : 
 1150 michael                   219               3 :     filename = convert_and_check_filename(PG_GETARG_TEXT_PP(0));
                                220                 : 
 1171 fujii                     221               3 :     if (stat(filename, &fst) < 0)
                                222               1 :         ereport(ERROR,
                                223                 :                 (errcode_for_file_access(),
                                224                 :                  errmsg("could not stat file \"%s\": %m", filename)));
                                225                 : 
                                226               2 :     fsync_fname_ext(filename, S_ISDIR(fst.st_mode), false, ERROR);
                                227                 : 
                                228               2 :     PG_RETURN_VOID();
                                229                 : }
                                230                 : 
                                231                 : /* ------------------------------------
                                232                 :  * pg_file_rename - old version
                                233                 :  *
                                234                 :  * The superuser() check here must be kept as the library might be upgraded
                                235                 :  * without the extension being upgraded, meaning that in pre-1.1 installations
                                236                 :  * these functions could be called by any user.
                                237                 :  */
                                238                 : Datum
 6031 bruce                     239 UBC           0 : pg_file_rename(PG_FUNCTION_ARGS)
                                240                 : {
                                241                 :     text       *file1;
                                242                 :     text       *file2;
                                243                 :     text       *file3;
                                244                 :     bool        result;
                                245                 : 
 6158 tgl                       246               0 :     requireSuperuser();
                                247                 : 
                                248               0 :     if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
                                249               0 :         PG_RETURN_NULL();
                                250                 : 
 1829 sfrost                    251               0 :     file1 = PG_GETARG_TEXT_PP(0);
                                252               0 :     file2 = PG_GETARG_TEXT_PP(1);
                                253                 : 
 6158 tgl                       254               0 :     if (PG_ARGISNULL(2))
 1829 sfrost                    255               0 :         file3 = NULL;
                                256                 :     else
                                257               0 :         file3 = PG_GETARG_TEXT_PP(2);
                                258                 : 
                                259               0 :     result = pg_file_rename_internal(file1, file2, file3);
                                260                 : 
                                261               0 :     PG_RETURN_BOOL(result);
                                262                 : }
                                263                 : 
                                264                 : /* ------------------------------------
                                265                 :  * pg_file_rename_v1_1 - Version 1.1
                                266                 :  *
                                267                 :  * As of adminpack version 1.1, we no longer need to check if the user
                                268                 :  * is a superuser because we REVOKE EXECUTE on the function from PUBLIC.
                                269                 :  * Users can then grant access to it based on their policies.
                                270                 :  *
                                271                 :  * Otherwise identical to pg_file_write (above).
                                272                 :  */
                                273                 : Datum
 1829 sfrost                    274 CBC           3 : pg_file_rename_v1_1(PG_FUNCTION_ARGS)
                                275                 : {
                                276                 :     text       *file1;
                                277                 :     text       *file2;
                                278                 :     text       *file3;
                                279                 :     bool        result;
                                280                 : 
                                281               3 :     if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
 1829 sfrost                    282 UBC           0 :         PG_RETURN_NULL();
                                283                 : 
 1829 sfrost                    284 CBC           3 :     file1 = PG_GETARG_TEXT_PP(0);
                                285               3 :     file2 = PG_GETARG_TEXT_PP(1);
                                286                 : 
                                287               3 :     if (PG_ARGISNULL(2))
                                288               2 :         file3 = NULL;
                                289                 :     else
                                290               1 :         file3 = PG_GETARG_TEXT_PP(2);
                                291                 : 
                                292               3 :     result = pg_file_rename_internal(file1, file2, file3);
                                293                 : 
                                294               3 :     PG_RETURN_BOOL(result);
                                295                 : }
                                296                 : 
                                297                 : /* ------------------------------------
                                298                 :  * pg_file_rename_internal - Workhorse for pg_file_rename functions.
                                299                 :  *
                                300                 :  * This handles the actual work for pg_file_rename.
                                301                 :  */
                                302                 : static bool
                                303               3 : pg_file_rename_internal(text *file1, text *file2, text *file3)
                                304                 : {
                                305                 :     char       *fn1,
                                306                 :                *fn2,
                                307                 :                *fn3;
                                308                 :     int         rc;
                                309                 : 
 1150 michael                   310               3 :     fn1 = convert_and_check_filename(file1);
                                311               3 :     fn2 = convert_and_check_filename(file2);
                                312                 : 
 1829 sfrost                    313               3 :     if (file3 == NULL)
 1820 tgl                       314               2 :         fn3 = NULL;
                                315                 :     else
 1150 michael                   316               1 :         fn3 = convert_and_check_filename(file3);
                                317                 : 
 6158 tgl                       318               3 :     if (access(fn1, W_OK) < 0)
                                319                 :     {
                                320               1 :         ereport(WARNING,
                                321                 :                 (errcode_for_file_access(),
                                322                 :                  errmsg("file \"%s\" is not accessible: %m", fn1)));
                                323                 : 
 1829 sfrost                    324               1 :         return false;
                                325                 :     }
                                326                 : 
 6158 tgl                       327               2 :     if (fn3 && access(fn2, W_OK) < 0)
                                328                 :     {
 6158 tgl                       329 UBC           0 :         ereport(WARNING,
                                330                 :                 (errcode_for_file_access(),
                                331                 :                  errmsg("file \"%s\" is not accessible: %m", fn2)));
                                332                 : 
 1829 sfrost                    333               0 :         return false;
                                334                 :     }
                                335                 : 
 1820 tgl                       336 CBC           2 :     rc = access(fn3 ? fn3 : fn2, W_OK);
 6158                           337               2 :     if (rc >= 0 || errno != ENOENT)
                                338                 :     {
 6158 tgl                       339 UBC           0 :         ereport(ERROR,
                                340                 :                 (errcode(ERRCODE_DUPLICATE_FILE),
                                341                 :                  errmsg("cannot rename to target file \"%s\"",
                                342                 :                         fn3 ? fn3 : fn2)));
                                343                 :     }
                                344                 : 
 6158 tgl                       345 CBC           2 :     if (fn3)
                                346                 :     {
 6031 bruce                     347               1 :         if (rename(fn2, fn3) != 0)
                                348                 :         {
 6158 tgl                       349 UBC           0 :             ereport(ERROR,
                                350                 :                     (errcode_for_file_access(),
                                351                 :                      errmsg("could not rename \"%s\" to \"%s\": %m",
                                352                 :                             fn2, fn3)));
                                353                 :         }
 6158 tgl                       354 CBC           1 :         if (rename(fn1, fn2) != 0)
                                355                 :         {
 6158 tgl                       356 UBC           0 :             ereport(WARNING,
                                357                 :                     (errcode_for_file_access(),
                                358                 :                      errmsg("could not rename \"%s\" to \"%s\": %m",
                                359                 :                             fn1, fn2)));
                                360                 : 
                                361               0 :             if (rename(fn3, fn2) != 0)
                                362                 :             {
                                363               0 :                 ereport(ERROR,
                                364                 :                         (errcode_for_file_access(),
                                365                 :                          errmsg("could not rename \"%s\" back to \"%s\": %m",
                                366                 :                                 fn3, fn2)));
                                367                 :             }
                                368                 :             else
                                369                 :             {
                                370               0 :                 ereport(ERROR,
                                371                 :                         (errcode(ERRCODE_UNDEFINED_FILE),
                                372                 :                          errmsg("renaming \"%s\" to \"%s\" was reverted",
                                373                 :                                 fn2, fn3)));
                                374                 :             }
                                375                 :         }
                                376                 :     }
 6158 tgl                       377 CBC           1 :     else if (rename(fn1, fn2) != 0)
                                378                 :     {
 6158 tgl                       379 UBC           0 :         ereport(ERROR,
                                380                 :                 (errcode_for_file_access(),
                                381                 :                  errmsg("could not rename \"%s\" to \"%s\": %m", fn1, fn2)));
                                382                 :     }
                                383                 : 
 1829 sfrost                    384 CBC           2 :     return true;
                                385                 : }
                                386                 : 
                                387                 : 
                                388                 : /* ------------------------------------
                                389                 :  * pg_file_unlink - old version
                                390                 :  *
                                391                 :  * The superuser() check here must be kept as the library might be upgraded
                                392                 :  * without the extension being upgraded, meaning that in pre-1.1 installations
                                393                 :  * these functions could be called by any user.
                                394                 :  */
                                395                 : Datum
 6031 bruce                     396 UBC           0 : pg_file_unlink(PG_FUNCTION_ARGS)
                                397                 : {
                                398                 :     char       *filename;
                                399                 : 
 6158 tgl                       400               0 :     requireSuperuser();
                                401                 : 
 1150 michael                   402               0 :     filename = convert_and_check_filename(PG_GETARG_TEXT_PP(0));
                                403                 : 
 6158 tgl                       404               0 :     if (access(filename, W_OK) < 0)
                                405                 :     {
 6031 bruce                     406               0 :         if (errno == ENOENT)
                                407               0 :             PG_RETURN_BOOL(false);
                                408                 :         else
                                409               0 :             ereport(ERROR,
                                410                 :                     (errcode_for_file_access(),
                                411                 :                      errmsg("file \"%s\" is not accessible: %m", filename)));
                                412                 :     }
                                413                 : 
 6158 tgl                       414               0 :     if (unlink(filename) < 0)
                                415                 :     {
                                416               0 :         ereport(WARNING,
                                417                 :                 (errcode_for_file_access(),
                                418                 :                  errmsg("could not unlink file \"%s\": %m", filename)));
                                419                 : 
                                420               0 :         PG_RETURN_BOOL(false);
                                421                 :     }
                                422               0 :     PG_RETURN_BOOL(true);
                                423                 : }
                                424                 : 
                                425                 : 
                                426                 : /* ------------------------------------
                                427                 :  * pg_file_unlink_v1_1 - Version 1.1
                                428                 :  *
                                429                 :  * As of adminpack version 1.1, we no longer need to check if the user
                                430                 :  * is a superuser because we REVOKE EXECUTE on the function from PUBLIC.
                                431                 :  * Users can then grant access to it based on their policies.
                                432                 :  *
                                433                 :  * Otherwise identical to pg_file_unlink (above).
                                434                 :  */
                                435                 : Datum
 1829 sfrost                    436 CBC           5 : pg_file_unlink_v1_1(PG_FUNCTION_ARGS)
                                437                 : {
                                438                 :     char       *filename;
                                439                 : 
 1150 michael                   440               5 :     filename = convert_and_check_filename(PG_GETARG_TEXT_PP(0));
                                441                 : 
 1829 sfrost                    442               5 :     if (access(filename, W_OK) < 0)
                                443                 :     {
                                444               2 :         if (errno == ENOENT)
                                445               2 :             PG_RETURN_BOOL(false);
                                446                 :         else
 1829 sfrost                    447 UBC           0 :             ereport(ERROR,
                                448                 :                     (errcode_for_file_access(),
                                449                 :                      errmsg("file \"%s\" is not accessible: %m", filename)));
                                450                 :     }
                                451                 : 
 1829 sfrost                    452 CBC           3 :     if (unlink(filename) < 0)
                                453                 :     {
 1829 sfrost                    454 UBC           0 :         ereport(WARNING,
                                455                 :                 (errcode_for_file_access(),
                                456                 :                  errmsg("could not unlink file \"%s\": %m", filename)));
                                457                 : 
                                458               0 :         PG_RETURN_BOOL(false);
                                459                 :     }
 1829 sfrost                    460 CBC           3 :     PG_RETURN_BOOL(true);
                                461                 : }
                                462                 : 
                                463                 : /* ------------------------------------
                                464                 :  * pg_logdir_ls - Old version
                                465                 :  *
                                466                 :  * The superuser() check here must be kept as the library might be upgraded
                                467                 :  * without the extension being upgraded, meaning that in pre-1.1 installations
                                468                 :  * these functions could be called by any user.
                                469                 :  */
                                470                 : Datum
 1829 sfrost                    471 UBC           0 : pg_logdir_ls(PG_FUNCTION_ARGS)
                                472                 : {
 6031 bruce                     473               0 :     if (!superuser())
 6158 tgl                       474               0 :         ereport(ERROR,
                                475                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                476                 :                  errmsg("only superuser can list the log directory")));
                                477                 : 
 1829 sfrost                    478               0 :     return (pg_logdir_ls_internal(fcinfo));
                                479                 : }
                                480                 : 
                                481                 : /* ------------------------------------
                                482                 :  * pg_logdir_ls_v1_1 - Version 1.1
                                483                 :  *
                                484                 :  * As of adminpack version 1.1, we no longer need to check if the user
                                485                 :  * is a superuser because we REVOKE EXECUTE on the function from PUBLIC.
                                486                 :  * Users can then grant access to it based on their policies.
                                487                 :  *
                                488                 :  * Otherwise identical to pg_logdir_ls (above).
                                489                 :  */
                                490                 : Datum
                                491               0 : pg_logdir_ls_v1_1(PG_FUNCTION_ARGS)
                                492                 : {
                                493               0 :     return (pg_logdir_ls_internal(fcinfo));
                                494                 : }
                                495                 : 
                                496                 : static Datum
                                497               0 : pg_logdir_ls_internal(FunctionCallInfo fcinfo)
                                498                 : {
 1119 tgl                       499               0 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
                                500                 :     bool        randomAccess;
                                501                 :     TupleDesc   tupdesc;
                                502                 :     Tuplestorestate *tupstore;
                                503                 :     AttInMetadata *attinmeta;
                                504                 :     DIR        *dirdesc;
                                505                 :     struct dirent *de;
                                506                 :     MemoryContext oldcontext;
                                507                 : 
 6015                           508               0 :     if (strcmp(Log_filename, "postgresql-%Y-%m-%d_%H%M%S.log") != 0)
 6158                           509               0 :         ereport(ERROR,
                                510                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                511                 :                  errmsg("the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'")));
                                512                 : 
                                513                 :     /* check to see if caller supports us returning a tuplestore */
 1119                           514               0 :     if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
                                515               0 :         ereport(ERROR,
                                516                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                517                 :                  errmsg("set-valued function called in context that cannot accept a set")));
                                518               0 :     if (!(rsinfo->allowedModes & SFRM_Materialize))
                                519               0 :         ereport(ERROR,
                                520                 :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                521                 :                  errmsg("materialize mode required, but it is not allowed in this context")));
                                522                 : 
                                523                 :     /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
                                524               0 :     oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
                                525                 : 
                                526               0 :     tupdesc = CreateTemplateTupleDesc(2);
                                527               0 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime",
                                528                 :                        TIMESTAMPOID, -1, 0);
                                529               0 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename",
                                530                 :                        TEXTOID, -1, 0);
                                531                 : 
                                532               0 :     randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
                                533               0 :     tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
                                534               0 :     rsinfo->returnMode = SFRM_Materialize;
                                535               0 :     rsinfo->setResult = tupstore;
                                536               0 :     rsinfo->setDesc = tupdesc;
                                537                 : 
                                538               0 :     MemoryContextSwitchTo(oldcontext);
                                539                 : 
                                540               0 :     attinmeta = TupleDescGetAttInMetadata(tupdesc);
                                541                 : 
                                542               0 :     dirdesc = AllocateDir(Log_directory);
                                543               0 :     while ((de = ReadDir(dirdesc, Log_directory)) != NULL)
                                544                 :     {
                                545                 :         char       *values[2];
                                546                 :         HeapTuple   tuple;
                                547                 :         char        timestampbuf[32];
                                548                 :         char       *field[MAXDATEFIELDS];
                                549                 :         char        lowstr[MAXDATELEN + 1];
                                550                 :         int         dtype;
                                551                 :         int         nf,
                                552                 :                     ftype[MAXDATEFIELDS];
                                553                 :         fsec_t      fsec;
 6031 bruce                     554               0 :         int         tz = 0;
                                555                 :         struct pg_tm date;
                                556                 :         DateTimeErrorExtra extra;
                                557                 : 
                                558                 :         /*
                                559                 :          * Default format: postgresql-YYYY-MM-DD_HHMMSS.log
                                560                 :          */
 6158 tgl                       561 UIC           0 :         if (strlen(de->d_name) != 32
 6015 tgl                       562 UBC           0 :             || strncmp(de->d_name, "postgresql-", 11) != 0
 6158                           563               0 :             || de->d_name[21] != '_'
 6015                           564               0 :             || strcmp(de->d_name + 28, ".log") != 0)
 6031 bruce                     565               0 :             continue;
 6158 tgl                       566 EUB             : 
                                567                 :         /* extract timestamp portion of filename */
 6015 tgl                       568 UIC           0 :         strcpy(timestampbuf, de->d_name + 11);
 6015 tgl                       569 UBC           0 :         timestampbuf[17] = '\0';
 6158 tgl                       570 EUB             : 
                                571                 :         /* parse and decode expected timestamp to verify it's OK format */
 6015 tgl                       572 UIC           0 :         if (ParseDateTime(timestampbuf, lowstr, MAXDATELEN, field, ftype, MAXDATEFIELDS, &nf))
 6031 bruce                     573 UBC           0 :             continue;
 6158 tgl                       574 EUB             : 
  121 tgl                       575 UNC           0 :         if (DecodeDateTime(field, ftype, nf,
                                576                 :                            &dtype, &date, &fsec, &tz, &extra))
 6031 bruce                     577 UBC           0 :             continue;
                                578                 : 
 6015 tgl                       579 EUB             :         /* Seems the timestamp is OK; prepare and return tuple */
                                580                 : 
 6015 tgl                       581 UIC           0 :         values[0] = timestampbuf;
 1119                           582               0 :         values[1] = psprintf("%s/%s", Log_directory, de->d_name);
 6158 tgl                       583 EUB             : 
 1119 tgl                       584 UBC           0 :         tuple = BuildTupleFromCStrings(attinmeta, values);
                                585                 : 
                                586               0 :         tuplestore_puttuple(tupstore, tuple);
                                587                 :     }
 6158 tgl                       588 EUB             : 
 1119 tgl                       589 UIC           0 :     FreeDir(dirdesc);
                                590               0 :     return (Datum) 0;
 6158 tgl                       591 EUB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a