make got-index-pack clear its imsgbuf on exit to avoid leak reports
[got-portable.git] / libexec / got-index-pack / got-index-pack.c
blob2df5821acb36e16307473ce40fae65e904a9d9de
1 /*
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>
20 #include <sys/tree.h>
21 #include <sys/mman.h>
22 #include <sys/uio.h>
24 #include <err.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <imsg.h>
30 #include <limits.h>
31 #include <time.h>
32 #include <unistd.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"
48 #ifndef nitems
49 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
50 #endif
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);
80 int
81 main(int argc, char **argv)
83 const struct got_error *err = NULL, *close_err;
84 struct imsgbuf ibuf;
85 struct imsg imsg;
86 struct got_object_id pack_hash;
87 size_t i;
88 int idxfd = -1, tmpfd = -1;
89 FILE *tmpfiles[3];
90 struct got_pack pack;
91 off_t packfile_size;
92 struct got_ratelimit rl;
93 #if 0
94 static int attached;
95 while (!attached)
96 sleep(1);
97 #endif
99 got_ratelimit_init(&rl, 0, 500);
101 for (i = 0; i < nitems(tmpfiles); i++)
102 tmpfiles[i] = NULL;
104 if (imsgbuf_init(&ibuf, GOT_IMSG_FD_CHILD) == -1) {
105 warn("imsgbuf_init");
106 return 1;
108 imsgbuf_allow_fdpass(&ibuf);
110 memset(&pack, 0, sizeof(pack));
111 pack.fd = -1;
112 err = got_delta_cache_alloc(&pack.delta_cache);
113 if (err)
114 goto done;
115 #ifndef PROFILE
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);
121 return 1;
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);
128 return 1;
130 if (cap_enter() == -1) {
131 err = got_error_from_errno("cap_enter");
132 got_privsep_send_error(&ibuf, err);
133 return 1;
135 #endif
136 err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
137 if (err)
138 goto done;
139 if (imsg.hdr.type == GOT_IMSG_STOP)
140 goto done;
141 if (imsg.hdr.type != GOT_IMSG_IDXPACK_REQUEST) {
142 err = got_error(GOT_ERR_PRIVSEP_MSG);
143 goto done;
145 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(pack_hash)) {
146 err = got_error(GOT_ERR_PRIVSEP_LEN);
147 goto done;
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);
154 if (err)
155 goto done;
156 if (imsg.hdr.type == GOT_IMSG_STOP)
157 goto done;
158 if (imsg.hdr.type != GOT_IMSG_IDXPACK_OUTFD) {
159 err = got_error(GOT_ERR_PRIVSEP_MSG);
160 goto done;
162 if (imsg.hdr.len - IMSG_HEADER_SIZE != 0) {
163 err = got_error(GOT_ERR_PRIVSEP_LEN);
164 goto done;
166 idxfd = imsg_get_fd(&imsg);
168 for (i = 0; i < nitems(tmpfiles); i++) {
169 err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
170 if (err)
171 goto done;
172 if (imsg.hdr.type == GOT_IMSG_STOP)
173 goto done;
174 if (imsg.hdr.type != GOT_IMSG_TMPFD) {
175 err = got_error(GOT_ERR_PRIVSEP_MSG);
176 goto done;
178 if (imsg.hdr.len - IMSG_HEADER_SIZE != 0) {
179 err = got_error(GOT_ERR_PRIVSEP_LEN);
180 goto done;
182 tmpfd = imsg_get_fd(&imsg);
183 tmpfiles[i] = fdopen(tmpfd, "w+");
184 if (tmpfiles[i] == NULL) {
185 err = got_error_from_errno("fdopen");
186 goto done;
188 tmpfd = -1;
191 if (lseek(pack.fd, 0, SEEK_END) == -1) {
192 err = got_error_from_errno("lseek");
193 goto done;
195 packfile_size = lseek(pack.fd, 0, SEEK_CUR);
196 if (packfile_size == -1) {
197 err = got_error_from_errno("lseek");
198 goto done;
200 pack.filesize = packfile_size;
202 if (lseek(pack.fd, 0, SEEK_SET) == -1) {
203 err = got_error_from_errno("lseek");
204 goto done;
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,
210 pack.fd, 0);
211 if (pack.map == MAP_FAILED)
212 pack.map = NULL; /* fall back to read(2) */
214 #endif
215 err = got_pack_index(&pack, idxfd, tmpfiles[0], tmpfiles[1],
216 tmpfiles[2], &pack_hash, send_index_pack_progress, &ibuf, &rl);
217 done:
218 close_err = got_pack_close(&pack);
219 if (close_err && err == NULL)
220 err = close_err;
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 &&
227 err == NULL)
228 err = got_error_from_errno("fclose");
231 if (err == NULL)
232 err = send_index_pack_done(&ibuf);
233 if (err) {
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);
238 exit(1);
241 imsgbuf_clear(&ibuf);
242 exit(0);