Skip to content

Commit cfea2f2

Browse files
shejialuogitster
authored andcommitted
packed-backend: check whether the "packed-refs" is regular file
Although "git-fsck(1)" and "packed-backend.c" will check some consistency and correctness of "packed-refs" file, they never check the filetype of the "packed-refs". Let's verify that the "packed-refs" has the expected filetype, confirming it is created by "git pack-refs" command. We could use "open_nofollow" wrapper to open the raw "packed-refs" file. If the returned "fd" value is less than 0, we could check whether the "errno" is "ELOOP" to report an error to the user. And then we use "fstat" to check whether the "packed-refs" file is a regular file. Reuse "FSCK_MSG_BAD_REF_FILETYPE" fsck message id to report the error to the user if "packed-refs" is not a regular file. Mentored-by: Patrick Steinhardt <[email protected]> Mentored-by: Karthik Nayak <[email protected]> Signed-off-by: shejialuo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fdf3820 commit cfea2f2

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

refs/packed-backend.c

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "../git-compat-util.h"
55
#include "../config.h"
66
#include "../dir.h"
7+
#include "../fsck.h"
78
#include "../gettext.h"
89
#include "../hash.h"
910
#include "../hex.h"
@@ -1748,15 +1749,58 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s
17481749
return empty_ref_iterator_begin();
17491750
}
17501751

1751-
static int packed_fsck(struct ref_store *ref_store UNUSED,
1752-
struct fsck_options *o UNUSED,
1752+
static int packed_fsck(struct ref_store *ref_store,
1753+
struct fsck_options *o,
17531754
struct worktree *wt)
17541755
{
1756+
struct packed_ref_store *refs = packed_downcast(ref_store,
1757+
REF_STORE_READ, "fsck");
1758+
struct stat st;
1759+
int ret = 0;
1760+
int fd = -1;
17551761

17561762
if (!is_main_worktree(wt))
1757-
return 0;
1763+
goto cleanup;
17581764

1759-
return 0;
1765+
if (o->verbose)
1766+
fprintf_ln(stderr, "Checking packed-refs file %s", refs->path);
1767+
1768+
fd = open_nofollow(refs->path, O_RDONLY);
1769+
if (fd < 0) {
1770+
/*
1771+
* If the packed-refs file doesn't exist, there's nothing
1772+
* to check.
1773+
*/
1774+
if (errno == ENOENT)
1775+
goto cleanup;
1776+
1777+
if (errno == ELOOP) {
1778+
struct fsck_ref_report report = { 0 };
1779+
report.path = "packed-refs";
1780+
ret = fsck_report_ref(o, &report,
1781+
FSCK_MSG_BAD_REF_FILETYPE,
1782+
"not a regular file but a symlink");
1783+
goto cleanup;
1784+
}
1785+
1786+
ret = error_errno(_("unable to open '%s'"), refs->path);
1787+
goto cleanup;
1788+
} else if (fstat(fd, &st) < 0) {
1789+
ret = error_errno(_("unable to stat '%s'"), refs->path);
1790+
goto cleanup;
1791+
} else if (!S_ISREG(st.st_mode)) {
1792+
struct fsck_ref_report report = { 0 };
1793+
report.path = "packed-refs";
1794+
ret = fsck_report_ref(o, &report,
1795+
FSCK_MSG_BAD_REF_FILETYPE,
1796+
"not a regular file");
1797+
goto cleanup;
1798+
}
1799+
1800+
cleanup:
1801+
if (fd >= 0)
1802+
close(fd);
1803+
return ret;
17601804
}
17611805

17621806
struct ref_storage_be refs_be_packed = {

t/t0602-reffiles-fsck.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,4 +617,34 @@ test_expect_success 'ref content checks should work with worktrees' '
617617
)
618618
'
619619

620+
test_expect_success SYMLINKS 'the filetype of packed-refs should be checked' '
621+
test_when_finished "rm -rf repo" &&
622+
git init repo &&
623+
(
624+
cd repo &&
625+
test_commit default &&
626+
git branch branch-1 &&
627+
git branch branch-2 &&
628+
git branch branch-3 &&
629+
git pack-refs --all &&
630+
631+
mv .git/packed-refs .git/packed-refs-back &&
632+
ln -sf packed-refs-back .git/packed-refs &&
633+
test_must_fail git refs verify 2>err &&
634+
cat >expect <<-EOF &&
635+
error: packed-refs: badRefFiletype: not a regular file but a symlink
636+
EOF
637+
rm .git/packed-refs &&
638+
test_cmp expect err &&
639+
640+
mkdir .git/packed-refs &&
641+
test_must_fail git refs verify 2>err &&
642+
cat >expect <<-EOF &&
643+
error: packed-refs: badRefFiletype: not a regular file
644+
EOF
645+
rm -r .git/packed-refs &&
646+
test_cmp expect err
647+
)
648+
'
649+
620650
test_done

0 commit comments

Comments
 (0)