diff options
author | David 'Digit' Turner <digit@android.com> | 2011-06-01 17:23:23 +0200 |
---|---|---|
committer | David 'Digit' Turner <digit@android.com> | 2011-06-01 17:24:00 +0200 |
commit | 2e5feede9978fadb969c8cfa82b761a8446bf012 (patch) | |
tree | e9dbb51e71a14aa9118f8e9c980d4722abb04fd8 /os-posix.c | |
parent | a45e3e024836d7fbfb34d0b62f962a706d1b05fd (diff) | |
parent | 406a59bd0a2e7a38cd840a5c08602e3a36bd2df8 (diff) | |
download | external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.zip external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.tar.gz external_qemu-2e5feede9978fadb969c8cfa82b761a8446bf012.tar.bz2 |
upstream integration
This patch is a merge of a series of 42 upstream integration patches
into the emulator's master branch.
The individual patches come from the 'upstream-integrate'
branch that was uploaded separately on kernel.org.
The reference upstream sources used for this integration come
from http://meego.gitorious.org/qemu-maemo/qemu using the following
hash:
7243fbd089cce3c06ca24ed173a251f32644863c
In a nutshell, the goal is to make our source tree closer to upstream
in order to use various improvement there. Unfortunately, we're not to
the point where we can use the upstream ARMv7-A / NEON translator,
though we're getting close.
Major changes are:
- integrate upstream TCG and softfloat
- target-arm: Move most Android-specific helper functions to helper-android.c
and translate-android.h. This is in preparation of a _major_ integration
of the upstream ARM translator.
- moving various functions to different files (e.g. cpus.c,
qemu-os-posix.c, qemu-os-win32.c, arch_init.c, etc)
- qemu-char-android.c is now gone. We're using qemu-char.c
with slight modifications embedded within CONFIG_ANDROID-guarded
ifdef blocks.
- rename "trace.h" to "android-trace.h". We still need to keep
"trace.h" and "trace_common.h" until we also update
sdk/emulator/tools/qtools/ to use the new header names.
After this, we will integrate in a future integration
the auto-generated trace.h used by upstream.
- remove the OutputChannel hack. Instead, implement a "fake Monitor"
object that can be used with any function that takes a Monitor as
input. The fake Monitor is used to collect output into a dynamic
buffer (e.g. during snapshot save/load).
- convert to upstream QEMUTimer API changes.
- implement physical memory with RAMBlock lists (instead of a single array).
Short log of individual changes:
406a59b trace.h: rename to trace-android.h
288208c target-arm/translate.c: move Android-specific stuff out.
f1d9bf1 tcg: integrate upstream version
280afa0 ramblocks: integrate upstream implementation (sophisticated)
ae3098a vl-android.c: move arch-specific functions to arch_init.c
23ca2ae vl-android.c: move cpu functions to cpus.c
c1ac40a vl-android.c: use os-specific setup routines
e49c3f3 compatfd.c: minor integrate
4276038 cpu-exec.c: minor integrate
3b2846a qemu-char-android.c: rename to qemu-char.c
f645f7d cpu_restore_state: remove un-necessary argument.
f0753ac qjson.c: minor integrate
8354d2d vl-android.c: Move code to iohandler.c
d3d4468 translate-all.c: minor integrate
1f9ec0f qemu-config.c: minor integrate
d09775c monitor.c: minor integrate
9f64011 disas.c: minor integrate
69ed952 device_tree.c: minor integrate
e1c0948 bswap.h + others: minor integrate
6b9236d buffered_file.c: minor integrate
95a83ce savevm: Remove OutputBuffer hack.
986acc9 savevm.c: minor integrate
39373b1 arm-semi.c: minor integrate
fb955c7 README: minor integrate
8ee4e5e trace: simplify code and avoid conflicts
65d1521 acl.c: minor integrate
c98cf7b arm-dis.c: minor integrate
bfec547 fpu: upstream integrate
9bfb3d5 json-lexer.c, json-parser.c: minor integrate
6eaacfb trace.h: minor C compatibility fixes.
17410ee qemu-char.h, console.h: upstream integration
5973c77 qemu-timer.c: rename qemu_timer_new_scale()
317c9d5 qemu-timer.c: upstream integrate
47dc1f4 qerror: minor integrate
488bfd5 qemu-error: minor integrate
1646b4e posix-aio-compat.c: minor integrate
088edf8 os-posix.c + os-win32.c and dependencies
795bb19 qemu-common.h: other intergrates
45c3be0 integrate: qemu-common.h changes
Change-Id: If5771dd4b030c602b99845d7489d1f55406bf159
Diffstat (limited to 'os-posix.c')
-rw-r--r-- | os-posix.c | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/os-posix.c b/os-posix.c new file mode 100644 index 0000000..324bf13 --- /dev/null +++ b/os-posix.c @@ -0,0 +1,398 @@ +/* + * os-posix.c + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2010 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> +/*needed for MAP_POPULATE before including qemu-options.h */ +#include <sys/mman.h> +#include <pwd.h> +#include <libgen.h> + +/* Needed early for CONFIG_BSD etc. */ +#include "config-host.h" +#include "sysemu.h" +#include "net.h" +#include "qemu-options.h" + +#ifdef CONFIG_LINUX +#include <sys/prctl.h> +#include <sys/syscall.h> +#endif + +#ifdef CONFIG_EVENTFD +#include <sys/eventfd.h> +#endif + +static struct passwd *user_pwd; +static const char *chroot_dir; +static int daemonize; +static int fds[2]; + +void os_setup_early_signal_handling(void) +{ + struct sigaction act; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); +} + +static void termsig_handler(int signal) +{ + qemu_system_shutdown_request(); +} + +static void sigchld_handler(int signal) +{ + waitpid(-1, NULL, WNOHANG); +} + +void os_setup_signal_handling(void) +{ + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler = termsig_handler; + sigaction(SIGINT, &act, NULL); + sigaction(SIGHUP, &act, NULL); + sigaction(SIGTERM, &act, NULL); + + act.sa_handler = sigchld_handler; + act.sa_flags = SA_NOCLDSTOP; + sigaction(SIGCHLD, &act, NULL); +} + +/* Find a likely location for support files using the location of the binary. + For installed binaries this will be "$bindir/../share/qemu". When + 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 *dir; + char *p = NULL; + 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; + } + } + dir = dirname(p); + dir = dirname(dir); + + max_len = strlen(dir) + + MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1; + res = qemu_mallocz(max_len); + snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX); + if (access(res, R_OK)) { + snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX); + if (access(res, R_OK)) { + qemu_free(res); + res = NULL; + } + } + + return res; +} +#undef SHARE_SUFFIX +#undef BUILD_SUFFIX + +void os_set_proc_name(const char *s) +{ +#if defined(PR_SET_NAME) + char name[16]; + if (!s) + return; + name[sizeof(name) - 1] = 0; + strncpy(name, s, sizeof(name)); + /* 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)) { + perror("unable to change process name"); + exit(1); + } +#else + fprintf(stderr, "Change of process name not supported by your OS\n"); + exit(1); +#endif +} + +/* + * Parse OS specific command line options. + * return 0 if option handled, -1 otherwise + */ +void os_parse_cmd_args(int index, const char *optarg) +{ + switch (index) { +#ifdef CONFIG_SLIRP + case QEMU_OPTION_smb: +#if 1 + net_slirp_smb(optarg); +#else + if (net_slirp_smb(optarg) < 0) + exit(1); +#endif + break; +#endif + case QEMU_OPTION_runas: + user_pwd = getpwnam(optarg); + if (!user_pwd) { + fprintf(stderr, "User \"%s\" doesn't exist\n", optarg); + exit(1); + } + break; + case QEMU_OPTION_chroot: + chroot_dir = optarg; + break; + case QEMU_OPTION_daemonize: + daemonize = 1; + break; + } + return; +} + +static void change_process_uid(void) +{ + if (user_pwd) { + if (setgid(user_pwd->pw_gid) < 0) { + fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid); + exit(1); + } + if (setuid(user_pwd->pw_uid) < 0) { + fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid); + exit(1); + } + if (setuid(0) != -1) { + fprintf(stderr, "Dropping privileges failed\n"); + exit(1); + } + } +} + +static void change_root(void) +{ + if (chroot_dir) { + if (chroot(chroot_dir) < 0) { + fprintf(stderr, "chroot failed\n"); + exit(1); + } + if (chdir("/")) { + perror("not able to chdir to /"); + exit(1); + } + } + +} + +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) + exit(1); + + close(fds[0]); + qemu_set_cloexec(fds[1]); + + 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); + } +} + +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); + } + + change_root(); + change_process_uid(); + + if (daemonize) { + dup2(fd, 0); + dup2(fd, 1); + 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"); + } + } else + fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno)); +} + +void os_set_line_buffering(void) +{ + setvbuf(stdout, NULL, _IOLBF, 0); +} + +/* + * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set. + */ +int qemu_eventfd(int fds[2]) +{ +#ifdef CONFIG_EVENTFD + int ret; + + ret = eventfd(0, 0); + if (ret >= 0) { + fds[0] = ret; + qemu_set_cloexec(ret); + if ((fds[1] = dup(ret)) == -1) { + close(ret); + return -1; + } + qemu_set_cloexec(fds[1]); + return 0; + } + + if (errno != ENOSYS) { + return -1; + } +#endif + + return qemu_pipe(fds); +} + +int qemu_create_pidfile(const char *filename) +{ + char buffer[128]; + int len; + int fd; + + fd = qemu_open(filename, O_RDWR | O_CREAT, 0600); + if (fd == -1) { + return -1; + } + if (lockf(fd, F_TLOCK, 0) == -1) { + return -1; + } + len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid()); + if (write(fd, buffer, len) != len) { + return -1; + } + + return 0; +} + +int qemu_get_thread_id(void) +{ +#if defined (__linux__) + return syscall(SYS_gettid); +#else + return getpid(); +#endif +} |