xref: /haiku/src/build/libbe/support/Archivable.cpp (revision 338b8dc301721b1f472e8297a898d4eaa2f2ee3a)
1*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
2*338b8dc3SIngo Weinhold //	Copyright (c) 2001-2002, OpenBeOS
3*338b8dc3SIngo Weinhold //
4*338b8dc3SIngo Weinhold //	Permission is hereby granted, free of charge, to any person obtaining a
5*338b8dc3SIngo Weinhold //	copy of this software and associated documentation files (the "Software"),
6*338b8dc3SIngo Weinhold //	to deal in the Software without restriction, including without limitation
7*338b8dc3SIngo Weinhold //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*338b8dc3SIngo Weinhold //	and/or sell copies of the Software, and to permit persons to whom the
9*338b8dc3SIngo Weinhold //	Software is furnished to do so, subject to the following conditions:
10*338b8dc3SIngo Weinhold //
11*338b8dc3SIngo Weinhold //	The above copyright notice and this permission notice shall be included in
12*338b8dc3SIngo Weinhold //	all copies or substantial portions of the Software.
13*338b8dc3SIngo Weinhold //
14*338b8dc3SIngo Weinhold //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*338b8dc3SIngo Weinhold //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*338b8dc3SIngo Weinhold //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17*338b8dc3SIngo Weinhold //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18*338b8dc3SIngo Weinhold //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19*338b8dc3SIngo Weinhold //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20*338b8dc3SIngo Weinhold //	DEALINGS IN THE SOFTWARE.
21*338b8dc3SIngo Weinhold //
22*338b8dc3SIngo Weinhold //	File Name:		Archivable.cpp
23*338b8dc3SIngo Weinhold //	Author:			Erik Jaesler (erik@cgsoftware.com)
24*338b8dc3SIngo Weinhold //	Description:	BArchivable mix-in class defines the archiving
25*338b8dc3SIngo Weinhold //					protocol.  Also some global archiving functions.
26*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
27*338b8dc3SIngo Weinhold 
28*338b8dc3SIngo Weinhold // Standard Includes -----------------------------------------------------------
29*338b8dc3SIngo Weinhold #include <ctype.h>
30*338b8dc3SIngo Weinhold #include <errno.h>
31*338b8dc3SIngo Weinhold #include <stdlib.h>
32*338b8dc3SIngo Weinhold #include <stdio.h>
33*338b8dc3SIngo Weinhold #include <string>
34*338b8dc3SIngo Weinhold #include <typeinfo>
35*338b8dc3SIngo Weinhold #include <vector>
36*338b8dc3SIngo Weinhold 
37*338b8dc3SIngo Weinhold // System Includes -------------------------------------------------------------
38*338b8dc3SIngo Weinhold #include <AppFileInfo.h>
39*338b8dc3SIngo Weinhold #include <Archivable.h>
40*338b8dc3SIngo Weinhold #include <Entry.h>
41*338b8dc3SIngo Weinhold #include <List.h>
42*338b8dc3SIngo Weinhold #include <OS.h>
43*338b8dc3SIngo Weinhold #include <Path.h>
44*338b8dc3SIngo Weinhold //#include <Roster.h>
45*338b8dc3SIngo Weinhold #include <String.h>
46*338b8dc3SIngo Weinhold #include <SupportDefs.h>
47*338b8dc3SIngo Weinhold #include <syslog.h>
48*338b8dc3SIngo Weinhold 
49*338b8dc3SIngo Weinhold // Project Includes ------------------------------------------------------------
50*338b8dc3SIngo Weinhold 
51*338b8dc3SIngo Weinhold // Local Includes --------------------------------------------------------------
52*338b8dc3SIngo Weinhold 
53*338b8dc3SIngo Weinhold // Local Defines ---------------------------------------------------------------
54*338b8dc3SIngo Weinhold 
55*338b8dc3SIngo Weinhold // Globals ---------------------------------------------------------------------
56*338b8dc3SIngo Weinhold 
57*338b8dc3SIngo Weinhold 
58*338b8dc3SIngo Weinhold using std::string;
59*338b8dc3SIngo Weinhold using std::vector;
60*338b8dc3SIngo Weinhold 
61*338b8dc3SIngo Weinhold const char* B_CLASS_FIELD = "class";
62*338b8dc3SIngo Weinhold const char* B_ADD_ON_FIELD = "add_on";
63*338b8dc3SIngo Weinhold const int32 FUNC_NAME_LEN = 1024;
64*338b8dc3SIngo Weinhold 
65*338b8dc3SIngo Weinhold // TODO: consider moving these
66*338b8dc3SIngo Weinhold //		 to a separate module, and making them more full-featured (e.g., taking
67*338b8dc3SIngo Weinhold //		 NS::ClassName::Function(Param p) instead of just NS::ClassName)
68*338b8dc3SIngo Weinhold static void Demangle(const char *name, BString &out);
69*338b8dc3SIngo Weinhold static void Mangle(const char *name, BString &out);
70*338b8dc3SIngo Weinhold // static instantiation_func FindFuncInImage(BString& funcName, image_id id,
71*338b8dc3SIngo Weinhold // 										  status_t& err);
72*338b8dc3SIngo Weinhold // static bool CheckSig(const char* sig, image_info& info);
73*338b8dc3SIngo Weinhold 
74*338b8dc3SIngo Weinhold /*
75*338b8dc3SIngo Weinhold // TODO: Where do these get triggered from?
76*338b8dc3SIngo Weinhold Log entries graciously coughed up by the Be implementation:
77*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: NULL BMessage argument
78*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Failed to find an entrydefining the class name (Name not found).
79*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: No signature specified in archive, looking for class "TInvalidClassName".
80*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
81*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
82*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Failed to find exported Instantiate static function for class TInvalidClassName.
83*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Invalid argument (80000005)
84*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: No signature specified in archive, looking for class "TRemoteTestObject".
85*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object - couldn't get mime sig for /boot/home/src/projects/OpenBeOS/app_kit/test/lib/support/BArchivable/./BArchivableSystemTester
86*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
87*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
88*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
89*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
90*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
91*338b8dc3SIngo Weinhold 	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
92*338b8dc3SIngo Weinhold */
93*338b8dc3SIngo Weinhold 
94*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
95*338b8dc3SIngo Weinhold BArchivable::BArchivable()
96*338b8dc3SIngo Weinhold {
97*338b8dc3SIngo Weinhold 	;
98*338b8dc3SIngo Weinhold }
99*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
100*338b8dc3SIngo Weinhold BArchivable::BArchivable(BMessage* from)
101*338b8dc3SIngo Weinhold {
102*338b8dc3SIngo Weinhold 	;
103*338b8dc3SIngo Weinhold }
104*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
105*338b8dc3SIngo Weinhold BArchivable::~BArchivable()
106*338b8dc3SIngo Weinhold {
107*338b8dc3SIngo Weinhold 	;
108*338b8dc3SIngo Weinhold }
109*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
110*338b8dc3SIngo Weinhold status_t BArchivable::Archive(BMessage* into, bool deep) const
111*338b8dc3SIngo Weinhold {
112*338b8dc3SIngo Weinhold 	if (!into)
113*338b8dc3SIngo Weinhold 	{
114*338b8dc3SIngo Weinhold 		// TODO: logging/other error reporting?
115*338b8dc3SIngo Weinhold 		return B_BAD_VALUE;
116*338b8dc3SIngo Weinhold 	}
117*338b8dc3SIngo Weinhold 
118*338b8dc3SIngo Weinhold 	BString name;
119*338b8dc3SIngo Weinhold 	Demangle(typeid(*this).name(), name);
120*338b8dc3SIngo Weinhold 
121*338b8dc3SIngo Weinhold 	return into->AddString(B_CLASS_FIELD, name);
122*338b8dc3SIngo Weinhold }
123*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
124*338b8dc3SIngo Weinhold BArchivable* BArchivable::Instantiate(BMessage* from)
125*338b8dc3SIngo Weinhold {
126*338b8dc3SIngo Weinhold 	debugger("Can't create a plain BArchivable object");
127*338b8dc3SIngo Weinhold 	return NULL;
128*338b8dc3SIngo Weinhold }
129*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
130*338b8dc3SIngo Weinhold status_t BArchivable::Perform(perform_code d, void* arg)
131*338b8dc3SIngo Weinhold {
132*338b8dc3SIngo Weinhold 	// TODO: Check against original
133*338b8dc3SIngo Weinhold 	return B_ERROR;
134*338b8dc3SIngo Weinhold }
135*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
136*338b8dc3SIngo Weinhold void BArchivable::_ReservedArchivable1()
137*338b8dc3SIngo Weinhold {
138*338b8dc3SIngo Weinhold 	;
139*338b8dc3SIngo Weinhold }
140*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
141*338b8dc3SIngo Weinhold void BArchivable::_ReservedArchivable2()
142*338b8dc3SIngo Weinhold {
143*338b8dc3SIngo Weinhold 	;
144*338b8dc3SIngo Weinhold }
145*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
146*338b8dc3SIngo Weinhold void BArchivable::_ReservedArchivable3()
147*338b8dc3SIngo Weinhold {
148*338b8dc3SIngo Weinhold 	;
149*338b8dc3SIngo Weinhold }
150*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
151*338b8dc3SIngo Weinhold void BuildFuncName(const char* className, BString& funcName)
152*338b8dc3SIngo Weinhold {
153*338b8dc3SIngo Weinhold 	funcName = "";
154*338b8dc3SIngo Weinhold 
155*338b8dc3SIngo Weinhold 	//	This is what we're after:
156*338b8dc3SIngo Weinhold 	//		Instantiate__Q28OpenBeOS11BArchivableP8BMessage
157*338b8dc3SIngo Weinhold 	Mangle(className, funcName);
158*338b8dc3SIngo Weinhold 	funcName.Prepend("Instantiate__");
159*338b8dc3SIngo Weinhold 	funcName.Append("P8BMessage");
160*338b8dc3SIngo Weinhold }
161*338b8dc3SIngo Weinhold 
162*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
163*338b8dc3SIngo Weinhold bool validate_instantiation(BMessage* from, const char* class_name)
164*338b8dc3SIngo Weinhold {
165*338b8dc3SIngo Weinhold 	errno = B_OK;
166*338b8dc3SIngo Weinhold 
167*338b8dc3SIngo Weinhold 	// Make sure our params are kosher -- original skimped here =P
168*338b8dc3SIngo Weinhold 	if (!from)
169*338b8dc3SIngo Weinhold 	{
170*338b8dc3SIngo Weinhold 		// Not standard; Be implementation has a segment
171*338b8dc3SIngo Weinhold 		// violation on this error mode
172*338b8dc3SIngo Weinhold 		errno = B_BAD_VALUE;
173*338b8dc3SIngo Weinhold 
174*338b8dc3SIngo Weinhold 		return false;
175*338b8dc3SIngo Weinhold 	}
176*338b8dc3SIngo Weinhold 
177*338b8dc3SIngo Weinhold 	status_t err = B_OK;
178*338b8dc3SIngo Weinhold 	const char* data;
179*338b8dc3SIngo Weinhold 	for (int32 index = 0; err == B_OK; ++index)
180*338b8dc3SIngo Weinhold 	{
181*338b8dc3SIngo Weinhold 		err = from->FindString(B_CLASS_FIELD, index, &data);
182*338b8dc3SIngo Weinhold 		if (!err && strcmp(data, class_name) == 0)
183*338b8dc3SIngo Weinhold 		{
184*338b8dc3SIngo Weinhold 			return true;
185*338b8dc3SIngo Weinhold 		}
186*338b8dc3SIngo Weinhold 	}
187*338b8dc3SIngo Weinhold 
188*338b8dc3SIngo Weinhold 	errno = B_MISMATCHED_VALUES;
189*338b8dc3SIngo Weinhold 	syslog(LOG_ERR, "validate_instantiation failed on class %s.", class_name);
190*338b8dc3SIngo Weinhold 
191*338b8dc3SIngo Weinhold 	return false;
192*338b8dc3SIngo Weinhold }
193*338b8dc3SIngo Weinhold 
194*338b8dc3SIngo Weinhold 
195*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
196*338b8dc3SIngo Weinhold int GetNumber(const char*& name)
197*338b8dc3SIngo Weinhold {
198*338b8dc3SIngo Weinhold 	int val = atoi(name);
199*338b8dc3SIngo Weinhold 	while (isdigit(*name))
200*338b8dc3SIngo Weinhold 	{
201*338b8dc3SIngo Weinhold 		++name;
202*338b8dc3SIngo Weinhold 	}
203*338b8dc3SIngo Weinhold 
204*338b8dc3SIngo Weinhold 	return val;
205*338b8dc3SIngo Weinhold }
206*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
207*338b8dc3SIngo Weinhold void Demangle(const char* name, BString& out)
208*338b8dc3SIngo Weinhold {
209*338b8dc3SIngo Weinhold // TODO: add support for template classes
210*338b8dc3SIngo Weinhold //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
211*338b8dc3SIngo Weinhold 
212*338b8dc3SIngo Weinhold 	out = "";
213*338b8dc3SIngo Weinhold 
214*338b8dc3SIngo Weinhold 	// Are we in a namespace?
215*338b8dc3SIngo Weinhold 	if (*name == 'Q')
216*338b8dc3SIngo Weinhold 	{
217*338b8dc3SIngo Weinhold 		// Yessir, we are; how many deep are we?
218*338b8dc3SIngo Weinhold 		int nsCount = 0;
219*338b8dc3SIngo Weinhold 		++name;
220*338b8dc3SIngo Weinhold 		if (*name == '_')	// more than 10 deep
221*338b8dc3SIngo Weinhold 		{
222*338b8dc3SIngo Weinhold 			++name;
223*338b8dc3SIngo Weinhold 			if (!isdigit(*name))
224*338b8dc3SIngo Weinhold 				;	// TODO: error handling
225*338b8dc3SIngo Weinhold 
226*338b8dc3SIngo Weinhold 			nsCount = GetNumber(name);
227*338b8dc3SIngo Weinhold 			if (*name == '_')	// more than 10 deep
228*338b8dc3SIngo Weinhold 				++name;
229*338b8dc3SIngo Weinhold 			else
230*338b8dc3SIngo Weinhold 				;	// this should be an error condition
231*338b8dc3SIngo Weinhold 		}
232*338b8dc3SIngo Weinhold 		else
233*338b8dc3SIngo Weinhold 		{
234*338b8dc3SIngo Weinhold 			nsCount = *name - '0';
235*338b8dc3SIngo Weinhold 			++name;
236*338b8dc3SIngo Weinhold 		}
237*338b8dc3SIngo Weinhold 
238*338b8dc3SIngo Weinhold 		int nameLen = 0;
239*338b8dc3SIngo Weinhold 		for (int i = 0; i < nsCount - 1; ++i)
240*338b8dc3SIngo Weinhold 		{
241*338b8dc3SIngo Weinhold 			if (!isdigit(*name))
242*338b8dc3SIngo Weinhold 				;	// TODO: error handling
243*338b8dc3SIngo Weinhold 
244*338b8dc3SIngo Weinhold 			nameLen = GetNumber(name);
245*338b8dc3SIngo Weinhold 			out.Append(name, nameLen);
246*338b8dc3SIngo Weinhold 			out += "::";
247*338b8dc3SIngo Weinhold 			name += nameLen;
248*338b8dc3SIngo Weinhold 		}
249*338b8dc3SIngo Weinhold 	}
250*338b8dc3SIngo Weinhold 
251*338b8dc3SIngo Weinhold 	out.Append(name, GetNumber(name));
252*338b8dc3SIngo Weinhold }
253*338b8dc3SIngo Weinhold //------------------------------------------------------------------------------
254*338b8dc3SIngo Weinhold void Mangle(const char* name, BString& out)
255*338b8dc3SIngo Weinhold {
256*338b8dc3SIngo Weinhold // TODO: add support for template classes
257*338b8dc3SIngo Weinhold //	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
258*338b8dc3SIngo Weinhold 
259*338b8dc3SIngo Weinhold 	//	Chop this:
260*338b8dc3SIngo Weinhold 	//		testthree::testfour::Testthree::Testfour
261*338b8dc3SIngo Weinhold 	//	up into little bite-sized pieces
262*338b8dc3SIngo Weinhold 	int count = 0;
263*338b8dc3SIngo Weinhold 	string origName(name);
264*338b8dc3SIngo Weinhold 	vector<string> spacenames;
265*338b8dc3SIngo Weinhold 
266*338b8dc3SIngo Weinhold 	string::size_type pos = 0;
267*338b8dc3SIngo Weinhold 	string::size_type oldpos = 0;
268*338b8dc3SIngo Weinhold 	while (pos != string::npos)
269*338b8dc3SIngo Weinhold 	{
270*338b8dc3SIngo Weinhold 		pos = origName.find_first_of("::", oldpos);
271*338b8dc3SIngo Weinhold 		spacenames.push_back(string(origName, oldpos, pos - oldpos));
272*338b8dc3SIngo Weinhold 		pos = origName.find_first_not_of("::", pos);
273*338b8dc3SIngo Weinhold 		oldpos = pos;
274*338b8dc3SIngo Weinhold 		++count;
275*338b8dc3SIngo Weinhold 	}
276*338b8dc3SIngo Weinhold 
277*338b8dc3SIngo Weinhold 	//	Now mangle it into this:
278*338b8dc3SIngo Weinhold 	//		Q49testthree8testfour9Testthree8Testfour
279*338b8dc3SIngo Weinhold 	out = "";
280*338b8dc3SIngo Weinhold 	if (count > 1)
281*338b8dc3SIngo Weinhold 	{
282*338b8dc3SIngo Weinhold 		out += 'Q';
283*338b8dc3SIngo Weinhold 		if (count > 10)
284*338b8dc3SIngo Weinhold 			out += '_';
285*338b8dc3SIngo Weinhold 		out << count;
286*338b8dc3SIngo Weinhold 		if (count > 10)
287*338b8dc3SIngo Weinhold 			out += '_';
288*338b8dc3SIngo Weinhold 	}
289*338b8dc3SIngo Weinhold 
290*338b8dc3SIngo Weinhold 	for (unsigned int i = 0; i < spacenames.size(); ++i)
291*338b8dc3SIngo Weinhold 	{
292*338b8dc3SIngo Weinhold 		out << (int)spacenames[i].length();
293*338b8dc3SIngo Weinhold 		out += spacenames[i].c_str();
294*338b8dc3SIngo Weinhold 	}
295*338b8dc3SIngo Weinhold }
296*338b8dc3SIngo Weinhold 
297*338b8dc3SIngo Weinhold 
298*338b8dc3SIngo Weinhold /*
299*338b8dc3SIngo Weinhold  * $Log $
300*338b8dc3SIngo Weinhold  *
301*338b8dc3SIngo Weinhold  * $Id  $
302*338b8dc3SIngo Weinhold  *
303*338b8dc3SIngo Weinhold  */
304*338b8dc3SIngo Weinhold 
305