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{
440440lclContext * ctx = (lclContext * )AH -> formatData ;
441- int id ;
442441lclTocEntry * tctx = (lclTocEntry * )te -> formatData ;
443442int blkType ;
443+ int id ;
444444
445445if (tctx -> dataState == K_OFFSET_NO_DATA )
446446return ;
447447
448448if (!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-
461459switch (blkType )
462460{
463461case BLK_DATA :
@@ -479,13 +477,33 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
479477}
480478else
481479{
482- /*Grab it */
480+ /*We can just seek to the place we need to be. */
483481if (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? */
490508if (id != te -> dumpId )
491509die_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+ */
915944if (AH -> version < K_VERS_1_3 )
916945* type = BLK_DATA ;
917946else
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}