commit - 40cf7208131e42d6d484d93ea5e4fd69daf3de04
commit + 876c234bd6598fe15505cb4befb6e0809752c450
blob - b1d1830b01b36ea576c29ee80aba577fc0adf4ae
blob + f37d59860962d9ba6610ce564206b13bddd1f756
--- lib/got_lib_object_parse.h
+++ lib/got_lib_object_parse.h
const struct got_error *got_read_file_to_mem(uint8_t **, size_t *, FILE *);
void got_object_tree_entry_close(struct got_tree_entry *);
+
+struct got_pack;
+struct got_packidx;
+
+const struct got_error *got_object_packed_read_privsep(struct got_object **,
+ struct got_repository *, struct got_pack *, struct got_packidx *, int,
+ struct got_object_id *);
blob - 4de7dfb978353377b576337a4fb4bea2052821a4
blob + c36360e3371cbea006d4f4cffe3cad2e726123d4
--- lib/got_lib_pack.h
+++ lib/got_lib_pack.h
int fd;
uint8_t *map;
size_t filesize;
+ struct got_privsep_child *privsep_child;
};
+const struct got_error *got_pack_stop_privsep_child(struct got_pack *);
const struct got_error *got_pack_close(struct got_pack *);
#define GOT_PACK_PREFIX "pack-"
blob - 1932648fb838ffb3fe750b46ae9dd0e9adebae65
blob + bd788e1cf8afe72c07db5ba44934534ace650175
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
#define GOT_PROG_READ_TREE got-read-tree
#define GOT_PROG_READ_COMMIT got-read-commit
#define GOT_PROG_READ_BLOB got-read-blob
+#define GOT_PROG_READ_PACK got-read-pack
#define GOT_STRINGIFY(x) #x
#define GOT_STRINGVAL(x) GOT_STRINGIFY(x)
GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_COMMIT)
#define GOT_PATH_PROG_READ_BLOB \
GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_BLOB)
+#define GOT_PATH_PROG_READ_PACK \
+ GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_PACK)
+struct got_privsep_child {
+ int imsg_fd;
+ pid_t pid;
+ struct imsgbuf *ibuf;
+};
+
enum got_imsg_type {
/* An error occured while processing a request. */
GOT_IMSG_ERROR,
GOT_IMSG_BLOB_REQUEST,
GOT_IMSG_BLOB_OUTFD,
GOT_IMSG_BLOB,
+
+ /* Messages related to pack files. */
+ GOT_IMSG_PACKIDX,
+ GOT_IMSG_PACK,
+ GOT_IMSG_PACKED_OBJECT_REQUEST,
+
/* Messages for transmitting deltas and associated delta streams: */
GOT_IMSG_DELTA,
GOT_IMSG_DELTA_STREAM,
size_t delta_len;
/*
- * Followed by delta stream in remaining bytes of imsg buffer.
- * If delta_len exceeds imsg buffer length, followed by one or
- * more DELTA_STREAM messages until delta_len bytes of delta
- * stream have been transmitted.
+ * Followed by one or more DELTA_STREAM messages until delta_len
+ * bytes of delta stream have been transmitted.
*/
};
size_t hdrlen;
size_t size;
+ off_t pack_offset;
int ndeltas; /* this many GOT_IMSG_DELTA messages follow */
};
size_t size;
};
+/* Structure for GOT_IMSG_PACKIDX. */
+struct got_imsg_packidx {
+ size_t len;
+ /* Additionally, a file desciptor is passed via imsg. */
+};
+
+/* Structure for GOT_IMSG_PACK. */
+struct got_imsg_pack {
+ char path_packfile[PATH_MAX];
+ size_t filesize;
+ /* Additionally, a file desciptor is passed via imsg. */
+};
+
+/*
+ * Structure for GOT_IMSG_PACKED_OBJECT_REQUEST data.
+ */
+struct got_imsg_packed_object {
+ int idx;
+};
+
+struct got_pack;
+struct got_packidx;
+
+const struct got_error *got_privsep_wait_for_child(pid_t);
const struct got_error *got_privsep_send_stop(int);
const struct got_error *got_privsep_recv_imsg(struct imsg *, struct imsgbuf *,
size_t);
struct got_object *);
const struct got_error *got_privsep_send_blob_req(struct imsgbuf *, int, int);
const struct got_error *got_privsep_send_obj(struct imsgbuf *,
- struct got_object *, int);
+ struct got_object *);
const struct got_error *got_privsep_recv_obj(struct got_object **,
struct imsgbuf *);
const struct got_error *got_privsep_send_commit(struct imsgbuf *,
struct got_tree_object *);
const struct got_error *got_privsep_send_blob(struct imsgbuf *, size_t);
const struct got_error *got_privsep_recv_blob(size_t *, struct imsgbuf *);
+const struct got_error *got_privsep_init_pack_child(struct imsgbuf *,
+ struct got_pack *, struct got_packidx *);
+const struct got_error *got_privsep_send_packed_obj_req(struct imsgbuf *, int);
+const struct got_error *got_privsep_send_pack_child_ready(struct imsgbuf *);
blob - 4c18ac2b1f6e9d6d8c7eaf5b8fb1b21cf92d2813
blob + d663456eb11bc81aa37a87e77507c574b311dcc7
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
int cache_miss;
};
-struct got_privsep_child {
- int imsg_fd;
- pid_t pid;
- struct imsgbuf *ibuf;
-};
-
struct got_repository {
char *path;
char *path_git_dir;
/* Open file handles for pack files. */
struct got_pack packs[GOT_PACK_CACHE_SIZE];
- /* Handles to child processes for reading pack files. */
- struct got_privsep_child pack_privsep_children[GOT_PACK_CACHE_SIZE];
-
/* Handles to child processes for reading loose objects. */
struct got_privsep_child privsep_children[4];
#define GOT_REPO_PRIVSEP_CHILD_OBJECT 0
blob - 876b0f74524ae19d1d229b5b36fdf463a0b76678
blob + a7327c30c72cf05bcb5f66bd7533321a2618c7f6
--- lib/object.c
+++ lib/object.c
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/wait.h>
+#include <sys/syslimits.h>
#include <errno.h>
#include <fcntl.h>
goto done;
}
- err = got_packfile_open_object(obj, pack, packidx, idx, id);
+ err = got_object_packed_read_privsep(obj, repo, pack, packidx, idx, id);
if (err)
goto done;
blob - ae0f79da9b119071a9e68b2b7e4dc9471dc0fbbe
blob + e65fda042d9ca8b020b2446672505c315fe8f146
--- lib/object_parse.c
+++ lib/object_parse.c
#include <sys/queue.h>
#include <sys/uio.h>
#include <sys/socket.h>
+#include <sys/syslimits.h>
#include <sys/wait.h>
#include <errno.h>
return request_object(obj, repo, obj_fd);
}
+static const struct got_error *
+request_packed_object(struct got_object **obj, struct got_pack *pack, int idx,
+ struct got_object_id *id)
+{
+ const struct got_error *err = NULL;
+ struct imsgbuf *ibuf = pack->privsep_child->ibuf;
+
+ err = got_privsep_send_packed_obj_req(ibuf, idx);
+ if (err)
+ return err;
+
+ err = got_privsep_recv_obj(obj, ibuf);
+ if (err)
+ return err;
+
+ (*obj)->path_packfile = strdup(pack->path_packfile);
+ if ((*obj)->path_packfile == NULL) {
+ err = got_error_from_errno();
+ return err;
+ }
+ memcpy(&(*obj)->id, id, sizeof((*obj)->id));
+
+ return NULL;
+}
+
+const struct got_error *
+got_object_packed_read_privsep(struct got_object **obj,
+ struct got_repository *repo, struct got_pack *pack,
+ struct got_packidx *packidx, int idx, struct got_object_id *id)
+{
+ const struct got_error *err = NULL;
+ int imsg_fds[2];
+ pid_t pid;
+ struct imsgbuf *ibuf;
+
+ if (pack->privsep_child)
+ return request_packed_object(obj, pack, idx, id);
+
+ ibuf = calloc(1, sizeof(*ibuf));
+ if (ibuf == NULL)
+ return got_error_from_errno();
+
+ pack->privsep_child = calloc(1, sizeof(*pack->privsep_child));
+ if (pack->privsep_child == NULL) {
+ err = got_error_from_errno();
+ free(ibuf);
+ return err;
+ }
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ err = got_error_from_errno();
+ goto done;
+ } else if (pid == 0) {
+ exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_PACK,
+ pack->path_packfile);
+ /* not reached */
+ }
+
+ close(imsg_fds[1]);
+ pack->privsep_child->imsg_fd = imsg_fds[0];
+ pack->privsep_child->pid = pid;
+ imsg_init(ibuf, imsg_fds[0]);
+ pack->privsep_child->ibuf = ibuf;
+
+ err = got_privsep_init_pack_child(ibuf, pack, packidx);
+ if (err) {
+ const struct got_error *child_err;
+ err = got_privsep_send_stop(pack->privsep_child->imsg_fd);
+ child_err = got_privsep_wait_for_child(
+ pack->privsep_child->pid);
+ if (child_err && err == NULL)
+ err = child_err;
+ free(ibuf);
+ free(pack->privsep_child);
+ pack->privsep_child = NULL;
+ return err;
+ }
+
+done:
+ if (err) {
+ free(ibuf);
+ free(pack->privsep_child);
+ pack->privsep_child = NULL;
+ } else
+ err = request_packed_object(obj, pack, idx, id);
+ return err;
+}
+
struct got_commit_object *
got_object_commit_alloc_partial(void)
{
blob - d0a4ae18c3cecf4dc659772b0c5f005b5d15119b
blob + 00d5a158a66d76ebd4b9210a50d5bbabccef3c7b
--- lib/pack.c
+++ lib/pack.c
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/queue.h>
+#include <sys/uio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sha1.h>
#include <endian.h>
#include <zlib.h>
+#include <imsg.h>
#include "got_error.h"
#include "got_object.h"
#include "got_lib_delta.h"
#include "got_lib_inflate.h"
#include "got_lib_object.h"
+#include "got_lib_privsep.h"
#ifndef nitems
#define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
}
const struct got_error *
+got_pack_stop_privsep_child(struct got_pack *pack)
+{
+ const struct got_error *err = NULL, *child_err = NULL;
+
+ if (pack->privsep_child == NULL)
+ return NULL;
+
+ err = got_privsep_send_stop(pack->privsep_child->imsg_fd);
+ child_err = got_privsep_wait_for_child(
+ pack->privsep_child->pid);
+ if (child_err && err == NULL)
+ err = child_err;
+ free(pack->privsep_child);
+ pack->privsep_child = NULL;
+ return err;
+}
+
+const struct got_error *
got_pack_close(struct got_pack *pack)
{
const struct got_error *err = NULL;
- if (pack->map && munmap(pack->map, pack->filesize) == -1)
+ err = got_pack_stop_privsep_child(pack);
+ if (pack->map && munmap(pack->map, pack->filesize) == -1 && !err)
err = got_error_from_errno();
close(pack->fd);
pack->fd = -1;
(*obj)->flags = GOT_OBJ_FLAG_PACKED;
(*obj)->hdrlen = 0;
(*obj)->size = size;
- memcpy(&(*obj)->id, id, sizeof((*obj)->id));
+ if (id)
+ memcpy(&(*obj)->id, id, sizeof((*obj)->id));
(*obj)->pack_offset = offset;
return NULL;
(*obj)->flags = 0;
(*obj)->hdrlen = 0;
(*obj)->size = 0; /* Not known because deltas aren't applied yet. */
- memcpy(&(*obj)->id, id, sizeof((*obj)->id));
+ if (id)
+ memcpy(&(*obj)->id, id, sizeof((*obj)->id));
(*obj)->pack_offset = offset + tslen;
(*obj)->path_packfile = strdup(pack->path_packfile);
blob - e01100b024d9a4e2277b55413469962af808b8c4
blob + fbd2510c80004cc514a078c8e4d6c7a2c2b89fa3
--- lib/privsep.c
+++ lib/privsep.c
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/uio.h>
+#include <sys/syslimits.h>
+#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include "got_lib_object.h"
#include "got_lib_object_parse.h"
#include "got_lib_privsep.h"
+#include "got_lib_pack.h"
#ifndef MIN
#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
}
const struct got_error *
+got_privsep_wait_for_child(pid_t pid)
+{
+ int child_status;
+
+ waitpid(pid, &child_status, 0);
+
+ if (!WIFEXITED(child_status))
+ return got_error(GOT_ERR_PRIVSEP_DIED);
+
+ if (WEXITSTATUS(child_status) != 0)
+ return got_error(GOT_ERR_PRIVSEP_EXIT);
+
+ return NULL;
+}
+
+const struct got_error *
got_privsep_recv_imsg(struct imsg *imsg, struct imsgbuf *ibuf, size_t min_datalen)
{
const struct got_error *err;
ssize_t n;
- err = read_imsg(ibuf);
- if (err)
- return err;
-
n = imsg_get(ibuf, imsg);
- if (n == 0)
- return got_error(GOT_ERR_PRIVSEP_READ);
+ if (n == -1)
+ return got_error_from_errno();
+ while (n == 0) {
+ err = read_imsg(ibuf);
+ if (err)
+ return err;
+ n = imsg_get(ibuf, imsg);
+ }
+
if (imsg->hdr.len < IMSG_HEADER_SIZE + min_datalen)
return got_error(GOT_ERR_PRIVSEP_LEN);
iobj.hdrlen = obj->hdrlen;
iobj.size = obj->size;
iobj.ndeltas = 0;
+ if (iobj.flags & GOT_OBJ_FLAG_PACKED)
+ iobj.pack_offset = obj->pack_offset;
iobjp = &iobj;
iobj_size = sizeof(iobj);
return flush_imsg(ibuf);
}
+static const struct got_error *
+send_delta(struct got_delta *delta, struct imsgbuf *ibuf)
+{
+ struct got_imsg_delta idelta;
+ size_t offset, remain;
+
+ idelta.offset = delta->offset;
+ idelta.tslen = delta->tslen;
+ idelta.type = delta->type;
+ idelta.size = delta->size;
+ idelta.data_offset = delta->data_offset;
+ idelta.delta_len = delta->delta_len;
+
+ if (imsg_compose(ibuf, GOT_IMSG_DELTA, 0, 0, -1,
+ &idelta, sizeof(idelta)) == -1)
+ return got_error_from_errno();
+
+ if (imsg_flush(ibuf) == -1)
+ return got_error_from_errno();
+
+ offset = 0;
+ remain = delta->delta_len;
+ while (remain > 0) {
+ size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE, remain);
+
+ if (imsg_compose(ibuf, GOT_IMSG_DELTA_STREAM, 0, 0, -1,
+ delta->delta_buf + offset, n) == -1)
+ return got_error_from_errno();
+
+ if (imsg_flush(ibuf) == -1)
+ return got_error_from_errno();
+
+ offset += n;
+ remain -= n;
+ }
+
+ return NULL;
+}
+
const struct got_error *
-got_privsep_send_obj(struct imsgbuf *ibuf, struct got_object *obj, int ndeltas)
+got_privsep_send_obj(struct imsgbuf *ibuf, struct got_object *obj)
{
+ const struct got_error *err = NULL;
struct got_imsg_object iobj;
+ struct got_delta *delta;
iobj.type = obj->type;
iobj.flags = obj->flags;
iobj.hdrlen = obj->hdrlen;
iobj.size = obj->size;
- iobj.ndeltas = ndeltas;
+ iobj.ndeltas = obj->deltas.nentries;
+ if (iobj.flags & GOT_OBJ_FLAG_PACKED)
+ iobj.pack_offset = obj->pack_offset;
- if (ndeltas > 0) {
- /* TODO: Handle deltas */
- }
-
if (imsg_compose(ibuf, GOT_IMSG_OBJECT, 0, 0, -1, &iobj, sizeof(iobj))
== -1)
return got_error_from_errno();
- return flush_imsg(ibuf);
+ err = flush_imsg(ibuf);
+ if (err)
+ return err;
+
+ SIMPLEQ_FOREACH(delta, &obj->deltas.entries, entry) {
+ err = send_delta(delta, ibuf);
+ if (err)
+ break;
+ }
+
+ return err;
}
+static const struct got_error *
+receive_delta(struct got_delta **delta, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ struct got_imsg_delta idelta;
+ uint8_t *delta_buf = NULL;
+ const size_t min_datalen =
+ MIN(sizeof(struct got_imsg_error), sizeof(struct got_imsg_delta));
+ size_t datalen, offset, remain;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
+ if (err)
+ return err;
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ if (imsg.hdr.type == GOT_IMSG_ERROR)
+ return recv_imsg_error(&imsg, datalen);
+
+ if (imsg.hdr.type != GOT_IMSG_DELTA)
+ return got_error(GOT_ERR_PRIVSEP_MSG);
+ if (datalen != sizeof(idelta))
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+
+ memcpy(&idelta, imsg.data, sizeof(idelta));
+ imsg_free(&imsg);
+
+ switch (idelta.type) {
+ case GOT_OBJ_TYPE_OFFSET_DELTA:
+ case GOT_OBJ_TYPE_REF_DELTA:
+ if (idelta.delta_len < GOT_DELTA_STREAM_LENGTH_MIN)
+ return got_error(GOT_ERR_BAD_DELTA);
+ break;
+ default:
+ if (idelta.delta_len != 0)
+ return got_error(GOT_ERR_BAD_DELTA);
+ break;
+ }
+
+ if (idelta.delta_len > 0) {
+ delta_buf = calloc(1, idelta.delta_len);
+ if (delta_buf == NULL)
+ return got_error_from_errno();
+
+ offset = 0;
+ remain = idelta.delta_len;
+ while (remain > 0) {
+ size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE, remain);
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, n);
+ if (err)
+ return err;
+
+ if (imsg.hdr.type == GOT_IMSG_ERROR)
+ return recv_imsg_error(&imsg, datalen);
+
+ if (imsg.hdr.type == GOT_IMSG_STOP)
+ break;
+
+ if (imsg.hdr.type != GOT_IMSG_DELTA_STREAM)
+ return got_error(GOT_ERR_PRIVSEP_MSG);
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ if (datalen != n)
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+
+ memcpy(delta_buf + offset, imsg.data, n);
+ imsg_free(&imsg);
+
+ offset += n;
+ remain -= n;
+ }
+ }
+
+ *delta = got_delta_open(idelta.offset, idelta.tslen, idelta.type,
+ idelta.size, idelta.data_offset, delta_buf, idelta.delta_len);
+ if (*delta == NULL) {
+ err = got_error_from_errno();
+ free(delta_buf);
+ }
+
+ return err;
+}
+
const struct got_error *
got_privsep_recv_obj(struct got_object **obj, struct imsgbuf *ibuf)
{
err = got_error(GOT_ERR_PRIVSEP_LEN);
break;
}
+ if (iobj.ndeltas > 0 &&
+ (iobj.flags & GOT_OBJ_FLAG_DELTIFIED) == 0) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ break;
+ }
*obj = calloc(1, sizeof(**obj));
if (*obj == NULL) {
}
(*obj)->type = iobj.type;
+ (*obj)->flags = iobj.flags;
(*obj)->hdrlen = iobj.hdrlen;
(*obj)->size = iobj.size;
+ /* id and path_packfile might be copied in by caller */
+ (*obj)->pack_offset = iobj.pack_offset;
+ SIMPLEQ_INIT(&(*obj)->deltas.entries);
for (i = 0; i < iobj.ndeltas; i++) {
- /* TODO: Handle deltas */
+ struct got_delta *delta;
+ err = receive_delta(&delta, ibuf);
+ if (err)
+ break;
+ (*obj)->deltas.nentries++;
+ SIMPLEQ_INSERT_TAIL(&(*obj)->deltas.entries, delta,
+ entry);
}
break;
default:
return err;
}
+
+const struct got_error *
+got_privsep_init_pack_child(struct imsgbuf *ibuf, struct got_pack *pack,
+ struct got_packidx *packidx)
+{
+ struct got_imsg_packidx ipackidx;
+ struct got_imsg_pack ipack;
+ int fd;
+
+ ipackidx.len = packidx->len;
+ fd = dup(packidx->fd);
+ if (fd == -1)
+ return got_error_from_errno();
+
+ if (imsg_compose(ibuf, GOT_IMSG_PACKIDX, 0, 0, fd, &ipackidx,
+ sizeof(ipackidx)) == -1)
+ return got_error_from_errno();
+
+ if (strlcpy(ipack.path_packfile, pack->path_packfile,
+ sizeof(ipack.path_packfile)) >= sizeof(ipack.path_packfile))
+ return got_error(GOT_ERR_NO_SPACE);
+ ipack.filesize = pack->filesize;
+
+ fd = dup(pack->fd);
+ if (fd == -1)
+ return got_error_from_errno();
+
+ if (imsg_compose(ibuf, GOT_IMSG_PACK, 0, 0, fd, &ipack, sizeof(ipack))
+ == -1)
+ return got_error_from_errno();
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_send_packed_obj_req(struct imsgbuf *ibuf, int idx)
+{
+ struct got_imsg_packed_object iobj;
+
+ iobj.idx = idx;
+
+ if (imsg_compose(ibuf, GOT_IMSG_PACKED_OBJECT_REQUEST, 0, 0, -1,
+ &iobj, sizeof(iobj)) == -1)
+ return got_error_from_errno();
+
+ return flush_imsg(ibuf);
+}
blob - d7db2f58c13d7070176e00eb3563b5a567520170
blob + f0fb85579ae6052de9bd7214f47e96826c6d1577
--- lib/repository.c
+++ lib/repository.c
#include <sys/queue.h>
#include <sys/uio.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <sys/mman.h>
+#include <sys/syslimits.h>
#include <fcntl.h>
#include <limits.h>
#include "got_lib_inflate.h"
#include "got_lib_object.h"
#include "got_lib_pack.h"
+#include "got_lib_privsep.h"
#include "got_lib_repository.h"
#include "got_lib_worktree.h"
#include "got_lib_object_idcache.h"
-#include "got_lib_privsep.h"
#ifndef nitems
#define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
}
#endif
-static const struct got_error *
-wait_for_child(pid_t pid)
-{
- int child_status;
-
- waitpid(pid, &child_status, 0);
-
- if (!WIFEXITED(child_status))
- return got_error(GOT_ERR_PRIVSEP_DIED);
-
- if (WEXITSTATUS(child_status) != 0)
- return got_error(GOT_ERR_PRIVSEP_EXIT);
-
- return NULL;
-}
-
const struct got_error *
got_repo_close(struct got_repository *repo)
{
imsg_clear(repo->privsep_children[i].ibuf);
free(repo->privsep_children[i].ibuf);
err = got_privsep_send_stop(repo->privsep_children[i].imsg_fd);
- child_err = wait_for_child(repo->privsep_children[i].pid);
+ child_err = got_privsep_wait_for_child(
+ repo->privsep_children[i].pid);
if (child_err && err == NULL)
err = child_err;
close(repo->privsep_children[i].imsg_fd);
blob - 33f79980386c63a8da9a85071f4a800d04fd8d20
blob + ca4265c6c9cffaefb598a20e1a7d751b1b8d97aa
--- libexec/Makefile
+++ libexec/Makefile
-SUBDIR = got-read-blob got-read-commit got-read-object got-read-tree
+SUBDIR = got-read-blob got-read-commit got-read-object got-read-tree \
+ got-read-pack
.include <bsd.subdir.mk>
blob - 2302e711eaaf23075b4319ef22ba5cc36caefdff
blob + eaf315f5317e307d53c4178c251da9213dd36241
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/limits.h>
+#include <sys/syslimits.h>
#include <stdint.h>
#include <imsg.h>
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
- if (imsg.hdr.len == 0)
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
err = NULL;
break;
}
imsg_free(&imsg);
imsg_free(&imsg_outfd);
if (err) {
- got_privsep_send_error(&ibuf, err);
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
+ err = NULL;
+ else
+ got_privsep_send_error(&ibuf, err);
break;
}
}
blob - 178dd961e87c303cc67120aaa8d9878f9fb741b2
blob + 7936f1a29d699fa3b1c6a3252f558c313a59f205
--- libexec/got-read-commit/got-read-commit.c
+++ libexec/got-read-commit/got-read-commit.c
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/limits.h>
+#include <sys/syslimits.h>
#include <stdint.h>
#include <imsg.h>
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
- if (imsg.hdr.len == 0)
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
err = NULL;
break;
}
if (obj)
got_object_close(obj);
if (err) {
- got_privsep_send_error(&ibuf, err);
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
+ err = NULL;
+ else
+ got_privsep_send_error(&ibuf, err);
break;
}
}
blob - 0911e80092f384fa5eec6a65e28f5b24b5849066
blob + 8a787460e3108b743e5595fb7ee1bb1a2da55afb
--- libexec/got-read-object/got-read-object.c
+++ libexec/got-read-object/got-read-object.c
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/limits.h>
+#include <sys/syslimits.h>
#include <stdint.h>
#include <imsg.h>
while (1) {
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
- if (imsg.hdr.len == 0)
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
err = NULL;
break;
}
if (err)
goto done;
- err = got_privsep_send_obj(&ibuf, obj, 0);
+ err = got_privsep_send_obj(&ibuf, obj);
done:
close(imsg.fd);
imsg_free(&imsg);
if (obj)
got_object_close(obj);
if (err) {
- got_privsep_send_error(&ibuf, err);
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
+ err = NULL;
+ else
+ got_privsep_send_error(&ibuf, err);
break;
}
}
blob - 43696a70aa71949a1566e43e2e43d3f9b0076481
blob + cb003bb2a8f4e554783c2a0c22796481435ee1f3
--- libexec/got-read-tree/got-read-tree.c
+++ libexec/got-read-tree/got-read-tree.c
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/limits.h>
+#include <sys/syslimits.h>
#include <stdint.h>
#include <imsg.h>
err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
if (err) {
- if (imsg.hdr.len == 0)
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
err = NULL;
break;
}
if (obj)
got_object_close(obj);
if (err) {
- got_privsep_send_error(&ibuf, err);
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
+ err = NULL;
+ else
+ got_privsep_send_error(&ibuf, err);
break;
}
}
blob - /dev/null
blob + 688107f4d8b2a5ce11d51c5dab085e2ec0da4d97 (mode 644)
--- /dev/null
+++ libexec/got-read-pack/Makefile
+.PATH:${.CURDIR}/../../lib
+
+PROG= got-read-pack
+SRCS= got-read-pack.c delta.c error.c inflate.c object_parse.c \
+ opentemp.c pack.c path.c privsep.c sha1.c
+
+CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
+LDADD = -lutil -lz
+DPADD = ${LIBZ} ${LIBUTIL}
+
+# For now, default to installing binary in ~/bin
+GROUP!=id -g -n
+install:
+ ${INSTALL} ${INSTALL_COPY} -o ${USER} -g ${GROUP} \
+ -m ${BINMODE} ${PROG} ${GOT_LIBEXECDIR}/${PROG}
+
+# Don't install man pages yet
+NOMAN = Yes
+
+.include <bsd.prog.mk>
blob - /dev/null
blob + f243749639d228ffa0c9ee34ec70c83ce07e3b5d (mode 644)
--- /dev/null
+++ libexec/got-read-pack/got-read-pack.c
+/*
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/limits.h>
+#include <sys/syslimits.h>
+#include <sys/mman.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <imsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sha1.h>
+#include <zlib.h>
+
+#include "got_error.h"
+#include "got_object.h"
+
+#include "got_lib_delta.h"
+#include "got_lib_inflate.h"
+#include "got_lib_object.h"
+#include "got_lib_object_parse.h"
+#include "got_lib_privsep.h"
+#include "got_lib_pack.h"
+
+static const struct got_error *
+object_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
+ struct got_packidx *packidx)
+{
+ const struct got_error *err = NULL;
+ struct got_imsg_packed_object iobj;
+ struct got_object *obj;
+ size_t datalen;
+
+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+ if (datalen != sizeof(iobj))
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+ memcpy(&iobj, imsg->data, sizeof(iobj));
+
+ err = got_packfile_open_object(&obj, pack, packidx, iobj.idx, NULL);
+ if (err)
+ return err;
+
+ err = got_privsep_send_obj(ibuf, obj);
+ got_object_close(obj);
+ return err;
+}
+
+static const struct got_error *
+commit_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
+ struct got_packidx *packidx)
+{
+ return got_error(GOT_ERR_NOT_IMPL);
+}
+
+static const struct got_error *
+tree_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
+ struct got_packidx *packidx)
+{
+ return got_error(GOT_ERR_NOT_IMPL);
+}
+
+static const struct got_error *
+blob_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
+ struct got_packidx *packidx)
+{
+ return got_error(GOT_ERR_NOT_IMPL);
+}
+
+static const struct got_error *
+receive_packidx(struct got_packidx **packidx, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ struct got_imsg_packidx ipackidx;
+ size_t datalen;
+ struct got_packidx *p;
+
+ *packidx = NULL;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, 0);
+ if (err)
+ return err;
+
+ p = calloc(1, sizeof(*p));
+ if (p == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ if (imsg.hdr.type != GOT_IMSG_PACKIDX) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ goto done;
+ }
+
+ if (imsg.fd == -1) {
+ err = got_error(GOT_ERR_PRIVSEP_NO_FD);
+ goto done;
+ }
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ if (datalen != sizeof(ipackidx)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ memcpy(&ipackidx, imsg.data, sizeof(ipackidx));
+
+ p->len = ipackidx.len;
+ p->fd = dup(imsg.fd);
+ if (p->fd == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+#ifndef GOT_PACK_NO_MMAP
+ p->map = mmap(NULL, p->len, PROT_READ, MAP_PRIVATE, p->fd, 0);
+ if (p->map == MAP_FAILED)
+ p->map = NULL; /* fall back to read(2) */
+#endif
+ err = got_packidx_init_hdr(p, 1);
+done:
+ if (err) {
+ if (imsg.fd != -1)
+ close(imsg.fd);
+ got_packidx_close(p);
+ } else
+ *packidx = p;
+ imsg_free(&imsg);
+ return err;
+}
+
+static const struct got_error *
+receive_pack(struct got_pack **packp, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ struct got_imsg_pack ipack;
+ size_t datalen;
+ struct got_pack *pack;
+
+ *packp = NULL;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, 0);
+ if (err)
+ return err;
+
+ pack = calloc(1, sizeof(*pack));
+ if (pack == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ if (imsg.hdr.type != GOT_IMSG_PACK) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ goto done;
+ }
+
+ if (imsg.fd == -1) {
+ err = got_error(GOT_ERR_PRIVSEP_NO_FD);
+ goto done;
+ }
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ if (datalen != sizeof(ipack)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ memcpy(&ipack, imsg.data, sizeof(ipack));
+
+ pack->filesize = ipack.filesize;
+ pack->fd = dup(imsg.fd);
+ if (pack->fd == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ pack->path_packfile = strdup(ipack.path_packfile);
+ if (pack->path_packfile == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+#ifndef GOT_PACK_NO_MMAP
+ pack->map = mmap(NULL, pack->filesize, PROT_READ, MAP_PRIVATE,
+ pack->fd, 0);
+ if (pack->map == MAP_FAILED)
+ pack->map = NULL; /* fall back to read(2) */
+#endif
+done:
+ if (err) {
+ if (imsg.fd != -1)
+ close(imsg.fd);
+ free(pack);
+ } else
+ *packp = pack;
+ imsg_free(&imsg);
+ return err;
+}
+
+int
+main(int argc, char *argv[])
+{
+ const struct got_error *err = NULL;
+ struct imsgbuf ibuf;
+ struct imsg imsg;
+ struct got_packidx *packidx;
+ struct got_pack *pack;
+
+ //static int attached;
+ //while (!attached) sleep(1);
+
+ imsg_init(&ibuf, GOT_IMSG_FD_CHILD);
+
+ /* revoke access to most system calls */
+ if (pledge("stdio recvfd", NULL) == -1) {
+ err = got_error_from_errno();
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
+
+ err = receive_packidx(&packidx, &ibuf);
+ if (err) {
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
+
+ err = receive_pack(&pack, &ibuf);
+ if (err) {
+ got_privsep_send_error(&ibuf, err);
+ return 1;
+ }
+
+ while (1) {
+ imsg.fd = -1;
+
+ err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
+ if (err) {
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
+ err = NULL;
+ break;
+ }
+
+ if (imsg.hdr.type == GOT_IMSG_STOP)
+ break;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_PACKED_OBJECT_REQUEST:
+ err = object_request(&imsg, &ibuf, pack, packidx);
+ break;
+ case GOT_IMSG_COMMIT_REQUEST:
+ err = commit_request(&imsg, &ibuf, pack, packidx);
+ break;
+ case GOT_IMSG_TREE_REQUEST:
+ err = tree_request(&imsg, &ibuf, pack, packidx);
+ break;
+ case GOT_IMSG_BLOB_REQUEST:
+ err = blob_request(&imsg, &ibuf, pack, packidx);
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+
+ if (imsg.fd != -1)
+ close(imsg.fd);
+ imsg_free(&imsg);
+ if (err) {
+ if (err->code == GOT_ERR_PRIVSEP_PIPE)
+ err = NULL;
+ else
+ got_privsep_send_error(&ibuf, err);
+ break;
+ }
+ }
+
+ got_pack_close(pack);
+ imsg_clear(&ibuf);
+ if (err)
+ fprintf(stderr, "%s: %s\n", getprogname(), err->msg);
+ close(GOT_IMSG_FD_CHILD);
+ return err ? 1 : 0;
+}