X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=os-posix.c;h=c6ddb7d830198929d2805d74b64336fae12def08;hb=d81db0becaeca093a55f3dba110c55528ad5c3bc;hp=5c437ca12ca1b66cb515cbebd770a201ae2e91ed;hpb=f3c6a169a39d188e98c17a0a0ebfa7f85e5aafdd;p=mirror_qemu.git diff --git a/os-posix.c b/os-posix.c index 5c437ca12c..c6ddb7d830 100644 --- a/os-posix.c +++ b/os-posix.c @@ -23,22 +23,21 @@ * THE SOFTWARE. */ -#include -#include -#include -#include +#include "qemu/osdep.h" #include /*needed for MAP_POPULATE before including qemu-options.h */ -#include #include #include #include /* Needed early for CONFIG_BSD etc. */ -#include "config-host.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "net/slirp.h" #include "qemu-options.h" +#include "qemu/rcu.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/cutils.h" #ifdef CONFIG_LINUX #include @@ -47,7 +46,7 @@ static struct passwd *user_pwd; static const char *chroot_dir; static int daemonize; -static int fds[2]; +static int daemon_pipe; void os_setup_early_signal_handling(void) { @@ -80,46 +79,17 @@ void os_setup_signal_handling(void) running from the build tree this will be "$bindir/../pc-bios". */ #define SHARE_SUFFIX "/share/qemu" #define BUILD_SUFFIX "/pc-bios" -char *os_find_datadir(const char *argv0) +char *os_find_datadir(void) { - char *dir; - char *p = NULL; + char *dir, *exec_dir; char *res; - char buf[PATH_MAX]; size_t max_len; -#if defined(__linux__) - { - int len; - len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); - if (len > 0) { - buf[len] = 0; - p = buf; - } - } -#elif defined(__FreeBSD__) - { - static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; - size_t len = sizeof(buf) - 1; - - *buf = '\0'; - if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) && - *buf) { - buf[sizeof(buf) - 1] = '\0'; - p = buf; - } - } -#endif - /* If we don't have any way of figuring out the actual executable - location then try argv[0]. */ - if (!p) { - p = realpath(argv0, buf); - if (!p) { - return NULL; - } + exec_dir = qemu_get_exec_dir(); + if (exec_dir == NULL) { + return NULL; } - dir = dirname(p); - dir = dirname(dir); + dir = g_path_get_dirname(exec_dir); max_len = strlen(dir) + MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1; @@ -133,6 +103,8 @@ char *os_find_datadir(const char *argv0) } } + g_free(dir); + g_free(exec_dir); return res; } #undef SHARE_SUFFIX @@ -144,8 +116,7 @@ void os_set_proc_name(const char *s) char name[16]; if (!s) return; - name[sizeof(name) - 1] = 0; - strncpy(name, s, sizeof(name)); + pstrcpy(name, sizeof(name), s); /* Could rewrite argv[0] too, but that's a bit more complicated. This simple way is enough for `top'. */ if (prctl(PR_SET_NAME, name)) { @@ -167,6 +138,8 @@ void os_parse_cmd_args(int index, const char *optarg) switch (index) { #ifdef CONFIG_SLIRP case QEMU_OPTION_smb: + error_report("The -smb option is deprecated. " + "Please use '-netdev user,smb=...' instead."); if (net_slirp_smb(optarg) < 0) exit(1); break; @@ -184,8 +157,12 @@ void os_parse_cmd_args(int index, const char *optarg) case QEMU_OPTION_daemonize: daemonize = 1; break; +#if defined(CONFIG_LINUX) + case QEMU_OPTION_enablefips: + fips_set_state(true); + break; +#endif } - return; } static void change_process_uid(void) @@ -229,49 +206,50 @@ static void change_root(void) void os_daemonize(void) { if (daemonize) { - pid_t pid; - - if (pipe(fds) == -1) - exit(1); - - pid = fork(); - if (pid > 0) { - uint8_t status; - ssize_t len; - - close(fds[1]); - - again: - len = read(fds[0], &status, 1); - if (len == -1 && (errno == EINTR)) - goto again; - - if (len != 1) - exit(1); - else if (status == 1) { - fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno)); - exit(1); - } else - exit(0); - } else if (pid < 0) + pid_t pid; + int fds[2]; + + if (pipe(fds) == -1) { exit(1); + } - close(fds[0]); - qemu_set_cloexec(fds[1]); + pid = fork(); + if (pid > 0) { + uint8_t status; + ssize_t len; - setsid(); + close(fds[1]); - pid = fork(); - if (pid > 0) - exit(0); - else if (pid < 0) - exit(1); + do { + len = read(fds[0], &status, 1); + } while (len < 0 && errno == EINTR); - umask(027); + /* only exit successfully if our child actually wrote + * a one-byte zero to our pipe, upon successful init */ + exit(len == 1 && status == 0 ? 0 : 1); + + } else if (pid < 0) { + exit(1); + } + + close(fds[0]); + daemon_pipe = fds[1]; + qemu_set_cloexec(daemon_pipe); + + setsid(); + + pid = fork(); + if (pid > 0) { + exit(0); + } else if (pid < 0) { + exit(1); + } + umask(027); signal(SIGTSTP, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); + rcu_after_fork(); } } @@ -280,47 +258,39 @@ void os_setup_post(void) int fd = 0; if (daemonize) { - uint8_t status = 0; - ssize_t len; - - again1: - len = write(fds[1], &status, 1); - if (len == -1 && (errno == EINTR)) - goto again1; - - if (len != 1) - exit(1); - if (chdir("/")) { perror("not able to chdir to /"); exit(1); } - TFR(fd = qemu_open("/dev/null", O_RDWR)); - if (fd == -1) - exit(1); + TFR(fd = qemu_open("/dev/null", O_RDWR)); + if (fd == -1) { + exit(1); + } } change_root(); change_process_uid(); if (daemonize) { + uint8_t status = 0; + ssize_t len; + dup2(fd, 0); dup2(fd, 1); - dup2(fd, 2); + /* In case -D is given do not redirect stderr to /dev/null */ + if (!qemu_logfile) { + dup2(fd, 2); + } close(fd); - } -} -void os_pidfile_error(void) -{ - if (daemonize) { - uint8_t status = 1; - if (write(fds[1], &status, 1) != 1) { - perror("daemonize. Writing to pipe\n"); + do { + len = write(daemon_pipe, &status, 1); + } while (len < 0 && errno == EINTR); + if (len != 1) { + exit(1); } - } else - fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno)); + } } void os_set_line_buffering(void) @@ -348,6 +318,23 @@ int qemu_create_pidfile(const char *filename) return -1; } - close(fd); + /* keep pidfile open & locked forever */ return 0; } + +bool is_daemonized(void) +{ + return daemonize; +} + +int os_mlock(void) +{ + int ret = 0; + + ret = mlockall(MCL_CURRENT | MCL_FUTURE); + if (ret < 0) { + perror("mlockall"); + } + + return ret; +}