diff --git a/tools/fakefs.c b/tools/fakefs.c index 118ec8d78d..f24694cc3d 100644 --- a/tools/fakefs.c +++ b/tools/fakefs.c @@ -188,6 +188,20 @@ bool fakefs_import(const char *archive_path, const char *fs, struct fakefsify_er if (fd != -1) close(fd); + struct timespec times[2] = { + // for utimes, atime is first, mtime is second + {.tv_sec = archive_entry_atime(entry), .tv_nsec = archive_entry_atime_nsec(entry)}, + {.tv_sec = archive_entry_mtime(entry), .tv_nsec = archive_entry_mtime_nsec(entry)}, + // utimes cannot set ctime + }; + if (!archive_entry_atime_is_set(entry)) + times[0].tv_nsec = UTIME_OMIT; + if (!archive_entry_mtime_is_set(entry)) + times[1].tv_nsec = UTIME_OMIT; + err = utimensat(root_fd, fix_path(entry_path), times, 0); + if (err < 0) + POSIX_ERR(); + struct ish_stat stat = { .mode = (uint32_t) archive_entry_mode(entry), .uid = (uint32_t) archive_entry_uid(entry), @@ -231,7 +245,7 @@ bool fakefs_export(const char *fs, const char *archive_path, struct fakefsify_er if (archive == NULL) ARCHIVE_ERR(archive); archive_write_add_filter_gzip(archive); - archive_write_set_format_pax_restricted(archive); + archive_write_set_format_pax(archive); if (archive_write_open_filename(archive, archive_path) != ARCHIVE_OK) ARCHIVE_ERR(archive); @@ -256,7 +270,7 @@ bool fakefs_export(const char *fs, const char *archive_path, struct fakefsify_er int64_t paths_done = 0; struct archive_entry_linkresolver *linkresolver = archive_entry_linkresolver_new(); - archive_entry_linkresolver_set_strategy(linkresolver, ARCHIVE_FORMAT_TAR_PAX_RESTRICTED); + archive_entry_linkresolver_set_strategy(linkresolver, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); sqlite3_stmt *query = PREPARE("select path, inode, stat from paths, stats using (inode)"); while (STEP(query)) { @@ -289,6 +303,14 @@ bool fakefs_export(const char *fs, const char *archive_path, struct fakefsify_er POSIX_ERR(); } archive_entry_set_size(entry, real_stat.st_size); +#if __APPLE__ +#define TIMESPEC(x) st_##x##timespec +#elif __linux__ +#define TIMESPEC(x) st_##x##tim +#endif + archive_entry_set_atime(entry, real_stat.st_atime, real_stat.TIMESPEC(a).tv_nsec); + archive_entry_set_mtime(entry, real_stat.st_mtime, real_stat.TIMESPEC(m).tv_nsec); + archive_entry_set_ctime(entry, real_stat.st_ctime, real_stat.TIMESPEC(c).tv_nsec); int fd = -1; S_IFMT;