db: live with sha1 and md5

this also convers scripts file to a tar archive.
cute-signatures
Timo Teras 2009-07-14 19:14:05 +03:00
parent e9eaedff50
commit 981bc118f8
15 changed files with 374 additions and 162 deletions

View File

@ -103,7 +103,8 @@ static int add_main(void *ctx, int argc, char **argv)
goto err;
}
virtpkg->name = apk_db_get_name(&db, APK_BLOB_STR(actx->virtpkg));
csum_blob(APK_BLOB_STR(virtpkg->name->name), virtpkg->csum);
apk_blob_checksum(APK_BLOB_STR(virtpkg->name->name),
apk_default_checksum(), &virtpkg->csum);
virtpkg->version = strdup("0");
virtpkg->description = strdup("virtual meta package");
virtdep = apk_dep_from_pkg(&db, virtpkg);

View File

@ -23,9 +23,7 @@
#include "apk_defines.h"
#include "apk_applet.h"
#include "apk_blob.h"
#include "apk_csum.h"
csum_t bad_checksum = {0};
const char *apk_root;
struct apk_repository_url apk_repository_list;
int apk_verbosity = 1, apk_cwd_fd, apk_wait;

View File

@ -4,7 +4,7 @@
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
@ -22,6 +22,7 @@ typedef int (*apk_archive_entry_parser)(void *ctx,
int apk_parse_tar(struct apk_istream *, apk_archive_entry_parser parser, void *ctx);
int apk_parse_tar_gz(struct apk_bstream *, apk_archive_entry_parser parser, void *ctx);
int apk_write_tar_entry(struct apk_ostream *, const struct apk_file_info *ae, char *data);
int apk_archive_entry_extract(const struct apk_file_info *ae,
struct apk_istream *is,

View File

@ -13,6 +13,8 @@
#define APK_BLOB_H
#include <string.h>
#include <openssl/evp.h>
#include "apk_defines.h"
struct apk_blob {
@ -22,10 +24,38 @@ struct apk_blob {
typedef struct apk_blob apk_blob_t;
typedef int (*apk_blob_cb)(void *ctx, apk_blob_t blob);
#define APK_CHECKSUM_NONE 0
#define APK_CHECKSUM_MD5 16
#define APK_CHECKSUM_SHA1 20
/* Internal cointainer for MD5 or SHA1 */
struct apk_checksum {
unsigned char data[20];
unsigned char type;
};
static inline const EVP_MD *apk_default_checksum(void)
{
return EVP_sha1();
}
static inline const EVP_MD *apk_get_digest(int type)
{
switch (type) {
case APK_CHECKSUM_MD5:
return EVP_md5();
case APK_CHECKSUM_SHA1:
return EVP_sha1();
}
return EVP_md_null();
}
#define APK_BLOB_IS_NULL(blob) ((blob).ptr == NULL)
#define APK_BLOB_NULL ((apk_blob_t){0, NULL})
#define APK_BLOB_BUF(buf) ((apk_blob_t){sizeof(buf), (char *)(buf)})
#define APK_BLOB_CSUM(csum) ((apk_blob_t){(csum).type, (char *)(csum).data})
#define APK_BLOB_STRUCT(s) ((apk_blob_t){sizeof(s), (char*)&(s)})
#define APK_BLOB_PTR_LEN(beg,len) ((apk_blob_t){(len), (beg)})
#define APK_BLOB_PTR_PTR(beg,end) APK_BLOB_PTR_LEN((beg),(end)-(beg)+1)
@ -47,12 +77,26 @@ int apk_blob_compare(apk_blob_t a, apk_blob_t b);
int apk_blob_for_each_segment(apk_blob_t blob, const char *split,
apk_blob_cb cb, void *ctx);
static inline void apk_blob_checksum(apk_blob_t b, const EVP_MD *md, struct apk_checksum *csum)
{
csum->type = EVP_MD_size(md);
EVP_Digest(b.ptr, b.len, csum->data, NULL, md, NULL);
}
static inline const int apk_checksum_compare(const struct apk_checksum *a,
const struct apk_checksum *b)
{
return apk_blob_compare(APK_BLOB_PTR_LEN((char *) a->data, a->type),
APK_BLOB_PTR_LEN((char *) b->data, b->type));
}
void apk_blob_push_blob(apk_blob_t *to, apk_blob_t literal);
void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix);
void apk_blob_push_csum(apk_blob_t *to, struct apk_checksum *csum);
void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary);
void apk_blob_pull_char(apk_blob_t *b, int expected);
unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix);
void apk_blob_pull_csum(apk_blob_t *b, struct apk_checksum *csum);
void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to);
#endif

View File

@ -1,49 +0,0 @@
/* apk_csum.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2009 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
#ifndef APK_CSUM_H
#define APK_CSUM_H
#include <openssl/evp.h>
#define MAX_CSUM_SIZE 16 /* MD5 */
typedef unsigned char *csum_p;
typedef unsigned char csum_t[MAX_CSUM_SIZE];
typedef EVP_MD_CTX csum_ctx_t;
extern csum_t bad_checksum;
static inline void csum_init(csum_ctx_t *ctx)
{
EVP_DigestInit(ctx, EVP_md5());
}
static inline void csum_process(csum_ctx_t *ctx, unsigned char *buf, size_t len)
{
EVP_DigestUpdate(ctx, buf, len);
}
static inline void csum_finish(csum_ctx_t *ctx, csum_p csum)
{
EVP_DigestFinal(ctx, csum, NULL);
}
static inline int csum_valid(csum_p csum)
{
return memcmp(csum, bad_checksum, MAX_CSUM_SIZE);
}
static inline void csum_blob(apk_blob_t blob, csum_p csum)
{
EVP_Digest(blob.ptr, blob.len, csum, NULL, EVP_md5(), NULL);
}
#endif

View File

@ -17,7 +17,8 @@
#include "apk_archive.h"
#include "apk_package.h"
#define APK_MAX_REPOS 32
#define APK_MAX_REPOS 32
#define APK_CACHE_CSUM_BYTES 4
extern const char * const apk_index_gz;
@ -29,8 +30,8 @@ struct apk_db_file {
struct hlist_node diri_files_list;
struct apk_db_dir_instance *diri;
csum_t csum;
unsigned short namelen;
struct apk_checksum csum;
char name[];
};
@ -73,7 +74,7 @@ struct apk_name {
struct apk_repository {
char *url;
csum_t url_csum;
struct apk_checksum csum;
};
struct apk_database {
@ -135,7 +136,7 @@ int apk_db_cache_active(struct apk_database *db);
struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file);
struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg);
struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum);
struct apk_package *apk_db_get_pkg(struct apk_database *db, struct apk_checksum *csum);
struct apk_package *apk_db_get_file_owner(struct apk_database *db, apk_blob_t filename);
int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo);
@ -143,9 +144,10 @@ int apk_db_index_write(struct apk_database *db, struct apk_ostream *os);
int apk_db_add_repository(apk_database_t db, apk_blob_t repository);
int apk_repository_update(struct apk_database *db, struct apk_repository *repo);
int apk_cache_download(struct apk_database *db, csum_t csum,
int apk_cache_download(struct apk_database *db, struct apk_checksum *csum,
const char *url, const char *item);
int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item);
int apk_cache_exists(struct apk_database *db, struct apk_checksum *csum,
const char *item);
int apk_db_install_pkg(struct apk_database *db,
struct apk_package *oldpkg,

View File

@ -11,9 +11,10 @@
#ifndef APK_IO
#define APK_IO
#include <openssl/evp.h>
#include "apk_defines.h"
#include "apk_blob.h"
#include "apk_csum.h"
struct apk_file_info {
char *name;
@ -26,7 +27,7 @@ struct apk_file_info {
mode_t mode;
time_t mtime;
dev_t device;
csum_t csum;
struct apk_checksum csum;
};
struct apk_istream {
@ -83,7 +84,7 @@ size_t apk_ostream_write_string(struct apk_ostream *ostream, const char *string)
apk_blob_t apk_blob_from_istream(struct apk_istream *istream, size_t size);
apk_blob_t apk_blob_from_file(const char *file);
int apk_file_get_info(const char *filename, struct apk_file_info *fi);
int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *fi);
int apk_url_download(const char *url, const char *file);
const char *apk_url_local_file(const char *url);

View File

@ -4,7 +4,7 @@
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
@ -52,7 +52,6 @@ APK_ARRAY(apk_dependency_array, struct apk_dependency);
struct apk_package {
apk_hash_node hash_node;
csum_t csum;
unsigned repos;
struct apk_name *name;
char *version;
@ -60,6 +59,7 @@ struct apk_package {
struct apk_dependency_array *depends;
size_t installed_size, size;
char *filename;
struct apk_checksum csum;
/* for installed packages only */
struct list_head installed_pkgs_list;
@ -68,6 +68,8 @@ struct apk_package {
};
APK_ARRAY(apk_package_array, struct apk_package *);
extern const char *apk_script_types[];
int apk_deps_add(struct apk_dependency_array **depends,
struct apk_dependency *dep);
void apk_deps_del(struct apk_dependency_array **deps,

View File

@ -44,19 +44,34 @@ struct tar_header {
char padding[12]; /* 500-512 */
};
#define GET_OCTAL(s) get_octal(s, sizeof(s))
#define GET_OCTAL(s) get_octal(s, sizeof(s))
#define PUT_OCTAL(s,v) put_octal(s, sizeof(s), v)
static int get_octal(char *s, size_t l)
{
apk_blob_t b = APK_BLOB_PTR_LEN(s, l);
return apk_blob_pull_uint(&b, 8);
}
static void put_octal(char *s, size_t l, size_t value)
{
char *ptr = &s[l - 1];
*(ptr--) = '\0';
while (value != 0 && ptr >= s) {
*(ptr--) = '0' + (value % 8);
value /= 8;
}
while (ptr >= s)
*(ptr--) = '0';
}
struct apk_tar_entry_istream {
struct apk_istream is;
struct apk_istream *tar_is;
size_t bytes_left;
csum_ctx_t csum_ctx;
csum_p csum;
EVP_MD_CTX mdctx;
struct apk_checksum *csum;
};
static size_t tar_entry_read(void *stream, void *ptr, size_t size)
@ -69,9 +84,11 @@ static size_t tar_entry_read(void *stream, void *ptr, size_t size)
size = teis->tar_is->read(teis->tar_is, ptr, size);
if (size > 0) {
teis->bytes_left -= size;
csum_process(&teis->csum_ctx, ptr, size);
if (teis->bytes_left == 0)
csum_finish(&teis->csum_ctx, teis->csum);
EVP_DigestUpdate(&teis->mdctx, ptr, size);
if (teis->bytes_left == 0) {
teis->csum->type = EVP_MD_CTX_size(&teis->mdctx);
EVP_DigestFinal_ex(&teis->mdctx, teis->csum->data, NULL);
}
}
return size;
}
@ -83,13 +100,14 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser,
struct apk_tar_entry_istream teis = {
.is.read = tar_entry_read,
.tar_is = is,
.csum = entry.csum,
.csum = &entry.csum,
};
struct tar_header buf;
unsigned long offset = 0;
int end = 0, r;
size_t toskip;
EVP_MD_CTX_init(&teis.mdctx);
memset(&entry, 0, sizeof(entry));
while ((r = is->read(is, &buf, 512)) == 512) {
offset += 512;
@ -156,11 +174,11 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser,
entry.name = strdup(buf.name);
/* callback parser function */
csum_init(&teis.csum_ctx);
EVP_DigestInit_ex(&teis.mdctx, apk_default_checksum(), NULL);
r = parser(ctx, &entry, &teis.is);
free(entry.name);
if (r != 0)
return r;
goto err;
entry.name = NULL;
}
@ -173,12 +191,67 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser,
if (toskip != 0)
is->read(is, NULL, toskip);
}
EVP_MD_CTX_cleanup(&teis.mdctx);
if (r != 0) {
apk_error("Bad TAR header (r=%d)", r);
return -1;
}
return 0;
err:
EVP_MD_CTX_cleanup(&teis.mdctx);
return r;
}
int apk_write_tar_entry(struct apk_ostream *os, const struct apk_file_info *ae, char *data)
{
static char padding[512];
struct tar_header buf;
int pad;
memset(&buf, 0, sizeof(buf));
if (ae != NULL) {
const unsigned char *src;
int chksum, i;
if (S_ISREG(ae->mode))
buf.typeflag = '0';
else
return -1;
strncpy(buf.name, ae->name, sizeof(buf.name));
strncpy(buf.uname, ae->uname, sizeof(buf.uname));
strncpy(buf.gname, ae->gname, sizeof(buf.gname));
PUT_OCTAL(buf.size, ae->size);
PUT_OCTAL(buf.uid, ae->uid);
PUT_OCTAL(buf.gid, ae->gid);
PUT_OCTAL(buf.mode, ae->mode & 07777);
PUT_OCTAL(buf.mtime, ae->mtime);
/* Checksum */
strcpy(buf.magic, "ustar ");
memset(buf.chksum, ' ', sizeof(buf.chksum));
src = (const unsigned char *) &buf;
for (i = chksum = 0; i < sizeof(buf); i++)
chksum += src[i];
put_octal(buf.chksum, sizeof(buf.chksum)-1, chksum);
}
if (os->write(os, &buf, sizeof(buf)) != sizeof(buf))
return -1;
if (data != NULL) {
if (os->write(os, data, ae->size) != ae->size)
return -1;
pad = 512 - (ae->size & 511);
if (pad != 512 &&
os->write(os, padding, pad) != pad)
return -1;
}
return 0;
}

View File

@ -46,7 +46,7 @@ static int audit_directory(apk_hash_item item, void *ctx)
snprintf(tmp, sizeof(tmp), "%s/%s", dbd->name, de->d_name);
if (apk_file_get_info(tmp, &fi) < 0)
if (apk_file_get_info(tmp, APK_CHECKSUM_NONE, &fi) < 0)
continue;
if (S_ISDIR(fi.mode)) {
@ -57,8 +57,10 @@ static int audit_directory(apk_hash_item item, void *ctx)
} else {
dbf = apk_db_file_query(db, bdir, APK_BLOB_STR(de->d_name));
if (dbf != NULL) {
if (apk_blob_compare(APK_BLOB_BUF(fi.csum),
APK_BLOB_BUF(dbf->csum)) == 0)
if (apk_file_get_info(tmp, dbf->csum.type, &fi) < 0)
continue;
if (apk_checksum_compare(&fi.csum, &dbf->csum) == 0)
continue;
reason = 'U';

View File

@ -186,6 +186,30 @@ void apk_blob_push_uint(apk_blob_t *to, unsigned int value, int radix)
apk_blob_push_blob(to, APK_BLOB_PTR_PTR(ptr+1, &buf[sizeof(buf)-1]));
}
static int checksum_char_to_id(char chr)
{
switch (chr) {
case '1': return APK_CHECKSUM_SHA1;
}
return APK_CHECKSUM_NONE;
}
void apk_blob_push_csum(apk_blob_t *to, struct apk_checksum *csum)
{
switch (csum->type) {
case APK_CHECKSUM_MD5:
apk_blob_push_hexdump(to, APK_BLOB_CSUM(*csum));
break;
case APK_CHECKSUM_SHA1:
apk_blob_push_blob(to, APK_BLOB_STR("X1"));
apk_blob_push_hexdump(to, APK_BLOB_CSUM(*csum));
break;
default:
*to = APK_BLOB_NULL;
break;
}
}
void apk_blob_push_hexdump(apk_blob_t *to, apk_blob_t binary)
{
char *d;
@ -239,6 +263,31 @@ unsigned int apk_blob_pull_uint(apk_blob_t *b, int radix)
return val;
}
void apk_blob_pull_csum(apk_blob_t *b, struct apk_checksum *csum)
{
if (unlikely(APK_BLOB_IS_NULL(*b)))
return;
if (unlikely(b->len < 2)) {
*b = APK_BLOB_NULL;
return;
}
switch (b->ptr[0]) {
case 'X':
csum->type = checksum_char_to_id(b->ptr[1]);
b->ptr += 2;
b->len -= 2;
apk_blob_pull_hexdump(b, APK_BLOB_CSUM(*csum));
break;
default:
/* Assume MD5 for backwards compatibility */
csum->type = APK_CHECKSUM_MD5;
apk_blob_pull_hexdump(b, APK_BLOB_CSUM(*csum));
break;
}
}
void apk_blob_pull_hexdump(apk_blob_t *b, apk_blob_t to)
{
char *s, *d;

View File

@ -46,13 +46,13 @@ static int cache_download(struct apk_database *db)
pkg = change->newpkg;
snprintf(pkgfile, sizeof(pkgfile), "%s-%s.apk",
pkg->name->name, pkg->version);
if (apk_cache_exists(db, pkg->csum, pkgfile))
if (apk_cache_exists(db, &pkg->csum, pkgfile))
continue;
for (i = 0; i < db->num_repos; i++) {
if (!(pkg->repos & BIT(i)))
continue;
r = apk_cache_download(db, pkg->csum, db->repos[i].url,
r = apk_cache_download(db, &pkg->csum, db->repos[i].url,
pkgfile);
if (r != 0)
return r;
@ -68,11 +68,9 @@ static int cache_clean(struct apk_database *db)
{
DIR *dir;
struct dirent *de;
struct apk_package *pkg;
char path[256];
char path[256], csum[APK_CACHE_CSUM_BYTES];
int delete, i;
apk_blob_t b;
csum_t csum;
snprintf(path, sizeof(path), "%s/%s", db->root, db->cache_dir);
if (chdir(path) != 0)
@ -87,24 +85,25 @@ static int cache_clean(struct apk_database *db)
continue;
delete = TRUE;
do {
if (strlen(de->d_name) <= sizeof(csum_t)*2+2)
if (strlen(de->d_name) <= APK_CACHE_CSUM_BYTES*2+2)
break;
b = APK_BLOB_PTR_LEN(de->d_name, sizeof(csum_t) * 2);
b = APK_BLOB_PTR_LEN(de->d_name, APK_CACHE_CSUM_BYTES*2);
apk_blob_pull_hexdump(&b, APK_BLOB_BUF(csum));
if (APK_BLOB_IS_NULL(b))
break;
if (de->d_name[sizeof(csum_t)*2] != '.')
if (de->d_name[APK_CACHE_CSUM_BYTES*2] != '.')
break;
if (strcmp(&de->d_name[sizeof(csum_t)*2+1],
if (strcmp(&de->d_name[APK_CACHE_CSUM_BYTES*2+1],
apk_index_gz) == 0) {
/* Index - check for matching repository */
for (i = 0; i < db->num_repos; i++)
if (memcmp(db->repos[i].url_csum,
csum, sizeof(csum_t)) == 0)
if (memcmp(db->repos[i].csum.data,
csum, APK_CACHE_CSUM_BYTES) == 0)
break;
delete = (i >= db->num_repos);
} else {
/* Package - search for it */
#if 0
pkg = apk_db_get_pkg(db, csum);
if (pkg == NULL)
break;
@ -113,6 +112,8 @@ static int cache_clean(struct apk_database *db)
pkg->name->name, pkg->version);
delete = strcmp(&de->d_name[sizeof(csum_t)*2+1],
path);
#endif
//#warning FIXME - need to check if cache file is valid - look up using name, check csum
}
} while (0);

View File

@ -36,7 +36,7 @@ struct install_ctx {
int script;
struct apk_db_dir_instance *diri;
csum_t data_csum;
struct apk_checksum data_csum;
apk_progress_cb cb;
void *cb_ctx;
@ -69,7 +69,7 @@ static const struct apk_hash_ops pkg_name_hash_ops = {
static apk_blob_t pkg_info_get_key(apk_hash_item item)
{
return APK_BLOB_BUF(((struct apk_package *) item)->csum);
return APK_BLOB_CSUM(((struct apk_package *) item)->csum);
}
static unsigned long csum_hash(apk_blob_t csum)
@ -372,7 +372,7 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *
{
struct apk_package *idb;
idb = apk_hash_get(&db->available.packages, APK_BLOB_BUF(pkg->csum));
idb = apk_hash_get(&db->available.packages, APK_BLOB_CSUM(pkg->csum));
if (idb == NULL) {
idb = pkg;
apk_hash_insert(&db->available.packages, pkg);
@ -473,8 +473,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
apk_error("FDB checksum entry before file entry");
return -1;
}
apk_blob_pull_hexdump(&l, APK_BLOB_BUF(file->csum));
apk_blob_pull_csum(&l, &file->csum);
break;
default:
apk_error("FDB entry '%c' unsupported", field);
@ -518,9 +517,9 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("R:"));
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(file->name, file->namelen));
if (csum_valid(file->csum)) {
if (file->csum.type != APK_CHECKSUM_NONE) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nZ:"));
apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(file->csum));
apk_blob_push_csum(&bbuf, &file->csum);
}
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
@ -538,46 +537,114 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
return 0;
}
struct apk_script_header {
csum_t csum;
unsigned int type;
unsigned int size;
};
static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os)
{
struct apk_package *pkg;
struct apk_script *script;
struct apk_script_header hdr;
struct hlist_node *c2;
struct apk_file_info fi;
char filename[256];
apk_blob_t bfn;
int r, i;
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
hlist_for_each_entry(script, c2, &pkg->scripts, script_list) {
memcpy(hdr.csum, pkg->csum, sizeof(csum_t));
hdr.type = script->type;
hdr.size = script->size;
fi = (struct apk_file_info) {
.name = filename,
.uname = "root",
.gname = "root",
.size = script->size,
.uid = 0,
.gid = 0,
.mode = 0755 | S_IFREG,
.mtime = time(NULL),
};
/* The scripts db expects file names in format:
* pkg-version.<hexdump of package checksum>.action */
bfn = APK_BLOB_BUF(filename);
apk_blob_push_blob(&bfn, APK_BLOB_STR(pkg->name->name));
apk_blob_push_blob(&bfn, APK_BLOB_STR("-"));
apk_blob_push_blob(&bfn, APK_BLOB_STR(pkg->version));
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
apk_blob_push_csum(&bfn, &pkg->csum);
apk_blob_push_blob(&bfn, APK_BLOB_STR("."));
apk_blob_push_blob(&bfn, APK_BLOB_STR(apk_script_types[script->type]));
apk_blob_push_blob(&bfn, APK_BLOB_PTR_LEN("", 1));
if (os->write(os, &hdr, sizeof(hdr)) != sizeof(hdr))
return -1;
if (os->write(os, script->script, script->size) != script->size)
return -1;
r = apk_write_tar_entry(os, &fi, script->script);
if (r < 0)
return r;
}
}
for (i = 0; i < 2; i++) {
r = apk_write_tar_entry(os, NULL, NULL);
if (r < 0)
return r;
}
return 0;
}
static int apk_db_scriptdb_read_v1(struct apk_database *db, struct apk_istream *is)
{
struct apk_package *pkg;
struct {
unsigned char md5sum[16];
unsigned int type;
unsigned int size;
} hdr;
struct apk_checksum csum;
while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) {
memcpy(csum.data, hdr.md5sum, sizeof(hdr.md5sum));
csum.type = APK_CHECKSUM_MD5;
pkg = apk_db_get_pkg(db, &csum);
if (pkg != NULL)
apk_pkg_add_script(pkg, is, hdr.type, hdr.size);
else
apk_istream_skip(is, hdr.size);
}
return 0;
}
static int apk_db_scriptdb_read(struct apk_database *db, struct apk_istream *is)
static int apk_read_script_archive_entry(void *ctx,
const struct apk_file_info *ae,
struct apk_istream *is)
{
struct apk_database *db = (struct apk_database *) ctx;
struct apk_package *pkg;
struct apk_script_header hdr;
char *fncsum, *fnaction;
struct apk_checksum csum;
apk_blob_t blob;
int type;
while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) {
pkg = apk_db_get_pkg(db, hdr.csum);
if (pkg != NULL)
apk_pkg_add_script(pkg, is, hdr.type, hdr.size);
}
if (!S_ISREG(ae->mode))
return 0;
/* The scripts db expects file names in format:
* pkgname-version.<hexdump of package checksum>.action */
fnaction = memrchr(ae->name, '.', strlen(ae->name));
if (fnaction == NULL || fnaction == ae->name)
return 0;
fncsum = memrchr(ae->name, '.', fnaction - ae->name - 1);
if (fncsum == NULL)
return 0;
fnaction++;
fncsum++;
/* Parse it */
type = apk_script_type(fnaction);
if (type == APK_SCRIPT_INVALID)
return 0;
blob = APK_BLOB_PTR_PTR(fncsum, fnaction - 2);
apk_blob_pull_csum(&blob, &csum);
/* Attach script */
pkg = apk_db_get_pkg(db, &csum);
if (pkg != NULL)
apk_pkg_add_script(pkg, is, type, ae->size);
return 0;
}
@ -619,11 +686,16 @@ static int apk_db_read_state(struct apk_database *db, int flags)
}
if (!(flags & APK_OPENF_NO_SCRIPTS)) {
is = apk_istream_from_file("var/lib/apk/scripts");
is = apk_istream_from_file("var/lib/apk/scripts.tar");
if (is != NULL) {
apk_db_scriptdb_read(db, is);
is->close(is);
apk_parse_tar(is, apk_read_script_archive_entry, db);
} else {
is = apk_istream_from_file("var/lib/apk/scripts");
if (is != NULL)
apk_db_scriptdb_read_v1(db, is);
}
if (is != NULL)
is->close(is);
}
return 0;
@ -817,11 +889,15 @@ int apk_db_write_config(struct apk_database *db)
if (rename("var/lib/apk/installed.new", "var/lib/apk/installed") < 0)
return -errno;
os = apk_ostream_to_file("var/lib/apk/scripts", 0644);
os = apk_ostream_to_file("var/lib/apk/scripts.tar.new", 0644);
if (os == NULL)
return -1;
apk_db_scriptdb_write(db, os);
os->close(os);
if (rename("var/lib/apk/scripts.tar.new", "var/lib/apk/scripts.tar") < 0)
return -errno;
unlink("var/lib/apk/scripts");
return 0;
}
@ -868,10 +944,10 @@ int apk_db_cache_active(struct apk_database *db)
return db->cache_dir != apk_static_cache_dir;
}
struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum)
struct apk_package *apk_db_get_pkg(struct apk_database *db,
struct apk_checksum *csum)
{
return apk_hash_get(&db->available.packages,
APK_BLOB_PTR_LEN((void*) sum, sizeof(csum_t)));
return apk_hash_get(&db->available.packages, APK_BLOB_CSUM(*csum));
}
struct apk_package *apk_db_get_file_owner(struct apk_database *db,
@ -939,22 +1015,24 @@ int apk_db_index_write(struct apk_database *db, struct apk_ostream *os)
}
static void apk_db_cache_get_name(char *buf, size_t bufsz,
struct apk_database *db, csum_t csum,
struct apk_database *db,
struct apk_checksum *csum,
const char *file, int temp)
{
char csumstr[sizeof(csum_t)*2+1];
char csumstr[APK_CACHE_CSUM_BYTES*2+1];
apk_blob_t bbuf = APK_BLOB_BUF(csumstr);
apk_blob_push_hexdump(&bbuf,
APK_BLOB_PTR_LEN((void *)csum, sizeof(csum_t)));
apk_blob_push_blob(&bbuf, APK_BLOB_STR(""));
APK_BLOB_PTR_LEN((char *) csum->data, APK_CACHE_CSUM_BYTES));
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN("", 1));
snprintf(buf, bufsz, "%s/%s/%s.%s%s",
db->root, db->cache_dir, csumstr, file, temp ? ".new" : "");
}
static struct apk_bstream *apk_db_cache_open(struct apk_database *db,
csum_t csum, const char *file)
struct apk_checksum *csum,
const char *file)
{
char tmp[256];
@ -975,7 +1053,7 @@ static struct apk_bstream *apk_repository_file_open(struct apk_repository *repo,
return apk_bstream_from_url(tmp);
}
int apk_cache_download(struct apk_database *db, csum_t csum,
int apk_cache_download(struct apk_database *db, struct apk_checksum *csum,
const char *url, const char *item)
{
char tmp[256], tmp2[256];
@ -999,7 +1077,8 @@ int apk_cache_download(struct apk_database *db, csum_t csum,
return 0;
}
int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item)
int apk_cache_exists(struct apk_database *db, struct apk_checksum *csum,
const char *item)
{
char tmp[256];
@ -1012,10 +1091,10 @@ int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item)
int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
{
if (!csum_valid(repo->url_csum))
if (repo->csum.type == APK_CHECKSUM_NONE)
return 0;
return apk_cache_download(db, repo->url_csum, repo->url, apk_index_gz);
return apk_cache_download(db, &repo->csum, repo->url, apk_index_gz);
}
int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
@ -1040,19 +1119,18 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
};
if (apk_url_local_file(repo->url) == NULL) {
csum_blob(repository, repo->url_csum);
apk_blob_checksum(repository, apk_default_checksum(), &repo->csum);
if (apk_flags & APK_UPDATE_CACHE)
n = apk_repository_update(db, repo);
bs = apk_db_cache_open(db, repo->url_csum, apk_index_gz);
bs = apk_db_cache_open(db, &repo->csum, apk_index_gz);
if (bs == NULL) {
if (n == 1)
n = apk_repository_update(db, repo);
if (n < 0)
return n;
bs = apk_db_cache_open(db, repo->url_csum,
apk_index_gz);
bs = apk_db_cache_open(db, &repo->csum, apk_index_gz);
}
} else {
bs = apk_repository_file_open(repo, apk_index_gz);
@ -1203,9 +1281,8 @@ static int apk_db_install_archive_entry(void *_ctx,
printf("%s\n", ae->name);
if ((diri->dir->flags & APK_DBDIRF_PROTECTED) &&
apk_file_get_info(ae->name, &fi) == 0 &&
(memcmp(file->csum, fi.csum, sizeof(csum_t)) != 0 ||
!csum_valid(file->csum))) {
apk_file_get_info(ae->name, file->csum.type, &fi) == 0 &&
apk_checksum_compare(&file->csum, &fi.csum) != 0) {
/* Protected file. Extract to separate place */
if (!(apk_flags & APK_CLEAN_PROTECTED)) {
snprintf(alt_name, sizeof(alt_name),
@ -1213,15 +1290,18 @@ static int apk_db_install_archive_entry(void *_ctx,
diri->dir->name, file->name);
r = apk_archive_entry_extract(ae, is, alt_name,
extract_cb, ctx);
/* remove identical apk-new */
if (memcmp(ae->csum, fi.csum, sizeof(csum_t)) == 0)
if (ae->csum.type != fi.csum.type)
apk_file_get_info(ae->name, ae->csum.type, &fi);
if (apk_checksum_compare(&ae->csum, &fi.csum) == 0)
unlink(alt_name);
}
} else {
r = apk_archive_entry_extract(ae, is, NULL,
extract_cb, ctx);
}
memcpy(file->csum, ae->csum, sizeof(csum_t));
memcpy(&file->csum, &ae->csum, sizeof(file->csum));
} else {
if (apk_verbosity > 1)
printf("%s\n", ae->name);
@ -1286,7 +1366,8 @@ static int apk_db_gzip_part(void *pctx, EVP_MD_CTX *mdctx, int part)
EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
break;
case APK_MPART_END:
EVP_DigestFinal_ex(mdctx, ctx->data_csum, NULL);
ctx->data_csum.type = EVP_MD_CTX_size(mdctx);
EVP_DigestFinal_ex(mdctx, ctx->data_csum.data, NULL);
break;
}
return 0;
@ -1320,14 +1401,15 @@ static int apk_db_unpack_pkg(struct apk_database *db,
}
repo = &db->repos[i];
if (apk_db_cache_active(db) && csum_valid(repo->url_csum))
bs = apk_db_cache_open(db, newpkg->csum, pkgname);
if (apk_db_cache_active(db) &&
repo->csum.type != APK_CHECKSUM_NONE)
bs = apk_db_cache_open(db, &newpkg->csum, pkgname);
if (bs == NULL) {
snprintf(file, sizeof(file), "%s/%s",
repo->url, pkgname);
bs = apk_bstream_from_url(file);
if (csum_valid(repo->url_csum))
if (repo->csum.type != APK_CHECKSUM_NONE)
need_copy = TRUE;
}
} else {
@ -1337,7 +1419,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
if (!apk_db_cache_active(db))
need_copy = FALSE;
if (need_copy) {
apk_db_cache_get_name(file, sizeof(file), db, newpkg->csum,
apk_db_cache_get_name(file, sizeof(file), db, &newpkg->csum,
pkgname, TRUE);
bs = apk_bstream_tee(bs, file);
}
@ -1362,7 +1444,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
bs->close(bs, &length);
/* Check the package checksum */
if (memcmp(ctx.data_csum, newpkg->csum, sizeof(csum_t)) != 0)
if (apk_checksum_compare(&ctx.data_csum, &newpkg->csum) != 0)
apk_warning("%s-%s: checksum does not match",
newpkg->name->name, newpkg->version);
@ -1370,7 +1452,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
if (length == newpkg->size) {
char file2[256];
apk_db_cache_get_name(file2, sizeof(file2), db,
newpkg->csum, pkgname, FALSE);
&newpkg->csum, pkgname, FALSE);
rename(file, file2);
} else {
unlink(file);

View File

@ -440,11 +440,10 @@ err_fd:
return APK_BLOB_NULL;
}
int apk_file_get_info(const char *filename, struct apk_file_info *fi)
int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *fi)
{
struct stat st;
struct apk_bstream *bs;
csum_ctx_t ctx;
if (stat(filename, &st) != 0)
return -1;
@ -458,14 +457,19 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi)
.device = st.st_dev,
};
if (checksum == APK_CHECKSUM_NONE)
return 0;
bs = apk_bstream_from_file(filename);
if (bs != NULL) {
EVP_MD_CTX mdctx;
apk_blob_t blob;
csum_init(&ctx);
EVP_DigestInit(&mdctx, apk_get_digest(checksum));
while (!APK_BLOB_IS_NULL(blob = bs->read(bs, APK_BLOB_NULL)))
csum_process(&ctx, (void*) blob.ptr, blob.len);
csum_finish(&ctx, fi->csum);
EVP_DigestUpdate(&mdctx, (void*) blob.ptr, blob.len);
fi->csum.type = EVP_MD_CTX_size(&mdctx);
EVP_DigestFinal(&mdctx, fi->csum.data, NULL);
bs->close(bs, NULL);
}

View File

@ -230,7 +230,7 @@ int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os)
return n;
}
static const char *script_types[] = {
const char *apk_script_types[] = {
[APK_SCRIPT_PRE_INSTALL] = "pre-install",
[APK_SCRIPT_POST_INSTALL] = "post-install",
[APK_SCRIPT_PRE_DEINSTALL] = "pre-deinstall",
@ -252,9 +252,9 @@ int apk_script_type(const char *name)
{
int i;
for (i = 0; i < ARRAY_SIZE(script_types); i++)
if (script_types[i] &&
strcmp(script_types[i], name) == 0)
for (i = 0; i < ARRAY_SIZE(apk_script_types); i++)
if (apk_script_types[i] &&
strcmp(apk_script_types[i], name) == 0)
return i;
return APK_SCRIPT_INVALID;
@ -290,7 +290,7 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
apk_deps_parse(db, &pkg->depends, value);
break;
case 'C':
apk_blob_pull_hexdump(&value, APK_BLOB_BUF(pkg->csum));
apk_blob_pull_csum(&value, &pkg->csum);
break;
case 'S':
pkg->size = apk_blob_pull_uint(&value, 10);
@ -426,7 +426,8 @@ static int apk_pkg_gzip_part(void *ctx, EVP_MD_CTX *mdctx, int part)
EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
break;
case APK_MPART_END:
EVP_DigestFinal_ex(mdctx, ri->pkg->csum, NULL);
ri->pkg->csum.type = EVP_MD_CTX_size(mdctx);
EVP_DigestFinal_ex(mdctx, ri->pkg->csum.data, NULL);
break;
}
return 0;
@ -572,7 +573,7 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd,
snprintf(fn, sizeof(fn),
"tmp/%s-%s.%s",
pkg->name->name, pkg->version,
script_types[type]);
apk_script_types[type]);
fd = creat(fn, 0777);
if (fd < 0)
return fd;
@ -591,7 +592,7 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd,
execle(fn, "INSTALL", script_types2[type],
pkg->version, "", NULL, environment);
} else {
execle(fn, script_types[type],
execle(fn, apk_script_types[type],
pkg->version, "", NULL, environment);
}
exit(1);
@ -649,7 +650,7 @@ int apk_pkg_write_index_entry(struct apk_package *info,
int r;
apk_blob_push_blob(&bbuf, APK_BLOB_STR("C:"));
apk_blob_push_hexdump(&bbuf, APK_BLOB_BUF(info->csum));
apk_blob_push_csum(&bbuf, &info->csum);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nP:"));
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->name->name));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nV:"));