|
Packit Service |
ff689b |
#include <stdio.h>
|
|
Packit Service |
ff689b |
#include <stdlib.h>
|
|
Packit Service |
ff689b |
#include <unistd.h>
|
|
Packit Service |
ff689b |
#include <fcntl.h>
|
|
Packit Service |
ff689b |
#include <sys/types.h>
|
|
Packit Service |
ff689b |
#include <sys/wait.h>
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
#include "pool.h"
|
|
Packit Service |
ff689b |
#include "repo.h"
|
|
Packit Service |
ff689b |
#include "chksum.h"
|
|
Packit Service |
ff689b |
#include "solv_xfopen.h"
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
#include "repoinfo.h"
|
|
Packit Service |
ff689b |
#include "mirror.h"
|
|
Packit Service |
ff689b |
#include "checksig.h"
|
|
Packit Service |
ff689b |
#if defined(FEDORA) || defined(MAGEIA)
|
|
Packit Service |
ff689b |
#include "repoinfo_config_yum.h"
|
|
Packit Service |
ff689b |
#endif
|
|
Packit Service |
ff689b |
#include "repoinfo_download.h"
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
static inline int
|
|
Packit Service |
ff689b |
opentmpfile()
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
char tmpl[100];
|
|
Packit Service |
ff689b |
int fd;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
strcpy(tmpl, "/var/tmp/solvXXXXXX");
|
|
Packit Service |
ff689b |
fd = mkstemp(tmpl);
|
|
Packit Service |
ff689b |
if (fd < 0)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
perror("mkstemp");
|
|
Packit Service |
ff689b |
exit(1);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
unlink(tmpl);
|
|
Packit Service |
ff689b |
return fd;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
int
|
|
Packit Service |
ff689b |
verify_checksum(int fd, const char *file, const unsigned char *chksum, Id chksumtype)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
char buf[1024];
|
|
Packit Service |
ff689b |
const unsigned char *sum;
|
|
Packit Service |
ff689b |
Chksum *h;
|
|
Packit Service |
ff689b |
int l;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
h = solv_chksum_create(chksumtype);
|
|
Packit Service |
ff689b |
if (!h)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
printf("%s: unknown checksum type\n", file);
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
while ((l = read(fd, buf, sizeof(buf))) > 0)
|
|
Packit Service |
ff689b |
solv_chksum_add(h, buf, l);
|
|
Packit Service |
ff689b |
lseek(fd, 0, SEEK_SET);
|
|
Packit Service |
ff689b |
l = 0;
|
|
Packit Service |
ff689b |
sum = solv_chksum_get(h, &l);
|
|
Packit Service |
ff689b |
if (memcmp(sum, chksum, l))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
printf("%s: checksum mismatch\n", file);
|
|
Packit Service |
ff689b |
solv_chksum_free(h, 0);
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
solv_chksum_free(h, 0);
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
FILE *
|
|
Packit Service |
ff689b |
curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsigned char *chksum, Id chksumtype, int markincomplete)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
FILE *fp;
|
|
Packit Service |
ff689b |
pid_t pid;
|
|
Packit Service |
ff689b |
int fd;
|
|
Packit Service |
ff689b |
int status;
|
|
Packit Service |
ff689b |
char url[4096];
|
|
Packit Service |
ff689b |
const char *baseurl = cinfo->baseurl;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
if (!baseurl)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (!cinfo->metalink && !cinfo->mirrorlist)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
if (file != cinfo->metalink && file != cinfo->mirrorlist)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
unsigned char mlchksum[32];
|
|
Packit Service |
ff689b |
Id mlchksumtype = 0;
|
|
Packit Service |
ff689b |
fp = curlfopen(cinfo, cinfo->metalink ? cinfo->metalink : cinfo->mirrorlist, 0, 0, 0, 0);
|
|
Packit Service |
ff689b |
if (!fp)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
if (cinfo->metalink)
|
|
Packit Service |
ff689b |
cinfo->baseurl = findmetalinkurl(fp, mlchksum, &mlchksumtype);
|
|
Packit Service |
ff689b |
else
|
|
Packit Service |
ff689b |
cinfo->baseurl = findmirrorlisturl(fp);
|
|
Packit Service |
ff689b |
fclose(fp);
|
|
Packit Service |
ff689b |
if (!cinfo->baseurl)
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
#if defined(FEDORA) || defined(MAGEIA)
|
|
Packit Service |
ff689b |
if (strchr(cinfo->baseurl, '$'))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
char *b = yum_substitute(cinfo->repo->pool, cinfo->baseurl);
|
|
Packit Service |
ff689b |
free(cinfo->baseurl);
|
|
Packit Service |
ff689b |
cinfo->baseurl = strdup(b);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
#endif
|
|
Packit Service |
ff689b |
if (!chksumtype && mlchksumtype && !strcmp(file, "repodata/repomd.xml"))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
chksumtype = mlchksumtype;
|
|
Packit Service |
ff689b |
chksum = mlchksum;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
return curlfopen(cinfo, file, uncompress, chksum, chksumtype, markincomplete);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
snprintf(url, sizeof(url), "%s", file);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
else
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
const char *path = cinfo->path && strcmp(cinfo->path, "/") != 0 ? cinfo->path : "";
|
|
Packit Service |
ff689b |
int l = strlen(baseurl);
|
|
Packit Service |
ff689b |
int pl = strlen(path);
|
|
Packit Service |
ff689b |
const char *sep = l && baseurl[l - 1] == '/' ? "" : "/";
|
|
Packit Service |
ff689b |
const char *psep = pl && cinfo->path[pl - 1] == '/' ? "" : "/";
|
|
Packit Service |
ff689b |
snprintf(url, sizeof(url), "%s%s%s%s%s", baseurl, sep, path, psep, file);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
fd = opentmpfile();
|
|
Packit Service |
ff689b |
// printf("url: %s\n", url);
|
|
Packit Service |
ff689b |
if ((pid = fork()) == (pid_t)-1)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
perror("fork");
|
|
Packit Service |
ff689b |
exit(1);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (pid == 0)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (fd != 1)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
dup2(fd, 1);
|
|
Packit Service |
ff689b |
close(fd);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
execlp("curl", "curl", "-f", "-s", "-L", url, (char *)0);
|
|
Packit Service |
ff689b |
perror("curl");
|
|
Packit Service |
ff689b |
_exit(0);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
status = 0;
|
|
Packit Service |
ff689b |
while (waitpid(pid, &status, 0) != pid)
|
|
Packit Service |
ff689b |
;
|
|
Packit Service |
ff689b |
if (lseek(fd, 0, SEEK_END) == 0 && (!status || !chksumtype))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
/* empty file */
|
|
Packit Service |
ff689b |
close(fd);
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
lseek(fd, 0, SEEK_SET);
|
|
Packit Service |
ff689b |
if (status)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
printf("%s: download error %d\n", file, status >> 8 ? status >> 8 : status);
|
|
Packit Service |
ff689b |
if (markincomplete)
|
|
Packit Service |
ff689b |
cinfo->incomplete = 1;
|
|
Packit Service |
ff689b |
close(fd);
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (chksumtype && !verify_checksum(fd, file, chksum, chksumtype))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (markincomplete)
|
|
Packit Service |
ff689b |
cinfo->incomplete = 1;
|
|
Packit Service |
ff689b |
close(fd);
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
|
Packit Service |
ff689b |
if (uncompress)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
if (solv_xfopen_iscompressed(file) < 0)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
printf("%s: unsupported compression\n", file);
|
|
Packit Service |
ff689b |
if (markincomplete)
|
|
Packit Service |
ff689b |
cinfo->incomplete = 1;
|
|
Packit Service |
ff689b |
close(fd);
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
fp = solv_xfopen_fd(file, fd, "r");
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
else
|
|
Packit Service |
ff689b |
fp = fdopen(fd, "r");
|
|
Packit Service |
ff689b |
if (!fp)
|
|
Packit Service |
ff689b |
close(fd);
|
|
Packit Service |
ff689b |
return fp;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
FILE *
|
|
Packit Service |
ff689b |
downloadpackage(Solvable *s, const char *loc)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
const unsigned char *chksum;
|
|
Packit Service |
ff689b |
Id chksumtype;
|
|
Packit Service |
ff689b |
struct repoinfo *cinfo = s->repo->appdata;
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
#ifdef ENABLE_SUSEREPO
|
|
Packit Service |
ff689b |
if (cinfo->type == TYPE_SUSETAGS)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
const char *datadir = repo_lookup_str(cinfo->repo, SOLVID_META, SUSETAGS_DATADIR);
|
|
Packit Service |
ff689b |
loc = pool_tmpjoin(s->repo->pool, datadir ? datadir : "suse", "/", loc);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
#endif
|
|
Packit Service |
ff689b |
chksumtype = 0;
|
|
Packit Service |
ff689b |
chksum = solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &chksumtype);
|
|
Packit Service |
ff689b |
return curlfopen(cinfo, loc, 0, chksum, chksumtype, 0);
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|
|
Packit Service |
ff689b |
int
|
|
Packit Service |
ff689b |
downloadchecksig(struct repoinfo *cinfo, FILE *fp, const char *sigurl, Pool **sigpool)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
FILE *sigfp;
|
|
Packit Service |
ff689b |
sigfp = curlfopen(cinfo, sigurl, 0, 0, 0, 0);
|
|
Packit Service |
ff689b |
if (!sigfp)
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
printf(" unsigned, skipped\n");
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
if (!*sigpool)
|
|
Packit Service |
ff689b |
*sigpool = read_sigs();
|
|
Packit Service |
ff689b |
if (!checksig(*sigpool, fp, sigfp))
|
|
Packit Service |
ff689b |
{
|
|
Packit Service |
ff689b |
printf(" checksig failed, skipped\n");
|
|
Packit Service |
ff689b |
fclose(sigfp);
|
|
Packit Service |
ff689b |
return 0;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
fclose(sigfp);
|
|
Packit Service |
ff689b |
return 1;
|
|
Packit Service |
ff689b |
}
|
|
Packit Service |
ff689b |
|