io: enhance istream/bstreams with pipe to forked child
* prunes the child pid to avoid zombies * handles the errors so e.g. file-not-found is reported properlycute-signatures
parent
c9690b0e7c
commit
d92df52079
|
@ -18,7 +18,7 @@
|
||||||
#include "apk_defines.h"
|
#include "apk_defines.h"
|
||||||
|
|
||||||
struct apk_blob {
|
struct apk_blob {
|
||||||
unsigned int len;
|
long len;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
};
|
};
|
||||||
typedef struct apk_blob apk_blob_t;
|
typedef struct apk_blob apk_blob_t;
|
||||||
|
@ -56,6 +56,7 @@ static inline const EVP_MD *apk_checksum_default(void)
|
||||||
#define APK_BLOB_IS_NULL(blob) ((blob).ptr == NULL)
|
#define APK_BLOB_IS_NULL(blob) ((blob).ptr == NULL)
|
||||||
|
|
||||||
#define APK_BLOB_NULL ((apk_blob_t){0, NULL})
|
#define APK_BLOB_NULL ((apk_blob_t){0, NULL})
|
||||||
|
#define APK_BLOB_ERROR(err) ((apk_blob_t){err, NULL})
|
||||||
#define APK_BLOB_BUF(buf) ((apk_blob_t){sizeof(buf), (char *)(buf)})
|
#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_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_STRUCT(s) ((apk_blob_t){sizeof(s), (char*)&(s)})
|
||||||
|
|
14
src/apk_io.h
14
src/apk_io.h
|
@ -73,7 +73,7 @@ static inline struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs)
|
||||||
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_istream *apk_istream_from_fd(int fd);
|
struct apk_istream *apk_istream_from_fd_pid(int fd, pid_t pid, int (*translate_status)(int));
|
||||||
struct apk_istream *apk_istream_from_file(int atfd, const char *file);
|
struct apk_istream *apk_istream_from_file(int atfd, const char *file);
|
||||||
struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file);
|
struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file);
|
||||||
struct apk_istream *apk_istream_from_url(const char *url);
|
struct apk_istream *apk_istream_from_url(const char *url);
|
||||||
|
@ -82,12 +82,22 @@ size_t apk_istream_skip(struct apk_istream *istream, size_t size);
|
||||||
size_t apk_istream_splice(void *stream, int fd, size_t size,
|
size_t apk_istream_splice(void *stream, int fd, size_t size,
|
||||||
apk_progress_cb cb, void *cb_ctx);
|
apk_progress_cb cb, void *cb_ctx);
|
||||||
|
|
||||||
|
static inline struct apk_istream *apk_istream_from_fd(int fd)
|
||||||
|
{
|
||||||
|
return apk_istream_from_fd_pid(fd, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream);
|
struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream);
|
||||||
struct apk_bstream *apk_bstream_from_fd(int fd);
|
struct apk_bstream *apk_bstream_from_fd_pid(int fd, pid_t pid, int (*translate_status)(int));
|
||||||
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file);
|
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file);
|
||||||
struct apk_bstream *apk_bstream_from_url(const char *url);
|
struct apk_bstream *apk_bstream_from_url(const char *url);
|
||||||
struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const char *to);
|
struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const char *to);
|
||||||
|
|
||||||
|
static inline struct apk_bstream *apk_bstream_from_fd(int fd)
|
||||||
|
{
|
||||||
|
return apk_bstream_from_fd_pid(fd, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -61,8 +61,8 @@ static ssize_t gzi_read(void *stream, void *ptr, size_t size)
|
||||||
gis->cbprev = blob.ptr;
|
gis->cbprev = blob.ptr;
|
||||||
gis->zs.avail_in = blob.len;
|
gis->zs.avail_in = blob.len;
|
||||||
gis->zs.next_in = (void *) gis->cbprev;
|
gis->zs.next_in = (void *) gis->cbprev;
|
||||||
if (gis->zs.avail_in < 0) {
|
if (blob.len < 0) {
|
||||||
gis->err = -EIO;
|
gis->err = blob.len;
|
||||||
goto ret;
|
goto ret;
|
||||||
} else if (gis->zs.avail_in == 0) {
|
} else if (gis->zs.avail_in == 0) {
|
||||||
gis->err = 1;
|
gis->err = 1;
|
||||||
|
|
33
src/io.c
33
src/io.c
|
@ -15,6 +15,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
@ -26,6 +27,8 @@
|
||||||
struct apk_fd_istream {
|
struct apk_fd_istream {
|
||||||
struct apk_istream is;
|
struct apk_istream is;
|
||||||
int fd;
|
int fd;
|
||||||
|
pid_t pid;
|
||||||
|
int (*translate_status)(int status);
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssize_t fdi_read(void *stream, void *ptr, size_t size)
|
static ssize_t fdi_read(void *stream, void *ptr, size_t size)
|
||||||
|
@ -45,9 +48,15 @@ static ssize_t fdi_read(void *stream, void *ptr, size_t size)
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return i;
|
break;
|
||||||
i += r;
|
i += r;
|
||||||
}
|
}
|
||||||
|
if (i == 0 && fis->pid != 0) {
|
||||||
|
int status;
|
||||||
|
if (waitpid(fis->pid, &status, 0) == fis->pid)
|
||||||
|
i = fis->translate_status(status);
|
||||||
|
fis->pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -56,12 +65,15 @@ static void fdi_close(void *stream)
|
||||||
{
|
{
|
||||||
struct apk_fd_istream *fis =
|
struct apk_fd_istream *fis =
|
||||||
container_of(stream, struct apk_fd_istream, is);
|
container_of(stream, struct apk_fd_istream, is);
|
||||||
|
int status;
|
||||||
|
|
||||||
close(fis->fd);
|
close(fis->fd);
|
||||||
|
if (fis->pid != 0)
|
||||||
|
waitpid(fis->pid, &status, 0);
|
||||||
free(fis);
|
free(fis);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct apk_istream *apk_istream_from_fd(int fd)
|
struct apk_istream *apk_istream_from_fd_pid(int fd, pid_t pid, int (*translate_status)(int))
|
||||||
{
|
{
|
||||||
struct apk_fd_istream *fis;
|
struct apk_fd_istream *fis;
|
||||||
|
|
||||||
|
@ -78,6 +90,8 @@ struct apk_istream *apk_istream_from_fd(int fd)
|
||||||
.is.read = fdi_read,
|
.is.read = fdi_read,
|
||||||
.is.close = fdi_close,
|
.is.close = fdi_close,
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
|
.pid = pid,
|
||||||
|
.translate_status = translate_status,
|
||||||
};
|
};
|
||||||
|
|
||||||
return &fis->is;
|
return &fis->is;
|
||||||
|
@ -196,9 +210,9 @@ static apk_blob_t is_bs_read(void *stream, apk_blob_t token)
|
||||||
goto ret_all;
|
goto ret_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we've exchausted earlier, it's end of stream */
|
/* If we've exchausted earlier, it's end of stream or error */
|
||||||
if (APK_BLOB_IS_NULL(isbs->left))
|
if (APK_BLOB_IS_NULL(isbs->left))
|
||||||
return APK_BLOB_NULL;
|
return isbs->left;
|
||||||
|
|
||||||
/* We need more data */
|
/* We need more data */
|
||||||
if (isbs->left.len != 0)
|
if (isbs->left.len != 0)
|
||||||
|
@ -213,6 +227,10 @@ static apk_blob_t is_bs_read(void *stream, apk_blob_t token)
|
||||||
if (isbs->left.len == 0)
|
if (isbs->left.len == 0)
|
||||||
isbs->left = APK_BLOB_NULL;
|
isbs->left = APK_BLOB_NULL;
|
||||||
goto ret_all;
|
goto ret_all;
|
||||||
|
} else {
|
||||||
|
/* cache and return error */
|
||||||
|
isbs->left = ret = APK_BLOB_ERROR(size);
|
||||||
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!APK_BLOB_IS_NULL(token)) {
|
if (!APK_BLOB_IS_NULL(token)) {
|
||||||
|
@ -294,7 +312,6 @@ static void mmap_close(void *stream, size_t *size)
|
||||||
|
|
||||||
if (size != NULL)
|
if (size != NULL)
|
||||||
*size = mbs->size;
|
*size = mbs->size;
|
||||||
|
|
||||||
munmap(mbs->ptr, mbs->size);
|
munmap(mbs->ptr, mbs->size);
|
||||||
close(mbs->fd);
|
close(mbs->fd);
|
||||||
free(mbs);
|
free(mbs);
|
||||||
|
@ -332,18 +349,20 @@ static struct apk_bstream *apk_mmap_bstream_from_fd(int fd)
|
||||||
return &mbs->bs;
|
return &mbs->bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct apk_bstream *apk_bstream_from_fd(int fd)
|
struct apk_bstream *apk_bstream_from_fd_pid(int fd, pid_t pid, int (*translate_status)(int))
|
||||||
{
|
{
|
||||||
struct apk_bstream *bs;
|
struct apk_bstream *bs;
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
bs = apk_mmap_bstream_from_fd(fd);
|
bs = apk_mmap_bstream_from_fd(fd);
|
||||||
if (bs != NULL)
|
if (bs != NULL)
|
||||||
return bs;
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
return apk_bstream_from_istream(apk_istream_from_fd(fd));
|
return apk_bstream_from_istream(apk_istream_from_fd_pid(fd, pid, translate_status));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file)
|
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file)
|
||||||
|
|
|
@ -26,7 +26,7 @@ int apk_print_indented(struct apk_indent *i, apk_blob_t blob)
|
||||||
i->x = i->indent;
|
i->x = i->indent;
|
||||||
printf("\n%*s", i->indent - 1, "");
|
printf("\n%*s", i->indent - 1, "");
|
||||||
}
|
}
|
||||||
i->x += printf(" %.*s", blob.len, blob.ptr);
|
i->x += printf(" %.*s", (int) blob.len, blob.ptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
42
src/url.c
42
src/url.c
|
@ -31,7 +31,26 @@ const char *apk_url_local_file(const char *url)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fork_wget(const char *url)
|
static int translate_wget(int status)
|
||||||
|
{
|
||||||
|
if (!WIFEXITED(status))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
switch (WEXITSTATUS(status)) {
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 3:
|
||||||
|
return -EIO;
|
||||||
|
case 4:
|
||||||
|
return -ECONNABORTED;
|
||||||
|
case 8:
|
||||||
|
return -ENOENT;
|
||||||
|
default:
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fork_wget(const char *url, pid_t *ppid)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int fds[2];
|
int fds[2];
|
||||||
|
@ -56,15 +75,23 @@ static int fork_wget(const char *url)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
|
|
||||||
|
if (ppid != NULL)
|
||||||
|
*ppid = pid;
|
||||||
|
|
||||||
return fds[0];
|
return fds[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
struct apk_istream *apk_istream_from_url(const char *url)
|
struct apk_istream *apk_istream_from_url(const char *url)
|
||||||
{
|
{
|
||||||
|
pid_t pid;
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (apk_url_local_file(url) != NULL)
|
if (apk_url_local_file(url) != NULL)
|
||||||
return apk_istream_from_file(AT_FDCWD, apk_url_local_file(url));
|
return apk_istream_from_file(AT_FDCWD, apk_url_local_file(url));
|
||||||
|
|
||||||
return apk_istream_from_fd(fork_wget(url));
|
fd = fork_wget(url, &pid);
|
||||||
|
return apk_istream_from_fd_pid(fd, pid, translate_wget);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct apk_istream *apk_istream_from_url_gz(const char *file)
|
struct apk_istream *apk_istream_from_url_gz(const char *file)
|
||||||
|
@ -74,10 +101,14 @@ struct apk_istream *apk_istream_from_url_gz(const char *file)
|
||||||
|
|
||||||
struct apk_bstream *apk_bstream_from_url(const char *url)
|
struct apk_bstream *apk_bstream_from_url(const char *url)
|
||||||
{
|
{
|
||||||
|
pid_t pid;
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (apk_url_local_file(url))
|
if (apk_url_local_file(url))
|
||||||
return apk_bstream_from_file(AT_FDCWD, url);
|
return apk_bstream_from_file(AT_FDCWD, url);
|
||||||
|
|
||||||
return apk_bstream_from_fd(fork_wget(url));
|
fd = fork_wget(url, &pid);
|
||||||
|
return apk_bstream_from_fd_pid(fd, pid, translate_wget);
|
||||||
}
|
}
|
||||||
|
|
||||||
int apk_url_download(const char *url, int atfd, const char *file)
|
int apk_url_download(const char *url, int atfd, const char *file)
|
||||||
|
@ -102,9 +133,10 @@ int apk_url_download(const char *url, int atfd, const char *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
status = translate_wget(status);
|
||||||
|
if (status != 0) {
|
||||||
unlinkat(atfd, file, 0);
|
unlinkat(atfd, file, 0);
|
||||||
return -1;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -33,7 +33,7 @@ static int ver_indexes(struct apk_database *db, int argc, char **argv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
printf("%.*s [%s]\n",
|
printf("%.*s [%s]\n",
|
||||||
repo->description.len,
|
(int) repo->description.len,
|
||||||
repo->description.ptr,
|
repo->description.ptr,
|
||||||
db->repos[i].url);
|
db->repos[i].url);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue