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);
}
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');
'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
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;";
*
*-------------------------------------------------------------------------
*/
-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);
* 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
* 6 digits, a space, and a null, which is legal per POSIX.
*/
sprintf(&h[148], "%06o ", tarChecksum(h));
+
+ return TAR_OK;
}