mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 12:07:31 +00:00 
			
		
		
		
	 f3a8bdc1d5
			
		
	
	
		f3a8bdc1d5
		
	
	
	
	
		
			
			If one uses -L $PATH to point to a full chroot, the startup time is significant. In addition, the existing probing algorithm fails to handle symlink loops. Instead, probe individual paths on demand. Cache both positive and negative results within $PATH, so that any one filename is probed only once. Use glib filename functions for clarity. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Tested-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20190519201953.20161-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
		
			
				
	
	
		
			71 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Code to mangle pathnames into those matching a given prefix.
 | |
|    eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so");
 | |
| 
 | |
|    The assumption is that this area does not change.
 | |
| */
 | |
| #include "qemu/osdep.h"
 | |
| #include <sys/param.h>
 | |
| #include <dirent.h>
 | |
| #include "qemu/cutils.h"
 | |
| #include "qemu/path.h"
 | |
| #include "qemu/thread.h"
 | |
| 
 | |
| static const char *base;
 | |
| static GHashTable *hash;
 | |
| static QemuMutex lock;
 | |
| 
 | |
| void init_paths(const char *prefix)
 | |
| {
 | |
|     if (prefix[0] == '\0' || !strcmp(prefix, "/")) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (prefix[0] == '/') {
 | |
|         base = g_strdup(prefix);
 | |
|     } else {
 | |
|         char *cwd = g_get_current_dir();
 | |
|         base = g_build_filename(cwd, prefix, NULL);
 | |
|         g_free(cwd);
 | |
|     }
 | |
| 
 | |
|     hash = g_hash_table_new(g_str_hash, g_str_equal);
 | |
|     qemu_mutex_init(&lock);
 | |
| }
 | |
| 
 | |
| /* Look for path in emulation dir, otherwise return name. */
 | |
| const char *path(const char *name)
 | |
| {
 | |
|     gpointer key, value;
 | |
|     const char *ret;
 | |
| 
 | |
|     /* Only do absolute paths: quick and dirty, but should mostly be OK.  */
 | |
|     if (!base || !name || name[0] != '/') {
 | |
|         return name;
 | |
|     }
 | |
| 
 | |
|     qemu_mutex_lock(&lock);
 | |
| 
 | |
|     /* Have we looked up this file before?  */
 | |
|     if (g_hash_table_lookup_extended(hash, name, &key, &value)) {
 | |
|         ret = value ? value : name;
 | |
|     } else {
 | |
|         char *save = g_strdup(name);
 | |
|         char *full = g_build_filename(base, name, NULL);
 | |
| 
 | |
|         /* Look for the path; record the result, pass or fail.  */
 | |
|         if (access(full, F_OK) == 0) {
 | |
|             /* Exists.  */
 | |
|             g_hash_table_insert(hash, save, full);
 | |
|             ret = full;
 | |
|         } else {
 | |
|             /* Does not exist.  */
 | |
|             g_free(full);
 | |
|             g_hash_table_insert(hash, save, NULL);
 | |
|             ret = name;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     qemu_mutex_unlock(&lock);
 | |
|     return ret;
 | |
| }
 |