Skip to content

Commit 2c711bd

Browse files
committed
[Issue #204] Make version check of remote agent more robust
1 parent 497f5b2 commit 2c711bd

File tree

5 files changed

+49
-65
lines changed

5 files changed

+49
-65
lines changed

src/fetch.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ slurpFile(const char *datadir, const char *path, size_t *filesize, bool safe, fi
4444
fullpath, strerror(errno));
4545
}
4646

47-
if (fio_fstat(fd, &statbuf) < 0)
47+
if (fio_stat(fullpath, &statbuf, true, location) < 0)
4848
{
4949
if (safe)
5050
return NULL;

src/pg_probackup.c

+2-11
Original file line numberDiff line numberDiff line change
@@ -343,16 +343,8 @@ main(int argc, char *argv[])
343343
else if (strcmp(argv[1], "ssh") == 0)
344344
launch_ssh(argv);
345345
#endif
346-
else if (strcmp(argv[1], "agent") == 0 && argc > 2)
346+
else if (strcmp(argv[1], "agent") == 0)
347347
{
348-
remote_agent = argv[2];
349-
if (strcmp(remote_agent, PROGRAM_VERSION) != 0)
350-
{
351-
uint32 agent_version = parse_program_version(remote_agent);
352-
elog(agent_version != AGENT_PROTOCOL_VERSION ? ERROR : WARNING,
353-
"Agent version %s doesn't match master pg_probackup version %s",
354-
PROGRAM_VERSION, remote_agent);
355-
}
356348
fio_communicate(STDIN_FILENO, STDOUT_FILENO);
357349
return 0;
358350
}
@@ -528,8 +520,7 @@ main(int argc, char *argv[])
528520
{
529521
/* Ensure that backup_path is a path to a directory */
530522
if (!S_ISDIR(st.st_mode))
531-
elog(ERROR, "-B, --backup-path must be a path to directory. Inode: %lu. ST_MODE: %u",
532-
st.st_ino, st.st_mode);
523+
elog(ERROR, "-B, --backup-path must be a path to directory");
533524
}
534525
}
535526
}

src/utils/file.c

+15-42
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,19 @@ static ssize_t fio_write_all(int fd, void const* buf, size_t size)
185185
return offs;
186186
}
187187

188+
/* Get version of remote agent */
189+
int fio_get_agent_version(void)
190+
{
191+
fio_header hdr;
192+
hdr.cop = FIO_AGENT_VERSION;
193+
hdr.size = 0;
194+
195+
IO_CHECK(fio_write_all(fio_stdout, &hdr, sizeof(hdr)), sizeof(hdr));
196+
IO_CHECK(fio_read_all(fio_stdin, &hdr, sizeof(hdr)), sizeof(hdr));
197+
198+
return hdr.arg;
199+
}
200+
188201
/* Open input stream. Remote file is fetched to the in-memory buffer and then accessed through Linux fmemopen */
189202
FILE* fio_open_stream(char const* path, fio_location location)
190203
{
@@ -728,44 +741,6 @@ ssize_t fio_read(int fd, void* buf, size_t size)
728741
}
729742
}
730743

731-
/* Get information about stdio file */
732-
int fio_ffstat(FILE* f, struct stat* st)
733-
{
734-
return fio_is_remote_file(f)
735-
? fio_fstat(fio_fileno(f), st)
736-
: fio_fstat(fileno(f), st);
737-
}
738-
739-
/* Get information about file descriptor */
740-
int fio_fstat(int fd, struct stat* st)
741-
{
742-
if (fio_is_remote_fd(fd))
743-
{
744-
fio_header hdr;
745-
746-
hdr.cop = FIO_FSTAT;
747-
hdr.handle = fd & ~FIO_PIPE_MARKER;
748-
hdr.size = 0;
749-
750-
IO_CHECK(fio_write_all(fio_stdout, &hdr, sizeof(hdr)), sizeof(hdr));
751-
752-
IO_CHECK(fio_read_all(fio_stdin, &hdr, sizeof(hdr)), sizeof(hdr));
753-
Assert(hdr.cop == FIO_FSTAT);
754-
IO_CHECK(fio_read_all(fio_stdin, st, sizeof(*st)), sizeof(*st));
755-
756-
if (hdr.arg != 0)
757-
{
758-
errno = hdr.arg;
759-
return -1;
760-
}
761-
return 0;
762-
}
763-
else
764-
{
765-
return fstat(fd, st);
766-
}
767-
}
768-
769744
/* Get information about file */
770745
int fio_stat(char const* path, struct stat* st, bool follow_symlink, fio_location location)
771746
{
@@ -2065,11 +2040,9 @@ void fio_communicate(int in, int out)
20652040
if (hdr.size != 0)
20662041
IO_CHECK(fio_write_all(out, buf, hdr.size), hdr.size);
20672042
break;
2068-
case FIO_FSTAT: /* Get information about opened file */
2069-
hdr.size = sizeof(st);
2070-
hdr.arg = fstat(fd[hdr.handle], &st) < 0 ? errno : 0;
2043+
case FIO_AGENT_VERSION:
2044+
hdr.arg = AGENT_PROTOCOL_VERSION;
20712045
IO_CHECK(fio_write_all(out, &hdr, sizeof(hdr)), sizeof(hdr));
2072-
IO_CHECK(fio_write_all(out, &st, sizeof(st)), sizeof(st));
20732046
break;
20742047
case FIO_STAT: /* Get information about file with specified path */
20752048
hdr.size = sizeof(st);

src/utils/file.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ typedef enum
2727
FIO_READ,
2828
FIO_LOAD,
2929
FIO_STAT,
30-
FIO_FSTAT,
3130
FIO_SEND,
3231
FIO_ACCESS,
3332
FIO_OPENDIR,
@@ -47,6 +46,8 @@ typedef enum
4746
/* messages for closing connection */
4847
FIO_DISCONNECT,
4948
FIO_DISCONNECTED,
49+
/* message for compatibility check */
50+
FIO_AGENT_VERSION
5051
} fio_operations;
5152

5253
typedef enum
@@ -79,6 +80,7 @@ extern fio_location MyLocation;
7980
extern void fio_redirect(int in, int out, int err);
8081
extern void fio_communicate(int in, int out);
8182

83+
extern int fio_get_agent_version(void);
8284
extern FILE* fio_fopen(char const* name, char const* mode, fio_location location);
8385
extern size_t fio_fwrite(FILE* f, void const* buf, size_t size);
8486
extern ssize_t fio_fwrite_compressed(FILE* f, void const* buf, size_t size, int compress_alg);

src/utils/remote.c

+28-10
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ bool launch_agent(void)
111111
int outfd[2];
112112
int infd[2];
113113
int errfd[2];
114+
int agent_version;
114115

115116
ssh_argc = 0;
116117
#ifdef WIN32
@@ -163,24 +164,24 @@ bool launch_agent(void)
163164
}
164165
}
165166
if (needs_quotes(instance_config.remote.path) || needs_quotes(PROGRAM_NAME_FULL))
166-
snprintf(cmd, sizeof(cmd), "\"%s\\%s\" agent %s",
167-
instance_config.remote.path, probackup, PROGRAM_VERSION);
167+
snprintf(cmd, sizeof(cmd), "\"%s\\%s\" agent",
168+
instance_config.remote.path, probackup);
168169
else
169-
snprintf(cmd, sizeof(cmd), "%s\\%s agent %s",
170-
instance_config.remote.path, probackup, PROGRAM_VERSION);
170+
snprintf(cmd, sizeof(cmd), "%s\\%s agent",
171+
instance_config.remote.path, probackup);
171172
#else
172173
if (needs_quotes(instance_config.remote.path) || needs_quotes(PROGRAM_NAME_FULL))
173-
snprintf(cmd, sizeof(cmd), "\"%s/%s\" agent %s",
174-
instance_config.remote.path, probackup, PROGRAM_VERSION);
174+
snprintf(cmd, sizeof(cmd), "\"%s/%s\" agent",
175+
instance_config.remote.path, probackup);
175176
else
176-
snprintf(cmd, sizeof(cmd), "%s/%s agent %s",
177-
instance_config.remote.path, probackup, PROGRAM_VERSION);
177+
snprintf(cmd, sizeof(cmd), "%s/%s agent",
178+
instance_config.remote.path, probackup);
178179
#endif
179180
} else {
180181
if (needs_quotes(PROGRAM_NAME_FULL))
181-
snprintf(cmd, sizeof(cmd), "\"%s\" agent %s", PROGRAM_NAME_FULL, PROGRAM_VERSION);
182+
snprintf(cmd, sizeof(cmd), "\"%s\" agent", PROGRAM_NAME_FULL);
182183
else
183-
snprintf(cmd, sizeof(cmd), "%s agent %s", PROGRAM_NAME_FULL, PROGRAM_VERSION);
184+
snprintf(cmd, sizeof(cmd), "%s agent", PROGRAM_NAME_FULL);
184185
}
185186

186187
#ifdef WIN32
@@ -228,5 +229,22 @@ bool launch_agent(void)
228229

229230
fio_redirect(infd[0], outfd[1], errfd[0]); /* write to stdout */
230231
}
232+
233+
/* Make sure that remote agent has the same version
234+
* TODO: we must also check PG version and fork edition
235+
*/
236+
agent_version = fio_get_agent_version();
237+
if (agent_version != AGENT_PROTOCOL_VERSION)
238+
{
239+
char agent_version_str[1024];
240+
sprintf(agent_version_str, "%d.%d.%d",
241+
agent_version / 10000,
242+
(agent_version / 100) % 100,
243+
agent_version % 100);
244+
245+
elog(ERROR, "Remote agent version %s does not match local program version %s",
246+
agent_version_str, PROGRAM_VERSION);
247+
}
248+
231249
return true;
232250
}

0 commit comments

Comments
 (0)