diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d59b95e..159d4ad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ pkg_check_modules(RPM REQUIRED rpm) pkg_check_modules(SQLITE3 REQUIRED sqlite3) pkg_check_modules(LIBUNWIND REQUIRED libunwind) pkg_check_modules(LIBDW REQUIRED libdw) +pkg_check_modules(LIBXML2 REQUIRED libxml-2.0) find_library(LIBIBERTY NAMES iberty) include_directories(include) @@ -44,11 +45,19 @@ target_link_libraries(distromatic ${RPM_LIBRARIES} ${ZLIB_LIBRARIES} ${SQLITE3_LIBRARIES} + ${LIBREPO_LIBRARIES} + ${LIBXML2_LIBRARIES} ${LIBUNWIND_LIBRARIES} ${LIBDW_LIBRARIES} ${LIBIBERTY} ) -target_include_directories(distromatic PUBLIC ${RPM_INCLUDE_DIRS} ${LIBUNWIND_INCLUDE_DIRS}) +target_include_directories(distromatic PUBLIC + ${RPM_INCLUDE_DIRS} + ${LIBREPO_INCLUDE_DIRS} + ${LIBXML2_INCLUDE_DIRS} + ${LIBUNWIND_INCLUDE_DIRS} +) + # # NOTE: -fno-toplevel-reorder required to prevent Sqlite3 weird problems # @@ -68,11 +77,18 @@ target_link_libraries(distroquery ${RPM_LIBRARIES} ${ZLIB_LIBRARIES} ${SQLITE3_LIBRARIES} + ${LIBREPO_LIBRARIES} + ${LIBXML2_LIBRARIES} ${LIBUNWIND_LIBRARIES} ${LIBDW_LIBRARIES} ${LIBIBERTY} ) -target_include_directories(distroquery PUBLIC ${RPM_INCLUDE_DIRS} ${LIBUNWIND_INCLUDE_DIRS}) +target_include_directories(distroquery PUBLIC + ${RPM_INCLUDE_DIRS} + ${LIBREPO_INCLUDE_DIRS} + ${LIBXML2_INCLUDE_DIRS} + ${LIBUNWIND_INCLUDE_DIRS} +) install( TARGETS distromatic diff --git a/src/functions.c b/src/functions.c index e863008..05bd673 100644 --- a/src/functions.c +++ b/src/functions.c @@ -244,10 +244,12 @@ struct configTag* read_configuration(const char *confFile) curraltrep++; } else if (!strcmp(vartok, "HTML_DIR")) { currconfigtag->html_dir = (char *) strdup(valuetok); - } else if (!strcmp(vartok, "DOWNLOAD_PREFIX")) { + } else if (!strcmp(vartok, "DOWNLOAD_PREFIX")) { currconfigtag->download_prefix = (char *) strdup(valuetok); } else if (!strcmp(vartok, "DOWNLOAD_DIR")) { currconfigtag->download_dir = (char *) strdup(valuetok); + } else if (!strcmp(vartok, "REPODATA_URL")) { + currconfigtag->repodata_url = (char *) strdup(valuetok); } else if (!strcmp(vartok, "SHOWFILE_PREFIX")) { currconfigtag->showfile_prefix = (char *) strdup(valuetok); } else if (!strcmp(vartok, "REPOSITORY_SOURCE_DIR")) { diff --git a/src/headerlist.c b/src/headerlist.c index 08c68df..775497b 100644 --- a/src/headerlist.c +++ b/src/headerlist.c @@ -1,7 +1,7 @@ /* * distromatic - tool for RPM based repositories * - * Copyright (C) 2004-2020 by Silvan Calarco + * Copyright (C) 2004-2021 by Silvan Calarco * Copyright (C) 2006 by Davide Madrisan * * This program is free software; you can redistribute it and/or modify it under @@ -21,6 +21,10 @@ #include #include +#include +#include +#include + #ifndef H_RPMLIB # include #endif @@ -607,20 +611,350 @@ findOrCreateFileGroupListEntry(struct fileGroupList* *first,char* name, int arch return newf; } +struct repoData { + char *dir; + char *primary; + xmlDoc *primary_doc; + long primary_size; + char *filelists; + xmlDoc *filelists_doc; + long filelists_size; + char *other; + xmlDoc *other_doc; + long other_size; +}; + +xmlDoc* parseRepodataXmlGz(char* filename, long size_open) { + xmlDoc *doc = NULL; + gzFile gzIn; + + gzIn = gzopen(filename, "r"); + if (gzIn == NULL) { + logmsg(LOG_ERROR, "error opening file: %", filename); + } else { + char *buffer = malloc(size_open); + gzread(gzIn, buffer, size_open); + gzclose(gzIn); + doc = xmlReadMemory(buffer, size_open, "noname.xml", NULL, 0); + free(buffer); + } + return doc; +} + +struct repoData* getRepodata(char *repodata_url, char *arch) { + gboolean ret; + LrHandle *h; + LrResult *r; + LrYumRepoMd *repomd; + char *download_list[] = LR_RPMMD_BASEXML; + char *urls[] = { NULL, NULL }; + GError *tmp_err = NULL; + struct repoData *repodata; + + urls[0] = malloc(PATH_MAX); + if (!arch) + snprintf(urls[0], PATH_MAX, "%s/SRPMS.base/", repodata_url); + else + snprintf(urls[0], PATH_MAX, "%s/RPMS.%s/", repodata_url, arch); + + h = lr_handle_init(); + r = lr_result_init(); + + lr_handle_setopt(h, NULL, LRO_URLS, urls); + lr_handle_setopt(h, NULL, LRO_REPOTYPE, LR_YUMREPO); + lr_handle_setopt(h, NULL, LRO_YUMDLIST, download_list); + + // Create temporary directory + char template[] = "/tmp/distromatic.tmp.XXXXXX"; + char *dir_name = mkdtemp(template); + if(dir_name == NULL) + { + perror("mkdtemp failed: "); + return NULL; + } + repodata = malloc(sizeof(struct repoData)); + repodata->dir = strdup(dir_name); + lr_handle_setopt(h, NULL, LRO_DESTDIR, dir_name); + + ret = lr_handle_perform(h, r, &tmp_err); + if (!ret) { + logmsg(LOG_ERROR, "cannot get repodata: %d: %s\n", + tmp_err->code, tmp_err->message); + g_error_free(tmp_err); + lr_result_free(r); + lr_handle_free(h); + return NULL; + } + + lr_result_getinfo(r, &tmp_err, LRR_YUM_REPOMD, &repomd); + + if (!tmp_err) { + char filename[PATH_MAX]; + for (GSList *elem = repomd->records; elem; elem = g_slist_next(elem)) { + LrYumRepoMdRecord *rec = (LrYumRepoMdRecord *) elem->data; + if (!strcmp(rec->type, "primary")) { + repodata->primary = strdup(rec->location_href); + snprintf(filename, PATH_MAX, "%s/%s", repodata->dir, + repodata->primary); + repodata->primary_doc = parseRepodataXmlGz(filename, + rec->size_open); + } else if (!strcmp(rec->type, "filelists")) { + repodata->filelists = strdup(rec->location_href); + snprintf(filename, PATH_MAX, "%s/%s", repodata->dir, + repodata->filelists); + repodata->filelists_doc = parseRepodataXmlGz(filename, + rec->size_open); + } else if (!strcmp(rec->type, "other")) { + repodata->other = strdup(rec->location_href); + snprintf(filename, PATH_MAX, "%s/%s", repodata->dir, + repodata->other); + repodata->other_doc = parseRepodataXmlGz(filename, + rec->size_open); + } + /*printf(" Type: %s\n", rec->type); + printf(" Location href: %s\n", rec->location_href); + if (rec->location_base) + printf(" Location base: %s\n", rec->location_base); + if (rec->checksum) + printf(" Checksum: %s\n", rec->checksum); + if (rec->checksum_type) + printf(" Checksum type: %s\n", rec->checksum_type); + if (rec->checksum_open) + printf(" Checksum open: %s\n", rec->checksum_open); + if (rec->checksum_open_type) + printf(" Checksum open type: %s\n", rec->checksum_open_type); + if (rec->timestamp > 0) + printf(" Timestamp: %"G_GINT64_FORMAT"\n", rec->timestamp); + if (rec->size > 0) + printf(" Size: %"G_GINT64_FORMAT"\n", rec->size); + if (rec->size_open > 0) + printf(" Size open: %"G_GINT64_FORMAT"\n", rec->size_open); + if (rec->db_version > 0) + printf(" Db version: %d\n", rec->db_version); + printf("------------------------------------------------\n");*/ + } + } + + lr_result_free(r); + lr_handle_free(h); + + return repodata; +} + +void cleanRepodata(struct repoData *repodata) { + char filename[PATH_MAX]; + + if (!repodata) return; + + if (repodata->dir) { + if (repodata->primary) { + snprintf(filename, PATH_MAX, "%s/%s", repodata->dir, + repodata->primary); + unlink(filename); + free(repodata->primary); + xmlFreeDoc(repodata->primary_doc); + } + if (repodata->filelists) { + snprintf(filename, PATH_MAX, "%s/%s", repodata->dir, + repodata->filelists); + unlink(filename); + free(repodata->filelists); + xmlFreeDoc(repodata->filelists_doc); + } + if (repodata->other) { + snprintf(filename, PATH_MAX, "%s/%s", repodata->dir, + repodata->other); + unlink(filename); + free(repodata->other); + xmlFreeDoc(repodata->other_doc); + } + snprintf(filename, PATH_MAX, "%s/repodata/repomd.xml", repodata->dir); + unlink(filename); + snprintf(filename, PATH_MAX, "%s/repodata", repodata->dir); + rmdir(filename); + rmdir(repodata->dir); + free(repodata->dir); + } + free(repodata); +} + +/** + * print_element_names: + * @a_node: the initial xml node to consider. + * + * Prints the names of the all the xml elements + * that are siblings or children of a given xml node. + */ +static void +print_element_names(xmlNode * a_node, int level) +{ + xmlNode *cur_node = NULL; + char *str = malloc(level + 1); + char *ptr = str; + + for (int i=0; i < level; i++) { + *ptr ++ = ' '; + } + *ptr = 0; + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + if (cur_node->children && cur_node->children->content) + printf("%snode type: Element, name: %s, content: %s\n", str, + cur_node->name, XML_GET_CONTENT(cur_node->children)); + else + printf("%snode type: Element, name: %s\n", str, cur_node->name); + if (cur_node->properties) { + xmlAttr* attribute = cur_node->properties; + while(attribute && attribute->name && attribute->children) + { + xmlChar* value = xmlNodeListGetString(cur_node->doc, attribute->children, 1); + printf ("%s | attribute %s: %s\n", str, attribute->name, value); + xmlFree(value); + attribute = attribute->next; + } + } + } + print_element_names(cur_node->children, level + 1); + } +} + +xmlChar* findXMLAttributeByName(xmlNode *node, char* name) { + xmlAttr* attribute = node->properties; + while(attribute && attribute->name && attribute->children) + { + if (!strcmp((char*)attribute->name, name)) { + xmlChar* value = xmlNodeListGetString(node->doc, attribute->children, 1); + return value; + } + attribute = attribute->next; + } + return NULL; +} + +xmlNode* findXMLPropertyByName(xmlNode *node, char* name) { + xmlNode *props_node = NULL; + + for (props_node = node->children; props_node; props_node = props_node->next) { + if (props_node->type == XML_ELEMENT_NODE && !strcmp((char*)props_node->name, name)) + return props_node; + } + return NULL; +} + +xmlNode* findXMLPackageByName(xmlNode *root_node, char* name) { + xmlNode *package_node = NULL; + xmlNode *props_node = NULL; + for (package_node = root_node->children; package_node; package_node = package_node->next) { + if (!strcmp((char*)package_node->name, "package")) { + for (props_node = package_node->children; props_node; props_node = props_node->next) { + if (props_node->type == XML_ELEMENT_NODE && !strcmp((char*)props_node->name, "name")) { + if (props_node->children && !strcmp((char*)props_node->children, name)) + return package_node; + break; + } + } + xmlChar* value = findXMLAttributeByName(package_node, "name"); + if (value) { + if (!strcmp((char*)value, name)) { + xmlFree(value); + return package_node; + } + xmlFree(value); + } + } + } + return NULL; +} + static long sourceid = 0; +void addNewToSourceHeaderList(struct headerSourceList **headersourcelist, + struct headerSourceList *newheadersourcelist, struct configTag *ct, + int altrepository) { + + struct headerSourceList *currheadersourcelist = NULL; + struct headerSourceList *prevheadersourcelist; + char warning[PATH_MAX]; + + /* if main repository (altrepository=0) packages are inserted sequentially + * otherwise the list is scanned and packages are inserted alphabetically */ + if (!altrepository) { + if (currheadersourcelist) { + currheadersourcelist->next = newheadersourcelist; + } + currheadersourcelist = newheadersourcelist; + } else { /* altrepository */ + currheadersourcelist = *headersourcelist; + prevheadersourcelist = NULL; + while ((currheadersourcelist) && + (strcasecmp(currheadersourcelist->name,newheadersourcelist->name) < 0)) { + prevheadersourcelist = currheadersourcelist; + currheadersourcelist = currheadersourcelist->next; + } + + if ((currheadersourcelist) && + (!strcmp(currheadersourcelist->name,newheadersourcelist->name))) { + /* the package is both in main and alternate repositories. + override main repository package */ + if ((currheadersourcelist->epoch > newheadersourcelist->epoch) || + ((currheadersourcelist->epoch == newheadersourcelist->epoch) && + (rpmvercmp(currheadersourcelist->version, + newheadersourcelist->version) > 0)) || + ((currheadersourcelist->epoch == newheadersourcelist->epoch) && + (rpmvercmp(currheadersourcelist->version, + newheadersourcelist->version) == 0) && + (rpmvercmp(currheadersourcelist->release, + newheadersourcelist->release) >= 0))) { + if (ct->repository_level == altrepository) { + snprintf(warning, PATH_MAX, "is older or same release of upstream package in %s (%ld:%s-%s <= %ld:%s-%s)", + ct->repository[currheadersourcelist->altrepository]->tag, + newheadersourcelist->epoch, + newheadersourcelist->version, + newheadersourcelist->release, + currheadersourcelist->epoch, + currheadersourcelist->version, + currheadersourcelist->release); + logmsg(LOG_WARNING, + "%s(source,%s): %s", + newheadersourcelist->name, + ct->repository[newheadersourcelist->altrepository]->tag, + warning); + addWarning(newheadersourcelist, warning); + } + } + newheadersourcelist->next = currheadersourcelist->next; + /* overriden package is not deallocated but referenced with currheadersourcelist->old */ + newheadersourcelist->old=currheadersourcelist; + newheadersourcelist->old->updatingparent=newheadersourcelist; + } else { + /* add the new package to the list */ + newheadersourcelist->next = currheadersourcelist; + } + if (prevheadersourcelist) { + prevheadersourcelist->next = newheadersourcelist; + } else { + *headersourcelist = newheadersourcelist; + } + } /* altrepository */ + + if (!*headersourcelist) { + /* set first pointer of the list */ + *headersourcelist = newheadersourcelist; + } + +} + int addToSourceHeaderList(struct headerSourceList **headersourcelist, struct configTag *ct, int mode, int altrepository) { char *scanpath; - struct headerSourceList *currheadersourcelist = NULL, *newheadersourcelist, - *prevheadersourcelist; + struct headerSourceList *newheadersourcelist; struct dirent **namelist; struct changeLog *changelog; Header h; char filepath[bufsize + 1]; - int n, j, arch, filenamescount, dirnamescount; + int n = 0, j, arch, filenamescount, dirnamescount; int_16 *fileflags; char **basenames, **dirnames, **usernames, **groupnames; const char* errstr; @@ -628,188 +962,196 @@ addToSourceHeaderList(struct headerSourceList **headersourcelist, struct configT char **requireversion, **requirename; uint_32 *requireflags, *dirindexes; char warning[PATH_MAX]; - rpmts ts = rpmtsCreate(); + rpmts ts; + struct repoData* repodata = NULL; if (altrepository == ct->repository_level) { scanpath = ct->repository_source_dir; + if (ct->repodata_url) repodata = getRepodata(ct->repodata_url, NULL); } else if (altrepository == -1) { // non-incremental mode scanpath = ct->repository_source_dir; altrepository = 0; + if (ct->repodata_url) repodata = getRepodata(ct->repodata_url, NULL); } else { scanpath = ct->repository[altrepository]->repository_source_dir; + if (ct->repodata_url) repodata = getRepodata(ct->repository[altrepository]->repodata_url, NULL); } - assert(scanpath != NULL); - memcpy(filepath, scanpath, strlen(scanpath) + 1); + if (repodata) { + // Use repodata + //n = atoi((char*)findXMLPropertyByName(xmlDocGetRootElement(repodata->primary_doc), "packages")); + //xmlNode* packageNode = findXMLPackageByName(xmlDocGetRootElement(repodata->other_doc), "firefox"); + //print_element_names(packageNode->children, 0); + xmlNode *package_node; + for (package_node = xmlDocGetRootElement(repodata->primary_doc)->children; + package_node; package_node = package_node->next) { + if (!strcmp((char*)package_node->name, "package")) { + newheadersourcelist = malloc(sizeof(struct headerSourceList)); + if (newheadersourcelist == NULL) return 1; - logmsg(LOG_DEBUG, "scanning source directory '%s' (%d)", scanpath, altrepository); - n = scansdir(scanpath, &namelist, sourcerpmselector, scanrpmnamecmp); - if (n < 0) { - errstr = strerror(errno); - logmsg(LOG_ERROR, "cannot scan directory '%s' (%s)", scanpath, errstr); - return 1; - } + newheadersourcelist->next = NULL; + for (arch = 0; arch < ARCHS_MAX; arch++) { + newheadersourcelist->firstchild[arch] = NULL; + } + newheadersourcelist->updatingparent = NULL; + newheadersourcelist->altrepository = altrepository; + newheadersourcelist->firstwarning = NULL; + newheadersourcelist->firstrebuild = NULL; + newheadersourcelist->old = NULL; + newheadersourcelist->id = ++sourceid; - int cnt; - for (cnt = 0; cnt < n; ++cnt) { - /* check for duplicates */ - if ((cnt < n - 1) && - (!rpmnamecmp(namelist[cnt]->d_name,namelist[cnt+1]->d_name,0))) { + newheadersourcelist->name = strdup((char*) + findXMLPropertyByName(package_node, "name")->children->content); + xmlNode *version = findXMLPropertyByName(package_node, "version"); + newheadersourcelist->epoch = atoi((char*)findXMLAttributeByName(version, "epoch")); + newheadersourcelist->version = strdup((char*)findXMLAttributeByName(version, "ver")); + newheadersourcelist->release = strdup((char*)findXMLAttributeByName(version, "rel")); + newheadersourcelist->summary = strdup((char*) + findXMLPropertyByName(package_node, "summary")->children->content); + newheadersourcelist->arch = strdup((char*) + findXMLPropertyByName(package_node, "arch")->children->content); + // hl->buildarchs = headerGetStringEntry(h, RPMTAG_BUILDARCHS); + // hl->excludearch = headerGetStringEntry(h, RPMTAG_EXCLUDEARCH); + if (findXMLPropertyByName(package_node, "description")->children) { + newheadersourcelist->description = strdup((char*) + findXMLPropertyByName(package_node, "description")->children->content); + } + char* packager = strdup((char*) + findXMLPropertyByName(package_node, "packager")->children->content); + if (!packager) { + logmsg(LOG_WARNING,"missing packager definition in package %s.",newheadersourcelist->name); + newheadersourcelist->packager = NULL; + } else { + newheadersourcelist->packager = getPackagerByName(packager,1); + if (!newheadersourcelist->packager) { + logmsg(LOG_WARNING,"cannot create '%s' packager for package %s.", + packager, newheadersourcelist->name); + } + free(packager); + } + xmlNode *format = findXMLPropertyByName(package_node, "format"); + newheadersourcelist->group = strdup((char*) + findXMLPropertyByName(format, "group")->children->content); + newheadersourcelist->license = strdup((char*) + findXMLPropertyByName(format, "license")->children->content); + //newheadersourcelist->source = strdup((char*) + newheadersourcelist->url = strdup((char*) + findXMLPropertyByName(package_node, "url")->children->content); + if (!newheadersourcelist->url) + logmsg(LOG_WARNING,"missing URL definition for package %s.", + newheadersourcelist->name); + xmlNode *ptime = findXMLPropertyByName(package_node, "time"); + newheadersourcelist->buildtime = atoi( + (char*)findXMLAttributeByName(ptime, "build")); + xmlNode *psize = findXMLPropertyByName(package_node, "size"); + newheadersourcelist->buildtime = atoi( + (char*)findXMLAttributeByName(psize, "package")); + //hl->patch = headerGetStringArrayEntry(h, RPMTAG_PATCH, &count); + + addNewToSourceHeaderList(headersourcelist, + newheadersourcelist, ct, altrepository); + } + } + + cleanRepodata(repodata); + + } else { + // Scan local repository dir + ts = rpmtsCreate(); + assert(scanpath != NULL); + memcpy(filepath, scanpath, strlen(scanpath) + 1); + logmsg(LOG_DEBUG, "scanning source directory '%s' (%d)", scanpath, altrepository); + n = scansdir(scanpath, &namelist, sourcerpmselector, scanrpmnamecmp); + if (n < 0) { + errstr = strerror(errno); + logmsg(LOG_ERROR, "cannot scan directory '%s' (%s)", scanpath, errstr); + return 1; + } + int cnt; + for (cnt = 0; cnt < n; ++cnt) { + /* check for duplicates */ + if ((cnt < n - 1) && + (!rpmnamecmp(namelist[cnt]->d_name,namelist[cnt+1]->d_name,0))) { logmsg(LOG_WARNING,"skipping old SRPM package %s",namelist[cnt]->d_name); - cnt++; - } - strcpy(&filepath[strlen(scanpath)], namelist[cnt]->d_name); + cnt++; + } + strcpy(&filepath[strlen(scanpath)], namelist[cnt]->d_name); + logmsg(LOG_DEBUG, "getting header for %s", filepath); - logmsg(LOG_DEBUG, "getting header for %s", filepath); + if (getHeader(&ts, filepath, &h)) { + errstr = strerror(errno); + logmsg(LOG_WARNING, "%s: unable to read header (%s); skipping.", + namelist[cnt]->d_name, errstr); + } else { + getPackageFiles(h, &dirindexes, &dirnames, &dirnamescount, + &basenames, &filenamescount, &usernames, &groupnames, &fileflags); - if (getHeader(&ts, filepath, &h)) { - errstr = strerror(errno); - logmsg(LOG_WARNING, - "%s: unable to read header (%s); skipping.",namelist[cnt]->d_name, errstr); - } else { - getPackageFiles(h, &dirindexes, &dirnames, &dirnamescount, - &basenames, &filenamescount, - &usernames, &groupnames, &fileflags); + newheadersourcelist = malloc(sizeof(struct headerSourceList)); + if (newheadersourcelist == NULL) return 1; - newheadersourcelist = - malloc(sizeof(struct headerSourceList)); - if (newheadersourcelist == NULL) { - return 1; - } + newheadersourcelist->next = NULL; + for (arch = 0; arch < ARCHS_MAX; arch++) { + newheadersourcelist->firstchild[arch] = NULL; + } + newheadersourcelist->updatingparent = NULL; + newheadersourcelist->altrepository = altrepository; + newheadersourcelist->firstwarning = NULL; + newheadersourcelist->firstrebuild = NULL; + newheadersourcelist->old = NULL; + newheadersourcelist->id = ++sourceid; - newheadersourcelist->next = NULL; - for (arch = 0; arch < ARCHS_MAX; arch++) { - newheadersourcelist->firstchild[arch] = NULL; - } - newheadersourcelist->updatingparent = NULL; - newheadersourcelist->altrepository = altrepository; - newheadersourcelist->firstwarning = NULL; - newheadersourcelist->firstrebuild = NULL; - newheadersourcelist->old = NULL; - newheadersourcelist->id = ++sourceid; + getPackageInfoIntoHeaderSourceList(h, newheadersourcelist); - getPackageInfoIntoHeaderSourceList(h, newheadersourcelist); + getPackageRequires(h, &requirename, &requireflags, &requireversion, + &requirecount); + newheadersourcelist->dirindex = malloc(sizeof(int) * filenamescount); + if (!newheadersourcelist->dirindex) return 1; - getPackageRequires(h, &requirename, &requireflags, - &requireversion, &requirecount); + memcpy(newheadersourcelist->dirindex, dirindexes, + sizeof(int) * filenamescount); + newheadersourcelist->dirname = + (char **) dupnargv(dirnames, dirnamescount); + newheadersourcelist->basename = + (char **) dupnargv(basenames, filenamescount); + newheadersourcelist->filenamecount = filenamescount; + newheadersourcelist->require = malloc(requirecount * + sizeof(struct Require *)); + for (j=0; j < requirecount; j++) { + newheadersourcelist->require[j] = malloc(sizeof(struct Require)); + newheadersourcelist->require[j]->name = requirename[j]; + newheadersourcelist->require[j]->flags = requireflags[j]; + newheadersourcelist->require[j]->version = requireversion[j]; + newheadersourcelist->require[j]->resolved = NULL; + } + newheadersourcelist->requirecount = requirecount; - newheadersourcelist->dirindex = - malloc(sizeof(int) * filenamescount); - if (!newheadersourcelist->dirindex) { - return 1; - } - memcpy(newheadersourcelist->dirindex, dirindexes, - sizeof(int) * filenamescount); - newheadersourcelist->dirname = - (char **) dupnargv(dirnames, dirnamescount); - newheadersourcelist->basename = - (char **) dupnargv(basenames, filenamescount); - newheadersourcelist->filenamecount = filenamescount; - - newheadersourcelist->require = malloc(requirecount * sizeof(struct Require *)); - for (j=0; j < requirecount; j++) { - newheadersourcelist->require[j] = malloc(sizeof(struct Require)); - newheadersourcelist->require[j]->name = requirename[j]; - newheadersourcelist->require[j]->flags = requireflags[j]; - newheadersourcelist->require[j]->version = requireversion[j]; - newheadersourcelist->require[j]->resolved = NULL; - } - newheadersourcelist->requirecount = requirecount; - - if (mode & GENHEADER_CHANGELOG) { + if (mode & GENHEADER_CHANGELOG) { changelog = getPackageChangelog(h, newheadersourcelist); while (changelog) { if ((!changelog->pkg) || (!changelog->text)) { snprintf(warning, PATH_MAX, "missing changelog name and/or text"); logmsg(LOG_WARNING, - "%s: missing changelog name and/or text", - newheadersourcelist->name); + "%s: missing changelog name and/or text", + newheadersourcelist->name); addWarning(newheadersourcelist, warning); } changelog = changelog->next; } - } else { - newheadersourcelist->changelog = NULL; - } + } else { + newheadersourcelist->changelog = NULL; + } - /* if main repository (altrepository=0) packages are inserted sequentially - * otherwise the list is scanned and packages are inserted alphabetically */ - if (!altrepository) { - if (currheadersourcelist) { - currheadersourcelist->next = newheadersourcelist; - } - currheadersourcelist = newheadersourcelist; - } else { /* altrepository */ - currheadersourcelist = *headersourcelist; - prevheadersourcelist = NULL; + addNewToSourceHeaderList(headersourcelist, + newheadersourcelist, ct, altrepository); - while ((currheadersourcelist) && - (strcasecmp(currheadersourcelist->name,newheadersourcelist->name) < 0)) { - prevheadersourcelist = currheadersourcelist; - currheadersourcelist = currheadersourcelist->next; - } - - if ((currheadersourcelist) && - (!strcmp(currheadersourcelist->name,newheadersourcelist->name))) { - /* the package is both in main and alternate repositories. - override main repository package */ - if ((currheadersourcelist->epoch > newheadersourcelist->epoch) || - ((currheadersourcelist->epoch == newheadersourcelist->epoch) && - (rpmvercmp - (currheadersourcelist->version, - newheadersourcelist->version) > 0)) || - ((currheadersourcelist->epoch == newheadersourcelist->epoch) && - (rpmvercmp - (currheadersourcelist->version, - newheadersourcelist->version) == 0) && - (rpmvercmp - (currheadersourcelist->release, - newheadersourcelist->release) >= 0)) - ) { - if (ct->repository_level == altrepository) { - snprintf(warning, PATH_MAX, "is older or same release of upstream package in %s (%ld:%s-%s <= %ld:%s-%s)", - ct->repository[currheadersourcelist->altrepository]->tag, - newheadersourcelist->epoch, - newheadersourcelist->version, - newheadersourcelist->release, - currheadersourcelist->epoch, - currheadersourcelist->version, - currheadersourcelist->release); - logmsg(LOG_WARNING, - "%s(source,%s): %s", - newheadersourcelist->name, - ct->repository[newheadersourcelist->altrepository]->tag, - warning); - addWarning(newheadersourcelist, warning); - } - } - newheadersourcelist->next = currheadersourcelist->next; - /* overriden package is not deallocated but referenced with currheadersourcelist->old */ - newheadersourcelist->old=currheadersourcelist; - newheadersourcelist->old->updatingparent=newheadersourcelist; - } else { - /* add the new package to the list */ - newheadersourcelist->next = currheadersourcelist; - } - if (prevheadersourcelist) { - prevheadersourcelist->next = newheadersourcelist; - } else { - *headersourcelist = newheadersourcelist; - } - } - - if (!*headersourcelist) { - /* set first pointer of the list */ - *headersourcelist = newheadersourcelist; - } /* altrepository */ - (void) headerFree(h); - } // if getHeader() - free(namelist[cnt]); - } // for - - free(namelist); - rpmtsFree(ts); + (void) headerFree(h); + } // if getHeader() + free(namelist[cnt]); + } // for + free(namelist); + rpmtsFree(ts); + } return 0; } @@ -823,7 +1165,7 @@ generateSourceHeaderList(struct configTag *ct, int mode, int incremental) for (i = 0; i <= ct->repository_level; i++) { if (ct->repository[i]) { if (addToSourceHeaderList(headersourcelist, ct, mode, i)) { - logmsg(LOG_ERROR,"Error scanning alternate SRPMs repository"); + logmsg(LOG_ERROR,"Error scanning SRPMs repository"); return 1; } } else { @@ -832,11 +1174,10 @@ generateSourceHeaderList(struct configTag *ct, int mode, int incremental) } } else { if (addToSourceHeaderList(headersourcelist, ct, mode, -1)) { - logmsg(LOG_ERROR,"Error scanning alternate SRPMs repository"); + logmsg(LOG_ERROR,"Error scanning SRPMs repository"); return 1; } } - return 0; } diff --git a/src/include/config.h b/src/include/config.h index 7ecd93d..a04d9a6 100644 --- a/src/include/config.h +++ b/src/include/config.h @@ -32,6 +32,7 @@ struct configTag { char *html_dir; char *download_prefix; char *download_dir; + char *repodata_url; char *showfile_prefix; char *arch[ARCHS_MAX]; struct headerList *headerlist[ARCHS_MAX];