Home | History | Annotate | Download | only in tf_daemon
      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>
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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