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>
20 #include <sys/socket.h>
35 #include "got_compat.h"
37 #include "got_error.h"
38 #include "got_object.h"
39 #include "got_repository.h"
40 #include "got_opentemp.h"
43 #include "got_lib_sha1.h"
44 #include "got_lib_delta.h"
45 #include "got_lib_inflate.h"
46 #include "got_lib_object.h"
47 #include "got_lib_object_parse.h"
48 #include "got_lib_object_cache.h"
49 #include "got_lib_pack.h"
50 #include "got_lib_privsep.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 const struct got_error
*err
= NULL
;
81 *qid
= malloc(sizeof(**qid
));
83 return got_error_from_errno("malloc");
85 (*qid
)->id
= malloc(sizeof(*((*qid
)->id
)));
86 if ((*qid
)->id
== NULL
) {
87 err
= got_error_from_errno("malloc");
88 got_object_qid_free(*qid
);
97 const struct got_error
*
98 got_object_id_str(char **outbuf
, struct got_object_id
*id
)
100 static const size_t len
= SHA1_DIGEST_STRING_LENGTH
;
102 *outbuf
= malloc(len
);
104 return got_error_from_errno("malloc");
106 if (got_sha1_digest_to_str(id
->sha1
, *outbuf
, len
) == NULL
) {
109 return got_error(GOT_ERR_BAD_OBJ_ID_STR
);
116 got_object_close(struct got_object
*obj
)
118 if (obj
->refcnt
> 0) {
124 if (obj
->flags
& GOT_OBJ_FLAG_DELTIFIED
) {
125 struct got_delta
*delta
;
126 while (!STAILQ_EMPTY(&obj
->deltas
.entries
)) {
127 delta
= STAILQ_FIRST(&obj
->deltas
.entries
);
128 STAILQ_REMOVE_HEAD(&obj
->deltas
.entries
, entry
);
136 got_object_qid_free(struct got_object_qid
*qid
)
143 got_object_id_queue_free(struct got_object_id_queue
*ids
)
145 struct got_object_qid
*qid
;
147 while (!STAILQ_EMPTY(ids
)) {
148 qid
= STAILQ_FIRST(ids
);
149 STAILQ_REMOVE_HEAD(ids
, entry
);
150 got_object_qid_free(qid
);
154 const struct got_error
*
155 got_object_parse_header(struct got_object
**obj
, char *buf
, size_t len
)
157 const char *obj_labels
[] = {
158 GOT_OBJ_LABEL_COMMIT
,
163 const int obj_types
[] = {
170 size_t size
= 0, hdrlen
= 0;
175 hdrlen
= strnlen(buf
, len
) + 1 /* '\0' */;
177 return got_error(GOT_ERR_BAD_OBJ_HDR
);
179 for (i
= 0; i
< nitems(obj_labels
); i
++) {
180 const char *label
= obj_labels
[i
];
181 size_t label_len
= strlen(label
);
184 if (strncmp(buf
, label
, label_len
) != 0)
188 if (len
<= label_len
)
189 return got_error(GOT_ERR_BAD_OBJ_HDR
);
190 size
= strtonum(buf
+ label_len
, 0, LONG_MAX
, &errstr
);
192 return got_error(GOT_ERR_BAD_OBJ_HDR
);
197 return got_error(GOT_ERR_BAD_OBJ_HDR
);
199 *obj
= calloc(1, sizeof(**obj
));
201 return got_error_from_errno("calloc");
203 (*obj
)->hdrlen
= hdrlen
;
208 const struct got_error
*
209 got_object_read_header(struct got_object
**obj
, int fd
)
211 const struct got_error
*err
;
212 struct got_inflate_buf zb
;
214 const size_t zbsize
= 64;
215 size_t outlen
, totlen
;
220 buf
= malloc(zbsize
);
222 return got_error_from_errno("malloc");
224 err
= got_inflate_init(&zb
, buf
, zbsize
, NULL
);
230 err
= got_inflate_read_fd(&zb
, fd
, &outlen
, NULL
);
236 if (memchr(zb
.outbuf
, '\0', outlen
) == NULL
) {
239 newbuf
= recallocarray(buf
, nbuf
- 1, nbuf
, zbsize
);
240 if (newbuf
== NULL
) {
241 err
= got_error_from_errno("recallocarray");
245 zb
.outbuf
= newbuf
+ totlen
;
246 zb
.outlen
= (nbuf
* zbsize
) - totlen
;
248 } while (memchr(zb
.outbuf
, '\0', outlen
) == NULL
);
250 err
= got_object_parse_header(obj
, buf
, totlen
);
253 got_inflate_end(&zb
);
257 struct got_commit_object
*
258 got_object_commit_alloc_partial(void)
260 struct got_commit_object
*commit
;
262 commit
= calloc(1, sizeof(*commit
));
265 commit
->tree_id
= malloc(sizeof(*commit
->tree_id
));
266 if (commit
->tree_id
== NULL
) {
271 STAILQ_INIT(&commit
->parent_ids
);
276 const struct got_error
*
277 got_object_commit_add_parent(struct got_commit_object
*commit
,
280 const struct got_error
*err
= NULL
;
281 struct got_object_qid
*qid
;
283 err
= got_object_qid_alloc_partial(&qid
);
287 if (!got_parse_sha1_digest(qid
->id
->sha1
, id_str
)) {
288 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
289 got_object_qid_free(qid
);
293 STAILQ_INSERT_TAIL(&commit
->parent_ids
, qid
, entry
);
299 static const struct got_error
*
300 parse_gmtoff(time_t *gmtoff
, const char *tzstr
)
303 const char *p
= tzstr
;
311 return got_error(GOT_ERR_BAD_OBJ_DATA
);
313 if (!isdigit(*p
) && !isdigit(*(p
+ 1)))
314 return got_error(GOT_ERR_BAD_OBJ_DATA
);
315 h
= (((*p
- '0') * 10) + (*(p
+ 1) - '0'));
318 if (!isdigit(*p
) && !isdigit(*(p
+ 1)))
319 return got_error(GOT_ERR_BAD_OBJ_DATA
);
320 m
= ((*p
- '0') * 10) + (*(p
+ 1) - '0');
322 *gmtoff
= (h
* 60 * 60 + m
* 60) * sign
;
326 static const struct got_error
*
327 parse_commit_time(time_t *time
, time_t *gmtoff
, char *committer
)
329 const struct got_error
*err
= NULL
;
333 /* Parse and strip off trailing timezone indicator string. */
334 space
= strrchr(committer
, ' ');
336 return got_error(GOT_ERR_BAD_OBJ_DATA
);
337 tzstr
= strdup(space
+ 1);
339 return got_error_from_errno("strdup");
340 err
= parse_gmtoff(gmtoff
, tzstr
);
343 if (err
->code
!= GOT_ERR_BAD_OBJ_DATA
)
345 /* Old versions of Git omitted the timestamp. */
352 /* Timestamp is separated from committer name + email by space. */
353 space
= strrchr(committer
, ' ');
355 return got_error(GOT_ERR_BAD_OBJ_DATA
);
357 /* Timestamp parsed here is expressed as UNIX timestamp (UTC). */
358 *time
= strtonum(space
+ 1, 0, INT64_MAX
, &errstr
);
360 return got_error(GOT_ERR_BAD_OBJ_DATA
);
362 /* Strip off parsed time information, leaving just author and email. */
369 got_object_commit_close(struct got_commit_object
*commit
)
371 if (commit
->refcnt
> 0) {
373 if (commit
->refcnt
> 0)
377 got_object_id_queue_free(&commit
->parent_ids
);
378 free(commit
->tree_id
);
379 free(commit
->author
);
380 free(commit
->committer
);
381 free(commit
->logmsg
);
385 struct got_object_id
*
386 got_object_commit_get_tree_id(struct got_commit_object
*commit
)
388 return commit
->tree_id
;
392 got_object_commit_get_nparents(struct got_commit_object
*commit
)
394 return commit
->nparents
;
397 const struct got_object_id_queue
*
398 got_object_commit_get_parent_ids(struct got_commit_object
*commit
)
400 return &commit
->parent_ids
;
404 got_object_commit_get_author(struct got_commit_object
*commit
)
406 return commit
->author
;
410 got_object_commit_get_author_time(struct got_commit_object
*commit
)
412 return commit
->author_time
;
415 time_t got_object_commit_get_author_gmtoff(struct got_commit_object
*commit
)
417 return commit
->author_gmtoff
;
421 got_object_commit_get_committer(struct got_commit_object
*commit
)
423 return commit
->committer
;
427 got_object_commit_get_committer_time(struct got_commit_object
*commit
)
429 return commit
->committer_time
;
433 got_object_commit_get_committer_gmtoff(struct got_commit_object
*commit
)
435 return commit
->committer_gmtoff
;
438 const struct got_error
*
439 got_object_commit_get_logmsg(char **logmsg
, struct got_commit_object
*commit
)
441 const struct got_error
*err
= NULL
;
446 len
= strlen(commit
->logmsg
);
447 *logmsg
= malloc(len
+ 2); /* leave room for a trailing \n and \0 */
449 return got_error_from_errno("malloc");
452 * Strip out unusual headers. Headers are separated from the commit
453 * message body by a single empty line.
455 src
= commit
->logmsg
;
457 while (*src
!= '\0' && *src
!= '\n') {
458 int copy_header
= 1, eol
= 0;
459 if (strncmp(src
, GOT_COMMIT_LABEL_TREE
,
460 strlen(GOT_COMMIT_LABEL_TREE
)) != 0 &&
461 strncmp(src
, GOT_COMMIT_LABEL_AUTHOR
,
462 strlen(GOT_COMMIT_LABEL_AUTHOR
)) != 0 &&
463 strncmp(src
, GOT_COMMIT_LABEL_PARENT
,
464 strlen(GOT_COMMIT_LABEL_PARENT
)) != 0 &&
465 strncmp(src
, GOT_COMMIT_LABEL_COMMITTER
,
466 strlen(GOT_COMMIT_LABEL_COMMITTER
)) != 0)
469 while (*src
!= '\0' && !eol
) {
481 if (strlcat(*logmsg
, src
, len
+ 1) >= len
+ 1) {
482 err
= got_error(GOT_ERR_NO_SPACE
);
486 /* Trim redundant trailing whitespace. */
487 len
= strlen(*logmsg
);
488 while (len
> 1 && isspace((unsigned char)(*logmsg
)[len
- 2]) &&
489 isspace((unsigned char)(*logmsg
)[len
- 1])) {
490 (*logmsg
)[len
- 1] = '\0';
494 /* Append a trailing newline if missing. */
495 if (len
> 0 && (*logmsg
)[len
- 1] != '\n') {
496 (*logmsg
)[len
] = '\n';
497 (*logmsg
)[len
+ 1] = '\0';
508 got_object_commit_get_logmsg_raw(struct got_commit_object
*commit
)
510 return commit
->logmsg
;
513 const struct got_error
*
514 got_object_parse_commit(struct got_commit_object
**commit
, char *buf
,
517 const struct got_error
*err
= NULL
;
520 ssize_t remain
= (ssize_t
)len
;
523 return got_error(GOT_ERR_BAD_OBJ_DATA
);
525 *commit
= got_object_commit_alloc_partial();
527 return got_error_from_errno("got_object_commit_alloc_partial");
529 label_len
= strlen(GOT_COMMIT_LABEL_TREE
);
530 if (strncmp(s
, GOT_COMMIT_LABEL_TREE
, label_len
) == 0) {
532 if (remain
< SHA1_DIGEST_STRING_LENGTH
) {
533 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
537 if (!got_parse_sha1_digest((*commit
)->tree_id
->sha1
, s
)) {
538 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
541 remain
-= SHA1_DIGEST_STRING_LENGTH
;
542 s
+= SHA1_DIGEST_STRING_LENGTH
;
544 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
548 label_len
= strlen(GOT_COMMIT_LABEL_PARENT
);
549 while (strncmp(s
, GOT_COMMIT_LABEL_PARENT
, label_len
) == 0) {
551 if (remain
< SHA1_DIGEST_STRING_LENGTH
) {
552 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
556 err
= got_object_commit_add_parent(*commit
, s
);
560 remain
-= SHA1_DIGEST_STRING_LENGTH
;
561 s
+= SHA1_DIGEST_STRING_LENGTH
;
564 label_len
= strlen(GOT_COMMIT_LABEL_AUTHOR
);
565 if (strncmp(s
, GOT_COMMIT_LABEL_AUTHOR
, label_len
) == 0) {
571 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
575 p
= memchr(s
, '\n', remain
);
577 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
582 err
= parse_commit_time(&(*commit
)->author_time
,
583 &(*commit
)->author_gmtoff
, s
);
586 (*commit
)->author
= strdup(s
);
587 if ((*commit
)->author
== NULL
) {
588 err
= got_error_from_errno("strdup");
595 label_len
= strlen(GOT_COMMIT_LABEL_COMMITTER
);
596 if (strncmp(s
, GOT_COMMIT_LABEL_COMMITTER
, label_len
) == 0) {
602 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
606 p
= memchr(s
, '\n', remain
);
608 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
613 err
= parse_commit_time(&(*commit
)->committer_time
,
614 &(*commit
)->committer_gmtoff
, s
);
617 (*commit
)->committer
= strdup(s
);
618 if ((*commit
)->committer
== NULL
) {
619 err
= got_error_from_errno("strdup");
626 (*commit
)->logmsg
= strndup(s
, remain
);
627 if ((*commit
)->logmsg
== NULL
) {
628 err
= got_error_from_errno("strndup");
633 got_object_commit_close(*commit
);
640 got_object_tree_close(struct got_tree_object
*tree
)
642 if (tree
->refcnt
> 0) {
644 if (tree
->refcnt
> 0)
652 static const struct got_error
*
653 parse_tree_entry(struct got_parsed_tree_entry
**pte
, const char **name
,
654 size_t *elen
, char *buf
,
658 const struct got_error
*err
= NULL
;
663 *pte
= malloc(sizeof(**pte
));
665 return got_error_from_errno("malloc");
667 *elen
= strnlen(buf
, maxlen
) + 1;
668 if (*elen
> maxlen
) {
671 return got_error(GOT_ERR_BAD_OBJ_DATA
);
674 space
= memchr(buf
, ' ', *elen
);
675 if (space
== NULL
|| space
<= buf
) {
676 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
684 if (*p
< '0' && *p
> '7') {
685 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
689 (*pte
)->mode
|= *p
- '0';
693 if (*elen
> maxlen
|| maxlen
- *elen
< SHA1_DIGEST_LENGTH
) {
694 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
700 *elen
+= SHA1_DIGEST_LENGTH
;
709 const struct got_error
*
710 got_object_parse_tree(struct got_pathlist_head
*entries
, int *nentries
,
711 uint8_t *buf
, size_t len
)
713 const struct got_error
*err
= NULL
;
718 return NULL
; /* tree is empty */
721 struct got_parsed_tree_entry
*pte
;
722 struct got_pathlist_entry
*new = NULL
;
726 err
= parse_tree_entry(&pte
, &name
, &elen
, buf
, remain
);
729 err
= got_pathlist_insert(&new, entries
, name
, pte
);
733 err
= got_error(GOT_ERR_TREE_DUP_ENTRY
);
742 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
747 got_object_parsed_tree_entries_free(entries
);
754 got_object_parsed_tree_entries_free(struct got_pathlist_head
*entries
)
756 struct got_pathlist_entry
*pe
;
758 TAILQ_FOREACH(pe
, entries
, entry
) {
759 struct got_parsed_tree_entry
*pte
= pe
->data
;
762 got_pathlist_free(entries
);
766 got_object_tag_close(struct got_tag_object
*tag
)
768 if (tag
->refcnt
> 0) {
780 const struct got_error
*
781 got_object_parse_tag(struct got_tag_object
**tag
, uint8_t *buf
, size_t len
)
783 const struct got_error
*err
= NULL
;
789 return got_error(GOT_ERR_BAD_OBJ_DATA
);
791 *tag
= calloc(1, sizeof(**tag
));
793 return got_error_from_errno("calloc");
795 label_len
= strlen(GOT_TAG_LABEL_OBJECT
);
796 if (strncmp(s
, GOT_TAG_LABEL_OBJECT
, label_len
) == 0) {
798 if (remain
< SHA1_DIGEST_STRING_LENGTH
) {
799 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
803 if (!got_parse_sha1_digest((*tag
)->id
.sha1
, s
)) {
804 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
807 remain
-= SHA1_DIGEST_STRING_LENGTH
;
808 s
+= SHA1_DIGEST_STRING_LENGTH
;
810 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
815 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
819 label_len
= strlen(GOT_TAG_LABEL_TYPE
);
820 if (strncmp(s
, GOT_TAG_LABEL_TYPE
, label_len
) == 0) {
823 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
827 if (strncmp(s
, GOT_OBJ_LABEL_COMMIT
,
828 strlen(GOT_OBJ_LABEL_COMMIT
)) == 0) {
829 (*tag
)->obj_type
= GOT_OBJ_TYPE_COMMIT
;
830 label_len
= strlen(GOT_OBJ_LABEL_COMMIT
);
833 } else if (strncmp(s
, GOT_OBJ_LABEL_TREE
,
834 strlen(GOT_OBJ_LABEL_TREE
)) == 0) {
835 (*tag
)->obj_type
= GOT_OBJ_TYPE_TREE
;
836 label_len
= strlen(GOT_OBJ_LABEL_TREE
);
839 } else if (strncmp(s
, GOT_OBJ_LABEL_BLOB
,
840 strlen(GOT_OBJ_LABEL_BLOB
)) == 0) {
841 (*tag
)->obj_type
= GOT_OBJ_TYPE_BLOB
;
842 label_len
= strlen(GOT_OBJ_LABEL_BLOB
);
845 } else if (strncmp(s
, GOT_OBJ_LABEL_TAG
,
846 strlen(GOT_OBJ_LABEL_TAG
)) == 0) {
847 (*tag
)->obj_type
= GOT_OBJ_TYPE_TAG
;
848 label_len
= strlen(GOT_OBJ_LABEL_TAG
);
852 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
856 if (remain
<= 0 || *s
!= '\n') {
857 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
863 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
867 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
871 label_len
= strlen(GOT_TAG_LABEL_TAG
);
872 if (strncmp(s
, GOT_TAG_LABEL_TAG
, label_len
) == 0) {
877 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
881 p
= memchr(s
, '\n', remain
);
883 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
888 (*tag
)->tag
= strndup(s
, slen
);
889 if ((*tag
)->tag
== NULL
) {
890 err
= got_error_from_errno("strndup");
896 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
900 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
904 label_len
= strlen(GOT_TAG_LABEL_TAGGER
);
905 if (strncmp(s
, GOT_TAG_LABEL_TAGGER
, label_len
) == 0) {
911 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
915 p
= memchr(s
, '\n', remain
);
917 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
922 err
= parse_commit_time(&(*tag
)->tagger_time
,
923 &(*tag
)->tagger_gmtoff
, s
);
926 (*tag
)->tagger
= strdup(s
);
927 if ((*tag
)->tagger
== NULL
) {
928 err
= got_error_from_errno("strdup");
934 err
= got_error(GOT_ERR_BAD_OBJ_DATA
);
938 /* Some old tags in the Linux git repo have no tagger. */
939 (*tag
)->tagger
= strdup("");
940 if ((*tag
)->tagger
== NULL
) {
941 err
= got_error_from_errno("strdup");
946 (*tag
)->tagmsg
= strndup(s
, remain
);
947 if ((*tag
)->tagmsg
== NULL
) {
948 err
= got_error_from_errno("strndup");
953 got_object_tag_close(*tag
);
959 const struct got_error
*
960 got_read_file_to_mem(uint8_t **outbuf
, size_t *outlen
, FILE *f
)
962 const struct got_error
*err
= NULL
;
963 static const size_t blocksize
= 512;
964 size_t n
, total
, remain
;
970 buf
= malloc(blocksize
);
972 return got_error_from_errno("malloc");
979 newbuf
= reallocarray(buf
, 1, total
+ blocksize
);
980 if (newbuf
== NULL
) {
981 err
= got_error_from_errno("reallocarray");
987 n
= fread(buf
+ total
, 1, remain
, f
);
990 err
= got_ferror(f
, GOT_ERR_IO
);