Skip to content

Commit 0317f45

Browse files
jonathantanmygitster
authored andcommitted
pack: move open_pack_index(), parse_pack_index()
alloc_packed_git() in packfile.c is duplicated from sha1_file.c. In a subsequent commit, alloc_packed_git() will be removed from sha1_file.c. Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8e21176 commit 0317f45

File tree

10 files changed

+163
-148
lines changed

10 files changed

+163
-148
lines changed

builtin/count-objects.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "builtin.h"
1111
#include "parse-options.h"
1212
#include "quote.h"
13+
#include "packfile.h"
1314

1415
static unsigned long garbage;
1516
static off_t size_garbage;

builtin/fsck.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "progress.h"
1616
#include "streaming.h"
1717
#include "decorate.h"
18+
#include "packfile.h"
1819

1920
#define REACHABLE 0x0001
2021
#define SEEN 0x0002

builtin/pack-objects.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "sha1-array.h"
2626
#include "argv-array.h"
2727
#include "mru.h"
28+
#include "packfile.h"
2829

2930
static const char *pack_usage[] = {
3031
N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"),

cache.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,8 +1605,6 @@ struct pack_entry {
16051605
struct packed_git *p;
16061606
};
16071607

1608-
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
1609-
16101608
/* A hook to report invalid files in pack directory */
16111609
#define PACKDIR_FILE_PACK 1
16121610
#define PACKDIR_FILE_IDX 2
@@ -1641,12 +1639,6 @@ extern int odb_mkstemp(struct strbuf *template, const char *pattern);
16411639
*/
16421640
extern int odb_pack_keep(const char *name);
16431641

1644-
/*
1645-
* mmap the index file for the specified packfile (if it is not
1646-
* already mmapped). Return 0 on success.
1647-
*/
1648-
extern int open_pack_index(struct packed_git *);
1649-
16501642
/*
16511643
* munmap the index file for the specified packfile (if it is
16521644
* currently mmapped).

pack-bitmap.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "pack-bitmap.h"
1010
#include "pack-revindex.h"
1111
#include "pack-objects.h"
12+
#include "packfile.h"
1213

1314
/*
1415
* An entry on the bitmap index, representing the bitmap for a given

pack-check.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "pack.h"
33
#include "pack-revindex.h"
44
#include "progress.h"
5+
#include "packfile.h"
56

67
struct idx_entry {
78
off_t offset;

packfile.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cache.h"
22
#include "mru.h"
3+
#include "pack.h"
34

45
char *odb_pack_name(struct strbuf *buf,
56
const unsigned char *sha1,
@@ -59,3 +60,151 @@ void pack_report(void)
5960
pack_open_windows, peak_pack_open_windows,
6061
sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
6162
}
63+
64+
/*
65+
* Open and mmap the index file at path, perform a couple of
66+
* consistency checks, then record its information to p. Return 0 on
67+
* success.
68+
*/
69+
static int check_packed_git_idx(const char *path, struct packed_git *p)
70+
{
71+
void *idx_map;
72+
struct pack_idx_header *hdr;
73+
size_t idx_size;
74+
uint32_t version, nr, i, *index;
75+
int fd = git_open(path);
76+
struct stat st;
77+
78+
if (fd < 0)
79+
return -1;
80+
if (fstat(fd, &st)) {
81+
close(fd);
82+
return -1;
83+
}
84+
idx_size = xsize_t(st.st_size);
85+
if (idx_size < 4 * 256 + 20 + 20) {
86+
close(fd);
87+
return error("index file %s is too small", path);
88+
}
89+
idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
90+
close(fd);
91+
92+
hdr = idx_map;
93+
if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
94+
version = ntohl(hdr->idx_version);
95+
if (version < 2 || version > 2) {
96+
munmap(idx_map, idx_size);
97+
return error("index file %s is version %"PRIu32
98+
" and is not supported by this binary"
99+
" (try upgrading GIT to a newer version)",
100+
path, version);
101+
}
102+
} else
103+
version = 1;
104+
105+
nr = 0;
106+
index = idx_map;
107+
if (version > 1)
108+
index += 2; /* skip index header */
109+
for (i = 0; i < 256; i++) {
110+
uint32_t n = ntohl(index[i]);
111+
if (n < nr) {
112+
munmap(idx_map, idx_size);
113+
return error("non-monotonic index %s", path);
114+
}
115+
nr = n;
116+
}
117+
118+
if (version == 1) {
119+
/*
120+
* Total size:
121+
* - 256 index entries 4 bytes each
122+
* - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
123+
* - 20-byte SHA1 of the packfile
124+
* - 20-byte SHA1 file checksum
125+
*/
126+
if (idx_size != 4*256 + nr * 24 + 20 + 20) {
127+
munmap(idx_map, idx_size);
128+
return error("wrong index v1 file size in %s", path);
129+
}
130+
} else if (version == 2) {
131+
/*
132+
* Minimum size:
133+
* - 8 bytes of header
134+
* - 256 index entries 4 bytes each
135+
* - 20-byte sha1 entry * nr
136+
* - 4-byte crc entry * nr
137+
* - 4-byte offset entry * nr
138+
* - 20-byte SHA1 of the packfile
139+
* - 20-byte SHA1 file checksum
140+
* And after the 4-byte offset table might be a
141+
* variable sized table containing 8-byte entries
142+
* for offsets larger than 2^31.
143+
*/
144+
unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
145+
unsigned long max_size = min_size;
146+
if (nr)
147+
max_size += (nr - 1)*8;
148+
if (idx_size < min_size || idx_size > max_size) {
149+
munmap(idx_map, idx_size);
150+
return error("wrong index v2 file size in %s", path);
151+
}
152+
if (idx_size != min_size &&
153+
/*
154+
* make sure we can deal with large pack offsets.
155+
* 31-bit signed offset won't be enough, neither
156+
* 32-bit unsigned one will be.
157+
*/
158+
(sizeof(off_t) <= 4)) {
159+
munmap(idx_map, idx_size);
160+
return error("pack too large for current definition of off_t in %s", path);
161+
}
162+
}
163+
164+
p->index_version = version;
165+
p->index_data = idx_map;
166+
p->index_size = idx_size;
167+
p->num_objects = nr;
168+
return 0;
169+
}
170+
171+
int open_pack_index(struct packed_git *p)
172+
{
173+
char *idx_name;
174+
size_t len;
175+
int ret;
176+
177+
if (p->index_data)
178+
return 0;
179+
180+
if (!strip_suffix(p->pack_name, ".pack", &len))
181+
die("BUG: pack_name does not end in .pack");
182+
idx_name = xstrfmt("%.*s.idx", (int)len, p->pack_name);
183+
ret = check_packed_git_idx(idx_name, p);
184+
free(idx_name);
185+
return ret;
186+
}
187+
188+
static struct packed_git *alloc_packed_git(int extra)
189+
{
190+
struct packed_git *p = xmalloc(st_add(sizeof(*p), extra));
191+
memset(p, 0, sizeof(*p));
192+
p->pack_fd = -1;
193+
return p;
194+
}
195+
196+
struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
197+
{
198+
const char *path = sha1_pack_name(sha1);
199+
size_t alloc = st_add(strlen(path), 1);
200+
struct packed_git *p = alloc_packed_git(alloc);
201+
202+
memcpy(p->pack_name, path, alloc); /* includes NUL */
203+
hashcpy(p->sha1, sha1);
204+
if (check_packed_git_idx(idx_path, p)) {
205+
free(p);
206+
return NULL;
207+
}
208+
209+
return p;
210+
}

packfile.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ extern unsigned int pack_max_fds;
3333
extern size_t peak_pack_mapped;
3434
extern size_t pack_mapped;
3535

36+
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
37+
3638
extern void pack_report(void);
3739

40+
/*
41+
* mmap the index file for the specified packfile (if it is not
42+
* already mmapped). Return 0 on success.
43+
*/
44+
extern int open_pack_index(struct packed_git *);
45+
3846
#endif

sha1_file.c

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -681,130 +681,6 @@ static int has_loose_object(const unsigned char *sha1)
681681
return check_and_freshen(sha1, 0);
682682
}
683683

684-
/*
685-
* Open and mmap the index file at path, perform a couple of
686-
* consistency checks, then record its information to p. Return 0 on
687-
* success.
688-
*/
689-
static int check_packed_git_idx(const char *path, struct packed_git *p)
690-
{
691-
void *idx_map;
692-
struct pack_idx_header *hdr;
693-
size_t idx_size;
694-
uint32_t version, nr, i, *index;
695-
int fd = git_open(path);
696-
struct stat st;
697-
698-
if (fd < 0)
699-
return -1;
700-
if (fstat(fd, &st)) {
701-
close(fd);
702-
return -1;
703-
}
704-
idx_size = xsize_t(st.st_size);
705-
if (idx_size < 4 * 256 + 20 + 20) {
706-
close(fd);
707-
return error("index file %s is too small", path);
708-
}
709-
idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
710-
close(fd);
711-
712-
hdr = idx_map;
713-
if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
714-
version = ntohl(hdr->idx_version);
715-
if (version < 2 || version > 2) {
716-
munmap(idx_map, idx_size);
717-
return error("index file %s is version %"PRIu32
718-
" and is not supported by this binary"
719-
" (try upgrading GIT to a newer version)",
720-
path, version);
721-
}
722-
} else
723-
version = 1;
724-
725-
nr = 0;
726-
index = idx_map;
727-
if (version > 1)
728-
index += 2; /* skip index header */
729-
for (i = 0; i < 256; i++) {
730-
uint32_t n = ntohl(index[i]);
731-
if (n < nr) {
732-
munmap(idx_map, idx_size);
733-
return error("non-monotonic index %s", path);
734-
}
735-
nr = n;
736-
}
737-
738-
if (version == 1) {
739-
/*
740-
* Total size:
741-
* - 256 index entries 4 bytes each
742-
* - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
743-
* - 20-byte SHA1 of the packfile
744-
* - 20-byte SHA1 file checksum
745-
*/
746-
if (idx_size != 4*256 + nr * 24 + 20 + 20) {
747-
munmap(idx_map, idx_size);
748-
return error("wrong index v1 file size in %s", path);
749-
}
750-
} else if (version == 2) {
751-
/*
752-
* Minimum size:
753-
* - 8 bytes of header
754-
* - 256 index entries 4 bytes each
755-
* - 20-byte sha1 entry * nr
756-
* - 4-byte crc entry * nr
757-
* - 4-byte offset entry * nr
758-
* - 20-byte SHA1 of the packfile
759-
* - 20-byte SHA1 file checksum
760-
* And after the 4-byte offset table might be a
761-
* variable sized table containing 8-byte entries
762-
* for offsets larger than 2^31.
763-
*/
764-
unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
765-
unsigned long max_size = min_size;
766-
if (nr)
767-
max_size += (nr - 1)*8;
768-
if (idx_size < min_size || idx_size > max_size) {
769-
munmap(idx_map, idx_size);
770-
return error("wrong index v2 file size in %s", path);
771-
}
772-
if (idx_size != min_size &&
773-
/*
774-
* make sure we can deal with large pack offsets.
775-
* 31-bit signed offset won't be enough, neither
776-
* 32-bit unsigned one will be.
777-
*/
778-
(sizeof(off_t) <= 4)) {
779-
munmap(idx_map, idx_size);
780-
return error("pack too large for current definition of off_t in %s", path);
781-
}
782-
}
783-
784-
p->index_version = version;
785-
p->index_data = idx_map;
786-
p->index_size = idx_size;
787-
p->num_objects = nr;
788-
return 0;
789-
}
790-
791-
int open_pack_index(struct packed_git *p)
792-
{
793-
char *idx_name;
794-
size_t len;
795-
int ret;
796-
797-
if (p->index_data)
798-
return 0;
799-
800-
if (!strip_suffix(p->pack_name, ".pack", &len))
801-
die("BUG: pack_name does not end in .pack");
802-
idx_name = xstrfmt("%.*s.idx", (int)len, p->pack_name);
803-
ret = check_packed_git_idx(idx_name, p);
804-
free(idx_name);
805-
return ret;
806-
}
807-
808684
static void scan_windows(struct packed_git *p,
809685
struct packed_git **lru_p,
810686
struct pack_window **lru_w,
@@ -1302,22 +1178,6 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)
13021178
return p;
13031179
}
13041180

1305-
struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
1306-
{
1307-
const char *path = sha1_pack_name(sha1);
1308-
size_t alloc = st_add(strlen(path), 1);
1309-
struct packed_git *p = alloc_packed_git(alloc);
1310-
1311-
memcpy(p->pack_name, path, alloc); /* includes NUL */
1312-
hashcpy(p->sha1, sha1);
1313-
if (check_packed_git_idx(idx_path, p)) {
1314-
free(p);
1315-
return NULL;
1316-
}
1317-
1318-
return p;
1319-
}
1320-
13211181
void install_packed_git(struct packed_git *pack)
13221182
{
13231183
if (pack->pack_fd != -1)

sha1_name.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "remote.h"
1010
#include "dir.h"
1111
#include "sha1-array.h"
12+
#include "packfile.h"
1213

1314
static int get_oid_oneline(const char *, struct object_id *, struct commit_list *);
1415

0 commit comments

Comments
 (0)