Skip to content

Commit f5d4bdd

Browse files
committed
Unify some tar functionality across different parts
Move some of the tar functionality that existed mostly duplicated in both pg_dump and the walsender basebackup functionality into port/tar.c instead, so it can be used from both. It will also be used by pg_basebackup in the future, which would've caused a third copy of it around. Zoltan Boszormenyi and Magnus Hagander
1 parent a266f7d commit f5d4bdd

File tree

5 files changed

+154
-228
lines changed

5 files changed

+154
-228
lines changed

src/backend/replication/basebackup.c

Lines changed: 3 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -740,49 +740,13 @@ sendDir(char *path, int basepathlen, bool sizeonly)
740740
*/
741741

742742

743-
/*
744-
* Utility routine to print possibly larger than 32 bit integers in a
745-
* portable fashion. Filled with zeros.
746-
*/
747-
static void
748-
print_val(char *s, uint64 val, unsigned int base, size_t len)
749-
{
750-
int i;
751-
752-
for (i = len; i > 0; i--)
753-
{
754-
int digit = val % base;
755-
756-
s[i - 1] = '0' + digit;
757-
val = val / base;
758-
}
759-
}
760-
761743
/*
762744
* Maximum file size for a tar member: The limit inherent in the
763745
* format is 2^33-1 bytes (nearly 8 GB). But we don't want to exceed
764746
* what we can represent in pgoff_t.
765747
*/
766748
#define MAX_TAR_MEMBER_FILELEN (((int64) 1 << Min(33, sizeof(pgoff_t)*8 - 1)) - 1)
767749

768-
static int
769-
_tarChecksum(char *header)
770-
{
771-
int i,
772-
sum;
773-
774-
/*
775-
* Per POSIX, the checksum is the simple sum of all bytes in the header,
776-
* treating the bytes as unsigned, and treating the checksum field (at
777-
* offset 148) as though it contained 8 spaces.
778-
*/
779-
sum = 8 * ' '; /* presumed value for checksum field */
780-
for (i = 0; i < 512; i++)
781-
if (i < 148 || i >= 156)
782-
sum += 0xFF & header[i];
783-
return sum;
784-
}
785-
786750
/*
787751
* Given the member, write the TAR header & send the file.
788752
*
@@ -874,95 +838,9 @@ _tarWriteHeader(const char *filename, const char *linktarget,
874838
{
875839
char h[512];
876840

877-
/*
878-
* Note: most of the fields in a tar header are not supposed to be
879-
* null-terminated. We use sprintf, which will write a null after the
880-
* required bytes; that null goes into the first byte of the next field.
881-
* This is okay as long as we fill the fields in order.
882-
*/
883-
memset(h, 0, sizeof(h));
884-
885-
/* Name 100 */
886-
sprintf(&h[0], "%.99s", filename);
887-
if (linktarget != NULL || S_ISDIR(statbuf->st_mode))
888-
{
889-
/*
890-
* We only support symbolic links to directories, and this is
891-
* indicated in the tar format by adding a slash at the end of the
892-
* name, the same as for regular directories.
893-
*/
894-
int flen = strlen(filename);
895-
896-
flen = Min(flen, 99);
897-
h[flen] = '/';
898-
h[flen + 1] = '\0';
899-
}
900-
901-
/* Mode 8 */
902-
sprintf(&h[100], "%07o ", (int) statbuf->st_mode);
903-
904-
/* User ID 8 */
905-
sprintf(&h[108], "%07o ", statbuf->st_uid);
906-
907-
/* Group 8 */
908-
sprintf(&h[116], "%07o ", statbuf->st_gid);
909-
910-
/* File size 12 - 11 digits, 1 space; use print_val for 64 bit support */
911-
if (linktarget != NULL || S_ISDIR(statbuf->st_mode))
912-
/* Symbolic link or directory has size zero */
913-
print_val(&h[124], 0, 8, 11);
914-
else
915-
print_val(&h[124], statbuf->st_size, 8, 11);
916-
sprintf(&h[135], " ");
917-
918-
/* Mod Time 12 */
919-
sprintf(&h[136], "%011o ", (int) statbuf->st_mtime);
920-
921-
/* Checksum 8 cannot be calculated until we've filled all other fields */
922-
923-
if (linktarget != NULL)
924-
{
925-
/* Type - Symbolic link */
926-
sprintf(&h[156], "2");
927-
/* Link Name 100 */
928-
sprintf(&h[157], "%.99s", linktarget);
929-
}
930-
else if (S_ISDIR(statbuf->st_mode))
931-
/* Type - directory */
932-
sprintf(&h[156], "5");
933-
else
934-
/* Type - regular file */
935-
sprintf(&h[156], "0");
936-
937-
/* Magic 6 */
938-
sprintf(&h[257], "ustar");
939-
940-
/* Version 2 */
941-
sprintf(&h[263], "00");
942-
943-
/* User 32 */
944-
/* XXX: Do we need to care about setting correct username? */
945-
sprintf(&h[265], "%.31s", "postgres");
946-
947-
/* Group 32 */
948-
/* XXX: Do we need to care about setting correct group name? */
949-
sprintf(&h[297], "%.31s", "postgres");
950-
951-
/* Major Dev 8 */
952-
sprintf(&h[329], "%07o ", 0);
953-
954-
/* Minor Dev 8 */
955-
sprintf(&h[337], "%07o ", 0);
956-
957-
/* Prefix 155 - not used, leave as nulls */
958-
959-
/*
960-
* We mustn't overwrite the next field while inserting the checksum.
961-
* Fortunately, the checksum can't exceed 6 octal digits, so we just write
962-
* 6 digits, a space, and a null, which is legal per POSIX.
963-
*/
964-
sprintf(&h[148], "%06o ", _tarChecksum(h));
841+
tarCreateHeader(h, filename, linktarget, statbuf->st_size,
842+
statbuf->st_mode, statbuf->st_uid, statbuf->st_gid,
843+
statbuf->st_mtime);
965844

966-
/* Now send the completed header. */
967845
pq_putmessage('d', h, 512);
968846
}

src/bin/pg_dump/pg_backup_tar.c

Lines changed: 3 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ static char *tarGets(char *buf, size_t len, TAR_MEMBER *th);
115115
static int tarPrintf(ArchiveHandle *AH, TAR_MEMBER *th, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
116116

117117
static void _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th);
118-
static int _tarChecksum(char *th);
119118
static TAR_MEMBER *_tarPositionTo(ArchiveHandle *AH, const char *filename);
120119
static size_t tarRead(void *buf, size_t len, TAR_MEMBER *th);
121120
static size_t tarWrite(const void *buf, size_t len, TAR_MEMBER *th);
@@ -1016,29 +1015,11 @@ tarPrintf(ArchiveHandle *AH, TAR_MEMBER *th, const char *fmt,...)
10161015
return cnt;
10171016
}
10181017

1019-
static int
1020-
_tarChecksum(char *header)
1021-
{
1022-
int i,
1023-
sum;
1024-
1025-
/*
1026-
* Per POSIX, the checksum is the simple sum of all bytes in the header,
1027-
* treating the bytes as unsigned, and treating the checksum field (at
1028-
* offset 148) as though it contained 8 spaces.
1029-
*/
1030-
sum = 8 * ' '; /* presumed value for checksum field */
1031-
for (i = 0; i < 512; i++)
1032-
if (i < 148 || i >= 156)
1033-
sum += 0xFF & header[i];
1034-
return sum;
1035-
}
1036-
10371018
bool
10381019
isValidTarHeader(char *header)
10391020
{
10401021
int sum;
1041-
int chk = _tarChecksum(header);
1022+
int chk = tarChecksum(header);
10421023

10431024
sscanf(&header[148], "%8o", &sum);
10441025

@@ -1251,7 +1232,7 @@ _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
12511232
(unsigned long) len);
12521233

12531234
/* Calc checksum */
1254-
chk = _tarChecksum(h);
1235+
chk = tarChecksum(h);
12551236
sscanf(&h[148], "%8o", &sum);
12561237

12571238
/*
@@ -1305,92 +1286,12 @@ _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
13051286
}
13061287

13071288

1308-
/*
1309-
* Utility routine to print possibly larger than 32 bit integers in a
1310-
* portable fashion. Filled with zeros.
1311-
*/
1312-
static void
1313-
print_val(char *s, uint64 val, unsigned int base, size_t len)
1314-
{
1315-
int i;
1316-
1317-
for (i = len; i > 0; i--)
1318-
{
1319-
int digit = val % base;
1320-
1321-
s[i - 1] = '0' + digit;
1322-
val = val / base;
1323-
}
1324-
}
1325-
1326-
13271289
static void
13281290
_tarWriteHeader(TAR_MEMBER *th)
13291291
{
13301292
char h[512];
13311293

1332-
/*
1333-
* Note: most of the fields in a tar header are not supposed to be
1334-
* null-terminated. We use sprintf, which will write a null after the
1335-
* required bytes; that null goes into the first byte of the next field.
1336-
* This is okay as long as we fill the fields in order.
1337-
*/
1338-
memset(h, 0, sizeof(h));
1339-
1340-
/* Name 100 */
1341-
sprintf(&h[0], "%.99s", th->targetFile);
1342-
1343-
/* Mode 8 */
1344-
sprintf(&h[100], "0000600 ");
1345-
1346-
/* User ID 8 */
1347-
sprintf(&h[108], "0004000 ");
1348-
1349-
/* Group 8 */
1350-
sprintf(&h[116], "0002000 ");
1351-
1352-
/* File size 12 - 11 digits, 1 space; use print_val for 64 bit support */
1353-
print_val(&h[124], th->fileLen, 8, 11);
1354-
sprintf(&h[135], " ");
1355-
1356-
/* Mod Time 12 */
1357-
sprintf(&h[136], "%011o ", (int) time(NULL));
1358-
1359-
/* Checksum 8 cannot be calculated until we've filled all other fields */
1360-
1361-
/* Type - regular file */
1362-
sprintf(&h[156], "0");
1363-
1364-
/* Link Name 100 (leave as nulls) */
1365-
1366-
/* Magic 6 */
1367-
sprintf(&h[257], "ustar");
1368-
1369-
/* Version 2 */
1370-
sprintf(&h[263], "00");
1371-
1372-
/* User 32 */
1373-
/* XXX: Do we need to care about setting correct username? */
1374-
sprintf(&h[265], "%.31s", "postgres");
1375-
1376-
/* Group 32 */
1377-
/* XXX: Do we need to care about setting correct group name? */
1378-
sprintf(&h[297], "%.31s", "postgres");
1379-
1380-
/* Major Dev 8 */
1381-
sprintf(&h[329], "%07o ", 0);
1382-
1383-
/* Minor Dev 8 */
1384-
sprintf(&h[337], "%07o ", 0);
1385-
1386-
/* Prefix 155 - not used, leave as nulls */
1387-
1388-
/*
1389-
* We mustn't overwrite the next field while inserting the checksum.
1390-
* Fortunately, the checksum can't exceed 6 octal digits, so we just write
1391-
* 6 digits, a space, and a null, which is legal per POSIX.
1392-
*/
1393-
sprintf(&h[148], "%06o ", _tarChecksum(h));
1294+
tarCreateHeader(h, th->targetFile, NULL, th->fileLen, 0600, 04000, 02000, time(NULL));
13941295

13951296
/* Now write the completed header. */
13961297
if (fwrite(h, 1, 512, th->tarFH) != 512)

src/include/port.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,4 +465,8 @@ extern int pg_check_dir(const char *dir);
465465
/* port/pgmkdirp.c */
466466
extern int pg_mkdir_p(char *path, int omode);
467467

468+
/* port/tar.c */
469+
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);
470+
int tarChecksum(char *header);
471+
468472
#endif /* PG_PORT_H */

src/port/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ LIBS += $(PTHREAD_LIBS)
3232

3333
OBJS = $(LIBOBJS) chklocale.o dirmod.o erand48.o exec.o fls.o inet_net_ntop.o \
3434
noblock.o path.o pgcheckdir.o pg_crc.o pgmkdirp.o pgsleep.o \
35-
pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o
35+
pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o tar.o thread.o
3636

3737
# foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND
3838
OBJS_SRV = $(OBJS:%.o=%_srv.o)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy