| 460 | } |
| 461 | |
| 462 | static int read_ref_internal(struct ref_store *ref_store, const char *refname, |
| 463 | struct object_id *oid, struct strbuf *referent, |
| 464 | unsigned int *type, int *failure_errno, int skip_packed_refs) |
| 465 | { |
| 466 | struct files_ref_store *refs = |
| 467 | files_downcast(ref_store, REF_STORE_READ, "read_raw_ref"); |
| 468 | struct strbuf sb_contents = STRBUF_INIT; |
| 469 | struct strbuf sb_path = STRBUF_INIT; |
| 470 | const char *path; |
| 471 | const char *buf; |
| 472 | struct stat st; |
| 473 | int fd; |
| 474 | int ret = -1; |
| 475 | int remaining_retries = 3; |
| 476 | int myerr = 0; |
| 477 | |
| 478 | *type = 0; |
| 479 | strbuf_reset(&sb_path); |
| 480 | |
| 481 | files_ref_path(refs, &sb_path, refname); |
| 482 | |
| 483 | path = sb_path.buf; |
| 484 | |
| 485 | stat_ref: |
| 486 | /* |
| 487 | * We might have to loop back here to avoid a race |
| 488 | * condition: first we lstat() the file, then we try |
| 489 | * to read it as a link or as a file. But if somebody |
| 490 | * changes the type of the file (file <-> directory |
| 491 | * <-> symlink) between the lstat() and reading, then |
| 492 | * we don't want to report that as an error but rather |
| 493 | * try again starting with the lstat(). |
| 494 | * |
| 495 | * We'll keep a count of the retries, though, just to avoid |
| 496 | * any confusing situation sending us into an infinite loop. |
| 497 | */ |
| 498 | |
| 499 | if (remaining_retries-- <= 0) |
| 500 | goto out; |
| 501 | |
| 502 | if (lstat(path, &st) < 0) { |
| 503 | int ignore_errno; |
| 504 | myerr = errno; |
| 505 | if (myerr != ENOENT || skip_packed_refs) |
| 506 | goto out; |
| 507 | if (refs_read_raw_ref(refs->packed_ref_store, refname, oid, |
| 508 | referent, type, &ignore_errno)) { |
| 509 | myerr = ENOENT; |
| 510 | goto out; |
| 511 | } |
| 512 | ret = 0; |
| 513 | goto out; |
| 514 | } |
| 515 | |
| 516 | /* Follow "normalized" - ie "refs/.." symlinks by hand */ |
| 517 | if (S_ISLNK(st.st_mode)) { |
| 518 | strbuf_reset(&sb_contents); |
| 519 | if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) { |
no test coverage detected