16
16
*
17
17
*
18
18
* IDENTIFICATION
19
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.28 2002/09/04 20:31:34 momjian Exp $
19
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.29 2002/09/06 21:58:36 petere Exp $
20
20
*
21
21
*-------------------------------------------------------------------------
22
22
*/
@@ -73,6 +73,17 @@ typedef struct
73
73
ArchiveHandle * AH ;
74
74
} TAR_MEMBER ;
75
75
76
+ /*
77
+ * Maximum file size for a tar member: The limit inherent in the
78
+ * format is 2^33-1 bytes (nearly 8 GB). But we don't want to exceed
79
+ * what we can represent by an off_t.
80
+ */
81
+ #ifdef INT64_IS_BUSTED
82
+ #define MAX_TAR_MEMBER_FILELEN INT_MAX
83
+ #else
84
+ #define MAX_TAR_MEMBER_FILELEN (((int64) 1 << Min(33, sizeof(off_t)*8 - 1)) - 1)
85
+ #endif
86
+
76
87
typedef struct
77
88
{
78
89
int hasSeek ;
@@ -1006,6 +1017,8 @@ _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)
1006
1017
*/
1007
1018
fseeko (tmp , 0 , SEEK_END );
1008
1019
th -> fileLen = ftello (tmp );
1020
+ if (th -> fileLen > MAX_TAR_MEMBER_FILELEN )
1021
+ die_horribly (AH , modulename , "archive member too large for tar format\n" );
1009
1022
fseeko (tmp , 0 , SEEK_SET );
1010
1023
1011
1024
_tarWriteHeader (th );
@@ -1219,6 +1232,23 @@ _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
1219
1232
return 1 ;
1220
1233
}
1221
1234
1235
+
1236
+ /*
1237
+ * Utility routine to print possibly larger than 32 bit integers in a
1238
+ * portable fashion. Filled with zeros.
1239
+ */
1240
+ static void print_val (char * s , uint64 val , unsigned int base , size_t len )
1241
+ {
1242
+ int i ;
1243
+ for (i = len ; i > 0 ; i -- )
1244
+ {
1245
+ int digit = val % base ;
1246
+ s [i - 1 ] = '0' + digit ;
1247
+ val = val / base ;
1248
+ }
1249
+ }
1250
+
1251
+
1222
1252
static void
1223
1253
_tarWriteHeader (TAR_MEMBER * th )
1224
1254
{
@@ -1235,34 +1265,30 @@ _tarWriteHeader(TAR_MEMBER *th)
1235
1265
sprintf (& h [100 ], "100600 " );
1236
1266
1237
1267
/* User ID 8 */
1238
- sprintf (& h [108 ], " 04000 " );
1268
+ sprintf (& h [108 ], "004000 " );
1239
1269
1240
1270
/* Group 8 */
1241
- sprintf (& h [116 ], " 02000 " );
1271
+ sprintf (& h [116 ], "002000 " );
1242
1272
1243
- /* File size 12 */
1244
- /* FIXME: This goes only up to 2^30. -- What about larger files? */
1245
- sprintf (& h [124 ], "%10o " , ( unsigned int ) th -> fileLen );
1273
+ /* File size 12 - 11 digits, 1 space, no NUL */
1274
+ print_val ( & h [ 124 ], th -> fileLen , 8 , 11 );
1275
+ sprintf (& h [135 ], " " );
1246
1276
1247
1277
/* Mod Time 12 */
1248
- sprintf (& h [136 ], "%10o " , (int ) time (NULL ));
1278
+ sprintf (& h [136 ], "%011o " , (int ) time (NULL ));
1249
1279
1250
1280
/* Checksum 8 */
1251
- sprintf (& h [148 ], "%6o " , lastSum );
1281
+ sprintf (& h [148 ], "%06o " , lastSum );
1252
1282
1253
- /* Type 1 */
1254
- /* sprintf(&h[156], "%c", LF_NORMAL); */
1283
+ /* Type - regular file */
1255
1284
sprintf (& h [156 ], "0" );
1256
1285
1257
1286
/* Link tag 100 (NULL) */
1258
1287
1259
- /* Magic 8 */
1260
- sprintf (& h [257 ], "ustar " );
1261
-
1262
- /*
1263
- * GNU Version... sprintf(&h[257], "ustar"); sprintf(&h[263], "00");
1264
- */
1288
+ /* Magic 6 + Version 2 */
1289
+ sprintf (& h [257 ], "ustar00" );
1265
1290
1291
+ #if 0
1266
1292
/* User 32 */
1267
1293
sprintf (& h [265 ], "%.31s" , "" ); /* How do I get username reliably?
1268
1294
* Do I need to? */
@@ -1272,15 +1298,15 @@ _tarWriteHeader(TAR_MEMBER *th)
1272
1298
* I need to? */
1273
1299
1274
1300
/* Maj Dev 8 */
1275
- /* sprintf(&h[329], "%6o ", 0); */
1276
-
1277
- /* Min Dev */
1278
- /* sprintf(&h[337], "%6o ", 0); */
1301
+ sprintf (& h [329 ], "%6o " , 0 );
1279
1302
1303
+ /* Min Dev 8 */
1304
+ sprintf (& h [337 ], "%6o " , 0 );
1305
+ #endif
1280
1306
1281
1307
while ((sum = _tarChecksum (h )) != lastSum )
1282
1308
{
1283
- sprintf (& h [148 ], "%6o " , sum );
1309
+ sprintf (& h [148 ], "%06o " , sum );
1284
1310
lastSum = sum ;
1285
1311
}
1286
1312
0 commit comments