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 <sys/types.h>
32 #include "got_compat.h"
34 #include "got_error.h"
35 #include "got_object.h"
36 #include "got_repository.h"
37 #include "got_opentemp.h"
41 #include "got_lib_sha1.h"
42 #include "got_lib_deflate.h"
43 #include "got_lib_delta.h"
44 #include "got_lib_object.h"
45 #include "got_lib_object_parse.h"
46 #include "got_lib_lockfile.h"
48 #include "got_lib_object_create.h"
53 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
56 static const struct got_error
*
57 create_object_file(struct got_object_id
*id
, FILE *content
,
58 off_t content_len
, struct got_repository
*repo
)
60 const struct got_error
*err
= NULL
, *unlock_err
= NULL
;
61 char *objpath
= NULL
, *tmppath
= NULL
;
63 struct got_lockfile
*lf
= NULL
;
66 err
= got_object_get_path(&objpath
, id
, repo
);
70 err
= got_opentemp_named(&tmppath
, &tmpfile
, objpath
);
73 if (!(err
->code
== GOT_ERR_ERRNO
&& errno
== ENOENT
))
75 err
= got_path_dirname(&parent_path
, objpath
);
78 err
= got_path_mkdir(parent_path
);
82 err
= got_opentemp_named(&tmppath
, &tmpfile
, objpath
);
87 if (fchmod(fileno(tmpfile
), GOT_DEFAULT_FILE_MODE
) != 0) {
88 err
= got_error_from_errno2("fchmod", tmppath
);
92 err
= got_deflate_to_file(&tmplen
, content
, content_len
, tmpfile
, NULL
);
96 err
= got_lockfile_lock(&lf
, objpath
, -1);
100 if (rename(tmppath
, objpath
) != 0) {
101 err
= got_error_from_errno3("rename", tmppath
, objpath
);
109 if (unlink(tmppath
) != 0 && err
== NULL
)
110 err
= got_error_from_errno2("unlink", tmppath
);
113 if (tmpfile
&& fclose(tmpfile
) == EOF
&& err
== NULL
)
114 err
= got_error_from_errno("fclose");
116 unlock_err
= got_lockfile_unlock(lf
, -1);
117 return err
? err
: unlock_err
;
120 const struct got_error
*
121 got_object_blob_file_create(struct got_object_id
**id
, FILE **blobfile
,
122 off_t
*blobsize
, const char *ondisk_path
)
124 const struct got_error
*err
= NULL
;
129 size_t headerlen
= 0, n
;
137 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
139 if (!got_err_open_nofollow_on_symlink())
140 return got_error_from_errno2("open", ondisk_path
);
142 if (lstat(ondisk_path
, &sb
) == -1) {
143 err
= got_error_from_errno2("lstat", ondisk_path
);
146 } else if (fstat(fd
, &sb
) == -1) {
147 err
= got_error_from_errno2("fstat", ondisk_path
);
151 if (asprintf(&header
, "%s %lld", GOT_OBJ_LABEL_BLOB
,
152 (long long)sb
.st_size
) == -1) {
153 err
= got_error_from_errno("asprintf");
156 headerlen
= strlen(header
) + 1;
157 SHA1Update(&sha1_ctx
, header
, headerlen
);
159 *blobfile
= got_opentemp();
160 if (*blobfile
== NULL
) {
161 err
= got_error_from_errno("got_opentemp");
165 n
= fwrite(header
, 1, headerlen
, *blobfile
);
166 if (n
!= headerlen
) {
167 err
= got_ferror(*blobfile
, GOT_ERR_IO
);
170 *blobsize
+= headerlen
;
172 char buf
[PATH_MAX
* 8];
175 if (S_ISLNK(sb
.st_mode
)) {
176 inlen
= readlink(ondisk_path
, buf
, sizeof(buf
));
178 err
= got_error_from_errno("readlink");
182 inlen
= read(fd
, buf
, sizeof(buf
));
184 err
= got_error_from_errno("read");
190 SHA1Update(&sha1_ctx
, buf
, inlen
);
191 n
= fwrite(buf
, 1, inlen
, *blobfile
);
193 err
= got_ferror(*blobfile
, GOT_ERR_IO
);
197 if (S_ISLNK(sb
.st_mode
))
201 *id
= malloc(sizeof(**id
));
203 err
= got_error_from_errno("malloc");
206 SHA1Final((*id
)->sha1
, &sha1_ctx
);
208 if (fflush(*blobfile
) != 0) {
209 err
= got_error_from_errno("fflush");
215 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
216 err
= got_error_from_errno("close");
228 const struct got_error
*
229 got_object_blob_create(struct got_object_id
**id
, const char *ondisk_path
,
230 struct got_repository
*repo
)
232 const struct got_error
*err
= NULL
;
233 FILE *blobfile
= NULL
;
236 err
= got_object_blob_file_create(id
, &blobfile
, &blobsize
,
241 err
= create_object_file(*id
, blobfile
, blobsize
, repo
);
242 if (fclose(blobfile
) == EOF
&& err
== NULL
)
243 err
= got_error_from_errno("fclose");
251 static const struct got_error
*
252 te_mode2str(char *buf
, size_t len
, struct got_tree_entry
*te
)
258 * Some Git implementations are picky about modes seen in tree entries.
259 * For best compatibility we normalize the file/directory mode here.
261 if (S_ISREG(te
->mode
)) {
262 mode
= GOT_DEFAULT_FILE_MODE
;
263 if (te
->mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
))
264 mode
|= S_IXUSR
| S_IXGRP
| S_IXOTH
;
265 } else if (got_object_tree_entry_is_submodule(te
))
266 mode
= S_IFDIR
| S_IFLNK
;
267 else if (S_ISLNK(te
->mode
))
268 mode
= S_IFLNK
; /* Git leaves all the other bits unset. */
269 else if (S_ISDIR(te
->mode
))
270 mode
= S_IFDIR
; /* Git leaves all the other bits unset. */
272 return got_error(GOT_ERR_BAD_FILETYPE
);
274 ret
= snprintf(buf
, len
, "%o ", mode
);
275 if (ret
== -1 || ret
>= len
)
276 return got_error(GOT_ERR_NO_SPACE
);
281 * Git expects directory tree entries to be sorted with an imaginary slash
282 * appended to their name, and will break otherwise. Let's be nice.
283 * This function is intended to be used with mergesort(3) to sort an
284 * array of pointers to struct got_tree_entry objects.
287 sort_tree_entries_the_way_git_likes_it(const void *arg1
, const void *arg2
)
289 struct got_tree_entry
* const *te1
= arg1
;
290 struct got_tree_entry
* const *te2
= arg2
;
291 char name1
[NAME_MAX
+ 2];
292 char name2
[NAME_MAX
+ 2];
294 strlcpy(name1
, (*te1
)->name
, sizeof(name1
));
295 strlcpy(name2
, (*te2
)->name
, sizeof(name2
));
296 if (S_ISDIR((*te1
)->mode
))
297 strlcat(name1
, "/", sizeof(name1
));
298 if (S_ISDIR((*te2
)->mode
))
299 strlcat(name2
, "/", sizeof(name2
));
300 return strcmp(name1
, name2
);
303 const struct got_error
*
304 got_object_tree_create(struct got_object_id
**id
,
305 struct got_pathlist_head
*paths
, int nentries
, struct got_repository
*repo
)
307 const struct got_error
*err
= NULL
;
308 char modebuf
[sizeof("100644 ")];
311 size_t headerlen
, len
= 0, n
;
312 FILE *treefile
= NULL
;
314 struct got_pathlist_entry
*pe
;
315 struct got_tree_entry
**sorted_entries
;
316 struct got_tree_entry
*te
;
323 sorted_entries
= calloc(nentries
, sizeof(struct got_tree_entry
*));
324 if (sorted_entries
== NULL
)
325 return got_error_from_errno("calloc");
328 TAILQ_FOREACH(pe
, paths
, entry
)
329 sorted_entries
[i
++] = pe
->data
;
330 mergesort(sorted_entries
, nentries
, sizeof(struct got_tree_entry
*),
331 sort_tree_entries_the_way_git_likes_it
);
333 for (i
= 0; i
< nentries
; i
++) {
334 te
= sorted_entries
[i
];
335 err
= te_mode2str(modebuf
, sizeof(modebuf
), te
);
338 len
+= strlen(modebuf
) + strlen(te
->name
) + 1 +
342 if (asprintf(&header
, "%s %zd", GOT_OBJ_LABEL_TREE
, len
) == -1) {
343 err
= got_error_from_errno("asprintf");
346 headerlen
= strlen(header
) + 1;
347 SHA1Update(&sha1_ctx
, header
, headerlen
);
349 treefile
= got_opentemp();
350 if (treefile
== NULL
) {
351 err
= got_error_from_errno("got_opentemp");
355 n
= fwrite(header
, 1, headerlen
, treefile
);
356 if (n
!= headerlen
) {
357 err
= got_ferror(treefile
, GOT_ERR_IO
);
360 treesize
+= headerlen
;
362 for (i
= 0; i
< nentries
; i
++) {
363 te
= sorted_entries
[i
];
364 err
= te_mode2str(modebuf
, sizeof(modebuf
), te
);
367 len
= strlen(modebuf
);
368 n
= fwrite(modebuf
, 1, len
, treefile
);
370 err
= got_ferror(treefile
, GOT_ERR_IO
);
373 SHA1Update(&sha1_ctx
, modebuf
, len
);
376 len
= strlen(te
->name
) + 1; /* must include NUL */
377 n
= fwrite(te
->name
, 1, len
, treefile
);
379 err
= got_ferror(treefile
, GOT_ERR_IO
);
382 SHA1Update(&sha1_ctx
, te
->name
, len
);
385 len
= SHA1_DIGEST_LENGTH
;
386 n
= fwrite(te
->id
.sha1
, 1, len
, treefile
);
388 err
= got_ferror(treefile
, GOT_ERR_IO
);
391 SHA1Update(&sha1_ctx
, te
->id
.sha1
, len
);
395 *id
= malloc(sizeof(**id
));
397 err
= got_error_from_errno("malloc");
400 SHA1Final((*id
)->sha1
, &sha1_ctx
);
402 if (fflush(treefile
) != 0) {
403 err
= got_error_from_errno("fflush");
408 err
= create_object_file(*id
, treefile
, treesize
, repo
);
411 free(sorted_entries
);
412 if (treefile
&& fclose(treefile
) == EOF
&& err
== NULL
)
413 err
= got_error_from_errno("fclose");
421 const struct got_error
*
422 got_object_commit_create(struct got_object_id
**id
,
423 struct got_object_id
*tree_id
, struct got_object_id_queue
*parent_ids
,
424 int nparents
, const char *author
, time_t author_time
,
425 const char *committer
, time_t committer_time
,
426 const char *logmsg
, struct got_repository
*repo
)
428 const struct got_error
*err
= NULL
;
430 char *header
= NULL
, *tree_str
= NULL
;
431 char *author_str
= NULL
, *committer_str
= NULL
;
433 size_t headerlen
, len
= 0, n
;
434 FILE *commitfile
= NULL
;
435 off_t commitsize
= 0;
436 struct got_object_qid
*qid
;
443 msg0
= strdup(logmsg
);
445 return got_error_from_errno("strdup");
448 while (isspace((unsigned char)msg
[0]))
451 while (len
> 0 && isspace((unsigned char)msg
[len
- 1])) {
456 if (asprintf(&author_str
, "%s%s %lld +0000\n",
457 GOT_COMMIT_LABEL_AUTHOR
, author
, (long long)author_time
) == -1)
458 return got_error_from_errno("asprintf");
460 if (asprintf(&committer_str
, "%s%s %lld +0000\n",
461 GOT_COMMIT_LABEL_COMMITTER
, committer
? committer
: author
,
462 (long long)(committer
? committer_time
: author_time
))
464 err
= got_error_from_errno("asprintf");
468 len
= strlen(GOT_COMMIT_LABEL_TREE
) + SHA1_DIGEST_STRING_LENGTH
+
470 (strlen(GOT_COMMIT_LABEL_PARENT
) + SHA1_DIGEST_STRING_LENGTH
) +
471 + strlen(author_str
) + strlen(committer_str
) + 2 + strlen(msg
);
473 if (asprintf(&header
, "%s %zd", GOT_OBJ_LABEL_COMMIT
, len
) == -1) {
474 err
= got_error_from_errno("asprintf");
477 headerlen
= strlen(header
) + 1;
478 SHA1Update(&sha1_ctx
, header
, headerlen
);
480 commitfile
= got_opentemp();
481 if (commitfile
== NULL
) {
482 err
= got_error_from_errno("got_opentemp");
486 n
= fwrite(header
, 1, headerlen
, commitfile
);
487 if (n
!= headerlen
) {
488 err
= got_ferror(commitfile
, GOT_ERR_IO
);
491 commitsize
+= headerlen
;
493 err
= got_object_id_str(&id_str
, tree_id
);
496 if (asprintf(&tree_str
, "%s%s\n", GOT_COMMIT_LABEL_TREE
, id_str
)
498 err
= got_error_from_errno("asprintf");
501 len
= strlen(tree_str
);
502 SHA1Update(&sha1_ctx
, tree_str
, len
);
503 n
= fwrite(tree_str
, 1, len
, commitfile
);
505 err
= got_ferror(commitfile
, GOT_ERR_IO
);
513 STAILQ_FOREACH(qid
, parent_ids
, entry
) {
514 char *parent_str
= NULL
;
516 err
= got_object_id_str(&id_str
, &qid
->id
);
519 if (asprintf(&parent_str
, "%s%s\n",
520 GOT_COMMIT_LABEL_PARENT
, id_str
) == -1) {
521 err
= got_error_from_errno("asprintf");
524 len
= strlen(parent_str
);
525 SHA1Update(&sha1_ctx
, parent_str
, len
);
526 n
= fwrite(parent_str
, 1, len
, commitfile
);
528 err
= got_ferror(commitfile
, GOT_ERR_IO
);
539 len
= strlen(author_str
);
540 SHA1Update(&sha1_ctx
, author_str
, len
);
541 n
= fwrite(author_str
, 1, len
, commitfile
);
543 err
= got_ferror(commitfile
, GOT_ERR_IO
);
548 len
= strlen(committer_str
);
549 SHA1Update(&sha1_ctx
, committer_str
, len
);
550 n
= fwrite(committer_str
, 1, len
, commitfile
);
552 err
= got_ferror(commitfile
, GOT_ERR_IO
);
557 SHA1Update(&sha1_ctx
, "\n", 1);
558 n
= fwrite("\n", 1, 1, commitfile
);
560 err
= got_ferror(commitfile
, GOT_ERR_IO
);
566 SHA1Update(&sha1_ctx
, msg
, len
);
567 n
= fwrite(msg
, 1, len
, commitfile
);
569 err
= got_ferror(commitfile
, GOT_ERR_IO
);
574 SHA1Update(&sha1_ctx
, "\n", 1);
575 n
= fwrite("\n", 1, 1, commitfile
);
577 err
= got_ferror(commitfile
, GOT_ERR_IO
);
582 *id
= malloc(sizeof(**id
));
584 err
= got_error_from_errno("malloc");
587 SHA1Final((*id
)->sha1
, &sha1_ctx
);
589 if (fflush(commitfile
) != 0) {
590 err
= got_error_from_errno("fflush");
595 err
= create_object_file(*id
, commitfile
, commitsize
, repo
);
603 if (commitfile
&& fclose(commitfile
) == EOF
&& err
== NULL
)
604 err
= got_error_from_errno("fclose");
612 const struct got_error
*
613 got_object_tag_create(struct got_object_id
**id
,
614 const char *tag_name
, struct got_object_id
*object_id
, const char *tagger
,
615 time_t tagger_time
, const char *tagmsg
, const char *signer_id
,
616 struct got_repository
*repo
, int verbosity
)
618 const struct got_error
*err
= NULL
;
621 char *tag_str
= NULL
, *tagger_str
= NULL
;
622 char *id_str
= NULL
, *obj_str
= NULL
, *type_str
= NULL
;
623 size_t headerlen
, len
= 0, sig_len
= 0, n
;
624 FILE *tagfile
= NULL
;
626 char *msg0
= NULL
, *msg
;
627 const char *obj_type_str
;
635 err
= got_object_id_str(&id_str
, object_id
);
638 if (asprintf(&obj_str
, "%s%s\n", GOT_TAG_LABEL_OBJECT
, id_str
) == -1) {
639 err
= got_error_from_errno("asprintf");
643 err
= got_object_get_type(&obj_type
, repo
, object_id
);
648 case GOT_OBJ_TYPE_BLOB
:
649 obj_type_str
= GOT_OBJ_LABEL_BLOB
;
651 case GOT_OBJ_TYPE_TREE
:
652 obj_type_str
= GOT_OBJ_LABEL_TREE
;
654 case GOT_OBJ_TYPE_COMMIT
:
655 obj_type_str
= GOT_OBJ_LABEL_COMMIT
;
657 case GOT_OBJ_TYPE_TAG
:
658 obj_type_str
= GOT_OBJ_LABEL_TAG
;
661 err
= got_error(GOT_ERR_OBJ_TYPE
);
665 if (asprintf(&type_str
, "%s%s\n", GOT_TAG_LABEL_TYPE
,
666 obj_type_str
) == -1) {
667 err
= got_error_from_errno("asprintf");
671 if (asprintf(&tag_str
, "%s%s\n", GOT_TAG_LABEL_TAG
, tag_name
) == -1) {
672 err
= got_error_from_errno("asprintf");
676 if (asprintf(&tagger_str
, "%s%s %lld +0000\n",
677 GOT_TAG_LABEL_TAGGER
, tagger
, (long long)tagger_time
) == -1)
678 return got_error_from_errno("asprintf");
680 msg0
= strdup(tagmsg
);
682 err
= got_error_from_errno("strdup");
687 while (isspace((unsigned char)msg
[0]))
697 err
= buf_alloc(&buf
, 0);
702 err
= buf_puts(&len
, buf
, obj_str
);
705 err
= buf_puts(&len
, buf
, type_str
);
708 err
= buf_puts(&len
, buf
, tag_str
);
711 err
= buf_puts(&len
, buf
, tagger_str
);
714 err
= buf_putc(buf
, '\n');
717 err
= buf_puts(&len
, buf
, msg
);
720 err
= buf_putc(buf
, '\n');
724 err
= got_sigs_sign_tag_ssh(&pid
, &in_fd
, &out_fd
, signer_id
,
728 if (buf_write_fd(buf
, in_fd
) == -1) {
729 err
= got_error_from_errno("write");
732 if (close(in_fd
) == -1) {
733 err
= got_error_from_errno("close");
737 if (waitpid(pid
, &status
, 0) == -1) {
738 err
= got_error_from_errno("waitpid");
741 if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
742 err
= got_error(GOT_ERR_SIGNING_TAG
);
746 out
= fdopen(out_fd
, "r");
748 err
= got_error_from_errno("fdopen");
752 err
= buf_load(&buf
, out
);
755 sig_len
= buf_len(buf
) + 1;
756 err
= buf_putc(buf
, '\0');
759 if (close(out_fd
) == -1) {
760 err
= got_error_from_errno("close");
765 len
= strlen(obj_str
) + strlen(type_str
) + strlen(tag_str
) +
766 strlen(tagger_str
) + 1 + strlen(msg
) + 1 + sig_len
;
767 if (asprintf(&header
, "%s %zd", GOT_OBJ_LABEL_TAG
, len
) == -1) {
768 err
= got_error_from_errno("asprintf");
772 headerlen
= strlen(header
) + 1;
773 SHA1Update(&sha1_ctx
, header
, headerlen
);
775 tagfile
= got_opentemp();
776 if (tagfile
== NULL
) {
777 err
= got_error_from_errno("got_opentemp");
781 n
= fwrite(header
, 1, headerlen
, tagfile
);
782 if (n
!= headerlen
) {
783 err
= got_ferror(tagfile
, GOT_ERR_IO
);
786 tagsize
+= headerlen
;
787 len
= strlen(obj_str
);
788 SHA1Update(&sha1_ctx
, obj_str
, len
);
789 n
= fwrite(obj_str
, 1, len
, tagfile
);
791 err
= got_ferror(tagfile
, GOT_ERR_IO
);
795 len
= strlen(type_str
);
796 SHA1Update(&sha1_ctx
, type_str
, len
);
797 n
= fwrite(type_str
, 1, len
, tagfile
);
799 err
= got_ferror(tagfile
, GOT_ERR_IO
);
804 len
= strlen(tag_str
);
805 SHA1Update(&sha1_ctx
, tag_str
, len
);
806 n
= fwrite(tag_str
, 1, len
, tagfile
);
808 err
= got_ferror(tagfile
, GOT_ERR_IO
);
813 len
= strlen(tagger_str
);
814 SHA1Update(&sha1_ctx
, tagger_str
, len
);
815 n
= fwrite(tagger_str
, 1, len
, tagfile
);
817 err
= got_ferror(tagfile
, GOT_ERR_IO
);
822 SHA1Update(&sha1_ctx
, "\n", 1);
823 n
= fwrite("\n", 1, 1, tagfile
);
825 err
= got_ferror(tagfile
, GOT_ERR_IO
);
831 SHA1Update(&sha1_ctx
, msg
, len
);
832 n
= fwrite(msg
, 1, len
, tagfile
);
834 err
= got_ferror(tagfile
, GOT_ERR_IO
);
839 SHA1Update(&sha1_ctx
, "\n", 1);
840 n
= fwrite("\n", 1, 1, tagfile
);
842 err
= got_ferror(tagfile
, GOT_ERR_IO
);
847 if (signer_id
&& buf_len(buf
) > 0) {
849 SHA1Update(&sha1_ctx
, buf_get(buf
), len
);
850 n
= fwrite(buf_get(buf
), 1, len
, tagfile
);
852 err
= got_ferror(tagfile
, GOT_ERR_IO
);
858 *id
= malloc(sizeof(**id
));
860 err
= got_error_from_errno("malloc");
863 SHA1Final((*id
)->sha1
, &sha1_ctx
);
865 if (fflush(tagfile
) != 0) {
866 err
= got_error_from_errno("fflush");
871 err
= create_object_file(*id
, tagfile
, tagsize
, repo
);
879 if (tagfile
&& fclose(tagfile
) == EOF
&& err
== NULL
)
880 err
= got_error_from_errno("fclose");