1 /**
2 * Copyright(c) 2011 Trusted Logic. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name Trusted Logic nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <string.h>
36
37 #if defined(_WIN32_WCE)
38 #include "os_wm.h"
39 #else
40 #include <errno.h>
41 #endif
42
43 #include "smc_properties_parser.h"
44 #include "lib_manifest2.h"
45 #include "s_error.h"
46
47 /* ---------------------------------------------------------------------------------
48 Defines
49 ---------------------------------------------------------------------------------*/
50
51 #define STRUE "true"
52 #define SFALSE "false"
53
54 #if defined(_WIN32_WCE)
55 #define GET_LAST_ERR GetLastError()
56 #else
57 #define GET_LAST_ERR errno
58 #endif
59
60 #if defined (LINUX) || defined (__SYMBIAN32__) || defined (__ANDROID32__)
61 #define STRICMP strcasecmp
62 #elif defined(_WIN32_WCE)
63 #define STRICMP _stricmp
64 #else
65 #define STRICMP stricmp
66 #endif
67
68
69 /* ---------------------------------------------------------------------------------
70 Logs and Traces.
71 ---------------------------------------------------------------------------------*/
72 #ifdef __SYMBIAN32__
73 #include "os_symbian.h"
74 #elif NDEBUG
75 /* Compile-out the traces */
76 #define TRACE_ERROR(...)
77 #define TRACE_WARNING(...)
78 #define TRACE_INFO(...)
79 #else
80 #include <stdarg.h>
TRACE_ERROR(const char * format,...)81 static void TRACE_ERROR(const char* format, ...)
82 {
83 va_list ap;
84 va_start(ap, format);
85 fprintf(stderr, "TRACE: ERROR: ");
86 vfprintf(stderr, format, ap);
87 fprintf(stderr, "\n");
88 va_end(ap);
89 }
90
TRACE_WARNING(const char * format,...)91 static void TRACE_WARNING(const char* format, ...)
92 {
93 va_list ap;
94 va_start(ap, format);
95 fprintf(stderr, "TRACE: WARNING: ");
96 vfprintf(stderr, format, ap);
97 fprintf(stderr, "\n");
98 va_end(ap);
99 }
100
TRACE_INFO(const char * format,...)101 static void TRACE_INFO(const char* format, ...)
102 {
103 va_list ap;
104 va_start(ap, format);
105 fprintf(stderr, "TRACE: ");
106 vfprintf(stderr, format, ap);
107 fprintf(stderr, "\n");
108 va_end(ap);
109 }
110 #endif /* NDEBUG */
111
112 /* ---------------------------------------------------------------------------------
113 private functions.
114 ---------------------------------------------------------------------------------*/
115
static_listFindNodeElement(NODE * pList,char * pName,bool bIsCaseSensitive)116 static NODE* static_listFindNodeElement(NODE* pList,char* pName,bool bIsCaseSensitive)
117 {
118 int32_t nCmp;
119
120 assert(pName!=NULL);
121
122 while (pList!=NULL)
123 {
124 if (bIsCaseSensitive)
125 {
126 nCmp=strcmp(pName,pList->pName);
127 }
128 else
129 {
130 nCmp=STRICMP(pName,pList->pName);
131 }
132 if (nCmp>0)
133 {
134 pList=pList->pRight;
135 }
136 else if (nCmp<0)
137 {
138 pList=pList->pLeft;
139 }
140 else
141 {
142 break;
143 }
144 }
145 return pList;
146 }
147
148
static_listSortedAddNode(NODE * pList,NODE * pNode)149 static S_RESULT static_listSortedAddNode(NODE* pList,NODE* pNode)
150 {
151 int32_t nCmp;
152
153 do {
154 nCmp=strcmp(pNode->pName,pList->pName);
155 if (nCmp>0)
156 {
157 if (pList->pRight!=NULL)
158 {
159 pList=pList->pRight;
160 }
161 else
162 {
163 pList->pRight=pNode;
164 /* update linked list */
165 pNode->pPrevious=pList;
166 pNode->pNext=pList->pNext;
167 if (pList->pNext!=NULL)
168 {
169 pList->pNext->pPrevious=pNode;
170 }
171 pList->pNext=pNode;
172 return S_SUCCESS;
173 }
174 }
175 else if (nCmp<0)
176 {
177 if (pList->pLeft!=NULL)
178 {
179 pList=pList->pLeft;
180 }
181 else
182 {
183 pList->pLeft=pNode;
184 /* update linked list */
185 pNode->pNext=pList;
186 pNode->pPrevious=pList->pPrevious;
187 if (pList->pPrevious!=NULL)
188 {
189 pList->pPrevious->pNext=pNode;
190 }
191 pList->pPrevious=pNode;
192 return S_SUCCESS;
193 }
194 }
195 } while (nCmp!=0);
196
197 TRACE_ERROR("%s already exist !\n",pNode->pName);
198 return S_ERROR_ITEM_EXISTS;
199 }
200
201
SMCPropListSortedAdd(LIST * pList,NODE * pNode)202 static S_RESULT SMCPropListSortedAdd(LIST* pList,NODE* pNode)
203 {
204 S_RESULT nResult;
205
206 assert(pList!=NULL && pNode!=NULL);
207
208 if (pNode->pName==NULL)
209 {
210 TRACE_ERROR("Trying to insert a NULL node name !\n");
211 return S_ERROR_BAD_PARAMETERS;
212 }
213
214 if (pList->pRoot==NULL)
215 {
216 pList->pRoot=pNode;
217 pList->pFirst=pNode;
218 return S_SUCCESS;
219 }
220 else
221 {
222 nResult=static_listSortedAddNode(pList->pRoot,pNode);
223 /* update the first node of the linked list */
224 if (nResult==S_SUCCESS && pNode->pPrevious==NULL)
225 {
226 pList->pFirst=pNode;
227 }
228 }
229 return nResult;
230 }
231
232
SMCPropListFindElement(LIST * pList,char * pName,bool bIsCaseSensitive)233 static NODE* SMCPropListFindElement(LIST* pList,char* pName,bool bIsCaseSensitive)
234 {
235 if (pList->pRoot!=NULL)
236 {
237 return static_listFindNodeElement(pList->pRoot,pName,bIsCaseSensitive);
238 }
239 return NULL;
240 }
241
242
SMCPropYacc(uint8_t * pBuffer,uint32_t nBufferLength,CONF_FILE * pConfFile)243 static S_RESULT SMCPropYacc(uint8_t* pBuffer, uint32_t nBufferLength,
244 CONF_FILE* pConfFile)
245 {
246 S_RESULT nError=S_SUCCESS;
247 LIST *pPublicPropertyList=NULL;
248 LIST *pPrivatePropertyList=NULL;
249 PROPERTY* pProperty=NULL;
250 SERVICE_SECTION* pServSection;
251 SERVICE_SECTION* pPreviousService=NULL;
252
253 uint8_t* pName;
254 uint32_t nNameLength;
255 uint8_t* pValue;
256 uint32_t nValueLength;
257 char* pNameZ = NULL;
258 char* pValueZ = NULL;
259 LIB_MANIFEST2_CONTEXT sParserContext;
260 char serviceManifestName[1024];
261
262 sParserContext.pManifestName = "Configuration File";
263 sParserContext.pManifestContent = pBuffer;
264 sParserContext.nManifestLength = nBufferLength;
265 sParserContext.nType = LIB_MANIFEST2_TYPE_SOURCE_WITH_SECTIONS;
266
267 libManifest2InitContext(&sParserContext);
268
269 while (true)
270 {
271 nError = libManifest2GetNextItem(
272 &sParserContext,
273 &pName,
274 &nNameLength,
275 &pValue,
276 &nValueLength);
277 if (nError == S_ERROR_ITEM_NOT_FOUND)
278 {
279 /* End of parsing */
280 nError = S_SUCCESS;
281 break;
282 }
283 else if (nError != S_SUCCESS)
284 {
285 /* Error */
286 goto error;
287 }
288
289 /* Duplicate name and value in as zero-terminated strings */
290 /* Unclean: those strings are not going to be deallocated
291 This is not a problem because this code is run in a tool
292 */
293 pNameZ = malloc(nNameLength+1);
294 if (pNameZ == NULL)
295 {
296 nError = S_ERROR_OUT_OF_MEMORY;
297 goto error;
298 }
299 memcpy(pNameZ, pName, nNameLength);
300 pNameZ[nNameLength] = 0;
301
302 if (pValue == NULL)
303 {
304 /* It's a section */
305 if (STRICMP(pNameZ, SYSTEM_SECTION_NAME) == 0)
306 {
307 free(pNameZ);
308 pPublicPropertyList=&pConfFile->sSystemSectionPropertyList;
309 }
310 else
311 {
312 pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
313 &pConfFile->sDriverSectionList,
314 pNameZ,
315 false);
316 if (pServSection==NULL)
317 {
318 pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
319 &pConfFile->sPreinstalledSectionList,
320 pNameZ,
321 false);
322 }
323 if (pServSection==NULL)
324 {
325 pServSection=(SERVICE_SECTION*)SMCPropListFindElement(
326 &pConfFile->sSectionList,
327 pNameZ,
328 false);
329 if (pServSection==NULL)
330 {
331 nError=S_ERROR_ITEM_NOT_FOUND;
332 goto error;
333 }
334 }
335 free(pNameZ);
336
337 pServSection->inSCF=true;
338 if (pPreviousService!=NULL)
339 {
340 pPreviousService->pNextInSCF=pServSection;
341 }
342 else
343 {
344 pConfFile->pFirstSectionInSCF=pServSection;
345 }
346 pPreviousService=pServSection;
347
348 pPublicPropertyList=&pServSection->sPublicPropertyList;
349 pPrivatePropertyList=&pServSection->sPrivatePropertyList;
350 }
351 }
352 else
353 {
354 /* It's a property definition */
355 pValueZ = malloc(nValueLength+1);
356 if (pValueZ == NULL)
357 {
358 nError = S_ERROR_OUT_OF_MEMORY;
359 goto error;
360 }
361 memcpy(pValueZ, pValue, nValueLength);
362 pValueZ[nValueLength] = 0;
363
364 pProperty=(PROPERTY*)malloc(sizeof(PROPERTY));
365 if (pProperty==NULL)
366 {
367 nError=S_ERROR_OUT_OF_MEMORY;
368 goto error;
369 }
370 memset(pProperty, 0x00, sizeof(PROPERTY));
371 pProperty->sNode.pName=pNameZ;
372
373 pProperty->pValue=pValueZ;
374
375 if (pPrivatePropertyList==NULL)
376 {
377 nError=SMCPropListSortedAdd(pPublicPropertyList,(NODE*)pProperty);
378 if (nError!=S_SUCCESS)
379 {
380 goto error;
381 }
382 }
383 else
384 {
385 if ((nValueLength > strlen(CONFIG_PROPERTY_NAME)) &&
386 (memcmp(pProperty->sNode.pName, CONFIG_PROPERTY_NAME, strlen(CONFIG_PROPERTY_NAME)) == 0))
387 {
388 nError=SMCPropListSortedAdd(pPrivatePropertyList,(NODE*)pProperty);
389 }
390 else
391 {
392 nError=SMCPropListSortedAdd(pPublicPropertyList,(NODE*)pProperty);
393 }
394 if (nError!=S_SUCCESS)
395 {
396 goto error;
397 }
398 }
399 }
400 }
401
402 error:
403 if (nError!=S_SUCCESS)
404 {
405 switch (nError)
406 {
407 case S_ERROR_BAD_FORMAT:
408 /* Error message already output */
409 break;
410 case S_ERROR_WRONG_SIGNATURE:
411 TRACE_ERROR("Configuration file: wrong service UUID: %s\n", pValueZ);
412 break;
413 case S_ERROR_OUT_OF_MEMORY:
414 TRACE_ERROR("Out of memory\n");
415 break;
416 case S_ERROR_ITEM_NOT_FOUND:
417 TRACE_ERROR("Configuration file: service \"%s\" not found\n", pNameZ);
418 break;
419 }
420 }
421 return nError;
422 }
423
424
static_readFile(const char * pFilename,void ** ppFile,uint32_t * pnFileLength)425 S_RESULT static_readFile(const char* pFilename, void** ppFile, uint32_t* pnFileLength)
426 {
427 S_RESULT nResult = S_SUCCESS;
428 long nFilesize;
429 FILE* pFile = NULL;
430 void *pBuff = NULL;
431
432 // open file and get its size...
433 if ((pFile = fopen(pFilename, "rb")) == NULL)
434 {
435 TRACE_ERROR("static_readFile: fopen(%s) failed [%d]", pFilename, GET_LAST_ERR);
436 nResult = S_ERROR_ITEM_NOT_FOUND;
437 return nResult;
438 }
439 if (fseek(pFile, 0, SEEK_END) != 0)
440 {
441 TRACE_ERROR("static_readFile: fseek(%s) failed [%d]", pFilename, GET_LAST_ERR);
442 nResult = S_ERROR_UNDERLYING_OS;
443 goto error;
444 }
445 nFilesize = ftell(pFile);
446 if (nFilesize < 0)
447 {
448 TRACE_ERROR("static_readFile: ftell(%s) failed [%d]", pFilename, GET_LAST_ERR);
449 nResult = S_ERROR_UNDERLYING_OS;
450 goto error;
451 }
452 rewind(pFile);
453
454 // allocate the buffer
455 pBuff = malloc(nFilesize + 1);
456 if (pBuff == NULL)
457 {
458 TRACE_ERROR("static_readFile: out of memory");
459 nResult = S_ERROR_OUT_OF_MEMORY;
460 goto error;
461 }
462
463 // read the file
464 if (fread(pBuff, sizeof(uint8_t), (size_t)nFilesize, pFile) != (size_t)nFilesize)
465 {
466 TRACE_ERROR("static_readFile: fread failed [%d]", GET_LAST_ERR);
467 nResult = S_ERROR_UNDERLYING_OS;
468 goto error;
469 }
470 ((char*)pBuff)[nFilesize] = 0;
471
472 *ppFile = pBuff;
473 *pnFileLength = nFilesize;
474 return S_SUCCESS;
475
476 error:
477 if (pBuff != NULL)
478 free(pBuff);
479 fclose(pFile);
480
481 *ppFile = NULL;
482 *pnFileLength = 0;
483 return nResult;
484 }
485
486
487
488
489
490 /* ---------------------------------------------------------------------------------
491 API functions.
492 ---------------------------------------------------------------------------------*/
493
SMCPropGetSystemProperty(CONF_FILE * pConfFile,char * pPropertyName)494 char* SMCPropGetSystemProperty(CONF_FILE* pConfFile, char* pPropertyName)
495 {
496 PROPERTY* pProperty;
497
498 pProperty=(PROPERTY*)SMCPropListFindElement(
499 &pConfFile->sSystemSectionPropertyList,
500 pPropertyName,
501 true);
502 if (pProperty!=NULL)
503 {
504 return pProperty->pValue;
505 }
506 return NULL;
507 }
508
SMCPropGetSystemPropertyAsInt(CONF_FILE * pConfFile,char * pPropertyName)509 uint32_t SMCPropGetSystemPropertyAsInt(CONF_FILE* pConfFile, char* pPropertyName)
510 {
511 uint32_t nValue;
512 char* pValue=SMCPropGetSystemProperty(pConfFile,pPropertyName);
513
514 if (libString2GetStringAsInt(pValue, &nValue) == S_SUCCESS)
515 {
516 return nValue;
517 }
518 return 0;
519 }
520
521
SMCPropParseConfigFile(char * pConfigFilename,CONF_FILE * pConfFile)522 S_RESULT SMCPropParseConfigFile(char* pConfigFilename,CONF_FILE* pConfFile)
523 {
524 S_RESULT nError=S_SUCCESS;
525 void* pFile;
526 uint32_t nFileLength;
527 bool bReuseManifest;
528
529 assert(pConfFile!=NULL);
530
531 TRACE_INFO("Processing configuration file '%s'", pConfigFilename);
532
533 if(pConfigFilename != NULL)
534 {
535 nError=static_readFile(pConfigFilename,&pFile,&nFileLength);
536 if (nError!=S_SUCCESS)
537 {
538 goto error;
539 }
540 bReuseManifest = true;
541 }
542 else
543 {
544 assert(0);
545 }
546
547 nError=SMCPropYacc(pFile,nFileLength,pConfFile);
548
549 if(pConfigFilename != NULL)
550 {
551 free(pFile);
552 }
553
554 error:
555 return nError;
556 }
557