commit - 13ce8c9368c159db1a4d9471a6cf7cf7cd83b73b
commit + abe0f35f1af70d4413ea3b79ef5f37eb0c7db2c2
blob - 83435ade8c0f36340678bfe485c738fc0cbe8fb8
blob + eec7237a4fc2f2bc544d6b22e892861661037774
--- lib/fetch.c
+++ lib/fetch.c
pid_t pid;
char *tmppackpath = NULL, *tmpidxpath = NULL, *default_destdir = NULL;
char *packpath = NULL, *idxpath = NULL, *id_str = NULL;
+ struct got_pathlist_head symrefs;
+ struct got_pathlist_entry *pe;
+
+ TAILQ_INIT(&symrefs);
fetchfd = -1;
if (got_parse_uri(uri, proto, host, port, path, repo) == -1)
struct got_object_id *id;
char *refname;
err = got_privsep_recv_fetch_progress(&done,
- &id, &refname, &ibuf);
+ &id, &refname, &symrefs, &ibuf);
if (err != NULL)
return err;
if (done) {
if (packhash == NULL)
return got_error_from_errno(
"got_object_id_dup");
- } else {
+ printf("symrefs:");
+ TAILQ_FOREACH(pe, &symrefs, entry) {
+ printf(" %s:%s", pe->path,
+ (const char *)pe->data);
+ }
+ printf("\n");
+ } else if (id) {
char *id_str;
/* TODO Use a progress callback */
err = got_object_id_str(&id_str, id);
free(packpath);
free(default_destdir);
free(packhash);
+ TAILQ_FOREACH(pe, &symrefs, entry) {
+ free((void *)pe->path);
+ free(pe->data);
+ }
+ got_pathlist_free(&symrefs);
return NULL;
}
blob - 4b14f8cacd48ffe10d30e6cf407481cd9e12e27f
blob + 96d82f6fab85ba429a3482411e1491566e7f97ce
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
/* Messages related to networking. */
GOT_IMSG_FETCH_REQUEST,
+ GOT_IMSG_FETCH_SYMREFS,
GOT_IMSG_FETCH_PROGRESS,
GOT_IMSG_FETCH_DONE,
GOT_IMSG_IDXPACK_REQUEST,
* Followed by 'tagmsg_len' bytes of tag message data in
* one or more GOT_IMSG_TAG_TAGMSG messages.
*/
+} __attribute__((__packed__));
+
+/* Structures for GOT_IMSG_FETCH_SYMREFS data. */
+struct got_imsg_fetch_symref {
+ size_t name_len;
+ size_t target_len;
+
+ /*
+ * Followed by name_len + target_len gata bytes.
+ */
+} __attribute__((__packed__));
+
+struct got_imsg_fetch_symrefs {
+ size_t nsymrefs;
+
+ /* Followed by nsymrefs times of got_imsg_fetch_symref data. */
} __attribute__((__packed__));
/* Structure for GOT_IMSG_FETCH_PROGRESS data. */
struct got_imsg_fetch_progress {
- /* Descirbes a reference which will be fetched. */
+ /* Describes a reference which will be fetched. */
uint8_t refid[SHA1_DIGEST_LENGTH];
/* Followed by reference name in remaining data of imsg buffer. */
};
const struct got_error *got_privsep_send_index_pack_done(struct imsgbuf *);
const struct got_error *got_privsep_wait_index_pack_done(struct imsgbuf *);
const struct got_error *got_privsep_send_fetch_req(struct imsgbuf *, int);
+const struct got_error *got_privsep_send_fetch_symrefs(struct imsgbuf *,
+ struct got_pathlist_head *);
const struct got_error *got_privsep_send_fetch_progress(struct imsgbuf *,
struct got_object_id *, const char *);
const struct got_error *got_privsep_recv_fetch_progress(int *,
- struct got_object_id **, char **, struct imsgbuf *);
+ struct got_object_id **, char **, struct got_pathlist_head *,
+ struct imsgbuf *);
const struct got_error *got_privsep_send_fetch_done(struct imsgbuf *,
struct got_object_id);
const struct got_error *got_privsep_get_imsg_obj(struct got_object **,
blob - 642c62a8f986362d8cddddd8fbeb351284c09e39
blob + 23b8318e31fac27d4a29d740ed4be0b84cdfbceb
--- lib/privsep.c
+++ lib/privsep.c
}
const struct got_error *
+got_privsep_send_fetch_symrefs(struct imsgbuf *ibuf,
+ struct got_pathlist_head *symrefs)
+{
+ const struct got_error *err = NULL;
+ struct ibuf *wbuf;
+ size_t len, nsymrefs = 0;
+ struct got_pathlist_entry *pe;
+
+ len = sizeof(struct got_imsg_fetch_symrefs);
+ TAILQ_FOREACH(pe, symrefs, entry) {
+ const char *target = pe->data;
+ len += sizeof(struct got_imsg_fetch_symref) +
+ pe->path_len + strlen(target);
+ nsymrefs++;
+ }
+
+ if (len >= MAX_IMSGSIZE - IMSG_HEADER_SIZE)
+ return got_error(GOT_ERR_NO_SPACE);
+
+ wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_SYMREFS, 0, 0, len);
+ if (wbuf == NULL)
+ return got_error_from_errno("imsg_create FETCH_SYMREFS");
+
+ /* Keep in sync with struct got_imsg_fetch_symrefs definition! */
+ if (imsg_add(wbuf, &nsymrefs, sizeof(nsymrefs)) == -1) {
+ err = got_error_from_errno("imsg_add FETCH_SYMREFS");
+ ibuf_free(wbuf);
+ return err;
+ }
+
+ TAILQ_FOREACH(pe, symrefs, entry) {
+ const char *name = pe->path;
+ size_t name_len = pe->path_len;
+ const char *target = pe->data;
+ size_t target_len = strlen(target);
+
+ /* Keep in sync with struct got_imsg_fetch_symref definition! */
+ if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1) {
+ err = got_error_from_errno("imsg_add FETCH_SYMREFS");
+ ibuf_free(wbuf);
+ return err;
+ }
+ if (imsg_add(wbuf, &target_len, sizeof(target_len)) == -1) {
+ err = got_error_from_errno("imsg_add FETCH_SYMREFS");
+ ibuf_free(wbuf);
+ return err;
+ }
+ if (imsg_add(wbuf, name, name_len) == -1) {
+ err = got_error_from_errno("imsg_add FETCH_SYMREFS");
+ ibuf_free(wbuf);
+ return err;
+ }
+ if (imsg_add(wbuf, target, target_len) == -1) {
+ err = got_error_from_errno("imsg_add FETCH_SYMREFS");
+ ibuf_free(wbuf);
+ return err;
+ }
+ }
+
+ wbuf->fd = -1;
+ imsg_close(ibuf, wbuf);
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
got_privsep_send_fetch_progress(struct imsgbuf *ibuf,
struct got_object_id *refid, const char *refname)
{
const struct got_error *
got_privsep_recv_fetch_progress(int *done, struct got_object_id **id,
- char **refname, struct imsgbuf *ibuf)
+ char **refname, struct got_pathlist_head *symrefs, struct imsgbuf *ibuf)
{
const struct got_error *err = NULL;
struct imsg imsg;
size_t datalen;
const size_t min_datalen =
- MIN(sizeof(struct got_imsg_error),
- sizeof(struct got_imsg_fetch_progress));
+ MIN(MIN(sizeof(struct got_imsg_error),
+ sizeof(struct got_imsg_fetch_progress)),
+ sizeof(struct got_imsg_fetch_symrefs));
+ struct got_imsg_fetch_symrefs *isymrefs = NULL;
+ size_t n, remain;
+ off_t off;
*done = 0;
*id = NULL;
case GOT_IMSG_ERROR:
err = recv_imsg_error(&imsg, datalen);
break;
+ case GOT_IMSG_FETCH_SYMREFS:
+ if (datalen < sizeof(*isymrefs)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ break;
+ }
+ if (isymrefs != NULL) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+ isymrefs = (struct got_imsg_fetch_symrefs *)imsg.data;
+ off = sizeof(*isymrefs);
+ remain = datalen - off;
+ for (n = 0; n < isymrefs->nsymrefs; n++) {
+ struct got_imsg_fetch_symref *s;
+ char *name, *target;
+ if (remain < sizeof(struct got_imsg_fetch_symref)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ s = (struct got_imsg_fetch_symref *)(imsg.data + off);
+ off += sizeof(*s);
+ remain -= sizeof(*s);
+ if (remain < s->name_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ name = strndup(imsg.data + off, s->name_len);
+ if (name == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ off += s->name_len;
+ remain -= s->name_len;
+ if (remain < s->target_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ free(name);
+ goto done;
+ }
+ target = strndup(imsg.data + off, s->target_len);
+ if (target == NULL) {
+ err = got_error_from_errno("strndup");
+ free(name);
+ goto done;
+ }
+ off += s->target_len;
+ remain -= s->target_len;
+ err = got_pathlist_append(symrefs, name, target);
+ if (err) {
+ free(name);
+ free(target);
+ goto done;
+ }
+ }
+ break;
case GOT_IMSG_FETCH_PROGRESS:
*id = malloc(sizeof(**id));
if (*id == NULL) {
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
-
+done:
if (err) {
free(*id);
*id = NULL;
blob - 4fb64788f5a648f7f34e87ff0205d269d68c990d
blob + 7340b1a9a9076ae86fed9a6e1276134ce7d005b7
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
#include "got_error.h"
#include "got_object.h"
+#include "got_path.h"
#include "got_version.h"
#include "got_lib_sha1.h"
}
static const struct got_error *
-match_capabilities(char **my_capabilities, char *server_capabilities)
+add_symref(struct got_pathlist_head *symrefs, const char *capa)
{
const struct got_error *err = NULL;
- char *capa;
+ char *colon, *name = NULL, *target = NULL;
+
+ /* Need at least "A:B" */
+ if (strlen(capa) < 3)
+ return NULL;
+
+ colon = strchr(capa, ':');
+ if (colon == NULL)
+ return NULL;
+
+ *colon = '\0';
+ name = strdup(capa);
+ if (name == NULL)
+ return got_error_from_errno("strdup");
+
+ target = strdup(colon + 1);
+ if (target == NULL) {
+ err = got_error_from_errno("strdup");
+ goto done;
+ }
+
+ /* We can't validate the ref itself here. The main process will. */
+ err = got_pathlist_append(symrefs, name, target);
+done:
+ if (err) {
+ free(name);
+ free(target);
+ }
+ return err;
+}
+
+static const struct got_error *
+match_capabilities(char **my_capabilities, struct got_pathlist_head *symrefs,
+ char *server_capabilities)
+{
+ const struct got_error *err = NULL;
+ char *capa, *equalsign;
int i;
*my_capabilities = NULL;
if (capa == NULL)
return NULL;
+ equalsign = strchr(capa, '=');
+ if (equalsign != NULL &&
+ strncmp(capa, "symref", equalsign - capa) == 0) {
+ err = add_symref(symrefs, equalsign + 1);
+ if (err)
+ break;
+ continue;
+ }
+
for (i = 0; i < nitems(got_capabilities); i++) {
err = match_capability(my_capabilities,
capa, &got_capabilities[i]);
return err;
}
-
+
static const struct got_error *
fetch_pack(int fd, int packfd, struct got_object_id *packid,
struct imsgbuf *ibuf)
int i, n, req;
off_t packsz;
char *my_capabilities = NULL;
+ struct got_pathlist_head symrefs;
+ struct got_pathlist_entry *pe;
+ TAILQ_INIT(&symrefs);
+
have = malloc(refsz * sizeof(have[0]));
if (have == NULL)
return got_error_from_errno("malloc");
if (chattygit && sp[2][0] != '\0')
fprintf(stderr, "server capabilities: %s\n", sp[2]);
if (is_firstpkt) {
- err = match_capabilities(&my_capabilities, sp[2]);
+ err = match_capabilities(&my_capabilities, &symrefs,
+ sp[2]);
if (err)
goto done;
if (chattygit && my_capabilities)
fprintf(stderr, "my matched capabilities: %s\n",
my_capabilities);
+ err = got_privsep_send_fetch_symrefs(ibuf, &symrefs);
+ if (err)
+ goto done;
}
is_firstpkt = 0;
if (strstr(sp[1], "^{}"))
if (got_check_pack_hash(packfd, packsz, packid->sha1) == -1)
err = got_error(GOT_ERR_BAD_PACKFILE);
done:
+ TAILQ_FOREACH(pe, &symrefs, entry) {
+ free((void *)pe->path);
+ free(pe->data);
+ }
+ got_pathlist_free(&symrefs);
free(have);
free(want);
return err;