@@ -215,8 +215,12 @@ static NORETURN void die_invalid_line(const char *path,
215215 */
216216static struct packed_ref_cache * read_packed_refs (struct packed_ref_store * refs )
217217{
218- FILE * f ;
219218 struct packed_ref_cache * packed_refs = xcalloc (1 , sizeof (* packed_refs ));
219+ int fd ;
220+ struct stat st ;
221+ size_t size ;
222+ char * buf ;
223+ const char * pos , * eol , * eof ;
220224 struct ref_entry * last = NULL ;
221225 struct strbuf line = STRBUF_INIT ;
222226 enum { PEELED_NONE , PEELED_TAGS , PEELED_FULLY } peeled = PEELED_NONE ;
@@ -227,8 +231,8 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
227231 packed_refs -> cache = create_ref_cache (NULL , NULL );
228232 packed_refs -> cache -> root -> flag &= ~REF_INCOMPLETE ;
229233
230- f = fopen (refs -> path , "r" );
231- if (! f ) {
234+ fd = open (refs -> path , O_RDONLY );
235+ if (fd < 0 ) {
232236 if (errno == ENOENT ) {
233237 /*
234238 * This is OK; it just means that no
@@ -241,24 +245,35 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
241245 }
242246 }
243247
244- stat_validity_update (& packed_refs -> validity , fileno (f ));
248+ stat_validity_update (& packed_refs -> validity , fd );
249+
250+ if (fstat (fd , & st ) < 0 )
251+ die_errno ("couldn't stat %s" , refs -> path );
252+
253+ size = xsize_t (st .st_size );
254+ buf = xmmap (NULL , size , PROT_READ , MAP_PRIVATE , fd , 0 );
255+ pos = buf ;
256+ eof = buf + size ;
245257
246258 dir = get_ref_dir (packed_refs -> cache -> root );
247- while (strbuf_getwholeline ( & line , f , '\n' ) != EOF ) {
259+ while (pos < eof ) {
248260 struct object_id oid ;
249261 const char * refname ;
250262 const char * traits ;
251263
252- if (!line .len || line .buf [line .len - 1 ] != '\n' )
253- die_unterminated_line (refs -> path , line .buf , line .len );
264+ eol = memchr (pos , '\n' , eof - pos );
265+ if (!eol )
266+ die_unterminated_line (refs -> path , pos , eof - pos );
267+
268+ strbuf_add (& line , pos , eol + 1 - pos );
254269
255270 if (skip_prefix (line .buf , "# pack-refs with:" , & traits )) {
256271 if (strstr (traits , " fully-peeled " ))
257272 peeled = PEELED_FULLY ;
258273 else if (strstr (traits , " peeled " ))
259274 peeled = PEELED_TAGS ;
260275 /* perhaps other traits later as well */
261- continue ;
276+ goto next_line ;
262277 }
263278
264279 refname = parse_ref_line (& line , & oid );
@@ -291,11 +306,18 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
291306 } else {
292307 die_invalid_line (refs -> path , line .buf , line .len );
293308 }
309+
310+ next_line :
311+ /* The "+ 1" is for the LF character. */
312+ pos = eol + 1 ;
313+ strbuf_reset (& line );
294314 }
295315
296- fclose (f );
297- strbuf_release (& line );
316+ if (munmap (buf , size ))
317+ die_errno ("error ummapping packed-refs file" );
318+ close (fd );
298319
320+ strbuf_release (& line );
299321 return packed_refs ;
300322}
301323
0 commit comments