X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmono-config.c;h=0dc6bd9698d833c1f645d45d71abb0ab39a09d75;hb=3d0e5bf63c66a86f9f2ce2c0ea6ec6c33371af90;hp=cef1a7c9560f52ba7733a6877b968c4590ef955a;hpb=3a53032bfa7ce32e371345e723f9df7b82ec4153;p=mono.git diff --git a/mono/metadata/mono-config.c b/mono/metadata/mono-config.c index cef1a7c9560..0dc6bd9698d 100644 --- a/mono/metadata/mono-config.c +++ b/mono/metadata/mono-config.c @@ -10,8 +10,63 @@ #include "config.h" #include #include + +#include "mono/metadata/assembly.h" #include "mono/metadata/loader.h" #include "mono/metadata/mono-config.h" +#include "mono/metadata/metadata-internals.h" +#include "mono/metadata/object-internals.h" +#include "mono/utils/mono-logger.h" + +#if defined(__linux__) +#define CONFIG_OS "linux" +#elif defined(__APPLE__) +#define CONFIG_OS "osx" +#elif defined(sun) +#define CONFIG_OS "solaris" +#elif defined(__FreeBSD__) +#define CONFIG_OS "freebsd" +#elif defined(__NetBSD__) +#define CONFIG_OS "netbsd" +#elif defined(__OpenBSD__) +#define CONFIG_OS "openbsd" +#elif defined(__WIN32__) +#define CONFIG_OS "windows" +#elif defined(_IBMR2) +#define CONFIG_OS "aix" +#elif defined(__hpux) +#define CONFIG_OS "hpux" +#else +#warning Unknown operating system +#define CONFIG_OS "unknownOS" +#endif + +#if defined(__i386__) +#define CONFIG_CPU "x86" +#elif defined(__x86_64__) +#define CONFIG_CPU "x86-64" +#elif defined(sparc) || defined(__sparc__) +#define CONFIG_CPU "sparc" +#elif defined(__ppc__) || defined(__powerpc__) +#define CONFIG_CPU "ppc" +#elif defined(__s390x__) +#define CONFIG_CPU "s390x" +#elif defined(__s390__) +#define CONFIG_CPU "s390" +#elif defined(__arm__) +#define CONFIG_CPU "arm" +#elif defined(__ia64__) +#define CONFIG_CPU "ia64" +#elif defined(__alpha__) +#define CONFIG_CPU "alpha" +#elif defined(hppa) || defined(__hppa__) +#define CONFIG_CPU "hppa" +#elif defined(mips) || defined(__mips) || defined(_mips) +#define CONFIG_CPU "mips" +#else +#warning Unknown CPU +#define CONFIG_CPU "unknownCPU" +#endif static void start_element (GMarkupParseContext *context, const gchar *element_name, @@ -134,9 +189,29 @@ static void parse_error (GMarkupParseContext *context, { } +static int +arch_matches (const char* arch, const char *value) +{ + char **splitted, **p; + int found = FALSE; + if (value [0] == '!') + return !arch_matches (arch, value + 1); + p = splitted = g_strsplit (value, ",", 0); + while (*p) { + if (strcmp (arch, *p) == 0) { + found = TRUE; + break; + } + p++; + } + g_strfreev (splitted); + return found; +} + typedef struct { char *dll; char *target; + int ignore; MonoImage *assembly; } DllInfo; @@ -160,15 +235,22 @@ dllmap_start (gpointer user_data, g_free (info->dll); g_free (info->target); info->dll = info->target = NULL; + info->ignore = FALSE; for (i = 0; attribute_names [i]; ++i) { if (strcmp (attribute_names [i], "dll") == 0) info->dll = g_strdup (attribute_values [i]); else if (strcmp (attribute_names [i], "target") == 0) info->target = g_strdup (attribute_values [i]); + else if (strcmp (attribute_names [i], "os") == 0 && !arch_matches (CONFIG_OS, attribute_values [i])) + info->ignore = TRUE; + else if (strcmp (attribute_names [i], "cpu") == 0 && !arch_matches (CONFIG_CPU, attribute_values [i])) + info->ignore = TRUE; } - mono_dllmap_insert (info->assembly, info->dll, NULL, info->target, NULL); + if (!info->ignore) + mono_dllmap_insert (info->assembly, info->dll, NULL, info->target, NULL); } else if (strcmp (element_name, "dllentry") == 0) { const char *name = NULL, *target = NULL, *dll = NULL; + int ignore = FALSE; for (i = 0; attribute_names [i]; ++i) { if (strcmp (attribute_names [i], "dll") == 0) dll = attribute_values [i]; @@ -176,10 +258,15 @@ dllmap_start (gpointer user_data, target = attribute_values [i]; else if (strcmp (attribute_names [i], "name") == 0) name = attribute_values [i]; + else if (strcmp (attribute_names [i], "os") == 0 && !arch_matches (CONFIG_OS, attribute_values [i])) + ignore = TRUE; + else if (strcmp (attribute_names [i], "cpu") == 0 && !arch_matches (CONFIG_CPU, attribute_values [i])) + ignore = TRUE; } if (!dll) dll = info->dll; - mono_dllmap_insert (info->assembly, info->dll, name, dll, target); + if (!info->ignore && !ignore) + mono_dllmap_insert (info->assembly, info->dll, name, dll, target); } } @@ -203,6 +290,31 @@ dllmap_handler = { dllmap_finish }; +static void +legacyUEP_start (gpointer user_data, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values) { + if ((strcmp (element_name, "legacyUnhandledExceptionPolicy") == 0) && + (attribute_names [0] != NULL) && + (strcmp (attribute_names [0], "enabled") == 0)) { + if ((strcmp (attribute_values [0], "1") == 0) || + (g_strcasecmp (attribute_values [0], "true") == 0)) { + mono_runtime_unhandled_exception_policy_set (MONO_UNHANLED_POLICY_LEGACY); + } + } +} + +static const MonoParseHandler +legacyUEP_handler = { + "legacyUnhandledExceptionPolicy", + NULL, /* init */ + legacyUEP_start, + NULL, /* text */ + NULL, /* end */ + NULL, /* finish */ +}; + static int inited = 0; static void @@ -211,32 +323,57 @@ mono_config_init (void) inited = 1; config_handlers = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (config_handlers, (gpointer) dllmap_handler.element_name, (gpointer) &dllmap_handler); + g_hash_table_insert (config_handlers, (gpointer) legacyUEP_handler.element_name, (gpointer) &legacyUEP_handler); } /* FIXME: error handling */ -/* If assembly is NULL, parse in the global context */ -static int -mono_config_parse_file_with_context (ParseState *state, const char *filename) +static void +mono_config_parse_xml_with_context (ParseState *state, const char *text, gsize len) { GMarkupParseContext *context; - char *text; - gsize len; if (!inited) mono_config_init (); - if (!g_file_get_contents (filename, &text, &len, NULL)) - return 0; context = g_markup_parse_context_new (&mono_parser, 0, state, NULL); if (g_markup_parse_context_parse (context, text, len, NULL)) { g_markup_parse_context_end_parse (context, NULL); } g_markup_parse_context_free (context); +} + +/* If assembly is NULL, parse in the global context */ +static int +mono_config_parse_file_with_context (ParseState *state, const char *filename) +{ + char *text; + gsize len; + + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_CONFIG, + "Config attempting to parse: '%s'.", filename); + + if (!g_file_get_contents (filename, &text, &len, NULL)) + return 0; + mono_config_parse_xml_with_context (state, text, len); g_free (text); return 1; } +/** + * mono_config_parse_memory: + * @buffer: a pointer to an string XML representation of the configuration + * + * Parses the configuration from a buffer + */ +void +mono_config_parse_memory (const char *buffer) +{ + ParseState state = {NULL}; + + mono_config_parse_xml_with_context (&state, buffer, strlen (buffer)); +} + static void mono_config_parse_file (const char *filename) { @@ -256,26 +393,68 @@ get_assembly_filename (MonoImage *image, int state) { switch (state) { case 0: - return g_strdup (image->assembly_name); + return g_strdup (mono_image_get_name (image)); default: return NULL; } } +typedef struct _BundledConfig BundledConfig; + +struct _BundledConfig { + BundledConfig *next; + const char* aname; + const char* config_xml; +}; + +static BundledConfig *bundled_configs = NULL; + +static const char *bundled_machine_config = NULL; + +void +mono_register_config_for_assembly (const char* assembly_name, const char* config_xml) +{ + BundledConfig *bconfig; + + bconfig = g_new0 (BundledConfig, 1); + bconfig->aname = assembly_name; + bconfig->config_xml = config_xml; + bconfig->next = bundled_configs; + bundled_configs = bconfig; +} + +const char * +mono_config_string_for_assembly_file (const char *filename) +{ + BundledConfig *bconfig; + + for (bconfig = bundled_configs; bconfig; bconfig = bconfig->next) { + if (bconfig->aname && strcmp (bconfig->aname, filename) == 0) + return bconfig->config_xml; + } + return NULL; +} + void mono_config_for_assembly (MonoImage *assembly) { ParseState state = {NULL}; int got_it = 0, i; char *aname, *cfg, *cfg_name; + const char *bundled_config; const char *home; state.assembly = assembly; - cfg_name = g_strdup_printf ("%s.config", assembly->name); + + bundled_config = mono_config_string_for_assembly_file (assembly->module_name); + if (bundled_config) + mono_config_parse_xml_with_context (&state, bundled_config, strlen (bundled_config)); + + cfg_name = g_strdup_printf ("%s.config", mono_image_get_filename (assembly)); mono_config_parse_file_with_context (&state, cfg_name); g_free (cfg_name); - cfg_name = g_strdup_printf ("%s.config", assembly->assembly_name); + cfg_name = g_strdup_printf ("%s.config", mono_image_get_name (assembly)); home = g_get_home_dir (); @@ -296,16 +475,21 @@ mono_config_for_assembly (MonoImage *assembly) g_free (cfg_name); } -/* +/** + * mono_config_parse: + * @filename: the filename to load the configuration variables from. + * * Pass a NULL filename to parse the default config files * (or the file in the MONO_CONFIG env var). */ void mono_config_parse (const char *filename) { const char *home; - char *user_cfg; char *mono_cfg; - +#ifndef PLATFORM_WIN32 + char *user_cfg; +#endif + if (filename) { mono_config_parse_file (filename); return; @@ -329,35 +513,160 @@ mono_config_parse (const char *filename) { #endif } -static char *mono_cfg_dir = NULL; +static const char *mono_cfg_dir = NULL; -static void -mono_install_get_config_dir (void) +/* Invoked during startup */ +void +mono_set_config_dir (const char *dir) { -#ifdef PLATFORM_WIN32 - int i; -#endif - - mono_cfg_dir = g_getenv ("MONO_CFG_DIR"); - - if (!mono_cfg_dir) { -#ifndef PLATFORM_WIN32 - mono_cfg_dir = MONO_CFG_DIR; -#else - mono_cfg_dir = g_strdup (MONO_CFG_DIR); - for (i = strlen (mono_cfg_dir) - 1; i >= 0; i--) { - if (mono_cfg_dir [i] == '/') - ((char*) mono_cfg_dir) [i] = '\\'; - } -#endif - } + /* If this variable is set, overrides the directory computed */ + mono_cfg_dir = g_getenv ("MONO_CFG_DIR"); + if (mono_cfg_dir == NULL) + mono_cfg_dir = g_strdup (dir); } const char* mono_get_config_dir (void) { - if (!mono_cfg_dir) - mono_install_get_config_dir (); + if (mono_cfg_dir == NULL) + mono_set_dirs (NULL, NULL); + return mono_cfg_dir; } +void +mono_register_machine_config (const char *config_xml) +{ + bundled_machine_config = config_xml; +} + +const char * +mono_get_machine_config (void) +{ + return bundled_machine_config; +} + +static void +publisher_policy_start (gpointer user_data, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values) +{ + MonoAssemblyBindingInfo *info; + int n; + + info = user_data; + if (!strcmp (element_name, "assemblyIdentity")) { + for (n = 0; attribute_names [n]; n++) { + const gchar *attribute_name = attribute_names [n]; + + if (!strcmp (attribute_name, "name")) + info->name = g_strdup (attribute_values [n]); + else if (!strcmp (attribute_name, "publicKeyToken")) { + if (strlen (attribute_values [n]) == MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) + g_strlcpy ((char *) info->public_key_token, attribute_values [n], MONO_PUBLIC_KEY_TOKEN_LENGTH); + } else if (!strcmp (attribute_name, "culture")) { + if (!strcmp (attribute_values [n], "neutral")) + info->culture = g_strdup (""); + else + info->culture = g_strdup (attribute_values [n]); + } + } + } else if (!strcmp (element_name, "bindingRedirect")) { + for (n = 0; attribute_names [n]; n++) { + const gchar *attribute_name = attribute_names [n]; + + if (!strcmp (attribute_name, "oldVersion")) { + gchar **numbers, **version, **versions; + gint major, minor, build, revision; + + /* Invalid value */ + if (!strcmp (attribute_values [n], "")) + return; + + versions = g_strsplit (attribute_values [n], "-", 2); + version = g_strsplit (*versions, ".", 4); + + /* We assign the values to gint vars to do the checks */ + numbers = version; + major = *numbers ? atoi (*numbers++) : -1; + minor = *numbers ? atoi (*numbers++) : -1; + build = *numbers ? atoi (*numbers++) : -1; + revision = *numbers ? atoi (*numbers) : -1; + g_strfreev (version); + if (major < 0 || minor < 0 || build < 0 || revision < 0) { + g_strfreev (versions); + return; + } + + info->old_version_bottom.major = major; + info->old_version_bottom.minor = minor; + info->old_version_bottom.build = build; + info->old_version_bottom.revision = revision; + info->has_old_version_bottom = TRUE; + + if (!*(versions + 1)) { + g_strfreev (versions); + continue; + } + + numbers = version = g_strsplit (*(versions + 1), ".", 4); + major = *numbers ? atoi (*numbers++) : -1; + minor = *numbers ? atoi (*numbers++) : -1; + build = *numbers ? atoi (*numbers++) : -1; + revision = *numbers ? atoi (*numbers) : 1; + g_strfreev (version); + if (major < 0 || minor < 0 || build < 0 || revision < 0) { + g_strfreev (versions); + return; + } + + info->old_version_top.major = major; + info->old_version_top.minor = minor; + info->old_version_top.build = build; + info->old_version_top.revision = revision; + info->has_old_version_top = TRUE; + + g_strfreev (versions); + } else if (!strcmp (attribute_name, "newVersion")) { + gchar **numbers, **version; + + /* Invalid value */ + if (!strcmp (attribute_values [n], "")) + return; + + numbers = version = g_strsplit (attribute_values [n], ".", 4); + info->new_version.major = *numbers ? atoi (*numbers++) : -1; + info->new_version.minor = *numbers ? atoi (*numbers++) : -1; + info->new_version.build = *numbers ? atoi (*numbers++) : -1; + info->new_version.revision = *numbers ? atoi (*numbers) : -1; + info->has_new_version = TRUE; + g_strfreev (version); + } + } + } +} + +static MonoParseHandler +publisher_policy_parser = { + "", /* We don't need to use declare an xml element */ + NULL, + publisher_policy_start, + NULL, + NULL, + NULL +}; + +void +mono_config_parse_publisher_policy (const gchar *filename, MonoAssemblyBindingInfo *info) +{ + ParseState state = { + &publisher_policy_parser, /* MonoParseHandler */ + info, /* user_data */ + NULL, /* MonoImage (we don't need it right now)*/ + TRUE /* We are already inited */ + }; + + mono_config_parse_file_with_context (&state, filename); +} +