2 * Copyright (c) 2009, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
23 static unsigned char *
24 decompress(unsigned char *in, int inl, int *outlp)
30 memset(&strm, 0, sizeof(strm));
33 out = solv_malloc(4096);
35 strm.avail_out = 4096;
37 ret = inflateInit2(&strm, -MAX_WBITS);
45 if (strm.avail_out == 0)
48 out = solv_realloc(out, outl + 4096);
49 strm.next_out = out + outl;
50 strm.avail_out = 4096;
52 ret = inflate(&strm, Z_NO_FLUSH);
53 if (ret == Z_STREAM_END)
61 outl += 4096 - strm.avail_out;
68 parseonedep(Pool *pool, char *p)
70 char *n, *ne, *e, *ee;
74 while (*p == ' ' || *p == '\t' || *p == '\n')
79 /* find end of name */
80 while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != '(' && *p != '|')
83 while (*p == ' ' || *p == '\t' || *p == '\n')
91 while (*p == ' ' || *p == '\t' || *p == '\n')
112 while (*p == ' ' || *p == '\t' || *p == '\n')
115 while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ')')
118 while (*p && *p != ')')
122 while (*p == ' ' || *p == '\t' || *p == '\n')
125 if (ne - n > 4 && ne[-4] == ':' && !strncmp(ne - 4, ":any", 4))
127 /* multiarch annotation */
128 name = pool_strn2id(pool, n, ne - n - 4, 1);
129 name = pool_rel2id(pool, name, ARCH_ANY, REL_MULTIARCH, 1);
132 name = pool_strn2id(pool, n, ne - n, 1);
135 evr = pool_strn2id(pool, e, ee - e, 1);
136 name = pool_rel2id(pool, name, evr, flags, 1);
140 Id id = parseonedep(pool, p + 1);
142 name = pool_rel2id(pool, name, id, REL_OR, 1);
148 makedeps(Repo *repo, char *deps, unsigned int olddeps, Id marker)
150 Pool *pool = repo->pool;
154 while ((p = strchr(deps, ',')) != 0)
157 olddeps = makedeps(repo, deps, olddeps, marker);
161 id = parseonedep(pool, deps);
164 return repo_addid_dep(repo, olddeps, id, marker);
168 /* put data from control file into the solvable */
169 /* warning: does inplace changes */
171 control2solvable(Solvable *s, Repodata *data, char *control)
173 Repo *repo = s->repo;
174 Pool *pool = repo->pool;
175 char *p, *q, *end, *tag;
178 char checksum[32 * 2 + 1];
188 if (p[1] == ' ' || p[1] == '\t')
191 /* continuation line */
193 while (q >= control && *q == ' ' && *q == '\t')
197 memmove(p + 1 - l, control, l);
206 /* strip trailing space */
207 while (end >= control && *end == ' ' && *end == '\t')
211 q = strchr(tag, ':');
212 if (!q || q - tag < 4)
215 while (*q == ' ' || *q == '\t')
217 x = '@' + (tag[0] & 0x1f);
218 x = (x << 8) + '@' + (tag[1] & 0x1f);
222 if (!strcasecmp(tag, "architecture"))
223 s->arch = pool_str2id(pool, q, 1);
226 if (!strcasecmp(tag, "breaks"))
227 s->conflicts = makedeps(repo, q, s->conflicts, 0);
230 if (!strcasecmp(tag, "conflicts"))
231 s->conflicts = makedeps(repo, q, s->conflicts, 0);
234 if (!strcasecmp(tag, "depends"))
235 s->requires = makedeps(repo, q, s->requires, -SOLVABLE_PREREQMARKER);
236 else if (!strcasecmp(tag, "description"))
238 char *ld = strchr(q, '\n');
242 repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, ld);
245 repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, q);
246 repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, q);
250 if (!strcasecmp(tag, "enhances"))
251 s->enhances = makedeps(repo, q, s->enhances, 0);
254 if (!strcasecmp(tag, "filename"))
255 repodata_set_location(data, s - pool->solvables, 0, 0, q);
258 if (!strcasecmp(tag, "homepage"))
259 repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, q);
262 if (!strcasecmp(tag, "installed-size"))
263 repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(q, 0, 10) << 10);
266 if (!strcasecmp(tag, "md5sum") && !checksumtype && strlen(q) == 16 * 2)
269 checksumtype = REPOKEY_TYPE_MD5;
273 if (!strcasecmp(tag, "package"))
274 s->name = pool_str2id(pool, q, 1);
277 if (!strcasecmp(tag, "pre-depends"))
278 s->requires = makedeps(repo, q, s->requires, SOLVABLE_PREREQMARKER);
279 else if (!strcasecmp(tag, "provides"))
280 s->provides = makedeps(repo, q, s->provides, 0);
283 if (!strcasecmp(tag, "replaces"))
284 s->obsoletes = makedeps(repo, q, s->obsoletes, 0);
285 else if (!strcasecmp(tag, "recommends"))
286 s->recommends = makedeps(repo, q, s->recommends, 0);
289 newtype = solv_chksum_str2type(tag);
290 if (!newtype || solv_chksum_len(newtype) * 2 != strlen(q))
292 if (!checksumtype || (newtype == REPOKEY_TYPE_SHA1 && checksumtype != REPOKEY_TYPE_SHA256) || newtype == REPOKEY_TYPE_SHA256)
295 checksumtype = newtype;
299 if (!strcasecmp(tag, "source"))
302 /* ignore version for now */
303 for (q2 = q; *q2; q2++)
304 if (*q2 == ' ' || *q2 == '\t')
309 if (s->name && !strcmp(q, pool_id2str(pool, s->name)))
310 repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
312 repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, pool_str2id(pool, q, 1));
317 if (!strcasecmp(tag, "suggests"))
318 s->suggests = makedeps(repo, q, s->suggests, 0);
321 if (!strcasecmp(tag, "version"))
322 s->evr = pool_str2id(pool, q, 1);
327 repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, checksumtype, checksum);
333 s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
334 if (s->name && !havesource)
335 repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
338 /* obsoletes only count when the packages also conflict */
339 /* XXX: should not transcode here */
342 for (i = j = s->obsoletes; (d = repo->idarraydata[i]) != 0; i++)
346 for (k = s->conflicts; (cid = repo->idarraydata[k]) != 0; k++)
348 if (repo->idarraydata[k] == cid)
352 Reldep *rd = GETRELDEP(pool, cid);
353 if (rd->flags < 8 && rd->name == d)
354 break; /* specialize obsoletes */
358 repo->idarraydata[j++] = cid;
360 repo->idarraydata[j] = 0;
361 if (j == s->obsoletes)
367 repo_add_debpackages(Repo *repo, FILE *fp, int flags)
369 Pool *pool = repo->pool;
375 data = repo_add_repodata(repo, flags);
376 buf = solv_malloc(4096);
383 if (!(p = strchr(p, '\n')))
386 if (l + 1024 >= bufl)
388 buf = solv_realloc(buf, bufl + 4096);
394 ll = fread(p, 1, bufl - l - 1, fp);
398 while ((l3 = strlen(p)) < ll)
408 s = pool_id2solvable(pool, repo_add_solvable(repo));
409 control2solvable(s, data, buf);
411 repo_free_solvable(repo, s - pool->solvables, 1);
413 memmove(buf, p + 1, l - ll);
420 s = pool_id2solvable(pool, repo_add_solvable(repo));
421 control2solvable(s, data, buf);
423 repo_free_solvable(repo, s - pool->solvables, 1);
426 if (!(flags & REPO_NO_INTERNALIZE))
427 repodata_internalize(data);
432 repo_add_debdb(Repo *repo, int flags)
435 const char *path = "/var/lib/dpkg/status";
436 if (flags & REPO_USE_ROOTDIR)
437 path = pool_prepend_rootdir_tmp(repo->pool, path);
438 if ((fp = fopen(path, "r")) == 0)
439 return pool_error(repo->pool, -1, "%s: %s", path, strerror(errno));
440 repo_add_debpackages(repo, fp, flags);
446 repo_add_deb(Repo *repo, const char *deb, int flags)
448 Pool *pool = repo->pool;
450 unsigned char buf[4096], *bp;
451 int l, l2, vlen, clen, ctarlen;
453 unsigned char pkgid[16];
460 data = repo_add_repodata(repo, flags);
461 if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, deb) : deb, "r")) == 0)
463 pool_error(pool, -1, "%s: %s", deb, strerror(errno));
466 if (fstat(fileno(fp), &stb))
468 pool_error(pool, -1, "fstat: %s", strerror(errno));
472 l = fread(buf, 1, sizeof(buf), fp);
473 if (l < 8 + 60 || strncmp((char *)buf, "!<arch>\ndebian-binary ", 8 + 16) != 0)
475 pool_error(pool, -1, "%s: not a deb package", deb);
479 vlen = atoi((char *)buf + 8 + 48);
480 if (vlen < 0 || vlen > l)
482 pool_error(pool, -1, "%s: not a deb package", deb);
487 if (l < 8 + 60 + vlen + 60)
489 pool_error(pool, -1, "%s: unhandled deb package", deb);
493 if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) != 0)
495 pool_error(pool, -1, "%s: control.tar.gz is not second entry", deb);
499 clen = atoi((char *)buf + 8 + 60 + vlen + 48);
500 if (clen <= 0 || clen >= 0x100000)
502 pool_error(pool, -1, "%s: control.tar.gz has illegal size", deb);
506 ctgz = solv_calloc(1, clen + 4);
507 bp = buf + 8 + 60 + vlen + 60;
508 l -= 8 + 60 + vlen + 60;
515 if (fread(ctgz + l, clen - l, 1, fp) != 1)
517 pool_error(pool, -1, "%s: unexpected EOF", deb);
525 if (flags & DEBS_ADD_WITH_PKGID)
527 Chksum *chk = solv_chksum_create(REPOKEY_TYPE_MD5);
528 solv_chksum_add(chk, ctgz, clen);
529 solv_chksum_free(chk, pkgid);
532 if (ctgz[0] != 0x1f || ctgz[1] != 0x8b)
534 pool_error(pool, -1, "%s: control.tar.gz is not gzipped", deb);
538 if (ctgz[2] != 8 || (ctgz[3] & 0xe0) != 0)
540 pool_error(pool, -1, "%s: control.tar.gz is compressed in a strange way", deb);
545 bp += 6; /* skip time, xflags and OS code */
548 /* skip extra field */
549 l = bp[0] | bp[1] << 8;
551 if (bp >= ctgz + clen)
553 pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb);
558 if (ctgz[3] & 0x08) /* orig filename */
561 if (ctgz[3] & 0x10) /* file comment */
564 if (ctgz[3] & 0x02) /* header crc */
566 if (bp >= ctgz + clen)
568 pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb);
572 ctar = decompress(bp, ctgz + clen - bp, &ctarlen);
576 pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb);
585 for (j = 124; j < 124 + 12; j++)
586 if (bp[j] >= '0' && bp[j] <= '7')
587 l2 = l2 * 8 + (bp[j] - '0');
588 if (!strcmp((char *)bp, "./control") || !strcmp((char *)bp, "control"))
590 l2 = 512 + ((l2 + 511) & ~511);
594 if (l <= 512 || l - 512 - l2 <= 0 || l2 <= 0)
596 pool_error(pool, -1, "%s: control.tar.gz contains no control file", deb);
600 memmove(ctar, bp + 512, l2);
601 ctar = solv_realloc(ctar, l2 + 1);
603 s = pool_id2solvable(pool, repo_add_solvable(repo));
604 control2solvable(s, data, (char *)ctar);
605 if (!(flags & REPO_NO_LOCATION))
606 repodata_set_location(data, s - pool->solvables, 0, 0, deb);
607 if (S_ISREG(stb.st_mode))
608 repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned long long)stb.st_size);
610 repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid);
612 if (!(flags & REPO_NO_INTERNALIZE))
613 repodata_internalize(data);
614 return s - pool->solvables;