/* Reduced from git-2.39.0's pack-revindex.c */ typedef unsigned int __uint32_t; typedef unsigned long int __uintmax_t; typedef long int __off_t; typedef long int __off64_t; typedef __SIZE_TYPE__ size_t; typedef __off64_t off_t; typedef __uint32_t uint32_t; typedef __uintmax_t uintmax_t; struct stat { /* [...snip...] */ __off_t st_size; /* [...snip...] */ }; extern int close(int __fd); extern int fstat(int __fd, struct stat *__buf) __attribute__((__nothrow__, __leaf__)) __attribute__((__nonnull__(2))); extern uint32_t default_swab32(uint32_t val); extern uint32_t git_bswap32(uint32_t x); __attribute__((__noreturn__)) void die(const char *err, ...) __attribute__((format(printf, 1, 2))); int error(const char *err, ...) __attribute__((format(printf, 1, 2))); int error_errno(const char *err, ...) __attribute__((format(printf, 1, 2))); static inline int const_error(void) { return -1; } extern int munmap(void *__addr, size_t __len) __attribute__((__nothrow__, __leaf__)); extern size_t st_mult(size_t a, size_t b); extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); extern size_t xsize_t(off_t len); extern char *gettext(const char *__msgid) __attribute__((__nothrow__, __leaf__)) __attribute__((__format_arg__(1))); static inline __attribute__((format_arg(1))) const char *_(const char *msgid) { if (!*msgid) return ""; return gettext(msgid); } struct repository { /* [...snip...] */ const struct git_hash_algo *hash_algo; /* [...snip...] */ }; extern struct repository *the_repository; struct git_hash_algo { /* [...snip...] */ size_t rawsz; /* [...snip...] */ }; int git_open_cloexec(const char *name, int flags); struct revindex_header { uint32_t signature; uint32_t version; uint32_t hash_id; }; int load_revindex_from_disk(char *revindex_name, uint32_t num_objects, const uint32_t **data_p, size_t *len_p) { int fd, ret = 0; struct stat st; void *data = ((void *)0); size_t revindex_size; struct revindex_header *hdr; fd = git_open_cloexec(revindex_name, 00); if (fd < 0) { ret = -1; goto cleanup; } if (fstat(fd, &st)) { ret = (error_errno(_("failed to read %s"), revindex_name), const_error()); goto cleanup; } revindex_size = xsize_t(st.st_size); if (revindex_size < ((12) + (2 * the_repository->hash_algo->rawsz))) { ret = (error(_("reverse-index file %s is too small"), revindex_name), const_error()); goto cleanup; } if (revindex_size - ((12) + (2 * the_repository->hash_algo->rawsz)) != st_mult(sizeof(uint32_t), num_objects)) { ret = (error(_("reverse-index file %s is corrupt"), revindex_name), const_error()); goto cleanup; } data = xmmap(((void *)0), revindex_size, 0x1, 0x02, fd, 0); hdr = data; if (git_bswap32(hdr->signature) != 0x52494458) { ret = (error(_("reverse-index file %s has unknown signature"), revindex_name), const_error()); goto cleanup; } if (git_bswap32(hdr->version) != 1) { ret = (error(_("reverse-index file %s has unsupported version %" "u"), revindex_name, git_bswap32(hdr->version)), const_error()); goto cleanup; } if (!(git_bswap32(hdr->hash_id) == 1 || git_bswap32(hdr->hash_id) == 2)) { ret = (error(_("reverse-index file %s has unsupported hash id %" "u"), revindex_name, git_bswap32(hdr->hash_id)), const_error()); goto cleanup; } cleanup: if (ret) { if (data) /* { dg-bogus "check of 'data' for NULL after already dereferencing it" } */ munmap(data, revindex_size); } else { *len_p = revindex_size; *data_p = (const uint32_t *)data; } if (fd >= 0) close(fd); return ret; }