1/*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <architecture_private.h>
8
9#include <stdio.h>
10#include <string.h>
11#include <sys/stat.h>
12
13#include <OS.h>
14
15#include <directories.h>
16#include <find_directory_private.h>
17#include <runtime_loader.h>
18
19
20static const char* const kArchitecture = B_HAIKU_ABI_NAME;
21static const char* const kPrimaryArchitecture = __HAIKU_PRIMARY_PACKAGING_ARCH;
22
23#ifdef __HAIKU_ARCH_X86
24	static const char* const kSiblingArchitectures[] = {"x86_gcc2", "x86"};
25#else
26	static const char* const kSiblingArchitectures[] = {};
27#endif
28
29static const size_t kSiblingArchitectureCount
30	= sizeof(kSiblingArchitectures) / sizeof(const char*);
31
32
33static bool
34has_secondary_architecture(const char* architecture)
35{
36	if (strcmp(architecture, kPrimaryArchitecture) == 0)
37		return false;
38
39	char path[B_PATH_NAME_LENGTH];
40	snprintf(path, sizeof(path), kSystemLibDirectory "/%s/libroot.so",
41		architecture);
42
43	struct stat st;
44	return lstat(path, &st) == 0;
45}
46
47
48// #pragma mark -
49
50
51const char*
52__get_architecture()
53{
54	return kArchitecture;
55}
56
57
58const char*
59__get_primary_architecture()
60{
61	return kPrimaryArchitecture;
62}
63
64
65size_t
66__get_secondary_architectures(const char** architectures, size_t count)
67{
68	size_t index = 0;
69
70	// If this is an architecture that could be a primary or secondary
71	// architecture, check for which architectures a libroot.so is present.
72	if (kSiblingArchitectureCount > 0) {
73		for (size_t i = 0; i < kSiblingArchitectureCount; i++) {
74			const char* architecture = kSiblingArchitectures[i];
75			if (!has_secondary_architecture(architecture))
76				continue;
77
78			if (index < count)
79				architectures[index] = architecture;
80			index++;
81		}
82	}
83
84	return index;
85}
86
87
88size_t
89__get_architectures(const char** architectures, size_t count)
90{
91	if (count == 0)
92		return __get_secondary_architectures(NULL, 0) + 1;
93
94	architectures[0] = __get_primary_architecture();
95	return __get_secondary_architectures(architectures + 1, count -1) + 1;
96}
97
98
99const char*
100__guess_architecture_for_path(const char* path)
101{
102	if (kSiblingArchitectureCount == 0)
103		return kPrimaryArchitecture;
104
105	// ask the runtime loader
106	const char* architecture;
107	if (__gRuntimeLoader->get_executable_architecture(path, &architecture)
108			== B_OK) {
109		// verify that it is one of the sibling architectures
110		for (size_t i = 0; i < kSiblingArchitectureCount; i++) {
111			if (strcmp(architecture, kSiblingArchitectures[i]) == 0)
112				return kSiblingArchitectures[i];
113		}
114	}
115
116	// guess from the given path
117	architecture = __guess_secondary_architecture_from_path(path,
118		kSiblingArchitectures, kSiblingArchitectureCount);
119
120	return architecture != NULL && has_secondary_architecture(architecture)
121		? architecture : kPrimaryArchitecture;
122}
123
124
125B_DEFINE_WEAK_ALIAS(__get_architecture, get_architecture);
126B_DEFINE_WEAK_ALIAS(__get_primary_architecture, get_primary_architecture);
127B_DEFINE_WEAK_ALIAS(__get_secondary_architectures, get_secondary_architectures);
128B_DEFINE_WEAK_ALIAS(__get_architectures, get_architectures);
129B_DEFINE_WEAK_ALIAS(__guess_architecture_for_path, guess_architecture_for_path);
130