#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
int
chngproc(int netsock, const char *root)
{
char *tok = NULL, *th = NULL, *fmt = NULL, **fs = NULL;
size_t i, fsz = 0;
int rc = 0, fd = -1, cc;
long lval;
enum chngop op;
void *pp;
if (unveil(root, "wc") == -1) {
warn("unveil %s", root);
goto out;
}
if (pledge("stdio cpath wpath", NULL) == -1) {
warn("pledge");
goto out;
}
for (;;) {
op = CHNG__MAX;
if ((lval = readop(netsock, COMM_CHNG_OP)) == 0)
op = CHNG_STOP;
else if (lval == CHNG_SYN)
op = lval;
if (op == CHNG__MAX) {
warnx("unknown operation from netproc");
goto out;
} else if (op == CHNG_STOP)
break;
assert(op == CHNG_SYN);
if ((th = readstr(netsock, COMM_THUMB)) == NULL)
goto out;
else if ((tok = readstr(netsock, COMM_TOK)) == NULL)
goto out;
else if (strlen(tok) < 1) {
warnx("token is too short");
goto out;
}
for (i = 0; tok[i]; ++i) {
int ch = (unsigned char)tok[i];
if (!isalnum(ch) && ch != '-' && ch != '_') {
warnx("token is not a valid base64url");
goto out;
}
}
if (asprintf(&fmt, "%s.%s", tok, th) == -1) {
warn("asprintf");
goto out;
}
pp = reallocarray(fs, (fsz + 1), sizeof(char *));
if (pp == NULL) {
warn("realloc");
goto out;
}
fs = pp;
if (asprintf(&fs[fsz], "%s/%s", root, tok) == -1) {
warn("asprintf");
goto out;
}
fsz++;
free(tok);
tok = NULL;
fd = open(fs[fsz - 1], O_WRONLY|O_CREAT|O_TRUNC, 0444);
if (fd == -1) {
warn("%s", fs[fsz - 1]);
goto out;
}
if (write(fd, fmt, strlen(fmt)) == -1) {
warn("%s", fs[fsz - 1]);
goto out;
}
if (close(fd) == -1) {
warn("%s", fs[fsz - 1]);
goto out;
}
fd = -1;
free(th);
free(fmt);
th = fmt = NULL;
dodbg("%s: created", fs[fsz - 1]);
cc = writeop(netsock, COMM_CHNG_ACK, CHNG_ACK);
if (cc == 0)
break;
if (cc < 0)
goto out;
}
rc = 1;
out:
close(netsock);
if (fd != -1)
close(fd);
for (i = 0; i < fsz; i++) {
if (unlink(fs[i]) == -1 && errno != ENOENT)
warn("%s", fs[i]);
free(fs[i]);
}
free(fs);
free(fmt);
free(th);
free(tok);
return rc;
}