Line Flow Count Block(s) Source
1 - /*
2 - * Copyright (C) the libgit2 contributors. All rights reserved.
3 - *
4 - * This file is part of libgit2, distributed under the GNU GPL v2 with
5 - * a Linking Exception. For full terms see the included COPYING file.
6 - */
7 -
8 - #include "common.h"
9 -
10 - #include <zlib.h>
11 - #include "git2/object.h"
12 - #include "git2/sys/odb_backend.h"
13 - #include "futils.h"
14 - #include "hash.h"
15 - #include "odb.h"
16 - #include "delta.h"
17 - #include "filebuf.h"
18 - #include "object.h"
19 - #include "zstream.h"
20 -
21 - #include "git2/odb_backend.h"
22 - #include "git2/types.h"
23 -
24 - /* maximum possible header length */
25 - #define MAX_HEADER_LEN 64
26 -
27 - typedef struct { /* object header data */
28 - git_object_t type; /* object type */
29 - size_t size; /* object size */
30 - } obj_hdr;
31 -
32 - typedef struct {
33 - git_odb_stream stream;
34 - git_filebuf fbuf;
35 - } loose_writestream;
36 -
37 - typedef struct {
38 - git_odb_stream stream;
39 - git_map map;
40 - char start[MAX_HEADER_LEN];
41 - size_t start_len;
42 - size_t start_read;
43 - git_zstream zstream;
44 - } loose_readstream;
45 -
46 - typedef struct loose_backend {
47 - git_odb_backend parent;
48 -
49 - int object_zlib_level; /** loose object zlib compression level. */
50 - int fsync_object_files; /** loose object file fsync flag. */
51 - mode_t object_file_mode;
52 - mode_t object_dir_mode;
53 -
54 - size_t objects_dirlen;
55 - char objects_dir[GIT_FLEX_ARRAY];
56 - } loose_backend;
57 -
58 - /* State structure for exploring directories,
59 - * in order to locate objects matching a short oid.
60 - */
61 - typedef struct {
62 - size_t dir_len;
63 - unsigned char short_oid[GIT_OID_HEXSZ]; /* hex formatted oid to match */
64 - size_t short_oid_len;
65 - int found; /* number of matching
66 - * objects already found */
67 - unsigned char res_oid[GIT_OID_HEXSZ]; /* hex formatted oid of
68 - * the object found */
69 - } loose_locate_object_state;
70 -
71 -
72 - /***********************************************************
73 - *
74 - * MISCELLANEOUS HELPER FUNCTIONS
75 - *
76 - ***********************************************************/
77 -
78 66168 2 static int object_file_name(
79 - git_buf *name, const loose_backend *be, const git_oid *id)
80 - {
81 - size_t alloclen;
82 -
83 - /* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
84 66204 2-8 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, be->objects_dirlen, GIT_OID_HEXSZ);
85 66192 9-15 GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 3);
86 66316 16,17 if (git_buf_grow(name, alloclen) < 0)
87 ##### 18 return -1;
88 -
89 66316 19 git_buf_set(name, be->objects_dir, be->objects_dirlen);
90 66422 20 git_path_to_dir(name);
91 -
92 - /* loose object filename: aa/aaa... (41 bytes) */
93 66373 21 git_oid_pathfmt(name->ptr + name->size, id);
94 66384 22 name->size += GIT_OID_HEXSZ + 1;
95 66384 22 name->ptr[name->size] = '\0';
96 -
97 66384 22 return 0;
98 - }
99 -
100 1643 2 static int object_mkdir(const git_buf *name, const loose_backend *be)
101 - {
102 1643 2,2 return git_futils_mkdir_relative(
103 1643 2 name->ptr + be->objects_dirlen, be->objects_dir, be->object_dir_mode,
104 - GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR, NULL);
105 - }
106 -
107 11 2 static int parse_header_packlike(
108 - obj_hdr *out, size_t *out_len, const unsigned char *data, size_t len)
109 - {
110 - unsigned long c;
111 11 2 size_t shift, size, used = 0;
112 -
113 11 2 if (len == 0)
114 ##### 3 goto on_error;
115 -
116 11 4 c = data[used++];
117 11 4 out->type = (c >> 4) & 7;
118 -
119 11 4 size = c & 15;
120 11 4 shift = 4;
121 11 4,10 while (c & 0x80) {
122 ##### 5 if (len <= used)
123 ##### 6 goto on_error;
124 -
125 ##### 7 if (sizeof(size_t) * 8 <= shift)
126 ##### 8 goto on_error;
127 -
128 ##### 9 c = data[used++];
129 ##### 9 size += (c & 0x7f) << shift;
130 ##### 9 shift += 7;
131 - }
132 -
133 11 11 out->size = size;
134 -
135 11 11 if (out_len)
136 11 12 *out_len = used;
137 -
138 11 13 return 0;
139 -
140 - on_error:
141 ##### 14 git_error_set(GIT_ERROR_OBJECT, "failed to parse loose object: invalid header");
142 ##### 15 return -1;
143 - }
144 -
145 - 2 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files)static int parse_header(
146 - obj_hdr *out,
147 - size_t *out_len,
148 - const unsigned char *_data,
149 - size_t data_len)
150 - {
151 - 2 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) const char *data = (char *)_data;
152 - size_t i, typename_len, size_idx, size_len;
153 - int64_t size;
154 -
155 - 2 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) *out_len = 0;
156 -
157 - /* find the object type name */
158 - 2,5,6 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) for (i = 0, typename_len = 0; i < data_len; i++, typename_len++) {
159 - 3 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) if (data[i] == ' ')
160 - 4 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) break;
161 - }
162 -
163 - 7 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) if (typename_len == data_len)
164 - 8 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) goto on_error;
165 -
166 - 9 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) out->type = git_object_stringn2type(data, typename_len);
167 -
168 - 10 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) size_idx = typename_len + 1;
169 - 10,13,14 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) for (i = size_idx, size_len = 0; i < data_len; i++, size_len++) {
170 - 11 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) if (data[i] == '\0')
171 - 12 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) break;
172 - }
173 -
174 - 15 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) if (i == data_len)
175 - 16 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) goto on_error;
176 -
177 - 17-19 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) if (git__strntol64(&size, &data[size_idx], size_len, NULL, 10) < 0 ||
178 - 19 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) size < 0)
179 - goto on_error;
180 -
181 - if ((uint64_t)size > SIZE_MAX) {
182 - git_error_set(GIT_ERROR_OBJECT, "object is larger than available memory");
183 - return -1;
184 - }
185 -
186 - 20 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) out->size = (size_t)size;
187 -
188 - 20-25 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) if (GIT_ADD_SIZET_OVERFLOW(out_len, i, 1))
189 - 26 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) goto on_error;
190 -
191 - 27 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) return 0;
192 -
193 - on_error:
194 - 28 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_OBJECT, "failed to parse loose object: invalid header");
195 - 29 suppressed: function cannot be solved parse_header (automatic due to inconsistent arc counts in .gcda files) return -1;
196 - }
197 -
198 - 2 suppressed: function cannot be solved is_zlib_compressed_data (automatic due to inconsistent arc counts in .gcda files)static int is_zlib_compressed_data(unsigned char *data, size_t data_len)
199 - {
200 - unsigned int w;
201 -
202 - 2 suppressed: function cannot be solved is_zlib_compressed_data (automatic due to inconsistent arc counts in .gcda files) if (data_len < 2)
203 - 3 suppressed: function cannot be solved is_zlib_compressed_data (automatic due to inconsistent arc counts in .gcda files) return 0;
204 -
205 - 4 suppressed: function cannot be solved is_zlib_compressed_data (automatic due to inconsistent arc counts in .gcda files) w = ((unsigned int)(data[0]) << 8) + data[1];
206 - 4 suppressed: function cannot be solved is_zlib_compressed_data (automatic due to inconsistent arc counts in .gcda files) return (data[0] & 0x8F) == 0x08 && !(w % 31);
207 - }
208 -
209 - /***********************************************************
210 - *
211 - * ODB OBJECT READING & WRITING
212 - *
213 - * Backend for the public API; read headers and full objects
214 - * from the ODB. Write raw data to the ODB.
215 - *
216 - ***********************************************************/
217 -
218 -
219 - /*
220 - * At one point, there was a loose object format that was intended to
221 - * mimic the format used in pack-files. This was to allow easy copying
222 - * of loose object data into packs. This format is no longer used, but
223 - * we must still read it.
224 - */
225 3 2 static int read_loose_packlike(git_rawobj *out, git_buf *obj)
226 - {
227 3 2 git_buf body = GIT_BUF_INIT;
228 - const unsigned char *obj_data;
229 - obj_hdr hdr;
230 - size_t obj_len, head_len, alloc_size;
231 - int error;
232 -
233 3 2 obj_data = (unsigned char *)obj->ptr;
234 3 2 obj_len = obj->size;
235 -
236 - /*
237 - * read the object header, which is an (uncompressed)
238 - * binary encoding of the object type and size.
239 - */
240 3 2,3 if ((error = parse_header_packlike(&hdr, &head_len, obj_data, obj_len)) < 0)
241 ##### 4 goto done;
242 -
243 3 5-7 if (!git_object_typeisloose(hdr.type) || head_len > obj_len) {
244 2 8 git_error_set(GIT_ERROR_ODB, "failed to inflate loose object");
245 2 9 error = -1;
246 2 9 goto done;
247 - }
248 -
249 1 10 obj_data += head_len;
250 1 10 obj_len -= head_len;
251 -
252 - /*
253 - * allocate a buffer and inflate the data into it
254 - */
255 1 10-12,14 if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) ||
256 1 13 git_buf_init(&body, alloc_size) < 0) {
257 ##### 15 error = -1;
258 ##### 15 goto done;
259 - }
260 -
261 1 16,17 if ((error = git_zstream_inflatebuf(&body, obj_data, obj_len)) < 0)
262 ##### 18 goto done;
263 -
264 1 19 out->len = hdr.size;
265 1 19 out->type = hdr.type;
266 1 19,20 out->data = git_buf_detach(&body);
267 -
268 - done:
269 3 21 git_buf_dispose(&body);
270 3 22 return error;
271 - }
272 -
273 - 2 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files)static int read_loose_standard(git_rawobj *out, git_buf *obj)
274 - {
275 - 2 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) git_zstream zstream = GIT_ZSTREAM_INIT;
276 - 2 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) unsigned char head[MAX_HEADER_LEN], *body = NULL;
277 - size_t decompressed, head_len, body_len, alloc_size;
278 - obj_hdr hdr;
279 - int error;
280 -
281 - 2,3,6,7 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0 ||
282 - 4,5 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) (error = git_zstream_set_input(&zstream, git_buf_cstr(obj), git_buf_len(obj))) < 0)
283 - goto done;
284 -
285 - 8 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) decompressed = sizeof(head);
286 -
287 - /*
288 - * inflate the initial part of the compressed buffer in order to
289 - * parse the header; read the largest header possible, then push the
290 - * remainder into the body buffer.
291 - */
292 - 8-11 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if ((error = git_zstream_get_output(head, &decompressed, &zstream)) < 0 ||
293 - 10 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) (error = parse_header(&hdr, &head_len, head, decompressed)) < 0)
294 - goto done;
295 -
296 - 12,13 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if (!git_object_typeisloose(hdr.type)) {
297 - 14 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_ODB, "failed to inflate disk object");
298 - 15 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) error = -1;
299 - 15 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) goto done;
300 - }
301 -
302 - /*
303 - * allocate a buffer and inflate the object data into it
304 - * (including the initial sequence in the head buffer).
305 - */
306 - 16-20 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) ||
307 - 19 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) (body = git__malloc(alloc_size)) == NULL) {
308 - 21 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) error = -1;
309 - 21 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) goto done;
310 - }
311 -
312 - 22,23 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) assert(decompressed >= head_len);
313 - 24 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) body_len = decompressed - head_len;
314 -
315 - 24 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if (body_len)
316 - 25 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) memcpy(body, head + head_len, body_len);
317 -
318 - 26 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) decompressed = hdr.size - body_len;
319 - 26,27 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if ((error = git_zstream_get_output(body + body_len, &decompressed, &zstream)) < 0)
320 - 28 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) goto done;
321 -
322 - 29,30 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if (!git_zstream_done(&zstream)) {
323 - 31 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) git_error_set(GIT_ERROR_ZLIB, "failed to finish zlib inflation: stream aborted prematurely");
324 - 32 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) error = -1;
325 - 32 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) goto done;
326 - }
327 -
328 - 33 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) body[hdr.size] = '\0';
329 -
330 - 33 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) out->data = body;
331 - 33 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) out->len = hdr.size;
332 - 33 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) out->type = hdr.type;
333 -
334 - done:
335 - 34 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) if (error < 0)
336 - 35 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) git__free(body);
337 -
338 - 36 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) git_zstream_free(&zstream);
339 - 37 suppressed: function cannot be solved read_loose_standard (automatic due to inconsistent arc counts in .gcda files) return error;
340 - }
341 -
342 - 2 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files)static int read_loose(git_rawobj *out, git_buf *loc)
343 - {
344 - int error;
345 - 2 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) git_buf obj = GIT_BUF_INIT;
346 -
347 - 2-4 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) assert(out && loc);
348 -
349 - 5,6 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) if (git_buf_oom(loc))
350 - 7 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) return -1;
351 -
352 - 8 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) out->data = NULL;
353 - 8 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) out->len = 0;
354 - 8 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) out->type = GIT_OBJECT_INVALID;
355 -
356 - 8,9 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) if ((error = git_futils_readbuffer(&obj, loc->ptr)) < 0)
357 - 10 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) goto done;
358 -
359 - 11,12 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) if (!is_zlib_compressed_data((unsigned char *)obj.ptr, obj.size))
360 - 13 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) error = read_loose_packlike(out, &obj);
361 - else
362 - 14 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) error = read_loose_standard(out, &obj);
363 -
364 - done:
365 - 15 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) git_buf_dispose(&obj);
366 - 16 suppressed: function cannot be solved read_loose (automatic due to inconsistent arc counts in .gcda files) return error;
367 - }
368 -
369 1 2 static int read_header_loose_packlike(
370 - git_rawobj *out, const unsigned char *data, size_t len)
371 - {
372 - obj_hdr hdr;
373 - size_t header_len;
374 - int error;
375 -
376 1 2,3 if ((error = parse_header_packlike(&hdr, &header_len, data, len)) < 0)
377 ##### 4 return error;
378 -
379 1 5 out->len = hdr.size;
380 1 5 out->type = hdr.type;
381 -
382 1 5 return error;
383 - }
384 -
385 10019 2 static int read_header_loose_standard(
386 - git_rawobj *out, const unsigned char *data, size_t len)
387 - {
388 10019 2 git_zstream zs = GIT_ZSTREAM_INIT;
389 - obj_hdr hdr;
390 - unsigned char inflated[MAX_HEADER_LEN];
391 10019 2 size_t header_len, inflated_len = sizeof(inflated);
392 - int error;
393 -
394 10019 2-5 if ((error = git_zstream_init(&zs, GIT_ZSTREAM_INFLATE)) < 0 ||
395 10019 6,7 (error = git_zstream_set_input(&zs, data, len)) < 0 ||
396 10019 8,9 (error = git_zstream_get_output_chunk(inflated, &inflated_len, &zs)) < 0 ||
397 10019 8 (error = parse_header(&hdr, &header_len, inflated, inflated_len)) < 0)
398 - goto done;
399 -
400 10019 10 out->len = hdr.size;
401 10019 10 out->type = hdr.type;
402 -
403 - done:
404 10019 11 git_zstream_free(&zs);
405 10019 12 return error;
406 - }
407 -
408 10020 2 static int read_header_loose(git_rawobj *out, git_buf *loc)
409 - {
410 - unsigned char obj[1024];
411 - ssize_t obj_len;
412 - int fd, error;
413 -
414 10020 2-4 assert(out && loc);
415 -
416 10020 5,6 if (git_buf_oom(loc))
417 ##### 7 return -1;
418 -
419 10020 8 out->data = NULL;
420 -
421 10020 8,9 if ((error = fd = git_futils_open_ro(loc->ptr)) < 0)
422 ##### 10 goto done;
423 -
424 10020 11,12 if ((obj_len = p_read(fd, obj, sizeof(obj))) < 0) {
425 ##### 13 error = (int)obj_len;
426 ##### 13 goto done;
427 - }
428 -
429 10020 14,15 if (!is_zlib_compressed_data(obj, (size_t)obj_len))
430 1 16 error = read_header_loose_packlike(out, obj, (size_t)obj_len);
431 - else
432 10019 17 error = read_header_loose_standard(out, obj, (size_t)obj_len);
433 -
434 10020 18-20 if (!error && !git_object_typeisloose(out->type)) {
435 ##### 21 git_error_set(GIT_ERROR_ZLIB, "failed to read loose object header");
436 ##### 22 error = -1;
437 ##### 22 goto done;
438 - }
439 -
440 - done:
441 10020 23 if (fd >= 0)
442 10020 24 p_close(fd);
443 10020 25 return error;
444 - }
445 -
446 58972 2 static int locate_object(
447 - git_buf *object_location,
448 - loose_backend *backend,
449 - const git_oid *oid)
450 - {
451 58972 2 int error = object_file_name(object_location, backend, oid);
452 -
453 59343 3-5 if (!error && !git_path_exists(object_location->ptr))
454 786 6 return GIT_ENOTFOUND;
455 -
456 58641 7 return error;
457 - }
458 -
459 - /* Explore an entry of a directory and see if it matches a short oid */
460 426 2 static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) {
461 426 2 loose_locate_object_state *sstate = (loose_locate_object_state *)state;
462 -
463 426 2,3 if (git_buf_len(pathbuf) - sstate->dir_len != GIT_OID_HEXSZ - 2) {
464 - /* Entry cannot be an object. Continue to next entry */
465 ##### 4 return 0;
466 - }
467 -
468 426 5,6 if (git_path_isdir(pathbuf->ptr) == false) {
469 - /* We are already in the directory matching the 2 first hex characters,
470 - * compare the first ncmp characters of the oids */
471 426 7,7 if (!memcmp(sstate->short_oid + 2,
472 426 7 (unsigned char *)pathbuf->ptr + sstate->dir_len,
473 426 7 sstate->short_oid_len - 2)) {
474 -
475 361 8 if (!sstate->found) {
476 360 9 sstate->res_oid[0] = sstate->short_oid[0];
477 360 9 sstate->res_oid[1] = sstate->short_oid[1];
478 360 9 memcpy(sstate->res_oid+2, pathbuf->ptr+sstate->dir_len, GIT_OID_HEXSZ-2);
479 - }
480 361 10 sstate->found++;
481 - }
482 - }
483 -
484 426 11 if (sstate->found > 1)
485 1 12 return GIT_EAMBIGUOUS;
486 -
487 425 13 return 0;
488 - }
489 -
490 - /* Locate an object matching a given short oid */
491 557 2 static int locate_object_short_oid(
492 - git_buf *object_location,
493 - git_oid *res_oid,
494 - loose_backend *backend,
495 - const git_oid *short_oid,
496 - size_t len)
497 - {
498 557 2 char *objects_dir = backend->objects_dir;
499 557 2 size_t dir_len = strlen(objects_dir), alloc_len;
500 - loose_locate_object_state state;
501 - int error;
502 -
503 - /* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
504 557 2-8 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
505 557 9-15 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 3);
506 557 16,17 if (git_buf_grow(object_location, alloc_len) < 0)
507 ##### 18 return -1;
508 -
509 557 19 git_buf_set(object_location, objects_dir, dir_len);
510 557 20 git_path_to_dir(object_location);
511 -
512 - /* save adjusted position at end of dir so it can be restored later */
513 557 21 dir_len = git_buf_len(object_location);
514 -
515 - /* Convert raw oid to hex formatted oid */
516 557 22 git_oid_fmt((char *)state.short_oid, short_oid);
517 -
518 - /* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
519 557 23,24 if (git_buf_put(object_location, (char *)state.short_oid, 3) < 0)
520 ##### 25 return -1;
521 557 26 object_location->ptr[object_location->size - 1] = '/';
522 -
523 - /* Check that directory exists */
524 557 26,27 if (git_path_isdir(object_location->ptr) == false)
525 183 28 return git_odb__error_notfound("no matching loose object for prefix",
526 - short_oid, len);
527 -
528 374 29 state.dir_len = git_buf_len(object_location);
529 374 30 state.short_oid_len = len;
530 374 30 state.found = 0;
531 -
532 - /* Explore directory to find a unique object matching short_oid */
533 374 30 error = git_path_direach(
534 - object_location, 0, fn_locate_object_short_oid, &state);
535 374 31,32 if (error < 0 && error != GIT_EAMBIGUOUS)
536 ##### 33 return error;
537 -
538 374 34 if (!state.found)
539 14 35 return git_odb__error_notfound("no matching loose object for prefix",
540 - short_oid, len);
541 -
542 360 36 if (state.found > 1)
543 1 37 return git_odb__error_ambiguous("multiple matches in loose objects");
544 -
545 - /* Convert obtained hex formatted oid to raw */
546 359 38 error = git_oid_fromstr(res_oid, (char *)state.res_oid);
547 359 39 if (error)
548 ##### 40 return error;
549 -
550 - /* Update the location according to the oid obtained */
551 359 41-47 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
552 359 48-54 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
553 -
554 359 55 git_buf_truncate(object_location, dir_len);
555 359 56,57 if (git_buf_grow(object_location, alloc_len) < 0)
556 ##### 58 return -1;
557 -
558 359 59 git_oid_pathfmt(object_location->ptr + dir_len, res_oid);
559 -
560 359 60 object_location->size += GIT_OID_HEXSZ + 1;
561 359 60 object_location->ptr[object_location->size] = '\0';
562 -
563 359 60 return 0;
564 - }
565 -
566 -
567 -
568 -
569 -
570 -
571 -
572 -
573 -
574 - /***********************************************************
575 - *
576 - * LOOSE BACKEND PUBLIC API
577 - *
578 - * Implement the git_odb_backend API calls
579 - *
580 - ***********************************************************/
581 -
582 10102 2 static int loose_backend__read_header(size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
583 - {
584 10102 2 git_buf object_path = GIT_BUF_INIT;
585 - git_rawobj raw;
586 - int error;
587 -
588 10102 2-4 assert(backend && oid);
589 -
590 10102 5 raw.len = 0;
591 10102 5 raw.type = GIT_OBJECT_INVALID;
592 -
593 10102 5,6 if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
594 82 7 error = git_odb__error_notfound("no matching loose object",
595 - oid, GIT_OID_HEXSZ);
596 10020 8,9 } else if ((error = read_header_loose(&raw, &object_path)) == 0) {
597 10020 10 *len_p = raw.len;
598 10020 10 *type_p = raw.type;
599 - }
600 -
601 10102 11 git_buf_dispose(&object_path);
602 -
603 10102 12 return error;
604 - }
605 -
606 - 2 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files)static int loose_backend__read(void **buffer_p, size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
607 - {
608 - 2 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) git_buf object_path = GIT_BUF_INIT;
609 - git_rawobj raw;
610 - 2 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) int error = 0;
611 -
612 - 2-4 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) assert(backend && oid);
613 -
614 - 5,6 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
615 - 7 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) error = git_odb__error_notfound("no matching loose object",
616 - oid, GIT_OID_HEXSZ);
617 - 8,9 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) } else if ((error = read_loose(&raw, &object_path)) == 0) {
618 - 10 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) *buffer_p = raw.data;
619 - 10 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) *len_p = raw.len;
620 - 10 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) *type_p = raw.type;
621 - }
622 -
623 - 11 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) git_buf_dispose(&object_path);
624 -
625 - 12 suppressed: function cannot be solved loose_backend__read (automatic due to inconsistent arc counts in .gcda files) return error;
626 - }
627 -
628 471 2 static int loose_backend__read_prefix(
629 - git_oid *out_oid,
630 - void **buffer_p,
631 - size_t *len_p,
632 - git_object_t *type_p,
633 - git_odb_backend *backend,
634 - const git_oid *short_oid,
635 - size_t len)
636 - {
637 471 2 int error = 0;
638 -
639 471 2-4 assert(len >= GIT_OID_MINPREFIXLEN && len <= GIT_OID_HEXSZ);
640 -
641 471 5 if (len == GIT_OID_HEXSZ) {
642 - /* We can fall back to regular read method */
643 3 6 error = loose_backend__read(buffer_p, len_p, type_p, backend, short_oid);
644 3 7 if (!error)
645 3 8,9 git_oid_cpy(out_oid, short_oid);
646 - } else {
647 468 10 git_buf object_path = GIT_BUF_INIT;
648 - git_rawobj raw;
649 -
650 468 10-12 assert(backend && short_oid);
651 -
652 468 13,14 if ((error = locate_object_short_oid(&object_path, out_oid,
653 312 15,16 (loose_backend *)backend, short_oid, len)) == 0 &&
654 - (error = read_loose(&raw, &object_path)) == 0)
655 - {
656 312 17 *buffer_p = raw.data;
657 312 17 *len_p = raw.len;
658 312 17 *type_p = raw.type;
659 - }
660 -
661 468 18,19 git_buf_dispose(&object_path);
662 - }
663 -
664 471 20 return error;
665 - }
666 -
667 934 2 static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
668 - {
669 934 2 git_buf object_path = GIT_BUF_INIT;
670 - int error;
671 -
672 934 2-4 assert(backend && oid);
673 -
674 934 5 error = locate_object(&object_path, (loose_backend *)backend, oid);
675 -
676 934 6 git_buf_dispose(&object_path);
677 -
678 934 7 return !error;
679 - }
680 -
681 89 2 static int loose_backend__exists_prefix(
682 - git_oid *out, git_odb_backend *backend, const git_oid *short_id, size_t len)
683 - {
684 89 2 git_buf object_path = GIT_BUF_INIT;
685 - int error;
686 -
687 89 2-6 assert(backend && out && short_id && len >= GIT_OID_MINPREFIXLEN);
688 -
689 89 7 error = locate_object_short_oid(
690 - &object_path, out, (loose_backend *)backend, short_id, len);
691 -
692 89 8 git_buf_dispose(&object_path);
693 -
694 89 9 return error;
695 - }
696 -
697 - struct foreach_state {
698 - size_t dir_len;
699 - git_odb_foreach_cb cb;
700 - void *data;
701 - };
702 -
703 133 2 GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
704 - {
705 133 2 int v, i = 0;
706 133 2 if (strlen(ptr) != GIT_OID_HEXSZ+1)
707 12 3 return -1;
708 -
709 121 4 if (ptr[2] != '/') {
710 ##### 5 return -1;
711 - }
712 -
713 121 6,7 v = (git__fromhex(ptr[i]) << 4) | git__fromhex(ptr[i+1]);
714 121 8 if (v < 0)
715 ##### 9 return -1;
716 -
717 121 10 oid->id[0] = (unsigned char) v;
718 -
719 121 10 ptr += 3;
720 2420 10,15,16 for (i = 0; i < 38; i += 2) {
721 2299 11,12 v = (git__fromhex(ptr[i]) << 4) | git__fromhex(ptr[i + 1]);
722 2299 13 if (v < 0)
723 ##### 14 return -1;
724 -
725 2299 15 oid->id[1 + i/2] = (unsigned char) v;
726 - }
727 -
728 121 17 return 0;
729 - }
730 -
731 133 2 static int foreach_object_dir_cb(void *_state, git_buf *path)
732 - {
733 - git_oid oid;
734 133 2 struct foreach_state *state = (struct foreach_state *) _state;
735 -
736 133 2,3 if (filename_to_oid(&oid, path->ptr + state->dir_len) < 0)
737 12 4 return 0;
738 -
739 121 5 return git_error_set_after_callback_function(
740 121 5 state->cb(&oid, state->data), "git_odb_foreach");
741 - }
742 -
743 105 2 static int foreach_cb(void *_state, git_buf *path)
744 - {
745 105 2 struct foreach_state *state = (struct foreach_state *) _state;
746 -
747 - /* non-dir is some stray file, ignore it */
748 105 2-4 if (!git_path_isdir(git_buf_cstr(path)))
749 1 5 return 0;
750 -
751 104 6 return git_path_direach(path, 0, foreach_object_dir_cb, state);
752 - }
753 -
754 3 2 static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb cb, void *data)
755 - {
756 - char *objects_dir;
757 - int error;
758 3 2 git_buf buf = GIT_BUF_INIT;
759 - struct foreach_state state;
760 3 2 loose_backend *backend = (loose_backend *) _backend;
761 -
762 3 2-4 assert(backend && cb);
763 -
764 3 5 objects_dir = backend->objects_dir;
765 -
766 3 5 git_buf_sets(&buf, objects_dir);
767 3 6 git_path_to_dir(&buf);
768 3 7,8 if (git_buf_oom(&buf))
769 ##### 9 return -1;
770 -
771 3 10 memset(&state, 0, sizeof(state));
772 3 10 state.cb = cb;
773 3 10 state.data = data;
774 3 10 state.dir_len = git_buf_len(&buf);
775 -
776 3 11 error = git_path_direach(&buf, 0, foreach_cb, &state);
777 -
778 3 12 git_buf_dispose(&buf);
779 -
780 3 13 return error;
781 - }
782 -
783 753 2 static int loose_backend__writestream_finalize(git_odb_stream *_stream, const git_oid *oid)
784 - {
785 753 2 loose_writestream *stream = (loose_writestream *)_stream;
786 753 2 loose_backend *backend = (loose_backend *)_stream->backend;
787 753 2 git_buf final_path = GIT_BUF_INIT;
788 753 2 int error = 0;
789 -
790 753 2,3,5 if (object_file_name(&final_path, backend, oid) < 0 ||
791 753 4 object_mkdir(&final_path, backend) < 0)
792 ##### 6 error = -1;
793 - else
794 753 7 error = git_filebuf_commit_at(
795 753 7 &stream->fbuf, final_path.ptr);
796 -
797 753 8 git_buf_dispose(&final_path);
798 -
799 753 9 return error;
800 - }
801 -
802 5748 2 static int loose_backend__writestream_write(git_odb_stream *_stream, const char *data, size_t len)
803 - {
804 5748 2 loose_writestream *stream = (loose_writestream *)_stream;
805 5748 2 return git_filebuf_write(&stream->fbuf, data, len);
806 - }
807 -
808 2889 2 static void loose_backend__writestream_free(git_odb_stream *_stream)
809 - {
810 2889 2 loose_writestream *stream = (loose_writestream *)_stream;
811 -
812 2889 2 git_filebuf_cleanup(&stream->fbuf);
813 2889 3 git__free(stream);
814 2889 4 }
815 -
816 3779 2 static int filebuf_flags(loose_backend *backend)
817 - {
818 3779 2 int flags = GIT_FILEBUF_TEMPORARY |
819 3779 2 (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT);
820 -
821 3779 2,3 if (backend->fsync_object_files || git_repository__fsync_gitdir)
822 3 4 flags |= GIT_FILEBUF_FSYNC;
823 -
824 3779 5 return flags;
825 - }
826 -
827 2889 2 static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backend *_backend, git_object_size_t length, git_object_t type)
828 - {
829 - loose_backend *backend;
830 2889 2 loose_writestream *stream = NULL;
831 - char hdr[MAX_HEADER_LEN];
832 2889 2 git_buf tmp_path = GIT_BUF_INIT;
833 - size_t hdrlen;
834 - int error;
835 -
836 2889 2,3 assert(_backend);
837 -
838 2889 4 backend = (loose_backend *)_backend;
839 2889 4 *stream_out = NULL;
840 -
841 2889 4,5 if ((error = git_odb__format_object_header(&hdrlen,
842 - hdr, sizeof(hdr), length, type)) < 0)
843 ##### 6 return error;
844 -
845 2889 7 stream = git__calloc(1, sizeof(loose_writestream));
846 2889 8,9 GIT_ERROR_CHECK_ALLOC(stream);
847 -
848 2889 10 stream->stream.backend = _backend;
849 2889 10 stream->stream.read = NULL; /* read only */
850 2889 10 stream->stream.write = &loose_backend__writestream_write;
851 2889 10 stream->stream.finalize_write = &loose_backend__writestream_finalize;
852 2889 10 stream->stream.free = &loose_backend__writestream_free;
853 2889 10 stream->stream.mode = GIT_STREAM_WRONLY;
854 -
855 2889 10,11,14 if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
856 2889 12,13 git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend),
857 2889 16 backend->object_file_mode) < 0 ||
858 2889 15 stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)
859 - {
860 ##### 17 git_filebuf_cleanup(&stream->fbuf);
861 ##### 18 git__free(stream);
862 ##### 19 stream = NULL;
863 - }
864 2889 20 git_buf_dispose(&tmp_path);
865 2889 21 *stream_out = (git_odb_stream *)stream;
866 -
867 2889 21 return !stream ? -1 : 0;
868 - }
869 -
870 3352 2 static int loose_backend__readstream_read(
871 - git_odb_stream *_stream,
872 - char *buffer,
873 - size_t buffer_len)
874 - {
875 3352 2 loose_readstream *stream = (loose_readstream *)_stream;
876 3352 2 size_t start_remain = stream->start_len - stream->start_read;
877 3352 2 int total = 0, error;
878 -
879 3352 2 buffer_len = min(buffer_len, INT_MAX);
880 -
881 - /*
882 - * if we read more than just the header in the initial read, play
883 - * that back for the caller.
884 - */
885 3352 2,3 if (start_remain && buffer_len) {
886 420 4 size_t chunk = min(start_remain, buffer_len);
887 420 4 memcpy(buffer, stream->start + stream->start_read, chunk);
888 -
889 420 4 buffer += chunk;
890 420 4 stream->start_read += chunk;
891 -
892 420 4 total += (int)chunk;
893 420 4 buffer_len -= chunk;
894 - }
895 -
896 3352 5 if (buffer_len) {
897 2958 6 size_t chunk = buffer_len;
898 -
899 2958 6,7 if ((error = git_zstream_get_output(buffer, &chunk, &stream->zstream)) < 0)
900 ##### 8 return error;
901 -
902 2958 9 total += (int)chunk;
903 - }
904 -
905 3352 10 return (int)total;
906 - }
907 -
908 49 2 static void loose_backend__readstream_free(git_odb_stream *_stream)
909 - {
910 49 2 loose_readstream *stream = (loose_readstream *)_stream;
911 -
912 49 2 git_futils_mmap_free(&stream->map);
913 49 3 git_zstream_free(&stream->zstream);
914 49 4 git__free(stream);
915 49 5 }
916 -
917 7 2 static int loose_backend__readstream_packlike(
918 - obj_hdr *hdr,
919 - loose_readstream *stream)
920 - {
921 - const unsigned char *data;
922 - size_t data_len, head_len;
923 - int error;
924 -
925 7 2 data = stream->map.data;
926 7 2 data_len = stream->map.len;
927 -
928 - /*
929 - * read the object header, which is an (uncompressed)
930 - * binary encoding of the object type and size.
931 - */
932 7 2,3 if ((error = parse_header_packlike(hdr, &head_len, data, data_len)) < 0)
933 ##### 4 return error;
934 -
935 7 5,6 if (!git_object_typeisloose(hdr->type)) {
936 ##### 7 git_error_set(GIT_ERROR_ODB, "failed to inflate loose object");
937 ##### 8 return -1;
938 - }
939 -
940 7 9 return git_zstream_set_input(&stream->zstream,
941 - data + head_len, data_len - head_len);
942 - }
943 -
944 42 2 static int loose_backend__readstream_standard(
945 - obj_hdr *hdr,
946 - loose_readstream *stream)
947 - {
948 - unsigned char head[MAX_HEADER_LEN];
949 - size_t init, head_len;
950 - int error;
951 -
952 42 2,2,3 if ((error = git_zstream_set_input(&stream->zstream,
953 42 2 stream->map.data, stream->map.len)) < 0)
954 ##### 4 return error;
955 -
956 42 5 init = sizeof(head);
957 -
958 - /*
959 - * inflate the initial part of the compressed buffer in order to
960 - * parse the header; read the largest header possible, then store
961 - * it in the `start` field of the stream object.
962 - */
963 42 5-8 if ((error = git_zstream_get_output(head, &init, &stream->zstream)) < 0 ||
964 42 7 (error = parse_header(hdr, &head_len, head, init)) < 0)
965 ##### 9 return error;
966 -
967 42 10,11 if (!git_object_typeisloose(hdr->type)) {
968 ##### 12 git_error_set(GIT_ERROR_ODB, "failed to inflate disk object");
969 ##### 13 return -1;
970 - }
971 -
972 42 14 if (init > head_len) {
973 35 15 stream->start_len = init - head_len;
974 35 15 memcpy(stream->start, head + head_len, init - head_len);
975 - }
976 -
977 42 16 return 0;
978 - }
979 -
980 49 2 static int loose_backend__readstream(
981 - git_odb_stream **stream_out,
982 - size_t *len_out,
983 - git_object_t *type_out,
984 - git_odb_backend *_backend,
985 - const git_oid *oid)
986 - {
987 - loose_backend *backend;
988 49 2 loose_readstream *stream = NULL;
989 49 2 git_hash_ctx *hash_ctx = NULL;
990 49 2 git_buf object_path = GIT_BUF_INIT;
991 - obj_hdr hdr;
992 49 2 int error = 0;
993 -
994 49 2-7 assert(stream_out && len_out && type_out && _backend && oid);
995 -
996 49 8 backend = (loose_backend *)_backend;
997 49 8 *stream_out = NULL;
998 49 8 *len_out = 0;
999 49 8 *type_out = GIT_OBJECT_INVALID;
1000 -
1001 49 8,9 if (locate_object(&object_path, backend, oid) < 0) {
1002 ##### 10 error = git_odb__error_notfound("no matching loose object",
1003 - oid, GIT_OID_HEXSZ);
1004 ##### 11 goto done;
1005 - }
1006 -
1007 49 12 stream = git__calloc(1, sizeof(loose_readstream));
1008 49 13,14 GIT_ERROR_CHECK_ALLOC(stream);
1009 -
1010 49 15 hash_ctx = git__malloc(sizeof(git_hash_ctx));
1011 49 16,17 GIT_ERROR_CHECK_ALLOC(hash_ctx);
1012 -
1013 49 18-21 if ((error = git_hash_ctx_init(hash_ctx)) < 0 ||
1014 49 20,22,23 (error = git_futils_mmap_ro_file(&stream->map, object_path.ptr)) < 0 ||
1015 49 22 (error = git_zstream_init(&stream->zstream, GIT_ZSTREAM_INFLATE)) < 0)
1016 - goto done;
1017 -
1018 - /* check for a packlike loose object */
1019 49 24,25 if (!is_zlib_compressed_data(stream->map.data, stream->map.len))
1020 7 26 error = loose_backend__readstream_packlike(&hdr, stream);
1021 - else
1022 42 27 error = loose_backend__readstream_standard(&hdr, stream);
1023 -
1024 49 28 if (error < 0)
1025 ##### 29 goto done;
1026 -
1027 49 30 stream->stream.backend = _backend;
1028 49 30 stream->stream.hash_ctx = hash_ctx;
1029 49 30 stream->stream.read = &loose_backend__readstream_read;
1030 49 30 stream->stream.free = &loose_backend__readstream_free;
1031 -
1032 49 30 *stream_out = (git_odb_stream *)stream;
1033 49 30 *len_out = hdr.size;
1034 49 30 *type_out = hdr.type;
1035 -
1036 - done:
1037 49 31 if (error < 0) {
1038 ##### 32 if (stream) {
1039 ##### 33 git_futils_mmap_free(&stream->map);
1040 ##### 34 git_zstream_free(&stream->zstream);
1041 ##### 35 git__free(stream);
1042 - }
1043 ##### 36 if (hash_ctx) {
1044 ##### 37 git_hash_ctx_cleanup(hash_ctx);
1045 ##### 38 git__free(hash_ctx);
1046 - }
1047 - }
1048 -
1049 49 39 git_buf_dispose(&object_path);
1050 49 40 return error;
1051 - }
1052 -
1053 890 2 static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_object_t type)
1054 - {
1055 890 2 int error = 0;
1056 890 2 git_buf final_path = GIT_BUF_INIT;
1057 - char header[MAX_HEADER_LEN];
1058 - size_t header_len;
1059 890 2 git_filebuf fbuf = GIT_FILEBUF_INIT;
1060 - loose_backend *backend;
1061 -
1062 890 2 backend = (loose_backend *)_backend;
1063 -
1064 - /* prepare the header for the file */
1065 890 2,3 if ((error = git_odb__format_object_header(&header_len,
1066 - header, sizeof(header), len, type)) < 0)
1067 ##### 4 goto cleanup;
1068 -
1069 890 5,6,9 if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
1070 890 7,8 git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
1071 - backend->object_file_mode) < 0)
1072 - {
1073 ##### 10 error = -1;
1074 ##### 10 goto cleanup;
1075 - }
1076 -
1077 890 11 git_filebuf_write(&fbuf, header, header_len);
1078 890 12 git_filebuf_write(&fbuf, data, len);
1079 -
1080 890 13,14,16 if (object_file_name(&final_path, backend, oid) < 0 ||
1081 890 15,18 object_mkdir(&final_path, backend) < 0 ||
1082 890 17 git_filebuf_commit_at(&fbuf, final_path.ptr) < 0)
1083 ##### 19 error = -1;
1084 -
1085 - cleanup:
1086 890 20 if (error < 0)
1087 ##### 21 git_filebuf_cleanup(&fbuf);
1088 890 22 git_buf_dispose(&final_path);
1089 890 23 return error;
1090 - }
1091 -
1092 5565 2 static int loose_backend__freshen(
1093 - git_odb_backend *_backend,
1094 - const git_oid *oid)
1095 - {
1096 5565 2 loose_backend *backend = (loose_backend *)_backend;
1097 5565 2 git_buf path = GIT_BUF_INIT;
1098 - int error;
1099 -
1100 5565 2,3 if (object_file_name(&path, backend, oid) < 0)
1101 ##### 4 return -1;
1102 -
1103 5565 5 error = git_futils_touch(path.ptr, NULL);
1104 5565 6 git_buf_dispose(&path);
1105 -
1106 5565 7 return error;
1107 - }
1108 -
1109 3792 2 static void loose_backend__free(git_odb_backend *_backend)
1110 - {
1111 - loose_backend *backend;
1112 3792 2,3 assert(_backend);
1113 3792 4 backend = (loose_backend *)_backend;
1114 -
1115 3792 4 git__free(backend);
1116 3793 5 }
1117 -
1118 - 2 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files)int git_odb_backend_loose(
1119 - git_odb_backend **backend_out,
1120 - const char *objects_dir,
1121 - int compression_level,
1122 - int do_fsync,
1123 - unsigned int dir_mode,
1124 - unsigned int file_mode)
1125 - {
1126 - loose_backend *backend;
1127 - size_t objects_dirlen, alloclen;
1128 -
1129 - 2-4 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) assert(backend_out && objects_dir);
1130 -
1131 - 5 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) objects_dirlen = strlen(objects_dir);
1132 -
1133 - 5-11 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, sizeof(loose_backend), objects_dirlen);
1134 - 12-18 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 2);
1135 - 19 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend = git__calloc(1, alloclen);
1136 - 20,21 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC(backend);
1137 -
1138 - 22 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.version = GIT_ODB_BACKEND_VERSION;
1139 - 22 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->objects_dirlen = objects_dirlen;
1140 - 22 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) memcpy(backend->objects_dir, objects_dir, objects_dirlen);
1141 - 22 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) if (backend->objects_dir[backend->objects_dirlen - 1] != '/')
1142 - 23 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->objects_dir[backend->objects_dirlen++] = '/';
1143 -
1144 - 24 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) if (compression_level < 0)
1145 - 25 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) compression_level = Z_BEST_SPEED;
1146 -
1147 - 26 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) if (dir_mode == 0)
1148 - 27 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) dir_mode = GIT_OBJECT_DIR_MODE;
1149 -
1150 - 28 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) if (file_mode == 0)
1151 - 29 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) file_mode = GIT_OBJECT_FILE_MODE;
1152 -
1153 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->object_zlib_level = compression_level;
1154 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->fsync_object_files = do_fsync;
1155 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->object_dir_mode = dir_mode;
1156 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->object_file_mode = file_mode;
1157 -
1158 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.read = &loose_backend__read;
1159 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.write = &loose_backend__write;
1160 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.read_prefix = &loose_backend__read_prefix;
1161 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.read_header = &loose_backend__read_header;
1162 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.writestream = &loose_backend__writestream;
1163 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.readstream = &loose_backend__readstream;
1164 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.exists = &loose_backend__exists;
1165 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.exists_prefix = &loose_backend__exists_prefix;
1166 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.foreach = &loose_backend__foreach;
1167 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.freshen = &loose_backend__freshen;
1168 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) backend->parent.free = &loose_backend__free;
1169 -
1170 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) *backend_out = (git_odb_backend *)backend;
1171 - 30 suppressed: function cannot be solved git_odb_backend_loose (automatic due to inconsistent arc counts in .gcda files) return 0;
1172 - }