LCOV - code coverage report
Current view: top level - src/backend/archive - shell_archive.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 42 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 4 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 54 0

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * shell_archive.c
       4                 :             :  *
       5                 :             :  * This archiving function uses a user-specified shell command (the
       6                 :             :  * archive_command GUC) to copy write-ahead log files.  It is used as the
       7                 :             :  * default, but other modules may define their own custom archiving logic.
       8                 :             :  *
       9                 :             :  * Copyright (c) 2022-2026, PostgreSQL Global Development Group
      10                 :             :  *
      11                 :             :  * IDENTIFICATION
      12                 :             :  *        src/backend/archive/shell_archive.c
      13                 :             :  *
      14                 :             :  *-------------------------------------------------------------------------
      15                 :             :  */
      16                 :             : #include "postgres.h"
      17                 :             : 
      18                 :             : #include <sys/wait.h>
      19                 :             : 
      20                 :             : #include "access/xlog.h"
      21                 :             : #include "archive/archive_module.h"
      22                 :             : #include "archive/shell_archive.h"
      23                 :             : #include "common/percentrepl.h"
      24                 :             : #include "pgstat.h"
      25                 :             : 
      26                 :             : static bool shell_archive_configured(ArchiveModuleState *state);
      27                 :             : static bool shell_archive_file(ArchiveModuleState *state,
      28                 :             :                                                            const char *file,
      29                 :             :                                                            const char *path);
      30                 :             : static void shell_archive_shutdown(ArchiveModuleState *state);
      31                 :             : 
      32                 :             : static const ArchiveModuleCallbacks shell_archive_callbacks = {
      33                 :             :         .startup_cb = NULL,
      34                 :             :         .check_configured_cb = shell_archive_configured,
      35                 :             :         .archive_file_cb = shell_archive_file,
      36                 :             :         .shutdown_cb = shell_archive_shutdown
      37                 :             : };
      38                 :             : 
      39                 :             : const ArchiveModuleCallbacks *
      40                 :           0 : shell_archive_init(void)
      41                 :             : {
      42                 :           0 :         return &shell_archive_callbacks;
      43                 :             : }
      44                 :             : 
      45                 :             : static bool
      46                 :           0 : shell_archive_configured(ArchiveModuleState *state)
      47                 :             : {
      48         [ #  # ]:           0 :         if (XLogArchiveCommand[0] != '\0')
      49                 :           0 :                 return true;
      50                 :             : 
      51                 :           0 :         arch_module_check_errdetail("\"%s\" is not set.",
      52                 :             :                                                                 "archive_command");
      53                 :           0 :         return false;
      54                 :           0 : }
      55                 :             : 
      56                 :             : static bool
      57                 :           0 : shell_archive_file(ArchiveModuleState *state, const char *file,
      58                 :             :                                    const char *path)
      59                 :             : {
      60                 :           0 :         char       *xlogarchcmd;
      61                 :           0 :         char       *nativePath = NULL;
      62                 :           0 :         int                     rc;
      63                 :             : 
      64         [ #  # ]:           0 :         if (path)
      65                 :             :         {
      66                 :           0 :                 nativePath = pstrdup(path);
      67                 :           0 :                 make_native_path(nativePath);
      68                 :           0 :         }
      69                 :             : 
      70                 :           0 :         xlogarchcmd = replace_percent_placeholders(XLogArchiveCommand,
      71                 :             :                                                                                            "archive_command", "fp",
      72                 :           0 :                                                                                            file, nativePath);
      73                 :             : 
      74   [ #  #  #  # ]:           0 :         ereport(DEBUG3,
      75                 :             :                         (errmsg_internal("executing archive command \"%s\"",
      76                 :             :                                                          xlogarchcmd)));
      77                 :             : 
      78                 :           0 :         fflush(NULL);
      79                 :           0 :         pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
      80                 :           0 :         rc = system(xlogarchcmd);
      81                 :           0 :         pgstat_report_wait_end();
      82                 :             : 
      83         [ #  # ]:           0 :         if (rc != 0)
      84                 :             :         {
      85                 :             :                 /*
      86                 :             :                  * If either the shell itself, or a called command, died on a signal,
      87                 :             :                  * abort the archiver.  We do this because system() ignores SIGINT and
      88                 :             :                  * SIGQUIT while waiting; so a signal is very likely something that
      89                 :             :                  * should have interrupted us too.  Also die if the shell got a hard
      90                 :             :                  * "command not found" type of error.  If we overreact it's no big
      91                 :             :                  * deal, the postmaster will just start the archiver again.
      92                 :             :                  */
      93                 :           0 :                 int                     lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
      94                 :             : 
      95         [ #  # ]:           0 :                 if (WIFEXITED(rc))
      96                 :             :                 {
      97   [ #  #  #  #  :           0 :                         ereport(lev,
          #  #  #  #  #  
                      # ]
      98                 :             :                                         (errmsg("archive command failed with exit code %d",
      99                 :             :                                                         WEXITSTATUS(rc)),
     100                 :             :                                          errdetail("The failed archive command was: %s",
     101                 :             :                                                            xlogarchcmd)));
     102                 :           0 :                 }
     103   [ #  #  #  # ]:           0 :                 else if (WIFSIGNALED(rc))
     104                 :             :                 {
     105                 :             : #if defined(WIN32)
     106                 :             :                         ereport(lev,
     107                 :             :                                         (errmsg("archive command was terminated by exception 0x%X",
     108                 :             :                                                         WTERMSIG(rc)),
     109                 :             :                                          errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
     110                 :             :                                          errdetail("The failed archive command was: %s",
     111                 :             :                                                            xlogarchcmd)));
     112                 :             : #else
     113   [ #  #  #  #  :           0 :                         ereport(lev,
          #  #  #  #  #  
                      # ]
     114                 :             :                                         (errmsg("archive command was terminated by signal %d: %s",
     115                 :             :                                                         WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
     116                 :             :                                          errdetail("The failed archive command was: %s",
     117                 :             :                                                            xlogarchcmd)));
     118                 :             : #endif
     119                 :           0 :                 }
     120                 :             :                 else
     121                 :             :                 {
     122   [ #  #  #  #  :           0 :                         ereport(lev,
          #  #  #  #  #  
                      # ]
     123                 :             :                                         (errmsg("archive command exited with unrecognized status %d",
     124                 :             :                                                         rc),
     125                 :             :                                          errdetail("The failed archive command was: %s",
     126                 :             :                                                            xlogarchcmd)));
     127                 :             :                 }
     128                 :           0 :                 pfree(xlogarchcmd);
     129                 :             : 
     130                 :           0 :                 return false;
     131                 :           0 :         }
     132                 :           0 :         pfree(xlogarchcmd);
     133                 :             : 
     134   [ #  #  #  # ]:           0 :         elog(DEBUG1, "archived write-ahead log file \"%s\"", file);
     135                 :           0 :         return true;
     136                 :           0 : }
     137                 :             : 
     138                 :             : static void
     139                 :           0 : shell_archive_shutdown(ArchiveModuleState *state)
     140                 :             : {
     141   [ #  #  #  # ]:           0 :         elog(DEBUG1, "archiver process shutting down");
     142                 :           0 : }
        

Generated by: LCOV version 2.3.2-1