From 12d039fcc78cb917176ea3080a6a94c883cf9e3f Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Tue, 5 Sep 2023 20:25:14 -0500 Subject: image: Tar backend: Fix ups * Use portably. * Create the target directory if it doesn't exist. * Fix symlink detection bug that could cause target mtab to halt image creation. --- image/backends/tar.cc | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'image/backends') diff --git a/image/backends/tar.cc b/image/backends/tar.cc index efd38e5..d9c2248 100644 --- a/image/backends/tar.cc +++ b/image/backends/tar.cc @@ -48,6 +48,7 @@ public: int prepare() override { int res; + error_code ec; a = archive_write_new(); archive_write_set_format_pax_restricted(a); @@ -66,6 +67,20 @@ public: break; } + output_info("tar backend", "creating directory tree"); + fs::create_directory(this->ir_dir, ec); + if(ec && ec.value() != EEXIST) { + output_error("tar backend", "could not create IR directory", + ec.message()); + return 1; + } + fs::create_directory(this->ir_dir + "/target", ec); + if(ec && ec.value() != EEXIST) { + output_error("tar backend", "could not create target directory", + ec.message()); + return 1; + } + res = archive_write_open_filename(a, this->out_path.c_str()); if(res < ARCHIVE_OK) { if(res < ARCHIVE_WARN) { @@ -93,17 +108,18 @@ public: for(const auto& dent : fs::recursive_directory_iterator(target, ec)) { fs::path relpath = dent.path().lexically_relative(target); + std::string pathstr(dent.path().native()); #define OUTPUT_FAILURE(x) \ - output_error("tar backend", "failed to " x " '" + std::string(dent.path()) + "'",\ + output_error("tar backend", "failed to " x " '" + pathstr + "'",\ strerror(errno)); - r = lstat(dent.path().c_str(), &s); + r = lstat(pathstr.c_str(), &s); if(r == -1) { OUTPUT_FAILURE("stat") code = -1; goto ret; } archive_entry_copy_stat(entry, &s); - if(dent.is_symlink()) { + if(fs::is_symlink(dent)) { archive_entry_set_filetype(entry, AE_IFLNK); fs::path resolved = fs::read_symlink(dent.path(), ec); if(ec) { @@ -112,31 +128,31 @@ public: code = -1; goto ret; } - const auto r_path = resolved.u8string(); + const auto r_path = resolved.native(); archive_entry_update_symlink_utf8(entry, r_path.c_str()); } - archive_entry_update_pathname_utf8(entry, relpath.u8string().c_str()); + archive_entry_update_pathname_utf8(entry, relpath.native().c_str()); if(archive_write_header(this->a, entry) != ARCHIVE_OK) { output_error("tar backend", archive_error_string(a)); code = -1; goto ret; } - if(dent.is_regular_file() && dent.file_size() > 0) { - fd = open(dent.path().c_str(), O_RDONLY); + if(fs::is_regular_file(dent) && !fs::is_symlink(dent) && + s.st_size > 0) { + fd = open(pathstr.c_str(), O_RDONLY); if(fd == -1) { OUTPUT_FAILURE("open") code = -1; goto ret; } - buff = mmap(NULL, dent.file_size(), PROT_READ, MAP_SHARED, - fd, 0); + buff = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); if(buff == MAP_FAILED) { OUTPUT_FAILURE("map") close(fd); code = -1; goto ret; } - archive_write_data(this->a, buff, dent.file_size()); + archive_write_data(this->a, buff, s.st_size); close(fd); } archive_write_finish_entry(this->a); -- cgit v1.2.3-70-g09d2