• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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