@@ -78,6 +78,8 @@ struct cpio_context {
struct cpio_link_hash *link_hash[CPIO_LINK_HASH_SIZE];
struct list_head dir_list;
+
+ bool parse_only;
};
int __cpio cpio_start(struct cpio_context *ctx);
@@ -15,7 +15,12 @@ static ssize_t __cpio xwrite(struct cpio_context *ctx, struct file *file,
/* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
while (count) {
- ssize_t rv = kernel_write(file, p, count, pos);
+ ssize_t rv;
+
+ if (ctx->parse_only)
+ rv = count;
+ else
+ rv = kernel_write(file, p, count, pos);
if (rv < 0) {
if (rv == -EINTR || rv == -EAGAIN)
@@ -136,7 +141,8 @@ static void __cpio dir_utime(struct cpio_context *ctx)
list_for_each_entry_safe(de, tmp, &ctx->dir_list, list) {
list_del(&de->list);
- do_utime(de->name, de->mtime);
+ if (!ctx->parse_only)
+ do_utime(de->name, de->mtime);
kfree(de);
}
}
@@ -374,6 +380,13 @@ static int __cpio do_name(struct cpio_context *ctx)
free_hash(ctx);
return 0;
}
+
+ if (ctx->parse_only) {
+ if (S_ISREG(ctx->mode))
+ ctx->state = CPIO_COPYFILE;
+ return 0;
+ }
+
clean_path(ctx->collected, ctx->mode);
if (S_ISREG(ctx->mode)) {
int ml = maybe_link(ctx);
@@ -454,8 +467,10 @@ static int __cpio do_copy(struct cpio_context *ctx)
if (ret != ctx->body_len)
return (ret < 0) ? ret : -EIO;
- do_utime_path(&ctx->wfile->f_path, ctx->mtime);
- fput(ctx->wfile);
+ if (!ctx->parse_only) {
+ do_utime_path(&ctx->wfile->f_path, ctx->mtime);
+ fput(ctx->wfile);
+ }
if (ctx->csum_present && ctx->io_csum != ctx->hdr_csum)
return -EBADMSG;
@@ -480,6 +495,12 @@ static int __cpio do_symlink(struct cpio_context *ctx)
struct path path;
int error;
+ ctx->state = CPIO_SKIPIT;
+ ctx->next_state = CPIO_RESET;
+
+ if (ctx->parse_only)
+ return 0;
+
ctx->collected[N_ALIGN(ctx->name_len) + ctx->body_len] = '\0';
clean_path(ctx->collected, 0);
@@ -498,8 +519,7 @@ static int __cpio do_symlink(struct cpio_context *ctx)
cpio_chown(ctx->collected, ctx->uid, ctx->gid, AT_SYMLINK_NOFOLLOW);
do_utime(ctx->collected, ctx->mtime);
- ctx->state = CPIO_SKIPIT;
- ctx->next_state = CPIO_RESET;
+
return 0;
}
@@ -581,7 +601,8 @@ int __cpio cpio_start(struct cpio_context *ctx)
void __cpio cpio_finish(struct cpio_context *ctx)
{
- dir_utime(ctx);
+ if (!ctx->parse_only)
+ dir_utime(ctx);
kfree(ctx->name_buf);
kfree(ctx->symlink_buf);
kfree(ctx->header_buf);
In order to allow a CPIO archive to be parsed without actually extracting anything add a parse_only flag. Signed-off-by: Jonathan McDowell <noodles@fb.com> --- include/linux/cpio.h | 2 ++ lib/cpio.c | 35 ++++++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-)