2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <sys/types.h>
19 #include <sys/queue.h>
21 #include <sys/socket.h>
36 #include "got_compat.h"
38 #include "got_error.h"
39 #include "got_object.h"
40 #include "got_repository.h"
41 #include "got_opentemp.h"
44 #include "got_lib_hash.h"
45 #include "got_lib_delta.h"
46 #include "got_lib_inflate.h"
47 #include "got_lib_object.h"
48 #include "got_lib_object_parse.h"
49 #include "got_lib_object_cache.h"
50 #include "got_lib_pack.h"
51 #include "got_lib_repository.h"
54 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
57 struct got_object_id
*
58 got_object_id_dup(struct got_object_id
*id1
)
60 struct got_object_id
*id2
;
62 id2
= malloc(sizeof(*id2
));
65 memcpy(id2
, id1
, sizeof(*id2
));
70 got_object_id_cmp(const struct got_object_id
*id1
,
71 const struct got_object_id
*id2
)
73 return memcmp(id1
->sha1
, id2
->sha1
, SHA1_DIGEST_LENGTH
);
76 const struct got_error
*
77 got_object_qid_alloc_partial(struct got_object_qid
**qid
)
79 *qid
= malloc(sizeof(**qid
));
81 return got_error_from_errno("malloc");
87 const struct got_error
*
88 got_object_id_str(char **outbuf
, struct got_object_id
*id
)
90 static const size_t len
= GOT_OBJECT_ID_HEX_MAXLEN
;
92 *outbuf
= malloc(len
);
94 return got_error_from_errno("malloc");
96 if (got_object_id_hex(id
, *outbuf
, len
) == NULL
) {
99 return got_error(GOT_ERR_BAD_OBJ_ID_STR
);
106 got_object_id_hex(struct got_object_id
*id
, char *buf
, size_t len
)
108 return got_sha1_digest_to_str(id
->sha1
, buf
, len
);
112 got_object_close(struct got_object
*obj
)
114 if (obj
->refcnt
> 0) {
120 if (obj
->flags
& GOT_OBJ_FLAG_DELTIFIED
) {
121 struct got_delta
*delta
;
122 while (!STAILQ_EMPTY(&obj
->deltas
.entries
)) {
123 delta
= STAILQ_FIRST(&obj
->deltas
.entries
);
124 STAILQ_REMOVE_HEAD(&obj
->deltas
.entries
, entry
);
131 const struct got_error
*
132 got_object_raw_close(struct got_raw_object
*obj
)
134 const struct got_error
*err
= NULL
;
136 if (obj
->refcnt
> 0) {
145 if (obj
->f
== NULL
) {
147 if (munmap(obj
->data
, obj
->hdrlen
+ obj
->size
) == -1)
148 err
= got_error_from_errno("munmap");
149 if (close(obj
->fd
) == -1 && err
== NULL
)
150 err
= got_error_from_errno("close");
154 if (fclose(obj
->f
) == EOF
&& err
== NULL
)
155 err
= got_error_from_errno("fclose");
162 got_object_qid_free(struct got_object_qid
*qid
)
168 got_object_id_queue_free(struct got_object_id_queue
*ids
)
170 struct got_object_qid
*qid
;
172 while (!STAILQ_EMPTY(ids
)) {
173 qid
= STAILQ_FIRST(ids
);
174 STAILQ_REMOVE_HEAD(ids
, entry
);
175 got_object_qid_free(qid
);
179 const struct got_error
*
180 got_object_parse_header(struct got_object
**obj
, char *buf
, size_t len
)
182 const char *obj_labels
[] = {
183 GOT_OBJ_LABEL_COMMIT
,
188 const int obj_types
[] = {
201 end
= memchr(buf
, '\0', len
);
203 return got_error(GOT_ERR_BAD_OBJ_HDR
);
205 for (i
= 0; i
< nitems(obj_labels
); i
++) {
206 const char *label
= obj_labels
[i
];
207 size_t label_len
= strlen(label
);
210 if (len
<= label_len
|| buf
+ label_len
>= end
||
211 strncmp(buf
, label
, label_len
) != 0)
215 size
= strtonum(buf
+ label_len
, 0, LONG_MAX
, &errstr
);
217 return got_error(GOT_ERR_BAD_OBJ_HDR
);
222 return got_error(GOT_ERR_BAD_OBJ_HDR
);
224 *obj
= calloc(1, sizeof(**obj
));
226 return got_error_from_errno("calloc");
228 (*obj
)->hdrlen
= end
- buf
+ 1;
233 const struct got_error
*
234 got_object_read_header(struct got_object
**obj
, int fd
)
236 const struct got_error
*err
;
237 struct got_inflate_buf zb
;
239 const size_t zbsize
= 64;
240 size_t outlen
, totlen
;
245 buf
= malloc(zbsize
);
247 return got_error_from_errno("malloc");
250 err
= got_inflate_init(&zb
, buf
, zbsize
, NULL
);
256 err
= got_inflate_read_fd(&zb
, fd
, &outlen
, NULL
);
262 if (memchr(zb
.outbuf
, '\0', outlen
) == NULL
) {
265 newbuf
= recallocarray(buf
, nbuf
- 1, nbuf
, zbsize
);
266 if (newbuf
== NULL
) {
267 err
= got_error_from_errno("recallocarray");
271 zb
.outbuf
= newbuf
+ totlen
;
272 zb
.outlen
= (nbuf
* zbsize
) - totlen
;
274 } while (memchr(zb
.outbuf
, '\0', outlen
) == NULL
);
276 err
= got_object_parse_header(obj
, buf
, totlen
);
279 got_inflate_end(&zb
);
283 const struct got_error
*
284 got_object_read_raw(uint8_t **outbuf
, off_t
*size
, size_t *hdrlen
,
285 size_t max_in_mem_size
, int outfd
, struct got_object_id
*expected_id
,
288 const struct got_error
*err
= NULL
;
289 struct got_object
*obj
;
290 struct got_inflate_checksum csum
;
291 struct got_object_id id
;
293 size_t len
, consumed
;
300 got_hash_init(&ctx
, GOT_HASH_SHA1
);
301 memset(&csum
, 0, sizeof(csum
));
302 csum
.output_ctx
= &ctx
;
304 if (lseek(infd
, SEEK_SET
, 0) == -1)
305 return got_error_from_errno("lseek");
307 err
= got_object_read_header(&obj
, infd
);
311 if (lseek(infd
, SEEK_SET
, 0) == -1)
312 return got_error_from_errno("lseek");
314 if (obj
->size
+ obj
->hdrlen
<= max_in_mem_size
) {
315 err
= got_inflate_to_mem_fd(outbuf
, &len
, &consumed
, &csum
,
316 obj
->size
+ obj
->hdrlen
, infd
);
320 * XXX This uses an extra file descriptor for no good reason.
321 * We should have got_inflate_fd_to_fd().
325 return got_error_from_errno("dup");
328 err
= got_error_from_errno("fdopen");
333 err
= got_inflate_to_fd(&len
, f
, &csum
, outfd
);
338 if (len
< obj
->hdrlen
|| len
!= obj
->hdrlen
+ obj
->size
) {
339 err
= got_error(GOT_ERR_BAD_OBJ_HDR
);
343 got_hash_final_object_id(&ctx
, &id
);
344 if (got_object_id_cmp(expected_id
, &id
) != 0) {
345 err
= got_error_checksum(expected_id
);
350 *hdrlen
= obj
->hdrlen
;
352 got_object_close(obj
);
353 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
354 err
= got_error_from_errno("fclose");
358 struct got_commit_object
*
359 got_object_commit_alloc_partial(void)
361 struct got_commit_object
*commit
;
363 commit
= calloc(1, sizeof(*commit
));
366 commit
->tree_id
= malloc(sizeof(*commit
->tree_id
));
367 if (commit
->tree_id
== NULL
) {
372 STAILQ_INIT(&commit
->parent_ids
);
377 const struct got_error
*
378 got_object_commit_add_parent(struct got_commit_object
*commit
,
381 const struct got_error
*err
= NULL
;
382 struct got_object_qid
*qid
;
384 err
= got_object_qid_alloc_partial(&qid
);
388 if (!got_parse_object_id(&qid
->id
, id_str
, GOT_HASH_SHA1
)) {
389 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
390 got_object_qid_free(qid
);
394 STAILQ_INSERT_TAIL(&commit
->parent_ids
, qid
, entry
);
400 static const struct got_error
*
401 parse_gmtoff(time_t *gmtoff
, const char *tzstr
)
404 const char *p
= tzstr
;
412 return got_error(GOT_ERR_BAD_OBJ_DATA
);
414 if (!isdigit((unsigned char)*p
) &&
415 !isdigit((unsigned char)*(p
+ 1)))
416 return got_error(GOT_ERR_BAD_OBJ_DATA
);
417 h
= (((*p
- '0') * 10) + (*(p
+ 1) - '0'));
420 if (!isdigit((unsigned char)*p
) &&
421 !isdigit((unsigned char)*(p
+ 1)))
422 return got_error(GOT_ERR_BAD_OBJ_DATA
);
423 m
= ((*p
- '0') * 10) + (*(p
+ 1) - '0');
425 *gmtoff
= (h
* 60 * 60 + m
* 60) * sign
;
429 static const struct got_error
*
430 parse_commit_time(time_t *time
, time_t *gmtoff
, char *committer
)
432 const struct got_error
*err
= NULL
;
436 /* Parse and strip off trailing timezone indicator string. */
437 space
= strrchr(committer
, ' ');
439 return got_error(GOT_ERR_BAD_OBJ_DATA
);
440 tzstr
= strdup(space
+ 1);
442 return got_error_from_errno("strdup");
443 err
= parse_gmtoff(gmtoff
, tzstr
);
446 if (err
->code
!= GOT_ERR_BAD_OBJ_DATA
)
448 /* Old versions of Git omitted the timestamp. */
455 /* Timestamp is separated from committer name + email by space. */
456 space
= strrchr(committer
, ' ');
458 return got_error(GOT_ERR_BAD_OBJ_DATA
);
460 /* Timestamp parsed here is expressed as UNIX timestamp (UTC). */
461 *time
= strtonum(space
+ 1, 0, INT64_MAX
, &errstr
);
463 return got_error(GOT_ERR_BAD_OBJ_DATA
);
465 /* Strip off parsed time information, leaving just author and email. */
472 got_object_commit_close(struct got_commit_object
*commit
)
474 if (commit
->refcnt
> 0) {
476 if (commit
->refcnt
> 0)
480 got_object_id_queue_free(&commit
->parent_ids
);
481 free(commit
->tree_id
);
482 free(commit
->author
);
483 free(commit
->committer
);
484 free(commit
->logmsg
);
488 struct got_object_id
*
489 got_object_commit_get_tree_id(struct got_commit_object
*commit
)
491 return commit
->tree_id
;
495 got_object_commit_get_nparents(struct got_commit_object
*commit
)
497 return commit
->nparents
;
500 const struct got_object_id_queue
*
501 got_object_commit_get_parent_ids(struct got_commit_object
*commit
)
503 return &commit
->parent_ids
;
507 got_object_commit_get_author(struct got_commit_object
*commit
)
509 return commit
->author
;
513 got_object_commit_get_author_time(struct got_commit_object
*commit
)
515 return commit
->author_time
;
518 time_t got_object_commit_get_author_gmtoff(struct got_commit_object
*commit
)
520 return commit
->author_gmtoff
;
524 got_object_commit_get_committer(struct got_commit_object
*commit
)
526 return commit
->committer
;
530 got_object_commit_get_committer_time(struct got_commit_object
*commit
)
532 return commit
->committer_time
;
536 got_object_commit_get_committer_gmtoff(struct got_commit_object
*commit
)
538 return commit
->committer_gmtoff
;
541 const struct got_error
*
542 got_object_commit_get_logmsg(char **logmsg
, struct got_commit_object
*commit
)
544 const struct got_error
*err
= NULL
;
549 len
= strlen(commit
->logmsg
);
550 *logmsg
= malloc(len
+ 2); /* leave room for a trailing \n and \0 */
552 return got_error_from_errno("malloc");
555 * Strip out unusual headers. Headers are separated from the commit
556 * message body by a single empty line.
558 src
= commit
->logmsg
;
560 while (*src
!= '\0' && *src
!= '\n') {
561 int copy_header
= 1, eol
= 0;
562 if (strncmp(src
, GOT_COMMIT_LABEL_TREE
,
563 strlen(GOT_COMMIT_LABEL_TREE
)) != 0 &&
564 strncmp(src
, GOT_COMMIT_LABEL_AUTHOR
,
565 strlen(GOT_COMMIT_LABEL_AUTHOR
)) != 0 &&
566 strncmp(src
, GOT_COMMIT_LABEL_PARENT
,
567 strlen(GOT_COMMIT_LABEL_PARENT
)) != 0 &&
568 strncmp(src
, GOT_COMMIT_LABEL_COMMITTER
,
569 strlen(GOT_COMMIT_LABEL_COMMITTER
)) != 0)
572 while (*src
!= '\0' && !eol
) {
584 if (strlcat(*logmsg
, src
, len
+ 1) >= len
+ 1) {
585 err
= got_error(GOT_ERR_NO_SPACE
);
589 /* Trim redundant trailing whitespace. */
590 len
= strlen(*logmsg
);
591 while (len
> 1 && isspace((unsigned char)(*logmsg
)[len
- 2]) &&
592 isspace((unsigned char)(*logmsg
)[len
- 1])) {
593 (*logmsg
)[len
- 1] = '\0';
597 /* Append a trailing newline if missing. */
598 if (len
> 0 && (*logmsg
)[len
- 1] != '\n') {
599 (*logmsg
)[len
] = '\n';
600 (*logmsg
)[len
+ 1] = '\0';
611 got_object_commit_get_logmsg_raw(struct got_commit_object
*commit
)
613 return commit
->logmsg
;
616 const struct got_error
*
617 got_object_parse_commit(struct got_commit_object
**commit
, char *buf
,
620 const struct got_error
*err
= NULL
;
621 enum got_hash_algorithm algo
= GOT_HASH_SHA1
;
624 ssize_t remain
= (ssize_t
)len
;
627 return got_error(GOT_ERR_BAD_OBJ_DATA
);
629 *commit
= got_object_commit_alloc_partial();
631 return got_error_from_errno("got_object_commit_alloc_partial");
633 label_len
= strlen(GOT_COMMIT_LABEL_TREE
);
634 if (strncmp(s
, GOT_COMMIT_LABEL_TREE
, label_len
) == 0) {
636 if (remain
< SHA1_DIGEST_STRING_LENGTH
) {
637 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
641 if (!got_parse_object_id((*commit
)->tree_id
, s
, algo
)) {
642 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
645 remain
-= SHA1_DIGEST_STRING_LENGTH
;
646 s
+= SHA1_DIGEST_STRING_LENGTH
;
648 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
652 label_len
= strlen(GOT_COMMIT_LABEL_PARENT
);
653 while (strncmp(s
, GOT_COMMIT_LABEL_PARENT
, label_len
) == 0) {
655 if (remain
< SHA1_DIGEST_STRING_LENGTH
) {
656 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
660 err
= got_object_commit_add_parent(*commit
, s
);
664 remain
-= SHA1_DIGEST_STRING_LENGTH
;
665 s
+= SHA1_DIGEST_STRING_LENGTH
;
668 label_len
= strlen(GOT_COMMIT_LABEL_AUTHOR
);
669 if (strncmp(s
, GOT_COMMIT_LABEL_AUTHOR
, label_len
) == 0) {
675 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
679 p
= memchr(s
, '\n', remain
);
681 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
686 err
= parse_commit_time(&(*commit
)->author_time
,
687 &(*commit
)->author_gmtoff
, s
);
690 (*commit
)->author
= strdup(s
);
691 if ((*commit
)->author
== NULL
) {
692 err
= got_error_from_errno("strdup");
699 label_len
= strlen(GOT_COMMIT_LABEL_COMMITTER
);
700 if (strncmp(s
, GOT_COMMIT_LABEL_COMMITTER
, label_len
) == 0) {
706 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
710 p
= memchr(s
, '\n', remain
);
712 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
717 err
= parse_commit_time(&(*commit
)->committer_time
,
718 &(*commit
)->committer_gmtoff
, s
);
721 (*commit
)->committer
= strdup(s
);
722 if ((*commit
)->committer
== NULL
) {
723 err
= got_error_from_errno("strdup");
730 (*commit
)->logmsg
= strndup(s
, remain
);
731 if ((*commit
)->logmsg
== NULL
) {
732 err
= got_error_from_errno("strndup");
737 got_object_commit_close(*commit
);
743 const struct got_error
*
744 got_object_read_commit(struct got_commit_object
**commit
, int fd
,
745 struct got_object_id
*expected_id
, size_t expected_size
)
747 struct got_object
*obj
= NULL
;
748 const struct got_error
*err
= NULL
;
751 struct got_inflate_checksum csum
;
753 struct got_object_id id
;
755 got_hash_init(&ctx
, GOT_HASH_SHA1
);
756 memset(&csum
, 0, sizeof(csum
));
757 csum
.output_ctx
= &ctx
;
759 err
= got_inflate_to_mem_fd(&p
, &len
, NULL
, &csum
, expected_size
, fd
);
763 got_hash_final_object_id(&ctx
, &id
);
764 if (got_object_id_cmp(expected_id
, &id
) != 0) {
765 err
= got_error_checksum(expected_id
);
769 err
= got_object_parse_header(&obj
, p
, len
);
773 if (len
< obj
->hdrlen
+ obj
->size
) {
774 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
778 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
779 err
= got_error(GOT_ERR_OBJ_TYPE
);
783 /* Skip object header. */
785 err
= got_object_parse_commit(commit
, p
+ obj
->hdrlen
, len
);
789 got_object_close(obj
);
794 got_object_tree_close(struct got_tree_object
*tree
)
796 if (tree
->refcnt
> 0) {
798 if (tree
->refcnt
> 0)
806 static const struct got_error
*
807 parse_tree_entry(struct got_parsed_tree_entry
*pte
, size_t *elen
, char *buf
,
814 *elen
= strnlen(buf
, maxlen
) + 1;
816 return got_error(GOT_ERR_BAD_OBJ_DATA
);
818 space
= memchr(buf
, ' ', *elen
);
819 if (space
== NULL
|| space
<= buf
)
820 return got_error(GOT_ERR_BAD_OBJ_DATA
);
825 if (*p
< '0' || *p
> '7')
826 return got_error(GOT_ERR_BAD_OBJ_DATA
);
828 pte
->mode
|= *p
- '0';
832 if (*elen
> maxlen
|| maxlen
- *elen
< SHA1_DIGEST_LENGTH
)
833 return got_error(GOT_ERR_BAD_OBJ_DATA
);
835 pte
->name
= space
+ 1;
836 pte
->namelen
= strlen(pte
->name
);
839 *elen
+= SHA1_DIGEST_LENGTH
;
844 pte_cmp(const void *pa
, const void *pb
)
846 const struct got_parsed_tree_entry
*a
= pa
, *b
= pb
;
848 return got_path_cmp(a
->name
, b
->name
, a
->namelen
, b
->namelen
);
851 const struct got_error
*
852 got_object_parse_tree(struct got_parsed_tree_entry
**entries
, size_t *nentries
,
853 size_t *nentries_alloc
, uint8_t *buf
, size_t len
)
855 const struct got_error
*err
= NULL
;
857 const size_t nalloc
= 16;
858 struct got_parsed_tree_entry
*pte
;
863 return NULL
; /* tree is empty */
868 if (*nentries
>= *nentries_alloc
) {
869 pte
= recallocarray(*entries
, *nentries_alloc
,
870 *nentries_alloc
+ nalloc
, sizeof(**entries
));
872 err
= got_error_from_errno("recallocarray");
876 *nentries_alloc
+= nalloc
;
879 pte
= &(*entries
)[*nentries
];
880 err
= parse_tree_entry(pte
, &elen
, buf
, remain
);
889 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
894 mergesort(*entries
, *nentries
, sizeof(**entries
), pte_cmp
);
896 for (i
= 0; i
< *nentries
- 1; i
++) {
897 struct got_parsed_tree_entry
*prev
= &(*entries
)[i
];
898 pte
= &(*entries
)[i
+ 1];
899 if (got_path_cmp(prev
->name
, pte
->name
,
900 prev
->namelen
, pte
->namelen
) == 0) {
901 err
= got_error(GOT_ERR_TREE_DUP_ENTRY
);
912 const struct got_error
*
913 got_object_read_tree(struct got_parsed_tree_entry
**entries
, size_t *nentries
,
914 size_t *nentries_alloc
, uint8_t **p
, int fd
,
915 struct got_object_id
*expected_id
)
917 const struct got_error
*err
= NULL
;
918 struct got_object
*obj
= NULL
;
920 struct got_inflate_checksum csum
;
922 struct got_object_id id
;
924 got_hash_init(&ctx
, GOT_HASH_SHA1
);
925 memset(&csum
, 0, sizeof(csum
));
926 csum
.output_ctx
= &ctx
;
928 err
= got_inflate_to_mem_fd(p
, &len
, NULL
, &csum
, 0, fd
);
932 got_hash_final_object_id(&ctx
, &id
);
933 if (got_object_id_cmp(expected_id
, &id
) != 0) {
934 err
= got_error_checksum(expected_id
);
938 err
= got_object_parse_header(&obj
, *p
, len
);
942 if (len
< obj
->hdrlen
+ obj
->size
) {
943 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
947 /* Skip object header. */
949 err
= got_object_parse_tree(entries
, nentries
, nentries_alloc
,
950 *p
+ obj
->hdrlen
, len
);
953 got_object_close(obj
);
958 got_object_tag_close(struct got_tag_object
*tag
)
960 if (tag
->refcnt
> 0) {
972 const struct got_error
*
973 got_object_parse_tag(struct got_tag_object
**tag
, uint8_t *buf
, size_t len
)
975 const struct got_error
*err
= NULL
;
976 enum got_hash_algorithm algo
= GOT_HASH_SHA1
;
982 return got_error(GOT_ERR_BAD_OBJ_DATA
);
984 *tag
= calloc(1, sizeof(**tag
));
986 return got_error_from_errno("calloc");
988 label_len
= strlen(GOT_TAG_LABEL_OBJECT
);
989 if (strncmp(s
, GOT_TAG_LABEL_OBJECT
, label_len
) == 0) {
991 if (remain
< SHA1_DIGEST_STRING_LENGTH
) {
992 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
996 if (!got_parse_object_id(&(*tag
)->id
, s
, algo
)) {
997 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1000 remain
-= SHA1_DIGEST_STRING_LENGTH
;
1001 s
+= SHA1_DIGEST_STRING_LENGTH
;
1003 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1008 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1012 label_len
= strlen(GOT_TAG_LABEL_TYPE
);
1013 if (strncmp(s
, GOT_TAG_LABEL_TYPE
, label_len
) == 0) {
1014 remain
-= label_len
;
1016 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1020 if (strncmp(s
, GOT_OBJ_LABEL_COMMIT
,
1021 strlen(GOT_OBJ_LABEL_COMMIT
)) == 0) {
1022 (*tag
)->obj_type
= GOT_OBJ_TYPE_COMMIT
;
1023 label_len
= strlen(GOT_OBJ_LABEL_COMMIT
);
1025 remain
-= label_len
;
1026 } else if (strncmp(s
, GOT_OBJ_LABEL_TREE
,
1027 strlen(GOT_OBJ_LABEL_TREE
)) == 0) {
1028 (*tag
)->obj_type
= GOT_OBJ_TYPE_TREE
;
1029 label_len
= strlen(GOT_OBJ_LABEL_TREE
);
1031 remain
-= label_len
;
1032 } else if (strncmp(s
, GOT_OBJ_LABEL_BLOB
,
1033 strlen(GOT_OBJ_LABEL_BLOB
)) == 0) {
1034 (*tag
)->obj_type
= GOT_OBJ_TYPE_BLOB
;
1035 label_len
= strlen(GOT_OBJ_LABEL_BLOB
);
1037 remain
-= label_len
;
1038 } else if (strncmp(s
, GOT_OBJ_LABEL_TAG
,
1039 strlen(GOT_OBJ_LABEL_TAG
)) == 0) {
1040 (*tag
)->obj_type
= GOT_OBJ_TYPE_TAG
;
1041 label_len
= strlen(GOT_OBJ_LABEL_TAG
);
1043 remain
-= label_len
;
1045 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1049 if (remain
<= 0 || *s
!= '\n') {
1050 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1056 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1060 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1064 label_len
= strlen(GOT_TAG_LABEL_TAG
);
1065 if (strncmp(s
, GOT_TAG_LABEL_TAG
, label_len
) == 0) {
1068 remain
-= label_len
;
1070 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1074 p
= memchr(s
, '\n', remain
);
1076 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1081 (*tag
)->tag
= strndup(s
, slen
);
1082 if ((*tag
)->tag
== NULL
) {
1083 err
= got_error_from_errno("strndup");
1089 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1093 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1097 label_len
= strlen(GOT_TAG_LABEL_TAGGER
);
1098 if (strncmp(s
, GOT_TAG_LABEL_TAGGER
, label_len
) == 0) {
1102 remain
-= label_len
;
1104 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1108 p
= memchr(s
, '\n', remain
);
1110 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1115 err
= parse_commit_time(&(*tag
)->tagger_time
,
1116 &(*tag
)->tagger_gmtoff
, s
);
1119 (*tag
)->tagger
= strdup(s
);
1120 if ((*tag
)->tagger
== NULL
) {
1121 err
= got_error_from_errno("strdup");
1127 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1131 /* Some old tags in the Linux git repo have no tagger. */
1132 (*tag
)->tagger
= strdup("");
1133 if ((*tag
)->tagger
== NULL
) {
1134 err
= got_error_from_errno("strdup");
1139 (*tag
)->tagmsg
= strndup(s
, remain
);
1140 if ((*tag
)->tagmsg
== NULL
) {
1141 err
= got_error_from_errno("strndup");
1146 got_object_tag_close(*tag
);
1152 const struct got_error
*
1153 got_object_read_tag(struct got_tag_object
**tag
, int fd
,
1154 struct got_object_id
*expected_id
, size_t expected_size
)
1156 const struct got_error
*err
= NULL
;
1157 struct got_object
*obj
= NULL
;
1160 struct got_inflate_checksum csum
;
1161 struct got_hash ctx
;
1162 struct got_object_id id
;
1164 got_hash_init(&ctx
, GOT_HASH_SHA1
);
1165 memset(&csum
, 0, sizeof(csum
));
1166 csum
.output_ctx
= &ctx
;
1168 err
= got_inflate_to_mem_fd(&p
, &len
, NULL
, &csum
,
1173 got_hash_final_object_id(&ctx
, &id
);
1174 if (got_object_id_cmp(expected_id
, &id
) != 0) {
1175 err
= got_error_checksum(expected_id
);
1179 err
= got_object_parse_header(&obj
, p
, len
);
1183 if (len
< obj
->hdrlen
+ obj
->size
) {
1184 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
1188 /* Skip object header. */
1190 err
= got_object_parse_tag(tag
, p
+ obj
->hdrlen
, len
);
1194 got_object_close(obj
);
1198 const struct got_error
*
1199 got_read_file_to_mem(uint8_t **outbuf
, size_t *outlen
, FILE *f
)
1201 const struct got_error
*err
= NULL
;
1202 static const size_t blocksize
= 512;
1203 size_t n
, total
, remain
;
1209 buf
= malloc(blocksize
);
1211 return got_error_from_errno("malloc");
1218 newbuf
= reallocarray(buf
, 1, total
+ blocksize
);
1219 if (newbuf
== NULL
) {
1220 err
= got_error_from_errno("reallocarray");
1224 remain
+= blocksize
;
1226 n
= fread(buf
+ total
, 1, remain
, f
);
1229 err
= got_ferror(f
, GOT_ERR_IO
);