summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2015-11-09 12:47:23 +0200
committerTimo Teräs <timo.teras@iki.fi>2015-11-09 12:51:01 +0200
commitcce4cff55310cddb2e2ec61d19b758e52a4e2c97 (patch)
treede2735305369fc75caee961485a6d44bc2782ce5
parent7501f6012fc06ebfa8c6d8f928f38318267abe72 (diff)
io, database: preserve [am]time for cached and fetched files
preserve [am]time for all packages and indexes. this fixes the caching error that 'apk update' is after new index is generated, but before the used mirror is synchronized. this caused local apkindex timestamp to be newer than file in mirror, when in fact it was outdated index. this also fixes fetched files to have build timestamp so that files going to .iso or custom images have proper timestamps (rsync with appropriate --modify-window now works)
-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)