summaryrefslogtreecommitdiffstats
path: root/arch/sandbox/os/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sandbox/os/common.c')
-rw-r--r--arch/sandbox/os/common.c138
1 files changed, 88 insertions, 50 deletions
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index 4eb6d37fff..3446074f99 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -40,7 +40,6 @@
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <sys/time.h>
-#include <signal.h>
/*
* ...except the ones needed to connect with barebox
*/
@@ -76,6 +75,15 @@ static void cookmode(void)
tcsetattr(0, TCSANOW, &term_orig);
}
+static char *stickypage_path;
+
+static void prepare_exit(void)
+{
+ cookmode();
+ if (stickypage_path)
+ remove(stickypage_path);
+}
+
int linux_tstc(int fd)
{
struct timeval tv = {
@@ -123,13 +131,27 @@ uint64_t linux_get_time(void)
void __attribute__((noreturn)) linux_exit(void)
{
- cookmode();
+ prepare_exit();
exit(0);
}
-static size_t saved_argv_len;
static char **saved_argv;
+static int selfpath(char *buf, size_t len)
+{
+ int ret;
+
+ /* we must follow the symlink, so we can exec an updated executable */
+ ret = readlink("/proc/self/exe", buf, len - 1);
+ if (ret < 0)
+ return ret;
+
+ if (0 < ret && ret < len - 1)
+ buf[ret] = '\0';
+
+ return ret;
+}
+
void linux_reexec(void)
{
char buf[4097];
@@ -138,9 +160,8 @@ void linux_reexec(void)
cookmode();
/* we must follow the symlink, so we can exec an updated executable */
- ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
- if (0 < ret && ret < sizeof(buf) - 1) {
- buf[ret] = '\0';
+ ret = selfpath(buf, sizeof(buf));
+ if (ret > 0) {
execv(buf, saved_argv);
if (!strcmp(&buf[ret - DELETED_OFFSET], " (deleted)")) {
printf("barebox image on disk changed. Loading new.\n");
@@ -155,7 +176,7 @@ void linux_reexec(void)
void linux_hang(void)
{
- cookmode();
+ prepare_exit();
/* falls through to generic hang() */
}
@@ -317,55 +338,76 @@ static int add_image(const char *_str, char *devname_template, int *devname_numb
return ret;
}
-int linux_open_hostfile(struct hf_info *hf)
+extern uint8_t stickypage[4096];
+
+char *linux_get_stickypage_path(void)
{
- char *buf = NULL;
- struct stat s;
- int fd = -1;
+ size_t nwritten;
+ ssize_t ret;
+ int fd;
- printf("add %s %sbacked by file %s%s\n", hf->devname,
- hf->filename ? "" : "initially un", hf->filename ?: "",
- hf->is_readonly ? "(ro)" : "");
+ ret = asprintf(&stickypage_path, "%s/barebox/stickypage.%lu",
+ getenv("XDG_RUNTIME_DIR") ?: "/run", (long)getpid());
+ if (ret < 0)
+ goto err_asprintf;
- if (hf->filename) {
- fd = hf->fd = open(hf->filename, (hf->is_readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC);
- } else {
- char *filename;
- int ret;
+ ret = mkdir(dirname(stickypage_path), 0755);
+ if (ret < 0 && errno != EEXIST) {
+ perror("mkdir");
+ goto err_creat;
+ }
+
+ stickypage_path[strlen(stickypage_path)] = '/';
+
+ fd = open(stickypage_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644);
+ if (fd < 0) {
+ if (errno == EEXIST)
+ return stickypage_path;
+
+ perror("open");
+ goto err_creat;
+ }
- ret = asprintf(&buf, "--image=%s=/tmp/barebox-hostfileXXXXXX", hf->devname);
+ for (nwritten = 0; nwritten < sizeof(stickypage); ) {
+ ret = write(fd, &stickypage[nwritten], sizeof(stickypage) - nwritten);
if (ret < 0) {
- perror("asprintf");
- goto err_out;
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ perror("write");
+ goto err_write;
}
- filename = buf + strlen("--image==") + strlen(hf->devname);
+ nwritten += ret;
+ }
- fd = hf->fd = mkstemp(filename);
- if (fd >= 0) {
- ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
- if (ret < 0) {
- perror("fcntl");
- goto err_out;
- }
+ close(fd);
- ret = ftruncate(fd, hf->size);
- if (ret < 0) {
- perror("ftruncate");
- goto err_out;
- }
+ return stickypage_path;
- hf->filename = filename;
+err_write:
+ close(fd);
+err_creat:
+ free(stickypage_path);
+err_asprintf:
+ stickypage_path = NULL;
- saved_argv = realloc(saved_argv,
- ++saved_argv_len * sizeof(*saved_argv));
- if (!saved_argv)
- exit(1);
- saved_argv[saved_argv_len - 2] = buf;
- saved_argv[saved_argv_len - 1] = NULL;
- }
- }
+ return NULL;
+}
+
+int linux_open_hostfile(struct hf_info *hf)
+{
+ char *buf = NULL;
+ struct stat s;
+ int fd = -1;
+ printf("add %s %sbacked by file %s%s\n", hf->devname,
+ hf->filename ? "" : "initially un", hf->filename ?: "",
+ hf->is_readonly ? "(ro)" : "");
+
+ if (!hf->filename)
+ return -ENOENT;
+
+ fd = hf->fd = open(hf->filename, (hf->is_readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC);
if (fd < 0) {
perror("open");
goto err_out;
@@ -477,7 +519,7 @@ int main(int argc, char *argv[])
char *aux;
#ifdef CONFIG_ASAN
- __sanitizer_set_death_callback(cookmode);
+ __sanitizer_set_death_callback(prepare_exit);
#endif
while (1) {
@@ -517,11 +559,7 @@ int main(int argc, char *argv[])
}
}
- saved_argv_len = argc + 1;
- saved_argv = calloc(saved_argv_len, sizeof(*saved_argv));
- if (!saved_argv)
- exit(1);
- memcpy(saved_argv, argv, saved_argv_len * sizeof(*saved_argv));
+ saved_argv = argv;
ram = malloc(malloc_size);
if (!ram) {