1919 *
2020 *
2121 * IDENTIFICATION
22- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.44 2009/08/24 14:15:09 alvherre Exp $
22+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.45 2010/06/27 19:07:24 tgl Exp $
2323 *
2424 *-------------------------------------------------------------------------
2525 */
@@ -438,26 +438,24 @@ static void
438438_PrintTocData (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt )
439439{
440440 lclContext * ctx = (lclContext * ) AH -> formatData ;
441- int id ;
442441 lclTocEntry * tctx = (lclTocEntry * ) te -> formatData ;
443442 int blkType ;
443+ int id ;
444444
445445 if (tctx -> dataState == K_OFFSET_NO_DATA )
446446 return ;
447447
448448 if (!ctx -> hasSeek || tctx -> dataState == K_OFFSET_POS_NOT_SET )
449449 {
450- /* Skip over unnecessary blocks until we get the one we want. */
451-
450+ /*
451+ * We cannot seek directly to the desired block. Instead, skip
452+ * over block headers until we find the one we want. This could
453+ * fail if we are asked to restore items out-of-order.
454+ */
452455 _readBlockHeader (AH , & blkType , & id );
453456
454- while (id != te -> dumpId )
457+ while (blkType != EOF && id != te -> dumpId )
455458 {
456- if ((TocIDRequired (AH , id , ropt ) & REQ_DATA ) != 0 )
457- die_horribly (AH , modulename ,
458- "dumping a specific TOC data block out of order is not supported"
459- " without ID on this input stream (fseek required)\n" );
460-
461459 switch (blkType )
462460 {
463461 case BLK_DATA :
@@ -479,13 +477,33 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
479477 }
480478 else
481479 {
482- /* Grab it */
480+ /* We can just seek to the place we need to be. */
483481 if (fseeko (AH -> FH , tctx -> dataPos , SEEK_SET ) != 0 )
484- die_horribly (AH , modulename , "error during file seek: %s\n" , strerror (errno ));
482+ die_horribly (AH , modulename , "error during file seek: %s\n" ,
483+ strerror (errno ));
485484
486485 _readBlockHeader (AH , & blkType , & id );
487486 }
488487
488+ /* Produce suitable failure message if we fell off end of file */
489+ if (blkType == EOF )
490+ {
491+ if (tctx -> dataState == K_OFFSET_POS_NOT_SET )
492+ die_horribly (AH , modulename , "could not find block ID %d in archive -- "
493+ "possibly due to out-of-order restore request, "
494+ "which cannot be handled due to lack of data offsets in archive\n" ,
495+ te -> dumpId );
496+ else if (!ctx -> hasSeek )
497+ die_horribly (AH , modulename , "could not find block ID %d in archive -- "
498+ "possibly due to out-of-order restore request, "
499+ "which cannot be handled due to non-seekable input file\n" ,
500+ te -> dumpId );
501+ else /* huh, the dataPos led us to EOF? */
502+ die_horribly (AH , modulename , "could not find block ID %d in archive -- "
503+ "possibly corrupt archive\n" ,
504+ te -> dumpId );
505+ }
506+
489507 /* Are we sane? */
490508 if (id != te -> dumpId )
491509 die_horribly (AH , modulename , "found unexpected block ID (%d) when reading data -- expected %d\n" ,
@@ -907,15 +925,35 @@ _getFilePos(ArchiveHandle *AH, lclContext *ctx)
907925
908926/*
909927 * Read a data block header. The format changed in V1.3, so we
910- * put the code here for simplicity.
928+ * centralize the code here for simplicity. Returns *type = EOF
929+ * if at EOF.
911930 */
912931static void
913932_readBlockHeader (ArchiveHandle * AH , int * type , int * id )
914933{
934+ lclContext * ctx = (lclContext * ) AH -> formatData ;
935+ int byt ;
936+
937+ /*
938+ * Note: if we are at EOF with a pre-1.3 input file, we'll die_horribly
939+ * inside ReadInt rather than returning EOF. It doesn't seem worth
940+ * jumping through hoops to deal with that case better, because no such
941+ * files are likely to exist in the wild: only some 7.1 development
942+ * versions of pg_dump ever generated such files.
943+ */
915944 if (AH -> version < K_VERS_1_3 )
916945 * type = BLK_DATA ;
917946 else
918- * type = _ReadByte (AH );
947+ {
948+ byt = getc (AH -> FH );
949+ * type = byt ;
950+ if (byt == EOF )
951+ {
952+ * id = 0 ; /* don't return an uninitialized value */
953+ return ;
954+ }
955+ ctx -> filePos += 1 ;
956+ }
919957
920958 * id = ReadInt (AH );
921959}
0 commit comments