@@ -517,6 +517,53 @@ static int refname_contains_nul(struct strbuf *refname)
517517
518518#define SMALL_FILE_SIZE (32*1024)
519519
520+ static int allocate_snapshot_buffer (struct snapshot * snapshot , int fd , struct stat * st )
521+ {
522+ ssize_t bytes_read ;
523+ size_t size ;
524+
525+ size = xsize_t (st -> st_size );
526+ if (!size )
527+ return 0 ;
528+
529+ if (mmap_strategy == MMAP_NONE || size <= SMALL_FILE_SIZE ) {
530+ snapshot -> buf = xmalloc (size );
531+ bytes_read = read_in_full (fd , snapshot -> buf , size );
532+ if (bytes_read < 0 || bytes_read != size )
533+ die_errno ("couldn't read %s" , snapshot -> refs -> path );
534+ snapshot -> mmapped = 0 ;
535+ } else {
536+ snapshot -> buf = xmmap (NULL , size , PROT_READ , MAP_PRIVATE , fd , 0 );
537+ snapshot -> mmapped = 1 ;
538+ }
539+
540+ snapshot -> start = snapshot -> buf ;
541+ snapshot -> eof = snapshot -> buf + size ;
542+
543+ return 1 ;
544+ }
545+
546+ static void munmap_temporary_snapshot (struct snapshot * snapshot )
547+ {
548+ char * buf_copy ;
549+ size_t size ;
550+
551+ if (!snapshot )
552+ return ;
553+
554+ /*
555+ * We don't want to leave the file mmapped, so we are
556+ * forced to make a copy now:
557+ */
558+ size = snapshot -> eof - snapshot -> start ;
559+ buf_copy = xmalloc (size );
560+
561+ memcpy (buf_copy , snapshot -> start , size );
562+ clear_snapshot_buffer (snapshot );
563+ snapshot -> buf = snapshot -> start = buf_copy ;
564+ snapshot -> eof = buf_copy + size ;
565+ }
566+
520567/*
521568 * Depending on `mmap_strategy`, either mmap or read the contents of
522569 * the `packed-refs` file into the snapshot. Return 1 if the file
@@ -525,10 +572,9 @@ static int refname_contains_nul(struct strbuf *refname)
525572 */
526573static int load_contents (struct snapshot * snapshot )
527574{
528- int fd ;
529575 struct stat st ;
530- size_t size ;
531- ssize_t bytes_read ;
576+ int ret = 1 ;
577+ int fd ;
532578
533579 fd = open (snapshot -> refs -> path , O_RDONLY );
534580 if (fd < 0 ) {
@@ -550,27 +596,12 @@ static int load_contents(struct snapshot *snapshot)
550596
551597 if (fstat (fd , & st ) < 0 )
552598 die_errno ("couldn't stat %s" , snapshot -> refs -> path );
553- size = xsize_t (st .st_size );
554599
555- if (!size ) {
556- close (fd );
557- return 0 ;
558- } else if (mmap_strategy == MMAP_NONE || size <= SMALL_FILE_SIZE ) {
559- snapshot -> buf = xmalloc (size );
560- bytes_read = read_in_full (fd , snapshot -> buf , size );
561- if (bytes_read < 0 || bytes_read != size )
562- die_errno ("couldn't read %s" , snapshot -> refs -> path );
563- snapshot -> mmapped = 0 ;
564- } else {
565- snapshot -> buf = xmmap (NULL , size , PROT_READ , MAP_PRIVATE , fd , 0 );
566- snapshot -> mmapped = 1 ;
567- }
568- close (fd );
600+ if (!allocate_snapshot_buffer (snapshot , fd , & st ))
601+ ret = 0 ;
569602
570- snapshot -> start = snapshot -> buf ;
571- snapshot -> eof = snapshot -> buf + size ;
572-
573- return 1 ;
603+ close (fd );
604+ return ret ;
574605}
575606
576607static const char * find_reference_location_1 (struct snapshot * snapshot ,
@@ -751,19 +782,8 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs)
751782 verify_buffer_safe (snapshot );
752783 }
753784
754- if (mmap_strategy != MMAP_OK && snapshot -> mmapped ) {
755- /*
756- * We don't want to leave the file mmapped, so we are
757- * forced to make a copy now:
758- */
759- size_t size = snapshot -> eof - snapshot -> start ;
760- char * buf_copy = xmalloc (size );
761-
762- memcpy (buf_copy , snapshot -> start , size );
763- clear_snapshot_buffer (snapshot );
764- snapshot -> buf = snapshot -> start = buf_copy ;
765- snapshot -> eof = buf_copy + size ;
766- }
785+ if (mmap_strategy == MMAP_TEMPORARY && snapshot -> mmapped )
786+ munmap_temporary_snapshot (snapshot );
767787
768788 return snapshot ;
769789}
@@ -2059,7 +2079,7 @@ static int packed_fsck(struct ref_store *ref_store,
20592079{
20602080 struct packed_ref_store * refs = packed_downcast (ref_store ,
20612081 REF_STORE_READ , "fsck" );
2062- struct strbuf packed_ref_content = STRBUF_INIT ;
2082+ struct snapshot * snapshot = xcalloc ( 1 , sizeof ( * snapshot )) ;
20632083 unsigned int sorted = 0 ;
20642084 struct stat st ;
20652085 int ret = 0 ;
@@ -2103,21 +2123,26 @@ static int packed_fsck(struct ref_store *ref_store,
21032123 goto cleanup ;
21042124 }
21052125
2106- if (strbuf_read (& packed_ref_content , fd , 0 ) < 0 ) {
2107- ret = error_errno (_ ("unable to read '%s'" ), refs -> path );
2126+ if (!st .st_size )
21082127 goto cleanup ;
2109- }
21102128
2111- ret = packed_fsck_ref_content (o , ref_store , & sorted , packed_ref_content .buf ,
2112- packed_ref_content .buf + packed_ref_content .len );
2129+ if (!allocate_snapshot_buffer (snapshot , fd , & st ))
2130+ goto cleanup ;
2131+
2132+ if (mmap_strategy == MMAP_TEMPORARY && snapshot -> mmapped )
2133+ munmap_temporary_snapshot (snapshot );
2134+
2135+ ret = packed_fsck_ref_content (o , ref_store , & sorted , snapshot -> start ,
2136+ snapshot -> eof );
21132137 if (!ret && sorted )
2114- ret = packed_fsck_ref_sorted (o , ref_store , packed_ref_content . buf ,
2115- packed_ref_content . buf + packed_ref_content . len );
2138+ ret = packed_fsck_ref_sorted (o , ref_store , snapshot -> start ,
2139+ snapshot -> eof );
21162140
21172141cleanup :
21182142 if (fd >= 0 )
21192143 close (fd );
2120- strbuf_release (& packed_ref_content );
2144+ clear_snapshot_buffer (snapshot );
2145+ free (snapshot );
21212146 return ret ;
21222147}
21232148
0 commit comments