static int nextchunk(struct solv_zchunk *zck, unsigned int streamid) { unsigned char *p = zck->chunks; unsigned char *chunk_chk_ptr; unsigned int sid, chunk_len, uncompressed_len; unsigned char *cbuf; /* free old buffer */ zck->buf = solv_free(zck->buf); zck->buf_avail = 0; zck->buf_used = 0; for (;;) { if (zck->nchunks == 0) { zck->chunks = p; return 1; /* EOF reached */ } if (p >= zck->hdr_end) return 0; sid = streamid ? 1 : 0; /* check if this is the correct stream */ if ((zck->flags & 1) != 0 && (p = getuint(p, zck->hdr_end, &sid)) == 0) return 0; chunk_chk_ptr = p; /* remember for verification */ p += zck->chunk_chk_len; if (p >= zck->hdr_end) return 0; if ((p = getuint(p, zck->hdr_end, &chunk_len)) == 0) return 0; if ((p = getuint(p, zck->hdr_end, &uncompressed_len)) == 0) return 0; zck->nchunks--; if (sid == streamid) break; /* skip the chunk, but the dict chunk must come first */ if (streamid == 0 || skip_bytes(zck->fp, chunk_len, zck->data_chk) == 0) return 0; } zck->chunks = p; /* ok, read the compressed chunk */ if (!chunk_len) return uncompressed_len ? 0 : 1; cbuf = solv_malloc(chunk_len); if (fread(cbuf, chunk_len, 1, zck->fp) != 1) { solv_free(cbuf); return 0; } if (zck->data_chk) solv_chksum_add(zck->data_chk, cbuf, chunk_len); /* verify the chunk checksum */ if (zck->chunk_chk_id) { Chksum *chk = solv_chksum_create(zck->chunk_chk_id); if (!chk) { solv_free(cbuf); return 0; } solv_chksum_add(chk, cbuf, chunk_len); if (memcmp(solv_chksum_get(chk, 0), chunk_chk_ptr, zck->chunk_chk_len) != 0) { solv_chksum_free(chk, 0); solv_free(cbuf); return 0; } solv_chksum_free(chk, 0); } /* uncompress */ if (zck->comp == 0) { /* not compressed */ if (chunk_len != uncompressed_len) { solv_free(cbuf); return 0; } zck->buf = cbuf; zck->buf_avail = uncompressed_len; return 1; } if (zck->comp == 2) { /* zstd compressed */ size_t r; zck->buf = solv_malloc(uncompressed_len + 1); /* +1 so we can detect too large frames */ if (zck->ddict) r = ZSTD_decompress_usingDDict(zck->dctx, zck->buf, uncompressed_len + 1, cbuf, chunk_len, zck->ddict); else r = ZSTD_decompressDCtx(zck->dctx, zck->buf, uncompressed_len + 1, cbuf, chunk_len); solv_free(cbuf); if (r != uncompressed_len) return 0; zck->buf_avail = uncompressed_len; return 1; } solv_free(cbuf); return 0; }
Id repo_add_arch_pkg(Repo *repo, const char *fn, int flags) { Pool *pool = repo->pool; Repodata *data; FILE *fp; struct tarhead th; char line[4096]; int ignoreline; Solvable *s; int l, fd; struct stat stb; void *pkgidhandle = 0; data = repo_add_repodata(repo, flags); if ((fd = open(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, fn) : fn, O_RDONLY, 0)) < 0) { pool_error(pool, -1, "%s: %s", fn, strerror(errno)); return 0; } if (fstat(fd, &stb)) { pool_error(pool, -1, "%s: fstat: %s", fn, strerror(errno)); close(fd); return 0; } if (!(fp = solv_xfopen_fd(fn, fd, "r"))) { pool_error(pool, -1, "%s: fdopen failed", fn); close(fd); return 0; } s = 0; inittarhead(&th, fp); while (gettarhead(&th) > 0) { if (th.type != 1 || strcmp(th.path, ".PKGINFO") != 0) { skipentry(&th); continue; } ignoreline = 0; s = pool_id2solvable(pool, repo_add_solvable(repo)); if (flags & ARCH_ADD_WITH_PKGID) pkgidhandle = solv_chksum_create(REPOKEY_TYPE_MD5); while (getsentry(&th, line, sizeof(line))) { l = strlen(line); if (l == 0) continue; if (pkgidhandle) solv_chksum_add(pkgidhandle, line, l); if (line[l - 1] != '\n') { ignoreline = 1; continue; } if (ignoreline) { ignoreline = 0; continue; } line[--l] = 0; if (l == 0 || line[0] == '#') continue; if (!strncmp(line, "pkgname = ", 10)) s->name = pool_str2id(pool, line + 10, 1); else if (!strncmp(line, "pkgver = ", 9)) s->evr = pool_str2id(pool, line + 9, 1); else if (!strncmp(line, "pkgdesc = ", 10)) { repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line + 10); repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, line + 10); } else if (!strncmp(line, "url = ", 6)) repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, line + 6); else if (!strncmp(line, "builddate = ", 12)) repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, strtoull(line + 12, 0, 10)); else if (!strncmp(line, "packager = ", 11)) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_PACKAGER, line + 11); else if (!strncmp(line, "size = ", 7)) repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(line + 7, 0, 10)); else if (!strncmp(line, "arch = ", 7)) s->arch = pool_str2id(pool, line + 7, 1); else if (!strncmp(line, "license = ", 10)) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_LICENSE, line + 10); else if (!strncmp(line, "replaces = ", 11)) s->obsoletes = adddep(repo, s->obsoletes, line + 11); else if (!strncmp(line, "group = ", 8)) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_GROUP, line + 8); else if (!strncmp(line, "depend = ", 9)) s->requires = adddep(repo, s->requires, line + 9); else if (!strncmp(line, "optdepend = ", 12)) { char *p = strchr(line, ':'); if (p) *p = 0; s->suggests = adddep(repo, s->suggests, line + 12); } else if (!strncmp(line, "conflict = ", 11)) s->conflicts = adddep(repo, s->conflicts, line + 11); else if (!strncmp(line, "provides = ", 11)) s->provides = adddep(repo, s->provides, line + 11); } break; } freetarhead(&th); fclose(fp); if (!s) { pool_error(pool, -1, "%s: not an arch package", fn); if (pkgidhandle) solv_chksum_free(pkgidhandle, 0); return 0; } if (s && !s->name) { pool_error(pool, -1, "%s: package has no name", fn); repo_free_solvable(repo, s - pool->solvables, 1); s = 0; } if (s) { if (!s->arch) s->arch = ARCH_ANY; if (!s->evr) s->evr = ID_EMPTY; s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); if (!(flags & REPO_NO_LOCATION)) repodata_set_location(data, s - pool->solvables, 0, 0, fn); if (S_ISREG(stb.st_mode)) repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned long long)stb.st_size); if (pkgidhandle) { unsigned char pkgid[16]; solv_chksum_free(pkgidhandle, pkgid); repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid); pkgidhandle = 0; } } if (pkgidhandle) solv_chksum_free(pkgidhandle, 0); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return s ? s - pool->solvables : 0; }