@@ -554,7 +554,7 @@ sendFileWithContent(const char *filename, const char *content)
554
554
555
555
/*
556
556
* Include all files from the given directory in the output tar stream. If
557
- * 'sizeonly' is true, we just calculate a total length and return ig , without
557
+ * 'sizeonly' is true, we just calculate a total length and return it , without
558
558
* actually sending anything.
559
559
*/
560
560
static int64
@@ -744,11 +744,16 @@ _tarChecksum(char *header)
744
744
int i ,
745
745
sum ;
746
746
747
- sum = 0 ;
747
+ /*
748
+ * Per POSIX, the checksum is the simple sum of all bytes in the header,
749
+ * treating the bytes as unsigned, and treating the checksum field (at
750
+ * offset 148) as though it contained 8 spaces.
751
+ */
752
+ sum = 8 * ' ' ; /* presumed value for checksum field */
748
753
for (i = 0 ; i < 512 ; i ++ )
749
754
if (i < 148 || i >= 156 )
750
755
sum += 0xFF & header [i ];
751
- return sum + 256 ; /* Assume 8 blanks in checksum field */
756
+ return sum ;
752
757
}
753
758
754
759
/* Given the member, write the TAR header & send the file */
@@ -827,9 +832,13 @@ _tarWriteHeader(const char *filename, const char *linktarget,
827
832
struct stat * statbuf )
828
833
{
829
834
char h [512 ];
830
- int lastSum = 0 ;
831
- int sum ;
832
835
836
+ /*
837
+ * Note: most of the fields in a tar header are not supposed to be
838
+ * null-terminated. We use sprintf, which will write a null after the
839
+ * required bytes; that null goes into the first byte of the next field.
840
+ * This is okay as long as we fill the fields in order.
841
+ */
833
842
memset (h , 0 , sizeof (h ));
834
843
835
844
/* Name 100 */
@@ -841,8 +850,11 @@ _tarWriteHeader(const char *filename, const char *linktarget,
841
850
* indicated in the tar format by adding a slash at the end of the
842
851
* name, the same as for regular directories.
843
852
*/
844
- h [strlen (filename )] = '/' ;
845
- h [strlen (filename ) + 1 ] = '\0' ;
853
+ int flen = strlen (filename );
854
+
855
+ flen = Min (flen , 99 );
856
+ h [flen ] = '/' ;
857
+ h [flen + 1 ] = '\0' ;
846
858
}
847
859
848
860
/* Mode 8 */
@@ -852,9 +864,9 @@ _tarWriteHeader(const char *filename, const char *linktarget,
852
864
sprintf (& h [108 ], "%07o " , statbuf -> st_uid );
853
865
854
866
/* Group 8 */
855
- sprintf (& h [117 ], "%07o " , statbuf -> st_gid );
867
+ sprintf (& h [116 ], "%07o " , statbuf -> st_gid );
856
868
857
- /* File size 12 - 11 digits, 1 space, no NUL */
869
+ /* File size 12 - 11 digits, 1 space; use print_val for 64 bit support */
858
870
if (linktarget != NULL || S_ISDIR (statbuf -> st_mode ))
859
871
/* Symbolic link or directory has size zero */
860
872
print_val (& h [124 ], 0 , 8 , 11 );
@@ -865,13 +877,13 @@ _tarWriteHeader(const char *filename, const char *linktarget,
865
877
/* Mod Time 12 */
866
878
sprintf (& h [136 ], "%011o " , (int ) statbuf -> st_mtime );
867
879
868
- /* Checksum 8 */
869
- sprintf (& h [148 ], "%06o " , lastSum );
880
+ /* Checksum 8 cannot be calculated until we've filled all other fields */
870
881
871
882
if (linktarget != NULL )
872
883
{
873
884
/* Type - Symbolic link */
874
885
sprintf (& h [156 ], "2" );
886
+ /* Link Name 100 */
875
887
sprintf (& h [157 ], "%.99s" , linktarget );
876
888
}
877
889
else if (S_ISDIR (statbuf -> st_mode ))
@@ -881,10 +893,11 @@ _tarWriteHeader(const char *filename, const char *linktarget,
881
893
/* Type - regular file */
882
894
sprintf (& h [156 ], "0" );
883
895
884
- /* Link tag 100 (NULL) */
896
+ /* Magic 6 */
897
+ sprintf (& h [257 ], "ustar" );
885
898
886
- /* Magic 6 + Version 2 */
887
- sprintf (& h [257 ], "ustar00 " );
899
+ /* Version 2 */
900
+ sprintf (& h [263 ], "00 " );
888
901
889
902
/* User 32 */
890
903
/* XXX: Do we need to care about setting correct username? */
@@ -894,17 +907,21 @@ _tarWriteHeader(const char *filename, const char *linktarget,
894
907
/* XXX: Do we need to care about setting correct group name? */
895
908
sprintf (& h [297 ], "%.31s" , "postgres" );
896
909
897
- /* Maj Dev 8 */
898
- sprintf (& h [329 ], "%6o " , 0 );
910
+ /* Major Dev 8 */
911
+ sprintf (& h [329 ], "%07o " , 0 );
899
912
900
- /* Min Dev 8 */
901
- sprintf (& h [337 ], "%6o " , 0 );
913
+ /* Minor Dev 8 */
914
+ sprintf (& h [337 ], "%07o " , 0 );
902
915
903
- while ((sum = _tarChecksum (h )) != lastSum )
904
- {
905
- sprintf (& h [148 ], "%06o " , sum );
906
- lastSum = sum ;
907
- }
916
+ /* Prefix 155 - not used, leave as nulls */
917
+
918
+ /*
919
+ * We mustn't overwrite the next field while inserting the checksum.
920
+ * Fortunately, the checksum can't exceed 6 octal digits, so we just write
921
+ * 6 digits, a space, and a null, which is legal per POSIX.
922
+ */
923
+ sprintf (& h [148 ], "%06o " , _tarChecksum (h ));
908
924
925
+ /* Now send the completed header. */
909
926
pq_putmessage ('d' , h , 512 );
910
927
}
0 commit comments