#include #include #include #include #include #include "rpmbuild.h" #include "xmlparse.h" #include "xmlmisc.h" #include "xmlverify.h" #include "xmlstruct.h" void handleXMLStartLevel0(t_structXMLParse* pParse) { switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { case TAGVAL_SPEC: pParse->m_pSpec = newXMLSpec(pParse->m_pAttrs, pParse->m_szXMLFile); break; default: fprintf(stderr, "warning: %s(%d): Ignoring tag \"%s\" on level %d. (Function not implemented)\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser), g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_szName, pParse->m_nLevel); pParse->m_nWarnings++; break; } } /*f (!strcasecmp(szName, "pre")) { pPkg = getLastXMLPackage(pParse->m_pSpec->m_pPackages); pPkg->m_pPre = newXMLScript(attrToStruct(szaAttrs, &(pParse->m_pAttrs))); }*/ void handleXMLStartLevel1(t_structXMLParse* pParse) { t_structXMLSpec* pSpec = NULL; pSpec = pParse->m_pSpec; switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { case TAGVAL_MACRO: addXMLMacro(pParse->m_pAttrs, &(pSpec->m_pMacros)); break; case TAGVAL_SOURCE: if (pSpec->m_pSources) addXMLSource(pParse->m_pAttrs, &(pSpec->m_pSources)); else { if ((addXMLSource(pParse->m_pAttrs, &(pSpec->m_pSources))) && (pSpec->m_pSources->m_szDirectory)) { newStr(pSpec->m_pSources->m_szDirectory, (char**)&(pSpec->m_szBuildSubdir)); } } break; case TAGVAL_PATCH: addXMLSource(pParse->m_pAttrs, &(pSpec->m_pPatches)); break; case TAGVAL_PACKAGE: addXMLPackage(pParse->m_pAttrs, &(pSpec->m_pPackages)); break; case TAGVAL_PREP: pSpec->m_pPrep = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_BUILD: pSpec->m_pBuild = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_INSTALL: pSpec->m_pInstall = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_CLEAN: pSpec->m_pClean = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_BUILDREQUIRES: case TAGVAL_CHANGELOG: // we don't need to do anything break; default: fprintf(stderr, "warning: %s(%d): Ignoring tag \"%s\" on level %d. (Function not implemented)\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser), g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_szName, pParse->m_nLevel); pParse->m_nWarnings++; break; } } void handleXMLStartLevel2(t_structXMLParse* pParse) { t_structXMLSpec* pSpec = NULL; t_structXMLSource* pSource = NULL; t_structXMLPackage* pPkg = NULL; t_structXMLScript* pScript = NULL; t_structXMLAttr* pAttr = NULL; StringBuf pSb = NULL; int nNum = 0; int nLevel = 0; char* szTmp = NULL; char* szPath = NULL; pSpec = pParse->m_pSpec; switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { case TAGVAL_SOURCEMIRROR: pSource = getLastXMLSource(pSpec->m_pSources); addXMLMirror(pParse->m_pAttrs, &(pSource->m_pMirrors)); break; case TAGVAL_PATCHMIRROR: pSource = getLastXMLSource(pSpec->m_pPatches); addXMLMirror(pParse->m_pAttrs, &(pSource->m_pMirrors)); break; case TAGVAL_BUILDREQUIRE: addXMLRequire(pParse->m_pAttrs, &(pSpec->m_pBuildRequires)); break; case TAGVAL_CHANGES: addXMLChanges(pParse->m_pAttrs, &(pSpec->m_pChangelog)); break; case TAGVAL_PRE: pPkg = getLastXMLPackage(pSpec->m_pPackages); pPkg->m_pPre = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_POST: pPkg = getLastXMLPackage(pSpec->m_pPackages); pPkg->m_pPost = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_PREUN: pPkg = getLastXMLPackage(pSpec->m_pPackages); pPkg->m_pPreUn = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_POSTUN: pPkg = getLastXMLPackage(pSpec->m_pPackages); pPkg->m_pPostUn = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_VERIFY: pPkg = getLastXMLPackage(pSpec->m_pPackages); pPkg->m_pVerify = newXMLScripts(pParse->m_pAttrs); break; case TAGVAL_FILES: pPkg = getLastXMLPackage(pSpec->m_pPackages); pPkg->m_pFiles = newXMLFiles(pParse->m_pAttrs); break; case TAGVAL_SCRIPT: // prep, build, install, clean switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel-1]].m_nValue) { case TAGVAL_PREP: addXMLScript(pParse->m_pAttrs, &(pSpec->m_pPrep->m_pScripts)); break; case TAGVAL_BUILD: addXMLScript(pParse->m_pAttrs, &(pSpec->m_pBuild->m_pScripts)); break; case TAGVAL_INSTALL: addXMLScript(pParse->m_pAttrs, &(pSpec->m_pInstall->m_pScripts)); break; case TAGVAL_CLEAN: addXMLScript(pParse->m_pAttrs, &(pSpec->m_pClean->m_pScripts)); break; default: break; } break; case TAGVAL_SETUPMACRO: pScript = addXMLScript(NULL, &(pSpec->m_pPrep->m_pScripts)); if ((pAttr = getXMLAttr("source", pParse->m_pAttrs))) attrSetInt(pAttr, "source", &nNum); if ((pAttr = getXMLAttr("path", pParse->m_pAttrs))) attrSetStr(pAttr, "path", &szPath); else newStrEx(pParse->m_pSpec->m_szBuildSubdir, &szPath); if ((pSource = getXMLSource(nNum, pSpec->m_pSources))) { nNum = strlen(pSource->m_szName); szTmp = pSource->m_szName+(nNum-3); pSb = newStringBuf(); nNum = 1; if (!strcasecmp(szTmp, "bz2")) { szTmp = NULL; newStrEx("%{_bzip2bin} -dc ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); } else if (!strcasecmp(szTmp, ".gz")) { szTmp = NULL; newStrEx("%{_gzipbin} -dc ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); } else if (!strcasecmp(szTmp, "tgz")) { szTmp = NULL; newStrEx("%{_gzipbin} -dc ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); } else if (!strcasecmp(szTmp, "zip")) { szTmp = NULL; newStrEx("%{_unzipbin} ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); nNum = 0; } else if (!strcasecmp(szTmp, "tar")) { szTmp = NULL; newStrEx("cat ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); } else { fprintf(stderr, "error: %s(%d): Invalid compressed format for source in \"setup\" script.\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser)); pParse->m_nErrors++; freeStr(&szPath); freeStringBuf(pSb); return; } if (nNum && pParse->m_nVerbose) appendStringBuf(pSb, " | tar -xvvf -"); else if (nNum) appendStringBuf(pSb, " | tar -xf -"); appendLineStringBuf(pSb, ""); appendLineStringBuf(pSb, "STATUS=$?"); appendLineStringBuf(pSb, "if [ $STATUS -ne 0 ]; then"); appendLineStringBuf(pSb, " exit $STATUS"); appendLineStringBuf(pSb, "fi"); appendStringBuf(pSb, "cd "); appendStringBuf(pSb, szPath); appendLineStringBuf(pSb, ""); newStr(getStringBuf(pSb), (char**)&(pScript->m_szEntry)); freeStringBuf(pSb); freeStr(&szTmp); freeStr(&szPath); } else { freeStr(&szPath); fprintf(stderr, "error: %s(%d): Invalid \"setup\" script. Source not available.\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser)); pParse->m_nErrors++; } break; case TAGVAL_PATCHMACRO: pScript = addXMLScript(NULL, &(pSpec->m_pPrep->m_pScripts)); if ((pAttr = getXMLAttr("patch", pParse->m_pAttrs))) attrSetInt(pAttr, "patch", &nNum); if ((pAttr = getXMLAttr("path", pParse->m_pAttrs))) attrSetStr(pAttr, "path", &szPath); else newStrEx(pParse->m_pSpec->m_szBuildSubdir, &szPath); if ((pAttr = getXMLAttr("level", pParse->m_pAttrs))) attrSetInt(pAttr, "level", &nLevel); if ((pSource = getXMLSource(nNum, pSpec->m_pPatches))) { pSb = newStringBuf(); newStrEx("cd %{_builddir}", &szTmp); appendLineStringBuf(pSb, szTmp); freeStr(&szTmp); appendStringBuf(pSb, "cd "); appendStringBuf(pSb, szPath); appendLineStringBuf(pSb, ""); nNum = strlen(pSource->m_szName); szTmp = pSource->m_szName+(nNum-3); nNum = 1; if (!strcasecmp(szTmp, "bz2")) { szTmp = NULL; newStrEx("%{_bzip2bin} -dc ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); } else if (!strcasecmp(szTmp, ".gz")) { szTmp = NULL; newStrEx("%{_gzipbin} -dc ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); } else { szTmp = NULL; newStrEx("cat ", &szTmp); appendStringBuf(pSb, szTmp); appendStringBuf(pSb, pSource->m_szName); } freeStr(&szTmp); szTmp = malloc(strlen(" > patch -pN1234567890 -s ")+strlen(pSource->m_szName)+1); sprintf(szTmp, " | patch -Np%d -s", nLevel); appendStringBuf(pSb, szTmp); appendLineStringBuf(pSb, ""); appendLineStringBuf(pSb, "STATUS=$?"); appendLineStringBuf(pSb, "if [ $STATUS -ne 0 ]; then"); appendLineStringBuf(pSb, " exit $STATUS"); appendLineStringBuf(pSb, "fi"); appendLineStringBuf(pSb, ""); newStr(getStringBuf(pSb), (char**)&(pScript->m_szEntry)); freeStringBuf(pSb); freeStr(&szTmp); freeStr(&szPath); } else { freeStr(&szPath); fprintf(stderr, "error: %s(%d): Invalid \"patch\" script. Patch not available.\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser)); pParse->m_nErrors++; } break; case TAGVAL_SUMMARY: case TAGVAL_DESCRIPTION: case TAGVAL_REQUIRES: case TAGVAL_PROVIDES: case TAGVAL_OBSOLETES: case TAGVAL_CONFLICTS: // we don't need to do anything break; default: fprintf(stderr, "warning: %s(%d): Ignoring tag \"%s\" on level %d. (Function not implemented)\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser), g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_szName, pParse->m_nLevel); pParse->m_nWarnings++; break; } } void handleXMLStartLevel3(t_structXMLParse* pParse) { t_structXMLSpec* pSpec = NULL; t_structXMLPackage* pPkg = NULL; t_structXMLChanges* pChanges = NULL; pSpec = pParse->m_pSpec; switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { case TAGVAL_REQUIRE: pPkg = getLastXMLPackage(pSpec->m_pPackages); addXMLRequire(pParse->m_pAttrs, &(pPkg->m_pRequires)); break; case TAGVAL_PROVIDE: pPkg = getLastXMLPackage(pSpec->m_pPackages); addXMLRequire(pParse->m_pAttrs, &(pPkg->m_pProvides)); break; case TAGVAL_OBSOLETE: pPkg = getLastXMLPackage(pSpec->m_pPackages); addXMLRequire(pParse->m_pAttrs, &(pPkg->m_pObsoletes)); break; case TAGVAL_CONFLICT: pPkg = getLastXMLPackage(pSpec->m_pPackages); addXMLRequire(pParse->m_pAttrs, &(pPkg->m_pConflicts)); break; case TAGVAL_CHANGE: pChanges = getLastXMLChanges(pSpec->m_pChangelog); addXMLChange(pParse->m_pAttrs, &(pChanges->m_pChanges)); break; case TAGVAL_SCRIPT: // pre, post, ... pPkg = getLastXMLPackage(pSpec->m_pPackages); switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel-1]].m_nValue) { case TAGVAL_PRE: addXMLScript(pParse->m_pAttrs, &(pPkg->m_pPre->m_pScripts)); break; case TAGVAL_POST: addXMLScript(pParse->m_pAttrs, &(pPkg->m_pPost->m_pScripts)); break; case TAGVAL_PREUN: addXMLScript(pParse->m_pAttrs, &(pPkg->m_pPreUn->m_pScripts)); break; case TAGVAL_POSTUN: addXMLScript(pParse->m_pAttrs, &(pPkg->m_pPostUn->m_pScripts)); break; case TAGVAL_VERIFY: addXMLScript(pParse->m_pAttrs, &(pPkg->m_pVerify->m_pScripts)); break; default: break; } break; default: fprintf(stderr, "warning: %s(%d): Ignoring tag \"%s\" on level %d. (Function not implemented)\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser), g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_szName, pParse->m_nLevel); pParse->m_nWarnings++; break; } } void startXMLCB(void* pData, const XML_Char* szName, const XML_Char** szaAttrs) { t_structXMLParse* pParse = NULL; int nTagPos; if (!(pParse = (t_structXMLParse*)pData)) return; if ((nTagPos = verifyXMLPath(szName, pParse)) == -1) { pParse->m_nLevel++; return; } if (verifyXMLAttrs(szaAttrs, pParse, nTagPos) == -1) { pParse->m_nLevel++; return; } pParse->m_naTree[pParse->m_nLevel] = nTagPos; switch (pParse->m_nLevel) { case 0: handleXMLStartLevel0(pParse); break; case 1: handleXMLStartLevel1(pParse); break; case 2: handleXMLStartLevel2(pParse); break; case 3: handleXMLStartLevel3(pParse); break; default: fprintf(stderr, "warning: %s(%d): XML tag nesting of %d levels not handled Ignoring tag \"%s\".\n", pParse->m_szXMLFile, XML_GetCurrentLineNumber(pParse->m_pParser), pParse->m_nLevel, szName); pParse->m_nWarnings++; break; } pParse->m_nLevel++; pParse->m_nLastGoodLevel = pParse->m_nLevel; return; } void handleXMLEndLevel0(t_structXMLParse* pParse) { t_structXMLSpec* pSpec = NULL; pSpec = pParse->m_pSpec; switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { default: break; } } void handleXMLEndLevel1(t_structXMLParse* pParse) { t_structXMLSpec* pSpec = NULL; t_structXMLMacro* pMacro = NULL; pSpec = pParse->m_pSpec; switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { case TAGVAL_MACRO: pMacro = getLastXMLMacro(pSpec->m_pMacros); newStr(pParse->m_szValue, &(pMacro->m_szValue)); break; default: break; } } void handleXMLEndLevel2(t_structXMLParse* pParse) { t_structXMLSpec* pSpec = NULL; t_structXMLPackage* pPkg = NULL; t_structXMLScript* pScript = NULL; pSpec = pParse->m_pSpec; switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { case TAGVAL_SUMMARY: pPkg = getLastXMLPackage(pSpec->m_pPackages); newStrEx(pParse->m_szValue, &(pPkg->m_szSummary)); break; case TAGVAL_DESCRIPTION: pPkg = getLastXMLPackage(pSpec->m_pPackages); newStrEx(pParse->m_szValue, &(pPkg->m_szDescription)); break; case TAGVAL_SCRIPT: switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel-1]].m_nValue) { case TAGVAL_PREP: pScript = getLastXMLScript(pSpec->m_pPrep->m_pScripts); break; case TAGVAL_BUILD: pScript = getLastXMLScript(pSpec->m_pBuild->m_pScripts); break; case TAGVAL_INSTALL: pScript = getLastXMLScript(pSpec->m_pInstall->m_pScripts); break; case TAGVAL_CLEAN: pScript = getLastXMLScript(pSpec->m_pClean->m_pScripts); break; default: break; } if (pScript) newStrEx(pParse->m_szValue, (char**)&(pScript->m_szEntry)); break; default: break; } } void handleXMLEndLevel3(t_structXMLParse* pParse) { t_structXMLSpec* pSpec = NULL; t_structXMLPackage* pPkg = NULL; t_structXMLScript* pScript = NULL; pSpec = pParse->m_pSpec; switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel]].m_nValue) { case TAGVAL_SCRIPT: pPkg = getLastXMLPackage(pSpec->m_pPackages); switch (g_pXMLTags[pParse->m_naTree[pParse->m_nLevel-1]].m_nValue) { case TAGVAL_PRE: pScript = getLastXMLScript(pPkg->m_pPre->m_pScripts); break; case TAGVAL_POST: pScript = getLastXMLScript(pPkg->m_pPost->m_pScripts); break; case TAGVAL_PREUN: pScript = getLastXMLScript(pPkg->m_pPreUn->m_pScripts); break; case TAGVAL_POSTUN: pScript = getLastXMLScript(pPkg->m_pPostUn->m_pScripts); break; case TAGVAL_VERIFY: pScript = getLastXMLScript(pPkg->m_pVerify->m_pScripts); break; default: break; } if (pScript) newStrEx(pParse->m_szValue, (char**)&(pScript->m_szEntry)); break; default: break; } } void endXMLCB(void* pData, const XML_Char* szName) { t_structXMLParse* pParse = NULL; if ((pParse = (t_structXMLParse*)pData)) { pParse->m_nLevel--; switch (pParse->m_nLevel) { case 0: handleXMLEndLevel0(pParse); break; case 1: handleXMLEndLevel1(pParse); break; case 2: handleXMLEndLevel2(pParse); break; case 3: handleXMLEndLevel3(pParse); break; default: break; } freeStr(&(pParse->m_szValue)); } } void dataXMLCB(void* pData, const XML_Char* szValue, int nLen) { t_structXMLParse* pParse = NULL; char* szVal = NULL; char* szTmp = NULL; if ((pParse = (t_structXMLParse*)pData)) { szVal = malloc(nLen+2); szVal[nLen] = '\0'; snprintf(szVal, nLen+1, "%s", szValue); if (strlen(szVal)) { while ((szTmp = strchr(szVal, '\t'))) *szTmp = ' '; if (pParse->m_szValue) { szTmp = malloc(strlen(szVal)+strlen(pParse->m_szValue)+1); sprintf(szTmp, "%s%s", pParse->m_szValue, szVal); newStr(szTmp, &(pParse->m_szValue)); free(szTmp); } else newStr(szVal, &(pParse->m_szValue)); } free(szVal); } } t_structXMLSpec* parseXMLSpec(const char* szFile, int nVerbose) { XML_Parser pParser = NULL; t_structXMLParse* pSParse = NULL; t_structXMLSpec* pSpec = NULL; FILE* fIn = NULL; int nLen = 0; char szBuffer[1024+1]; pSParse = malloc(sizeof(t_structXMLParse)); pSParse->m_szXMLFile = (char*)szFile; pSParse->m_szValue = NULL; pSParse->m_nLevel = 0; pSParse->m_nLastGoodLevel = 0; pSParse->m_nWarnings = 0; pSParse->m_nErrors = 0; pSParse->m_pSpec = NULL; pSParse->m_pAttrs = NULL; pSParse->m_nVerbose = nVerbose; if ((fIn = fopen(szFile, "r"))) { if ((pParser = XML_ParserCreate(NULL))) { pSParse->m_pParser = pParser; XML_SetStartElementHandler(pParser, &startXMLCB); XML_SetEndElementHandler(pParser, &endXMLCB); XML_SetCharacterDataHandler(pParser, &dataXMLCB); XML_SetUserData(pParser, pSParse); while (!feof(fIn)) { nLen = fread(szBuffer, sizeof(char), 1024, fIn); if (!XML_Parse(pParser, szBuffer, nLen, 0)) { fprintf(stderr, "fatal: %s(%d): %s \n", szFile, XML_GetCurrentLineNumber(pParser), XML_ErrorString(XML_GetErrorCode(pParser))); pSParse->m_nErrors++; } } if (nVerbose) printf("+ XML parse completed with %d error(s), %d warning(s).\n", pSParse->m_nErrors, pSParse->m_nWarnings); XML_Parse(pParser, szBuffer, 0, 1); XML_ParserFree(pParser); } fclose(fIn); } else { free(pSParse); fprintf(stderr, "fatal: Open of \"%s\" failed.\n", szFile); return NULL; } freeXMLAttr(&(pSParse->m_pAttrs)); if (pSParse->m_nErrors) freeXMLSpec(&(pSParse->m_pSpec)); pSpec = pSParse->m_pSpec; free(pSParse); return pSpec; }