distromatic/src/reports.c

2089 lines
79 KiB
C

/*
* distromatic - tool for RPM based repositories
*
* Copyright (C) 2004-2022 by Silvan Calarco <silvan.calarco@mambasoft.it>
* Copyright (C) 2006 by Davide Madrisan <davide.madrisan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of version 2 of the GNU General Public License as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, to the extent permitted by law; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <linux/limits.h>
#include "distromatic.h"
#include "changelog.h"
#include "reports.h"
#include "rpmfunctions.h"
#include "functions.h"
#include "requirelist.h"
#include <errno.h>
#include <time.h>
#define HTMLSTATS_NUM 400
#define HTMLOLDSTATS_NUM 400
#define RSSSTATS_NUM 20
char *groupdirname(char *group,char *dest)
{
strcpy(dest,group);
unsigned int i=0;
while (dest[i] && i<PATH_MAX) {
switch (dest[i]) {
case '/': dest[i]=':'; break;
case ' ': dest[i]='_'; break;
default: break;
}
i++;
}
return dest;
}
int
comparePackagers(const void *ptr1, const void *ptr2)
{
int ret;
if (! (*(struct headerSourceList **)ptr1)->packager) return -1;
else if (! (*(struct headerSourceList **)ptr2)->packager) return +1;
else {
ret=strcasecmp((*(struct headerSourceList **)ptr1)->packager->name,
(*(struct headerSourceList **)ptr2)->packager->name);
if (!ret) {
ret=strcasecmp((*(struct headerSourceList **)ptr1)->name,
(*(struct headerSourceList **)ptr2)->name);
}
return ret;
}
}
int
printHTMLWarnings(FILE *fout, struct configTag *configtag, struct headerSourceList* pkg, int mode) {
char warningsfile[PATH_MAX];
char buf[PATH_MAX];
struct stat s;
FILE *fin;
int n;
struct warningList *firstwarning,*currwarning;
if (!pkg) return 0;
snprintf(warningsfile,PATH_MAX,"%swarnings/%s.in",configtag->html_dir,pkg->name);
/* find pointer to first warning also looking into old packages */
firstwarning = pkg->firstwarning;
while (!firstwarning && pkg->old) {
pkg = pkg->old;
firstwarning = pkg->firstwarning;
}
if (firstwarning || !stat(warningsfile,&s)) {
if (mode == 0) {
fprintf(fout,
"<img src=\"%s/warning-icon.png\" title=\"",
configtag->configdefaults->url_dir);
} else if (mode == 1) {
fprintf(fout,
"<div class=\"warning\"><img src=\"%s/warning-icon.png\" title=\"Beware: this package has warnings.\">&nbsp;<b>Beware, this package has warnings:</b><br>",
configtag->configdefaults->url_dir);
}
}
if (!stat(warningsfile,&s)) {
if ((fin = fopen(warningsfile, "r")) == NULL) {
perror(warningsfile);
return 0;
}
fprintf(fout,"&nbsp;&bull;&nbsp;Comment:");
while (!feof(fin)) {
n = fread(buf, 1, sizeof(buf), fin);
fwrite(buf,1,n,fout);
}
if (mode == 0) {
fprintf(fout,"\n");
} else if (mode == 1) {
fprintf(fout,"<br>");
}
fclose(fin);
}
currwarning = firstwarning;
while (currwarning || pkg->old) {
if (currwarning) {
if (mode == 0) {
fprintf(fout,"&nbsp;&bull;&nbsp;%s\n",currwarning->text);
} else if (mode == 1) {
fprintf(fout,"&nbsp;&bull;&nbsp;%s<br>",currwarning->text);
} else if (mode == 2) {
fprintf(fout,"%s %s\n",pkg->name,currwarning->text);
}
currwarning = currwarning->next;
}
while (!currwarning && pkg->old) {
/* print warnings coming from updated packages */
pkg = pkg->old;
currwarning = pkg->firstwarning;
}
}
if (firstwarning || !stat(warningsfile,&s)) {
if (mode == 0) {
fprintf(fout,"\">");
} else if (mode == 1) {
fprintf(fout,"</div><br>\n");
}
return 1;
}
return 0;
}
void printpkgicon(FILE *fout, struct configTag *configtag, struct headerSourceList *s) {
char buffer[PATH_MAX];
char strdate[16];
int i;
if (s->old) {
fprintf(fout,
"<img src=\"%s/pkgup.png\" ",
configtag->configdefaults->url_dir);
} else {
fprintf(fout,
"<img src=\"%s/pkg.png\" ",
configtag->configdefaults->url_dir);
}
if (s->changelog) {
simpleTimeToHuman(s->changelog->time, (humanDate *) & strdate);
fprintf(fout,
"title=\"%s - %s (%s)\n%s",
strdate,
s->changelog->pkg->name,
s->changelog->release,
htmlcleanNoBr(s->changelog->text,buffer,PATH_MAX));
if (s->changelog->next) {
simpleTimeToHuman(s->changelog->next->time, (humanDate *) & strdate);
fprintf(fout,
"\n%s - %s (%s)\n%s",
strdate,
s->changelog->next->pkg->name,
s->changelog->next->release,
htmlcleanNoBr(s->changelog->next->text,buffer,PATH_MAX));
}
} else {
fprintf(fout,
"title=\"WARNING: missing changelog");
}
fprintf(fout,"\n\nArchs:");
for (i = 0; i < ARCHS_MAX && configtag->arch[i]; i++) {
if (s->firstchild[i]) fprintf(fout," %s", configtag->arch[i]);
}
if (s->old) {
fprintf(fout,
"\n\nUpdates %s(%s,%s,%ld:%s-%s)\">",
s->old->name,
configtag->repository[s->old->altrepository]->tag,
s->old->arch,
s->old->epoch,
s->old->version,
s->old->release);
} else {
fprintf(fout, "\">");
}
}
int
generateMaintainersPages(struct configTag *configtag)
{
char idxfile[PATH_MAX],outfile[PATH_MAX],unmaintfile[PATH_MAX];
FILE *idx=NULL,*out=NULL,*unmaint=NULL;
int i,pkgnum,unmaintpkgnum;
struct stat buf;
struct Packager *currpackager = NULL;
/* sort headersourcelistvec by packager name */
qsort((void *) &configtag->stats.headersourcelistvec[0],
configtag->stats.headersourcecount, sizeof(struct headerSourceList *),
comparePackagers);
snprintf(outfile, PATH_MAX, "%smaintainers", configtag->html_dir);
if (stat(outfile,&buf)) {
if (mkdir(outfile,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
logmsg(LOG_ERROR,"cannot create %s directory; aborting.",outfile);
exit(1);
}
} else {
if (!S_ISDIR(buf.st_mode)) {
logmsg(LOG_ERROR,"cannot create %s directory, a file with this name already exists; aborting.",outfile);
exit(1);
}
}
snprintf(idxfile, PATH_MAX, "%s_maintainers.inc", configtag->html_dir);
if ((idx = fopen(idxfile, "w")) == NULL) {
perror(idxfile);
return 1;
}
fprintf(idx,
"<br>Maintainers for packages in the <b>%s</b> repository (%s):<br><br>\n",
configtag->tag,
configtag->description);
snprintf(unmaintfile, PATH_MAX, "%smaintainers/unmaintained.inc", configtag->html_dir);
if ((unmaint = fopen(unmaintfile, "w")) == NULL) {
perror(unmaintfile);
return 1;
}
fprintf(unmaint,
"<br>Packages that are <b>unmaintained</b> in the %s repository:<br><br>\n",configtag->tag);
i=0;
out=NULL;
pkgnum=0;
unmaintpkgnum=0;
while (i < configtag->stats.headersourcecount) {
if ((configtag->stats.headersourcelistvec[i])->packager) {
if ((i == 0) ||
((configtag->stats.headersourcelistvec[i-1])->packager != (configtag->stats.headersourcelistvec[i])->packager)) {
if ((configtag->stats.headersourcelistvec[i])->packager->role &
PACKAGER_ROLE_MAINTAINER) {
snprintf(outfile, PATH_MAX, "%smaintainers/%s.inc",
configtag->html_dir,
(configtag->stats.headersourcelistvec[i])->packager->name);
if ((out = fopen(outfile, "w")) == NULL) {
perror(outfile);
return 1;
}
fprintf(out,
"<br>Packages maintained by <b>%s</b> in the %s repository:<br><br>\n",
(configtag->stats.headersourcelistvec[i])->packager->name,
configtag->tag);
} // new maintainer file created
} // check for changed packager
if ((configtag->stats.headersourcelistvec[i])->packager->role & PACKAGER_ROLE_MAINTAINER) {
fprintf(out,
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s</a>: %s<br>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->summary);
pkgnum++;
if ((i+1 >= configtag->stats.headersourcecount) ||
((configtag->stats.headersourcelistvec[i])->packager !=
(configtag->stats.headersourcelistvec[i+1])->packager)) {
fprintf(idx,
"<a href=\"%stag=%s&amp;maintainer=%s\">%s </a>(pkg:%d; act:%5.2f%%)<br>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
configtag->stats.headersourcelistvec[i]->packager->name,
configtag->stats.headersourcelistvec[i]->packager->name,
pkgnum,
((double)(configtag->stats.headersourcelistvec[i]->packager->changes_count) * 100) / configtag->stats.changelog_total );
pkgnum=0;
fclose(out);
}
} else { // unmaintained package
fprintf(unmaint,
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s</a>: %s<br>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->summary);
unmaintpkgnum++;
}
}
i++;
} // while
fclose(unmaint);
currpackager = firstPackager();
// write stats for maintainer with 0 packages but changes (e.g. autodist)
while (currpackager) {
if ((currpackager->role & PACKAGER_ROLE_MAINTAINER) &&
(currpackager->packages_count == 0) &&
(currpackager->changes_count > 0) ) {
fprintf(idx,
"%s (pkg:%d; act:%5.2f%%)<br>\n",
currpackager->name,
0,
((double)(currpackager->changes_count) * 100) / configtag->stats.changelog_total );
}
/* else {
printf("skipped %s packages:%d changes:%d\n",currpackager->name,currpackager->packages_count,currpackager->changes_count);
}*/
currpackager = currpackager->next;
}
if (unmaintpkgnum)
fprintf(idx,
"<a href=\"%stag=%s&amp;maintainer=unmaintained\">unmaintained packages</a> (pkg:%d)<br>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
unmaintpkgnum);
fclose(idx);
return 0;
}
int
generateStats(struct configTag *configtag,int arch)
{
char outfile[PATH_MAX];
char rssfile[PATH_MAX];
char buffer[PATH_MAX];
FILE *htmlout=NULL,*htmloldout,*rssout,*groupout;
struct stat buf;
int i,pkgnum;
humanDate strdate,strolddate;
sizeString strsize;
struct tm *ytm;
time_t timesec;
timesec = time(&timesec);
ytm = localtime((time_t *) &timesec);
ytm->tm_sec = 0;
ytm->tm_min = 0;
ytm->tm_hour = 0;
ytm->tm_mday = 1;
ytm->tm_mon = 0;
timesec = mktime(ytm);
if (!configtag->configdefaults->html_basedir) {
return 2;
}
/* sort headersourcelistvec by Group */
qsort((void *) &configtag->stats.headersourcelistvec[0],
configtag->stats.headersourcecount, sizeof(struct headerSourceList *),
compareGroup);
snprintf(outfile, PATH_MAX, "%s_groups.inc", configtag->html_dir);
if ((groupout = fopen(outfile, "w")) == NULL) {
perror(outfile);
return 1;
}
/* create groups directory */
snprintf(outfile, PATH_MAX, "%sgroups",configtag->html_dir);
if (stat(outfile,&buf)) {
if (mkdir(outfile,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
logmsg(LOG_ERROR,"cannot create %s directory; aborting.",outfile);
exit(1);
}
} else {
if (!S_ISDIR(buf.st_mode)) {
logmsg(LOG_ERROR,"cannot create %s directory, a file with this name already exists; aborting.",outfile);
exit(1);
}
}
fprintf(groupout,
"<br>Groups in the <b>%s</b> repository (%s):<br><br>\n",
configtag->tag,
configtag->description);
i=0;
pkgnum=0;
if (configtag->stats.headersourcecount) do {
if (pkgnum==0) {
sprintf(outfile, "%sgroups/%s",
configtag->html_dir,
groupdirname(configtag->stats.headersourcelistvec[i]->group,buffer));
if (stat(outfile,&buf)) {
if (mkdir(outfile,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
logmsg(LOG_ERROR,"cannot create %s directory; aborting.",outfile);
exit(1);
}
} else {
if (!S_ISDIR(buf.st_mode)) {
logmsg(LOG_ERROR,"cannot create %s directory, a file with this name already exists; aborting.",outfile);
exit(1);
}
}
strncat(outfile, "/_index.inc", sizeof(outfile) - strlen(outfile));
if ((htmlout = fopen(outfile, "w")) == NULL) {
perror(outfile);
return 1;
}
fprintf(htmlout,
"<br>Packages in the <b>%s</b> group of the <b>%s</b> repository (%s):<br><br>\n",
configtag->stats.headersourcelistvec[i]->group,
configtag->tag,
configtag->description);
}
fprintf(htmlout,
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s</a>: %s<br>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->summary);
i++;
pkgnum++;
if ((i >= configtag->stats.headersourcecount) ||
(strcmp(configtag->stats.headersourcelistvec[i-1]->group,
configtag->stats.headersourcelistvec[i]->group))) {
fprintf(groupout,
"<a href=\"%stag=%s&amp;group=%s\">%s <b>(%d)</b></a><br>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
groupdirname(configtag->stats.headersourcelistvec[i-1]->group,buffer),
(configtag->stats.headersourcelistvec)[i-1]->group,
pkgnum);
pkgnum=0;
fclose(htmlout);
}
} while (i < configtag->stats.headersourcecount);
if (i>0) {
fclose(groupout);
}
strcpy(outfile, configtag->html_dir);
strncat(outfile, "_recent.inc", sizeof(outfile) - strlen(outfile));
if ((htmlout = fopen(outfile, "w")) == NULL) {
perror(outfile);
return 1;
}
/*else {
fprintf(htmlout, "<a href=\"%s/%s/recent.rss\">"
"<img src=\"%s/feed-icon.png\" "
"alt=\"RSS 2.0 news feed\"></a>",
configtag->configdefaults->url_dir,
configtag->tag,
configtag->configdefaults->url_dir);
fprintf(htmlout, "Recent builds:<br>\n");
}*/
strcpy(outfile, configtag->html_dir);
strncat(outfile, "_oldest.inc", sizeof(outfile) - strlen(outfile));
if ((htmloldout = fopen(outfile, "w")) == NULL) {
perror(outfile);
return 1;
}
/* else {
fprintf(htmloldout, "Oldest builds:<br>\n");
}*/
strcpy(rssfile, configtag->html_dir);
strncat(rssfile, "recent.rss", sizeof(rssfile) - strlen(rssfile));
if ((rssout = fopen(rssfile, "w")) == NULL) {
perror(rssfile);
return 1;
} else {
fprintf(rssout,"<?xml version=\"1.0\" ?>\n");
fprintf(rssout,"<rss version=\"2.0\">\n");
fprintf(rssout,"<channel>\n");
fprintf(rssout," <title>Recent packages for the %s repository</title>\n",configtag->tag);
fprintf(rssout," <link>http://%s/%s</link>\n",
configtag->configdefaults->url_address,
configtag->configdefaults->url_prefix);
//fprintf(rssout," <description></description>\n");
fprintf(rssout," <language>en-us</language>\n");
fprintf(rssout," <docs>http://blogs.law.harvard.edu/tech/rss</docs>");
fprintf(rssout," <generator>Distromatic %s</generator>\n",PACKAGE_VERSION);
}
/* sort headersourcelistvec by BuildDate */
qsort((void *) &configtag->stats.headersourcelistvec[0],
configtag->stats.headersourcecount, sizeof(struct headerSourceList *),
compareSourceHeaderBuildDate);
fprintf(htmlout, "<a href=\"%stag=%s\">SRPMS</a>(%d;%s)",
configtag->configdefaults->url_prefix,
configtag->tag,
configtag->stats.headersourcecount,
humanSize(configtag->stats.headersourcesize, &strsize));
for (i = 0; i < ARCHS_MAX && configtag->arch[i]; i++) {
fprintf(htmlout, " <a href=\"%stag=%s&arch=%s\">%s</a>(%d;%s) ",
configtag->configdefaults->url_prefix,
configtag->tag,
configtag->arch[i],
configtag->arch[i],
configtag->stats.headercount[i],
humanSize(configtag->stats.headersize[i], &strsize));
if (i % 2 == 0) fprintf(htmlout,"<br>");
}
if (i % 2 == 0) fprintf(htmlout,"<br>");
i=0;
while ((i < configtag->stats.headersourcecount) &&
((i < HTMLSTATS_NUM) || (i < RSSSTATS_NUM))) {
if ((configtag->stats.headersourcelistvec)[i]->buildtime < timesec) {
simpleTimeToTemplate(
(configtag->stats.headersourcelistvec)[i]->buildtime,
"%Y/%m/%d",&strdate);
} else {
simpleTimeToTemplate(
(configtag->stats.headersourcelistvec)[i]->buildtime,
"%m/%d",&strdate);
}
if (i < HTMLSTATS_NUM) {
// HTML statistics
printpkgicon(htmlout, configtag, (configtag->stats.headersourcelistvec)[i]);
fprintf(htmlout,
"<a href=\"%stag=%s&amp;pkg=%s.source\" title=\"%s\">%s %s %s-%s</a>&nbsp;",
configtag->configdefaults->url_prefix,
configtag->tag,
(configtag->stats.headersourcelistvec)[i]->name,
htmlclean((configtag->stats.headersourcelistvec)[i]->summary,buffer,PATH_MAX),
strdate,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->version,
(configtag->stats.headersourcelistvec)[i]->release);
// FIXME: warnings are printed before SRPMS warning are added below so SRPMS warning are missing in HTML pages
printHTMLWarnings(htmlout,configtag,(configtag->stats.headersourcelistvec)[i],0);
fprintf(htmlout,"<br>\n");
}
if (i < HTMLOLDSTATS_NUM) {
// HTML statistics
simpleTimeToTemplate((configtag->stats.headersourcelistvec)[configtag->stats.headersourcecount-1-i]->buildtime,"%Y/%m/%d",&strolddate);
fprintf(htmloldout,
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s %s %s-%s</a><br>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
(configtag->stats.headersourcelistvec)[configtag->stats.headersourcecount-1-i]->name,
strolddate,
(configtag->stats.headersourcelistvec)[configtag->stats.headersourcecount-1-i]->name,
(configtag->stats.headersourcelistvec)[configtag->stats.headersourcecount-1-i]->version,
(configtag->stats.headersourcelistvec)[configtag->stats.headersourcecount-1-i]->release);
}
if (i < RSSSTATS_NUM) {
// RSS recent packages
fprintf(rssout," <item>\n");
fprintf(rssout," <title>%s %s %s-%s</title>\n",
strdate,
(configtag->stats.headersourcelistvec)[i]->name,
(configtag->stats.headersourcelistvec)[i]->version,
(configtag->stats.headersourcelistvec)[i]->release);
fprintf(rssout," <link>http://%s%stag=%s&amp;pkg=%s.source</link>\n",
configtag->configdefaults->url_address,
configtag->configdefaults->url_prefix,
configtag->tag,
(configtag->stats.headersourcelistvec)[i]->name);
fprintf(rssout," </item>\n");
}
i++;
}
fclose(htmlout);
// fprintf(rssout, "</feed>\n");
fprintf(rssout, "</channel>\n");
fprintf(rssout, "</rss>\n");
fclose(rssout);
/* create APT repository file */
snprintf(outfile, PATH_MAX, "%s%s-%s.list",
configtag->html_dir,
configtag->configdefaults->distribution_name,
configtag->tag);
if ((htmlout = fopen(outfile, "w")) == NULL) {
perror(outfile);
return 1;
} else {
/* remove final slashes from download_prefix as required by apt */
strcpy(buffer, configtag->download_dir);
i=strlen(buffer);
while ((i > 0) && (buffer[i-1] == '/' )) {
buffer[i-1]='\0';
i--;
}
fprintf(htmlout, "#\n# %s %s repository sources list for APT\n#\n\n",
configtag->configdefaults->distribution_name,
configtag->tag);
fprintf(htmlout, "#\n# %s %s repository from %s\n#\n",
configtag->tag,
configtag->arch[arch],
configtag->configdefaults->url_address);
fprintf(htmlout, "rpm http://%s %s %s\n\n",
configtag->configdefaults->url_address,
buffer,
configtag->arch[arch]);
fprintf(htmlout, "#\n# %s sources repository from %s\n#\n",
configtag->tag,
configtag->configdefaults->url_address);
fprintf(htmlout, "rpm-src http://%s %s base\n\n",
configtag->configdefaults->url_address,
buffer);
fclose(htmlout);
}
/* create Changelog page */
struct tm tmdate;
tmdate.tm_min = 0;
tmdate.tm_hour = 0;
tmdate.tm_sec = 0;
tmdate.tm_year = 90;
tmdate.tm_mday = 1;
tmdate.tm_mon = 0;
snprintf(outfile, PATH_MAX, "%s_changelog.inc", configtag->html_dir);
if ((htmlout = fopen(outfile, "w")) == NULL) {
perror(outfile);
return 1;
}
fprintf(htmlout,
"<h1>Changelog for the <b>%s</b> repository (%s):</h1>\n",
configtag->tag,
configtag->description);
printChangelogSince(htmlout, configtag, &tmdate, 1);
fclose(htmlout);
return 0;
}
int
generateHTMLMainIndex(struct configTag *configtag)
{
char indexfile[PATH_MAX],buffer[PATH_MAX];
FILE *fout;
int i;
if (!configtag->configdefaults->html_basedir) {
return 2;
}
strcpy(indexfile, configtag->configdefaults->html_basedir);
strncat(indexfile, "_index.inc", sizeof(indexfile) - strlen(indexfile));
if ((fout = fopen(indexfile, "w")) == NULL) {
perror(indexfile);
return 1;
}
fprintf(fout,"<b>Available repositories:</b><br><br>\n");
while (configtag) {
fprintf(fout,
"<a href=\"%stag=%s\">%s</a>: %s<br>",
configtag->configdefaults->url_prefix,
configtag->tag,
configtag->tag,
configtag->description);
/* remove final slashes from download_prefix as required by apt */
strcpy(buffer, configtag->download_dir);
i=strlen(buffer);
while ((i > 0) && (buffer[i-1] == '/' )) {
buffer[i-1]='\0';
i--;
}
configtag = configtag->next;
}
fclose(fout);
return 0;
}
int
generateHTML_SRPMSFiles(struct configTag *configtag)
{
humanDate strdate;
char indexfile[PATH_MAX];
char htmlfile[PATH_MAX];
char warningsdir[PATH_MAX];
char buffer[PATH_MAX],buffer2[PATH_MAX];
int c,i,j,arch,idx;
char *st;
char curr_letter,curr_anchor ='a'-1;
FILE *findexout[ARCHS_MAX+1], *fout;
struct changeLog *currchangelog;
struct headerSourceList *currheadersourcelist;
struct headerList *currchild;
struct stat buf;
sizeString strsize;
// create packages directory
snprintf(buffer,PATH_MAX,"%spackages",configtag->html_dir);
if (stat(buffer,&buf)) {
if (mkdir(buffer,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
logmsg(LOG_ERROR,"cannot create %s directory; aborting.",buffer);
exit(1);
}
} else {
if (!S_ISDIR(buf.st_mode)) {
logmsg(LOG_ERROR,"cannot create %s directory, a file with this name already exists; aborting.",buffer);
exit(1);
}
}
// write an empty index.html file to avoid directory files browsing
snprintf(indexfile,PATH_MAX,"%sindex.html",configtag->html_dir);
if ((fout = fopen(indexfile, "w")) == NULL) {
perror(indexfile);
return 1;
}
fclose(fout);
// create warnings directory
snprintf(warningsdir,PATH_MAX,"%swarnings",configtag->html_dir);
if (stat(warningsdir,&buf)) {
if (mkdir(warningsdir,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
logmsg(LOG_ERROR,"cannot create %s directory; aborting.",warningsdir);
exit(1);
}
} else {
if (!S_ISDIR(buf.st_mode)) {
logmsg(LOG_ERROR,"cannot create %s directory, a file with this name already exists; aborting.",warningsdir);
exit(1);
}
}
/* open full SRPM index file */
snprintf(indexfile,PATH_MAX,"%s_index.inc",configtag->html_dir);
if ((findexout[0] = fopen(indexfile, "w")) == NULL) {
perror(indexfile);
return 1;
}
/* open arch specific SRPM index files */
for (arch = 0; arch < ARCHS_MAX; arch++) {
if (configtag->arch[arch]) {
snprintf(indexfile,PATH_MAX,"%s_index-%s.inc",configtag->html_dir,configtag->arch[arch]);
if ((findexout[arch+1] = fopen(indexfile, "w")) == NULL) {
perror(indexfile);
return 1;
}
} else {
findexout[arch+1] = NULL;
}
}
for (arch = 0; arch < ARCHS_MAX + 1 && findexout[arch]; arch++) {
fprintf(findexout[arch], "<h1><b>%s</b> - %s</h1>\n",
configtag->tag, configtag->description);
if (configtag->repository_level > 0) {
fprintf(findexout[arch],"<h2>Depends on:</h2> ");
for (c=0; c < configtag->repository_level; c++) {
fprintf(findexout[arch],"<a href=\"%stag=%s\">%s</a>&nbsp;- %s<br>",
configtag->configdefaults->url_prefix,
configtag->repository[c]->tag,
configtag->repository[c]->tag,
configtag->repository[c]->description);
}
fprintf(findexout[arch],"\n");
}
fprintf(findexout[arch], "<br><h2>List of packages:</h2>\n[ ");
// <th width=18></th><th nowrap align=left><b>Source</b></th><th nowrap align=left><b>Release</b></th><th width=100%% nowrap align=left><b>Builds</b></th></tr>\n");
for (c='a'; c <= 'z'; c++) {
fprintf(findexout[arch],"<a href=\"#%c\">%c</a>&nbsp;&nbsp;",c,c);
}
fprintf(findexout[arch]," ]<br><br><table>\n");
}
currheadersourcelist = configtag->headersourcelist;
while (currheadersourcelist) {
if ((configtag->repository_level == 0) ||
(currheadersourcelist->altrepository == configtag->repository_level)) {
curr_letter=currheadersourcelist->name[0];
if (curr_letter >= 'A' && curr_letter <= 'Z') curr_letter=curr_letter+'a'-'A';
snprintf(htmlfile,PATH_MAX,"%spackages/%s.source.inc",
configtag->html_dir,currheadersourcelist->name);
if ((fout = fopen(htmlfile, "w")) == NULL) {
perror(htmlfile);
return 1;
}
get_favicon_from_url(currheadersourcelist->url, buffer2, PATH_MAX);
fprintf(fout, "<h1><img src=\"%s\" width=\"16\" height=\"16\">"
"&nbsp;%s: %s (source)</h1><table class=\"pkgpage\" width=\"100%%\">\n",
buffer2,
currheadersourcelist->name,
htmlclean(currheadersourcelist->summary,buffer,PATH_MAX));
fprintf(fout,"<p>");
printHTMLWarnings(fout,configtag,currheadersourcelist,1);
fprintf(fout,
"<tr><td width=\"25%%\">Name:</td><td><b>%s</b></td></tr>\n",
currheadersourcelist->name);
if (currheadersourcelist->epoch > 0) {
fprintf(fout,
"<tr><td>Release:</td><td><b>%ld:%s-%s</b></td></tr>\n",
currheadersourcelist->epoch,
currheadersourcelist->version,
currheadersourcelist->release);
} else {
fprintf(fout,
"<tr><td>Release:</td><td><b>%s-%s</b></td></tr>\n",
currheadersourcelist->version,
currheadersourcelist->release);
}
/* fprintf(fout,
"<tr><td>Summary:</td><td><b>%s</b></td></tr>\n",
htmlclean(currheadersourcelist->summary,buffer,PATH_MAX));*/
fprintf(fout,
"<tr><td>Group:</td><td><a href=\"%stag=%s&amp;group=%s\">%s</a></td></tr>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
groupdirname(currheadersourcelist->group, buffer2),
htmlclean(currheadersourcelist->group,buffer,PATH_MAX));
fprintf(fout, "<tr><td>Maintainer:</td><td>");
if (currheadersourcelist->packager &&
(currheadersourcelist->packager->role & PACKAGER_ROLE_MAINTAINER)) {
fprintf(fout,
"<a href=\"%stag=%s&amp;maintainer=%s\">%s</a></td></tr>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
currheadersourcelist->packager->name,
currheadersourcelist->packager->name);
// currheadersourcelist->packager->packages_count++;
} else {
fprintf(fout,
"<a href=\"%stag=%s&amp;maintainer=unmaintained\"><b>unmaintained</b></a></td></tr>\n",
configtag->configdefaults->url_prefix,
configtag->tag);
}
fprintf(fout,
"<tr><td>Description:</td><td><font size=\"-1\">%s</font></td></tr>\n",
htmlclean(currheadersourcelist->description,buffer,PATH_MAX));
fprintf(fout,
"<tr><td>License:</td><td><font size=\"-1\">%s</font></td></tr>\n",
currheadersourcelist->license);
fprintf(fout,
"<tr><td>Size:</td><td><font size=\"-1\">%s</font></td></tr>\n",
humanSize(currheadersourcelist->size, &strsize));
if (configtag->download_prefix) {
fprintf(fout,"<tr><td>Download:</td><td><font size=\"-1\">");
fprintf(fout,"<a href=\"%s%s/SRPMS.base/%s-%s-%s.src.rpm\">%s-%s-%s.src.rpm</a>",
configtag->download_prefix,
configtag->download_dir,
currheadersourcelist->name,
currheadersourcelist->version,
currheadersourcelist->release,
currheadersourcelist->name,
currheadersourcelist->version,
currheadersourcelist->release);
fprintf(fout,"</font></td></tr>\n");
}
if (currheadersourcelist->url) {
fprintf(fout,
"<tr><td>URL:</td><td><font size=\"-1\"><a href=\"%s\" target=\"_new\">%s</a></font></td></tr>\n",
currheadersourcelist->url,
currheadersourcelist->url);
}
fprintf(fout,
"<tr><td>Specfile:</td><td><font size=\"-1\"><a href=\"%s%s/specs/%s.spec\">%s.spec</a>",
configtag->showfile_prefix,
configtag->download_dir,
currheadersourcelist->name,
currheadersourcelist->name);
if (currheadersourcelist->source) {
fprintf(fout,"<tr><td>Sources:</td><td><font size=\"-1\">");
i=0;
while (currheadersourcelist->source[i+1]) i++;
for (; i>=0; i--) fprintf(fout,"%s ",currheadersourcelist->source[i]);
fprintf(fout,"</font></td></tr>\n");
}
if (currheadersourcelist->patch) {
fprintf(fout,"<tr><td>Patches:</td><td><font size=\"-1\">");
i=0;
while (currheadersourcelist->patch[i+1]) i++;
for (; i>=0; i--) {
// fprintf(fout,"%s ",currheadersourcelist->patch[i]);
fprintf(fout,"<a href=\"%s%s/patches/%s\">%s</a>&nbsp;",
configtag->showfile_prefix,
configtag->download_dir,
currheadersourcelist->patch[i],
currheadersourcelist->patch[i]);
}
fprintf(fout,"</font></td></tr>\n");
}
fprintf(fout,
"<tr><td>Build time:</td><td><font size=\"-1\">%s</font></td></tr>\n",
*simpleTimeToHuman(currheadersourcelist->buildtime,
& strdate));
for (idx = 0; idx < ARCHS_MAX + 1; idx++) {
if ((idx > 0) && ((!configtag->arch[idx-1]) || (!currheadersourcelist->firstchild[idx-1]))) continue;
if (curr_anchor < curr_letter) {
fprintf(findexout[idx],"<tr><td>");
while (curr_anchor < curr_letter) {
curr_anchor += 1;
fprintf(findexout[idx],"<a name=\"%c\"></a>",curr_anchor);
}
fprintf(findexout[idx],"</td></tr>");
}
fprintf(findexout[idx],"<tr><td>");
printpkgicon(findexout[idx], configtag, currheadersourcelist);
fprintf(findexout[idx],"</td><td><b>%s</b>: <i>%s</i>",currheadersourcelist->name,htmlclean(currheadersourcelist->summary,buffer,PATH_MAX));
st=strstr(currheadersourcelist->url,"://");
if (st) {
strcpy(buffer,st+3);
st=strchr(buffer,'/');
if (st) st[0]='\0';
fprintf(findexout[idx],
" <a href=\"%s\" target=\"_new\"><img src=\"%s/external.png\" title=\"%s\" ></a>",
currheadersourcelist->url,
configtag->configdefaults->url_dir,
buffer);
}
fprintf(findexout[idx],"</td></tr><tr><td></td><td><i>");
if (currheadersourcelist->epoch) {
fprintf(findexout[idx],"%ld:%s-%s",
currheadersourcelist->epoch,
currheadersourcelist->version,
currheadersourcelist->release);
} else {
fprintf(findexout[idx],
"%s-%s",
currheadersourcelist->version,
currheadersourcelist->release);
}
fprintf(findexout[idx]," - ");
} // for
fprintf(fout,"<tr><td>Built RPMS:</td><td><font size=\"-1\">");
for (arch = 0; arch < ARCHS_MAX && configtag->arch[arch]; arch++) {
/* write children to both fout and findexout */
currchild = currheadersourcelist->firstchild[arch];
c = 0;
while (currchild) {
for (idx = 0; idx < ARCHS_MAX + 1 && findexout[idx]; idx++) {
if ((idx > 0) && ((!configtag->arch[idx-1]) || (arch != idx -1))) continue;
fprintf(findexout[idx],
"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s(%s)</a><a href=\"apt:%s\"><img src=\"%s/pkg.png\" title=\"Install\" ></a> ",
configtag->configdefaults->url_prefix,
configtag->tag, currchild->name, configtag->arch[arch],
currchild->name, configtag->arch[arch],
currchild->name,
configtag->configdefaults->url_dir);
}
fprintf(fout, "<a href=\"%stag=%s&amp;pkg=%s.%s\">%s(%s)</a> ",
configtag->configdefaults->url_prefix,
configtag->tag, currchild->name, configtag->arch[arch],
currchild->name, configtag->arch[arch]);
currchild = currchild->nextbrother;
c++;
}
}
fprintf(fout, "</font></td></tr>\n");
for (idx = 0; idx < ARCHS_MAX + 1 && findexout[idx]; idx++) {
if ((idx > 0) && ((!configtag->arch[idx-1]) || (!currheadersourcelist->firstchild[idx-1]))) continue;
fprintf(findexout[idx],
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s(source)</a></td></tr><tr><td colspan=2><hr></td></tr>\n",
configtag->configdefaults->url_prefix,
configtag->tag,
currheadersourcelist->name,
currheadersourcelist->name);
}
/* list build requirements */
fprintf(fout, "<tr><td nowrap>Build requirements:</td><td><font size=\"-1\">");
for (i = 0; i < currheadersourcelist->requirecount; i++) {
if (currheadersourcelist->require[i]->resolved) {
if (currheadersourcelist->require[i]->resolved->numbuildproviders == 0) {
// missing provider
fprintf(fout,"<b>%s(unresolved)</b>",currheadersourcelist->require[i]->resolved->name);
} else if (currheadersourcelist->require[i]->resolved->numbuildproviders == 1) {
// single provider
if ((i == 0 ||
strcmp(currheadersourcelist->require[i-1]->name,
currheadersourcelist->require[i]->name)) &&
strcmp(currheadersourcelist->name,
currheadersourcelist->require[i]->name)) {
fprintf(fout,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
configtag->configdefaults->url_prefix,
configtag->repository[currheadersourcelist->require[i]->resolved->buildprovider[0]->altrepository]->tag,
currheadersourcelist->require[i]->resolved->name,
configtag->arch[0],
currheadersourcelist->require[i]->resolved->name);
if ((configtag->repository_level > 0) &&
currheadersourcelist->require[i]->resolved->buildprovider[0]->sourceheader &&
(currheadersourcelist->require[i]->resolved->buildprovider[0]->altrepository == configtag->repository_level))
{
snprintf(buffer, PATH_MAX, "has build requirement %s which is only provided in this repository",
currheadersourcelist->require[i]->resolved->name);
addWarning(currheadersourcelist, buffer);
}
}
} else {
// multiple providers
if (i == 0 ||
!currheadersourcelist->require[i-1]->resolved ||
strcmp(currheadersourcelist->require[i-1]->resolved->name,
currheadersourcelist->require[i]->resolved->name))
fprintf(fout,"<i>%s</i>(",currheadersourcelist->require[i]->resolved->name);
for (j = 0; j < currheadersourcelist->require[i]->resolved->numbuildproviders; j++) {
fprintf(fout,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
configtag->configdefaults->url_prefix,
configtag->repository[currheadersourcelist->require[i]->resolved->buildprovider[j]->altrepository]->tag,
currheadersourcelist->require[i]->resolved->buildprovider[j]->name,
configtag->arch[0],
currheadersourcelist->require[i]->resolved->buildprovider[j]->name);
if (j+1 < currheadersourcelist->require[i]->resolved->numbuildproviders) fprintf(fout,"|");
}
fprintf(fout,")");
} // if numproviders
if (currheadersourcelist->require[i]->flags & (RPMSENSE_LESS|RPMSENSE_GREATER|RPMSENSE_EQUAL)) {
fprintf(fout,"[");
if (currheadersourcelist->require[i]->flags & RPMSENSE_LESS) fprintf(fout, "<");
if (currheadersourcelist->require[i]->flags & RPMSENSE_GREATER) fprintf(fout, ">");
if (currheadersourcelist->require[i]->flags & RPMSENSE_EQUAL) fprintf(fout, "=");
fprintf(fout, "%s", currheadersourcelist->require[i]->version);
fprintf(fout,"]");
}
fprintf(fout," ");
} // if required
} // for
fprintf(fout, "</font></td></tr>\n");
/* print changelog to fout */
fprintf(fout,
"<tr><td>Changelog:</td><td><font size=\"-1\" face=\"Courier,Courier New,monospace\">");
currchangelog = currheadersourcelist->changelog;
while (currchangelog) {
// changelog_total++;
simpleTimeToHuman(currchangelog->time, (humanDate *) & strdate);
if (currchangelog->pkg) {
if ((currchangelog->pkg->role & PACKAGER_ROLE_MAINTAINER) &&
(currchangelog->pkg->packages_count)) {
fprintf(fout, "%s - <a href=\"%stag=%s&amp;maintainer=%s\">%s</a> (%s)<br>%s<br>",
&strdate[0],
configtag->configdefaults->url_prefix,
configtag->tag,
currchangelog->pkg->name,
currchangelog->pkg->name,
currchangelog->release,
htmlclean(currchangelog->text,buffer,PATH_MAX));
// currchangelog->pkg->changes_count++;
} else {
fprintf(fout, "%s - %s (%s)<br>%s<br>",
&strdate[0],
currchangelog->pkg->name,
currchangelog->release,
htmlclean(currchangelog->text,buffer,PATH_MAX));
// currchangelog->pkg->changes_count++;
}
} else {
fprintf(fout, "%s - (noname) (%s)<br>%s<br>",
&strdate[0],
currchangelog->release,
htmlclean(currchangelog->text,buffer,PATH_MAX));
}
currchangelog = currchangelog->next;
}
/* close fout */
fprintf(fout, "</font></td></tr></table>");
fclose(fout);
}
currheadersourcelist = currheadersourcelist->next;
} // while currheadersourcelist
for (idx = 0; idx < ARCHS_MAX + 1 && findexout[idx]; idx++) {
fprintf(findexout[idx], "</table>\n");
fclose(findexout[idx]);
}
return 0;
}
static int
htmlincselector(const struct dirent *entry)
{
char *ptr;
ptr = strstr(entry->d_name, ".inc");
if (entry->d_type != DT_REG) return 0; /* skip if not a file */
if (ptr == NULL) {
return 0;
}
return 1;
}
int
cleanHTMLFilesInc(char* dir)
{
int n,cnt,r;
struct dirent **namelist;
const char* errstr;
char uf[PATH_MAX];
n = scansdir(dir, &namelist, htmlincselector, NULL);
if (n < 0) {
errstr = strerror(errno);
logmsg(LOG_ERROR, "cannot scan directory '%s' (%s)", dir, errstr);
return 1;
}
for (cnt = 0; cnt < n; ++cnt) {
snprintf(uf,PATH_MAX,"%s/%s",dir,namelist[cnt]->d_name);
logmsg(LOG_DEBUG,"unlinking %s",uf);
r=unlink(uf);
if (r < 0) {
errstr = strerror(errno);
logmsg(LOG_WARNING, "cannot remove file '%s' (%s)", uf, errstr);
}
}
return 0;
}
int
cleanHTMLPackagesFiles(struct configTag *ct)
{
char dir[PATH_MAX];
snprintf(dir,PATH_MAX,"%spackages",ct->html_dir);
if (cleanHTMLFilesInc(dir)) {
logmsg(LOG_WARNING,"cannot clean %s directory",dir);
}
return 0;
}
int
cleanHTMLFiles(struct configTag *ct)
{
int s;
char uf[PATH_MAX],dir[PATH_MAX];
const char* clean_subdir[] = { "", "maintainers" };
struct headerSourceList *currheadersourcelist;
struct stat buf;
for (s = 0; s < 2; s++) {
snprintf(dir,PATH_MAX,"%s%s",ct->html_dir,clean_subdir[s]);
if (cleanHTMLFilesInc(dir)) {
logmsg(LOG_WARNING,"cannot clean %s directory",dir);
}
}
currheadersourcelist = ct->headersourcelist;
while (currheadersourcelist) {
snprintf(dir, PATH_MAX, "%sgroups/%s",
ct->html_dir,
groupdirname(currheadersourcelist->group,uf));
if (!stat(dir,&buf)) {
logmsg(LOG_DEBUG,"removing directory %s",dir);
if (cleanHTMLFilesInc(dir)) {
logmsg(LOG_ERROR,"cannot clean %s directory; aborting",dir);
exit(1);
}
if (rmdir(dir)) {
logmsg(LOG_ERROR,"cannot remove %s directory; aborting.",dir);
exit(1);
}
}
/* legacy: clean old group dirs */
snprintf(dir, PATH_MAX, "%s%s",
ct->html_dir,
groupdirname(currheadersourcelist->group,uf));
if (!stat(dir,&buf)) {
logmsg(LOG_DEBUG,"removing legacy directory %s",dir);
if (cleanHTMLFilesInc(dir)) {
logmsg(LOG_ERROR,"cannot clean %s directory; aborting.",dir);
exit(1);
}
if (rmdir(dir)) {
logmsg(LOG_ERROR,"cannot remove %s directory; aborting.",dir);
exit(1);
}
}
currheadersourcelist = currheadersourcelist->next;
}
return 0;
}
int
generateHTMLFiles(struct configTag *ct, int arch)
{
char buffer[PATH_MAX];
char htmlfile[PATH_MAX];
int i,j;
sizeString strsize;
FILE *fout;
struct headerList *currheaderlist, *auxheaderlist;
struct headerSourceList *auxheadersourcelist;
int found;
struct stat buf;
snprintf(buffer,PATH_MAX,"%spackages",ct->html_dir);
if (stat(buffer,&buf)) {
if (mkdir(buffer,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
logmsg(LOG_ERROR,"cannot create %s directory; aborting.",buffer);
exit(1);
}
} else {
if (!S_ISDIR(buf.st_mode)) {
logmsg(LOG_ERROR,"cannot create %s directory, a file with this name already exists; aborting.",buffer);
exit(1);
}
}
currheaderlist = ct->headerlist[arch];
while (currheaderlist) {
if ((ct->repository_level == 0) ||
((currheaderlist->sourceheader) &&
(currheaderlist->altrepository == ct->repository_level))) {
logmsg(LOG_DEBUG,"generating HTML pages for %s",currheaderlist->name);
snprintf(htmlfile,PATH_MAX,"%spackages/%s.%s.inc",ct->html_dir,currheaderlist->name,ct->arch[arch]);
if ((fout = fopen(htmlfile, "w")) == NULL) {
perror(htmlfile);
return 1;
}
get_favicon_from_url(currheaderlist->sourceheader->url, buffer, PATH_MAX);
fprintf(fout,
"<h1><img src=\"%s\" width=\"16\" height=\"16\">"
"&nbsp;%s: %s</h1><table class=\"pkgpage\" width=\"100%%\">",
buffer,
currheaderlist->name,
currheaderlist->summary);
fprintf(fout,
"<tr><td width=\"15%%\">Name:</td><td><b>%s</b></td></tr>\n",
currheaderlist->name);
fprintf(fout,
"<tr><td>Release:</td><td><b>%s-%s</b></td></tr>\n",
currheaderlist->version, currheaderlist->release);
fprintf(fout,
"<tr><td>Architecture:</td><td>%s</td></tr>\n",
currheaderlist->arch);
//fprintf(fout,
// "<tr><td>Summary:</td><td><b>%s</b></td></tr>\n",
// htmlclean(currheaderlist->summary,buffer,PATH_MAX));
fprintf(fout,
"<tr><td>Group:</td><td>%s</td></tr>\n",
htmlclean(currheaderlist->group,buffer,PATH_MAX));
fprintf(fout, "<tr><td>Description:</td><td>%s</td></tr>\n",
htmlclean(currheaderlist->description,buffer,PATH_MAX));
fprintf(fout,
"<tr><td>Size:</td><td><font size=\"-1\">%s</font></td></tr>\n",
humanSize(currheaderlist->size, &strsize));
//fprintf(fout,
// "<tr><td>Arch:</td><td><font size=\"-1\">%s</font></td></tr>\n",
// currheaderlist->arch);
if (ct->download_prefix) {
fprintf(fout,"<tr><td>Download:</td><td><font size=\"-1\">");
fprintf(fout,"<a href=\"%s%s/RPMS.%s/%s-%s-%s.%s.rpm\">%s-%s-%s.%s.rpm</a>",
ct->download_prefix,
ct->download_dir,
ct->arch[arch],
currheaderlist->name,
currheaderlist->version,
currheaderlist->release,
currheaderlist->arch,
currheaderlist->name,
currheaderlist->version,
currheaderlist->release,
currheaderlist->arch);
fprintf(fout,"</font></td></tr>\n");
}
if (currheaderlist->sourcename && currheaderlist->sourceheader) {
fprintf(fout,
"<tr><td>Source RPM:</td><td><font size=\"-1\"><a href=\"%stag=%s&amp;pkg=%s.source\">%s</a></font></td></tr>\n",
ct->configdefaults->url_prefix,
ct->tag,
currheaderlist->sourceheader->name,
currheaderlist->sourcename);
}
/* list obsoletes */
if (currheaderlist->obsoletecount > 0) {
fprintf(fout,
"<tr><td>Obsoletes:</td><td><font size=\"-1\">");
for (i = 0; i < currheaderlist->obsoletecount; i++) {
fprintf(fout, "%s", currheaderlist->obsoletename[i]);
if (currheaderlist->obsoleteflags[i] & (RPMSENSE_LESS|RPMSENSE_GREATER|RPMSENSE_EQUAL)) {
fprintf(fout, "[");
if (currheaderlist->obsoleteflags[i] & RPMSENSE_LESS) fprintf(fout, "<");
if (currheaderlist->obsoleteflags[i] & RPMSENSE_GREATER) fprintf(fout, ">");
if (currheaderlist->obsoleteflags[i] & RPMSENSE_EQUAL) fprintf(fout, "=");
fprintf(fout, "%s]", currheaderlist->obsoleteversion[i]);
}
fprintf(fout," ");
}
fprintf(fout, "</font></td></tr>\n");
}
/* list provides */
fprintf(fout,
"<tr><td>Provides:</td><td><font size=\"-1\">");
for (i = 0; i < currheaderlist->providecount; i++) {
fprintf(fout, "%s", currheaderlist->providename[i]);
if (currheaderlist->provideflags[i] & (RPMSENSE_LESS|RPMSENSE_GREATER|RPMSENSE_EQUAL)) {
fprintf(fout, "[");
if (currheaderlist->provideflags[i] & RPMSENSE_LESS) fprintf(fout, "<");
if (currheaderlist->provideflags[i] & RPMSENSE_GREATER) fprintf(fout, ">");
if (currheaderlist->provideflags[i] & RPMSENSE_EQUAL) fprintf(fout, "=");
fprintf(fout, "%s]", currheaderlist->provideversion[i]);
}
fprintf(fout," ");
}
fprintf(fout, "</font></td></tr>\n");
/* list requires */
fprintf(fout, "<tr><td>Requires:</td><td><font size=\"-1\">");
for (i = 0; i < currheaderlist->requirecount; i++) {
if (currheaderlist->require[i]->resolved) {
if (currheaderlist->require[i]->resolved->numproviders == 0) {
// no provider
fprintf(fout,"%s",currheaderlist->require[i]->resolved->name);
} else if (currheaderlist->require[i]->resolved->numproviders == 1) {
// single provider
if (currheaderlist->require[i]->resolved->provider[0]->sourceheader) {
fprintf(fout,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
ct->configdefaults->url_prefix,
ct->repository[currheaderlist->require[i]->resolved->provider[0]->altrepository]->tag,
currheaderlist->require[i]->resolved->provider[0]->name,
ct->arch[arch],
currheaderlist->require[i]->resolved->name);
} else {
fprintf(fout,"%s",currheaderlist->require[i]->resolved->name);
}
} else {
// multiple providers
logmsg(LOG_DEBUG,"Requirement %s has multiple providers",currheaderlist->require[i]->resolved->name);
fprintf(fout,"<i>%s</i>(",currheaderlist->require[i]->resolved->name);
for (j = 0; j < currheaderlist->require[i]->resolved->numproviders; j++) {
if (currheaderlist->require[i]->resolved->provider[j]->sourceheader)
fprintf(fout,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
ct->configdefaults->url_prefix,
ct->repository[currheaderlist->require[i]->resolved->provider[j]->altrepository]->tag,
currheaderlist->require[i]->resolved->provider[j]->name,
ct->arch[arch],
currheaderlist->require[i]->resolved->provider[j]->name);
else
fprintf(fout,"%s",currheaderlist->require[i]->resolved->provider[j]->name);
if (j+1 < currheaderlist->require[i]->resolved->numproviders) fprintf(fout,"|");
}
fprintf(fout,")");
} // if numproviders
if (currheaderlist->require[i]->flags & (RPMSENSE_LESS|RPMSENSE_GREATER|RPMSENSE_EQUAL)) {
fprintf(fout,"[");
if (currheaderlist->require[i]->flags & RPMSENSE_LESS) fprintf(fout, "<");
if (currheaderlist->require[i]->flags & RPMSENSE_GREATER) fprintf(fout, ">");
if (currheaderlist->require[i]->flags & RPMSENSE_EQUAL) fprintf(fout, "=");
fprintf(fout, "%s", currheaderlist->require[i]->version);
fprintf(fout,"]");
}
fprintf(fout," ");
} // if required
} // for
fprintf(fout, "</font></td></tr>\n");
/* list RPM requirements */
fprintf(fout, "<tr><td>RPM requirements:</td><td><font size=\"-1\">");
for (i = 0; i < currheaderlist->requirecount; i++) {
if (currheaderlist->require[i]->resolved) {
if (currheaderlist->require[i]->resolved->numproviders == 0) {
// missing provider
fprintf(fout,"<b>%s(unresolved)</b> ",currheaderlist->require[i]->resolved->name);
} else if (currheaderlist->require[i]->resolved->numproviders == 1) {
// single provider
if ((i == 0 ||
!currheaderlist->require[i-1]->resolved ||
!currheaderlist->require[i-1]->resolved->numproviders ||
strcmp(currheaderlist->require[i-1]->resolved->provider[0]->name,
currheaderlist->require[i]->resolved->provider[0]->name)) &&
strcmp(currheaderlist->name,
currheaderlist->require[i]->resolved->provider[0]->name)) {
fprintf(fout,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a> ",
ct->configdefaults->url_prefix,
ct->repository[currheaderlist->require[i]->resolved->provider[0]->altrepository]->tag,
currheaderlist->require[i]->resolved->provider[0]->name,
ct->arch[arch],
currheaderlist->require[i]->resolved->provider[0]->name);
if ((ct->repository_level > 0) &&
(currheaderlist->sourceheader != currheaderlist->require[i]->resolved->provider[0]->sourceheader) &&
(currheaderlist->require[i]->resolved->provider[0]->altrepository == ct->repository_level)) {
snprintf(buffer, PATH_MAX, "%s(%s,%s) requires %s(%s,%s) which is only in this repository",
currheaderlist->name,
ct->arch[arch],
ct->repository[currheaderlist->altrepository]->tag,
currheaderlist->require[i]->resolved->provider[0]->name,
ct->arch[arch],
ct->repository[currheaderlist->require[i]->resolved->provider[0]->altrepository]->tag);
addWarning(currheaderlist->sourceheader, buffer);
}
}
} else {
// multiple providers
if (i == 0 ||
!currheaderlist->require[i-1]->resolved ||
!currheaderlist->require[i-1]->resolved->numproviders ||
strcmp(currheaderlist->require[i-1]->resolved->name,
currheaderlist->require[i]->resolved->name)) {
fprintf(fout,"<i>%s</i>(",currheaderlist->require[i]->resolved->name);
for (j = 0; j < currheaderlist->require[i]->resolved->numproviders; j++) {
fprintf(fout,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
ct->configdefaults->url_prefix,
ct->repository[currheaderlist->require[i]->resolved->provider[j]->altrepository]->tag,
currheaderlist->require[i]->resolved->provider[j]->name,
ct->arch[arch],
currheaderlist->require[i]->resolved->provider[j]->name);
if (j+1 < currheaderlist->require[i]->resolved->numproviders) fprintf(fout,"|");
}
fprintf(fout,") ");
}
} // if numproviders
} // if required
} // for
fprintf(fout, "</font></td></tr>\n");
/* list required by */
fprintf(fout, "<tr><td>Required by:</td><td><font size=\"-1\">");
auxheaderlist = ct->headerlist[arch];
while (auxheaderlist) {
found = 0;
if (auxheaderlist != currheaderlist) {
for (i = 0; i < auxheaderlist->requirecount; i++) {
if (auxheaderlist->require[i]->resolved) {
for (j = 0; j < auxheaderlist->require[i]->resolved->numproviders; j++) {
if (!strcmp(auxheaderlist->require[i]->resolved->provider[j]->name, currheaderlist->name)) {
fprintf(fout, "<a href=\"%stag=%s&amp;pkg=%s.%s\">%s(%s)</a> ",
ct->configdefaults->url_prefix,
ct->repository[auxheaderlist->altrepository]->tag,
auxheaderlist->name,
ct->arch[arch],
auxheaderlist->name,
ct->arch[arch]);
found = 1;
}
if (found) break;
}
}
if (found) break;
}
}
auxheaderlist = auxheaderlist->next;
} // while auxheaderlist
fprintf(fout, "</font></td></tr>\n");
/* list build required by */
fprintf(fout,
"<tr><td nowrap>Build required by:</td><td><font size=\"-1\">");
auxheadersourcelist = ct->headersourcelist;
while (auxheadersourcelist) {
found=0;
if (auxheadersourcelist != currheaderlist->sourceheader) {
for (i = 0; i < auxheadersourcelist->requirecount; i++) {
if (auxheadersourcelist->require[i]->resolved) {
for (j = 0; j < auxheadersourcelist->require[i]->resolved->numbuildproviders; j++) {
if (!strcmp(auxheadersourcelist->require[i]->resolved->buildprovider[j]->name,
currheaderlist->name)) {
fprintf(fout,
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s</a> ",
ct->configdefaults->url_prefix,
ct->repository[auxheadersourcelist->altrepository]->tag,
auxheadersourcelist->name,
auxheadersourcelist->name);
found=1;
}
}
}
if (found) break;
}
}
auxheadersourcelist = auxheadersourcelist->next;
}
fprintf(fout, "</font></td></tr>\n");
/* list filenames */
fprintf(fout, "<tr><td>Filenames:</td><td><font size=\"-1\">");
for (i = 0; i < currheaderlist->filenamecount; i++) {
ftname((currheaderlist->file)[i], buffer);
fprintf(fout, "/%s ",buffer);
}
fprintf(fout, "</font></td></tr></table>\n");
fclose(fout);
}
currheaderlist = currheaderlist->next;
} // while currheaderlist
return 0;
}
char *ftname(struct fileTree* ft, char* buf) {
buf[0]='\0';
int l;
if (ft) {
strcpy(buf,ft->name);
ft=ft->parent;
}
while (ft) {
l=strlen(ft->name);
if (strlen(buf)+l+1 <= PATH_MAX) {
memmove(buf+l+1,buf,strlen(buf)+1);
memcpy(buf,ft->name,l);
buf[l]='/';
} else break;
ft=ft->parent;
}
return buf;
}
void print_contents_subtree(FILE *f,
struct fileTree* ft,
struct configTag* ct,
char* buf, int bufsize) {
int i,j,k;
while (ft) {
if (ft->firstchild) {
print_contents_subtree(f,ft->firstchild,ct,buf,bufsize);
} else {
for (k = 0; k < ft->numproviders; k++) {
if ((ct->repository_level == 0) ||
((ft->provider[k]) &&
(ft->provider[k]->sourceheader) &&
(ft->provider[k]->altrepository == ct->repository_level))) {
ftname(ft,buf);
if ((j=strlen(buf)) < 60) {
for (i=(60-j)/8; i>0; i--) strncat(buf, "\t", bufsize - strlen(buf));
while (strlen(buf) < 60) strncat(buf, " ", bufsize - strlen(buf));
}
fprintf(f, "%s %s/%s\n",buf,ct->tag,ft->provider[0]->name);
}
}
}
ft=ft->next;
}
}
int print_contentslist(struct configTag *ct, int arch) {
FILE *fc;
char contents_filename[PATH_MAX],buf[PATH_MAX];
snprintf(contents_filename, PATH_MAX, "%scontentslist-%s", ct->repository_dir, ct->arch[arch]);
fc=fopen(contents_filename,"w");
if (!fc) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", contents_filename);
return 1;
}
//write contents (filenames)
logmsg(LOG_DEBUG,"writing contents file");
print_contents_subtree(fc, ct->filetree[arch], ct, buf, PATH_MAX);
fclose(fc);
return 0;
}
#define OBSOLETEBUF_SIZE 8096
int print_datatables(struct configTag *ct, int arch) {
FILE *fbd,*fd,*fv,*fb,*fbsh,*fs,*fw;
char builddeps_filename[PATH_MAX], deps_filename[PATH_MAX], virtual_filename[PATH_MAX],
builds_filename[PATH_MAX], builds_sh_filename[PATH_MAX], sources_filename[PATH_MAX],
warnings_filename[PATH_MAX];
char obsoletebuf[OBSOLETEBUF_SIZE];
struct headerList *currheaderlist, *currchild;
struct headerSourceList *currheadersourcelist, *oldheadersourcelist;
struct rebuildList *currrebuild;
int i, nonobsoletednumproviders;
snprintf(builddeps_filename, PATH_MAX, "%sbuilddeps-%s", ct->html_dir, ct->arch[arch]);
snprintf(deps_filename, PATH_MAX, "%sdeps-%s", ct->html_dir, ct->arch[arch]);
snprintf(virtual_filename, PATH_MAX, "%svirtual-%s", ct->html_dir, ct->arch[arch]);
snprintf(builds_filename, PATH_MAX, "%sbuilds-%s", ct->html_dir, ct->arch[arch]);
snprintf(builds_sh_filename, PATH_MAX, "%sbuilds-%s.sh", ct->html_dir, ct->arch[arch]);
snprintf(sources_filename, PATH_MAX, "%ssources-%s", ct->html_dir, ct->arch[arch]);
snprintf(warnings_filename, PATH_MAX, "%swarnings-%s", ct->repository_dir, ct->arch[arch]);
fbd=fopen(builddeps_filename,"w");
if (!fbd) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", builddeps_filename);
return 1;
}
fd=fopen(deps_filename,"w");
if (!fd) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", deps_filename);
return 1;
}
fv=fopen(virtual_filename,"w");
if (!fv) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", virtual_filename);
return 1;
}
fb=fopen(builds_filename,"w");
if (!fb) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", builds_filename);
return 1;
}
fbsh=fopen(builds_sh_filename,"w");
if (!fbsh) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", builds_filename);
return 1;
}
fs=fopen(sources_filename,"w");
if (!fs) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", sources_filename);
return 1;
}
fw=fopen(warnings_filename,"w");
if (!fw) {
fprintf(stderr, "Error: can't open file for writing: %s. Aborting.\n", warnings_filename);
return 1;
}
//
// headerlist scan: write top of deps and sources files
//
fprintf(fd,"ALL_PACKAGES = ");
fprintf(fb,"ALL_BUILDS=");
currheaderlist = ct->headerlist[arch];
while (currheaderlist) {
fprintf(fs,"%s: _%s\n", currheaderlist->name, currheaderlist->sourceheader->name);
fprintf(fd,"%s ", currheaderlist->name);
fprintf(fb,"%s ",currheaderlist->name);
currheaderlist = currheaderlist->next;
}
fprintf(fd,"\n");
//
// source headerlist scan: write top of deps and sources files
//
fprintf(fbd,"ALL_SOURCES = ");
fprintf(fs,"ALL_SOURCES = ");
currheadersourcelist = ct->headersourcelist;
while (currheadersourcelist) {
if (currheadersourcelist->firstchild[arch]) {
fprintf(fbd,"%s ", currheadersourcelist->name);
fprintf(fs,"_%s ", currheadersourcelist->name);
}
currheadersourcelist = currheadersourcelist->next;
}
fprintf(fbd,"\n");
fprintf(fs,"\n");
fprintf(fb,"\n");
// write deps file
logmsg(LOG_DEBUG,"writing deps files (1)");
struct providedList* provided = ct->providedlist_idx[arch][0];
while (provided) {
if (!strncmp("debuginfo(build-id)", provided->name, 20) ||
provided->name[0] == '(') { // Filter out complex deps like "(name >= ver1 with name < ver2)
provided = provided->next;
continue;
}
nonobsoletednumproviders=0;
for (i = 0; i < provided->numproviders; i++) {
// skip duplicated provides
if (i > 0) {
if (provided->provider[i] == provided->provider[i-1]) continue;
else if (!strcmp(provided->provider[i]->name,provided->provider[i-1]->name) &&
!provided->provider[i-1]->obsoleted) continue;
}
if (!provided->provider[i]->obsoleted) nonobsoletednumproviders++;
}
if (nonobsoletednumproviders > 1) {
fprintf(fd,"ifndef ");
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd,"\n");
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd," := ");
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd,"_to_be_defined # ");
fprintf_depstable_filtered_var(fs,provided->name);
fprintf(fs,":");
for (i = 0; i < provided->numproviders; i++) {
if (!provided->provider[i]->obsoleted) {
if (i == 0 || strcmp(provided->provider[i-1]->name,
provided->provider[i]->name))
fprintf(fd,"%s ",provided->provider[i]->name);
if (i == 0 || strcmp(provided->provider[i-1]->sourceheader->name,
provided->provider[i]->sourceheader->name))
fprintf(fs," _%s",provided->provider[i]->sourceheader->name);
}
}
fprintf(fs,"\n");
fprintf(fd,"\nendif\n");
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd,": ");
fprintf(fd,"$(");
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd,")\n");
fprintf(fv,"%s= # ",provided->name);
for (i = 0; i < provided->numproviders; i++) {
if (!provided->provider[i]->obsoleted) {
if (i == 0 || strcmp(provided->provider[i-1]->name,
provided->provider[i]->name))
fprintf(fv,"%s ",provided->provider[i]->name);
}
}
fprintf(fv,"\n");
} else if (nonobsoletednumproviders == 1) {
for (i = 0; i < provided->numproviders; i++) {
if (!provided->provider[i]->obsoleted) break;
}
if (strcmp(provided->name,provided->provider[i]->name)) {
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd,": ");
fprintf(fd,"%s\n",provided->provider[i]->name);
fprintf_depstable_filtered_var(fs,provided->name);
fprintf(fs,": _%s\n",provided->provider[i]->sourceheader->name);
}
} else {
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd,": ");
fprintf(fd,"__missing_provider_for_");
fprintf_depstable_filtered_var(fd,provided->name);
fprintf(fd,"\n");
}
provided = provided->next;
}
logmsg(LOG_DEBUG,"writing deps files (2)");
currheaderlist = ct->headerlist[arch];
while (currheaderlist) {
fprintf(fd,"%s: ", currheaderlist->name);
for (i = 0; i < currheaderlist->requirecount; i++) {
if (currheaderlist->require[i]->resolved) {
if (currheaderlist->require[i]->resolved->numproviders == 0) {
// Filter out complex deps like "(name >= ver1 with name < ver2)
if (currheaderlist->require[i]->resolved->name[0] != '(') {
fprintf_depstable_filtered_var(fd,
currheaderlist->require[i]->resolved->name);
fprintf(fd,"_unresolved_ ");
}
} else if (currheaderlist->require[i]->resolved->numproviders == 1) {
if ((i == 0 ||
!currheaderlist->require[i-1]->resolved ||
!currheaderlist->require[i-1]->resolved->numproviders ||
strcmp(currheaderlist->require[i-1]->resolved->provider[0]->name,
currheaderlist->require[i]->resolved->provider[0]->name)) &&
strcmp(currheaderlist->name,
currheaderlist->require[i]->resolved->provider[0]->name)) {
fprintf(fd,"%s ",currheaderlist->require[i]->resolved->provider[0]->name);
}
} else {
if (i == 0 ||
!currheaderlist->require[i-1]->resolved ||
!currheaderlist->require[i-1]->resolved->numproviders ||
strcmp(currheaderlist->require[i-1]->resolved->name,
currheaderlist->require[i]->resolved->name)) {
fprintf_depstable_filtered_var(fd,currheaderlist->require[i]->resolved->name);
fprintf(fd," ");
}
}
for (int j = 0; j < currheaderlist->require[i]->resolved->numproviders; j++) {
if (currheaderlist->require[i]->resolved->provider[j]->sourceheader != currheaderlist->sourceheader)
currheaderlist->require[i]->resolved->provider[j]->sourceheader->childrenrequiredcount[arch]++;
}
}
}
fprintf(fd,"\n");
//
// write builddeps file
//
fprintf(fbd,"%s:",currheaderlist->name);
for (i = 0; i < currheaderlist->sourceheader->requirecount; i++) {
if (strncmp("rpmlib(",currheaderlist->sourceheader->require[i]->name,7) &&
strncmp("debuginfo(build-id)",currheaderlist->sourceheader->require[i]->name,20)) {
fprintf(fbd," ");
fprintf_depstable_filtered_var(fbd,currheaderlist->sourceheader->require[i]->name);
if (currheaderlist->sourceheader->require[i]->resolved) {
for (int j = 0; j < currheaderlist->sourceheader->require[i]->resolved->numproviders; j++) {
if (currheaderlist->sourceheader->require[i]->resolved->provider[j]->sourceheader != currheaderlist->sourceheader)
currheaderlist->sourceheader->require[i]->resolved->provider[j]->sourceheader->childrenrequiredcount[arch]++;
}
}
}
}
fprintf(fbd,"\n");
/*for (i = 0; i < currheaderlist->obsoletecount; i++) {
fprintf(fbd,"%s: %s\n",currheaderlist->obsoletename[i],currheaderlist->name);
}*/
for (i = 0; i < currheaderlist->providecount; i++) {
if (strncmp(currheaderlist->provided[i]->name,currheaderlist->name,PATH_MAX) != 0) {
fprintf_depstable_filtered_var(fbd,currheaderlist->provided[i]->name);
fprintf(fbd,": %s\n",currheaderlist->name);
}
}
currheaderlist = currheaderlist->next;
}
//
// headersourcelist scan: write builds and sources files
//
logmsg(LOG_DEBUG,"writing builds and sources files (1)");
fprintf(fbsh,"pkg_list=(");
currheadersourcelist = ct->headersourcelist;
while (currheadersourcelist != NULL) {
if (((ct->repository_level == 0) ||
(currheadersourcelist->altrepository == ct->repository_level)) &&
(currheadersourcelist->firstchild[arch])) {
fprintf(fbsh,"%s ",currheadersourcelist->name);
}
currheadersourcelist = currheadersourcelist->next;
}
fprintf(fbsh,");\n");
fprintf(fbsh,"needport_list=(");
currheadersourcelist = ct->headersourcelist;
while (currheadersourcelist != NULL) {
if (!currheadersourcelist->firstchild[arch] &&
currheadersourcelist->old &&
currheadersourcelist->old->firstchild[arch] &&
(currheadersourcelist->altrepository == ct->repository_level)) {
fprintf(fbsh,"%s ",currheadersourcelist->name);
}
currheadersourcelist = currheadersourcelist->next;
}
fprintf(fbsh,");\n");
fprintf(fbsh,"warnings_list=(");
currheadersourcelist = ct->headersourcelist;
while (currheadersourcelist != NULL) {
if ((currheadersourcelist->altrepository == ct->repository_level) &&
(printHTMLWarnings(fw,ct,currheadersourcelist,2) == 1)) {
fprintf(fbsh,"%s ",currheadersourcelist->name);
}
currheadersourcelist = currheadersourcelist->next;
}
fprintf(fbsh,");\n");
currheadersourcelist = ct->headersourcelist;
logmsg(LOG_DEBUG,"writing builds and sources files (2)");
while (currheadersourcelist != NULL) {
currchild = currheadersourcelist->firstchild[arch];
if (currchild) {
fprintf(fbsh,"[ \"$pkg\" = \"%s\" ] && { pkg_header=(%s %s %s %s \"%s\" \"%s\" %ld %ld %d %s %ld); ",
currheadersourcelist->name,
currheadersourcelist->name,
currchild->arch,
currheadersourcelist->version,
currheadersourcelist->release,
currheadersourcelist->group,
currheadersourcelist->license,
currheadersourcelist->size,
currheadersourcelist->buildtime,
currheadersourcelist->altrepository,
ct->repository[currheadersourcelist->altrepository]->tag,
currheadersourcelist->epoch);
fprintf(fb,"%s:",
currheadersourcelist->name);
fprintf(fbsh,"pkg_builds=(");
obsoletebuf[0] = '\0';
while (currchild) {
fprintf(fbsh,"%s",currchild->name);
fprintf(fb," %s",currchild->name);
for (i = 0; i < currchild->obsoletecount; i++ ) {
if ((i > 0) && (!strcmp(currchild->obsoletename[i],currchild->obsoletename[i-1]))) continue;
if (strlen(obsoletebuf) + strlen(currchild->obsoletename[i]) >= OBSOLETEBUF_SIZE - 2) {
logmsg(LOG_WARNING, "%s: reached obsoletebuf maximum size (%d); skipping further obsoletes in output file",
currheadersourcelist->name, OBSOLETEBUF_SIZE);
break;
}
if (obsoletebuf[0] != '\0') strncat(obsoletebuf, " ", sizeof(obsoletebuf) - strlen(obsoletebuf));
strncat(obsoletebuf, currchild->obsoletename[i], sizeof(obsoletebuf) - strlen(obsoletebuf));
}
currchild = currchild->nextbrother;
if (currchild) fprintf(fbsh," ");
}
fprintf(fbsh,"); pkg_obsoletes=(%s);",obsoletebuf);
/* find pointer to firstrebuild also looking into old packages */
currrebuild = currheadersourcelist->firstrebuild;
oldheadersourcelist = currheadersourcelist->old;
while (!currrebuild && oldheadersourcelist) {
currrebuild = oldheadersourcelist->firstrebuild;
oldheadersourcelist = oldheadersourcelist->old;
}
fprintf(fbsh," pkg_needrebuild=(");
while (currrebuild) {
if (!strcmp(currrebuild->provider->arch, ct->arch[arch])) {
fprintf(fbsh, "%s@%s ", currrebuild->sourceheader->name, currrebuild->provider->name);
}
currrebuild = currrebuild->next;
}
fprintf(fbsh,"); }\n");
fprintf(fb,"\n");
}
currheadersourcelist = currheadersourcelist->next;
}
fclose(fd);
fclose(fv);
fclose(fbsh);
fclose(fb);
fclose(fs);
fclose(fw);
return 0;
}
int
generateSrcPkgList(struct configTag *ct)
{
FILE *fd;
char fn[PATH_MAX];
struct headerSourceList *currheadersourcelist;
humanDate strdate;
int i;
snprintf(fn, PATH_MAX, "%ssrcpkglist",ct->repository_dir);
fd=fopen(fn,"w");
if (!fd) {
fprintf(stderr, "Error: can't open file for writing: %s\n", fn);
return 1;
}
currheadersourcelist = ct->headersourcelist;
while (currheadersourcelist != NULL) {
fprintf(fd, "%s %s %s %s %ld %s ",
currheadersourcelist->name,
currheadersourcelist->version,
(char *)simpleTimeToTemplate(currheadersourcelist->buildtime,"%Y%m%d",&strdate),
ct->repository[currheadersourcelist->altrepository]->tag,
currheadersourcelist->epoch,
currheadersourcelist->release);
if (currheadersourcelist->source) {
i=0;
while (currheadersourcelist->source[i+1]) i++;
for (; i>=0; i--)
fprintf(fd, "%s ",currheadersourcelist->source[i]);
}
fprintf(fd, "\n");
currheadersourcelist = currheadersourcelist->next;
}
fclose(fd);
return 0;
}
int
generatePkgList(struct configTag *ct, int arch)
{
FILE *fd;
char fn[PATH_MAX];
struct headerList *currheaderlist;
snprintf(fn, PATH_MAX, "%spkglist.%s",ct->repository_dir,ct->arch[arch]);
fd=fopen(fn,"w");
if (!fd) {
fprintf(stderr, "Error: can't open file for writing: %s\n", fn);
return 1;
}
/* currheaderlist = headerlist; */
currheaderlist = ct->headerlist[arch];
while (currheaderlist != NULL) {
fprintf(fd, "%s %s %ld %d %s %ld %s\n",
currheaderlist->name,
currheaderlist->version,
currheaderlist->size, currheaderlist->filenamecount,
ct->repository[currheaderlist->altrepository]->tag,
currheaderlist->epoch,
currheaderlist->release);
currheaderlist = currheaderlist->next;
}
fclose(fd);
return 0;
}