resetting manifest requested domain to floor
[platform/upstream/deltarpm.git] / rpml.c
1 /*
2  * Copyright (c) 2004 Michael Schroeder (mls@suse.de)
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <sys/stat.h>
13
14 #include "rpml.h"
15 #include "util.h"
16 #include "rpmhead.h"
17
18 /****************************************************************
19  *
20  * rpml
21  *
22  */
23
24 static int
25 rpmlget16(FILE *fp)
26 {
27   int r;
28   r = getc(fp);
29   r = r << 8 | getc(fp);
30   return r;
31 }
32
33 static int
34 rpmlget32(FILE *fp)
35 {
36   int r;
37   r = getc(fp);
38   r = r << 8 | getc(fp);
39   r = r << 8 | getc(fp);
40   r = r << 8 | getc(fp);
41   return r;
42 }
43
44 static char *
45 rpmlgetstr(FILE *fp)
46 {
47   int l;
48   char *s, *s2;
49
50   l = getc(fp);
51   s = s2 = xmalloc(l + 2);
52   while(l-- > 0)
53     *s2++ = getc(fp);
54   *s2 = 0;
55   return s;
56 }
57
58 static void
59 rpmlskip(FILE *fp, int l)
60 {
61   while(l-- > 0)
62     (void)getc(fp);
63 }
64
65 static char *
66 rpmlgetfn(FILE *fp, char **lastfnp, int *lastfnlp)
67 {
68   int ol, l;
69   char *n;
70   char *lastfn = *lastfnp;
71   int lastfnl = *lastfnlp;
72
73   ol = getc(fp);
74   if (ol == EOF)
75     {
76       fprintf(stderr, "rpmlgetfn: EOF reached!\n");
77       exit(1);
78     }
79   l = getc(fp);
80   if (l == 255)
81     l = rpmlget16(fp);
82   if (l + ol + 1 > lastfnl)
83     {
84       lastfn = xrealloc(lastfn, l + ol + 1);
85       lastfnl = l + ol + 1;
86     }
87   n = lastfn + ol;
88   while(l-- > 0)
89     *n++ = getc(fp);
90   *n = 0;
91   *lastfnp = lastfn;
92   *lastfnlp = lastfnl;
93   return lastfn;
94 }
95
96 char *
97 rpmlread(FILE *fp, char *fn, int nomagic, struct rpmlfile **filesp, int *nfilesp)
98 {
99   int lastfnl = 0;
100   char *lastfn = 0;
101   char *n, *name, *evr, *nevr;
102   char *buildhost;
103   unsigned int buildtime;
104   int patchescnt, filec, i;
105   struct rpmlfile *files = 0;
106   int nfiles = 0;
107   unsigned int mode, s, ogs;
108
109   if (!nomagic && rpmlget32(fp) != 0x52504d4c)
110     {
111       fprintf(stderr, "%s: not an rpml file\n", fn);
112       exit(1);
113     }
114   name = rpmlgetstr(fp);
115   evr = rpmlgetstr(fp);
116   nevr = xmalloc(strlen(name) + strlen(evr) + 2);
117   sprintf(nevr, "%s-%s", name, evr);
118   buildhost = rpmlgetstr(fp);
119   buildtime = rpmlget32(fp);
120   patchescnt = rpmlget16(fp);
121   xfree(name);
122   xfree(evr);
123   xfree(buildhost);
124   if (patchescnt)
125     {
126       for (i = 0; i < patchescnt; i++)
127         rpmlgetstr(fp);
128       filec = rpmlget32(fp);
129       for (i = 0; i < filec; i++)
130         {
131           if ((nfiles & 15) == 0)
132             files = xrealloc(files, (nfiles + 16) * sizeof(*files));
133           n = rpmlgetfn(fp, &lastfn, &lastfnl);
134           files[nfiles].name = xmalloc(strlen(n) + 1);
135           strcpy(files[nfiles].name, n);
136           files[nfiles].mode = S_IFREG;
137           files[nfiles].fflags = FILE_UNPATCHED;
138           memset(files[nfiles].md5, 0, 16);
139           nfiles++;
140         }
141     }
142   for (;;)
143     {
144       n = rpmlgetfn(fp, &lastfn, &lastfnl);
145       if (!*n)
146         break;
147       if ((nfiles & 15) == 0)
148         files = xrealloc(files, (nfiles + 16) * sizeof(*files));
149       if (*n == '.' && n[1] == '/')
150         n += 2;
151       files[nfiles].name = xmalloc(strlen(n) + 1);
152       strcpy(files[nfiles].name, n);
153       files[nfiles].fflags = 0;
154       memset(files[nfiles].md5, 0, 16);
155       mode = rpmlget16(fp);
156       files[nfiles].mode = mode;
157       if (mode == 0)    /* hard link chain */
158         {
159            nfiles++;
160            continue;
161         }
162       ogs = getc(fp);
163       if (ogs == 0xff)
164         {
165           unsigned int ogs2;
166           ogs2 = getc(fp);
167           ogs = getc(fp);
168           if (ogs2)
169             rpmlskip(fp, ogs2 + 1);
170           if (ogs & 0xfc)
171             rpmlskip(fp, (ogs >> 2 & 0x3f) + 1);
172         }
173       else
174         {
175           if (ogs & 0xe0)
176             rpmlskip(fp, (ogs >> 5 & 7) + 1);
177           if (ogs & 0x1c)
178             rpmlskip(fp, (ogs >> 2 & 7) + 1);
179         }
180       if (S_ISCHR(mode) || S_ISBLK(mode))
181         rpmlget32(fp);  /* rdev */
182       if (S_ISREG(mode) || S_ISLNK(mode))
183         {
184           ogs &= 3;
185           s = 0;
186           if (ogs > 2)
187             s |= getc(fp) << 24;
188           if (ogs > 1)
189             s |= getc(fp) << 16;
190           if (ogs > 0)
191             s |= getc(fp) << 8;
192           s |= getc(fp);
193           if (s)
194             {
195               for (s = 0; s < 16; s++)
196                 files[nfiles].md5[s] = getc(fp);
197             }
198         }
199       nfiles++;
200     }
201   *filesp = files;
202   *nfilesp = nfiles;
203   return nevr;
204 }