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>
33 #include "got_compat.h"
34 #include "got_error.h"
35 #include "got_object.h"
37 #include "got_lib_delta.h"
38 #include "got_lib_delta_cache.h"
39 #include "got_lib_hash.h"
40 #include "got_lib_object.h"
41 #include "got_lib_object_qid.h"
42 #include "got_lib_privsep.h"
43 #include "got_lib_ratelimit.h"
44 #include "got_lib_pack.h"
45 #include "got_lib_pack_index.h"
48 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
51 static const struct got_error
*
52 send_index_pack_progress(void *arg
, uint32_t nobj_total
, uint32_t nobj_indexed
,
53 uint32_t nobj_loose
, uint32_t nobj_resolved
)
55 struct imsgbuf
*ibuf
= arg
;
56 struct got_imsg_index_pack_progress iprogress
;
58 iprogress
.nobj_total
= nobj_total
;
59 iprogress
.nobj_indexed
= nobj_indexed
;
60 iprogress
.nobj_loose
= nobj_loose
;
61 iprogress
.nobj_resolved
= nobj_resolved
;
63 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_PROGRESS
, 0, 0, -1,
64 &iprogress
, sizeof(iprogress
)) == -1)
65 return got_error_from_errno("imsg_compose IDXPACK_PROGRESS");
67 return got_privsep_flush_imsg(ibuf
);
70 static const struct got_error
*
71 send_index_pack_done(struct imsgbuf
*ibuf
)
73 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_DONE
, 0, 0, -1, NULL
, 0) == -1)
74 return got_error_from_errno("imsg_compose FETCH");
75 return got_privsep_flush_imsg(ibuf
);
80 main(int argc
, char **argv
)
82 const struct got_error
*err
= NULL
, *close_err
;
85 struct got_object_id pack_hash
;
87 int idxfd
= -1, tmpfd
= -1;
91 struct got_ratelimit rl
;
98 got_ratelimit_init(&rl
, 0, 500);
100 for (i
= 0; i
< nitems(tmpfiles
); i
++)
103 memset(&pack
, 0, sizeof(pack
));
105 err
= got_delta_cache_alloc(&pack
.delta_cache
);
109 if (imsgbuf_init(&ibuf
, GOT_IMSG_FD_CHILD
) == -1) {
110 warn("imsgbuf_init");
113 imsgbuf_allow_fdpass(&ibuf
);
115 /* revoke access to most system calls */
116 if (pledge("stdio recvfd", NULL
) == -1) {
117 err
= got_error_from_errno("pledge");
118 got_privsep_send_error(&ibuf
, err
);
122 /* revoke fs access */
123 if (landlock_no_fs() == -1) {
124 err
= got_error_from_errno("landlock_no_fs");
125 got_privsep_send_error(&ibuf
, err
);
128 if (cap_enter() == -1) {
129 err
= got_error_from_errno("cap_enter");
130 got_privsep_send_error(&ibuf
, err
);
134 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
137 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
139 if (imsg
.hdr
.type
!= GOT_IMSG_IDXPACK_REQUEST
) {
140 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
143 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= sizeof(pack_hash
)) {
144 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
147 memcpy(&pack_hash
, imsg
.data
, sizeof(pack_hash
));
148 pack
.fd
= imsg_get_fd(&imsg
);
149 pack
.algo
= pack_hash
.algo
;
151 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
154 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
156 if (imsg
.hdr
.type
!= GOT_IMSG_IDXPACK_OUTFD
) {
157 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
160 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= 0) {
161 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
164 idxfd
= imsg_get_fd(&imsg
);
166 for (i
= 0; i
< nitems(tmpfiles
); i
++) {
167 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
170 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
172 if (imsg
.hdr
.type
!= GOT_IMSG_TMPFD
) {
173 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
176 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= 0) {
177 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
180 tmpfd
= imsg_get_fd(&imsg
);
181 tmpfiles
[i
] = fdopen(tmpfd
, "w+");
182 if (tmpfiles
[i
] == NULL
) {
183 err
= got_error_from_errno("fdopen");
189 if (lseek(pack
.fd
, 0, SEEK_END
) == -1) {
190 err
= got_error_from_errno("lseek");
193 packfile_size
= lseek(pack
.fd
, 0, SEEK_CUR
);
194 if (packfile_size
== -1) {
195 err
= got_error_from_errno("lseek");
198 pack
.filesize
= packfile_size
;
200 if (lseek(pack
.fd
, 0, SEEK_SET
) == -1) {
201 err
= got_error_from_errno("lseek");
205 #ifndef GOT_PACK_NO_MMAP
206 if (pack
.filesize
> 0 && pack
.filesize
<= SIZE_MAX
) {
207 pack
.map
= mmap(NULL
, pack
.filesize
, PROT_READ
, MAP_PRIVATE
,
209 if (pack
.map
== MAP_FAILED
)
210 pack
.map
= NULL
; /* fall back to read(2) */
213 err
= got_pack_index(&pack
, idxfd
, tmpfiles
[0], tmpfiles
[1],
214 tmpfiles
[2], &pack_hash
, send_index_pack_progress
, &ibuf
, &rl
);
216 close_err
= got_pack_close(&pack
);
217 if (close_err
&& err
== NULL
)
219 if (idxfd
!= -1 && close(idxfd
) == -1 && err
== NULL
)
220 err
= got_error_from_errno("close");
221 if (tmpfd
!= -1 && close(tmpfd
) == -1 && err
== NULL
)
222 err
= got_error_from_errno("close");
223 for (i
= 0; i
< nitems(tmpfiles
); i
++) {
224 if (tmpfiles
[i
] != NULL
&& fclose(tmpfiles
[i
]) == EOF
&&
226 err
= got_error_from_errno("fclose");
230 err
= send_index_pack_done(&ibuf
);
232 got_privsep_send_error(&ibuf
, err
);
233 fprintf(stderr
, "%s: %s\n", getprogname(), err
->msg
);
234 got_privsep_send_error(&ibuf
, err
);