Skip to content

Commit 9e59b38

Browse files
jonathantanmygitster
authored andcommitted
object-file: emit corruption errors when detected
Instead of relying on errno being preserved across function calls, teach do_oid_object_info_extended() to itself report object corruption when it first detects it. There are 3 types of corruption being detected: - when a replacement object is missing - when a loose object is corrupt - when a packed object is corrupt and the object cannot be read in another way Note that in the RHS of this patch's diff, a check for ENOENT that was introduced in 3ba7a06 (A loose object is not corrupt if it cannot be read due to EMFILE, 2010-10-28) is also removed. The purpose of this check is to avoid a false report of corruption if the errno contains something like EMFILE (or anything that is not ENOENT), in which case a more generic report is presented. Because, as of this patch, we no longer rely on such a heuristic to determine corruption, but surface the error message at the point when we read something that we did not expect, this check is no longer necessary. Besides being more resilient, this also prepares for a future patch in which an indirect caller of do_oid_object_info_extended() will need such functionality. Helped-by: Jeff King <[email protected]> Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ae285ac commit 9e59b38

File tree

2 files changed

+31
-27
lines changed

2 files changed

+31
-27
lines changed

object-file.c

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,9 @@ static int loose_object_info(struct repository *r,
14221422
struct object_info *oi, int flags)
14231423
{
14241424
int status = 0;
1425+
int fd;
14251426
unsigned long mapsize;
1427+
const char *path;
14261428
void *map;
14271429
git_zstream stream;
14281430
char hdr[MAX_HEADER_LEN];
@@ -1443,7 +1445,6 @@ static int loose_object_info(struct repository *r,
14431445
* object even exists.
14441446
*/
14451447
if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
1446-
const char *path;
14471448
struct stat st;
14481449
if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
14491450
return quick_has_loose(r, oid) ? 0 : -1;
@@ -1454,7 +1455,13 @@ static int loose_object_info(struct repository *r,
14541455
return 0;
14551456
}
14561457

1457-
map = map_loose_object(r, oid, &mapsize);
1458+
fd = open_loose_object(r, oid, &path);
1459+
if (fd < 0) {
1460+
if (errno != ENOENT)
1461+
error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
1462+
return -1;
1463+
}
1464+
map = map_fd(fd, path, &mapsize);
14581465
if (!map)
14591466
return -1;
14601467

@@ -1492,6 +1499,10 @@ static int loose_object_info(struct repository *r,
14921499
break;
14931500
}
14941501

1502+
if (status && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
1503+
die(_("loose object %s (stored in %s) is corrupt"),
1504+
oid_to_hex(oid), path);
1505+
14951506
git_inflate_end(&stream);
14961507
cleanup:
14971508
munmap(map, mapsize);
@@ -1601,6 +1612,15 @@ static int do_oid_object_info_extended(struct repository *r,
16011612
continue;
16021613
}
16031614

1615+
if (flags & OBJECT_INFO_DIE_IF_CORRUPT) {
1616+
const struct packed_git *p;
1617+
if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid))
1618+
die(_("replacement %s not found for %s"),
1619+
oid_to_hex(real), oid_to_hex(oid));
1620+
if ((p = has_packed_and_bad(r, real)))
1621+
die(_("packed object %s (stored in %s) is corrupt"),
1622+
oid_to_hex(real), p->pack_name);
1623+
}
16041624
return -1;
16051625
}
16061626

@@ -1653,15 +1673,17 @@ int oid_object_info(struct repository *r,
16531673

16541674
static void *read_object(struct repository *r,
16551675
const struct object_id *oid, enum object_type *type,
1656-
unsigned long *size)
1676+
unsigned long *size,
1677+
int die_if_corrupt)
16571678
{
16581679
struct object_info oi = OBJECT_INFO_INIT;
16591680
void *content;
16601681
oi.typep = type;
16611682
oi.sizep = size;
16621683
oi.contentp = &content;
16631684

1664-
if (oid_object_info_extended(r, oid, &oi, 0) < 0)
1685+
if (oid_object_info_extended(r, oid, &oi, die_if_corrupt
1686+
? OBJECT_INFO_DIE_IF_CORRUPT : 0) < 0)
16651687
return NULL;
16661688
return content;
16671689
}
@@ -1697,35 +1719,14 @@ void *read_object_file_extended(struct repository *r,
16971719
int lookup_replace)
16981720
{
16991721
void *data;
1700-
const struct packed_git *p;
1701-
const char *path;
1702-
struct stat st;
17031722
const struct object_id *repl = lookup_replace ?
17041723
lookup_replace_object(r, oid) : oid;
17051724

17061725
errno = 0;
1707-
data = read_object(r, repl, type, size);
1726+
data = read_object(r, repl, type, size, 1);
17081727
if (data)
17091728
return data;
17101729

1711-
obj_read_lock();
1712-
if (errno && errno != ENOENT)
1713-
die_errno(_("failed to read object %s"), oid_to_hex(oid));
1714-
1715-
/* die if we replaced an object with one that does not exist */
1716-
if (repl != oid)
1717-
die(_("replacement %s not found for %s"),
1718-
oid_to_hex(repl), oid_to_hex(oid));
1719-
1720-
if (!stat_loose_object(r, repl, &st, &path))
1721-
die(_("loose object %s (stored in %s) is corrupt"),
1722-
oid_to_hex(repl), path);
1723-
1724-
if ((p = has_packed_and_bad(r, repl)))
1725-
die(_("packed object %s (stored in %s) is corrupt"),
1726-
oid_to_hex(repl), p->pack_name);
1727-
obj_read_unlock();
1728-
17291730
return NULL;
17301731
}
17311732

@@ -2268,7 +2269,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
22682269

22692270
if (has_loose_object(oid))
22702271
return 0;
2271-
buf = read_object(the_repository, oid, &type, &len);
2272+
buf = read_object(the_repository, oid, &type, &len, 0);
22722273
if (!buf)
22732274
return error(_("cannot read object for %s"), oid_to_hex(oid));
22742275
hdrlen = format_object_header(hdr, sizeof(hdr), type, len);

object-store.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ struct object_info {
445445
*/
446446
#define OBJECT_INFO_FOR_PREFETCH (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK)
447447

448+
/* Die if object corruption (not just an object being missing) was detected. */
449+
#define OBJECT_INFO_DIE_IF_CORRUPT 32
450+
448451
int oid_object_info_extended(struct repository *r,
449452
const struct object_id *,
450453
struct object_info *, unsigned flags);

0 commit comments

Comments
 (0)