Revert some changes which don't have proper dependencies.
[mono-project.git] / mono / metadata / mono-config.c
blob8c1c6442702a65dc405c7a3216d718df5d6aff35
1 /**
2 * \file
4 * Runtime and assembly configuration file support routines.
6 * Author: Paolo Molaro (lupus@ximian.com)
8 * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include "config.h"
13 #include <glib.h>
14 #include <string.h>
16 #include "mono/metadata/assembly.h"
17 #include "mono/metadata/loader.h"
18 #include "mono/metadata/mono-config.h"
19 #include "mono/metadata/mono-config-internals.h"
20 #include "mono/metadata/metadata-internals.h"
21 #include "mono/metadata/object-internals.h"
22 #include "mono/utils/mono-logger-internals.h"
24 #if defined(TARGET_PS3)
25 #define CONFIG_OS "CellOS"
26 #elif defined(__linux__)
27 #define CONFIG_OS "linux"
28 #elif defined(__APPLE__)
29 #define CONFIG_OS "osx"
30 #elif defined(sun)
31 #define CONFIG_OS "solaris"
32 #elif defined(__FreeBSD__)
33 #define CONFIG_OS "freebsd"
34 #elif defined(__NetBSD__)
35 #define CONFIG_OS "netbsd"
36 #elif defined(__OpenBSD__)
37 #define CONFIG_OS "openbsd"
38 #elif defined(__WIN32__) || defined(TARGET_WIN32)
39 #define CONFIG_OS "windows"
40 #elif defined(_IBMR2)
41 #define CONFIG_OS "aix"
42 #elif defined(__hpux)
43 #define CONFIG_OS "hpux"
44 #elif defined(__HAIKU__)
45 #define CONFIG_OS "haiku"
46 #elif defined (TARGET_WASM)
47 #define CONFIG_OS "wasm"
48 #else
49 #warning Unknown operating system
50 #define CONFIG_OS "unknownOS"
51 #endif
53 #ifndef CONFIG_CPU
54 #if defined(__i386__) || defined(TARGET_X86)
55 #define CONFIG_CPU "x86"
56 #define CONFIG_WORDSIZE "32"
57 #elif defined(__x86_64__) || defined(TARGET_AMD64)
58 #define CONFIG_CPU "x86-64"
59 #define CONFIG_WORDSIZE "64"
60 #elif defined(sparc) || defined(__sparc__)
61 #define CONFIG_CPU "sparc"
62 #define CONFIG_WORDSIZE "32"
63 #elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_64) || defined(TARGET_POWERPC)
64 #define CONFIG_WORDSIZE "64"
65 #ifdef __mono_ppc_ilp32__
66 # define CONFIG_CPU "ppc64ilp32"
67 #else
68 # define CONFIG_CPU "ppc64"
69 #endif
70 #elif defined(__ppc__) || defined(__powerpc__)
71 #define CONFIG_CPU "ppc"
72 #define CONFIG_WORDSIZE "32"
73 #elif defined(__s390x__)
74 #define CONFIG_CPU "s390x"
75 #define CONFIG_WORDSIZE "64"
76 #elif defined(__s390__)
77 #define CONFIG_CPU "s390"
78 #define CONFIG_WORDSIZE "32"
79 #elif defined(__arm__)
80 #define CONFIG_CPU "arm"
81 #define CONFIG_WORDSIZE "32"
82 #elif defined(__aarch64__)
83 #define CONFIG_CPU "armv8"
84 #define CONFIG_WORDSIZE "64"
85 #elif defined(mips) || defined(__mips) || defined(_mips)
86 #define CONFIG_CPU "mips"
87 #define CONFIG_WORDSIZE "32"
88 #elif defined (TARGET_RISCV32)
89 #define CONFIG_CPU "riscv32"
90 #define CONFIG_WORDSIZE "32"
91 #elif defined (TARGET_RISCV64)
92 #define CONFIG_CPU "riscv64"
93 #define CONFIG_WORDSIZE "64"
94 #elif defined(TARGET_WASM)
95 #define CONFIG_CPU "wasm"
96 #define CONFIG_WORDSIZE "32"
97 #else
98 #error Unknown CPU
99 #define CONFIG_CPU "unknownCPU"
100 #endif
101 #endif
104 * mono_config_get_os:
106 * Returns the operating system that Mono is running on, as used for dllmap entries.
108 const char *
109 mono_config_get_os (void)
111 return CONFIG_OS;
115 * mono_config_get_cpu:
117 * Returns the architecture that Mono is running on, as used for dllmap entries.
119 const char *
120 mono_config_get_cpu (void)
122 return CONFIG_CPU;
126 * mono_config_get_wordsize:
128 * Returns the word size that Mono is running on, as used for dllmap entries.
130 const char *
131 mono_config_get_wordsize (void)
133 return CONFIG_WORDSIZE;
136 static void start_element (GMarkupParseContext *context,
137 const gchar *element_name,
138 const gchar **attribute_names,
139 const gchar **attribute_values,
140 gpointer user_data,
141 GError **gerror);
143 static void end_element (GMarkupParseContext *context,
144 const gchar *element_name,
145 gpointer user_data,
146 GError **gerror);
148 static void parse_text (GMarkupParseContext *context,
149 const gchar *text,
150 gsize text_len,
151 gpointer user_data,
152 GError **gerror);
154 static void passthrough (GMarkupParseContext *context,
155 const gchar *text,
156 gsize text_len,
157 gpointer user_data,
158 GError **gerror);
160 static void parse_error (GMarkupParseContext *context,
161 GError *gerror,
162 gpointer user_data);
164 static const GMarkupParser
165 mono_parser = {
166 start_element,
167 end_element,
168 parse_text,
169 passthrough,
170 parse_error
173 static GHashTable *config_handlers;
175 static char *mono_cfg_dir = NULL;
177 /* when this interface is stable, export it. */
178 typedef struct MonoParseHandler MonoParseHandler;
180 struct MonoParseHandler {
181 const char *element_name;
182 void*(*init) (MonoImage *assembly);
183 void (*start) (gpointer user_data, const gchar *name,
184 const gchar **attributes,
185 const gchar **values);
186 void (*text) (gpointer user_data, const char *text, gsize test_len);
187 void (*end) (gpointer user_data, const char *name);
188 void (*finish) (gpointer user_data);
191 typedef struct {
192 MonoAssemblyBindingInfo *info;
193 void (*info_parsed)(MonoAssemblyBindingInfo *info, void *user_data);
194 void *user_data;
195 } ParserUserData;
197 typedef struct {
198 MonoParseHandler *current;
199 void *user_data;
200 MonoImage *assembly;
201 int inited;
202 } MonoConfigParseState;
204 static void start_element (GMarkupParseContext *context,
205 const gchar *element_name,
206 const gchar **attribute_names,
207 const gchar **attribute_values,
208 gpointer user_data,
209 GError **gerror)
211 MonoConfigParseState *state = (MonoConfigParseState *)user_data;
212 if (!state->current) {
213 state->current = (MonoParseHandler *)g_hash_table_lookup (config_handlers, element_name);
214 if (state->current && state->current->init)
215 state->user_data = state->current->init (state->assembly);
217 if (state->current && state->current->start)
218 state->current->start (state->user_data, element_name, attribute_names, attribute_values);
221 static void end_element (GMarkupParseContext *context,
222 const gchar *element_name,
223 gpointer user_data,
224 GError **gerror)
226 MonoConfigParseState *state = (MonoConfigParseState *)user_data;
227 if (state->current) {
228 if (state->current->end)
229 state->current->end (state->user_data, element_name);
230 if (strcmp (state->current->element_name, element_name) == 0) {
231 if (state->current->finish)
232 state->current->finish (state->user_data);
233 state->current = NULL;
234 state->user_data = NULL;
239 static void parse_text (GMarkupParseContext *context,
240 const gchar *text,
241 gsize text_len,
242 gpointer user_data,
243 GError **gerror)
245 MonoConfigParseState *state = (MonoConfigParseState *)user_data;
246 if (state->current && state->current->text)
247 state->current->text (state->user_data, text, text_len);
250 static void passthrough (GMarkupParseContext *context,
251 const gchar *text,
252 gsize text_len,
253 gpointer user_data,
254 GError **gerror)
256 /* do nothing */
259 static void parse_error (GMarkupParseContext *context,
260 GError *gerror,
261 gpointer user_data)
263 MonoConfigParseState *state = (MonoConfigParseState *)user_data;
264 const gchar *msg;
265 const gchar *filename;
267 filename = state && state->user_data ? (gchar *) state->user_data : "<unknown>";
268 msg = gerror && gerror->message ? gerror->message : "";
269 g_warning ("Error parsing %s: %s", filename, msg);
272 static int
273 arch_matches (const char* arch, const char *value)
275 char **splitted, **p;
276 int found = FALSE;
277 if (value [0] == '!')
278 return !arch_matches (arch, value + 1);
279 p = splitted = g_strsplit (value, ",", 0);
280 while (*p) {
281 if (strcmp (arch, *p) == 0) {
282 found = TRUE;
283 break;
285 p++;
287 g_strfreev (splitted);
288 return found;
291 typedef struct {
292 char *dll;
293 char *target;
294 int ignore;
295 MonoImage *assembly;
296 } DllInfo;
298 static void*
299 dllmap_init (MonoImage *assembly) {
300 DllInfo *info = g_new0 (DllInfo, 1);
301 info->assembly = assembly;
302 return info;
305 static void
306 dllmap_start (gpointer user_data,
307 const gchar *element_name,
308 const gchar **attribute_names,
309 const gchar **attribute_values)
311 int i;
312 DllInfo *info = (DllInfo *)user_data;
314 if (strcmp (element_name, "dllmap") == 0) {
315 g_free (info->dll);
316 g_free (info->target);
317 info->dll = info->target = NULL;
318 info->ignore = FALSE;
319 for (i = 0; attribute_names [i]; ++i) {
320 if (strcmp (attribute_names [i], "dll") == 0)
321 info->dll = g_strdup (attribute_values [i]);
322 else if (strcmp (attribute_names [i], "target") == 0){
323 const char* p = strstr (attribute_values [i], "$mono_libdir");
324 if (p != NULL){
325 char *libdir = mono_native_getrootdir ();
326 size_t libdir_len = strlen (libdir);
327 char *result;
329 result = (char *)g_malloc (libdir_len-strlen("$mono_libdir")+strlen(attribute_values[i])+1);
330 strncpy (result, attribute_values[i], p-attribute_values[i]);
331 strcpy (result+(p-attribute_values[i]), libdir);
332 g_free (libdir);
333 strcat (result, p+strlen("$mono_libdir"));
334 info->target = result;
335 } else
336 info->target = g_strdup (attribute_values [i]);
337 } else if (strcmp (attribute_names [i], "os") == 0 && !arch_matches (CONFIG_OS, attribute_values [i]))
338 info->ignore = TRUE;
339 else if (strcmp (attribute_names [i], "cpu") == 0 && !arch_matches (CONFIG_CPU, attribute_values [i]))
340 info->ignore = TRUE;
341 else if (strcmp (attribute_names [i], "wordsize") == 0 && !arch_matches (CONFIG_WORDSIZE, attribute_values [i]))
342 info->ignore = TRUE;
344 if (!info->ignore)
345 mono_dllmap_insert (info->assembly, info->dll, NULL, info->target, NULL);
346 } else if (strcmp (element_name, "dllentry") == 0) {
347 const char *name = NULL, *target = NULL, *dll = NULL;
348 int ignore = FALSE;
349 for (i = 0; attribute_names [i]; ++i) {
350 if (strcmp (attribute_names [i], "dll") == 0)
351 dll = attribute_values [i];
352 else if (strcmp (attribute_names [i], "target") == 0)
353 target = attribute_values [i];
354 else if (strcmp (attribute_names [i], "name") == 0)
355 name = attribute_values [i];
356 else if (strcmp (attribute_names [i], "os") == 0 && !arch_matches (CONFIG_OS, attribute_values [i]))
357 ignore = TRUE;
358 else if (strcmp (attribute_names [i], "cpu") == 0 && !arch_matches (CONFIG_CPU, attribute_values [i]))
359 ignore = TRUE;
360 else if (strcmp (attribute_names [i], "wordsize") == 0 && !arch_matches (CONFIG_WORDSIZE, attribute_values [i]))
361 ignore = TRUE;
363 if (!dll)
364 dll = info->dll;
365 if (!info->ignore && !ignore)
366 mono_dllmap_insert (info->assembly, info->dll, name, dll, target);
370 static void
371 dllmap_finish (gpointer user_data)
373 DllInfo *info = (DllInfo *)user_data;
375 g_free (info->dll);
376 g_free (info->target);
377 g_free (info);
380 static const MonoParseHandler
381 dllmap_handler = {
382 "dllmap",
383 dllmap_init,
384 dllmap_start,
385 NULL, /* text */
386 NULL, /* end */
387 dllmap_finish
390 static void
391 legacyUEP_start (gpointer user_data,
392 const gchar *element_name,
393 const gchar **attribute_names,
394 const gchar **attribute_values) {
395 if ((strcmp (element_name, "legacyUnhandledExceptionPolicy") == 0) &&
396 (attribute_names [0] != NULL) &&
397 (strcmp (attribute_names [0], "enabled") == 0)) {
398 if ((strcmp (attribute_values [0], "1") == 0) ||
399 (g_ascii_strcasecmp (attribute_values [0], "true") == 0)) {
400 mono_runtime_unhandled_exception_policy_set (MONO_UNHANDLED_POLICY_LEGACY);
405 static const MonoParseHandler
406 legacyUEP_handler = {
407 "legacyUnhandledExceptionPolicy",
408 NULL, /* init */
409 legacyUEP_start,
410 NULL, /* text */
411 NULL, /* end */
412 NULL, /* finish */
415 static void
416 aot_cache_start (gpointer user_data,
417 const gchar *element_name,
418 const gchar **attribute_names,
419 const gchar **attribute_values)
421 int i;
422 MonoAotCacheConfig *config;
424 if (strcmp (element_name, "aotcache") != 0)
425 return;
427 config = mono_get_aot_cache_config ();
429 /* Per-app configuration */
430 for (i = 0; attribute_names [i]; ++i) {
431 if (!strcmp (attribute_names [i], "app")) {
432 config->apps = g_slist_prepend (config->apps, g_strdup (attribute_values [i]));
436 /* Global configuration */
437 for (i = 0; attribute_names [i]; ++i) {
438 if (!strcmp (attribute_names [i], "assemblies")) {
439 char **parts, **ptr;
440 char *part;
442 parts = g_strsplit (attribute_values [i], " ", -1);
443 for (ptr = parts; ptr && *ptr; ptr ++) {
444 part = *ptr;
445 config->assemblies = g_slist_prepend (config->assemblies, g_strdup (part));
447 g_strfreev (parts);
448 } else if (!strcmp (attribute_names [i], "options")) {
449 config->aot_options = g_strdup (attribute_values [i]);
454 static const MonoParseHandler
455 aot_cache_handler = {
456 "aotcache",
457 NULL, /* init */
458 aot_cache_start,
459 NULL, /* text */
460 NULL, /* end */
461 NULL, /* finish */
464 static int inited = 0;
466 static void
467 mono_config_init (void)
469 inited = 1;
470 config_handlers = g_hash_table_new (g_str_hash, g_str_equal);
471 g_hash_table_insert (config_handlers, (gpointer) dllmap_handler.element_name, (gpointer) &dllmap_handler);
472 g_hash_table_insert (config_handlers, (gpointer) legacyUEP_handler.element_name, (gpointer) &legacyUEP_handler);
473 g_hash_table_insert (config_handlers, (gpointer) aot_cache_handler.element_name, (gpointer) &aot_cache_handler);
477 * mono_config_cleanup:
479 void
480 mono_config_cleanup (void)
482 if (config_handlers)
483 g_hash_table_destroy (config_handlers);
484 g_free (mono_cfg_dir);
487 /* FIXME: error handling */
489 static void
490 mono_config_parse_xml_with_context (MonoConfigParseState *state, const char *text, gsize len)
492 GMarkupParseContext *context;
494 if (!inited)
495 mono_config_init ();
497 context = g_markup_parse_context_new (&mono_parser, (GMarkupParseFlags)0, state, NULL);
498 if (g_markup_parse_context_parse (context, text, len, NULL)) {
499 g_markup_parse_context_end_parse (context, NULL);
501 g_markup_parse_context_free (context);
504 /* If assembly is NULL, parse in the global context */
505 static int
506 mono_config_parse_file_with_context (MonoConfigParseState *state, const char *filename)
508 gchar *text;
509 gsize len;
510 gint offset;
512 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_CONFIG,
513 "Config attempting to parse: '%s'.", filename);
515 if (!g_file_get_contents (filename, &text, &len, NULL))
516 return 0;
518 offset = 0;
519 if (len > 3 && text [0] == '\xef' && text [1] == (gchar) '\xbb' && text [2] == '\xbf')
520 offset = 3; /* Skip UTF-8 BOM */
521 if (state->user_data == NULL)
522 state->user_data = (gpointer) filename;
523 mono_config_parse_xml_with_context (state, text + offset, len - offset);
524 g_free (text);
525 return 1;
529 * mono_config_parse_memory:
530 * \param buffer a pointer to an string XML representation of the configuration
531 * Parses the configuration from a buffer
533 void
534 mono_config_parse_memory (const char *buffer)
536 MonoConfigParseState state = {NULL};
538 state.user_data = (gpointer) "<buffer>";
539 mono_config_parse_xml_with_context (&state, buffer, strlen (buffer));
542 static void
543 mono_config_parse_file (const char *filename)
545 MonoConfigParseState state = {NULL};
546 state.user_data = (gpointer) filename;
547 mono_config_parse_file_with_context (&state, filename);
551 * use the equivalent lookup code from the GAC when available.
552 * Depending on state, this should give something like:
553 * aname/version-pubtoken/
554 * aname/version/
555 * aname
557 static char*
558 get_assembly_filename (MonoImage *image, int state)
560 switch (state) {
561 case 0:
562 return g_strdup (mono_image_get_name (image));
563 default:
564 return NULL;
568 typedef struct _BundledConfig BundledConfig;
570 struct _BundledConfig {
571 BundledConfig *next;
572 const char* aname;
573 const char* config_xml;
576 static BundledConfig *bundled_configs = NULL;
578 static const char *bundled_machine_config = NULL;
581 * mono_register_config_for_assembly:
583 void
584 mono_register_config_for_assembly (const char* assembly_name, const char* config_xml)
586 BundledConfig *bconfig;
588 bconfig = g_new0 (BundledConfig, 1);
589 bconfig->aname = assembly_name;
590 bconfig->config_xml = config_xml;
591 bconfig->next = bundled_configs;
592 bundled_configs = bconfig;
596 * mono_config_string_for_assembly_file:
598 const char *
599 mono_config_string_for_assembly_file (const char *filename)
601 BundledConfig *bconfig;
603 for (bconfig = bundled_configs; bconfig; bconfig = bconfig->next) {
604 if (bconfig->aname && strcmp (bconfig->aname, filename) == 0)
605 return bconfig->config_xml;
607 return NULL;
610 void
611 mono_config_for_assembly_internal (MonoImage *assembly)
613 MONO_REQ_GC_UNSAFE_MODE;
615 MonoConfigParseState state = {NULL};
616 int got_it = 0, i;
617 char *aname, *cfg, *cfg_name;
618 const char *bundled_config;
620 state.assembly = assembly;
622 bundled_config = mono_config_string_for_assembly_file (assembly->module_name);
623 if (bundled_config) {
624 state.user_data = (gpointer) "<bundled>";
625 mono_config_parse_xml_with_context (&state, bundled_config, strlen (bundled_config));
628 cfg_name = g_strdup_printf ("%s.config", mono_image_get_filename (assembly));
629 mono_config_parse_file_with_context (&state, cfg_name);
630 g_free (cfg_name);
632 cfg_name = g_strdup_printf ("%s.config", mono_image_get_name (assembly));
633 const char *cfg_dir = mono_get_config_dir ();
634 if (!cfg_dir) {
635 g_free (cfg_name);
636 return;
639 for (i = 0; (aname = get_assembly_filename (assembly, i)) != NULL; ++i) {
640 cfg = g_build_filename (cfg_dir, "mono", "assemblies", aname, cfg_name, NULL);
641 got_it += mono_config_parse_file_with_context (&state, cfg);
642 g_free (cfg);
644 #ifdef TARGET_WIN32
645 const char *home = g_get_home_dir ();
646 cfg = g_build_filename (home, ".mono", "assemblies", aname, cfg_name, NULL);
647 got_it += mono_config_parse_file_with_context (&state, cfg);
648 g_free (cfg);
649 #endif
650 g_free (aname);
651 if (got_it)
652 break;
654 g_free (cfg_name);
658 * mono_config_parse:
659 * \param filename the filename to load the configuration variables from.
660 * Pass a NULL filename to parse the default config files
661 * (or the file in the \c MONO_CONFIG env var).
663 void
664 mono_config_parse (const char *filename) {
665 const char *home;
666 char *mono_cfg;
667 #ifndef TARGET_WIN32
668 char *user_cfg;
669 #endif
671 if (filename) {
672 mono_config_parse_file (filename);
673 return;
676 // FIXME: leak, do we store any references to home
677 char *env_home = g_getenv ("MONO_CONFIG");
678 if (env_home) {
679 mono_config_parse_file (env_home);
680 return;
683 const char *cfg_dir = mono_get_config_dir ();
684 if (cfg_dir) {
685 mono_cfg = g_build_filename (cfg_dir, "mono", "config", NULL);
686 mono_config_parse_file (mono_cfg);
687 g_free (mono_cfg);
690 #if !defined(TARGET_WIN32)
691 home = g_get_home_dir ();
692 user_cfg = g_strconcat (home, G_DIR_SEPARATOR_S, ".mono/config", NULL);
693 mono_config_parse_file (user_cfg);
694 g_free (user_cfg);
695 #endif
699 * mono_set_config_dir:
700 * Invoked during startup
702 void
703 mono_set_config_dir (const char *dir)
705 /* If this environment variable is set, overrides the directory computed */
706 char *env_mono_cfg_dir = g_getenv ("MONO_CFG_DIR");
707 if (env_mono_cfg_dir == NULL && dir != NULL)
708 env_mono_cfg_dir = g_strdup (dir);
710 if (mono_cfg_dir)
711 g_free (mono_cfg_dir);
712 mono_cfg_dir = env_mono_cfg_dir;
716 * mono_get_config_dir:
718 const char*
719 mono_get_config_dir (void)
721 if (mono_cfg_dir == NULL)
722 mono_set_dirs (NULL, NULL);
724 return mono_cfg_dir;
728 * mono_register_machine_config:
730 void
731 mono_register_machine_config (const char *config_xml)
733 bundled_machine_config = config_xml;
737 * mono_get_machine_config:
739 const char *
740 mono_get_machine_config (void)
742 return bundled_machine_config;
745 static void
746 assembly_binding_end (gpointer user_data, const char *element_name)
748 ParserUserData *pud = (ParserUserData *)user_data;
750 if (!strcmp (element_name, "dependentAssembly")) {
751 if (pud->info_parsed && pud->info) {
752 pud->info_parsed (pud->info, pud->user_data);
753 g_free (pud->info->name);
754 g_free (pud->info->culture);
759 static void
760 publisher_policy_start (gpointer user_data,
761 const gchar *element_name,
762 const gchar **attribute_names,
763 const gchar **attribute_values)
765 ParserUserData *pud;
766 MonoAssemblyBindingInfo *info;
767 int n;
769 pud = (ParserUserData *)user_data;
770 info = pud->info;
771 if (!strcmp (element_name, "dependentAssembly")) {
772 info->name = NULL;
773 info->culture = NULL;
774 info->has_old_version_bottom = FALSE;
775 info->has_old_version_top = FALSE;
776 info->has_new_version = FALSE;
777 info->is_valid = FALSE;
778 memset (&info->old_version_bottom, 0, sizeof (info->old_version_bottom));
779 memset (&info->old_version_top, 0, sizeof (info->old_version_top));
780 memset (&info->new_version, 0, sizeof (info->new_version));
781 } else if (!strcmp (element_name, "assemblyIdentity")) {
782 for (n = 0; attribute_names [n]; n++) {
783 const gchar *attribute_name = attribute_names [n];
785 if (!strcmp (attribute_name, "name"))
786 info->name = g_strdup (attribute_values [n]);
787 else if (!strcmp (attribute_name, "publicKeyToken")) {
788 if (strlen (attribute_values [n]) == MONO_PUBLIC_KEY_TOKEN_LENGTH - 1)
789 g_strlcpy ((char *) info->public_key_token, attribute_values [n], MONO_PUBLIC_KEY_TOKEN_LENGTH);
790 } else if (!strcmp (attribute_name, "culture")) {
791 if (!strcmp (attribute_values [n], "neutral"))
792 info->culture = g_strdup ("");
793 else
794 info->culture = g_strdup (attribute_values [n]);
797 } else if (!strcmp (element_name, "bindingRedirect")) {
798 for (n = 0; attribute_names [n]; n++) {
799 const gchar *attribute_name = attribute_names [n];
801 if (!strcmp (attribute_name, "oldVersion")) {
802 gchar **numbers, **version, **versions;
803 gint major, minor, build, revision;
805 /* Invalid value */
806 if (!strcmp (attribute_values [n], ""))
807 return;
809 versions = g_strsplit (attribute_values [n], "-", 2);
810 version = g_strsplit (*versions, ".", 4);
812 /* We assign the values to gint vars to do the checks */
813 numbers = version;
814 major = *numbers ? atoi (*numbers++) : -1;
815 minor = *numbers ? atoi (*numbers++) : -1;
816 build = *numbers ? atoi (*numbers++) : -1;
817 revision = *numbers ? atoi (*numbers) : -1;
818 g_strfreev (version);
819 if (major < 0 || minor < 0 || build < 0 || revision < 0) {
820 g_strfreev (versions);
821 return;
824 info->old_version_bottom.major = major;
825 info->old_version_bottom.minor = minor;
826 info->old_version_bottom.build = build;
827 info->old_version_bottom.revision = revision;
828 info->has_old_version_bottom = TRUE;
830 if (!*(versions + 1)) {
831 g_strfreev (versions);
832 continue;
835 numbers = version = g_strsplit (*(versions + 1), ".", 4);
836 major = *numbers ? atoi (*numbers++) : -1;
837 minor = *numbers ? atoi (*numbers++) : -1;
838 build = *numbers ? atoi (*numbers++) : -1;
839 revision = *numbers ? atoi (*numbers) : 1;
840 g_strfreev (version);
841 if (major < 0 || minor < 0 || build < 0 || revision < 0) {
842 g_strfreev (versions);
843 return;
846 info->old_version_top.major = major;
847 info->old_version_top.minor = minor;
848 info->old_version_top.build = build;
849 info->old_version_top.revision = revision;
850 info->has_old_version_top = TRUE;
852 g_strfreev (versions);
853 } else if (!strcmp (attribute_name, "newVersion")) {
854 gchar **numbers, **version;
856 /* Invalid value */
857 if (!strcmp (attribute_values [n], ""))
858 return;
860 numbers = version = g_strsplit (attribute_values [n], ".", 4);
861 info->new_version.major = *numbers ? atoi (*numbers++) : -1;
862 info->new_version.minor = *numbers ? atoi (*numbers++) : -1;
863 info->new_version.build = *numbers ? atoi (*numbers++) : -1;
864 info->new_version.revision = *numbers ? atoi (*numbers) : -1;
865 info->has_new_version = TRUE;
866 g_strfreev (version);
872 static MonoParseHandler
873 publisher_policy_parser = {
874 "", /* We don't need to use declare an xml element */
875 NULL,
876 publisher_policy_start,
877 NULL,
878 NULL,
879 NULL
882 void
883 mono_config_parse_publisher_policy (const gchar *filename, MonoAssemblyBindingInfo *info)
885 ParserUserData user_data = {
886 info,
887 NULL,
888 NULL
890 MonoConfigParseState state = {
891 &publisher_policy_parser, /* MonoParseHandler */
892 &user_data, /* user_data */
893 NULL, /* MonoImage (we don't need it right now)*/
894 TRUE /* We are already inited */
897 mono_config_parse_file_with_context (&state, filename);
900 static MonoParseHandler
901 config_assemblybinding_parser = {
902 "", /* We don't need to use declare an xml element */
903 NULL,
904 publisher_policy_start,
905 NULL,
906 assembly_binding_end,
907 NULL
910 void
911 mono_config_parse_assembly_bindings (const char *filename, int amajor, int aminor, void *user_data, void (*infocb)(MonoAssemblyBindingInfo *info, void *user_data))
913 MonoAssemblyBindingInfo info;
914 ParserUserData pud;
915 MonoConfigParseState state;
917 info.major = amajor;
918 info.minor = aminor;
920 pud.info = &info;
921 pud.info_parsed = infocb;
922 pud.user_data = user_data;
924 state.current = &config_assemblybinding_parser; /* MonoParseHandler */
925 state.user_data = &pud;
926 state.assembly = NULL; /* MonoImage (we don't need it right now)*/
927 state.inited = TRUE; /* We are already inited */
929 mono_config_parse_file_with_context (&state, filename);
932 static mono_bool mono_server_mode = FALSE;
935 * mono_config_set_server_mode:
937 void
938 mono_config_set_server_mode (mono_bool server_mode)
940 mono_server_mode = server_mode;
944 * mono_config_is_server_mode:
946 mono_bool
947 mono_config_is_server_mode (void)
949 return mono_server_mode;