//-------------------------------------------------------------------------------------------------- static void LoadECallSettings ( int32_t* hMinAccuracyPtr, int32_t* dirMinAccuracyPtr ) { char psapStr[LE_MDMDEFS_PHONE_NUM_MAX_BYTES] = {0}; LE_DEBUG("Start reading eCall app settings in Configuration Tree"); le_cfg_IteratorRef_t eCallCfgRef = le_cfg_CreateReadTxn(CFG_ECALL_APP_PATH); // Get PSAP if (le_cfg_NodeExists(eCallCfgRef, CFG_NODE_PSAP)) { if ( le_cfg_GetString(eCallCfgRef, CFG_NODE_PSAP, psapStr, sizeof(psapStr), "") != LE_OK ) { LE_FATAL("No node value set for '%s', exit the app!", CFG_NODE_PSAP); } LE_DEBUG("eCall settings, PSAP number is %s", psapStr); if (le_ecall_SetPsapNumber(psapStr) != LE_OK) { LE_FATAL("Cannot set PSAP number, exit the app!"); } } else { LE_FATAL("No value set for '%s', restart the app!", CFG_NODE_PSAP); } // Get minimum horizontal accuracy if (le_cfg_NodeExists(eCallCfgRef, CFG_NODE_H_MIN_ACCURACY)) { *hMinAccuracyPtr = le_cfg_GetInt(eCallCfgRef, CFG_NODE_H_MIN_ACCURACY, DEFAULT_H_ACCURACY); LE_DEBUG("eCall app settings, horizontal accuracy is %d meter(s)", *hMinAccuracyPtr); } else { *hMinAccuracyPtr = DEFAULT_H_ACCURACY; } // Get minimum direction accuracy if (le_cfg_NodeExists(eCallCfgRef, CFG_NODE_DIR_MIN_ACCURACY)) { *dirMinAccuracyPtr = le_cfg_GetInt(eCallCfgRef, CFG_NODE_DIR_MIN_ACCURACY, DEFAULT_DIR_ACCURACY); LE_DEBUG("eCall app settings, direction accuracy is %d degree(s)", *dirMinAccuracyPtr); } else { *dirMinAccuracyPtr = DEFAULT_DIR_ACCURACY; } le_cfg_CancelTxn(eCallCfgRef); }
//-------------------------------------------------------------------------------------------------- void userAddRemove_Add ( const char* appName ) //-------------------------------------------------------------------------------------------------- { le_result_t result; uid_t uid; gid_t gid; char userName[256] = "app"; result = le_utf8_Append(userName, appName, sizeof(userName), NULL); LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName); LE_INFO("Creating user '%s' for application '%s'.", userName, appName); // Start a read transaction and go to node /apps/app-name le_cfg_ConnectService(); le_cfg_IteratorRef_t i = le_cfg_CreateReadTxn("/apps"); le_cfg_GoToNode(i, appName); // If the node doesn't exist, bail out. if (!le_cfg_NodeExists(i, "")) { fprintf(stderr, "** ERROR: App '%s' doesn't exist in the system configuration.\n", appName); } else { result = user_Create(userName, &uid, &gid); if (result == LE_OK) { printf("Created user '%s' (uid %u, gid %u).\n", userName, uid, gid); // TODO: Groups configuration. le_cfg_CancelTxn(i); exit(EXIT_SUCCESS); } else if (result == LE_DUPLICATE) { // TODO: Verify correct groups configuration. printf("User '%s' already exists (uid %u, gid %u).\n", userName, uid, gid); le_cfg_CancelTxn(i); exit(EXIT_SUCCESS); } else { fprintf(stderr, "** ERROR: user_Create() failed for user '%s'.\n", userName); } } le_cfg_CancelTxn(i); exit(EXIT_FAILURE); }
//-------------------------------------------------------------------------------------------------- LE_SHARED le_result_t appCfg_GetVersion ( appCfg_Iter_t appIterRef, ///< [IN] Apps iterator char* bufPtr, ///< [OUT] Buffer to store the app version. size_t bufSize ///< [IN] Size of the buffer. ) { CheckFor(appIterRef, ITER_TYPE_APP); if (le_cfg_NodeExists(appIterRef->cfgIter, "") == false) { return LE_NOT_FOUND; } return le_cfg_GetString(appIterRef->cfgIter, CFG_APP_VERSION, bufPtr, bufSize, ""); }
//-------------------------------------------------------------------------------------------------- LE_SHARED le_result_t appCfg_GetProcExecName ( appCfg_Iter_t procIterRef, ///< [IN] Apps iterator char* bufPtr, ///< [OUT] Buffer to store the app name. size_t bufSize ///< [IN] Size of the buffer. ) { CheckFor(procIterRef, ITER_TYPE_PROC); if (le_cfg_NodeExists(procIterRef->cfgIter, "") == false) { return LE_NOT_FOUND; } return le_cfg_GetString(procIterRef->cfgIter, CFG_PROC_EXEC_NAME, bufPtr, bufSize, ""); }
//-------------------------------------------------------------------------------------------------- LE_SHARED le_result_t appCfg_GetAppName ( appCfg_Iter_t appIterRef, ///< [IN] Apps iterator char* bufPtr, ///< [OUT] Buffer to store the app name. size_t bufSize ///< [IN] Size of the buffer. ) { CheckFor(appIterRef, ITER_TYPE_APP); if (le_cfg_NodeExists(appIterRef->cfgIter, "") == false) { return LE_NOT_FOUND; } return le_cfg_GetNodeName(appIterRef->cfgIter, "", bufPtr, bufSize); }
//-------------------------------------------------------------------------------------------------- static void AddImportFiles ( le_cfg_IteratorRef_t cfgIter, ///< [IN] Iterator to the application config. const ImportObj_t (*importsPtr)[], ///< [IN] Imports to include in the application. size_t numImports ///< [IN] Number of import elements. ) { // Find the last node under the 'files' or 'dirs' section. size_t nodeNum = 0; char nodePath[LIMIT_MAX_PATH_BYTES]; while (1) { int n = snprintf(nodePath, sizeof(nodePath), "%zd", nodeNum); INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long."); INTERNAL_ERR_IF(n < 0, "Format error. %m"); if (!le_cfg_NodeExists(cfgIter, nodePath)) { break; } nodeNum++; } // Start adding files/directories at the end of the current list. int i; for (i = 0; i < numImports; i++) { // Add the source. int n = snprintf(nodePath, sizeof(nodePath), "%zd/src", nodeNum + i); INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long."); INTERNAL_ERR_IF(n < 0, "Format error. %m"); le_cfg_SetString(cfgIter, nodePath, (*importsPtr)[i].src); // Add the destination. n = snprintf(nodePath, sizeof(nodePath), "%zd/dest", nodeNum + i); INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long."); INTERNAL_ERR_IF(n < 0, "Format error. %m"); le_cfg_SetString(cfgIter, nodePath, (*importsPtr)[i].dest); } }
//-------------------------------------------------------------------------------------------------- LE_SHARED appCfg_Iter_t appCfg_FindApp ( const char* appName ///< [IN] Name of the app to find. ) { AppsIter_t* iterPtr = appCfg_CreateAppsIter(); le_cfg_GoToNode(iterPtr->cfgIter, appName); if (le_cfg_NodeExists(iterPtr->cfgIter, "") == false) { appCfg_DeleteIter(iterPtr); return NULL; } return iterPtr; }
//-------------------------------------------------------------------------------------------------- static int GetCfgResourceLimit ( le_cfg_IteratorRef_t limitCfg, // The iterator to use to read the configured limit. This // iterator is owned by the caller and should not be deleted // in this function. const char* nodeName, // The name of the node in the config tree that holds the value. int defaultValue // The default value to use if the config value is invalid. ) { int limitValue = le_cfg_GetInt(limitCfg, nodeName, defaultValue); if (!le_cfg_NodeExists(limitCfg, nodeName)) { LE_INFO("Configured resource limit %s is not available. Using the default value %d.", nodeName, defaultValue); return defaultValue; } if (le_cfg_IsEmpty(limitCfg, nodeName)) { LE_WARN("Configured resource limit %s is empty. Using the default value %d.", nodeName, defaultValue); return defaultValue; } if (le_cfg_GetNodeType(limitCfg, nodeName) != LE_CFG_TYPE_INT) { LE_ERROR("Configured resource limit %s is the wrong type. Using the default value %d.", nodeName, defaultValue); return defaultValue; } if (limitValue < 0) { LE_ERROR("Configured resource limit %s is negative. Using the default value %d.", nodeName, defaultValue); return defaultValue; } return limitValue; }
static void ExistAndEmptyTest() { static char pathBuffer[STR_SIZE] = { 0 }; snprintf(pathBuffer, STR_SIZE, "/%s/existAndEmptyTest/", TestRootDir); { le_cfg_IteratorRef_t iterRef = le_cfg_CreateWriteTxn(pathBuffer); le_cfg_SetEmpty(iterRef, ""); LE_TEST(le_cfg_IsEmpty(iterRef, "") == true); LE_TEST(le_cfg_NodeExists(iterRef, "valueA") == false); LE_TEST(le_cfg_NodeExists(iterRef, "valueB") == false); LE_TEST(le_cfg_NodeExists(iterRef, "valueC") == false); LE_TEST(le_cfg_NodeExists(iterRef, "valueD") == false); LE_TEST(le_cfg_IsEmpty(iterRef, "valueA") == true); LE_TEST(le_cfg_IsEmpty(iterRef, "valueB") == true); LE_TEST(le_cfg_IsEmpty(iterRef, "valueC") == true); LE_TEST(le_cfg_IsEmpty(iterRef, "valueD") == true); le_cfg_SetString(iterRef, "valueA", "aNewValue"); le_cfg_SetInt(iterRef, "valueB", 10); le_cfg_SetBool(iterRef, "valueC", true); le_cfg_SetFloat(iterRef, "valueD", 10.24); LE_TEST(le_cfg_NodeExists(iterRef, "valueA") == true); LE_TEST(le_cfg_NodeExists(iterRef, "valueB") == true); LE_TEST(le_cfg_NodeExists(iterRef, "valueC") == true); LE_TEST(le_cfg_NodeExists(iterRef, "valueD") == true); LE_TEST(le_cfg_IsEmpty(iterRef, "valueA") == false); LE_TEST(le_cfg_IsEmpty(iterRef, "valueB") == false); LE_TEST(le_cfg_IsEmpty(iterRef, "valueC") == false); LE_TEST(le_cfg_IsEmpty(iterRef, "valueD") == false); le_cfg_CommitTxn(iterRef); } }
//-------------------------------------------------------------------------------------------------- static void SetRLimit ( pid_t pid, // The pid of the process to set the limit for. le_cfg_IteratorRef_t procCfg, // The iterator for the process. This is a iterator is owned by // the caller and should not be deleted in this function. const char* resourceName, // The resource name in the config tree. int resourceID, // The resource ID that setrlimit() expects. rlim_t defaultValue // The default value for this resource limit. ) { // Initialize the limit to the defaults. struct rlimit lim = {defaultValue, defaultValue}; // Move the iterator to the resource limit to read. le_cfg_GoToNode(procCfg, resourceName); if (le_cfg_NodeExists(procCfg, "") == false) { LE_WARN("No resource limit %s. Using the default value %lu.", resourceName, defaultValue); } else { // Try reading the resource limit from the config tree. if (GetCfgResourceLimit(procCfg, &(lim.rlim_max)) != LE_OK) { LE_ERROR("Configured resource limit %s is invalid. Using the default value %lu.", resourceName, defaultValue); } else { // Check that the limit does not exceed the maximum. if ( (resourceID == RLIMIT_NOFILE) && (lim.rlim_max > MAX_LIMIT_NUM_FD) ) { LE_ERROR("Resource limit %s is greater than the maximum allowed limit (%d). Using the \ maximum allowed value.", resourceName, MAX_LIMIT_NUM_FD); lim.rlim_max = MAX_LIMIT_NUM_FD; } } // Move the iterator back to where it was. LE_ASSERT(le_cfg_GoToParent(procCfg) == LE_OK); }
//-------------------------------------------------------------------------------------------------- rlim_t resLim_GetSandboxedAppTmpfsLimit ( app_Ref_t appRef ///< [IN] The application to set resource limits for. ) { // Get the resource limit from the config tree. Zero means unlimited for tmpfs mounts and is // not allowed. // Determine the file system limit to set. rlim_t fileSysLimit = DEFAULT_LIMIT_FILE_SYSTEM_SIZE; // Create a config iterator to get the file system limit from the config tree. le_cfg_IteratorRef_t appCfg = le_cfg_CreateReadTxn(app_GetConfigPath(appRef)); le_cfg_GoToNode(appCfg, CFG_NODE_LIMIT_FILE_SYSTEM_SIZE); if (le_cfg_NodeExists(appCfg, "") == false) { LE_WARN("No resource limit %s. Assuming the default value %d.", CFG_NODE_LIMIT_FILE_SYSTEM_SIZE, DEFAULT_LIMIT_FILE_SYSTEM_SIZE); } else if ( (GetCfgResourceLimit(appCfg, &fileSysLimit) != LE_OK) || (fileSysLimit == 0) ) { // Use the default limit. LE_ERROR("Configured resource limit %s is invalid. Assuming the default value %d.", CFG_NODE_LIMIT_FILE_SYSTEM_SIZE, DEFAULT_LIMIT_FILE_SYSTEM_SIZE); fileSysLimit = DEFAULT_LIMIT_FILE_SYSTEM_SIZE; } le_cfg_CancelTxn(appCfg); return fileSysLimit; }
//-------------------------------------------------------------------------------------------------- static le_result_t GetServerUid ( le_cfg_IteratorRef_t i, ///< [in] Config tree iterator positioned at binding config. uid_t* uidPtr ///< [out] The application's user ID. ) //-------------------------------------------------------------------------------------------------- { le_result_t result; char userName[LIMIT_MAX_USER_NAME_BYTES]; // If an app name is present in the binding config, if (le_cfg_NodeExists(i, "app")) { // Make sure there isn't also a user name. if (le_cfg_NodeExists(i, "user")) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "", path, sizeof(path)); LE_CRIT("Both server user and app nodes appear under binding (@ %s)", path); return LE_DUPLICATE; } // Get the app name. char appName[LIMIT_MAX_APP_NAME_BYTES]; result = le_cfg_GetString(i, "app", appName, sizeof(appName), ""); if (result != LE_OK) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "app", path, sizeof(path)); LE_CRIT("Server app name too big (@ %s)", path); return result; } if (appName[0] == '\0') { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "app", path, sizeof(path)); LE_CRIT("Server app name empty (@ %s)", path); return LE_NOT_FOUND; } // Find out if the server app is sandboxed. If not, it runs as root. char path[LIMIT_MAX_PATH_BYTES]; if (snprintf(path, sizeof(path), "/apps/%s/sandboxed", appName) >= sizeof(path)) { LE_CRIT("Config node path too long (app name '%s').", appName); return LE_OVERFLOW; } if (!le_cfg_GetBool(i, path, true)) { *uidPtr = 0; return LE_OK; } // It is not sandboxed. Convert the app name into a user name. result = user_AppNameToUserName(appName, userName, sizeof(userName)); if (result != LE_OK) { LE_CRIT("Failed to convert app name '%s' into a user name.", appName); return result; } } // If a server app name is not present in the binding config, else { // Get the server user name instead. result = le_cfg_GetString(i, "user", userName, sizeof(userName), ""); if (result != LE_OK) { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "user", path, sizeof(path)); LE_CRIT("Server user name too big (@ %s)", path); return result; } if (userName[0] == '\0') { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "", path, sizeof(path)); LE_CRIT("Server user name or app name missing (@ %s)", path); return LE_NOT_FOUND; } } // Convert the server's user name into a user ID. result = user_GetUid(userName, uidPtr); if (result != LE_OK) { // Note: This can happen if the server application isn't installed yet. // When the server application is installed, sdir load will be run // again and the bindings will be correctly set up at that time. if (strncmp(userName, "app", 3) == 0) { LE_DEBUG("Couldn't get UID for application '%s'. Perhaps it is not installed yet?", userName + 3); } else { char path[LIMIT_MAX_PATH_BYTES]; le_cfg_GetPath(i, "", path, sizeof(path)); LE_CRIT("Couldn't convert server user name '%s' to UID (%s @ %s)", userName, LE_RESULT_TXT(result), path); } return result; } return LE_OK; }
//-------------------------------------------------------------------------------------------------- static void LoadPreferredList ( ) { uint32_t idx = 0; le_dls_List_t preferredNetworkList = LE_DLS_LIST_INIT; // Check that the modemRadioControl has a configuration value for preferred list. le_cfg_IteratorRef_t mrcCfg = le_cfg_CreateReadTxn(CFG_MODEMSERVICE_MRC_PATH"/"CFG_NODE_PREFERREDLIST); if (le_cfg_NodeExists(mrcCfg,"") == false) { LE_DEBUG("'%s' does not exist. Stop reading configuration", CFG_MODEMSERVICE_MRC_PATH"/"CFG_NODE_PREFERREDLIST); le_cfg_CancelTxn(mrcCfg); return; } // Read all network from configDB do { uint32_t ratMask; char mccNodePath[LIMIT_MAX_PATH_BYTES] = {0}; char mncNodePath[LIMIT_MAX_PATH_BYTES] = {0}; char ratNodePath[LIMIT_MAX_PATH_BYTES] = {0}; char mccStr[LIMIT_MAX_PATH_BYTES] = {0}; char mncStr[LIMIT_MAX_PATH_BYTES] = {0}; // Get the node name. char nodeName[LIMIT_MAX_PATH_BYTES] = {0}; sprintf(nodeName,PATTERN_NETWORK"%d",idx); if (le_cfg_IsEmpty(mrcCfg, nodeName)) { LE_DEBUG("'%s' does not exist. stop reading configuration", nodeName); break; } snprintf(mccNodePath, sizeof(mccNodePath), "%s/%s",nodeName,CFG_NODE_MCC); snprintf(mncNodePath, sizeof(mncNodePath), "%s/%s",nodeName,CFG_NODE_MNC); snprintf(ratNodePath, sizeof(ratNodePath), CFG_MODEMSERVICE_MRC_PATH"/"CFG_NODE_PREFERREDLIST"/%s/%s",nodeName,CFG_NODE_RAT); if ( le_cfg_GetString(mrcCfg,mccNodePath,mccStr,sizeof(mccStr),"") != LE_OK ) { LE_WARN("String value for '%s' too large.",mccNodePath); break; } if ( strcmp(mccStr,"") == 0 ) { LE_WARN("No node value set for '%s'",mccNodePath); break; } if ( le_cfg_GetString(mrcCfg,mncNodePath,mncStr,sizeof(mncStr),"") != LE_OK ) { LE_WARN("String value for '%s' too large.",mncNodePath); break; } if ( strcmp(mncStr,"") == 0 ) { LE_WARN("No node value set for '%s'",mncNodePath); break; } if ( LoadRatList(ratNodePath,&ratMask) != LE_OK ) { LE_WARN("Could not read rat information in '%s'",ratNodePath); break; } if ( pa_mrc_AddPreferredNetwork(&preferredNetworkList,mccStr,mncStr,ratMask) != LE_OK ) { LE_WARN("Could not add [%s,%s] into the preferred list",mccStr,mncStr); } ++idx; } while (true); le_cfg_CancelTxn(mrcCfg); if ( pa_mrc_SavePreferredList(&preferredNetworkList) != LE_OK ) { LE_WARN("Could not save the preferred list"); } pa_mrc_ClearPreferedList(&preferredNetworkList); }
//-------------------------------------------------------------------------------------------------- le_result_t le_cellnet_GetSimPinCode ( le_sim_Id_t simId, ///< [IN] ///< SIM identifier. char* pinCodePtr, ///< [OUT] ///< Read the PIN code from the config tree. size_t pinCodeNumElements ///< [IN] ) { le_result_t result=LE_OK; LE_DEBUG("simId= %d",simId); if (simId >= LE_SIM_ID_MAX) { LE_ERROR("Invalid simId (%d) provided!", simId); result = LE_OUT_OF_RANGE; } else { // Set the configuration path for the SIM. char configPath[LIMIT_MAX_PATH_BYTES]; char simPin[LE_SIM_PIN_MAX_BYTES] = {0}; le_cfg_IteratorRef_t simCfgRef; snprintf(configPath, sizeof(configPath), "%s/%d", CFG_MODEMSERVICE_SIM_PATH, simId); // Check that the app has a configuration value. simCfgRef = le_cfg_CreateReadTxn(configPath); // test if the node exists if (!le_cfg_NodeExists(simCfgRef, CFG_NODE_PIN)) { LE_ERROR("SIM PIN node isn't found in the config tree"); result = LE_NOT_FOUND; } else { //read config tree result = le_cfg_GetString(simCfgRef,CFG_NODE_PIN,simPin,sizeof(simPin),""); if (result != LE_OK) { LE_ERROR("retrieved SIM PIN code exceeds the supplied buffer"); result = LE_OVERFLOW; } else { //void entry is taken into account if ((strncmp(simPin,"",LE_SIM_PIN_MAX_LEN)!=0) && (strlen(simPin) < LE_SIM_PIN_MIN_LEN)) { LE_ERROR("retrieved SIM PIN code is not long enough (min 4 digits) "); result = LE_UNDERFLOW; } else { //copy pincode strncpy ( pinCodePtr, simPin, sizeof(simPin) ); LE_DEBUG("SIM PIN code= %s retrieved OK",pinCodePtr); } } } le_cfg_CancelTxn(simCfgRef); } return result; }