io: apk_ostream stuff
parent
4bafa681fe
commit
dc2ffc30e8
|
@ -96,7 +96,7 @@ void apk_db_close(struct apk_database *db);
|
|||
struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file);
|
||||
struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum);
|
||||
|
||||
void apk_db_index_write(struct apk_database *db, int fd);
|
||||
void 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_db_recalculate_and_commit(struct apk_database *db);
|
||||
|
|
15
src/apk_io.h
15
src/apk_io.h
|
@ -35,13 +35,20 @@ struct apk_istream {
|
|||
|
||||
struct apk_bstream {
|
||||
size_t (*read)(void *stream, void **ptr);
|
||||
void (*close)(void *stream, csum_p csum);
|
||||
void (*close)(void *stream, csum_p csum, size_t *size);
|
||||
};
|
||||
|
||||
struct apk_istream *apk_gunzip_bstream(struct apk_bstream *);
|
||||
struct apk_ostream {
|
||||
size_t (*write)(void *stream, const void *buf, size_t size);
|
||||
void (*close)(void *stream);
|
||||
};
|
||||
|
||||
struct apk_istream *apk_bstream_gunzip(struct apk_bstream *);
|
||||
struct apk_ostream *apk_ostream_gzip(struct apk_ostream *);
|
||||
|
||||
struct apk_istream *apk_istream_from_fd(int fd);
|
||||
struct apk_istream *apk_istream_from_file(const char *file);
|
||||
struct apk_istream *apk_istream_from_file_gz(const char *file);
|
||||
struct apk_istream *apk_istream_from_url(const char *url);
|
||||
size_t apk_istream_skip(struct apk_istream *istream, size_t size);
|
||||
size_t apk_istream_splice(void *stream, int fd, size_t size);
|
||||
|
@ -51,7 +58,9 @@ struct apk_bstream *apk_bstream_from_fd(int fd);
|
|||
struct apk_bstream *apk_bstream_from_file(const char *file);
|
||||
struct apk_bstream *apk_bstream_from_url(const char *url);
|
||||
|
||||
struct apk_istream *apk_istream_from_file_gz(const char *file);
|
||||
struct apk_ostream *apk_ostream_to_fd(int fd);
|
||||
struct apk_ostream *apk_ostream_to_file(const char *file, mode_t mode);
|
||||
struct apk_ostream *apk_ostream_to_file_gz(const char *file, mode_t mode);
|
||||
|
||||
apk_blob_t apk_blob_from_istream(struct apk_istream *istream, size_t size);
|
||||
apk_blob_t apk_blob_from_file(const char *file);
|
||||
|
|
|
@ -54,7 +54,7 @@ struct apk_package {
|
|||
char *version;
|
||||
char *url, *description, *license;
|
||||
struct apk_dependency_array *depends;
|
||||
unsigned int installed_size, size;
|
||||
size_t installed_size, size;
|
||||
char *filename;
|
||||
|
||||
/* for installed packages only */
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
#include "apk_defines.h"
|
||||
#include "apk_archive.h"
|
||||
|
||||
#ifndef GUNZIP_BINARY
|
||||
#define GUNZIP_BINARY "/bin/gunzip"
|
||||
#endif
|
||||
|
||||
struct tar_header {
|
||||
/* ustar header, Posix 1003.1 */
|
||||
char name[100]; /* 0-99 */
|
||||
|
@ -182,7 +178,7 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser,
|
|||
int apk_parse_tar_gz(struct apk_bstream *bs, apk_archive_entry_parser parser,
|
||||
void *ctx)
|
||||
{
|
||||
return apk_parse_tar(apk_gunzip_bstream(bs), parser, ctx);
|
||||
return apk_parse_tar(apk_bstream_gunzip(bs), parser, ctx);
|
||||
}
|
||||
|
||||
int apk_archive_entry_extract(const struct apk_file_info *ae,
|
||||
|
|
|
@ -369,7 +369,7 @@ static int apk_db_index_read(struct apk_database *db, struct apk_istream *is, in
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int apk_db_write_fdb(struct apk_database *db, int fd)
|
||||
static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
|
||||
{
|
||||
struct apk_package *pkg;
|
||||
struct apk_db_dir *dir;
|
||||
|
@ -382,14 +382,14 @@ static int apk_db_write_fdb(struct apk_database *db, int fd)
|
|||
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
|
||||
blob = apk_pkg_format_index_entry(pkg, sizeof(buf), buf);
|
||||
if (blob.ptr)
|
||||
write(fd, blob.ptr, blob.len - 1);
|
||||
os->write(os, blob.ptr, blob.len - 1);
|
||||
|
||||
n = 0;
|
||||
dir = NULL;
|
||||
hlist_for_each_entry(file, c2, &pkg->owned_files, pkg_files_list) {
|
||||
if (file->owner == NULL)
|
||||
continue;
|
||||
|
||||
n = 0;
|
||||
if (dir != file->dir) {
|
||||
dir = file->dir;
|
||||
n += snprintf(&buf[n], sizeof(buf)-n,
|
||||
|
@ -409,11 +409,10 @@ static int apk_db_write_fdb(struct apk_database *db, int fd)
|
|||
n += snprintf(&buf[n], sizeof(buf)-n, "\n");
|
||||
}
|
||||
|
||||
if (write(fd, buf, n) != n)
|
||||
if (os->write(os, buf, n) != n)
|
||||
return -1;
|
||||
n = 0;
|
||||
}
|
||||
write(fd, "\n", 1);
|
||||
os->write(os, "\n", 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -425,7 +424,7 @@ struct apk_script_header {
|
|||
unsigned int size;
|
||||
};
|
||||
|
||||
static int apk_db_scriptdb_write(struct apk_database *db, int fd)
|
||||
static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os)
|
||||
{
|
||||
struct apk_package *pkg;
|
||||
struct apk_script *script;
|
||||
|
@ -438,8 +437,11 @@ static int apk_db_scriptdb_write(struct apk_database *db, int fd)
|
|||
hdr.type = script->type;
|
||||
hdr.size = script->size;
|
||||
|
||||
write(fd, &hdr, sizeof(hdr));
|
||||
write(fd, script->script, script->size);
|
||||
if (os->write(os, &hdr, sizeof(hdr)) != sizeof(hdr))
|
||||
return -1;
|
||||
|
||||
if (os->write(os, script->script, script->size) != script->size)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,32 +582,33 @@ struct write_ctx {
|
|||
|
||||
static int apk_db_write_config(struct apk_database *db)
|
||||
{
|
||||
struct apk_ostream *os;
|
||||
char buf[1024];
|
||||
int n, fd;
|
||||
int n;
|
||||
|
||||
if (db->root == NULL)
|
||||
return 0;
|
||||
|
||||
fchdir(db->root_fd);
|
||||
|
||||
fd = creat("var/lib/apk/world", 0600);
|
||||
if (fd < 0)
|
||||
os = apk_ostream_to_file("var/lib/apk/world", 0600);
|
||||
if (os == NULL)
|
||||
return -1;
|
||||
n = apk_deps_format(buf, sizeof(buf), db->world);
|
||||
write(fd, buf, n);
|
||||
close(fd);
|
||||
os->write(os, buf, n);
|
||||
os->close(os);
|
||||
|
||||
fd = creat("var/lib/apk/installed", 0600);
|
||||
if (fd < 0)
|
||||
os = apk_ostream_to_file("var/lib/apk/installed", 0600);
|
||||
if (os == NULL)
|
||||
return -1;
|
||||
apk_db_write_fdb(db, fd);
|
||||
close(fd);
|
||||
apk_db_write_fdb(db, os);
|
||||
os->close(os);
|
||||
|
||||
fd = creat("var/lib/apk/scripts", 0600);
|
||||
if (fd < 0)
|
||||
os = apk_ostream_to_file("var/lib/apk/scripts", 0600);
|
||||
if (os == NULL)
|
||||
return -1;
|
||||
apk_db_scriptdb_write(db, fd);
|
||||
close(fd);
|
||||
apk_db_scriptdb_write(db, os);
|
||||
os->close(os);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -639,20 +642,23 @@ struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *fil
|
|||
|
||||
static int write_index_entry(apk_hash_item item, void *ctx)
|
||||
{
|
||||
int fd = (int) ctx;
|
||||
struct apk_ostream *os = (struct apk_ostream *) ctx;
|
||||
char buf[1024];
|
||||
apk_blob_t blob;
|
||||
|
||||
blob = apk_pkg_format_index_entry(item, sizeof(buf), buf);
|
||||
if (blob.ptr)
|
||||
write(fd, blob.ptr, blob.len);
|
||||
if (APK_BLOB_IS_NULL(blob))
|
||||
return 0;
|
||||
|
||||
if (os->write(os, blob.ptr, blob.len) != blob.len)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void apk_db_index_write(struct apk_database *db, int fd)
|
||||
void apk_db_index_write(struct apk_database *db, struct apk_ostream *os)
|
||||
{
|
||||
apk_hash_foreach(&db->available.packages, write_index_entry, (void *) fd);
|
||||
apk_hash_foreach(&db->available.packages, write_index_entry, (void *) os);
|
||||
}
|
||||
|
||||
int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
|
||||
|
@ -884,7 +890,7 @@ int apk_db_install_pkg(struct apk_database *db,
|
|||
if (apk_parse_tar_gz(bs, apk_db_install_archive_entry, &ctx) != 0)
|
||||
goto err_close;
|
||||
|
||||
bs->close(bs, csum);
|
||||
bs->close(bs, csum, NULL);
|
||||
|
||||
apk_pkg_set_state(db, newpkg, APK_STATE_INSTALL);
|
||||
|
||||
|
@ -903,6 +909,6 @@ int apk_db_install_pkg(struct apk_database *db,
|
|||
}
|
||||
return r;
|
||||
err_close:
|
||||
bs->close(bs, NULL);
|
||||
bs->close(bs, NULL, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ static void gz_close(void *stream)
|
|||
free(gis);
|
||||
}
|
||||
|
||||
struct apk_istream *apk_gunzip_bstream(struct apk_bstream *bs)
|
||||
struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs)
|
||||
{
|
||||
struct apk_gzip_istream *gis;
|
||||
|
||||
|
|
|
@ -43,12 +43,17 @@ static int index_main(int argc, char **argv)
|
|||
{
|
||||
struct apk_database db;
|
||||
struct counts counts = {0,0};
|
||||
struct apk_ostream *os;
|
||||
int i;
|
||||
|
||||
apk_db_open(&db, NULL);
|
||||
for (i = 0; i < argc; i++)
|
||||
apk_db_pkg_add_file(&db, argv[i]);
|
||||
apk_db_index_write(&db, STDOUT_FILENO);
|
||||
|
||||
os = apk_ostream_to_fd(STDOUT_FILENO);
|
||||
apk_db_index_write(&db, os);
|
||||
os->close(os);
|
||||
|
||||
apk_hash_foreach(&db.available.names, warn_if_no_providers, &counts);
|
||||
apk_db_close(&db);
|
||||
|
||||
|
|
90
src/io.c
90
src/io.c
|
@ -23,7 +23,7 @@ struct apk_fd_istream {
|
|||
int fd;
|
||||
};
|
||||
|
||||
static size_t fd_read(void *stream, void *ptr, size_t size)
|
||||
static size_t fdi_read(void *stream, void *ptr, size_t size)
|
||||
{
|
||||
struct apk_fd_istream *fis =
|
||||
container_of(stream, struct apk_fd_istream, is);
|
||||
|
@ -47,7 +47,7 @@ static size_t fd_read(void *stream, void *ptr, size_t size)
|
|||
return i;
|
||||
}
|
||||
|
||||
static void fd_close(void *stream)
|
||||
static void fdi_close(void *stream)
|
||||
{
|
||||
struct apk_fd_istream *fis =
|
||||
container_of(stream, struct apk_fd_istream, is);
|
||||
|
@ -68,8 +68,8 @@ struct apk_istream *apk_istream_from_fd(int fd)
|
|||
return NULL;
|
||||
|
||||
*fis = (struct apk_fd_istream) {
|
||||
.is.read = fd_read,
|
||||
.is.close = fd_close,
|
||||
.is.read = fdi_read,
|
||||
.is.close = fdi_close,
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
|
@ -148,6 +148,7 @@ struct apk_istream_bstream {
|
|||
struct apk_istream *is;
|
||||
csum_ctx_t csum_ctx;
|
||||
unsigned char buffer[8*1024];
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static size_t is_bs_read(void *stream, void **ptr)
|
||||
|
@ -161,12 +162,13 @@ static size_t is_bs_read(void *stream, void **ptr)
|
|||
return size;
|
||||
|
||||
csum_process(&isbs->csum_ctx, isbs->buffer, size);
|
||||
isbs->size += size;
|
||||
|
||||
*ptr = isbs->buffer;
|
||||
return size;
|
||||
}
|
||||
|
||||
static void is_bs_close(void *stream, csum_t csum)
|
||||
static void is_bs_close(void *stream, csum_t csum, size_t *size)
|
||||
{
|
||||
struct apk_istream_bstream *isbs =
|
||||
container_of(stream, struct apk_istream_bstream, bs);
|
||||
|
@ -178,11 +180,15 @@ static void is_bs_close(void *stream, csum_t csum)
|
|||
size = isbs->is->read(isbs->is, isbs->buffer,
|
||||
sizeof(isbs->buffer));
|
||||
csum_process(&isbs->csum_ctx, isbs->buffer, size);
|
||||
isbs->size += size;
|
||||
} while (size == sizeof(isbs->buffer));
|
||||
|
||||
csum_finish(&isbs->csum_ctx, csum);
|
||||
}
|
||||
|
||||
if (size != NULL)
|
||||
*size = isbs->size;
|
||||
|
||||
isbs->is->close(isbs->is);
|
||||
free(isbs);
|
||||
}
|
||||
|
@ -231,7 +237,7 @@ static size_t mmap_read(void *stream, void **ptr)
|
|||
return size;
|
||||
}
|
||||
|
||||
static void mmap_close(void *stream, csum_t csum)
|
||||
static void mmap_close(void *stream, csum_t csum, size_t *size)
|
||||
{
|
||||
struct apk_mmap_bstream *mbs =
|
||||
container_of(stream, struct apk_mmap_bstream, bs);
|
||||
|
@ -243,6 +249,9 @@ static void mmap_close(void *stream, csum_t csum)
|
|||
csum_finish(&mbs->csum_ctx, csum);
|
||||
}
|
||||
|
||||
if (size != NULL)
|
||||
*size = mbs->size;
|
||||
|
||||
munmap(mbs->ptr, mbs->size);
|
||||
free(mbs);
|
||||
}
|
||||
|
@ -373,13 +382,78 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi)
|
|||
|
||||
bs = apk_bstream_from_file(filename);
|
||||
if (bs != NULL)
|
||||
bs->close(bs, fi->csum);
|
||||
bs->close(bs, fi->csum, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct apk_istream *apk_istream_from_file_gz(const char *file)
|
||||
{
|
||||
return apk_gunzip_bstream(apk_bstream_from_file(file));
|
||||
return apk_bstream_gunzip(apk_bstream_from_file(file));
|
||||
}
|
||||
|
||||
struct apk_fd_ostream {
|
||||
struct apk_ostream os;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static size_t fdo_write(void *stream, const void *ptr, size_t size)
|
||||
{
|
||||
struct apk_fd_ostream *fos =
|
||||
container_of(stream, struct apk_fd_ostream, os);
|
||||
size_t i = 0, r;
|
||||
|
||||
while (i < size) {
|
||||
r = write(fos->fd, ptr + i, size - i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return i;
|
||||
i += r;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void fdo_close(void *stream)
|
||||
{
|
||||
struct apk_fd_ostream *fos =
|
||||
container_of(stream, struct apk_fd_ostream, os);
|
||||
|
||||
close(fos->fd);
|
||||
free(fos);
|
||||
}
|
||||
|
||||
struct apk_ostream *apk_ostream_to_fd(int fd)
|
||||
{
|
||||
struct apk_fd_ostream *fos;
|
||||
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
fos = malloc(sizeof(struct apk_fd_ostream));
|
||||
if (fos == NULL)
|
||||
return NULL;
|
||||
|
||||
*fos = (struct apk_fd_ostream) {
|
||||
.os.write = fdo_write,
|
||||
.os.close = fdo_close,
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return &fos->os;
|
||||
}
|
||||
|
||||
struct apk_ostream *apk_ostream_to_file(const char *file, mode_t mode)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = creat(file, mode);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
return apk_ostream_to_fd(fd);
|
||||
}
|
||||
|
||||
|
|
|
@ -331,35 +331,23 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file)
|
|||
{
|
||||
struct read_info_ctx ctx;
|
||||
struct apk_bstream *bs;
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
ctx.pkg = apk_pkg_new();
|
||||
if (ctx.pkg == NULL)
|
||||
return NULL;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0)
|
||||
bs = apk_bstream_from_file(file);
|
||||
if (bs == NULL)
|
||||
goto err;
|
||||
|
||||
fstat(fd, &st);
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
bs = apk_bstream_from_fd(fd);
|
||||
if (bs == NULL) {
|
||||
close(fd);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx.db = db;
|
||||
ctx.pkg->size = st.st_size;
|
||||
ctx.has_install = 0;
|
||||
if (apk_parse_tar_gz(bs, read_info_entry, &ctx) < 0) {
|
||||
apk_error("File %s is not an APK archive", file);
|
||||
bs->close(bs, NULL);
|
||||
bs->close(bs, NULL, NULL);
|
||||
goto err;
|
||||
}
|
||||
bs->close(bs, ctx.pkg->csum);
|
||||
bs->close(bs, ctx.pkg->csum, &ctx.pkg->size);
|
||||
|
||||
if (ctx.pkg->name == NULL) {
|
||||
apk_error("File %s is corrupted", file);
|
||||
|
|
Loading…
Reference in New Issue