Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * archive.c
4 : : * Routines to access WAL archives from frontend
5 : : *
6 : : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/fe_utils/archive.c
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : :
16 : : #include "postgres_fe.h"
17 : :
18 : : #include <unistd.h>
19 : : #include <sys/stat.h>
20 : :
21 : : #include "access/xlog_internal.h"
22 : : #include "common/archive.h"
23 : : #include "common/logging.h"
24 : : #include "fe_utils/archive.h"
25 : :
26 : :
27 : : /*
28 : : * RestoreArchivedFile
29 : : *
30 : : * Attempt to retrieve the specified file from off-line archival storage.
31 : : * If successful, return a file descriptor of the restored file, else
32 : : * return -1.
33 : : *
34 : : * For fixed-size files, the caller may pass the expected size as an
35 : : * additional crosscheck on successful recovery. If the file size is not
36 : : * known, set expectedSize = 0.
37 : : */
38 : : int
1474 michael@paquier.xyz 39 :CBC 1 : RestoreArchivedFile(const char *path, const char *xlogfname,
40 : : off_t expectedSize, const char *restoreCommand)
41 : : {
42 : : char xlogpath[MAXPGPATH];
43 : : char *xlogRestoreCmd;
44 : : int rc;
45 : : struct stat stat_buf;
46 : :
47 : 1 : snprintf(xlogpath, MAXPGPATH, "%s/" XLOGDIR "/%s", path, xlogfname);
48 : :
433 49 : 1 : xlogRestoreCmd = BuildRestoreCommand(restoreCommand, xlogpath,
50 : : xlogfname, NULL);
51 : :
52 : : /*
53 : : * Execute restore_command, which should copy the missing file from
54 : : * archival storage.
55 : : */
594 tgl@sss.pgh.pa.us 56 : 1 : fflush(NULL);
1474 michael@paquier.xyz 57 : 1 : rc = system(xlogRestoreCmd);
58 : 1 : pfree(xlogRestoreCmd);
59 : :
60 [ + - ]: 1 : if (rc == 0)
61 : : {
62 : : /*
63 : : * Command apparently succeeded, but let's make sure the file is
64 : : * really there now and has the correct size.
65 : : */
66 [ + - ]: 1 : if (stat(xlogpath, &stat_buf) == 0)
67 : : {
68 [ + - - + ]: 1 : if (expectedSize > 0 && stat_buf.st_size != expectedSize)
737 tgl@sss.pgh.pa.us 69 :UBC 0 : pg_fatal("unexpected file size for \"%s\": %lld instead of %lld",
70 : : xlogfname, (long long int) stat_buf.st_size,
71 : : (long long int) expectedSize);
72 : : else
73 : : {
1474 michael@paquier.xyz 74 :CBC 1 : int xlogfd = open(xlogpath, O_RDONLY | PG_BINARY, 0);
75 : :
76 [ - + ]: 1 : if (xlogfd < 0)
737 tgl@sss.pgh.pa.us 77 :UBC 0 : pg_fatal("could not open file \"%s\" restored from archive: %m",
78 : : xlogpath);
79 : : else
1474 michael@paquier.xyz 80 :CBC 1 : return xlogfd;
81 : : }
82 : : }
83 : : else
84 : : {
1474 michael@paquier.xyz 85 [ # # ]:UBC 0 : if (errno != ENOENT)
737 tgl@sss.pgh.pa.us 86 : 0 : pg_fatal("could not stat file \"%s\": %m",
87 : : xlogpath);
88 : : }
89 : : }
90 : :
91 : : /*
92 : : * If the failure was due to a signal, then it would be misleading to
93 : : * return with a failure at restoring the file. So just bail out and
94 : : * exit. Hard shell errors such as "command not found" are treated as
95 : : * fatal too.
96 : : */
1474 michael@paquier.xyz 97 [ # # ]: 0 : if (wait_result_is_any_signal(rc, true))
737 tgl@sss.pgh.pa.us 98 : 0 : pg_fatal("restore_command failed: %s",
99 : : wait_result_to_str(rc));
100 : :
101 : : /*
102 : : * The file is not available, so just let the caller decide what to do
103 : : * next.
104 : : */
1474 michael@paquier.xyz 105 : 0 : pg_log_error("could not restore file \"%s\" from archive",
106 : : xlogfname);
107 : 0 : return -1;
108 : : }
|