mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Fix two timeline handling bugs in pg_receivexlog.
When a timeline history file is fetched from server, it is initially created with a temporary file name, and renamed to place. However, the temporary file name was constructed using an uninitialized buffer. Usually that meant that the file was created in current directory instead of the target, which usually goes unnoticed, but if the target is on a different filesystem than the current dir, the rename() would fail. Fix that. The second issue is that pg_receivexlog would not take .partial files into account when determining when scanning the target directory for existing WAL files. If the timeline has switched in the server several times in the last WAL segment, and pg_receivexlog is restarted, it would choose a too old starting point. That's not a problem as long as the old WAL segment exists in the server and can be streamed over, but will cause a failure if it's not. Backpatch to 9.3, where this timeline handling code was written. Analysed by Andrew Gierth, bug #8453, based on a bug report on IRC.
This commit is contained in:
@ -166,8 +166,7 @@ close_walfile(char *basedir, char *partial_suffix)
|
||||
walfile = -1;
|
||||
|
||||
/*
|
||||
* Rename the .partial file only if we've completed writing the whole
|
||||
* segment or segment_complete is true.
|
||||
* If we finished writing a .partial file, rename it into place.
|
||||
*/
|
||||
if (currpos == XLOG_SEG_SIZE && partial_suffix)
|
||||
{
|
||||
@ -306,6 +305,8 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", basedir, histfname);
|
||||
|
||||
/*
|
||||
* Write into a temp file name.
|
||||
*/
|
||||
@ -356,8 +357,6 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
|
||||
/*
|
||||
* Now move the completed history file into place with its final name.
|
||||
*/
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", basedir, histfname);
|
||||
if (rename(tmppath, path) < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: could not rename file \"%s\" to \"%s\": %s\n"),
|
||||
|
Reference in New Issue
Block a user