|
33 | 33 | #include "utils/elog.h"
|
34 | 34 | #include "utils/memutils.h"
|
35 | 35 | #include "utils/ps_status.h"
|
| 36 | +#include "pgtar.h" |
36 | 37 |
|
37 | 38 | typedef struct
|
38 | 39 | {
|
@@ -845,49 +846,6 @@ sendDir(char *path, int basepathlen, bool sizeonly, List *tablespaces)
|
845 | 846 | */
|
846 | 847 |
|
847 | 848 |
|
848 |
| -/* |
849 |
| - * Utility routine to print possibly larger than 32 bit integers in a |
850 |
| - * portable fashion. Filled with zeros. |
851 |
| - */ |
852 |
| -static void |
853 |
| -print_val(char *s, uint64 val, unsigned int base, size_t len) |
854 |
| -{ |
855 |
| - int i; |
856 |
| - |
857 |
| - for (i = len; i > 0; i--) |
858 |
| - { |
859 |
| - int digit = val % base; |
860 |
| - |
861 |
| - s[i - 1] = '0' + digit; |
862 |
| - val = val / base; |
863 |
| - } |
864 |
| -} |
865 |
| - |
866 |
| -/* |
867 |
| - * Maximum file size for a tar member: The limit inherent in the |
868 |
| - * format is 2^33-1 bytes (nearly 8 GB). But we don't want to exceed |
869 |
| - * what we can represent in pgoff_t. |
870 |
| - */ |
871 |
| -#define MAX_TAR_MEMBER_FILELEN (((int64) 1 << Min(33, sizeof(pgoff_t)*8 - 1)) - 1) |
872 |
| - |
873 |
| -static int |
874 |
| -_tarChecksum(char *header) |
875 |
| -{ |
876 |
| - int i, |
877 |
| - sum; |
878 |
| - |
879 |
| - /* |
880 |
| - * Per POSIX, the checksum is the simple sum of all bytes in the header, |
881 |
| - * treating the bytes as unsigned, and treating the checksum field (at |
882 |
| - * offset 148) as though it contained 8 spaces. |
883 |
| - */ |
884 |
| - sum = 8 * ' '; /* presumed value for checksum field */ |
885 |
| - for (i = 0; i < 512; i++) |
886 |
| - if (i < 148 || i >= 156) |
887 |
| - sum += 0xFF & header[i]; |
888 |
| - return sum; |
889 |
| -} |
890 |
| - |
891 | 849 | /*
|
892 | 850 | * Given the member, write the TAR header & send the file.
|
893 | 851 | *
|
@@ -916,15 +874,6 @@ sendFile(char *readfilename, char *tarfilename, struct stat *statbuf,
|
916 | 874 | errmsg("could not open file \"%s\": %m", readfilename)));
|
917 | 875 | }
|
918 | 876 |
|
919 |
| - /* |
920 |
| - * Some compilers will throw a warning knowing this test can never be true |
921 |
| - * because pgoff_t can't exceed the compared maximum on their platform. |
922 |
| - */ |
923 |
| - if (statbuf->st_size > MAX_TAR_MEMBER_FILELEN) |
924 |
| - ereport(ERROR, |
925 |
| - (errmsg("archive member \"%s\" too large for tar format", |
926 |
| - tarfilename))); |
927 |
| - |
928 | 877 | _tarWriteHeader(tarfilename, NULL, statbuf);
|
929 | 878 |
|
930 | 879 | while ((cnt = fread(buf, 1, Min(sizeof(buf), statbuf->st_size - len), fp)) > 0)
|
@@ -979,95 +928,10 @@ _tarWriteHeader(const char *filename, const char *linktarget,
|
979 | 928 | {
|
980 | 929 | char h[512];
|
981 | 930 |
|
982 |
| - /* |
983 |
| - * Note: most of the fields in a tar header are not supposed to be |
984 |
| - * null-terminated. We use sprintf, which will write a null after the |
985 |
| - * required bytes; that null goes into the first byte of the next field. |
986 |
| - * This is okay as long as we fill the fields in order. |
987 |
| - */ |
988 |
| - memset(h, 0, sizeof(h)); |
989 |
| - |
990 |
| - /* Name 100 */ |
991 |
| - strlcpy(&h[0], filename, 100); |
992 |
| - if (linktarget != NULL || S_ISDIR(statbuf->st_mode)) |
993 |
| - { |
994 |
| - /* |
995 |
| - * We only support symbolic links to directories, and this is |
996 |
| - * indicated in the tar format by adding a slash at the end of the |
997 |
| - * name, the same as for regular directories. |
998 |
| - */ |
999 |
| - int flen = strlen(filename); |
1000 |
| - |
1001 |
| - flen = Min(flen, 99); |
1002 |
| - h[flen] = '/'; |
1003 |
| - h[flen + 1] = '\0'; |
1004 |
| - } |
1005 |
| - |
1006 |
| - /* Mode 8 */ |
1007 |
| - sprintf(&h[100], "%07o ", (int) statbuf->st_mode); |
1008 |
| - |
1009 |
| - /* User ID 8 */ |
1010 |
| - sprintf(&h[108], "%07o ", statbuf->st_uid); |
1011 |
| - |
1012 |
| - /* Group 8 */ |
1013 |
| - sprintf(&h[116], "%07o ", statbuf->st_gid); |
1014 |
| - |
1015 |
| - /* File size 12 - 11 digits, 1 space; use print_val for 64 bit support */ |
1016 |
| - if (linktarget != NULL || S_ISDIR(statbuf->st_mode)) |
1017 |
| - /* Symbolic link or directory has size zero */ |
1018 |
| - print_val(&h[124], 0, 8, 11); |
1019 |
| - else |
1020 |
| - print_val(&h[124], statbuf->st_size, 8, 11); |
1021 |
| - sprintf(&h[135], " "); |
1022 |
| - |
1023 |
| - /* Mod Time 12 */ |
1024 |
| - sprintf(&h[136], "%011o ", (int) statbuf->st_mtime); |
1025 |
| - |
1026 |
| - /* Checksum 8 cannot be calculated until we've filled all other fields */ |
1027 |
| - |
1028 |
| - if (linktarget != NULL) |
1029 |
| - { |
1030 |
| - /* Type - Symbolic link */ |
1031 |
| - sprintf(&h[156], "2"); |
1032 |
| - /* Link Name 100 */ |
1033 |
| - strlcpy(&h[157], linktarget, 100); |
1034 |
| - } |
1035 |
| - else if (S_ISDIR(statbuf->st_mode)) |
1036 |
| - /* Type - directory */ |
1037 |
| - sprintf(&h[156], "5"); |
1038 |
| - else |
1039 |
| - /* Type - regular file */ |
1040 |
| - sprintf(&h[156], "0"); |
1041 |
| - |
1042 |
| - /* Magic 6 */ |
1043 |
| - sprintf(&h[257], "ustar"); |
1044 |
| - |
1045 |
| - /* Version 2 */ |
1046 |
| - sprintf(&h[263], "00"); |
1047 |
| - |
1048 |
| - /* User 32 */ |
1049 |
| - /* XXX: Do we need to care about setting correct username? */ |
1050 |
| - strlcpy(&h[265], "postgres", 32); |
1051 |
| - |
1052 |
| - /* Group 32 */ |
1053 |
| - /* XXX: Do we need to care about setting correct group name? */ |
1054 |
| - strlcpy(&h[297], "postgres", 32); |
1055 |
| - |
1056 |
| - /* Major Dev 8 */ |
1057 |
| - sprintf(&h[329], "%07o ", 0); |
1058 |
| - |
1059 |
| - /* Minor Dev 8 */ |
1060 |
| - sprintf(&h[337], "%07o ", 0); |
1061 |
| - |
1062 |
| - /* Prefix 155 - not used, leave as nulls */ |
1063 |
| - |
1064 |
| - /* |
1065 |
| - * We mustn't overwrite the next field while inserting the checksum. |
1066 |
| - * Fortunately, the checksum can't exceed 6 octal digits, so we just write |
1067 |
| - * 6 digits, a space, and a null, which is legal per POSIX. |
1068 |
| - */ |
1069 |
| - sprintf(&h[148], "%06o ", _tarChecksum(h)); |
| 931 | + tarCreateHeader(h, filename, linktarget, statbuf->st_size, |
| 932 | + statbuf->st_mode, statbuf->st_uid, statbuf->st_gid, |
| 933 | + statbuf->st_mtime, |
| 934 | + false /* write real POSIX header */); |
1070 | 935 |
|
1071 |
| - /* Now send the completed header. */ |
1072 | 936 | pq_putmessage('d', h, 512);
|
1073 | 937 | }
|
0 commit comments