diff --git a/src/archive.c b/src/archive.c index 6f9542d5..ad9e6a7b 100644 --- a/src/archive.c +++ b/src/archive.c @@ -22,7 +22,7 @@ * compute and validate checksums. */ int -do_archive_push(char *wal_file_path, char *wal_file_name) +do_archive_push(char *wal_file_path, char *wal_file_name, bool overwrite) { char backup_wal_file_path[MAXPGPATH]; char absolute_wal_file_path[MAXPGPATH]; @@ -62,8 +62,6 @@ do_archive_push(char *wal_file_path, char *wal_file_name) join_path_components(backup_wal_file_path, arclog_path, wal_file_name); elog(INFO, "pg_probackup archive-push from %s to %s", absolute_wal_file_path, backup_wal_file_path); - if (access(backup_wal_file_path, F_OK) != -1) - elog(ERROR, "file '%s', already exists.", backup_wal_file_path); #ifdef HAVE_LIBZ if (compress_alg == PGLZ_COMPRESS) @@ -72,7 +70,8 @@ do_archive_push(char *wal_file_path, char *wal_file_name) is_compress = IsXLogFileName(wal_file_name); #endif - push_wal_file(absolute_wal_file_path, backup_wal_file_path, is_compress); + push_wal_file(absolute_wal_file_path, backup_wal_file_path, is_compress, + overwrite); elog(INFO, "pg_probackup archive-push completed successfully"); return 0; diff --git a/src/backup.c b/src/backup.c index d58d236b..a28282de 100644 --- a/src/backup.c +++ b/src/backup.c @@ -1867,22 +1867,6 @@ checkpoint_timeout(void) return val_int; } -/* - * Return true if the path is a existing regular file. - */ -bool -fileExists(const char *path) -{ - struct stat buf; - - if (stat(path, &buf) == -1 && errno == ENOENT) - return false; - else if (!S_ISREG(buf.st_mode)) - return false; - else - return true; -} - /* * Notify end of backup to server when "backup_label" is in the root directory * of the DB cluster. diff --git a/src/data.c b/src/data.c index 6b03fd09..a0cbb308 100644 --- a/src/data.c +++ b/src/data.c @@ -758,7 +758,8 @@ copy_meta(const char *from_path, const char *to_path, bool unlink_on_error) * Copy WAL segment from pgdata to archive catalog with possible compression. */ void -push_wal_file(const char *from_path, const char *to_path, bool is_compress) +push_wal_file(const char *from_path, const char *to_path, bool is_compress, + bool overwrite) { FILE *in = NULL; FILE *out; @@ -781,6 +782,10 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress) if (is_compress) { snprintf(gz_to_path, sizeof(gz_to_path), "%s.gz", to_path); + + if (!overwrite && fileExists(gz_to_path)) + elog(ERROR, "WAL segment \"%s\" already exists.", gz_to_path); + gz_out = gzopen(gz_to_path, "wb"); if (gzsetparams(gz_out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK) elog(ERROR, "Cannot set compression level %d to file \"%s\": %s", @@ -791,6 +796,9 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress) else #endif { + if (!overwrite && fileExists(to_path)) + elog(ERROR, "WAL segment \"%s\" already exists.", to_path); + out = fopen(to_path, "w"); if (out == NULL) elog(ERROR, "Cannot open destination WAL file \"%s\": %s", diff --git a/src/dir.c b/src/dir.c index e199fd2a..9115a685 100644 --- a/src/dir.c +++ b/src/dir.c @@ -80,7 +80,6 @@ static char *pgdata_exclude_files[] = NULL }; -pgFile *pgFileNew(const char *path, bool omit_symlink); static int BlackListCompare(const void *str1, const void *str2); static void dir_list_file_internal(parray *files, const char *root, @@ -947,3 +946,19 @@ dir_is_empty(const char *path) return true; } + +/* + * Return true if the path is a existing regular file. + */ +bool +fileExists(const char *path) +{ + struct stat buf; + + if (stat(path, &buf) == -1 && errno == ENOENT) + return false; + else if (!S_ISREG(buf.st_mode)) + return false; + else + return true; +} diff --git a/src/help.c b/src/help.c index 072f2a82..cf8d5e83 100644 --- a/src/help.c +++ b/src/help.c @@ -127,6 +127,7 @@ help_pg_probackup(void) printf(_(" --wal-file-path=wal-file-path\n")); printf(_(" --wal-file-name=wal-file-name\n")); printf(_(" [--compress [--compress-level=compress-level]]\n")); + printf(_(" [--overwrite]\n")); printf(_("\n %s archive-get -B backup-dir --instance=instance_name\n"), PROGRAM_NAME); printf(_(" --wal-file-path=wal-file-path\n")); @@ -365,6 +366,7 @@ help_archive_push(void) printf(_(" --wal-file-path=wal-file-path\n")); printf(_(" --wal-file-name=wal-file-name\n")); printf(_(" [--compress [--compress-level=compress-level]]\n\n")); + printf(_(" [--overwrite]\n")); printf(_(" -B, --backup-path=backup-path location of the backup storage area\n")); printf(_(" --instance=instance_name name of the instance to delete\n")); @@ -375,6 +377,7 @@ help_archive_push(void) printf(_(" --compress compress WAL file during archiving\n")); printf(_(" --compress-level=compress-level\n")); printf(_(" level of compression [0-9]\n")); + printf(_(" --overwrite overwrite archived WAL file\n")); } static void diff --git a/src/pg_probackup.c b/src/pg_probackup.c index 5afe93f4..5e6bd99f 100644 --- a/src/pg_probackup.c +++ b/src/pg_probackup.c @@ -85,6 +85,7 @@ uint64 system_identifier = 0; /* archive push options */ static char *wal_file_path; static char *wal_file_name; +static bool file_overwrite = false; /* current settings */ pgBackup current; @@ -161,6 +162,7 @@ static pgut_option options[] = /* archive-push options */ { 's', 160, "wal-file-path", &wal_file_path, SOURCE_CMDLINE }, { 's', 161, "wal-file-name", &wal_file_name, SOURCE_CMDLINE }, + { 'b', 162, "overwrite", &file_overwrite, SOURCE_CMDLINE }, { 0 } }; @@ -410,7 +412,7 @@ main(int argc, char *argv[]) switch (backup_subcmd) { case ARCHIVE_PUSH: - return do_archive_push(wal_file_path, wal_file_name); + return do_archive_push(wal_file_path, wal_file_name, file_overwrite); case ARCHIVE_GET: return do_archive_get(wal_file_path, wal_file_name); case ADD_INSTANCE: diff --git a/src/pg_probackup.h b/src/pg_probackup.h index f09abe3e..3074f01b 100644 --- a/src/pg_probackup.h +++ b/src/pg_probackup.h @@ -316,7 +316,6 @@ extern const char *pgdata_exclude_dir[]; extern int do_backup(time_t start_time); extern BackupMode parse_backup_mode(const char *value); extern const char *deparse_backup_mode(BackupMode mode); -extern bool fileExists(const char *path); extern void process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno); @@ -343,7 +342,8 @@ extern int do_init(void); extern int do_add_instance(void); /* in archive.c */ -extern int do_archive_push(char *wal_file_path, char *wal_file_name); +extern int do_archive_push(char *wal_file_path, char *wal_file_name, + bool overwrite); extern int do_archive_get(char *wal_file_path, char *wal_file_name); @@ -409,6 +409,8 @@ extern parray *dir_read_file_list(const char *root, const char *file_txt); extern int dir_create_dir(const char *path, mode_t mode); extern bool dir_is_empty(const char *path); +extern bool fileExists(const char *path); + extern pgFile *pgFileNew(const char *path, bool omit_symlink); extern pgFile *pgFileInit(const char *path); extern void pgFileDelete(pgFile *file); @@ -428,7 +430,7 @@ extern void restore_data_file(const char *from_root, const char *to_root, extern bool copy_file(const char *from_root, const char *to_root, pgFile *file); extern void push_wal_file(const char *from_path, const char *to_path, - bool is_compress); + bool is_compress, bool overwrite); extern void get_wal_file(const char *from_path, const char *to_path); extern bool calc_file_checksum(pgFile *file);