Download raw body.
chores; move patch send/recv to privsep.c
'got patch' is the only part of got that sends and receives messages
outside of privsep.c. When i first implemented it I haven't realize
this.
I tried to minimize the changes as much as possible. The only
difference is that recv_patch (now got_privsep_recv_patch) doesn't call
patch_free anymore, as i didn't want to export that function too.
Instead, we explicitly call it in the error path in patch.c, not a big
deal. I flipped the order of the params for consistency with the other
got_privsep_* functions.
thoughts/ok?
P.S. some of the errors used in got_privsep_recv_patch are not the best
choice, I intend to change them after this goes in.
diff /home/op/w/got
commit - 02a5c5d00338c9549f6a399391841bd8219d91cf
path + /home/op/w/got
blob - /dev/null
file + lib/got_lib_patch.h
--- /dev/null
+++ lib/got_lib_patch.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 Omar Polo <op@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.
+ */
+
+struct got_patch_hunk {
+ STAILQ_ENTRY(got_patch_hunk) entries;
+ const struct got_error *err;
+ int ws_mangled;
+ int offset;
+ int old_nonl;
+ int new_nonl;
+ int old_from;
+ int old_lines;
+ int new_from;
+ int new_lines;
+ size_t len;
+ size_t cap;
+ char **lines;
+};
+
+STAILQ_HEAD(got_patch_hunk_head, got_patch_hunk);
+struct got_patch {
+ char *old;
+ char *new;
+ char cid[41];
+ char blob[41];
+ struct got_patch_hunk_head head;
+};
blob - dac4ab973b68243e262fd1ae6482fffb6dc2bc57
file + lib/got_lib_privsep.h
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
@@ -660,6 +660,7 @@ struct got_remote_repo;
struct got_pack;
struct got_packidx;
struct got_pathlist_head;
+struct got_patch;
const struct got_error *got_send_ack(pid_t);
const struct got_error *got_privsep_wait_for_child(pid_t);
@@ -827,4 +828,8 @@ const struct got_error *got_privsep_recv_painted_commi
struct got_object_id_queue *, got_privsep_recv_painted_commit_cb, void *,
struct imsgbuf *);
+const struct got_error *got_privsep_send_patch(int, struct imsgbuf *);
+const struct got_error *got_privsep_recv_patch(int *, struct got_patch *,
+ int, struct imsgbuf *);
+
void got_privsep_exec_child(int[2], const char *, const char *);
blob - dbbc9b38387c388c49654f106cab82c723f3dd06
file + lib/patch.c
--- lib/patch.c
+++ lib/patch.c
@@ -53,61 +53,16 @@
#include "got_lib_object.h"
#include "got_lib_privsep.h"
#include "got_lib_sha1.h"
+#include "got_lib_patch.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
-struct got_patch_hunk {
- STAILQ_ENTRY(got_patch_hunk) entries;
- const struct got_error *err;
- int ws_mangled;
- int offset;
- int old_nonl;
- int new_nonl;
- int old_from;
- int old_lines;
- int new_from;
- int new_lines;
- size_t len;
- size_t cap;
- char **lines;
-};
-
-STAILQ_HEAD(got_patch_hunk_head, got_patch_hunk);
-struct got_patch {
- char *old;
- char *new;
- char cid[41];
- char blob[41];
- struct got_patch_hunk_head head;
-};
-
struct patch_args {
got_patch_progress_cb progress_cb;
void *progress_arg;
struct got_patch_hunk_head *head;
};
-static const struct got_error *
-send_patch(struct imsgbuf *ibuf, int fd)
-{
- const struct got_error *err = NULL;
-
- if (imsg_compose(ibuf, GOT_IMSG_PATCH_FILE, 0, 0, fd,
- NULL, 0) == -1) {
- err = got_error_from_errno(
- "imsg_compose GOT_IMSG_PATCH_FILE");
- close(fd);
- return err;
- }
-
- if (imsg_flush(ibuf) == -1) {
- err = got_error_from_errno("imsg_flush");
- imsg_clear(ibuf);
- }
-
- return err;
-}
-
static void
patch_free(struct got_patch *p)
{
@@ -131,194 +86,6 @@ patch_free(struct got_patch *p)
STAILQ_INIT(&p->head);
}
-static const struct got_error *
-pushline(struct got_patch_hunk *h, const char *line)
-{
- void *t;
- size_t newcap;
-
- if (h->len == h->cap) {
- if ((newcap = h->cap * 1.5) == 0)
- newcap = 16;
- t = recallocarray(h->lines, h->cap, newcap,
- sizeof(h->lines[0]));
- if (t == NULL)
- return got_error_from_errno("recallocarray");
- h->lines = t;
- h->cap = newcap;
- }
-
- if ((t = strdup(line)) == NULL)
- return got_error_from_errno("strdup");
-
- h->lines[h->len++] = t;
- return NULL;
-}
-
-static const struct got_error *
-recv_patch(struct imsgbuf *ibuf, int *done, struct got_patch *p, int strip)
-{
- const struct got_error *err = NULL;
- struct imsg imsg;
- struct got_imsg_patch_hunk hdr;
- struct got_imsg_patch patch;
- struct got_patch_hunk *h = NULL;
- size_t datalen;
- int lastmode = -1;
-
- memset(p, 0, sizeof(*p));
- STAILQ_INIT(&p->head);
-
- err = got_privsep_recv_imsg(&imsg, ibuf, 0);
- if (err)
- return err;
- if (imsg.hdr.type == GOT_IMSG_PATCH_EOF) {
- *done = 1;
- goto done;
- }
- if (imsg.hdr.type != GOT_IMSG_PATCH) {
- err = got_error(GOT_ERR_PRIVSEP_MSG);
- goto done;
- }
- datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
- if (datalen != sizeof(patch)) {
- err = got_error(GOT_ERR_PRIVSEP_LEN);
- goto done;
- }
- memcpy(&patch, imsg.data, sizeof(patch));
-
- if (patch.old[sizeof(patch.old)-1] != '\0' ||
- patch.new[sizeof(patch.new)-1] != '\0' ||
- patch.cid[sizeof(patch.cid)-1] != '\0' ||
- patch.blob[sizeof(patch.blob)-1] != '\0') {
- err = got_error(GOT_ERR_PRIVSEP_LEN);
- goto done;
- }
-
- if (*patch.cid != '\0')
- strlcpy(p->cid, patch.cid, sizeof(p->cid));
-
- if (*patch.blob != '\0')
- strlcpy(p->blob, patch.blob, sizeof(p->blob));
-
- /* automatically set strip=1 for git-style diffs */
- if (strip == -1 && patch.git &&
- (*patch.old == '\0' || !strncmp(patch.old, "a/", 2)) &&
- (*patch.new == '\0' || !strncmp(patch.new, "b/", 2)))
- strip = 1;
-
- /* prefer the new name if not /dev/null for not git-style diffs */
- if (!patch.git && *patch.new != '\0' && *patch.old != '\0') {
- err = got_path_strip(&p->old, patch.new, strip);
- if (err)
- goto done;
- } else if (*patch.old != '\0') {
- err = got_path_strip(&p->old, patch.old, strip);
- if (err)
- goto done;
- }
-
- if (*patch.new != '\0') {
- err = got_path_strip(&p->new, patch.new, strip);
- if (err)
- goto done;
- }
-
- if (p->old == NULL && p->new == NULL) {
- err = got_error(GOT_ERR_PATCH_MALFORMED);
- goto done;
- }
-
- imsg_free(&imsg);
-
- for (;;) {
- char *t;
-
- err = got_privsep_recv_imsg(&imsg, ibuf, 0);
- if (err) {
- patch_free(p);
- return err;
- }
-
- datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
- switch (imsg.hdr.type) {
- case GOT_IMSG_PATCH_DONE:
- if (h != NULL && h->len == 0)
- err = got_error(GOT_ERR_PATCH_MALFORMED);
- goto done;
- case GOT_IMSG_PATCH_HUNK:
- if (h != NULL &&
- (h->len == 0 || h->old_nonl || h->new_nonl)) {
- err = got_error(GOT_ERR_PATCH_MALFORMED);
- goto done;
- }
- lastmode = -1;
- if (datalen != sizeof(hdr)) {
- err = got_error(GOT_ERR_PRIVSEP_LEN);
- goto done;
- }
- memcpy(&hdr, imsg.data, sizeof(hdr));
- if (hdr.oldfrom < 0 || hdr.newfrom < 0) {
- err = got_error(GOT_ERR_PRIVSEP_LEN);
- goto done;
- }
- if ((h = calloc(1, sizeof(*h))) == NULL) {
- err = got_error_from_errno("calloc");
- goto done;
- }
- h->old_from = hdr.oldfrom;
- h->old_lines = hdr.oldlines;
- h->new_from = hdr.newfrom;
- h->new_lines = hdr.newlines;
- STAILQ_INSERT_TAIL(&p->head, h, entries);
- break;
- case GOT_IMSG_PATCH_LINE:
- if (h == NULL) {
- err = got_error(GOT_ERR_PRIVSEP_MSG);
- goto done;
- }
- t = imsg.data;
- /* at least one char */
- if (datalen < 2 || t[datalen-1] != '\0') {
- err = got_error(GOT_ERR_PRIVSEP_MSG);
- goto done;
- }
- if (*t != ' ' && *t != '-' && *t != '+' &&
- *t != '\\') {
- err = got_error(GOT_ERR_PRIVSEP_MSG);
- goto done;
- }
-
- if (*t != '\\')
- err = pushline(h, t);
- else if (lastmode == '-')
- h->old_nonl = 1;
- else if (lastmode == '+')
- h->new_nonl = 1;
- else
- err = got_error(GOT_ERR_PATCH_MALFORMED);
-
- if (err)
- goto done;
-
- lastmode = *t;
- break;
- default:
- err = got_error(GOT_ERR_PRIVSEP_MSG);
- goto done;
- }
-
- imsg_free(&imsg);
- }
-
-done:
- if (err)
- patch_free(p);
-
- imsg_free(&imsg);
- return err;
-}
-
/*
* Copy data from orig starting at copypos until pos into tmp.
* If pos is -1, copy until EOF.
@@ -985,7 +752,7 @@ got_patch(int fd, struct got_worktree *worktree, struc
imsg_fds[1] = -1;
imsg_init(ibuf, imsg_fds[0]);
- err = send_patch(ibuf, fd);
+ err = got_privsep_send_patch(fd, ibuf);
fd = -1;
if (err)
goto done;
@@ -1003,9 +770,11 @@ got_patch(int fd, struct got_worktree *worktree, struc
pa.progress_arg = progress_arg;
pa.head = &p.head;
- err = recv_patch(ibuf, &done, &p, strip);
- if (err || done)
+ err = got_privsep_recv_patch(&done, &p, strip, ibuf);
+ if (err || done) {
+ patch_free(&p);
break;
+ }
if (reverse)
reverse_patch(&p);
blob - 9a16d647b870eb31f58c9d131d1174c60e7d5eb1
file + lib/privsep.c
--- lib/privsep.c
+++ lib/privsep.c
@@ -47,6 +47,7 @@
#include "got_lib_object_parse.h"
#include "got_lib_privsep.h"
#include "got_lib_pack.h"
+#include "got_lib_patch.h"
#include "got_privsep.h"
@@ -3527,6 +3528,212 @@ got_privsep_recv_painted_commits(struct got_object_id_
}
const struct got_error *
+got_privsep_send_patch(int fd, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+
+ if (imsg_compose(ibuf, GOT_IMSG_PATCH_FILE, 0, 0, fd,
+ NULL, 0) == -1) {
+ err = got_error_from_errno(
+ "imsg_compose GOT_IMSG_PATCH_FILE");
+ close(fd);
+ return err;
+ }
+
+ if (imsg_flush(ibuf) == -1) {
+ err = got_error_from_errno("imsg_flush");
+ imsg_clear(ibuf);
+ }
+
+ return err;
+}
+
+static const struct got_error *
+patch_addline(struct got_patch_hunk *h, const char *line)
+{
+ void *t;
+ size_t newcap;
+
+ if (h->len == h->cap) {
+ if ((newcap = h->cap * 1.5) == 0)
+ newcap = 16;
+ t = recallocarray(h->lines, h->cap, newcap,
+ sizeof(h->lines[0]));
+ if (t == NULL)
+ return got_error_from_errno("recallocarray");
+ h->lines = t;
+ h->cap = newcap;
+ }
+
+ if ((t = strdup(line)) == NULL)
+ return got_error_from_errno("strdup");
+
+ h->lines[h->len++] = t;
+ return NULL;
+}
+
+const struct got_error *
+got_privsep_recv_patch(int *done, struct got_patch *p, int strip,
+ struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ struct got_imsg_patch_hunk hdr;
+ struct got_imsg_patch patch;
+ struct got_patch_hunk *h = NULL;
+ size_t datalen;
+ int lastmode = -1;
+
+ *done = 0;
+ memset(p, 0, sizeof(*p));
+ STAILQ_INIT(&p->head);
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, 0);
+ if (err)
+ return err;
+ if (imsg.hdr.type == GOT_IMSG_PATCH_EOF) {
+ *done = 1;
+ goto done;
+ }
+ if (imsg.hdr.type != GOT_IMSG_PATCH) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ goto done;
+ }
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ if (datalen != sizeof(patch)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ memcpy(&patch, imsg.data, sizeof(patch));
+
+ if (patch.old[sizeof(patch.old) - 1] != '\0' ||
+ patch.new[sizeof(patch.new) - 1] != '\0' ||
+ patch.cid[sizeof(patch.cid) - 1] != '\0' ||
+ patch.blob[sizeof(patch.blob) - 1] != '\0') {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+
+ if (*patch.cid != '\0')
+ strlcpy(p->cid, patch.cid, sizeof(p->cid));
+
+ if (*patch.blob != '\0')
+ strlcpy(p->blob, patch.blob, sizeof(p->blob));
+
+ /* automatically set strip=1 for git-style diffs */
+ if (strip == -1 && patch.git &&
+ (*patch.old == '\0' || !strncmp(patch.old, "a/", 2)) &&
+ (*patch.new == '\0' || !strncmp(patch.new, "b/", 2)))
+ strip = 1;
+
+ /* prefer the new name if not /dev/null for not git-style diffs */
+ if (!patch.git && *patch.new != '\0' && *patch.old != '\0') {
+ err = got_path_strip(&p->old, patch.new, strip);
+ if (err)
+ goto done;
+ } else if (*patch.old != '\0') {
+ err = got_path_strip(&p->old, patch.old, strip);
+ if (err)
+ goto done;
+ }
+
+ if (*patch.new != '\0') {
+ err = got_path_strip(&p->new, patch.new, strip);
+ if (err)
+ goto done;
+ }
+
+ if (p->old == NULL && p->new == NULL) {
+ err = got_error(GOT_ERR_PATCH_MALFORMED);
+ goto done;
+ }
+
+ imsg_free(&imsg);
+
+ for (;;) {
+ char *t;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, 0);
+ if (err)
+ return err;
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_PATCH_DONE:
+ if (h != NULL && h->len == 0)
+ err = got_error(GOT_ERR_PATCH_MALFORMED);
+ goto done;
+ case GOT_IMSG_PATCH_HUNK:
+ if (h != NULL &&
+ (h->len == 0 || h->old_nonl || h->new_nonl)) {
+ err = got_error(GOT_ERR_PATCH_MALFORMED);
+ goto done;
+ }
+ lastmode = -1;
+ if (datalen != sizeof(hdr)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ memcpy(&hdr, imsg.data, sizeof(hdr));
+ if (hdr.oldfrom < 0 || hdr.newfrom < 0) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ if ((h = calloc(1, sizeof(*h))) == NULL) {
+ err = got_error_from_errno("calloc");
+ goto done;
+ }
+ h->old_from = hdr.oldfrom;
+ h->old_lines = hdr.oldlines;
+ h->new_from = hdr.newfrom;
+ h->new_lines = hdr.newlines;
+ STAILQ_INSERT_TAIL(&p->head, h, entries);
+ break;
+ case GOT_IMSG_PATCH_LINE:
+ if (h == NULL) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ goto done;
+ }
+ t = imsg.data;
+ /* at least one char */
+ if (datalen < 2 || t[datalen-1] != '\0') {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ goto done;
+ }
+ if (*t != ' ' && *t != '-' && *t != '+' &&
+ *t != '\\') {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ goto done;
+ }
+
+ if (*t != '\\')
+ err = patch_addline(h, t);
+ else if (lastmode == '-')
+ h->old_nonl = 1;
+ else if (lastmode == '+')
+ h->new_nonl = 1;
+ else
+ err = got_error(GOT_ERR_PATCH_MALFORMED);
+
+ if (err)
+ goto done;
+
+ lastmode = *t;
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ goto done;
+ }
+
+ imsg_free(&imsg);
+ }
+
+done:
+ imsg_free(&imsg);
+ return err;
+}
+
+const struct got_error *
got_privsep_unveil_exec_helpers(void)
{
const char *helpers[] = {
chores; move patch send/recv to privsep.c