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>
34 #include "got_compat.h"
35 #include "got_error.h"
36 #include "got_object.h"
38 #include "got_lib_delta.h"
39 #include "got_lib_delta_cache.h"
40 #include "got_lib_hash.h"
41 #include "got_lib_object.h"
42 #include "got_lib_object_qid.h"
43 #include "got_lib_privsep.h"
44 #include "got_lib_ratelimit.h"
45 #include "got_lib_pack.h"
46 #include "got_lib_pack_index.h"
49 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
52 static const struct got_error
*
53 send_index_pack_progress(void *arg
, uint32_t nobj_total
, uint32_t nobj_indexed
,
54 uint32_t nobj_loose
, uint32_t nobj_resolved
)
56 struct imsgbuf
*ibuf
= arg
;
57 struct got_imsg_index_pack_progress iprogress
;
59 iprogress
.nobj_total
= nobj_total
;
60 iprogress
.nobj_indexed
= nobj_indexed
;
61 iprogress
.nobj_loose
= nobj_loose
;
62 iprogress
.nobj_resolved
= nobj_resolved
;
64 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_PROGRESS
, 0, 0, -1,
65 &iprogress
, sizeof(iprogress
)) == -1)
66 return got_error_from_errno("imsg_compose IDXPACK_PROGRESS");
68 return got_privsep_flush_imsg(ibuf
);
71 static const struct got_error
*
72 send_index_pack_done(struct imsgbuf
*ibuf
)
74 if (imsg_compose(ibuf
, GOT_IMSG_IDXPACK_DONE
, 0, 0, -1, NULL
, 0) == -1)
75 return got_error_from_errno("imsg_compose FETCH");
76 return got_privsep_flush_imsg(ibuf
);
81 main(int argc
, char **argv
)
83 const struct got_error
*err
= NULL
, *close_err
;
86 struct got_object_id pack_hash
;
88 int idxfd
= -1, tmpfd
= -1;
92 struct got_ratelimit rl
;
99 got_ratelimit_init(&rl
, 0, 500);
101 for (i
= 0; i
< nitems(tmpfiles
); i
++)
104 if (imsgbuf_init(&ibuf
, GOT_IMSG_FD_CHILD
) == -1) {
105 warn("imsgbuf_init");
108 imsgbuf_allow_fdpass(&ibuf
);
110 memset(&pack
, 0, sizeof(pack
));
112 err
= got_delta_cache_alloc(&pack
.delta_cache
);
116 /* revoke access to most system calls */
117 if (pledge("stdio recvfd", NULL
) == -1) {
118 err
= got_error_from_errno("pledge");
119 got_privsep_send_error(&ibuf
, err
);
120 imsgbuf_clear(&ibuf
);
124 /* revoke fs access */
125 if (landlock_no_fs() == -1) {
126 err
= got_error_from_errno("landlock_no_fs");
127 got_privsep_send_error(&ibuf
, err
);
130 if (cap_enter() == -1) {
131 err
= got_error_from_errno("cap_enter");
132 got_privsep_send_error(&ibuf
, err
);
136 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
139 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
141 if (imsg
.hdr
.type
!= GOT_IMSG_IDXPACK_REQUEST
) {
142 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
145 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= sizeof(pack_hash
)) {
146 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
149 memcpy(&pack_hash
, imsg
.data
, sizeof(pack_hash
));
150 pack
.fd
= imsg_get_fd(&imsg
);
151 pack
.algo
= pack_hash
.algo
;
153 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
156 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
158 if (imsg
.hdr
.type
!= GOT_IMSG_IDXPACK_OUTFD
) {
159 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
162 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= 0) {
163 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
166 idxfd
= imsg_get_fd(&imsg
);
168 for (i
= 0; i
< nitems(tmpfiles
); i
++) {
169 err
= got_privsep_recv_imsg(&imsg
, &ibuf
, 0);
172 if (imsg
.hdr
.type
== GOT_IMSG_STOP
)
174 if (imsg
.hdr
.type
!= GOT_IMSG_TMPFD
) {
175 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
178 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!= 0) {
179 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
182 tmpfd
= imsg_get_fd(&imsg
);
183 tmpfiles
[i
] = fdopen(tmpfd
, "w+");
184 if (tmpfiles
[i
] == NULL
) {
185 err
= got_error_from_errno("fdopen");
191 if (lseek(pack
.fd
, 0, SEEK_END
) == -1) {
192 err
= got_error_from_errno("lseek");
195 packfile_size
= lseek(pack
.fd
, 0, SEEK_CUR
);
196 if (packfile_size
== -1) {
197 err
= got_error_from_errno("lseek");
200 pack
.filesize
= packfile_size
;
202 if (lseek(pack
.fd
, 0, SEEK_SET
) == -1) {
203 err
= got_error_from_errno("lseek");
207 #ifndef GOT_PACK_NO_MMAP
208 if (pack
.filesize
> 0 && pack
.filesize
<= SIZE_MAX
) {
209 pack
.map
= mmap(NULL
, pack
.filesize
, PROT_READ
, MAP_PRIVATE
,
211 if (pack
.map
== MAP_FAILED
)
212 pack
.map
= NULL
; /* fall back to read(2) */
215 err
= got_pack_index(&pack
, idxfd
, tmpfiles
[0], tmpfiles
[1],
216 tmpfiles
[2], &pack_hash
, send_index_pack_progress
, &ibuf
, &rl
);
218 close_err
= got_pack_close(&pack
);
219 if (close_err
&& err
== NULL
)
221 if (idxfd
!= -1 && close(idxfd
) == -1 && err
== NULL
)
222 err
= got_error_from_errno("close");
223 if (tmpfd
!= -1 && close(tmpfd
) == -1 && err
== NULL
)
224 err
= got_error_from_errno("close");
225 for (i
= 0; i
< nitems(tmpfiles
); i
++) {
226 if (tmpfiles
[i
] != NULL
&& fclose(tmpfiles
[i
]) == EOF
&&
228 err
= got_error_from_errno("fclose");
232 err
= send_index_pack_done(&ibuf
);
234 got_privsep_send_error(&ibuf
, err
);
235 fprintf(stderr
, "%s: %s\n", getprogname(), err
->msg
);
236 got_privsep_send_error(&ibuf
, err
);
237 imsgbuf_clear(&ibuf
);
241 imsgbuf_clear(&ibuf
);