2 * Copyright (c) 2009, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
22 static unsigned char *
23 decompress(unsigned char *in, int inl, int *outlp)
29 memset(&strm, 0, sizeof(strm));
32 out = sat_malloc(4096);
34 strm.avail_out = 4096;
36 ret = inflateInit2(&strm, -MAX_WBITS);
44 if (strm.avail_out == 0)
47 out = sat_realloc(out, outl + 4096);
48 strm.next_out = out + outl;
49 strm.avail_out = 4096;
51 ret = inflate(&strm, Z_NO_FLUSH);
52 if (ret == Z_STREAM_END)
60 outl += 4096 - strm.avail_out;
67 parseonedep(Pool *pool, char *p)
69 char *n, *ne, *e, *ee;
73 while (*p == ' ' || *p == '\t' || *p == '\n')
78 /* find end of name */
79 while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != '(' && *p != '|')
82 while (*p == ' ' || *p == '\t' || *p == '\n')
90 while (*p == ' ' || *p == '\t' || *p == '\n')
111 while (*p == ' ' || *p == '\t' || *p == '\n')
114 while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ')')
117 while (*p && *p != ')')
121 while (*p == ' ' || *p == '\t' || *p == '\n')
124 name = strn2id(pool, n, ne - n, 1);
127 evr = strn2id(pool, e, ee - e, 1);
128 name = rel2id(pool, name, evr, flags, 1);
132 Id id = parseonedep(pool, p + 1);
134 name = rel2id(pool, name, id, REL_OR, 1);
140 makedeps(Repo *repo, char *deps, unsigned int olddeps, Id marker)
142 Pool *pool = repo->pool;
146 while ((p = strchr(deps, ',')) != 0)
149 olddeps = makedeps(repo, deps, olddeps, marker);
153 id = parseonedep(pool, deps);
156 return repo_addid_dep(repo, olddeps, id, marker);
160 /* put data from control file into the solvable */
161 /* warning: does inplace changes */
163 control2solvable(Solvable *s, Repodata *data, char *control)
165 Repo *repo = s->repo;
166 Pool *pool = repo->pool;
167 char *p, *q, *end, *tag;
170 char checksum[32 * 2 + 1];
179 if (p[1] == ' ' || p[1] == '\t')
182 /* continuation line */
184 while (q >= control && *q == ' ' && *q == '\t')
188 memmove(p + 1 - l, control, l);
197 /* strip trailing space */
198 while (end >= control && *end == ' ' && *end == '\t')
202 q = strchr(tag, ':');
203 if (!q || q - tag < 4)
206 while (*q == ' ' || *q == '\t')
208 x = '@' + (tag[0] & 0x1f);
209 x = (x << 8) + '@' + (tag[1] & 0x1f);
213 if (!strcasecmp(tag, "architecture"))
214 s->arch = str2id(pool, q, 1);
217 if (!strcasecmp(tag, "breaks"))
218 s->conflicts = makedeps(repo, q, s->conflicts, 0);
221 if (!strcasecmp(tag, "conflicts"))
222 s->conflicts = makedeps(repo, q, s->conflicts, 0);
225 if (!strcasecmp(tag, "depends"))
226 s->requires = makedeps(repo, q, s->requires, -SOLVABLE_PREREQMARKER);
227 else if (!strcasecmp(tag, "description"))
229 char *ld = strchr(q, '\n');
233 repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, ld);
236 repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, q);
237 repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, q);
241 if (!strcasecmp(tag, "enhances"))
242 s->enhances = makedeps(repo, q, s->enhances, 0);
245 if (!strcasecmp(tag, "filename"))
246 repodata_set_location(data, s - pool->solvables, 0, 0, q);
249 if (!strcasecmp(tag, "homepage"))
250 repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, q);
253 if (!strcasecmp(tag, "installed-size"))
254 repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, atoi(q));
257 if (!strcasecmp(tag, "md5sum") && !checksumtype && strlen(q) == 16 * 2)
260 checksumtype = REPOKEY_TYPE_MD5;
264 if (!strcasecmp(tag, "package"))
265 s->name = str2id(pool, q, 1);
268 if (!strcasecmp(tag, "pre-depends"))
269 s->requires = makedeps(repo, q, s->requires, SOLVABLE_PREREQMARKER);
270 else if (!strcasecmp(tag, "provides"))
271 s->provides = makedeps(repo, q, s->provides, 0);
274 if (!strcasecmp(tag, "replaces"))
275 s->obsoletes = makedeps(repo, q, s->conflicts, 0);
276 else if (!strcasecmp(tag, "recommends"))
277 s->recommends = makedeps(repo, q, s->recommends, 0);
280 if (!strcasecmp(tag, "sha1") && checksumtype != REPOKEY_TYPE_SHA256 && strlen(q) == 20 * 2)
283 checksumtype = REPOKEY_TYPE_SHA1;
285 else if (!strcasecmp(tag, "sha256") && strlen(q) == 32 * 2)
288 checksumtype = REPOKEY_TYPE_SHA256;
292 if (!strcasecmp(tag, "source"))
295 /* ignore version for now */
296 for (q2 = q; *q2; q2++)
297 if (*q2 == ' ' || *q2 == '\t')
302 if (s->name && !strcmp(q, id2str(pool, s->name)))
303 repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
305 repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, str2id(pool, q, 1));
310 if (!strcasecmp(tag, "suggests"))
311 s->suggests = makedeps(repo, q, s->suggests, 0);
314 if (!strcasecmp(tag, "version"))
315 s->evr = str2id(pool, q, 1);
320 repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, checksumtype, checksum);
326 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
327 if (s->name && !havesource)
328 repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
331 /* obsoletes only count when the packages also conflict */
334 for (i = j = s->obsoletes; (d = repo->idarraydata[i]) != 0; i++)
338 for (k = s->conflicts; repo->idarraydata[k] != 0; k++)
339 if (repo->idarraydata[k] == d)
341 if (repo->idarraydata[k])
343 repo->idarraydata[j++] = d;
347 repo->idarraydata[j] = 0;
352 repo_add_debpackages(Repo *repo, FILE *fp, int flags)
354 Pool *pool = repo->pool;
360 data = repo_add_repodata(repo, flags);
361 buf = sat_malloc(4096);
368 if (!(p = strchr(p, '\n')))
371 if (l + 1024 >= bufl)
373 buf = sat_realloc(buf, bufl + 4096);
379 ll = fread(p, 1, bufl - l - 1, fp);
383 while ((l3 = strlen(p)) < ll)
393 s = pool_id2solvable(pool, repo_add_solvable(repo));
394 control2solvable(s, data, buf);
396 repo_free_solvable_block(repo, s - pool->solvables, 1, 1);
398 memmove(buf, p + 1, l - ll);
405 s = pool_id2solvable(pool, repo_add_solvable(repo));
406 control2solvable(s, data, buf);
408 repo_free_solvable_block(repo, s - pool->solvables, 1, 1);
411 if (!(flags & REPO_NO_INTERNALIZE))
412 repodata_internalize(data);
416 repo_add_debs(Repo *repo, const char **debs, int ndebs, int flags)
418 Pool *pool = repo->pool;
420 unsigned char buf[4096], *bp;
421 int i, l, l2, vlen, clen, ctarlen;
423 unsigned char pkgid[16];
430 data = repo_add_repodata(repo, flags);
431 for (i = 0; i < ndebs; i++)
433 if ((fp = fopen(debs[i], "r")) == 0)
438 if (fstat(fileno(fp), &stb))
443 l = fread(buf, 1, sizeof(buf), fp);
444 if (l < 8 + 60 || strncmp((char *)buf, "!<arch>\ndebian-binary ", 8 + 16) != 0)
446 fprintf(stderr, "%s: not a deb package\n", debs[i]);
450 vlen = atoi((char *)buf + 8 + 48);
451 if (vlen < 0 || vlen > l)
453 fprintf(stderr, "%s: not a deb package\n", debs[i]);
458 if (l < 8 + 60 + vlen + 60)
460 fprintf(stderr, "%s: unhandled deb package\n", debs[i]);
464 if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) != 0)
466 fprintf(stderr, "%s: control.tar.gz is not second entry\n", debs[i]);
470 clen = atoi((char *)buf + 8 + 60 + vlen + 48);
473 fprintf(stderr, "%s: control.tar.gz has illegal size\n", debs[i]);
477 ctgz = sat_calloc(1, clen + 4);
478 bp = buf + 8 + 60 + vlen + 60;
479 l -= 8 + 60 + vlen + 60;
486 if (fread(ctgz + l, clen - l, 1, fp) != 1)
488 fprintf(stderr, "%s: unexpected EOF\n", debs[i]);
496 if (flags & DEBS_ADD_WITH_PKGID)
498 void *handle = sat_chksum_create(REPOKEY_TYPE_MD5);
499 sat_chksum_add(handle, ctgz, clen);
500 sat_chksum_free(handle, pkgid);
503 if (ctgz[0] != 0x1f || ctgz[1] != 0x8b)
505 fprintf(stderr, "%s: control.tar.gz is not gzipped\n", debs[i]);
509 if (ctgz[2] != 8 || (ctgz[3] & 0xe0) != 0)
511 fprintf(stderr, "%s: control.tar.gz is compressed in a strange way\n", debs[i]);
516 bp += 6; /* skip time, xflags and OS code */
519 /* skip extra field */
520 l = bp[0] | bp[1] << 8;
522 if (bp >= ctgz + clen)
524 fprintf(stderr, "%s: corrupt gzip\n", debs[i]);
529 if (ctgz[3] & 0x08) /* orig filename */
532 if (ctgz[3] & 0x10) /* file comment */
535 if (ctgz[3] & 0x02) /* header crc */
537 if (bp >= ctgz + clen)
539 fprintf(stderr, "%s: corrupt control.tar.gz\n", debs[i]);
543 ctar = decompress(bp, ctgz + clen - bp, &ctarlen);
547 fprintf(stderr, "%s: corrupt control.tar.gz\n", debs[i]);
556 for (j = 124; j < 124 + 12; j++)
557 if (bp[j] >= '0' && bp[j] <= '7')
558 l2 = l2 * 8 + (bp[j] - '0');
559 if (!strcmp((char *)bp, "./control"))
561 l2 = 512 + ((l2 + 511) & ~511);
565 if (l <= 512 || l - 512 - l2 <= 0 || l2 <= 0)
567 fprintf(stderr, "%s: control.tar.gz contains no ./control file\n", debs[i]);
571 memmove(ctar, bp + 512, l2);
572 ctar = sat_realloc(ctar, l2 + 1);
574 s = pool_id2solvable(pool, repo_add_solvable(repo));
575 control2solvable(s, data, (char *)ctar);
576 repodata_set_location(data, s - pool->solvables, 0, 0, debs[i]);
577 if (S_ISREG(stb.st_mode))
578 repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned int)((stb.st_size + 1023) / 1024));
580 repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid);
583 if (!(flags & REPO_NO_INTERNALIZE))
584 repodata_internalize(data);