2 * Copyright (c) 2019 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 "got_compat.h"
19 #include <sys/types.h>
21 #include <sys/queue.h>
35 #include "got_error.h"
36 #include "got_object.h"
37 #include "got_repository.h"
38 #include "got_opentemp.h"
42 #include "got_lib_hash.h"
43 #include "got_lib_deflate.h"
44 #include "got_lib_delta.h"
45 #include "got_lib_object.h"
46 #include "got_lib_object_parse.h"
47 #include "got_lib_lockfile.h"
49 #include "got_lib_object_create.h"
54 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
57 static const struct got_error
*
58 create_object_file(struct got_object_id
*id
, FILE *content
,
59 off_t content_len
, struct got_repository
*repo
)
61 const struct got_error
*err
= NULL
, *unlock_err
= NULL
;
62 char *objpath
= NULL
, *tmppath
= NULL
;
64 struct got_lockfile
*lf
= NULL
;
67 err
= got_object_get_path(&objpath
, id
, repo
);
71 err
= got_opentemp_named(&tmppath
, &tmpfile
, objpath
, "");
74 if (!(err
->code
== GOT_ERR_ERRNO
&& errno
== ENOENT
))
76 err
= got_path_dirname(&parent_path
, objpath
);
79 err
= got_path_mkdir(parent_path
);
83 err
= got_opentemp_named(&tmppath
, &tmpfile
, objpath
, "");
88 if (fchmod(fileno(tmpfile
), GOT_DEFAULT_FILE_MODE
) != 0) {
89 err
= got_error_from_errno2("fchmod", tmppath
);
93 err
= got_deflate_to_file(&tmplen
, content
, content_len
, tmpfile
, NULL
);
97 err
= got_lockfile_lock(&lf
, objpath
, -1);
101 if (rename(tmppath
, objpath
) != 0) {
102 err
= got_error_from_errno3("rename", tmppath
, objpath
);
110 if (unlink(tmppath
) != 0 && err
== NULL
)
111 err
= got_error_from_errno2("unlink", tmppath
);
114 if (tmpfile
&& fclose(tmpfile
) == EOF
&& err
== NULL
)
115 err
= got_error_from_errno("fclose");
117 unlock_err
= got_lockfile_unlock(lf
, -1);
118 return err
? err
: unlock_err
;
121 const struct got_error
*
122 got_object_blob_file_create(struct got_object_id
**id
, FILE **blobfile
,
123 off_t
*blobsize
, const char *ondisk_path
)
125 const struct got_error
*err
= NULL
;
130 size_t headerlen
= 0, n
;
136 got_hash_init(&ctx
, GOT_HASH_SHA1
);
138 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
140 if (!got_err_open_nofollow_on_symlink())
141 return got_error_from_errno2("open", ondisk_path
);
143 if (lstat(ondisk_path
, &sb
) == -1) {
144 err
= got_error_from_errno2("lstat", ondisk_path
);
147 } else if (fstat(fd
, &sb
) == -1) {
148 err
= got_error_from_errno2("fstat", ondisk_path
);
152 if (asprintf(&header
, "%s %lld", GOT_OBJ_LABEL_BLOB
,
153 (long long)sb
.st_size
) == -1) {
154 err
= got_error_from_errno("asprintf");
157 headerlen
= strlen(header
) + 1;
158 got_hash_update(&ctx
, header
, headerlen
);
160 *blobfile
= got_opentemp();
161 if (*blobfile
== NULL
) {
162 err
= got_error_from_errno("got_opentemp");
166 n
= fwrite(header
, 1, headerlen
, *blobfile
);
167 if (n
!= headerlen
) {
168 err
= got_ferror(*blobfile
, GOT_ERR_IO
);
171 *blobsize
+= headerlen
;
173 char buf
[PATH_MAX
* 8];
176 if (S_ISLNK(sb
.st_mode
)) {
177 inlen
= readlink(ondisk_path
, buf
, sizeof(buf
));
179 err
= got_error_from_errno("readlink");
183 inlen
= read(fd
, buf
, sizeof(buf
));
185 err
= got_error_from_errno("read");
191 got_hash_update(&ctx
, buf
, inlen
);
192 n
= fwrite(buf
, 1, inlen
, *blobfile
);
194 err
= got_ferror(*blobfile
, GOT_ERR_IO
);
198 if (S_ISLNK(sb
.st_mode
))
202 *id
= calloc(1, sizeof(**id
));
204 err
= got_error_from_errno("calloc");
207 got_hash_final_object_id(&ctx
, *id
);
209 if (fflush(*blobfile
) != 0) {
210 err
= got_error_from_errno("fflush");
216 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
217 err
= got_error_from_errno("close");
229 const struct got_error
*
230 got_object_blob_create(struct got_object_id
**id
, const char *ondisk_path
,
231 struct got_repository
*repo
)
233 const struct got_error
*err
= NULL
;
234 FILE *blobfile
= NULL
;
237 err
= got_object_blob_file_create(id
, &blobfile
, &blobsize
,
242 err
= create_object_file(*id
, blobfile
, blobsize
, repo
);
243 if (fclose(blobfile
) == EOF
&& err
== NULL
)
244 err
= got_error_from_errno("fclose");
252 static const struct got_error
*
253 te_mode2str(char *buf
, size_t len
, struct got_tree_entry
*te
)
259 * Some Git implementations are picky about modes seen in tree entries.
260 * For best compatibility we normalize the file/directory mode here.
262 if (S_ISREG(te
->mode
)) {
263 mode
= GOT_DEFAULT_FILE_MODE
;
264 if (te
->mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
))
265 mode
|= S_IXUSR
| S_IXGRP
| S_IXOTH
;
266 } else if (got_object_tree_entry_is_submodule(te
))
267 mode
= S_IFDIR
| S_IFLNK
;
268 else if (S_ISLNK(te
->mode
))
269 mode
= S_IFLNK
; /* Git leaves all the other bits unset. */
270 else if (S_ISDIR(te
->mode
))
271 mode
= S_IFDIR
; /* Git leaves all the other bits unset. */
273 return got_error(GOT_ERR_BAD_FILETYPE
);
275 ret
= snprintf(buf
, len
, "%o ", mode
);
276 if (ret
< 0 || (size_t)ret
>= len
)
277 return got_error(GOT_ERR_NO_SPACE
);
282 * Git expects directory tree entries to be sorted with an imaginary slash
283 * appended to their name, and will break otherwise. Let's be nice.
284 * This function is intended to be used with mergesort(3) to sort an
285 * array of pointers to struct got_tree_entry objects.
288 sort_tree_entries_the_way_git_likes_it(const void *arg1
, const void *arg2
)
290 struct got_tree_entry
* const *te1
= arg1
;
291 struct got_tree_entry
* const *te2
= arg2
;
292 char name1
[NAME_MAX
+ 2];
293 char name2
[NAME_MAX
+ 2];
295 strlcpy(name1
, (*te1
)->name
, sizeof(name1
));
296 strlcpy(name2
, (*te2
)->name
, sizeof(name2
));
297 if (S_ISDIR((*te1
)->mode
))
298 strlcat(name1
, "/", sizeof(name1
));
299 if (S_ISDIR((*te2
)->mode
))
300 strlcat(name2
, "/", sizeof(name2
));
301 return strcmp(name1
, name2
);
304 const struct got_error
*
305 got_object_tree_create(struct got_object_id
**id
,
306 struct got_pathlist_head
*paths
, int nentries
, struct got_repository
*repo
)
308 const struct got_error
*err
= NULL
;
309 char modebuf
[sizeof("100644 ")];
312 size_t headerlen
, len
= 0, n
;
313 FILE *treefile
= NULL
;
315 struct got_pathlist_entry
*pe
;
316 struct got_tree_entry
**sorted_entries
;
317 struct got_tree_entry
*te
;
322 got_hash_init(&ctx
, GOT_HASH_SHA1
);
324 sorted_entries
= calloc(nentries
, sizeof(struct got_tree_entry
*));
325 if (sorted_entries
== NULL
)
326 return got_error_from_errno("calloc");
329 TAILQ_FOREACH(pe
, paths
, entry
)
330 sorted_entries
[i
++] = pe
->data
;
331 mergesort(sorted_entries
, nentries
, sizeof(struct got_tree_entry
*),
332 sort_tree_entries_the_way_git_likes_it
);
334 for (i
= 0; i
< nentries
; i
++) {
335 te
= sorted_entries
[i
];
336 err
= te_mode2str(modebuf
, sizeof(modebuf
), te
);
339 len
+= strlen(modebuf
) + strlen(te
->name
) + 1 +
343 if (asprintf(&header
, "%s %zd", GOT_OBJ_LABEL_TREE
, len
) == -1) {
344 err
= got_error_from_errno("asprintf");
347 headerlen
= strlen(header
) + 1;
348 got_hash_update(&ctx
, header
, headerlen
);
350 treefile
= got_opentemp();
351 if (treefile
== NULL
) {
352 err
= got_error_from_errno("got_opentemp");
356 n
= fwrite(header
, 1, headerlen
, treefile
);
357 if (n
!= headerlen
) {
358 err
= got_ferror(treefile
, GOT_ERR_IO
);
361 treesize
+= headerlen
;
363 for (i
= 0; i
< nentries
; i
++) {
364 te
= sorted_entries
[i
];
365 err
= te_mode2str(modebuf
, sizeof(modebuf
), te
);
368 len
= strlen(modebuf
);
369 n
= fwrite(modebuf
, 1, len
, treefile
);
371 err
= got_ferror(treefile
, GOT_ERR_IO
);
374 got_hash_update(&ctx
, modebuf
, len
);
377 len
= strlen(te
->name
) + 1; /* must include NUL */
378 n
= fwrite(te
->name
, 1, len
, treefile
);
380 err
= got_ferror(treefile
, GOT_ERR_IO
);
383 got_hash_update(&ctx
, te
->name
, len
);
386 len
= SHA1_DIGEST_LENGTH
;
387 n
= fwrite(te
->id
.sha1
, 1, len
, treefile
);
389 err
= got_ferror(treefile
, GOT_ERR_IO
);
392 got_hash_update(&ctx
, te
->id
.sha1
, len
);
396 *id
= calloc(1, sizeof(**id
));
398 err
= got_error_from_errno("calloc");
401 got_hash_final_object_id(&ctx
, *id
);
403 if (fflush(treefile
) != 0) {
404 err
= got_error_from_errno("fflush");
409 err
= create_object_file(*id
, treefile
, treesize
, repo
);
412 free(sorted_entries
);
413 if (treefile
&& fclose(treefile
) == EOF
&& err
== NULL
)
414 err
= got_error_from_errno("fclose");
422 const struct got_error
*
423 got_object_commit_create(struct got_object_id
**id
,
424 struct got_object_id
*tree_id
, struct got_object_id_queue
*parent_ids
,
425 int nparents
, const char *author
, time_t author_time
,
426 const char *committer
, time_t committer_time
,
427 const char *logmsg
, struct got_repository
*repo
)
429 const struct got_error
*err
= NULL
;
431 char *header
= NULL
, *tree_str
= NULL
;
432 char *author_str
= NULL
, *committer_str
= NULL
;
434 size_t headerlen
, len
= 0, n
;
435 FILE *commitfile
= NULL
;
436 off_t commitsize
= 0;
437 struct got_object_qid
*qid
;
442 got_hash_init(&ctx
, GOT_HASH_SHA1
);
444 msg0
= strdup(logmsg
);
446 return got_error_from_errno("strdup");
449 while (isspace((unsigned char)msg
[0]))
452 while (len
> 0 && isspace((unsigned char)msg
[len
- 1])) {
457 if (asprintf(&author_str
, "%s%s %lld +0000\n",
458 GOT_COMMIT_LABEL_AUTHOR
, author
, (long long)author_time
) == -1) {
459 err
= got_error_from_errno("asprintf");
463 if (asprintf(&committer_str
, "%s%s %lld +0000\n",
464 GOT_COMMIT_LABEL_COMMITTER
, committer
? committer
: author
,
465 (long long)(committer
? committer_time
: author_time
))
467 err
= got_error_from_errno("asprintf");
471 len
= strlen(GOT_COMMIT_LABEL_TREE
) + SHA1_DIGEST_STRING_LENGTH
+
473 (strlen(GOT_COMMIT_LABEL_PARENT
) + SHA1_DIGEST_STRING_LENGTH
) +
474 + strlen(author_str
) + strlen(committer_str
) + 2 + strlen(msg
);
476 if (asprintf(&header
, "%s %zd", GOT_OBJ_LABEL_COMMIT
, len
) == -1) {
477 err
= got_error_from_errno("asprintf");
480 headerlen
= strlen(header
) + 1;
481 got_hash_update(&ctx
, header
, headerlen
);
483 commitfile
= got_opentemp();
484 if (commitfile
== NULL
) {
485 err
= got_error_from_errno("got_opentemp");
489 n
= fwrite(header
, 1, headerlen
, commitfile
);
490 if (n
!= headerlen
) {
491 err
= got_ferror(commitfile
, GOT_ERR_IO
);
494 commitsize
+= headerlen
;
496 err
= got_object_id_str(&id_str
, tree_id
);
499 if (asprintf(&tree_str
, "%s%s\n", GOT_COMMIT_LABEL_TREE
, id_str
)
501 err
= got_error_from_errno("asprintf");
504 len
= strlen(tree_str
);
505 got_hash_update(&ctx
, tree_str
, len
);
506 n
= fwrite(tree_str
, 1, len
, commitfile
);
508 err
= got_ferror(commitfile
, GOT_ERR_IO
);
516 STAILQ_FOREACH(qid
, parent_ids
, entry
) {
517 char *parent_str
= NULL
;
519 err
= got_object_id_str(&id_str
, &qid
->id
);
522 if (asprintf(&parent_str
, "%s%s\n",
523 GOT_COMMIT_LABEL_PARENT
, id_str
) == -1) {
524 err
= got_error_from_errno("asprintf");
527 len
= strlen(parent_str
);
528 got_hash_update(&ctx
, parent_str
, len
);
529 n
= fwrite(parent_str
, 1, len
, commitfile
);
531 err
= got_ferror(commitfile
, GOT_ERR_IO
);
542 len
= strlen(author_str
);
543 got_hash_update(&ctx
, author_str
, len
);
544 n
= fwrite(author_str
, 1, len
, commitfile
);
546 err
= got_ferror(commitfile
, GOT_ERR_IO
);
551 len
= strlen(committer_str
);
552 got_hash_update(&ctx
, committer_str
, len
);
553 n
= fwrite(committer_str
, 1, len
, commitfile
);
555 err
= got_ferror(commitfile
, GOT_ERR_IO
);
560 got_hash_update(&ctx
, "\n", 1);
561 n
= fwrite("\n", 1, 1, commitfile
);
563 err
= got_ferror(commitfile
, GOT_ERR_IO
);
569 got_hash_update(&ctx
, msg
, len
);
570 n
= fwrite(msg
, 1, len
, commitfile
);
572 err
= got_ferror(commitfile
, GOT_ERR_IO
);
577 got_hash_update(&ctx
, "\n", 1);
578 n
= fwrite("\n", 1, 1, commitfile
);
580 err
= got_ferror(commitfile
, GOT_ERR_IO
);
585 *id
= calloc(1, sizeof(**id
));
587 err
= got_error_from_errno("calloc");
590 got_hash_final_object_id(&ctx
, *id
);
592 if (fflush(commitfile
) != 0) {
593 err
= got_error_from_errno("fflush");
598 err
= create_object_file(*id
, commitfile
, commitsize
, repo
);
606 if (commitfile
&& fclose(commitfile
) == EOF
&& err
== NULL
)
607 err
= got_error_from_errno("fclose");
615 const struct got_error
*
616 got_object_tag_create(struct got_object_id
**id
,
617 const char *tag_name
, struct got_object_id
*object_id
, const char *tagger
,
618 time_t tagger_time
, const char *tagmsg
, const char *signer_id
,
619 struct got_repository
*repo
, int verbosity
)
621 const struct got_error
*err
= NULL
;
624 char *tag_str
= NULL
, *tagger_str
= NULL
;
625 char *id_str
= NULL
, *obj_str
= NULL
, *type_str
= NULL
;
626 size_t headerlen
, len
= 0, sig_len
= 0, n
;
627 FILE *tagfile
= NULL
;
629 char *msg0
= NULL
, *msg
;
630 const char *obj_type_str
;
636 got_hash_init(&ctx
, GOT_HASH_SHA1
);
638 err
= got_object_id_str(&id_str
, object_id
);
641 if (asprintf(&obj_str
, "%s%s\n", GOT_TAG_LABEL_OBJECT
, id_str
) == -1) {
642 err
= got_error_from_errno("asprintf");
646 err
= got_object_get_type(&obj_type
, repo
, object_id
);
651 case GOT_OBJ_TYPE_BLOB
:
652 obj_type_str
= GOT_OBJ_LABEL_BLOB
;
654 case GOT_OBJ_TYPE_TREE
:
655 obj_type_str
= GOT_OBJ_LABEL_TREE
;
657 case GOT_OBJ_TYPE_COMMIT
:
658 obj_type_str
= GOT_OBJ_LABEL_COMMIT
;
660 case GOT_OBJ_TYPE_TAG
:
661 obj_type_str
= GOT_OBJ_LABEL_TAG
;
664 err
= got_error(GOT_ERR_OBJ_TYPE
);
668 if (asprintf(&type_str
, "%s%s\n", GOT_TAG_LABEL_TYPE
,
669 obj_type_str
) == -1) {
670 err
= got_error_from_errno("asprintf");
674 if (asprintf(&tag_str
, "%s%s\n", GOT_TAG_LABEL_TAG
, tag_name
) == -1) {
675 err
= got_error_from_errno("asprintf");
679 if (asprintf(&tagger_str
, "%s%s %lld +0000\n",
680 GOT_TAG_LABEL_TAGGER
, tagger
, (long long)tagger_time
) == -1)
681 return got_error_from_errno("asprintf");
683 msg0
= strdup(tagmsg
);
685 err
= got_error_from_errno("strdup");
690 while (isspace((unsigned char)msg
[0]))
699 err
= buf_alloc(&buf
, 0);
704 err
= buf_puts(&len
, buf
, obj_str
);
707 err
= buf_puts(&len
, buf
, type_str
);
710 err
= buf_puts(&len
, buf
, tag_str
);
713 err
= buf_puts(&len
, buf
, tagger_str
);
716 err
= buf_putc(buf
, '\n');
719 err
= buf_puts(&len
, buf
, msg
);
722 err
= buf_putc(buf
, '\n');
726 err
= got_sigs_sign_tag_ssh(&pid
, &in_fd
, &out_fd
, signer_id
,
730 if (buf_write_fd(buf
, in_fd
) == -1) {
731 err
= got_error_from_errno("write");
734 if (close(in_fd
) == -1) {
735 err
= got_error_from_errno("close");
739 if (waitpid(pid
, &status
, 0) == -1) {
740 err
= got_error_from_errno("waitpid");
743 if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
744 err
= got_error(GOT_ERR_SIGNING_TAG
);
749 err
= buf_load_fd(&buf
, out_fd
);
752 sig_len
= buf_len(buf
);
753 if (close(out_fd
) == -1) {
754 err
= got_error_from_errno("close");
759 len
= strlen(obj_str
) + strlen(type_str
) + strlen(tag_str
) +
760 strlen(tagger_str
) + 1 + strlen(msg
) + 1 + sig_len
;
761 if (asprintf(&header
, "%s %zd", GOT_OBJ_LABEL_TAG
, len
) == -1) {
762 err
= got_error_from_errno("asprintf");
766 headerlen
= strlen(header
) + 1;
767 got_hash_update(&ctx
, header
, headerlen
);
769 tagfile
= got_opentemp();
770 if (tagfile
== NULL
) {
771 err
= got_error_from_errno("got_opentemp");
775 n
= fwrite(header
, 1, headerlen
, tagfile
);
776 if (n
!= headerlen
) {
777 err
= got_ferror(tagfile
, GOT_ERR_IO
);
780 tagsize
+= headerlen
;
781 len
= strlen(obj_str
);
782 got_hash_update(&ctx
, obj_str
, len
);
783 n
= fwrite(obj_str
, 1, len
, tagfile
);
785 err
= got_ferror(tagfile
, GOT_ERR_IO
);
789 len
= strlen(type_str
);
790 got_hash_update(&ctx
, type_str
, len
);
791 n
= fwrite(type_str
, 1, len
, tagfile
);
793 err
= got_ferror(tagfile
, GOT_ERR_IO
);
798 len
= strlen(tag_str
);
799 got_hash_update(&ctx
, tag_str
, len
);
800 n
= fwrite(tag_str
, 1, len
, tagfile
);
802 err
= got_ferror(tagfile
, GOT_ERR_IO
);
807 len
= strlen(tagger_str
);
808 got_hash_update(&ctx
, tagger_str
, len
);
809 n
= fwrite(tagger_str
, 1, len
, tagfile
);
811 err
= got_ferror(tagfile
, GOT_ERR_IO
);
816 got_hash_update(&ctx
, "\n", 1);
817 n
= fwrite("\n", 1, 1, tagfile
);
819 err
= got_ferror(tagfile
, GOT_ERR_IO
);
825 got_hash_update(&ctx
, msg
, len
);
826 n
= fwrite(msg
, 1, len
, tagfile
);
828 err
= got_ferror(tagfile
, GOT_ERR_IO
);
833 got_hash_update(&ctx
, "\n", 1);
834 n
= fwrite("\n", 1, 1, tagfile
);
836 err
= got_ferror(tagfile
, GOT_ERR_IO
);
841 if (signer_id
&& buf_len(buf
) > 0) {
843 got_hash_update(&ctx
, buf_get(buf
), len
);
844 n
= fwrite(buf_get(buf
), 1, len
, tagfile
);
846 err
= got_ferror(tagfile
, GOT_ERR_IO
);
852 *id
= calloc(1, sizeof(**id
));
854 err
= got_error_from_errno("calloc");
857 got_hash_final_object_id(&ctx
, *id
);
859 if (fflush(tagfile
) != 0) {
860 err
= got_error_from_errno("fflush");
865 err
= create_object_file(*id
, tagfile
, tagsize
, repo
);
873 if (tagfile
&& fclose(tagfile
) == EOF
&& err
== NULL
)
874 err
= got_error_from_errno("fclose");