diff options
Diffstat (limited to 'ANDROID_3.4.5/arch/um/os-Linux/umid.c')
-rw-r--r-- | ANDROID_3.4.5/arch/um/os-Linux/umid.c | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/ANDROID_3.4.5/arch/um/os-Linux/umid.c b/ANDROID_3.4.5/arch/um/os-Linux/umid.c deleted file mode 100644 index 4832eb51..00000000 --- a/ANDROID_3.4.5/arch/um/os-Linux/umid.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> -#include "init.h" -#include "os.h" - -#define UML_DIR "~/.uml/" - -#define UMID_LEN 64 - -/* Changed by set_umid, which is run early in boot */ -static char umid[UMID_LEN] = { 0 }; - -/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ -static char *uml_dir = UML_DIR; - -static int __init make_uml_dir(void) -{ - char dir[512] = { '\0' }; - int len, err; - - if (*uml_dir == '~') { - char *home = getenv("HOME"); - - err = -ENOENT; - if (home == NULL) { - printk(UM_KERN_ERR "make_uml_dir : no value in " - "environment for $HOME\n"); - goto err; - } - strlcpy(dir, home, sizeof(dir)); - uml_dir++; - } - strlcat(dir, uml_dir, sizeof(dir)); - len = strlen(dir); - if (len > 0 && dir[len - 1] != '/') - strlcat(dir, "/", sizeof(dir)); - - err = -ENOMEM; - uml_dir = malloc(strlen(dir) + 1); - if (uml_dir == NULL) { - printf("make_uml_dir : malloc failed, errno = %d\n", errno); - goto err; - } - strcpy(uml_dir, dir); - - if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) { - printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); - err = -errno; - goto err_free; - } - return 0; - -err_free: - free(uml_dir); -err: - uml_dir = NULL; - return err; -} - -/* - * Unlinks the files contained in @dir and then removes @dir. - * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We - * ignore ENOENT errors for anything (they happen, strangely enough - possibly - * due to races between multiple dying UML threads). - */ -static int remove_files_and_dir(char *dir) -{ - DIR *directory; - struct dirent *ent; - int len; - char file[256]; - int ret; - - directory = opendir(dir); - if (directory == NULL) { - if (errno != ENOENT) - return -errno; - else - return 0; - } - - while ((ent = readdir(directory)) != NULL) { - if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) - continue; - len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; - if (len > sizeof(file)) { - ret = -E2BIG; - goto out; - } - - sprintf(file, "%s/%s", dir, ent->d_name); - if (unlink(file) < 0 && errno != ENOENT) { - ret = -errno; - goto out; - } - } - - if (rmdir(dir) < 0 && errno != ENOENT) { - ret = -errno; - goto out; - } - - ret = 0; -out: - closedir(directory); - return ret; -} - -/* - * This says that there isn't already a user of the specified directory even if - * there are errors during the checking. This is because if these errors - * happen, the directory is unusable by the pre-existing UML, so we might as - * well take it over. This could happen either by - * the existing UML somehow corrupting its umid directory - * something other than UML sticking stuff in the directory - * this boot racing with a shutdown of the other UML - * In any of these cases, the directory isn't useful for anything else. - * - * Boolean return: 1 if in use, 0 otherwise. - */ -static inline int is_umdir_used(char *dir) -{ - char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; - char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p, n, err; - - n = snprintf(file, sizeof(file), "%s/pid", dir); - if (n >= sizeof(file)) { - printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n"); - err = -E2BIG; - goto out; - } - - dead = 0; - fd = open(file, O_RDONLY); - if (fd < 0) { - fd = -errno; - if (fd != -ENOENT) { - printk(UM_KERN_ERR "is_umdir_used : couldn't open pid " - "file '%s', err = %d\n", file, -fd); - } - goto out; - } - - err = 0; - n = read(fd, pid, sizeof(pid)); - if (n < 0) { - printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " - "'%s', err = %d\n", file, errno); - goto out_close; - } else if (n == 0) { - printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " - "'%s', 0-byte read\n", file); - goto out_close; - } - - p = strtoul(pid, &end, 0); - if (end == pid) { - printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file " - "'%s', errno = %d\n", file, errno); - goto out_close; - } - - if ((kill(p, 0) == 0) || (errno != ESRCH)) { - printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n", - umid, p); - return 1; - } - -out_close: - close(fd); -out: - return 0; -} - -/* - * Try to remove the directory @dir unless it's in use. - * Precondition: @dir exists. - * Returns 0 for success, < 0 for failure in removal or if the directory is in - * use. - */ -static int umdir_take_if_dead(char *dir) -{ - int ret; - if (is_umdir_used(dir)) - return -EEXIST; - - ret = remove_files_and_dir(dir); - if (ret) { - printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir " - "failed with err = %d\n", ret); - } - return ret; -} - -static void __init create_pid_file(void) -{ - char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; - char pid[sizeof("nnnnn\0")]; - int fd, n; - - if (umid_file_name("pid", file, sizeof(file))) - return; - - fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); - if (fd < 0) { - printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: " - "%s\n", file, strerror(errno)); - return; - } - - snprintf(pid, sizeof(pid), "%d\n", getpid()); - n = write(fd, pid, strlen(pid)); - if (n != strlen(pid)) - printk(UM_KERN_ERR "Write of pid file failed - err = %d\n", - errno); - - close(fd); -} - -int __init set_umid(char *name) -{ - if (strlen(name) > UMID_LEN - 1) - return -E2BIG; - - strlcpy(umid, name, sizeof(umid)); - - return 0; -} - -/* Changed in make_umid, which is called during early boot */ -static int umid_setup = 0; - -static int __init make_umid(void) -{ - int fd, err; - char tmp[256]; - - if (umid_setup) - return 0; - - make_uml_dir(); - - if (*umid == '\0') { - strlcpy(tmp, uml_dir, sizeof(tmp)); - strlcat(tmp, "XXXXXX", sizeof(tmp)); - fd = mkstemp(tmp); - if (fd < 0) { - printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: " - "%s\n", tmp, strerror(errno)); - err = -errno; - goto err; - } - - close(fd); - - set_umid(&tmp[strlen(uml_dir)]); - - /* - * There's a nice tiny little race between this unlink and - * the mkdir below. It'd be nice if there were a mkstemp - * for directories. - */ - if (unlink(tmp)) { - err = -errno; - goto err; - } - } - - snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); - err = mkdir(tmp, 0777); - if (err < 0) { - err = -errno; - if (err != -EEXIST) - goto err; - - if (umdir_take_if_dead(tmp) < 0) - goto err; - - err = mkdir(tmp, 0777); - } - if (err) { - err = -errno; - printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid, - errno); - goto err; - } - - umid_setup = 1; - - create_pid_file(); - - err = 0; - err: - return err; -} - -static int __init make_umid_init(void) -{ - if (!make_umid()) - return 0; - - /* - * If initializing with the given umid failed, then try again with - * a random one. - */ - printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a " - "random umid\n", umid); - *umid = '\0'; - make_umid(); - - return 0; -} - -__initcall(make_umid_init); - -int __init umid_file_name(char *name, char *buf, int len) -{ - int n, err; - - err = make_umid(); - if (err) - return err; - - n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); - if (n >= len) { - printk(UM_KERN_ERR "umid_file_name : buffer too short\n"); - return -E2BIG; - } - - return 0; -} - -char *get_umid(void) -{ - return umid; -} - -static int __init set_uml_dir(char *name, int *add) -{ - if (*name == '\0') { - printf("uml_dir can't be an empty string\n"); - return 0; - } - - if (name[strlen(name) - 1] == '/') { - uml_dir = name; - return 0; - } - - uml_dir = malloc(strlen(name) + 2); - if (uml_dir == NULL) { - printf("Failed to malloc uml_dir - error = %d\n", errno); - - /* - * Return 0 here because do_initcalls doesn't look at - * the return value. - */ - return 0; - } - sprintf(uml_dir, "%s/", name); - - return 0; -} - -__uml_setup("uml_dir=", set_uml_dir, -"uml_dir=<directory>\n" -" The location to place the pid and umid files.\n\n" -); - -static void remove_umid_dir(void) -{ - char dir[strlen(uml_dir) + UMID_LEN + 1], err; - - sprintf(dir, "%s%s", uml_dir, umid); - err = remove_files_and_dir(dir); - if (err) - printf("remove_umid_dir - remove_files_and_dir failed with " - "err = %d\n", err); -} - -__uml_exitcall(remove_umid_dir); |