io: convert bstream mmap to istream, remove the now obsolete bstream machinery

cute-signatures
Timo Teräs 2020-01-11 09:38:06 +02:00
parent 7caa217731
commit 1de9ef422c
2 changed files with 65 additions and 244 deletions

View File

@ -56,7 +56,6 @@ struct apk_file_info {
extern size_t apk_io_bufsize; extern size_t apk_io_bufsize;
struct apk_istream; struct apk_istream;
struct apk_bstream;
struct apk_ostream; struct apk_ostream;
struct apk_istream_ops { struct apk_istream_ops {
@ -133,20 +132,6 @@ struct apk_istream *apk_istream_segment(struct apk_segment_istream *sis, struct
struct apk_istream *apk_istream_tee(struct apk_istream *from, int atfd, const char *to, int copy_meta, struct apk_istream *apk_istream_tee(struct apk_istream *from, int atfd, const char *to, int copy_meta,
apk_progress_cb cb, void *cb_ctx); apk_progress_cb cb, void *cb_ctx);
#define APK_BSTREAM_SINGLE_READ 0x0001
#define APK_BSTREAM_EOF 0x0002
struct apk_bstream_ops {
void (*get_meta)(struct apk_bstream *bs, struct apk_file_meta *meta);
apk_blob_t (*read)(struct apk_bstream *bs, apk_blob_t token);
void (*close)(struct apk_bstream *bs);
};
struct apk_bstream {
unsigned int flags;
const struct apk_bstream_ops *ops;
};
struct apk_ostream_ops { struct apk_ostream_ops {
ssize_t (*write)(struct apk_ostream *os, const void *buf, size_t size); ssize_t (*write)(struct apk_ostream *os, const void *buf, size_t size);
int (*close)(struct apk_ostream *os); int (*close)(struct apk_ostream *os);
@ -158,38 +143,6 @@ struct apk_ostream {
struct apk_ostream *apk_ostream_gzip(struct apk_ostream *); struct apk_ostream *apk_ostream_gzip(struct apk_ostream *);
struct apk_ostream *apk_ostream_counter(off_t *); struct apk_ostream *apk_ostream_counter(off_t *);
struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream);
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file);
struct apk_bstream *apk_bstream_from_fd(int fd);
struct apk_bstream *apk_bstream_from_fd_url_if_modified(int atfd, const char *url, time_t since);
static inline struct apk_bstream *apk_bstream_from_url(const char *url)
{
return apk_bstream_from_fd_url_if_modified(AT_FDCWD, url, 0);
}
static inline struct apk_bstream *apk_bstream_from_fd_url(int fd, const char *url)
{
return apk_bstream_from_fd_url_if_modified(fd, url, 0);
}
static inline struct apk_bstream *apk_bstream_from_url_if_modified(const char *url, time_t since)
{
return apk_bstream_from_fd_url_if_modified(AT_FDCWD, url, since);
}
static inline void apk_bstream_get_meta(struct apk_bstream *bs, struct apk_file_meta *meta)
{
bs->ops->get_meta(bs, meta);
}
static inline apk_blob_t apk_bstream_read(struct apk_bstream *bs, apk_blob_t token)
{
return bs->ops->read(bs, token);
}
static inline void apk_bstream_close(struct apk_bstream *bs)
{
bs->ops->close(bs);
}
struct apk_ostream *apk_ostream_to_fd(int fd); struct apk_ostream *apk_ostream_to_fd(int fd);
struct apk_ostream *apk_ostream_to_file(int atfd, const char *file, const char *tmpfile, mode_t mode); struct apk_ostream *apk_ostream_to_file(int atfd, const char *file, const char *tmpfile, mode_t mode);
struct apk_ostream *apk_ostream_to_file_gz(int atfd, const char *file, const char *tmpfile, mode_t mode); struct apk_ostream *apk_ostream_to_file_gz(int atfd, const char *file, const char *tmpfile, mode_t mode);

262
src/io.c
View File

@ -355,6 +355,67 @@ err_is:
return ERR_PTR(r); return ERR_PTR(r);
} }
struct apk_mmap_istream {
struct apk_istream is;
int fd;
};
static void mmap_get_meta(struct apk_istream *is, struct apk_file_meta *meta)
{
struct apk_mmap_istream *mis = container_of(is, struct apk_mmap_istream, is);
return apk_file_meta_from_fd(mis->fd, meta);
}
static ssize_t mmap_read(struct apk_istream *is, void *ptr, size_t size)
{
return 0;
}
static void mmap_close(struct apk_istream *is)
{
struct apk_mmap_istream *mis = container_of(is, struct apk_mmap_istream, is);
munmap(mis->is.buf, mis->is.buf_size);
close(mis->fd);
free(mis);
}
static const struct apk_istream_ops mmap_istream_ops = {
.get_meta = mmap_get_meta,
.read = mmap_read,
.close = mmap_close,
};
static inline struct apk_istream *apk_mmap_istream_from_fd(int fd)
{
struct apk_mmap_istream *mis;
struct stat st;
void *ptr;
if (fstat(fd, &st) < 0) return ERR_PTR(-errno);
ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) return ERR_PTR(-errno);
mis = malloc(sizeof *mis);
if (mis == NULL) {
munmap(ptr, st.st_size);
return ERR_PTR(-ENOMEM);
}
*mis = (struct apk_mmap_istream) {
.is.flags = APK_ISTREAM_SINGLE_READ,
.is.err = 1,
.is.ops = &mmap_istream_ops,
.is.buf = ptr,
.is.buf_size = st.st_size,
.is.ptr = ptr,
.is.end = ptr + st.st_size,
.fd = fd,
};
return &mis->is;
}
struct apk_fd_istream { struct apk_fd_istream {
struct apk_istream is; struct apk_istream is;
int fd; int fd;
@ -419,6 +480,10 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file)
fd = openat(atfd, file, O_RDONLY | O_CLOEXEC); fd = openat(atfd, file, O_RDONLY | O_CLOEXEC);
if (fd < 0) return ERR_PTR(-errno); if (fd < 0) return ERR_PTR(-errno);
if (0) {
struct apk_istream *is = apk_mmap_istream_from_fd(fd);
if (!IS_ERR_OR_NULL(is)) return is;
}
return apk_istream_from_fd(fd); return apk_istream_from_fd(fd);
} }
@ -482,203 +547,6 @@ err:
return r; return r;
} }
struct apk_istream_bstream {
struct apk_bstream bs;
struct apk_istream *is;
apk_blob_t left;
char buffer[8*1024];
};
static void is_bs_get_meta(struct apk_bstream *bs, struct apk_file_meta *meta)
{
struct apk_istream_bstream *isbs = container_of(bs, struct apk_istream_bstream, bs);
return apk_istream_get_meta(isbs->is, meta);
}
static apk_blob_t is_bs_read(struct apk_bstream *bs, apk_blob_t token)
{
struct apk_istream_bstream *isbs = container_of(bs, struct apk_istream_bstream, bs);
ssize_t size;
apk_blob_t ret;
/* If we have cached stuff, first check if it full fills the request */
if (isbs->left.len != 0) {
if (!APK_BLOB_IS_NULL(token)) {
/* If we have tokenized thingy left, return it */
if (apk_blob_split(isbs->left, token, &ret, &isbs->left))
goto ret;
} else
goto ret_all;
}
/* If we've exchausted earlier, it's end of stream or error */
if (APK_BLOB_IS_NULL(isbs->left))
return isbs->left;
/* We need more data */
if (isbs->left.len != 0)
memmove(isbs->buffer, isbs->left.ptr, isbs->left.len);
isbs->left.ptr = isbs->buffer;
size = apk_istream_read(isbs->is, isbs->buffer + isbs->left.len,
sizeof(isbs->buffer) - isbs->left.len);
if (size > 0) {
isbs->left.len += size;
} else if (size == 0) {
if (isbs->left.len == 0)
isbs->left = APK_BLOB_NULL;
goto ret_all;
} else {
/* cache and return error */
isbs->left = ret = APK_BLOB_ERROR(size);
goto ret;
}
if (!APK_BLOB_IS_NULL(token)) {
/* If we have tokenized thingy left, return it */
if (apk_blob_split(isbs->left, token, &ret, &isbs->left))
goto ret;
/* No token found; just return the full buffer */
}
ret_all:
/* Return all that is in cache */
ret = isbs->left;
isbs->left.len = 0;
ret:
return ret;
}
static void is_bs_close(struct apk_bstream *bs)
{
struct apk_istream_bstream *isbs = container_of(bs, struct apk_istream_bstream, bs);
apk_istream_close(isbs->is);
free(isbs);
}
static const struct apk_bstream_ops is_bstream_ops = {
.get_meta = is_bs_get_meta,
.read = is_bs_read,
.close = is_bs_close,
};
struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream)
{
struct apk_istream_bstream *isbs;
if (IS_ERR_OR_NULL(istream)) return ERR_CAST(istream);
isbs = malloc(sizeof(struct apk_istream_bstream));
if (isbs == NULL) return ERR_PTR(-ENOMEM);
isbs->bs = (struct apk_bstream) {
.ops = &is_bstream_ops,
};
isbs->is = istream;
isbs->left = APK_BLOB_PTR_LEN(isbs->buffer, 0);
return &isbs->bs;
}
struct apk_mmap_bstream {
struct apk_bstream bs;
int fd;
size_t size;
unsigned char *ptr;
apk_blob_t left;
};
static void mmap_get_meta(struct apk_bstream *bs, struct apk_file_meta *meta)
{
struct apk_mmap_bstream *mbs = container_of(bs, struct apk_mmap_bstream, bs);
return apk_file_meta_from_fd(mbs->fd, meta);
}
static apk_blob_t mmap_read(struct apk_bstream *bs, apk_blob_t token)
{
struct apk_mmap_bstream *mbs = container_of(bs, struct apk_mmap_bstream, bs);
apk_blob_t ret;
if (!APK_BLOB_IS_NULL(token) && !APK_BLOB_IS_NULL(mbs->left)) {
if (apk_blob_split(mbs->left, token, &ret, &mbs->left))
return ret;
}
ret = mbs->left;
mbs->left = APK_BLOB_NULL;
mbs->bs.flags |= APK_BSTREAM_EOF;
return ret;
}
static void mmap_close(struct apk_bstream *bs)
{
struct apk_mmap_bstream *mbs = container_of(bs, struct apk_mmap_bstream, bs);
munmap(mbs->ptr, mbs->size);
close(mbs->fd);
free(mbs);
}
static const struct apk_bstream_ops mmap_bstream_ops = {
.get_meta = mmap_get_meta,
.read = mmap_read,
.close = mmap_close,
};
static struct apk_bstream *apk_mmap_bstream_from_fd(int fd)
{
struct apk_mmap_bstream *mbs;
struct stat st;
void *ptr;
if (fstat(fd, &st) < 0) return ERR_PTR(-errno);
ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) return ERR_PTR(-errno);
mbs = malloc(sizeof(struct apk_mmap_bstream));
if (mbs == NULL) {
munmap(ptr, st.st_size);
return ERR_PTR(-ENOMEM);
}
*mbs = (struct apk_mmap_bstream) {
.bs.flags = APK_BSTREAM_SINGLE_READ,
.bs.ops = &mmap_bstream_ops,
.fd = fd,
.size = st.st_size,
.ptr = ptr,
.left = APK_BLOB_PTR_LEN(ptr, st.st_size),
};
return &mbs->bs;
}
struct apk_bstream *apk_bstream_from_fd(int fd)
{
struct apk_bstream *bs;
if (fd < 0) return ERR_PTR(-EBADF);
bs = apk_mmap_bstream_from_fd(fd);
if (!IS_ERR_OR_NULL(bs))
return bs;
return apk_bstream_from_istream(apk_istream_from_fd(fd));
}
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file)
{
int fd;
fd = openat(atfd, file, O_RDONLY | O_CLOEXEC);
if (fd < 0) return ERR_PTR(-errno);
return apk_bstream_from_fd(fd);
}
apk_blob_t apk_blob_from_istream(struct apk_istream *is, size_t size) apk_blob_t apk_blob_from_istream(struct apk_istream *is, size_t size)
{ {
void *ptr; void *ptr;