/** * generate LedHardware from LedPrefsNode * * @param p LedPrefs context * @param n LedPrefsNode * @result newly created LedHardware */ LedHardware *led_prefs_hardware_from_node(LedPrefs * p, LedPrefsNode * n) { if(!p || !n) NFT_LOG_NULL(NULL); /* check if node is of expected class */ if(strcmp(nft_prefs_node_get_name(n), LED_HARDWARE_NAME) != 0) { NFT_LOG(L_ERROR, "got wrong LedPrefsNode class. Expected \"%s\" but got \"%s\"", LED_HARDWARE_NAME, nft_prefs_node_get_name(n)); return NULL; } return nft_prefs_obj_from_node(p, n, NULL); }
/** function to update a Person prefs-node from version 0 to version 1 */ NftResult _update_person(NftPrefsNode *node, unsigned int version, void *userptr) { /* get "email" property from node */ char *email; if(!(email = nft_prefs_node_prop_string_get(node, "email"))) { NFT_LOG(L_ERROR, "failed to get \"email\" property from node \"%s\"", nft_prefs_node_get_name(node)); return NFT_FAILURE; } /* function result */ NftResult result = NFT_FAILURE; /* split "email" property into "email_user" and "email_host" */ char *email_user = strtok(email, "@"); char *email_host = strtok(NULL, "@"); NFT_LOG(L_NOTICE, "Extracted email_host: \"%s\" and email_user: \"%s\"", email_user, email_host); /* add new "email_user" property to node */ if(!(nft_prefs_node_prop_string_set(node, "email_user", email_user))) { NFT_LOG(L_ERROR, "failed to set \"email_user\" property to \"%s\"", email_user); goto _up_exit; } /* add new "email_user" property to node */ if(!(nft_prefs_node_prop_string_set(node, "email_host", email_host))) { NFT_LOG(L_ERROR, "failed to set \"email_host\" property to \"%s\"", email_host); goto _up_exit; } /* remove old "email" property */ if(!(nft_prefs_node_prop_unset(node, "email"))) { NFT_LOG(L_ERROR, "failed to remove \"email\" property from node."); goto _up_exit; } result = NFT_SUCCESS; _up_exit: /* free string */ nft_prefs_free(email); return result; }
/** * get URI of document this node was parsed from (or NULL) * * @result URI of node origin or NULL if unset */ const char *nft_prefs_node_get_uri(NftPrefsNode * n) { if(!n) NFT_LOG_NULL(NULL); if(!n->doc) { NFT_LOG(L_DEBUG, "node \"%s\" has no uri set.", nft_prefs_node_get_name(n)); return NULL; } return (const char *) n->doc->URL; }
/** * create new NftPrefsNode from preferences file * * @param p NftPrefs context * @param filename full path of file * @result newly created NftPrefsNode or NULL */ NftPrefsNode *nft_prefs_node_from_file(NftPrefs *p, const char *filename) { if(!filename) NFT_LOG_NULL(NULL); /* parse XML */ xmlDocPtr doc; if(!(doc = xmlReadFile(filename, NULL, 0))) { NFT_LOG(L_ERROR, "Failed to xmlReadFile(\"%s\")", filename); return NULL; } /* parse XInclude stuff */ int xinc_res; if((xinc_res = xmlXIncludeProcess(doc)) == -1) { NFT_LOG(L_ERROR, "XInclude parsing failed."); goto _npnff_error; } NFT_LOG(L_DEBUG, "%d XInclude substitutions done", xinc_res); /* get node */ xmlNode *node; if(!(node = xmlDocGetRootElement(doc))) { NFT_LOG(L_ERROR, "No root element found in XML"); goto _npnff_error; } /* update node */ if(!_updater_node_process(p, node)) { NFT_LOG(L_ERROR, "Preference update failed for node \"%s\". This is a fatal bug. Aborting.", nft_prefs_node_get_name(node)); goto _npnff_error; } /* return node */ return node; _npnff_error: xmlFreeDoc(doc); return NULL; }
/** * create preferences minimal buffer from NftPrefsNode - compared to * nft_prefs_node_to_buffer, this doesn't include any encapsulation or headers. * Just the bare information contained in the node. This should be used to * export single nodes, e.g. for copying them to a clipboard * * @param p NftPrefs context * @param n NftPrefsNode * @result string holding xml representation of object (use free() to deallocate) * @note s. @ref nft_prefs_node_to_file for description */ char *nft_prefs_node_to_buffer_minimal(NftPrefs *p, NftPrefsNode * n) { if(!n) NFT_LOG_NULL(NULL); /* result pointer (xml dump) */ char *dump = NULL; /* add prefs version to node */ if(!(_updater_node_add_version(p, n))) { NFT_LOG(L_ERROR, "failed to add version to node \"%s\"", nft_prefs_node_get_name(n)); return NULL; } /* create buffer */ xmlBufferPtr buf; if(!(buf = xmlBufferCreate())) { NFT_LOG(L_ERROR, "failed to xmlBufferCreate()"); return NULL; } /* dump node */ if(xmlNodeDump(buf, n->doc, n, 0, true) < 0) { NFT_LOG(L_ERROR, "xmlNodeDump() failed"); goto _pntb_exit; } /* allocate buffer */ size_t length = xmlBufferLength(buf); if(!(dump = malloc(length + 1))) { NFT_LOG_PERROR("malloc()"); goto _pntb_exit; } /* copy buffer */ strncpy(dump, (char *) xmlBufferContent(buf), length); dump[length] = '\0'; _pntb_exit: xmlBufferFree(buf); return dump; }
/** * generate LedChain from LedPrefsNode * * @param p LedPrefs context * @param n LedPrefsNode * @result newly created LedChain */ LedChain *led_prefs_chain_from_node(LedPrefs * p, LedPrefsNode * n) { if(!p || !n) NFT_LOG_NULL(NULL); /* check if node is of expected class */ if(!led_prefs_is_chain_node(n)) { NFT_LOG(L_ERROR, "got wrong LedPrefsNode class. Expected \"%s\" but got \"%s\"", LED_CHAIN_NAME, nft_prefs_node_get_name(n)); return NULL; } return nft_prefs_obj_from_node(p, n, NULL); }
/** * get next sibling of a node with a certain name * * @param n NftPrefsNode from which sibling should be fetched * @param name name of sibling node * @result sibling node or NULL */ NftPrefsNode *nft_prefs_node_get_next_with_name(NftPrefsNode * n, const char *name) { if(!n || !name) NFT_LOG_NULL(NULL); for(NftPrefsNode *sibling = nft_prefs_node_get_next(n); sibling; sibling = nft_prefs_node_get_next(sibling)) { if(strcmp(nft_prefs_node_get_name(sibling), name) == 0) { return sibling; } } return NULL; }
/** * create preferences file from NftPrefsNode and child nodes * * This will create the same output as nft_prefs_node_to_file() would but * without all encapsulation/headers/footers/... of the underlying prefs mechanism. * e.g. for XML this omits the "<?xml version="1.0" encoding="UTF-8"?>" header. * This is used when one only needs an "incomplete" snippet of a configuration. * e.g. for copy/paste or to use the XInclude feature of XML * * @param p NftPrefs context * @param n NftPrefsNode * @param filename full path of file to be written * @param overwrite if a file called "filename" already exists, it * will be overwritten if this is "true", otherwise NFT_FAILURE will be returned * @result NFT_SUCCESS or NFT_FAILURE */ NftResult nft_prefs_node_to_file_minimal(NftPrefs *p, NftPrefsNode * n, const char *filename, bool overwrite) { if(!n || !filename) NFT_LOG_NULL(NFT_FAILURE); /* file already existing? */ struct stat sts; if(stat(filename, &sts) == -1) { /* continue if stat error was caused because file doesn't exist */ if(errno != ENOENT) { NFT_LOG(L_ERROR, "Failed to access \"%s\" - %s", filename, strerror(errno)); return NFT_FAILURE; } } /* stat succeeded, file exists */ else if(strcmp("-", filename) != 0) { /* remove old file? */ if(!overwrite) return NFT_FAILURE; /* delete existing file */ if(unlink(filename) == -1) { NFT_LOG(L_ERROR, "Failed to remove old version of \"%s\" - %s", filename, strerror(errno)); return NFT_FAILURE; } } /* overall result */ NftResult r = NFT_FAILURE; /* add prefs version to node */ if(!(_updater_node_add_version(p, n))) { NFT_LOG(L_ERROR, "failed to add version to node \"%s\"", nft_prefs_node_get_name(n)); return r; } /* create buffer */ xmlBufferPtr buf; if(!(buf = xmlBufferCreate())) { NFT_LOG(L_ERROR, "failed to xmlBufferCreate()"); return r; } /* dump node */ if(xmlNodeDump(buf, n->doc, n, 0, true) < 0) { NFT_LOG(L_ERROR, "xmlNodeDump() failed"); goto _pntf_exit; } /* stdout? */ int fd; if(strcmp("-", filename) == 0) { fd = STDOUT_FILENO; } /* open file */ else { #ifdef WIN32 if((fd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) == -1) #else if((fd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP)) == -1) #endif { NFT_LOG_PERROR("open"); goto _pntf_exit; } } /* write to file */ ssize_t length = xmlBufferLength(buf); if(write(fd, (char *) xmlBufferContent(buf), length) != length) { NFT_LOG_PERROR("write"); goto _pntf_exit; } if(fd != STDOUT_FILENO) close(fd); r = NFT_SUCCESS; _pntf_exit: xmlBufferFree(buf); return r; }
/** * create preferences file with headers from NftPrefsNode and child nodes * * This will create the same output as nft_prefs_node_to_file_minimal() would but * with all encapsulation/headers/footers/... of the underlying prefs mechanism. * e.g. for XML this adds the "<?xml version="1.0" encoding="UTF-8"?>" header. * This is used when one needs a complete configuration (e.g. saved preferences * file) * * @param p NftPrefs context * @param n NftPrefsNode * @param filename full path of file to be written * @param overwrite if a file called "filename" already exists, it * will be overwritten if this is "true", otherwise NFT_FAILURE will be returned * @result NFT_SUCCESS or NFT_FAILURE */ NftResult nft_prefs_node_to_file(NftPrefs *p, NftPrefsNode * n, const char *filename, bool overwrite) { if(!n || !filename) NFT_LOG_NULL(NFT_FAILURE); /* add prefs version to node */ if(!(_updater_node_add_version(p, n))) { NFT_LOG(L_ERROR, "failed to add version to node \"%s\"", nft_prefs_node_get_name(n)); return NFT_FAILURE; } /* create copy of node */ NftPrefsNode *copy; if(!(copy = xmlCopyNode(n, 1))) return NFT_FAILURE; /* create temp xmlDoc */ xmlDoc *d = NULL; if(!(d = xmlNewDoc(BAD_CAST "1.0"))) { NFT_LOG(L_ERROR, "Failed to create new XML doc"); xmlFreeNode(copy); return NFT_FAILURE; } /* overall result */ NftResult r = NFT_FAILURE; /* set node as root element of temporary doc */ xmlDocSetRootElement(d, copy); /* file already existing? */ struct stat sts; if(stat(filename, &sts) == -1) { /* continue if stat error was caused because file doesn't exist */ if(errno != ENOENT) { NFT_LOG(L_ERROR, "Failed to access \"%s\" - %s", filename, strerror(errno)); goto _pntfwh_exit; } } /* stat succeeded, file exists */ else if(strcmp("-", filename) != 0) { /* remove old file? */ if(!overwrite) goto _pntfwh_exit; /* delete existing file */ if(unlink(filename) == -1) { NFT_LOG(L_ERROR, "Failed to remove old version of \"%s\" - %s", filename, strerror(errno)); goto _pntfwh_exit; } } /* write document to file */ if(xmlSaveFormatFileEnc(filename, d, "UTF-8", 1) < 0) { NFT_LOG(L_ERROR, "Failed to save XML file \"%s\"", filename); goto _pntfwh_exit; } /* successfully written file */ r = NFT_SUCCESS; _pntfwh_exit: if(copy) { /* unlink node from document again */ xmlUnlinkNode(copy); xmlFreeNode(copy); } /* free temporary xmlDoc */ if(d) { xmlFreeDoc(d); } return r; }
/** * create preferences buffer with all format specific encapsulation from a * NftPrefsNode. This is used when one needs a complete configuration. * * @param p NftPrefs context * @param n NftPrefsNode * @result string holding xml representation of object or NULL upon error * @note use free() to deallocate; s. @ref nft_prefs_node_to_file for description */ char *nft_prefs_node_to_buffer(NftPrefs *p, NftPrefsNode * n) { if(!n) NFT_LOG_NULL(NULL); /* add prefs version to node */ if(!(_updater_node_add_version(p, n))) { NFT_LOG(L_ERROR, "failed to add version to node \"%s\"", nft_prefs_node_get_name(n)); return NULL; } /* create copy of node */ NftPrefsNode *copy; if(!(copy = xmlCopyNode(n, 1))) return NULL; /* create temp xmlDoc */ xmlDoc *d = NULL; if(!(d = xmlNewDoc(BAD_CAST "1.0"))) { NFT_LOG(L_ERROR, "Failed to create new XML doc"); xmlFreeNode(copy); return NULL; } /* set node as root element of temporary doc */ xmlDocSetRootElement(d, copy); /* overall result */ char *r = NULL; xmlChar *dump = NULL; int length = 0; /* dump document to buffer */ xmlDocDumpFormatMemoryEnc(d, &dump, &length, "UTF-8", 1); if(!dump || length <= 0) { NFT_LOG(L_ERROR, "Failed to dump XML file"); goto _pntbwh_exit; } if(!(r = malloc(length + 1))) { NFT_LOG_PERROR("malloc"); goto _pntbwh_exit; } memcpy(r, dump, length); r[length] = '\0'; _pntbwh_exit: /* free node */ if(copy) { /* unlink node from document again */ xmlUnlinkNode(copy); xmlFreeNode(copy); } /* free xml buffer */ if(dump) xmlFree(dump); /* free temporary xmlDoc */ if(d) { xmlFreeDoc(d); } return r; }
/** * check if NftPrefsNode represents a hardware object * * @param n LedPrefsNode * @result true if node represents a hardware object, false otherwise */ bool led_prefs_is_hardware_node(LedPrefsNode * n) { return (strcmp(nft_prefs_node_get_name(n), LED_HARDWARE_NAME) == 0); }
/** * Config-to-Object function. * Creates a LedHardware model from a prefs node * @note you shouldn't call this function directly. * It's used by nft_prefs_obj_from_node() etc. */ static NftResult _prefs_to_hardware(LedPrefs * p, void **newObj, NftPrefsNode * n, void *userptr) { if(!p || !newObj || !n) NFT_LOG_NULL(NFT_FAILURE); /** initial result */ NftResult r = NFT_FAILURE; char *name = NULL; char *id = NULL; char *plugin_name = NULL; LedHardware *h = NULL; /* get hardware name */ if(! (name = nft_prefs_node_prop_string_get(n, LED_HARDWARE_PROP_NAME))) { NFT_LOG(L_ERROR, "\"hardware\" has no name"); goto _pth_end; } /* get plugin-name */ if(! (plugin_name = nft_prefs_node_prop_string_get(n, LED_HARDWARE_PROP_PLUGIN))) { NFT_LOG(L_ERROR, "\"hardware\" has no \"plugin\" type"); goto _pth_end; } /* get plugin-id */ if(!(id = nft_prefs_node_prop_string_get(n, LED_HARDWARE_PROP_ID))) { NFT_LOG(L_ERROR, "\"hardware\" has no \"id\" type"); goto _pth_end; } /* get stride */ LedCount stride; if(! (nft_prefs_node_prop_int_get (n, LED_HARDWARE_PROP_STRIDE, (int *) &stride))) { NFT_LOG(L_WARNING, "\"hardware\" has no \"stride\". Using 0 as default."); stride = 0; } /* create new hardware object */ if(!(h = led_hardware_new(name, plugin_name))) { NFT_LOG(L_ERROR, "Failed to initialize \"%s\" from \"%s\" plugin.", name, plugin_name); goto _pth_end; } /* set stride */ if(!(led_hardware_set_stride(h, stride))) { NFT_LOG(L_ERROR, "Failed to set stride (%d) of hardware \"%s\"", stride, name); goto _pth_end; } /* set id */ if(!(led_hardware_set_id(h, id))) { NFT_LOG(L_ERROR, "Failed to set ID \"%s\" of hardware \"%s\"", id, name); goto _pth_end; } /** @todo handle custom properties */ /* process child nodes */ LedPrefsNode *child; for(child = nft_prefs_node_get_first_child(n); child; child = nft_prefs_node_get_next(child)) { /* is child a tile node? */ if(led_prefs_is_tile_node(child)) { if(!led_hardware_append_tile (h, led_prefs_tile_from_node(p, child))) { NFT_LOG(L_ERROR, "Failed to add \"tile\" to \"%s\". Aborting.", name); goto _pth_end; } continue; } /* is child a chain node? */ else if(led_prefs_is_chain_node(child)) { LedChain *c; if(!(c = led_prefs_chain_from_node(p, child))) { NFT_LOG(L_ERROR, "Failed to create \"chain\" node of hardware %s", name); goto _pth_end; } if(!led_hardware_init (h, id, led_chain_get_ledcount(c), led_pixel_format_to_string(led_chain_get_format (c)))) { NFT_LOG(L_WARNING, "Failed to initialize hardware \"%s\"", name); } led_chain_destroy(c); } /* is child a plugin-property node? */ else if(strcmp (nft_prefs_node_get_name(child), LED_HARDWARE_PROPERTY_NAME) == 0) { char *name = NULL; char *type = NULL; char *value = NULL; /* get name of property */ if(! (name = nft_prefs_node_prop_string_get(child, LED_HARDWARE_PROPERTY_PROP_NAME))) { NFT_LOG(L_ERROR, "\"%s\" has no \"%s\" property", LED_HARDWARE_PROPERTY_NAME, LED_HARDWARE_PROPERTY_PROP_NAME); goto _pthp_end; } /* type of property */ if(! (type = nft_prefs_node_prop_string_get(child, LED_HARDWARE_PROPERTY_PROP_TYPE))) { NFT_LOG(L_ERROR, "\"%s\" has no \"%s\" property", LED_HARDWARE_PROPERTY_NAME, LED_HARDWARE_PROPERTY_PROP_TYPE); goto _pthp_end; } /* property value */ if(! (value = nft_prefs_node_prop_string_get(child, LED_HARDWARE_PROPERTY_PROP_VALUE))) { NFT_LOG(L_ERROR, "\"%s\" has no \"%s\" property", LED_HARDWARE_PROPERTY_NAME, LED_HARDWARE_PROPERTY_PROP_VALUE); goto _pthp_end; } /* decide about type */ switch (led_hardware_plugin_prop_type_from_string (type)) { /* int */ case LED_HW_CUSTOM_PROP_INT: { int integer; if(sscanf(value, "%32d", &integer) != 1) { NFT_LOG(L_ERROR, "Failed to parse integer from \"%s\" property (\"%s\")", LED_HARDWARE_PROPERTY_PROP_VALUE, value); goto _pthp_end; } if(!led_hardware_plugin_prop_set_int (h, name, integer)) { NFT_LOG(L_ERROR, "Failed to set \"%s\" = %d)", name, integer); goto _pthp_end; } break; } /* float */ case LED_HW_CUSTOM_PROP_FLOAT: { float f; if(sscanf(value, "%64f", &f) != 1) { NFT_LOG(L_ERROR, "Failed to parse float from \"%s\" property (\"%s\")", LED_HARDWARE_PROPERTY_PROP_VALUE, value); goto _pthp_end; } if(!led_hardware_plugin_prop_set_float (h, name, f)) { NFT_LOG(L_ERROR, "Failed to set \"%s\" = %f)", name, f); goto _pthp_end; } break; } /* string */ case LED_HW_CUSTOM_PROP_STRING: { if(!led_hardware_plugin_prop_set_string(h, name, value)) { NFT_LOG(L_ERROR, "Failed to set \"%s\" = \"%s\")", name, value); goto _pthp_end; } break; } /* huh? */ default: { NFT_LOG(L_ERROR, "Invalid plugin-property type: \"%s\"", type); break; } } _pthp_end: nft_prefs_free(name); nft_prefs_free(type); nft_prefs_free(value); continue; } else { NFT_LOG(L_WARNING, "Attempt to add \"%s\" node to hardware. Not allowed. (Ignoring node)", nft_prefs_node_get_name(child)); continue; } } /* everything pico bello */ r = NFT_SUCCESS; _pth_end: /* free strings */ nft_prefs_free(id); nft_prefs_free(plugin_name); nft_prefs_free(name); /* newly created hardware object */ *newObj = h; return r; }
/** * check if NftPrefsNode represents a chain object * * @param n LedPrefsNode * @result true if node represents a chain object, false otherwise */ bool led_prefs_is_chain_node(LedPrefsNode * n) { return (strcmp(nft_prefs_node_get_name(n), LED_CHAIN_NAME) == 0); }
/** * Config-to-Object function. * Creates a LedHardware model from a prefs node * @note you shouldn't call this function directly * It's used by nft_prefs_obj_from_node() etc. */ static NftResult _prefs_to_chain(LedPrefs * p, void **newObj, NftPrefsNode * n, void *userptr) { if(!p || !newObj) NFT_LOG_NULL(NFT_FAILURE); /* LedCount of chain */ int ledcount = 0; if(!nft_prefs_node_prop_int_get (n, LED_CHAIN_PROP_LEDCOUNT, &ledcount)) { NFT_LOG(L_WARNING, "chain has no \"%s\" property. Using %d as default.", LED_CHAIN_PROP_LEDCOUNT, ledcount); } /* new chain */ LedChain *c; /* get format of this chain */ char *format; if(!(format = nft_prefs_node_prop_string_get(n, LED_CHAIN_PROP_FORMAT))) { #define LED_CHAIN_DEFAULT_FORMAT "RGB u8" NFT_LOG(L_WARNING, "chain has no \"%s\" property. Using \"%s\" as default.", LED_CHAIN_PROP_FORMAT, LED_CHAIN_DEFAULT_FORMAT); /* new chain (with default format) */ if(!(c = led_chain_new((LedCount) ledcount, LED_CHAIN_DEFAULT_FORMAT))) { NFT_LOG(L_ERROR, "Failed to create new LedSetup object"); return NFT_FAILURE; } /* free string */ nft_prefs_free(format); } /* create new chain with given format */ else { /* new chain */ if(!(c = led_chain_new(ledcount, format))) { NFT_LOG(L_ERROR, "Failed to create new LedSetup object"); return NFT_FAILURE; } } /* free string */ nft_prefs_free(format); /* process child nodes (LEDs) */ NftPrefsNode *child; LedCount i = 0; for(child = nft_prefs_node_get_first_child(n); child; child = nft_prefs_node_get_next(child)) { /* check if node describes a Led object */ if(!led_prefs_is_led_node(child)) { NFT_LOG(L_ERROR, "\"chain\" may only contain \"%s\" children. Skipping \"%s\".", LED_LED_NAME, nft_prefs_node_get_name(child)); continue; } /* create Led from node */ Led *l = led_chain_get_nth(c, i++); if(!led_prefs_led_from_node(p, child, l)) goto _ptc_error; } /* save new chain-object to "newObj" pointer */ *newObj = c; return NFT_SUCCESS; _ptc_error: led_chain_destroy(c); return NFT_FAILURE; }
/** * Config-to-Object function. * Creates a LedSetup model from a prefs node * @note you shouldn't call this function directly * It's used by nft_prefs_obj_from_node() etc. */ static NftResult _prefs_to_setup(LedPrefs * p, void **newObj, NftPrefsNode * n, void *userptr) { if(!p || !newObj) NFT_LOG_NULL(NFT_FAILURE); /* new setup */ LedSetup *s; /* new setup */ if(!(s = led_setup_new())) { NFT_LOG(L_ERROR, "Failed to create new LedSetup object"); return NFT_FAILURE; } /* walk all child nodes and process them */ NftPrefsNode *child; for(child = nft_prefs_node_get_first_child(n); child; child = nft_prefs_node_get_next(child)) { /* check if node describes a LedHardware object */ if(!led_prefs_is_hardware_node(child)) { NFT_LOG(L_ERROR, "\"%s\" object may only contain \"%s\" children but got \"%s\"", LED_SETUP_NAME, LED_HARDWARE_NAME, nft_prefs_node_get_name(child)); goto _pts_error; } /* call toObj function of child node */ LedHardware *hw; if(!(hw = nft_prefs_obj_from_node(p, child, userptr))) { NFT_LOG(L_ERROR, "Failed to create object from preference node"); return NFT_FAILURE; } /* register first hardware */ if(!led_setup_get_hardware(s)) { led_setup_set_hardware(s, hw); } /* attach hardware to list */ else { if(!led_hardware_list_append_head (led_setup_get_hardware(s), hw)) { NFT_LOG(L_ERROR, "Failed to append LedHardware as sibling"); return NFT_FAILURE; } } } /* save new setup-object to "newObj" pointer */ *newObj = s; return NFT_SUCCESS; _pts_error: led_setup_destroy(s); return NFT_FAILURE; }