Blame examples/solv/repoinfo_download.c

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