2 * Copyright (c) 2019 Ori Bernstein <ori@openbsd.org>
3 * Copyright (c) 2020 Stefan Sperling <stsp@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/types.h>
19 #include <sys/queue.h>
32 #include "got_compat.h"
33 #include "got_error.h"
34 #include "got_object.h"
36 #include "got_lib_delta.h"
37 #include "got_lib_delta_cache.h"
38 #include "got_lib_hash.h"
39 #include "got_lib_object.h"
40 #include "got_lib_object_qid.h"
41 #include "got_lib_privsep.h"
42 #include "got_lib_ratelimit.h"
43 #include "got_lib_pack.h"
44 #include "got_lib_pack_index.h"
47 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
50 static const struct got_error
*
51 send_index_pack_progress(void *arg
, uint32_t nobj_total
, uint32_t nobj_indexed
,
52 uint32_t nobj_loose
, uint32_t nobj_resolved
)
54 struct imsgbuf
*ibuf
= arg
;
55 struct got_imsg_index_pack_progress iprogress
;
57 iprogress
.nobj_total
= nobj_total
;
58 iprogress
.nobj_indexed
= nobj_indexed
;
59 iprogress
.nobj_loose
= nobj_loose
;
60 iprogress
.nobj_resolved
= nobj_resolved
;
62 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_PROGRESS
, 0, 0, -1,
63 &iprogress
, sizeof(iprogress
)) == -1)
64 return got_error_from_errno("imsg_compose IDXPACK_PROGRESS");
66 return got_privsep_flush_imsg(ibuf
);
69 static const struct got_error
*
70 send_index_pack_done(struct imsgbuf
*ibuf
)
72 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_DONE
, 0, 0, -1, NULL
, 0) == -1)
73 return got_error_from_errno("imsg_compose FETCH");
74 return got_privsep_flush_imsg(ibuf
);
79 main(int argc
, char **argv
)
81 const struct got_error
*err
= NULL
, *close_err
;
85 int idxfd
= -1, tmpfd
= -1;
88 uint8_t pack_hash
[SHA1_DIGEST_LENGTH
];
90 struct got_ratelimit rl
;
97 got_ratelimit_init(&rl
, 0, 500);
99 for (i
= 0; i
< nitems(tmpfiles
); i
++)
102 memset(&pack
, 0, sizeof(pack
));
104 err
= got_delta_cache_alloc(&pack
.delta_cache
);
108 imsg_init(&ibuf
, GOT_IMSG_FD_CHILD
);
110 /* revoke access to most system calls */
111 if (pledge("stdio recvfd", NULL
) == -1) {
112 err
= got_error_from_errno("pledge");
113 got_privsep_send_error(&ibuf
, err
);
117 /* revoke fs access */
118 if (landlock_no_fs() == -1) {
119 err
= got_error_from_errno("landlock_no_fs");
120 got_privsep_send_error(&ibuf
, err
);
123 if (cap_enter() == -1) {
124 err
= got_error_from_errno("cap_enter");
125 got_privsep_send_error(&ibuf
, err
);
129 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
132 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
134 if (imsg
.hdr
.type
!= GOT_IMSG_IDXPACK_REQUEST
) {
135 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
138 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= sizeof(pack_hash
)) {
139 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
142 memcpy(pack_hash
, imsg
.data
, sizeof(pack_hash
));
145 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
148 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
150 if (imsg
.hdr
.type
!= GOT_IMSG_IDXPACK_OUTFD
) {
151 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
154 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= 0) {
155 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
160 for (i
= 0; i
< nitems(tmpfiles
); i
++) {
161 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
164 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
166 if (imsg
.hdr
.type
!= GOT_IMSG_TMPFD
) {
167 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
170 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= 0) {
171 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
175 tmpfiles
[i
] = fdopen(tmpfd
, "w+");
176 if (tmpfiles
[i
] == NULL
) {
177 err
= got_error_from_errno("fdopen");
183 if (lseek(pack
.fd
, 0, SEEK_END
) == -1) {
184 err
= got_error_from_errno("lseek");
187 packfile_size
= lseek(pack
.fd
, 0, SEEK_CUR
);
188 if (packfile_size
== -1) {
189 err
= got_error_from_errno("lseek");
192 pack
.filesize
= packfile_size
;
194 if (lseek(pack
.fd
, 0, SEEK_SET
) == -1) {
195 err
= got_error_from_errno("lseek");
199 #ifndef GOT_PACK_NO_MMAP
200 if (pack
.filesize
> 0 && pack
.filesize
<= SIZE_MAX
) {
201 pack
.map
= mmap(NULL
, pack
.filesize
, PROT_READ
, MAP_PRIVATE
,
203 if (pack
.map
== MAP_FAILED
)
204 pack
.map
= NULL
; /* fall back to read(2) */
207 err
= got_pack_index(&pack
, idxfd
, tmpfiles
[0], tmpfiles
[1],
208 tmpfiles
[2], pack_hash
, send_index_pack_progress
, &ibuf
, &rl
);
210 close_err
= got_pack_close(&pack
);
211 if (close_err
&& err
== NULL
)
213 if (idxfd
!= -1 && close(idxfd
) == -1 && err
== NULL
)
214 err
= got_error_from_errno("close");
215 if (tmpfd
!= -1 && close(tmpfd
) == -1 && err
== NULL
)
216 err
= got_error_from_errno("close");
217 for (i
= 0; i
< nitems(tmpfiles
); i
++) {
218 if (tmpfiles
[i
] != NULL
&& fclose(tmpfiles
[i
]) == EOF
&&
220 err
= got_error_from_errno("fclose");
224 err
= send_index_pack_done(&ibuf
);
226 got_privsep_send_error(&ibuf
, err
);
227 fprintf(stderr
, "%s: %s\n", getprogname(), err
->msg
);
228 got_privsep_send_error(&ibuf
, err
);