#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);
if (error->backtrace) {
printf("Rust Backtrace:\n");
for (int i = 0; i < error->backtrace->length; i++) {
const __pathrs_backtrace_entry_t *entry = &error->backtrace->head[i];
if (entry->symbol_name)
printf("'%s'@", entry->symbol_name);
printf("<0x%x>+0x%x\n", entry->symbol_address, entry->ip - entry->symbol_address);
if (entry->symbol_file)
printf(" in file '%s':%d\n", entry->symbol_file, entry->symbol_lineno);
}
}
errno = saved_errno;
}
int open_in_root(const char *root_path, const char *unsafe_path)
{
int fd = -1;
pathrs_root_t *root = NULL;
pathrs_handle_t *handle = NULL;
pathrs_error_t *error = NULL;
root = pathrs_open(root_path);
error = pathrs_error(PATHRS_ROOT, root);
if (error)
goto err;
handle = pathrs_resolve(root, unsafe_path);
error = pathrs_error(PATHRS_ROOT, root);
if (error)
goto err;
fd = pathrs_reopen(handle, O_RDONLY);
error = pathrs_error(PATHRS_HANDLE, handle);
if (error)
goto err;
err:
if (error)
print_error(error);
out:
pathrs_free(PATHRS_ROOT, root);
pathrs_free(PATHRS_HANDLE, handle);
pathrs_free(PATHRS_ERROR, 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;
}