#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include "../../include/pathrs.h"
#define bail(fmt, ...) \
do { fprintf(stderr, fmt "\n", #__VA_ARGS__); exit(1); } while (0)
void print_error(pathrs_error_t *error)
{
int saved_errno = error->saved_errno;
if (saved_errno)
printf("ERROR[%s]: %s\n", strerror(saved_errno), error->description);
else
printf("ERROR: %s\n", error->description);
errno = saved_errno;
}
int open_in_root(const char *root_path, const char *unsafe_path)
{
int liberr = 0;
int rootfd = -EBADF, fd = -EBADF;
rootfd = pathrs_open_root(root_path);
if (IS_PATHRS_ERR(rootfd)) {
liberr = rootfd;
goto err;
}
fd = pathrs_inroot_open(rootfd, unsafe_path, O_RDONLY);
if (IS_PATHRS_ERR(fd)) {
liberr = fd;
goto err;
}
err:
close(rootfd);
if (IS_PATHRS_ERR(liberr)) {
pathrs_error_t *error = pathrs_errorinfo(liberr);
print_error(error);
pathrs_errorinfo_free(error);
}
return fd;
}
void usage(void) {
printf("usage: cat <root> <unsafe-path>\n");
exit(1);
}
int main(int argc, char **argv)
{
int fd;
char *root, *path;
if (argc != 3)
usage();
root = argv[1];
path = argv[2];
fd = open_in_root(root, path);
if (fd < 0)
bail("open_in_root failed: %m");
for (;;) {
ssize_t copied, written;
char buffer[1024];
copied = read(fd, buffer, sizeof(buffer));
if (copied < 0)
bail("read failed: %m");
else if (copied == 0)
break;
written = write(STDOUT_FILENO, buffer, copied);
if (written < 0)
bail("write failed: %m");
if (written != copied)
bail("write was short (read %dB, wrote %dB)", copied, written);
}
close(fd);
return 0;
}