/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2024 Martin Preuss, all rights reserved. * * The license for this file can be found in the file COPYING which you * should have received along with this file. ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include "./net_read.h" #include "aqhome-react/aqhome_react_p.h" #include "aqhome-react/types/unit.h" #include "aqhome-react/units/u_module.h" #include "aqhome/aqhome.h" #include #include #include #include #include #include #include /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static time_t _getNewestFiletimeFromFileList(const GWEN_STRINGLIST *sl); static AQHREACT_UNIT *_readNetworkFromFile(AQHOME_REACT *aqh, const char *filename); static GWEN_XMLNODE *_readUnitNetFileToXml(const char *sFilename); static int _readUnitNetFilesIntoList(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl, AQHREACT_UNIT_LIST *unitList); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ time_t AQHomeReact_GetNewestUnitNetFiletime(void) { GWEN_STRINGLIST *sl; time_t t1; time_t t2; sl=AQH_GetListOfMatchingDataFiles("aqhome/react/networks", "*.xml"); t1=_getNewestFiletimeFromFileList(sl); GWEN_StringList_free(sl); sl=AQH_GetListOfMatchingSysconfFiles("aqhome/react/networks", "*.xml"); t2=_getNewestFiletimeFromFileList(sl); GWEN_StringList_free(sl); return (t1>t2)?t1:t2; } int AQHomeReact_ReadUnitNetFiles(AQHOME_REACT *aqh) { GWEN_STRINGLIST *sl; sl=AQH_GetListOfMatchingSysconfFiles("aqhome/react/networks", "*.xml"); if (sl) { int rv; GWEN_StringList_Sort(sl, 1, GWEN_StringList_SortModeNoCase); rv=_readUnitNetFilesIntoList(aqh, sl, aqh->unitList); GWEN_StringList_free(sl); if (rv<0) { DBG_INFO(NULL, "Error reading unit network files (%d)", rv); return rv; } } else { DBG_ERROR(NULL, "No unit network files"); } return 0; } AQHREACT_UNIT *AQHomeReact_FindAndReadDataDirNetwork(AQHOME_REACT *aqh, const char *networkName) { AQHREACT_UNIT *unit; GWEN_BUFFER *bufFilename; GWEN_BUFFER *bufPath; bufFilename=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendArgs(bufFilename, "aqhome/react/networks/%s.xml", networkName); bufPath=AQH_FindPathOfDataFile(GWEN_Buffer_GetStart(bufFilename)); if (bufPath==NULL) { DBG_ERROR(NULL, "Network file \"%s\" not found in data folders", GWEN_Buffer_GetStart(bufFilename)); GWEN_Buffer_free(bufFilename); return NULL; } GWEN_Buffer_free(bufFilename); unit=_readNetworkFromFile(aqh, GWEN_Buffer_GetStart(bufPath)); if (unit==NULL) { DBG_ERROR(NULL, "Error reading network from file \"%s\"", GWEN_Buffer_GetStart(bufPath)); GWEN_Buffer_free(bufPath); return NULL; } GWEN_Buffer_free(bufPath); return unit; } time_t _getNewestFiletimeFromFileList(const GWEN_STRINGLIST *sl) { time_t resultTime=0; if (sl) { GWEN_STRINGLISTENTRY *se; se=GWEN_StringList_FirstEntry(sl); while(se) { const char *s; s=GWEN_StringListEntry_Data(se); if (s && *s) { struct stat sb; if (stat(s, &sb)==0) { time_t t; t=sb.st_mtim.tv_sec; if (t>resultTime) resultTime=t; } else { DBG_WARN(NULL, "Error on stat(%s): %s (%d)", s, strerror(errno), errno); } } se=GWEN_StringListEntry_Next(se); } } return resultTime; } AQHREACT_UNIT *_readNetworkFromFile(AQHOME_REACT *aqh, const char *filename) { GWEN_XMLNODE *n; AQHREACT_UNIT *unit; n=_readUnitNetFileToXml(filename); if (n==NULL) { DBG_ERROR(NULL, "Error reading network file \"%s\"", filename); return NULL; } unit=AqHomeReact_UnitModule_fromXml(aqh, n); if (unit==NULL) { DBG_ERROR(NULL, "Error reading network from file \"%s\"", filename); GWEN_XMLNode_free(n); return NULL; } GWEN_XMLNode_free(n); return unit; } GWEN_XMLNODE *_readUnitNetFileToXml(const char *sFilename) { GWEN_XMLNODE *rootNode; GWEN_XMLNODE *netNode; int rv; rootNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, NULL); rv=GWEN_XML_ReadFile(rootNode, sFilename, GWEN_XML_FLAGS_DEFAULT); if (rv<0) { DBG_ERROR(NULL, "Error reading XML file \"%s\": %d", sFilename, rv); GWEN_XMLNode_free(rootNode); return NULL; } netNode=GWEN_XMLNode_FindFirstTag(rootNode, "network", NULL, NULL); if (netNode) { GWEN_XMLNode_UnlinkChild(rootNode, netNode); GWEN_XMLNode_free(rootNode); return netNode; } else { DBG_ERROR(NULL, "No \"network\" element in network file \"%s\"", sFilename); return NULL; } } int _readUnitNetFilesIntoList(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl, AQHREACT_UNIT_LIST *unitList) { GWEN_STRINGLISTENTRY *se; se=GWEN_StringList_FirstEntry(sl); while(se) { const char *s; s=GWEN_StringListEntry_Data(se); if (s && *s) { AQHREACT_UNIT *unit; DBG_INFO(NULL, "Reading unit network file \"%s\"", s); unit=_readNetworkFromFile(aqh, s); if (unit==NULL) { DBG_WARN(NULL, "No network read from network file \"%s\"", s); return GWEN_ERROR_GENERIC; } AQHREACT_Unit_List_Add(unit, unitList); } se=GWEN_StringListEntry_Next(se); } return 0; }