git

Форк
0
/
pack-mtimes.c 
133 строки · 2.9 Кб
1
#include "git-compat-util.h"
2
#include "gettext.h"
3
#include "pack-mtimes.h"
4
#include "object-file.h"
5
#include "object-store-ll.h"
6
#include "packfile.h"
7
#include "strbuf.h"
8

9
static char *pack_mtimes_filename(struct packed_git *p)
10
{
11
	size_t len;
12
	if (!strip_suffix(p->pack_name, ".pack", &len))
13
		BUG("pack_name does not end in .pack");
14
	return xstrfmt("%.*s.mtimes", (int)len, p->pack_name);
15
}
16

17
#define MTIMES_HEADER_SIZE (12)
18

19
struct mtimes_header {
20
	uint32_t signature;
21
	uint32_t version;
22
	uint32_t hash_id;
23
};
24

25
static int load_pack_mtimes_file(char *mtimes_file,
26
				 uint32_t num_objects,
27
				 const uint32_t **data_p, size_t *len_p)
28
{
29
	int fd, ret = 0;
30
	struct stat st;
31
	uint32_t *data = NULL;
32
	size_t mtimes_size, expected_size;
33
	struct mtimes_header header;
34

35
	fd = git_open(mtimes_file);
36

37
	if (fd < 0) {
38
		ret = -1;
39
		goto cleanup;
40
	}
41
	if (fstat(fd, &st)) {
42
		ret = error_errno(_("failed to read %s"), mtimes_file);
43
		goto cleanup;
44
	}
45

46
	mtimes_size = xsize_t(st.st_size);
47

48
	if (mtimes_size < MTIMES_HEADER_SIZE) {
49
		ret = error(_("mtimes file %s is too small"), mtimes_file);
50
		goto cleanup;
51
	}
52

53
	data = xmmap(NULL, mtimes_size, PROT_READ, MAP_PRIVATE, fd, 0);
54

55
	header.signature = ntohl(data[0]);
56
	header.version = ntohl(data[1]);
57
	header.hash_id = ntohl(data[2]);
58

59
	if (header.signature != MTIMES_SIGNATURE) {
60
		ret = error(_("mtimes file %s has unknown signature"), mtimes_file);
61
		goto cleanup;
62
	}
63

64
	if (header.version != 1) {
65
		ret = error(_("mtimes file %s has unsupported version %"PRIu32),
66
			    mtimes_file, header.version);
67
		goto cleanup;
68
	}
69

70
	if (!(header.hash_id == 1 || header.hash_id == 2)) {
71
		ret = error(_("mtimes file %s has unsupported hash id %"PRIu32),
72
			    mtimes_file, header.hash_id);
73
		goto cleanup;
74
	}
75

76

77
	expected_size = MTIMES_HEADER_SIZE;
78
	expected_size = st_add(expected_size, st_mult(sizeof(uint32_t), num_objects));
79
	expected_size = st_add(expected_size, 2 * (header.hash_id == 1 ? GIT_SHA1_RAWSZ : GIT_SHA256_RAWSZ));
80

81
	if (mtimes_size != expected_size) {
82
		ret = error(_("mtimes file %s is corrupt"), mtimes_file);
83
		goto cleanup;
84
	}
85

86
cleanup:
87
	if (ret) {
88
		if (data)
89
			munmap(data, mtimes_size);
90
	} else {
91
		*len_p = mtimes_size;
92
		*data_p = data;
93
	}
94

95
	if (fd >= 0)
96
		close(fd);
97
	return ret;
98
}
99

100
int load_pack_mtimes(struct packed_git *p)
101
{
102
	char *mtimes_name = NULL;
103
	int ret = 0;
104

105
	if (!p->is_cruft)
106
		return ret; /* not a cruft pack */
107
	if (p->mtimes_map)
108
		return ret; /* already loaded */
109

110
	ret = open_pack_index(p);
111
	if (ret < 0)
112
		goto cleanup;
113

114
	mtimes_name = pack_mtimes_filename(p);
115
	ret = load_pack_mtimes_file(mtimes_name,
116
				    p->num_objects,
117
				    &p->mtimes_map,
118
				    &p->mtimes_size);
119
cleanup:
120
	free(mtimes_name);
121
	return ret;
122
}
123

124
uint32_t nth_packed_mtime(struct packed_git *p, uint32_t pos)
125
{
126
	if (!p->mtimes_map)
127
		BUG("pack .mtimes file not loaded for %s", p->pack_name);
128
	if (p->num_objects <= pos)
129
		BUG("pack .mtimes out-of-bounds (%"PRIu32" vs %"PRIu32")",
130
		    pos, p->num_objects);
131

132
	return get_be32(p->mtimes_map + pos + 3);
133
}
134

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.