// ------------------------------------------------------------------------------------------------- static void DumpTreeJSON ( le_cfg_IteratorRef_t iterRef, ///< Read the tree data from this iterator. json_t* jsonObject ///< JSON object to hold the tree data. ) // ------------------------------------------------------------------------------------------------- { // Note that because this is a recursive function, the buffer here is static in order to save on // stack space. The implication here is that we then have to be careful how it is later // accessed. Also, this makes the function not thread safe. But this trade off was made as // this was not intended to be a multi-threaded program. static char strBuffer[LE_CFG_STR_LEN_BYTES] = ""; // Build up the child array. json_t* childArrayPtr = json_array(); do { // Simply grab the name and the type of the current node. le_cfg_GetNodeName(iterRef, "", strBuffer, sizeof(strBuffer)); le_cfg_nodeType_t type = le_cfg_GetNodeType(iterRef, ""); switch (type) { // It's a stem object, so mark this item as being a stem and recurse into the stem's // sub-items. case LE_CFG_TYPE_STEM: { json_t* nodePtr = CreateJsonNode(strBuffer, NodeTypeStr(type)); le_cfg_GoToFirstChild(iterRef); DumpTreeJSON(iterRef, nodePtr); le_cfg_GoToParent(iterRef); json_array_append(childArrayPtr, nodePtr); } break; default: { json_t* nodePtr = CreateJsonNodeFromIterator(iterRef); if (nodePtr != NULL) { json_array_append(childArrayPtr, nodePtr); } } break; } } while (le_cfg_GoToNextSibling(iterRef) == LE_OK); // Set children into the JSON document. json_object_set_new(jsonObject, JSON_FIELD_CHILDREN, childArrayPtr); }
static void DumpTree(le_cfg_IteratorRef_t iterRef, size_t indent) { if (le_arg_NumArgs() == 1) { return; } static char strBuffer[STR_SIZE] = { 0 }; do { size_t i; for (i = 0; i < indent; i++) { printf(" "); } le_cfg_GetNodeName(iterRef, "", strBuffer, STR_SIZE); le_cfg_nodeType_t type = le_cfg_GetNodeType(iterRef, ""); switch (type) { case LE_CFG_TYPE_STEM: printf("%s/\n", strBuffer); le_cfg_GoToFirstChild(iterRef); DumpTree(iterRef, indent + 2); le_cfg_GoToParent(iterRef); break; case LE_CFG_TYPE_EMPTY: printf("%s~~\n", strBuffer); break; default: printf("%s<%s> == ", strBuffer, NodeTypeStr(iterRef)); le_cfg_GetString(iterRef, "", strBuffer, STR_SIZE, ""); printf("%s\n", strBuffer); break; } } while (le_cfg_GoToNextSibling(iterRef) == LE_OK); }
//-------------------------------------------------------------------------------------------------- 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); }
//-------------------------------------------------------------------------------------------------- static void ConfigureGdb ( void ) { le_cfg_ConnectService(); le_cfgAdmin_ConnectService(); // Get a write iterator to the application node. le_cfg_IteratorRef_t cfgIter = le_cfg_CreateWriteTxn("/apps"); le_cfg_GoToNode(cfgIter, AppName); // Check if this is a temporary configuration that was previously created by this or a similar // tool. if (!le_cfg_IsEmpty(cfgIter, CFG_DEBUG_TOOL)) { char debugTool[LIMIT_MAX_PATH_BYTES]; // Don't need to check return code because the value is just informative and does not matter // if it is truncated. le_cfg_GetString(cfgIter, CFG_DEBUG_TOOL, debugTool, sizeof(debugTool), ""); fprintf(stderr, "This application has already been configured for %s debug mode.\n", debugTool); exit(EXIT_FAILURE); } // Write into the config's debug tool node to indicate that this configuration has been modified. le_cfg_SetString(cfgIter, CFG_DEBUG_TOOL, "gdb"); // Add 512K to the maxFileSytemBytes so that we can debug this app in sandboxed mode uint32_t maxBytes; maxBytes = le_cfg_GetInt(cfgIter, "maxFileSystemBytes", DEFAULT_LIMIT_MAX_FILE_SYSTEM_BYTES); maxBytes += ADD_FILE_SYSTEM_BYTES; // add an additional 512KBytes LE_INFO("Resetting maxFileSystemBytes to %d bytes", maxBytes); le_cfg_SetInt(cfgIter, "maxFileSystemBytes", maxBytes); // Add gdbserver and libs to the app's 'requires/files' section. le_cfg_GoToNode(cfgIter, "requires/files"); AddImportFiles(cfgIter, &GdbFilesImports, NUM_ARRAY_MEMBERS(GdbFilesImports)); // Add /proc to the app's dirs section. le_cfg_GoToParent(cfgIter); le_cfg_GoToNode(cfgIter, "dirs"); AddImportFiles(cfgIter, &GdbDirsImports, NUM_ARRAY_MEMBERS(GdbDirsImports)); // Delete the list of processes. le_cfg_GoToParent(cfgIter); le_cfg_GoToParent(cfgIter); int i; for (i = 0; i < NumProcs; i++) { char nodePath[LIMIT_MAX_PATH_BYTES]; int n = snprintf(nodePath, sizeof(nodePath), "procs/%s", ProcNames[i]); INTERNAL_ERR_IF(n >= sizeof(nodePath), "Node name is too long."); INTERNAL_ERR_IF(n < 0, "Format error. %m"); le_cfg_DeleteNode(cfgIter, nodePath); } le_cfg_CommitTxn(cfgIter); }
// ------------------------------------------------------------------------------------------------- static le_result_t HandleImportJSONIteration ( le_cfg_IteratorRef_t iterRef, ///< Dump the JSON data into this iterator. json_t* nodePtr ///< From this JSON object. ) // ------------------------------------------------------------------------------------------------- { // Get value json_t* value = json_object_get(nodePtr, JSON_FIELD_VALUE); // Check type const char* typeStr = json_string_value(json_object_get(nodePtr, JSON_FIELD_TYPE)); le_cfg_nodeType_t type = GetNodeTypeFromString(typeStr); switch (type) { case LE_CFG_TYPE_BOOL: le_cfg_SetBool(iterRef, "", json_is_true(value)); break; case LE_CFG_TYPE_STRING: le_cfg_SetString(iterRef, "", json_string_value(value)); break; case LE_CFG_TYPE_INT: le_cfg_SetInt(iterRef, "", json_integer_value(value)); break; case LE_CFG_TYPE_FLOAT: le_cfg_SetFloat(iterRef, "", json_real_value(value)); break; case LE_CFG_TYPE_STEM: { // Iterate on children json_t* childrenPtr = json_object_get(nodePtr, JSON_FIELD_CHILDREN); json_t* childPtr; int i; json_array_foreach(childrenPtr, i, childPtr) { // Get name const char* name = json_string_value(json_object_get(childPtr, JSON_FIELD_NAME)); // Is node exist with this name? le_cfg_nodeType_t existingType = le_cfg_GetNodeType(iterRef, name); switch (existingType) { case LE_CFG_TYPE_DOESNT_EXIST: case LE_CFG_TYPE_STEM: case LE_CFG_TYPE_EMPTY: // Not existing, already a stem or empty node, nothing to do break; default: // Issue with node creation fprintf(stderr, "Node conflict when importing, at node %s", name); return LE_NOT_POSSIBLE; break; } // Iterate to this child le_cfg_GoToNode(iterRef, name); // Iterate le_result_t subResult = HandleImportJSONIteration(iterRef, childPtr); if (subResult != LE_OK) { // Something went wrong return subResult; } // Go back to parent le_cfg_GoToParent(iterRef); } } break; default: return LE_FAULT; } return LE_OK; }
// ------------------------------------------------------------------------------------------------- static int HandleGetJSON ( const char* nodePathPtr, ///< Path to the node in the configTree. const char* filePathPtr ///< Path to the file in the file system. If NULL STDOUT is used ///< instead of a file. ) // ------------------------------------------------------------------------------------------------- { json_t* nodePtr = NULL; // Get the node path from our command line arguments. if (strcmp("*", nodePathPtr) == 0) { // Dump all trees // Create JSON root item json_t* rootPtr = CreateJsonNode("root", "root"); json_t* treeListPtr = json_array(); // Loop through the trees in the system. le_cfgAdmin_IteratorRef_t iteratorRef = le_cfgAdmin_CreateTreeIterator(); while (le_cfgAdmin_NextTree(iteratorRef) == LE_OK) { // Allocate space for the tree name, plus space for a trailing :/ used when we create a // transaction for that tree. char treeName[MAX_TREE_NAME_BYTES + 2] = ""; if (le_cfgAdmin_GetTreeName(iteratorRef, treeName, MAX_TREE_NAME_BYTES) != LE_OK) { continue; } // JSON node for the tree. json_t* treeNodePtr = CreateJsonNode(treeName, "tree"); strcat(treeName, ":/"); // Start a read transaction at the specified node path. Then dump the value, (if any.) le_cfg_IteratorRef_t iterRef = le_cfg_CreateReadTxn(treeName); le_cfg_GoToFirstChild(iterRef); // Dump tree to JSON DumpTreeJSON(iterRef, treeNodePtr); le_cfg_CancelTxn(iterRef); json_array_append(treeListPtr, treeNodePtr); } le_cfgAdmin_ReleaseTreeIterator(iteratorRef); // Finalize root object... json_object_set_new(rootPtr, "trees", treeListPtr); nodePtr = rootPtr; } else { // Start a read transaction at the specified node path. Then dump the value, (if any.) le_cfg_IteratorRef_t iterRef = le_cfg_CreateReadTxn(nodePathPtr); le_cfg_nodeType_t type = le_cfg_GetNodeType(iterRef, ""); switch (type) { case LE_CFG_TYPE_STEM: { char strBuffer[LE_CFG_STR_LEN_BYTES] = ""; char nodeType[LE_CFG_STR_LEN_BYTES] = ""; le_cfg_GetNodeName(iterRef, "", strBuffer, sizeof(strBuffer)); // If no name, we are dumping a complete tree. if (strlen(strBuffer) == 0) { strcpy(nodeType, "tree"); } else { strcpy(nodeType, NodeTypeStr(type)); } nodePtr = CreateJsonNode(strBuffer, nodeType); le_cfg_GoToFirstChild(iterRef); DumpTreeJSON(iterRef, nodePtr); le_cfg_GoToParent(iterRef); } break; default: nodePtr = CreateJsonNodeFromIterator(iterRef); break; } le_cfg_CancelTxn(iterRef); } if (nodePtr == NULL) { // Empty node nodePtr = json_object(); } // Dump Json content // stdout mode? int result = EXIT_SUCCESS; if (filePathPtr == NULL) { printf("%s\n", json_dumps(nodePtr, JSON_COMPACT)); } else if (json_dump_file(nodePtr, filePathPtr, JSON_COMPACT) != 0) { result = EXIT_FAILURE; } json_decref(nodePtr); return result; }
// ------------------------------------------------------------------------------------------------- static void DumpTree ( le_cfg_IteratorRef_t iterRef, ///< Write out the tree pointed to by this iterator. size_t indent ///< The amount of indentation to use for this item. ) // ------------------------------------------------------------------------------------------------- { // Note that because this is a recursive function, the buffer here is static in order to save on // stack space. The implication here is that we then have to be careful how it is later // accessed. Also, this makes the function not thread safe. But this trade off was made as // this was not intended to be a multi-threaded program. static char strBuffer[LE_CFG_STR_LEN_BYTES] = ""; do { // Quick and dirty way to indent the tree item. size_t i; for (i = 0; i < indent; i++) { printf(" "); } // Simply grab the name and the type of the current node. le_cfg_GetNodeName(iterRef, "", strBuffer, LE_CFG_STR_LEN_BYTES); le_cfg_nodeType_t type = le_cfg_GetNodeType(iterRef, ""); switch (type) { // It's a stem object, so mark this item as being a stem and recurse into the stem's // sub-items. case LE_CFG_TYPE_STEM: printf("%s/\n", strBuffer); le_cfg_GoToFirstChild(iterRef); DumpTree(iterRef, indent + 2); le_cfg_GoToParent(iterRef); // If we got back up to where we started then don't iterate the "root" node's // siblings. if (indent == 0) { return; } break; // The node is empty, so simply mark it as such. case LE_CFG_TYPE_EMPTY: printf("%s<empty>\n", strBuffer); break; case LE_CFG_TYPE_BOOL: { char* value = NULL; if (le_cfg_GetBool(iterRef, "", false)) { value = "true"; } else { value = "false"; } printf("%s<bool> == %s\n", strBuffer, value); } break; // The node has a different type. So write out the name and the type. Then print the // value. default: printf("%s<%s> == ", strBuffer, NodeTypeStr(le_cfg_GetNodeType(iterRef, ""))); le_cfg_GetString(iterRef, "", strBuffer, LE_CFG_STR_LEN_BYTES, ""); printf("%s\n", strBuffer); break; } } while (le_cfg_GoToNextSibling(iterRef) == LE_OK); }