summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/apk_io.h7
-rw-r--r--src/archive.c13
-rw-r--r--src/database.c3
-rw-r--r--src/fetch.c8
-rw-r--r--src/gunzip.c8
-rw-r--r--src/io.c58
-rw-r--r--src/url.c36
7 files changed, 122 insertions, 11 deletions
diff --git a/src/apk_io.h b/src/apk_io.h
index 6e2e37c..b0e15a4 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -33,6 +33,11 @@ struct apk_xattr {
};
APK_ARRAY(apk_xattr_array, struct apk_xattr);
+struct apk_file_meta {
+ time_t mtime, atime;
+};
+void apk_file_meta_to_fd(int fd, struct apk_file_meta *meta);
+
struct apk_file_info {
char *name;
char *link_target;
@@ -50,6 +55,7 @@ struct apk_file_info {
};
struct apk_istream {
+ void (*get_meta)(void *stream, struct apk_file_meta *meta);
ssize_t (*read)(void *stream, void *ptr, size_t size);
void (*close)(void *stream);
};
@@ -59,6 +65,7 @@ struct apk_istream {
struct apk_bstream {
unsigned int flags;
+ void (*get_meta)(void *stream, struct apk_file_meta *meta);
apk_blob_t (*read)(void *stream, apk_blob_t token);
void (*close)(void *stream, size_t *size);
};
diff --git a/src/archive.c b/src/archive.c
index e58f6d5..ecb276a 100644
--- a/src/archive.c
+++ b/src/archive.c
@@ -84,8 +84,19 @@ struct apk_tar_entry_istream {
size_t bytes_left;
EVP_MD_CTX mdctx;
struct apk_checksum *csum;
+ time_t mtime;
};
+static void tar_entry_get_meta(void *stream, struct apk_file_meta *meta)
+{
+ struct apk_tar_entry_istream *teis =
+ container_of(stream, struct apk_tar_entry_istream, is);
+ *meta = (struct apk_file_meta) {
+ .atime = teis->mtime,
+ .mtime = teis->mtime,
+ };
+}
+
static ssize_t tar_entry_read(void *stream, void *ptr, size_t size)
{
struct apk_tar_entry_istream *teis =
@@ -175,6 +186,7 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
{
struct apk_file_info entry;
struct apk_tar_entry_istream teis = {
+ .is.get_meta = tar_entry_get_meta,
.is.read = tar_entry_read,
.is.close = tar_entry_close,
.tar_is = is,
@@ -213,6 +225,7 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
buf.mode[0] = 0; /* to nul terminate 100-byte buf.name */
buf.magic[0] = 0; /* to nul terminate 100-byte buf.linkname */
teis.csum = NULL;
+ teis.mtime = entry.mtime;
apk_xattr_array_resize(&entry.xattrs, 0);
if (paxlen) {
diff --git a/src/database.c b/src/database.c
index ed7f10b..8a56401 100644
--- a/src/database.c
+++ b/src/database.c
@@ -655,7 +655,10 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo,
} else fd = -1, r = PTR_ERR(is) ?: -EIO;
if (fd >= 0) {
+ struct apk_file_meta meta;
r = apk_istream_splice(is, fd, APK_SPLICE_ALL, cb, cb_ctx);
+ is->get_meta(is, &meta);
+ apk_file_meta_to_fd(fd, &meta);
close(fd);
}
}
diff --git a/src/fetch.c b/src/fetch.c
index 43e4dbf..3bb7934 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -175,9 +175,13 @@ static int fetch_package(apk_hash_item item, void *pctx)
}
r = apk_istream_splice(is, fd, pkg->size, progress_cb, ctx);
- is->close(is);
- if (fd != STDOUT_FILENO)
+ if (fd != STDOUT_FILENO) {
+ struct apk_file_meta meta;
+ is->get_meta(is, &meta);
+ apk_file_meta_to_fd(fd, &meta);
close(fd);
+ }
+ is->close(is);
if (r != pkg->size) {
unlinkat(ctx->outdir_fd, filename, 0);
diff --git a/src/gunzip.c b/src/gunzip.c
index 366094f..d1eb0cb 100644
--- a/src/gunzip.c
+++ b/src/gunzip.c
@@ -30,6 +30,13 @@ struct apk_gzip_istream {
apk_blob_t cbarg;
};
+static void gzi_get_meta(void *stream, struct apk_file_meta *meta)
+{
+ struct apk_gzip_istream *gis =
+ container_of(stream, struct apk_gzip_istream, is);
+ gis->bs->get_meta(gis->bs, meta);
+}
+
static ssize_t gzi_read(void *stream, void *ptr, size_t size)
{
struct apk_gzip_istream *gis =
@@ -155,6 +162,7 @@ struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs,
if (!gis) goto err;
*gis = (struct apk_gzip_istream) {
+ .is.get_meta = gzi_get_meta,
.is.read = gzi_read,
.is.close = gzi_close,
.bs = bs,
diff --git a/src/io.c b/src/io.c
index 65851be..b48f932 100644
--- a/src/io.c
+++ b/src/io.c
@@ -33,6 +33,27 @@
#define HAVE_FGETGRENT_R
#endif
+static void apk_file_meta_from_fd(int fd, struct apk_file_meta *meta)
+{
+ struct stat st;
+
+ if (fstat(fd, &st) == 0) {
+ meta->mtime = st.st_mtime;
+ meta->atime = st.st_atime;
+ } else {
+ memset(meta, 0, sizeof(*meta));
+ }
+}
+
+void apk_file_meta_to_fd(int fd, struct apk_file_meta *meta)
+{
+ struct timespec times[2] = {
+ { .tv_sec = meta->atime, .tv_nsec = meta->atime ? 0 : UTIME_OMIT },
+ { .tv_sec = meta->mtime, .tv_nsec = meta->mtime ? 0 : UTIME_OMIT }
+ };
+ futimens(fd, times);
+}
+
struct apk_fd_istream {
struct apk_istream is;
int fd;
@@ -40,6 +61,13 @@ struct apk_fd_istream {
int (*translate_status)(int status);
};
+static void fdi_get_meta(void *stream, struct apk_file_meta *meta)
+{
+ struct apk_fd_istream *fis =
+ container_of(stream, struct apk_fd_istream, is);
+ apk_file_meta_from_fd(fis->fd, meta);
+}
+
static ssize_t fdi_read(void *stream, void *ptr, size_t size)
{
struct apk_fd_istream *fis =
@@ -95,6 +123,7 @@ struct apk_istream *apk_istream_from_fd_pid(int fd, pid_t pid, int (*translate_s
}
*fis = (struct apk_fd_istream) {
+ .is.get_meta = fdi_get_meta,
.is.read = fdi_read,
.is.close = fdi_close,
.fd = fd,
@@ -207,6 +236,13 @@ struct apk_istream_bstream {
size_t size;
};
+static void is_bs_get_meta(void *stream, struct apk_file_meta *meta)
+{
+ struct apk_istream_bstream *isbs =
+ container_of(stream, struct apk_istream_bstream, bs);
+ return isbs->is->get_meta(isbs->is, meta);
+}
+
static apk_blob_t is_bs_read(void *stream, apk_blob_t token)
{
struct apk_istream_bstream *isbs =
@@ -284,6 +320,7 @@ struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream)
if (isbs == NULL) return ERR_PTR(-ENOMEM);
isbs->bs = (struct apk_bstream) {
+ .get_meta = is_bs_get_meta,
.read = is_bs_read,
.close = is_bs_close,
};
@@ -302,6 +339,13 @@ struct apk_mmap_bstream {
apk_blob_t left;
};
+static void mmap_get_meta(void *stream, struct apk_file_meta *meta)
+{
+ struct apk_mmap_bstream *mbs =
+ container_of(stream, struct apk_mmap_bstream, bs);
+ return apk_file_meta_from_fd(mbs->fd, meta);
+}
+
static apk_blob_t mmap_read(void *stream, apk_blob_t token)
{
struct apk_mmap_bstream *mbs =
@@ -351,6 +395,7 @@ static struct apk_bstream *apk_mmap_bstream_from_fd(int fd)
mbs->bs = (struct apk_bstream) {
.flags = APK_BSTREAM_SINGLE_READ,
+ .get_meta = mmap_get_meta,
.read = mmap_read,
.close = mmap_close,
};
@@ -397,6 +442,13 @@ struct apk_tee_bstream {
void *cb_ctx;
};
+static void tee_get_meta(void *stream, struct apk_file_meta *meta)
+{
+ struct apk_tee_bstream *tbs =
+ container_of(stream, struct apk_tee_bstream, bs);
+ tbs->inner_bs->get_meta(tbs->inner_bs, meta);
+}
+
static apk_blob_t tee_read(void *stream, apk_blob_t token)
{
struct apk_tee_bstream *tbs =
@@ -415,9 +467,14 @@ static apk_blob_t tee_read(void *stream, apk_blob_t token)
static void tee_close(void *stream, size_t *size)
{
+ struct apk_file_meta meta;
struct apk_tee_bstream *tbs =
container_of(stream, struct apk_tee_bstream, bs);
+ /* copy info */
+ tbs->inner_bs->get_meta(tbs->inner_bs, &meta);
+ apk_file_meta_to_fd(tbs->fd, &meta);
+
tbs->inner_bs->close(tbs->inner_bs, NULL);
if (size != NULL)
*size = tbs->size;
@@ -449,6 +506,7 @@ struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const ch
}
tbs->bs = (struct apk_bstream) {
+ .get_meta = tee_get_meta,
.read = tee_read,
.close = tee_close,
};
diff --git a/src/url.c b/src/url.c
index b9fcc53..711755a 100644
--- a/src/url.c
+++ b/src/url.c
@@ -36,6 +36,7 @@ const char *apk_url_local_file(const char *url)
struct apk_fetch_istream {
struct apk_istream is;
fetchIO *fetchIO;
+ struct url_stat urlstat;
};
static int fetch_maperror(int ec)
@@ -66,6 +67,16 @@ static int fetch_maperror(int ec)
return map[ec];
}
+static void fetch_get_meta(void *stream, struct apk_file_meta *meta)
+{
+ struct apk_fetch_istream *fis = container_of(stream, struct apk_fetch_istream, is);
+
+ *meta = (struct apk_file_meta) {
+ .atime = fis->urlstat.atime,
+ .mtime = fis->urlstat.mtime,
+ };
+}
+
static ssize_t fetch_read(void *stream, void *ptr, size_t size)
{
struct apk_fetch_istream *fis = container_of(stream, struct apk_fetch_istream, is);
@@ -95,28 +106,35 @@ static struct apk_istream *apk_istream_fetch(const char *url, time_t since)
{
struct apk_fetch_istream *fis;
struct url *u;
- fetchIO *io;
+ fetchIO *io = NULL;
+ int rc = -ENOMEM;
u = fetchParseURL(url);
- if (!u) return ERR_PTR(-ENOMEM);
- u->last_modified = since;
- io = fetchGet(u, "i");
- fetchFreeURL(u);
- if (!io) return ERR_PTR(fetch_maperror(fetchLastErrCode));
-
fis = malloc(sizeof(*fis));
- if (!fis) goto err;
+ if (!fis || !u) goto err;
+
+ u->last_modified = since;
+ io = fetchXGet(u, &fis->urlstat, "i");
+ if (!io) {
+ rc = fetch_maperror(fetchLastErrCode);
+ goto err;
+ }
*fis = (struct apk_fetch_istream) {
+ .is.get_meta = fetch_get_meta,
.is.read = fetch_read,
.is.close = fetch_close,
.fetchIO = io,
+ .urlstat = fis->urlstat,
};
+ fetchFreeURL(u);
return &fis->is;
err:
+ if (u) fetchFreeURL(u);
if (io) fetchIO_close(io);
- return ERR_PTR(-ENOMEM);
+ if (fis) free(fis);
+ return ERR_PTR(rc);
}
struct apk_istream *apk_istream_from_fd_url_if_modified(int atfd, const char *url, time_t since)