summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/replication/basebackup.c21
-rw-r--r--src/bin/pg_basebackup/t/010_pg_basebackup.pl15
-rw-r--r--src/include/pgtar.h10
-rw-r--r--src/port/tar.c10
4 files changed, 52 insertions, 4 deletions
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 3058ce921b0..3563fd997fd 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -1258,11 +1258,30 @@ _tarWriteHeader(const char *filename, const char *linktarget,
struct stat * statbuf)
{
char h[512];
+ enum tarError rc;
- tarCreateHeader(h, filename, linktarget, statbuf->st_size,
+ rc = tarCreateHeader(h, filename, linktarget, statbuf->st_size,
statbuf->st_mode, statbuf->st_uid, statbuf->st_gid,
statbuf->st_mtime);
+ switch (rc)
+ {
+ case TAR_OK:
+ break;
+ case TAR_NAME_TOO_LONG:
+ ereport(ERROR,
+ (errmsg("file name too long for tar format: \"%s\"",
+ filename)));
+ break;
+ case TAR_SYMLINK_TOO_LONG:
+ ereport(ERROR,
+ (errmsg("symbolic link target too long for tar format: file name \"%s\", target \"%s\"",
+ filename, linktarget)));
+ break;
+ default:
+ elog(ERROR, "unrecognized tar error: %d", rc);
+ }
+
pq_putmessage('d', h, 512);
}
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index c966de0b741..7e9a776840c 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -2,7 +2,7 @@ use strict;
use warnings;
use Cwd;
use TestLib;
-use Test::More tests => 33;
+use Test::More tests => 35;
program_help_ok('pg_basebackup');
program_version_ok('pg_basebackup');
@@ -49,6 +49,13 @@ command_ok([ 'pg_basebackup', '-D', "$tempdir/tarbackup", '-Ft' ],
'tar format');
ok(-f "$tempdir/tarbackup/base.tar", 'backup tar was created');
+my $superlongname = "superlongname_" . ("x"x100);
+
+system_or_bail 'touch', "$tempdir/pgdata/$superlongname";
+command_fails([ 'pg_basebackup', '-D', "$tempdir/tarbackup_l1", '-Ft' ],
+ 'pg_basebackup tar with long name fails');
+unlink "$tempdir/pgdata/$superlongname";
+
# Create a temporary directory in the system location and symlink it
# to our physical temp location. That way we can use shorter names
# for the tablespace directories, which hopefully won't run afoul of
@@ -117,3 +124,9 @@ command_fails(
command_fails(
[ 'pg_basebackup', '-D', "$tempdir/backup_foo", '-Fp', "-Tfoo" ],
'-T with invalid format fails');
+
+mkdir "$tempdir/$superlongname";
+psql 'postgres', "CREATE TABLESPACE tblspc3 LOCATION '$tempdir/$superlongname';";
+command_fails([ 'pg_basebackup', '-D', "$tempdir/tarbackup_l3", '-Ft' ],
+ 'pg_basebackup tar with long symlink target fails');
+psql 'postgres', "DROP TABLESPACE tblspc3;";
diff --git a/src/include/pgtar.h b/src/include/pgtar.h
index 20e461091a2..906db7cebcb 100644
--- a/src/include/pgtar.h
+++ b/src/include/pgtar.h
@@ -11,5 +11,13 @@
*
*-------------------------------------------------------------------------
*/
-extern void tarCreateHeader(char *h, const char *filename, const char *linktarget, size_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime);
+
+enum tarError
+{
+ TAR_OK = 0,
+ TAR_NAME_TOO_LONG,
+ TAR_SYMLINK_TOO_LONG
+};
+
+extern enum tarError tarCreateHeader(char *h, const char *filename, const char *linktarget, size_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime);
extern int tarChecksum(char *header);
diff --git a/src/port/tar.c b/src/port/tar.c
index 8ef4f9c3883..4721df3ddc3 100644
--- a/src/port/tar.c
+++ b/src/port/tar.c
@@ -49,10 +49,16 @@ tarChecksum(char *header)
* must always have space for 512 characters, which is a requirement by
* the tar format.
*/
-void
+enum tarError
tarCreateHeader(char *h, const char *filename, const char *linktarget,
size_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
{
+ if (strlen(filename) > 99)
+ return TAR_NAME_TOO_LONG;
+
+ if (linktarget && strlen(linktarget) > 99)
+ return TAR_SYMLINK_TOO_LONG;
+
/*
* Note: most of the fields in a tar header are not supposed to be
* null-terminated. We use sprintf, which will write a null after the
@@ -141,4 +147,6 @@ tarCreateHeader(char *h, const char *filename, const char *linktarget,
* 6 digits, a space, and a null, which is legal per POSIX.
*/
sprintf(&h[148], "%06o ", tarChecksum(h));
+
+ return TAR_OK;
}