Imported Upstream version 0.6.29
[platform/upstream/libsolv.git] / examples / solv / deltarpm.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5
6 #include "pool.h"
7 #include "repo.h"
8 #include "repoinfo.h"
9 #include "repoinfo_download.h"
10
11 #include "deltarpm.h"
12
13 static inline int
14 opentmpfile()
15 {
16   char tmpl[100];
17   int fd;
18
19   strcpy(tmpl, "/var/tmp/solvXXXXXX");
20   fd = mkstemp(tmpl);
21   if (fd < 0) 
22     {    
23       perror("mkstemp");
24       exit(1);
25     }    
26   unlink(tmpl);
27   return fd;
28 }
29
30 FILE *
31 trydeltadownload(Solvable *s, const char *loc)
32 {
33   Repo *repo = s->repo;
34   Pool *pool = repo->pool;
35   struct repoinfo *cinfo = repo->appdata;
36   Dataiterator di;
37   Id pp;
38   const unsigned char *chksum;
39   Id chksumtype;
40   FILE *retfp = 0;
41   char *matchname = strdup(pool_id2str(pool, s->name));
42
43   dataiterator_init(&di, pool, repo, SOLVID_META, DELTA_PACKAGE_NAME, matchname, SEARCH_STRING);
44   dataiterator_prepend_keyname(&di, REPOSITORY_DELTAINFO);
45   while (dataiterator_step(&di))
46     {
47       Id baseevr, op;
48
49       dataiterator_setpos_parent(&di);
50       if (pool_lookup_id(pool, SOLVID_POS, DELTA_PACKAGE_EVR) != s->evr ||
51           pool_lookup_id(pool, SOLVID_POS, DELTA_PACKAGE_ARCH) != s->arch)
52         continue;
53       baseevr = pool_lookup_id(pool, SOLVID_POS, DELTA_BASE_EVR);
54       FOR_PROVIDES(op, pp, s->name)
55         {
56           Solvable *os = pool->solvables + op;
57           if (os->repo == pool->installed && os->name == s->name && os->arch == s->arch && os->evr == baseevr)
58             break;
59         }
60       if (op && access("/usr/bin/applydeltarpm", X_OK) == 0)
61         {
62           /* base is installed, run sequence check */
63           const char *seq;
64           const char *dloc;
65           const char *archstr;
66           FILE *fp;
67           char cmd[128];
68           int newfd;
69
70           archstr = pool_id2str(pool, s->arch);
71           if (strlen(archstr) > 10 || strchr(archstr, '\'') != 0)
72             continue;
73
74           seq = pool_tmpjoin(pool, pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NAME), "-", pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_EVR));
75           seq = pool_tmpappend(pool, seq, "-", pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NUM));
76           if (strchr(seq, '\'') != 0)
77             continue;
78 #if defined(FEDORA) || defined(MAGEIA)
79           sprintf(cmd, "/usr/bin/applydeltarpm -a '%s' -c -s '", archstr);
80 #else
81           sprintf(cmd, "/usr/bin/applydeltarpm -c -s '");
82 #endif
83           if (system(pool_tmpjoin(pool, cmd, seq, "'")) != 0)
84             continue;   /* didn't match */
85           /* looks good, download delta */
86           chksumtype = 0;
87           chksum = pool_lookup_bin_checksum(pool, SOLVID_POS, DELTA_CHECKSUM, &chksumtype);
88           if (!chksumtype)
89             continue;   /* no way! */
90           dloc = pool_lookup_deltalocation(pool, SOLVID_POS, 0);
91           if (!dloc)
92             continue;
93 #ifdef ENABLE_SUSEREPO
94           if (cinfo->type == TYPE_SUSETAGS)
95             {
96               const char *datadir = repo_lookup_str(repo, SOLVID_META, SUSETAGS_DATADIR);
97               dloc = pool_tmpjoin(pool, datadir ? datadir : "suse", "/", dloc);
98             }
99 #endif
100           if ((fp = curlfopen(cinfo, dloc, 0, chksum, chksumtype, 0)) == 0)
101             continue;
102           /* got it, now reconstruct */
103           newfd = opentmpfile();
104 #if defined(FEDORA) || defined(MAGEIA)
105           sprintf(cmd, "applydeltarpm -a '%s' /dev/fd/%d /dev/fd/%d", archstr, fileno(fp), newfd);
106 #else
107           sprintf(cmd, "applydeltarpm /dev/fd/%d /dev/fd/%d", fileno(fp), newfd);
108 #endif
109           fcntl(fileno(fp), F_SETFD, 0);
110           if (system(cmd))
111             {
112               close(newfd);
113               fclose(fp);
114               continue;
115             }
116           lseek(newfd, 0, SEEK_SET);
117           chksumtype = 0;
118           chksum = solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &chksumtype);
119           if (chksumtype && !verify_checksum(newfd, loc, chksum, chksumtype))
120             {
121               close(newfd);
122               fclose(fp);
123               continue;
124             }
125           retfp = fdopen(newfd, "r");
126           fclose(fp);
127           break;
128         }
129     }
130   dataiterator_free(&di);
131   solv_free(matchname);
132   return retfp;
133 }