diff options
author | Timo Teräs <timo.teras@iki.fi> | 2014-10-08 11:13:21 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2014-10-08 11:13:21 +0300 |
commit | 32627939f5c57887b25100dd49aa91839876abed (patch) | |
tree | c39918143209386d1509c70d56fe8683878f2b30 | |
parent | 555363f056377508040d3a555d198c4b87aff3a3 (diff) | |
download | apk-tools-32627939f5c57887b25100dd49aa91839876abed.tar.gz apk-tools-32627939f5c57887b25100dd49aa91839876abed.tar.bz2 apk-tools-32627939f5c57887b25100dd49aa91839876abed.tar.xz apk-tools-32627939f5c57887b25100dd49aa91839876abed.zip |
io,url,db: support for if-modified-since
-rw-r--r-- | src/apk_defines.h | 6 | ||||
-rw-r--r-- | src/apk_io.h | 25 | ||||
-rw-r--r-- | src/database.c | 38 | ||||
-rw-r--r-- | src/gunzip.c | 5 | ||||
-rw-r--r-- | src/io.c | 29 | ||||
-rw-r--r-- | src/url.c | 31 |
6 files changed, 81 insertions, 53 deletions
diff --git a/src/apk_defines.h b/src/apk_defines.h index 95b70de..d27bad4 100644 --- a/src/apk_defines.h +++ b/src/apk_defines.h @@ -32,6 +32,12 @@ #define NULL 0L #endif +static inline void *ERR_PTR(long error) { return (void*) error; } +static inline void *ERR_CAST(const void *ptr) { return (void*) ptr; } +static inline int PTR_ERR(const void *ptr) { return (int)(long) ptr; } +static inline int IS_ERR(const void *ptr) { return (unsigned long)ptr >= (unsigned long)-4095; } +static inline int IS_ERR_OR_NULL(const void *ptr) { return IS_ERR(ptr) || !ptr; } + #if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96 #define __builtin_expect(x, expected_value) (x) #endif diff --git a/src/apk_io.h b/src/apk_io.h index c61fc6e..82102aa 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -14,6 +14,7 @@ #include <sys/types.h> #include <openssl/evp.h> #include <fcntl.h> +#include <time.h> #include "apk_defines.h" #include "apk_blob.h" @@ -78,7 +79,7 @@ struct apk_ostream *apk_ostream_counter(off_t *); 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_gz(int atfd, const char *file); -struct apk_istream *apk_istream_from_fd_url(int atfd, const char *url); +struct apk_istream *apk_istream_from_fd_url_if_modified(int atfd, const char *url, time_t since); struct apk_istream *apk_istream_from_url_gz(const char *url); size_t apk_istream_skip(struct apk_istream *istream, size_t size); @@ -92,13 +93,21 @@ static inline struct apk_istream *apk_istream_from_fd(int fd) } static inline struct apk_istream *apk_istream_from_url(const char *url) { - return apk_istream_from_fd_url(AT_FDCWD, url); + return apk_istream_from_fd_url_if_modified(AT_FDCWD, url, 0); +} +static inline struct apk_istream *apk_istream_from_fd_url(int atfd, const char *url) +{ + return apk_istream_from_fd_url_if_modified(atfd, url, 0); +} +static inline struct apk_istream *apk_istream_from_url_if_modified(const char *url, time_t since) +{ + return apk_istream_from_fd_url_if_modified(AT_FDCWD, url, since); } struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream); 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_fd_url(int atfd, const char *url); +struct apk_bstream *apk_bstream_from_fd_url_if_modified(int atfd, const char *url, time_t since); struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const char *to, apk_progress_cb cb, void *cb_ctx); @@ -109,7 +118,15 @@ static inline struct apk_bstream *apk_bstream_from_fd(int fd) static inline struct apk_bstream *apk_bstream_from_url(const char *url) { - return apk_bstream_from_fd_url(AT_FDCWD, 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); } struct apk_ostream *apk_ostream_to_fd(int fd); diff --git a/src/database.c b/src/database.c index ef9f73c..3962a8e 100644 --- a/src/database.c +++ b/src/database.c @@ -605,6 +605,7 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, struct apk_package *pkg, int verify, apk_progress_cb cb, void *cb_ctx) { + struct stat st; struct apk_istream *is; struct apk_bstream *bs; struct apk_sign_ctx sctx; @@ -618,40 +619,42 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, r = apk_pkg_format_cache_pkg(b, pkg); else r = apk_repo_format_cache_index(b, repo); - if (r < 0) - return r; + if (r < 0) return r; r = apk_repo_format_real_url(db, repo, pkg, url, sizeof(url)); - if (r < 0) - return r; + if (r < 0) return r; - apk_message("fetch %s", url); + if (fstatat(db->cache_fd, cacheitem, &st, 0) != 0) st.st_mtime = 0; - if (apk_flags & APK_SIMULATE) - return 0; + apk_message("fetch %s", url); - if (cb) - cb(cb_ctx, 0); + if (apk_flags & APK_SIMULATE) return 0; + if (cb) cb(cb_ctx, 0); if (verify != APK_SIGN_NONE) { apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd); - bs = apk_bstream_from_url(url); + bs = apk_bstream_from_url_if_modified(url, st.st_mtime); bs = apk_bstream_tee(bs, db->cache_fd, tmpcacheitem, cb, cb_ctx); is = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &sctx); - if (is) r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE, &db->id_cache); - else r = -errno; + if (!IS_ERR_OR_NULL(is)) + r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE, &db->id_cache); + else + r = PTR_ERR(is) ?: -EIO; apk_sign_ctx_free(&sctx); } else { - is = apk_istream_from_url(url); - fd = openat(db->cache_fd, tmpcacheitem, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); + is = apk_istream_from_url_if_modified(url, st.st_mtime); + if (!IS_ERR_OR_NULL(is)) { + fd = openat(db->cache_fd, tmpcacheitem, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); + if (fd < 0) r = -errno; + } else fd = -1, r = PTR_ERR(is) ?: -EIO; + if (fd >= 0) { r = apk_istream_splice(is, fd, APK_SPLICE_ALL, cb, cb_ctx); close(fd); - } else { - r = -errno; } } - if (is) is->close(is); + if (!IS_ERR_OR_NULL(is)) is->close(is); + if (r == -EALREADY) return 0; if (r < 0) { unlinkat(db->cache_fd, tmpcacheitem, 0); return r; @@ -659,7 +662,6 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, if (renameat(db->cache_fd, tmpcacheitem, db->cache_fd, cacheitem) < 0) return -errno; - return 0; } diff --git a/src/gunzip.c b/src/gunzip.c index 944132e..45e3b3c 100644 --- a/src/gunzip.c +++ b/src/gunzip.c @@ -149,7 +149,7 @@ struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs, { struct apk_gzip_istream *gis; - if (!bs) return NULL; + if (IS_ERR_OR_NULL(bs)) return ERR_CAST(bs); gis = malloc(sizeof(struct apk_gzip_istream)); if (!gis) goto err; @@ -233,8 +233,7 @@ struct apk_ostream *apk_ostream_gzip(struct apk_ostream *output) { struct apk_gzip_ostream *gos; - if (output == NULL) - return NULL; + if (IS_ERR_OR_NULL(output)) return ERR_CAST(output); gos = malloc(sizeof(struct apk_gzip_ostream)); if (gos == NULL) @@ -83,8 +83,7 @@ struct apk_istream *apk_istream_from_fd_pid(int fd, pid_t pid, int (*translate_s { struct apk_fd_istream *fis; - if (fd < 0) - return NULL; + if (fd < 0) return NULL; fis = malloc(sizeof(struct apk_fd_istream)); if (fis == NULL) { @@ -108,8 +107,7 @@ struct apk_istream *apk_istream_from_file(int atfd, const char *file) int fd; fd = openat(atfd, file, O_RDONLY | O_CLOEXEC); - if (fd < 0) - return NULL; + if (fd < 0) return NULL; return apk_istream_from_fd(fd); } @@ -272,9 +270,10 @@ 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 NULL; + if (isbs == NULL) return NULL; isbs->bs = (struct apk_bstream) { .read = is_bs_read, @@ -331,12 +330,10 @@ static struct apk_bstream *apk_mmap_bstream_from_fd(int fd) struct stat st; void *ptr; - if (fstat(fd, &st) < 0) - return NULL; + if (fstat(fd, &st) < 0) return NULL; ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) - return NULL; + if (ptr == MAP_FAILED) return NULL; mbs = malloc(sizeof(struct apk_mmap_bstream)); if (mbs == NULL) { @@ -361,8 +358,7 @@ struct apk_bstream *apk_bstream_from_fd_pid(int fd, pid_t pid, int (*translate_s { struct apk_bstream *bs; - if (fd < 0) - return NULL; + if (fd < 0) return NULL; if (pid == 0) { bs = apk_mmap_bstream_from_fd(fd); @@ -378,8 +374,7 @@ 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 NULL; + if (fd < 0) return NULL; return apk_bstream_from_fd(fd); } @@ -427,7 +422,7 @@ struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const ch struct apk_tee_bstream *tbs; int fd; - if (!from) return NULL; + if (IS_ERR_OR_NULL(from)) return ERR_CAST(from); fd = openat(atfd, to, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); @@ -831,8 +826,8 @@ int apk_move_file(int atfd, const char *from, const char *to) return -errno; is = apk_istream_from_file(atfd, from); - if (is == NULL) - return -ENOENT; + if (IS_ERR(is)) return PTR_ERR(is); + if (!is) return -ENOENT; tofd = openat(atfd, to, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); @@ -63,34 +63,43 @@ static void fetch_close(void *stream) free(fis); } -static struct apk_istream *apk_istream_fetch(const char *url) +static struct apk_istream *apk_istream_fetch(const char *url, time_t since) { struct apk_fetch_istream *fis; + struct url *u; fetchIO *io; - io = fetchGetURL(url, ""); - if (!io) return NULL; - - fis = malloc(sizeof(*fis)); - if (!fis) { - fetchIO_close(io); + u = fetchParseURL(url); + if (!u) return NULL; + u->last_modified = since; + io = fetchGet(u, "i"); + fetchFreeURL(u); + if (!io) { + if (fetchLastErrCode == FETCH_UNCHANGED) return ERR_PTR(-EALREADY); return NULL; } + fis = malloc(sizeof(*fis)); + if (!fis) goto err; + *fis = (struct apk_fetch_istream) { .is.read = fetch_read, .is.close = fetch_close, .fetchIO = io, }; + fetchFreeURL(u); return &fis->is; +err: + if (io) fetchIO_close(io); + return NULL; } -struct apk_istream *apk_istream_from_fd_url(int atfd, const char *url) +struct apk_istream *apk_istream_from_fd_url_if_modified(int atfd, const char *url, time_t since) { if (apk_url_local_file(url) != NULL) return apk_istream_from_file(atfd, apk_url_local_file(url)); - return apk_istream_fetch(url); + return apk_istream_fetch(url, since); } struct apk_istream *apk_istream_from_url_gz(const char *file) @@ -98,9 +107,9 @@ struct apk_istream *apk_istream_from_url_gz(const char *file) return apk_bstream_gunzip(apk_bstream_from_url(file)); } -struct apk_bstream *apk_bstream_from_fd_url(int atfd, const char *url) +struct apk_bstream *apk_bstream_from_fd_url_if_modified(int atfd, const char *url, time_t since) { if (apk_url_local_file(url) != NULL) return apk_bstream_from_file(atfd, apk_url_local_file(url)); - return apk_bstream_from_istream(apk_istream_fetch(url)); + return apk_bstream_from_istream(apk_istream_fetch(url, since)); } |