Commit 32ce63371a6b4d7ad8786ac5d2f95a1e6cdd1af4
1 parent
ec86b0fb
path patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@96 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
154 additions
and
16 deletions
configure
| @@ -19,6 +19,7 @@ TMPH="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.h" | @@ -19,6 +19,7 @@ TMPH="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.h" | ||
| 19 | 19 | ||
| 20 | # default parameters | 20 | # default parameters |
| 21 | prefix="/usr/local" | 21 | prefix="/usr/local" |
| 22 | +interp_prefix="/usr/gnemul/qemu-i386" | ||
| 22 | cross_prefix="" | 23 | cross_prefix="" |
| 23 | cc="gcc" | 24 | cc="gcc" |
| 24 | host_cc="gcc" | 25 | host_cc="gcc" |
| @@ -89,6 +90,8 @@ for opt do | @@ -89,6 +90,8 @@ for opt do | ||
| 89 | case "$opt" in | 90 | case "$opt" in |
| 90 | --prefix=*) prefix=`echo $opt | cut -d '=' -f 2` | 91 | --prefix=*) prefix=`echo $opt | cut -d '=' -f 2` |
| 91 | ;; | 92 | ;; |
| 93 | + --interp-prefix=*) interp_prefix=`echo $opt | cut -d '=' -f 2` | ||
| 94 | + ;; | ||
| 92 | --source-path=*) source_path=`echo $opt | cut -d '=' -f 2` | 95 | --source-path=*) source_path=`echo $opt | cut -d '=' -f 2` |
| 93 | ;; | 96 | ;; |
| 94 | --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2` | 97 | --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2` |
| @@ -172,7 +175,7 @@ EOF | @@ -172,7 +175,7 @@ EOF | ||
| 172 | echo "Standard options:" | 175 | echo "Standard options:" |
| 173 | echo " --help print this message" | 176 | echo " --help print this message" |
| 174 | echo " --prefix=PREFIX install in PREFIX [$prefix]" | 177 | echo " --prefix=PREFIX install in PREFIX [$prefix]" |
| 175 | -echo " for audio/video/image support" | 178 | +echo " --interp-prefix=PREFIX where to find shared libraries, etc. [$interp_prefix]" |
| 176 | echo "" | 179 | echo "" |
| 177 | echo "Advanced options (experts only):" | 180 | echo "Advanced options (experts only):" |
| 178 | echo " --source-path=PATH path of source code [$source_path]" | 181 | echo " --source-path=PATH path of source code [$source_path]" |
| @@ -198,7 +201,7 @@ echo "# Automatically generated by configure - do not modify" > config.mak | @@ -198,7 +201,7 @@ echo "# Automatically generated by configure - do not modify" > config.mak | ||
| 198 | echo "/* Automatically generated by configure - do not modify */" > $TMPH | 201 | echo "/* Automatically generated by configure - do not modify */" > $TMPH |
| 199 | 202 | ||
| 200 | echo "prefix=$prefix" >> config.mak | 203 | echo "prefix=$prefix" >> config.mak |
| 201 | -echo "#define CONFIG_QEMU_PREFIX \"$prefix\"" >> $TMPH | 204 | +echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix\"" >> $TMPH |
| 202 | echo "MAKE=$make" >> config.mak | 205 | echo "MAKE=$make" >> config.mak |
| 203 | echo "CC=$cc" >> config.mak | 206 | echo "CC=$cc" >> config.mak |
| 204 | echo "GCC_MAJOR=$gcc_major" >> config.mak | 207 | echo "GCC_MAJOR=$gcc_major" >> config.mak |
linux-user/elfload.c
| @@ -70,7 +70,6 @@ struct linux_binprm { | @@ -70,7 +70,6 @@ struct linux_binprm { | ||
| 70 | int fd; | 70 | int fd; |
| 71 | int e_uid, e_gid; | 71 | int e_uid, e_gid; |
| 72 | int argc, envc; | 72 | int argc, envc; |
| 73 | - char * interp_prefix; /* prefix for interpreter */ | ||
| 74 | char * filename; /* Name of binary */ | 73 | char * filename; /* Name of binary */ |
| 75 | unsigned long loader, exec; | 74 | unsigned long loader, exec; |
| 76 | int dont_iput; /* binfmt handler has put inode */ | 75 | int dont_iput; /* binfmt handler has put inode */ |
| @@ -756,8 +755,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | @@ -756,8 +755,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | ||
| 756 | * is an a.out format binary | 755 | * is an a.out format binary |
| 757 | */ | 756 | */ |
| 758 | 757 | ||
| 759 | - elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+ | ||
| 760 | - strlen(bprm->interp_prefix)); | 758 | + elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); |
| 761 | 759 | ||
| 762 | if (elf_interpreter == NULL) { | 760 | if (elf_interpreter == NULL) { |
| 763 | free (elf_phdata); | 761 | free (elf_phdata); |
| @@ -765,12 +763,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | @@ -765,12 +763,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | ||
| 765 | return -ENOMEM; | 763 | return -ENOMEM; |
| 766 | } | 764 | } |
| 767 | 765 | ||
| 768 | - strcpy(elf_interpreter, bprm->interp_prefix); | ||
| 769 | retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); | 766 | retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); |
| 770 | if(retval >= 0) { | 767 | if(retval >= 0) { |
| 771 | - retval = read(bprm->fd, | ||
| 772 | - elf_interpreter+strlen(bprm->interp_prefix), | ||
| 773 | - elf_ppnt->p_filesz); | 768 | + retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); |
| 774 | } | 769 | } |
| 775 | if(retval < 0) { | 770 | if(retval < 0) { |
| 776 | perror("load_elf_binary2"); | 771 | perror("load_elf_binary2"); |
| @@ -792,7 +787,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | @@ -792,7 +787,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | ||
| 792 | printf("Using ELF interpreter %s\n", elf_interpreter); | 787 | printf("Using ELF interpreter %s\n", elf_interpreter); |
| 793 | #endif | 788 | #endif |
| 794 | if (retval >= 0) { | 789 | if (retval >= 0) { |
| 795 | - retval = open(elf_interpreter, O_RDONLY); | 790 | + retval = open(path(elf_interpreter), O_RDONLY); |
| 796 | if(retval >= 0) { | 791 | if(retval >= 0) { |
| 797 | interpreter_fd = retval; | 792 | interpreter_fd = retval; |
| 798 | } | 793 | } |
| @@ -1060,8 +1055,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | @@ -1060,8 +1055,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | ||
| 1060 | 1055 | ||
| 1061 | 1056 | ||
| 1062 | 1057 | ||
| 1063 | -int elf_exec(const char *interp_prefix, | ||
| 1064 | - const char * filename, char ** argv, char ** envp, | 1058 | +int elf_exec(const char * filename, char ** argv, char ** envp, |
| 1065 | struct target_pt_regs * regs, struct image_info *infop) | 1059 | struct target_pt_regs * regs, struct image_info *infop) |
| 1066 | { | 1060 | { |
| 1067 | struct linux_binprm bprm; | 1061 | struct linux_binprm bprm; |
| @@ -1080,7 +1074,6 @@ int elf_exec(const char *interp_prefix, | @@ -1080,7 +1074,6 @@ int elf_exec(const char *interp_prefix, | ||
| 1080 | else { | 1074 | else { |
| 1081 | bprm.fd = retval; | 1075 | bprm.fd = retval; |
| 1082 | } | 1076 | } |
| 1083 | - bprm.interp_prefix = (char *)interp_prefix; | ||
| 1084 | bprm.filename = (char *)filename; | 1077 | bprm.filename = (char *)filename; |
| 1085 | bprm.sh_bang = 0; | 1078 | bprm.sh_bang = 0; |
| 1086 | bprm.loader = 0; | 1079 | bprm.loader = 0; |
linux-user/path.c
0 โ 100644
| 1 | +/* Code to mangle pathnames into those matching a given prefix. | ||
| 2 | + eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so"); | ||
| 3 | + | ||
| 4 | + The assumption is that this area does not change. | ||
| 5 | +*/ | ||
| 6 | +#include <sys/types.h> | ||
| 7 | +#include <dirent.h> | ||
| 8 | +#include <unistd.h> | ||
| 9 | +#include <stdlib.h> | ||
| 10 | +#include <string.h> | ||
| 11 | +#include <errno.h> | ||
| 12 | +#include <stdio.h> | ||
| 13 | +#include "qemu.h" | ||
| 14 | + | ||
| 15 | +struct pathelem | ||
| 16 | +{ | ||
| 17 | + /* Name of this, eg. lib */ | ||
| 18 | + char *name; | ||
| 19 | + /* Full path name, eg. /usr/gnemul/x86-linux/lib. */ | ||
| 20 | + char *pathname; | ||
| 21 | + struct pathelem *parent; | ||
| 22 | + /* Children */ | ||
| 23 | + unsigned int num_entries; | ||
| 24 | + struct pathelem *entries[0]; | ||
| 25 | +}; | ||
| 26 | + | ||
| 27 | +static struct pathelem *base; | ||
| 28 | + | ||
| 29 | +/* First N chars of S1 match S2, and S2 is N chars long. */ | ||
| 30 | +static int strneq(const char *s1, unsigned int n, const char *s2) | ||
| 31 | +{ | ||
| 32 | + unsigned int i; | ||
| 33 | + | ||
| 34 | + for (i = 0; i < n; i++) | ||
| 35 | + if (s1[i] != s2[i]) | ||
| 36 | + return 0; | ||
| 37 | + return s2[i] == 0; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +static struct pathelem *add_entry(struct pathelem *root, const char *name); | ||
| 41 | + | ||
| 42 | +static struct pathelem *new_entry(const char *root, | ||
| 43 | + struct pathelem *parent, | ||
| 44 | + const char *name) | ||
| 45 | +{ | ||
| 46 | + struct pathelem *new = malloc(sizeof(*new)); | ||
| 47 | + new->name = strdup(name); | ||
| 48 | + asprintf(&new->pathname, "%s/%s", root, name); | ||
| 49 | + new->num_entries = 0; | ||
| 50 | + return new; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +#define streq(a,b) (strcmp((a), (b)) == 0) | ||
| 54 | + | ||
| 55 | +static struct pathelem *add_dir_maybe(struct pathelem *path) | ||
| 56 | +{ | ||
| 57 | + DIR *dir; | ||
| 58 | + | ||
| 59 | + if ((dir = opendir(path->pathname)) != NULL) { | ||
| 60 | + struct dirent *dirent; | ||
| 61 | + | ||
| 62 | + while ((dirent = readdir(dir)) != NULL) { | ||
| 63 | + if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){ | ||
| 64 | + path = add_entry(path, dirent->d_name); | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + closedir(dir); | ||
| 68 | + } | ||
| 69 | + return path; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +static struct pathelem *add_entry(struct pathelem *root, const char *name) | ||
| 73 | +{ | ||
| 74 | + root->num_entries++; | ||
| 75 | + | ||
| 76 | + root = realloc(root, sizeof(*root) | ||
| 77 | + + sizeof(root->entries[0])*root->num_entries); | ||
| 78 | + | ||
| 79 | + root->entries[root->num_entries-1] = new_entry(root->pathname, root, name); | ||
| 80 | + root->entries[root->num_entries-1] | ||
| 81 | + = add_dir_maybe(root->entries[root->num_entries-1]); | ||
| 82 | + return root; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +/* This needs to be done after tree is stabalized (ie. no more reallocs!). */ | ||
| 86 | +static void set_parents(struct pathelem *child, struct pathelem *parent) | ||
| 87 | +{ | ||
| 88 | + unsigned int i; | ||
| 89 | + | ||
| 90 | + child->parent = parent; | ||
| 91 | + for (i = 0; i < child->num_entries; i++) | ||
| 92 | + set_parents(child->entries[i], child); | ||
| 93 | +} | ||
| 94 | + | ||
| 95 | +void init_paths(const char *prefix) | ||
| 96 | +{ | ||
| 97 | + if (prefix[0] != '/' || | ||
| 98 | + prefix[0] == '\0' || | ||
| 99 | + !strcmp(prefix, "/")) | ||
| 100 | + return; | ||
| 101 | + | ||
| 102 | + base = new_entry("", NULL, prefix+1); | ||
| 103 | + base = add_dir_maybe(base); | ||
| 104 | + set_parents(base, base); | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */ | ||
| 108 | +static const char * | ||
| 109 | +follow_path(const struct pathelem *cursor, const char *name) | ||
| 110 | +{ | ||
| 111 | + unsigned int i, namelen; | ||
| 112 | + | ||
| 113 | + name += strspn(name, "/"); | ||
| 114 | + namelen = strcspn(name, "/"); | ||
| 115 | + | ||
| 116 | + if (namelen == 0) | ||
| 117 | + return cursor->pathname; | ||
| 118 | + | ||
| 119 | + if (strneq(name, namelen, "..")) | ||
| 120 | + return follow_path(cursor->parent, name + namelen); | ||
| 121 | + | ||
| 122 | + if (strneq(name, namelen, ".")) | ||
| 123 | + return follow_path(cursor, name + namelen); | ||
| 124 | + | ||
| 125 | + for (i = 0; i < cursor->num_entries; i++) | ||
| 126 | + if (strneq(name, namelen, cursor->entries[i]->name)) | ||
| 127 | + return follow_path(cursor->entries[i], name + namelen); | ||
| 128 | + | ||
| 129 | + /* Not found */ | ||
| 130 | + return NULL; | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +/* Look for path in emulation dir, otherwise return name. */ | ||
| 134 | +const char *path(const char *name) | ||
| 135 | +{ | ||
| 136 | + /* Only do absolute paths: quick and dirty, but should mostly be OK. | ||
| 137 | + Could do relative by tracking cwd. */ | ||
| 138 | + if (!base || name[0] != '/') | ||
| 139 | + return name; | ||
| 140 | + | ||
| 141 | + return follow_path(base, name) ?: name; | ||
| 142 | +} |
linux-user/qemu.h
| @@ -60,8 +60,7 @@ typedef struct TaskState { | @@ -60,8 +60,7 @@ typedef struct TaskState { | ||
| 60 | 60 | ||
| 61 | extern TaskState *first_task_state; | 61 | extern TaskState *first_task_state; |
| 62 | 62 | ||
| 63 | -int elf_exec(const char *interp_prefix, | ||
| 64 | - const char * filename, char ** argv, char ** envp, | 63 | +int elf_exec(const char * filename, char ** argv, char ** envp, |
| 65 | struct target_pt_regs * regs, struct image_info *infop); | 64 | struct target_pt_regs * regs, struct image_info *infop); |
| 66 | 65 | ||
| 67 | void target_set_brk(char *new_brk); | 66 | void target_set_brk(char *new_brk); |
| @@ -75,5 +74,6 @@ void process_pending_signals(void *cpu_env); | @@ -75,5 +74,6 @@ void process_pending_signals(void *cpu_env); | ||
| 75 | void signal_init(void); | 74 | void signal_init(void); |
| 76 | int queue_signal(int sig, target_siginfo_t *info); | 75 | int queue_signal(int sig, target_siginfo_t *info); |
| 77 | void save_v86_state(CPUX86State *env); | 76 | void save_v86_state(CPUX86State *env); |
| 78 | - | 77 | +void init_paths(const char *prefix); |
| 78 | +const char *path(const char *pathname); | ||
| 79 | #endif | 79 | #endif |