io: convert bstream mmap to istream, remove the now obsolete bstream machinery
parent
7caa217731
commit
1de9ef422c
47
src/apk_io.h
47
src/apk_io.h
|
@ -56,7 +56,6 @@ struct apk_file_info {
|
|||
extern size_t apk_io_bufsize;
|
||||
|
||||
struct apk_istream;
|
||||
struct apk_bstream;
|
||||
struct apk_ostream;
|
||||
|
||||
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,
|
||||
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 {
|
||||
ssize_t (*write)(struct apk_ostream *os, const void *buf, size_t size);
|
||||
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_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_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);
|
||||
|
|
262
src/io.c
262
src/io.c
|
@ -355,6 +355,67 @@ err_is:
|
|||
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_istream is;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -482,203 +547,6 @@ err:
|
|||
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)
|
||||
{
|
||||
void *ptr;
|
||||
|
|
Loading…
Reference in New Issue