)
-SET(SOURCES procd.c signal.c state.c inittab.c rcS.c ubus.c system.c
+SET(SOURCES procd.c signal.c state.c inittab.c rcS.c ubus.c system.c sysupgrade.c
service/service.c service/instance.c service/validate.c service/trigger.c service/watch.c
utils/utils.c)
IF(NOT DISABLE_INIT)
IF(DISABLE_INIT)
ADD_DEFINITIONS(-DDISABLE_INIT)
ELSE()
-ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c watchdog.c
+ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c sysupgrade.c watchdog.c
utils/utils.c ${SOURCES_ZRAM})
TARGET_LINK_LIBRARIES(init ${LIBS})
INSTALL(TARGETS init
#include "init.h"
#include "../watchdog.h"
+#include "../sysupgrade.h"
static struct uloop_process preinit_proc;
static struct uloop_process plugd_proc;
debug = lvl;
}
+static void
+check_sysupgrade(void)
+{
+ char *prefix = NULL, *path = NULL, *command = NULL;
+ size_t n;
+
+ if (chdir("/"))
+ return;
+
+ FILE *sysupgrade = fopen("/tmp/sysupgrade", "r");
+ if (!sysupgrade)
+ return;
+
+ n = 0;
+ if (getdelim(&prefix, &n, 0, sysupgrade) < 0)
+ goto fail;
+ n = 0;
+ if (getdelim(&path, &n, 0, sysupgrade) < 0)
+ goto fail;
+ n = 0;
+ if (getdelim(&command, &n, 0, sysupgrade) < 0)
+ goto fail;
+
+ fclose(sysupgrade);
+
+ sysupgrade_exec_upgraded(prefix, path, command);
+
+ while (true)
+ sleep(1);
+
+fail:
+ fclose(sysupgrade);
+ free(prefix);
+ free(path);
+ free(command);
+}
+
static void
spawn_procd(struct uloop_process *proc, int ret)
{
char *wdt_fd = watchdog_fd();
char *argv[] = { "/sbin/procd", NULL};
- struct stat s;
char dbg[2];
if (plugd_proc.pid > 0)
kill(plugd_proc.pid, SIGKILL);
- if (!stat("/tmp/sysupgrade", &s))
- while (true)
- sleep(1);
-
unsetenv("INITRAMFS");
unsetenv("PREINIT");
unlink("/tmp/.preinit");
+
+ check_sysupgrade();
+
DEBUG(2, "Exec to real procd now\n");
if (wdt_fd)
setenv("WDTFD", wdt_fd, 1);
#include <libubox/uloop.h>
#include "procd.h"
+#include "sysupgrade.h"
#include "watchdog.h"
static struct blob_buf b;
[SYSUPGRADE_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_STRING },
};
-static void
-procd_exec_upgraded(const char *prefix, char *path, char *command)
-{
- char *wdt_fd = watchdog_fd();
- char *argv[] = { "/sbin/upgraded", NULL, NULL, NULL};
-
- if (chroot(prefix)) {
- fprintf(stderr, "Failed to chroot for upgraded exec.\n");
- return;
- }
-
- argv[1] = path;
- argv[2] = command;
-
- DEBUG(2, "Exec to upgraded now\n");
- if (wdt_fd) {
- watchdog_set_cloexec(false);
- setenv("WDTFD", wdt_fd, 1);
- }
- execvp(argv[0], argv);
-
- /* Cleanup on failure */
- fprintf(stderr, "Failed to exec upgraded.\n");
- unsetenv("WDTFD");
- watchdog_set_cloexec(true);
- chroot(".");
-}
-
static int sysupgrade(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
if (!tb[SYSUPGRADE_PATH] || !tb[SYSUPGRADE_PREFIX])
return UBUS_STATUS_INVALID_ARGUMENT;
- procd_exec_upgraded(blobmsg_get_string(tb[SYSUPGRADE_PREFIX]),
- blobmsg_get_string(tb[SYSUPGRADE_PATH]),
- tb[SYSUPGRADE_COMMAND] ? blobmsg_get_string(tb[SYSUPGRADE_COMMAND]) : NULL);
+ sysupgrade_exec_upgraded(blobmsg_get_string(tb[SYSUPGRADE_PREFIX]),
+ blobmsg_get_string(tb[SYSUPGRADE_PATH]),
+ tb[SYSUPGRADE_COMMAND] ? blobmsg_get_string(tb[SYSUPGRADE_COMMAND]) : NULL);
return 0;
}
--- /dev/null
+/*
+ * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include "watchdog.h"
+#include "sysupgrade.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command)
+{
+ char *wdt_fd = watchdog_fd();
+ char *argv[] = { "/sbin/upgraded", NULL, NULL, NULL};
+
+ if (chroot(prefix)) {
+ fprintf(stderr, "Failed to chroot for upgraded exec.\n");
+ return;
+ }
+
+ argv[1] = path;
+ argv[2] = command;
+
+ if (wdt_fd) {
+ watchdog_set_cloexec(false);
+ setenv("WDTFD", wdt_fd, 1);
+ }
+ execvp(argv[0], argv);
+
+ /* Cleanup on failure */
+ fprintf(stderr, "Failed to exec upgraded.\n");
+ unsetenv("WDTFD");
+ watchdog_set_cloexec(true);
+ chroot(".");
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PROCD_SYSUPGRADE_H
+#define __PROCD_SYSUPGRADE_H
+
+
+void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command);
+
+
+#endif
#ifndef __PROCD_WATCHDOG_H
#define __PROCD_WATCHDOG_H
+#include <stdbool.h>
+
#ifndef DISABLE_INIT
void watchdog_init(int preinit);
char* watchdog_fd(void);