summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-22 03:28:05 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-22 17:12:45 +0200
commitadc8e37d7f86d661ab54adf9c43e4b0aa67a939c (patch)
treed075abb80d7cd22935a32e20e5bfcb53acef087d
parentc673f305ec0c2c80bc3873bcc8718d9ba85340c9 (diff)
Add a way to optionally keep the original time stamps
First of all, this commit adds a mod_time field to a tree node. When creating the tree node, the field is set from the struct stat. When scanning a directory, the time stamps from the input are used if set. Second, the libsqfs code that reads inodes is modified to store the mod_time from the inode in the fstree node and to write the tree node into a generated inode. Finally, tar2sqfs is modified to optionally keep the timestamps from the tar archive instead of setting defaults. gensquashfs is similarly modified to keep the input timestamps if specified. The result is as follows: - sqfs2tar will always carry the timestamps from the squashfs over to the tar ball. - tar2sqfs will set defaults, unless explicitly asked to preserve the mtime from the tar ball. - gensquashfs can optionally preserve the mtime from the input hierarchy it processes if only --pack-dir is specified. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--doc/gensquashfs.15
-rw-r--r--doc/tar2sqfs.15
-rw-r--r--include/fstree.h6
-rw-r--r--lib/fstree/add_by_path.c1
-rw-r--r--lib/fstree/fstree_from_dir.c14
-rw-r--r--lib/fstree/fstree_from_file.c6
-rw-r--r--lib/fstree/mknode.c1
-rw-r--r--lib/fstree/node_stat.c3
-rw-r--r--lib/sqfs/tree_node_from_inode.c1
-rw-r--r--lib/sqfs/write_inode.c2
-rw-r--r--mkfs/mkfs.c2
-rw-r--r--mkfs/mkfs.h1
-rw-r--r--mkfs/options.c12
-rw-r--r--tar/tar2sqfs.c15
14 files changed, 62 insertions, 12 deletions
diff --git a/doc/gensquashfs.1 b/doc/gensquashfs.1
index a880453..d7b78a1 100644
--- a/doc/gensquashfs.1
+++ b/doc/gensquashfs.1
@@ -37,6 +37,11 @@ Defaults to 131072.
Device block size to padd the image to.
Defaults to 4096.
.TP
+\fB\-\-keep\-time\fR, \fB\-k\fR
+Whe using \fB\-\-pack\-dir\fR only, use the timestamps from the input files
+instead of setting defaults on all input paths. The root inode and the
+modification time on the SquashFS image itself will still be set to defaults.
+.TP
\fB\-\-defaults\fR, \fB\-d\fR <options>
A comma seperated list of default values for
implicitly created directories.
diff --git a/doc/tar2sqfs.1 b/doc/tar2sqfs.1
index 8c7d20d..a6646c6 100644
--- a/doc/tar2sqfs.1
+++ b/doc/tar2sqfs.1
@@ -31,6 +31,11 @@ Defaults to 131072.
Device block size to padd the image to.
Defaults to 4096.
.TP
+\fB\-\-keep\-time\fR, \fB\-k\fR
+Keep the same time stamps stored in the tar archive for the SquashFS instead of
+setting defaults on all files. The root inode and the modification time on the
+SquashFS image itself will still be set to defaults.
+.TP
\fB\-\-defaults\fR, \fB\-d\fR <options>
A comma seperated list of default values for
implicitly created directories.
diff --git a/include/fstree.h b/include/fstree.h
index 4efa9d5..1b25363 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -119,6 +119,8 @@ struct tree_node_t {
uint32_t uid;
uint32_t gid;
+ uint32_t inode_num;
+ uint32_t mod_time;
uint16_t mode;
/* SquashFS inode refernce number. 32 bit offset of the meta data
@@ -128,8 +130,6 @@ struct tree_node_t {
Generated on the fly when writing inodes. */
uint64_t inode_ref;
- uint32_t inode_num;
-
/* Type specific data. Pointers are into payload area blow. */
union {
dir_info_t *dir;
@@ -241,7 +241,7 @@ int fstree_from_file(fstree_t *fs, const char *filename, FILE *fp);
Returns 0 on success, prints errors to stderr.
*/
-int fstree_from_dir(fstree_t *fs, const char *path);
+int fstree_from_dir(fstree_t *fs, const char *path, bool keep_time_stamps);
/* Add labels from an SELinux labeling file to all tree nodes.
Returns 0 on success. Internally prints errors to stderr. */
diff --git a/lib/fstree/add_by_path.c b/lib/fstree/add_by_path.c
index eaa0925..7e0a4ce 100644
--- a/lib/fstree/add_by_path.c
+++ b/lib/fstree/add_by_path.c
@@ -77,6 +77,7 @@ tree_node_t *fstree_add_generic(fstree_t *fs, const char *path,
child->uid = sb->st_uid;
child->gid = sb->st_gid;
child->mode = sb->st_mode;
+ child->mod_time = sb->st_mtime;
child->data.dir->created_implicitly = false;
return child;
}
diff --git a/lib/fstree/fstree_from_dir.c b/lib/fstree/fstree_from_dir.c
index 29911f4..ad75006 100644
--- a/lib/fstree/fstree_from_dir.c
+++ b/lib/fstree/fstree_from_dir.c
@@ -43,7 +43,7 @@ fail:
return NULL;
}
-static int populate_dir(fstree_t *fs, tree_node_t *root)
+static int populate_dir(fstree_t *fs, tree_node_t *root, bool keep_time_stamps)
{
char *extra = NULL;
struct dirent *ent;
@@ -92,6 +92,12 @@ static int populate_dir(fstree_t *fs, tree_node_t *root)
goto fail;
}
+ if (!keep_time_stamps) {
+ sb.st_atim = fs->defaults.st_atim;
+ sb.st_mtim = fs->defaults.st_mtim;
+ sb.st_ctim = fs->defaults.st_ctim;
+ }
+
n = fstree_mknode(fs, root, ent->d_name, strlen(ent->d_name),
extra, &sb);
if (n == NULL) {
@@ -110,7 +116,7 @@ static int populate_dir(fstree_t *fs, tree_node_t *root)
if (pushd(n->name))
return -1;
- if (populate_dir(fs, n))
+ if (populate_dir(fs, n, keep_time_stamps))
return -1;
if (popd())
@@ -127,14 +133,14 @@ fail:
return -1;
}
-int fstree_from_dir(fstree_t *fs, const char *path)
+int fstree_from_dir(fstree_t *fs, const char *path, bool keep_time_stamps)
{
int ret;
if (pushd(path))
return -1;
- ret = populate_dir(fs, fs->root);
+ ret = populate_dir(fs, fs->root, keep_time_stamps);
if (popd())
ret = -1;
diff --git a/lib/fstree/fstree_from_file.c b/lib/fstree/fstree_from_file.c
index 901e431..91a922b 100644
--- a/lib/fstree/fstree_from_file.c
+++ b/lib/fstree/fstree_from_file.c
@@ -66,6 +66,9 @@ static int add_file(fstree_t *fs, const char *filename, size_t line_num,
sb.st_uid = basic->st_uid;
sb.st_gid = basic->st_gid;
sb.st_mode = basic->st_mode;
+ sb.st_atim = basic->st_atim;
+ sb.st_mtim = basic->st_mtim;
+ sb.st_ctim = basic->st_ctim;
return add_generic(fs, filename, line_num, path, &sb, extra);
}
@@ -119,6 +122,9 @@ static int handle_line(fstree_t *fs, const char *filename,
size_t i;
memset(&sb, 0, sizeof(sb));
+ sb.st_mtime = fs->defaults.st_mtime;
+ sb.st_atime = fs->defaults.st_atime;
+ sb.st_ctime = fs->defaults.st_ctime;
/* isolate keyword */
for (i = 0; isalpha(line[i]); ++i)
diff --git a/lib/fstree/mknode.c b/lib/fstree/mknode.c
index 4b4cdfd..7d09fbd 100644
--- a/lib/fstree/mknode.c
+++ b/lib/fstree/mknode.c
@@ -43,6 +43,7 @@ tree_node_t *fstree_mknode(fstree_t *fs, tree_node_t *parent, const char *name,
n->uid = sb->st_uid;
n->gid = sb->st_gid;
n->mode = sb->st_mode;
+ n->mod_time = sb->st_mtime;
switch (sb->st_mode & S_IFMT) {
case S_IFDIR:
diff --git a/lib/fstree/node_stat.c b/lib/fstree/node_stat.c
index 8f62a0f..a28cae8 100644
--- a/lib/fstree/node_stat.c
+++ b/lib/fstree/node_stat.c
@@ -13,6 +13,9 @@ void fstree_node_stat(fstree_t *fs, tree_node_t *node, struct stat *sb)
sb->st_nlink = 1;
sb->st_uid = node->uid;
sb->st_gid = node->gid;
+ sb->st_mtime = node->mod_time;
+ sb->st_atime = node->mod_time;
+ sb->st_ctime = node->mod_time;
switch (node->mode & S_IFMT) {
case S_IFDIR:
diff --git a/lib/sqfs/tree_node_from_inode.c b/lib/sqfs/tree_node_from_inode.c
index 0d46eed..1ee85e5 100644
--- a/lib/sqfs/tree_node_from_inode.c
+++ b/lib/sqfs/tree_node_from_inode.c
@@ -88,6 +88,7 @@ tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode,
out->gid = idtbl->ids[inode->base.gid_idx];
out->mode = inode->base.mode;
out->inode_num = inode->base.inode_number;
+ out->mod_time = inode->base.mod_time;
out->name = (char *)out->payload;
switch (inode->base.type) {
diff --git a/lib/sqfs/write_inode.c b/lib/sqfs/write_inode.c
index a013d6f..6e11277 100644
--- a/lib/sqfs/write_inode.c
+++ b/lib/sqfs/write_inode.c
@@ -143,7 +143,7 @@ int meta_writer_write_inode(fstree_t *fs, id_table_t *idtbl, meta_writer_t *im,
base.mode = htole16(node->mode);
base.uid_idx = htole16(uid_idx);
base.gid_idx = htole16(gid_idx);
- base.mod_time = htole32(fs->defaults.st_mtime);
+ base.mod_time = htole32(node->mod_time);
base.inode_number = htole32(node->inode_num);
if (meta_writer_append(im, &base, sizeof(base))) {
diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c
index 91cb9bd..654534d 100644
--- a/mkfs/mkfs.c
+++ b/mkfs/mkfs.c
@@ -81,7 +81,7 @@ static int read_fstree(fstree_t *fs, options_t *opt)
int ret;
if (opt->infile == NULL)
- return fstree_from_dir(fs, opt->packdir);
+ return fstree_from_dir(fs, opt->packdir, opt->keep_time);
fp = fopen(opt->infile, "rb");
if (fp == NULL) {
diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h
index 70a2ed6..21a308b 100644
--- a/mkfs/mkfs.h
+++ b/mkfs/mkfs.h
@@ -29,6 +29,7 @@ typedef struct {
int outmode;
int blksz;
int devblksz;
+ bool keep_time;
bool exportable;
bool quiet;
const char *infile;
diff --git a/mkfs/options.c b/mkfs/options.c
index fe2bc69..f14e6ef 100644
--- a/mkfs/options.c
+++ b/mkfs/options.c
@@ -9,6 +9,7 @@ static struct option long_opts[] = {
{ "comp-extra", required_argument, NULL, 'X' },
{ "pack-file", required_argument, NULL, 'F' },
{ "pack-dir", required_argument, NULL, 'D' },
+ { "keep-time", required_argument, NULL, 'k' },
{ "exportable", no_argument, NULL, 'e' },
{ "force", no_argument, NULL, 'f' },
{ "quiet", no_argument, NULL, 'q' },
@@ -20,9 +21,9 @@ static struct option long_opts[] = {
};
#ifdef WITH_SELINUX
-static const char *short_opts = "s:F:D:X:c:b:B:d:efqhV";
+static const char *short_opts = "s:F:D:X:c:b:B:d:kefqhV";
#else
-static const char *short_opts = "F:D:X:c:b:B:d:efqhV";
+static const char *short_opts = "F:D:X:c:b:B:d:kefqhV";
#endif
extern char *__progname;
@@ -67,6 +68,9 @@ static const char *help_string =
" --selinux, -s <file> Specify an SELinux label file to get context\n"
" attributes from.\n"
#endif
+" --keep-time, -k When using --pack-dir only, use the timestamps\n"
+" from the input files instead of setting\n"
+" defaults on all input paths.\n"
" --exportable, -e Generate an export table for NFS support.\n"
" --force, -f Overwrite the output file if it exists.\n"
" --quiet, -q Do not print out progress reports.\n"
@@ -125,6 +129,7 @@ void process_command_line(options_t *opt, int argc, char **argv)
opt->compressor = compressor_get_default();
opt->blksz = SQFS_DEFAULT_BLOCK_SIZE;
opt->devblksz = SQFS_DEVBLK_SIZE;
+ opt->keep_time = false;
opt->exportable = false;
opt->quiet = false;
opt->infile = NULL;
@@ -169,6 +174,9 @@ void process_command_line(options_t *opt, int argc, char **argv)
case 'd':
opt->fs_defaults = optarg;
break;
+ case 'k':
+ opt->keep_time = true;
+ break;
case 'e':
opt->exportable = true;
break;
diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c
index f557f95..2493c3b 100644
--- a/tar/tar2sqfs.c
+++ b/tar/tar2sqfs.c
@@ -26,6 +26,7 @@ static struct option long_opts[] = {
{ "comp-extra", required_argument, NULL, 'X' },
{ "no-skip", no_argument, NULL, 's' },
{ "no-xattr", no_argument, NULL, 'x' },
+ { "keep-time", no_argument, NULL, 'k' },
{ "exportable", no_argument, NULL, 'e' },
{ "force", no_argument, NULL, 'f' },
{ "quiet", no_argument, NULL, 'q' },
@@ -33,7 +34,7 @@ static struct option long_opts[] = {
{ "version", no_argument, NULL, 'V' },
};
-static const char *short_opts = "c:b:B:d:X:sxefqhV";
+static const char *short_opts = "c:b:B:d:X:sxekfqhV";
static const char *usagestr =
"Usage: tar2sqfs [OPTIONS...] <sqfsfile>\n"
@@ -64,6 +65,8 @@ static const char *usagestr =
" --no-skip, -s Abort if a tar record cannot be read instead\n"
" of skipping it.\n"
" --no-xattr, -x Do not copy extended attributes from archive.\n"
+" --keep-time, -k Keep the time stamps stored in the archive\n"
+" instead of setting defaults on all files.\n"
" --exportable, -e Generate an export table for NFS support.\n"
" --force, -f Overwrite the output file if it exists.\n"
" --quiet, -q Do not print out progress reports.\n"
@@ -88,6 +91,7 @@ static char *fs_defaults = NULL;
static bool dont_skip = false;
static bool no_xattr = false;
static bool exportable = false;
+static bool keep_time = false;
static void process_args(int argc, char **argv)
{
@@ -137,6 +141,9 @@ static void process_args(int argc, char **argv)
case 'x':
no_xattr = true;
break;
+ case 'k':
+ keep_time = true;
+ break;
case 's':
dont_skip = true;
break;
@@ -234,6 +241,12 @@ static int create_node_and_repack_data(tar_header_decoded_t *hdr, fstree_t *fs,
{
tree_node_t *node;
+ if (!keep_time) {
+ hdr->sb.st_mtime = fs->defaults.st_mtime;
+ hdr->sb.st_ctime = fs->defaults.st_ctime;
+ hdr->sb.st_atime = fs->defaults.st_atime;
+ }
+
node = fstree_add_generic(fs, hdr->name, &hdr->sb, hdr->link_target);
if (node == NULL)
goto fail_errno;