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
rpmlget16(FILE * fp)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
rpmlget32(FILE * fp)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 *
rpmlgetstr(FILE * fp)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
rpmlskip(FILE * fp,int l)59 rpmlskip(FILE *fp, int l)
60 {
61 while(l-- > 0)
62 (void)getc(fp);
63 }
64
65 static char *
rpmlgetfn(FILE * fp,char ** lastfnp,int * lastfnlp)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 *
rpmlread(FILE * fp,char * fn,int nomagic,struct rpmlfile ** filesp,int * nfilesp)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 }
205