commit ntfs2btrfs for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ntfs2btrfs for openSUSE:Factory checked in at 2023-10-31 20:26:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ntfs2btrfs (Old) and /work/SRC/openSUSE:Factory/.ntfs2btrfs.new.17445 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "ntfs2btrfs" Tue Oct 31 20:26:28 2023 rev:2 rq:1121427 version:20230501 Changes: -------- --- /work/SRC/openSUSE:Factory/ntfs2btrfs/ntfs2btrfs.changes 2023-10-24 20:09:30.395031778 +0200 +++ /work/SRC/openSUSE:Factory/.ntfs2btrfs.new.17445/ntfs2btrfs.changes 2023-10-31 20:26:47.560348610 +0100 @@ -1,0 +2,10 @@ +Tue Oct 24 00:00:00 CEST 2023 - dsterba@suse.cz + +- Update to version 20230501: + * Fixed inline extent items being written out of order (not diagnosed by + btrfs check) + * Fixed metadata items being written with wrong level value (not diagnosed by + btrfs check) + * ADSes with overly-long names now get skipped + +------------------------------------------------------------------- Old: ---- 20220812.tar.gz New: ---- 20230501.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ntfs2btrfs.spec ++++++ --- /var/tmp/diff_new_pack.Z9Kfzv/_old 2023-10-31 20:26:48.064367123 +0100 +++ /var/tmp/diff_new_pack.Z9Kfzv/_new 2023-10-31 20:26:48.064367123 +0100 @@ -1,7 +1,7 @@ # # spec file for package ntfs2btrfs # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,7 +16,7 @@ # -%define tag 20220812 +%define tag 20230501 Name: ntfs2btrfs Version: %{tag} Release: 0 ++++++ 20220812.tar.gz -> 20230501.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/CMakeLists.txt new/ntfs2btrfs-20230501/CMakeLists.txt --- old/ntfs2btrfs-20220812/CMakeLists.txt 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/CMakeLists.txt 2023-05-01 22:59:36.000000000 +0200 @@ -3,7 +3,7 @@ cmake_policy(SET CMP0091 NEW) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") -project(ntfs2btrfs VERSION 20220812) +project(ntfs2btrfs VERSION 20230501) include(GNUInstallDirs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/README.md new/ntfs2btrfs-20230501/README.md --- old/ntfs2btrfs-20220812/README.md 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/README.md 2023-05-01 22:59:36.000000000 +0200 @@ -37,10 +37,12 @@ download the latest Zip file, or use [Scoop](https://github.com/ScoopInstaller/Main/blob/master/bucket/ntfs2btrfs.json). For Linux: -* [Arch](https://aur.archlinux.org/packages/ntfs2btrfs-git) (thanks to [nicman23](https://github.com/nicman23)) +* [Arch](https://aur.archlinux.org/packages/ntfs2btrfs) * [Fedora](https://src.fedoraproject.org/rpms/ntfs2btrfs) (thanks to [Conan-Kudo](https://github.com/Conan-Kudo)) -* [Gentoo ebuild](https://raw.githubusercontent.com/maharmstone/ntfs2btrfs/master/ntfs2btrfs-2...) -* [Debian & Ubuntu](https://sid.ethz.ch/debian/ntfs2btrfs/) (thanks to [alexmyczko](https://github.com/alexmyczko)) +* Gentoo - available as sys-fs/ntfs2btrfs in the guru repository +* [Debian](https://packages.debian.org/ntfs2btrfs) (thanks to [alexmyczko](https://github.com/alexmyczko)) +* [Ubuntu](https://packages.ubuntu.com/ntfs2btrfs) (thanks to [alexmyczko](https://github.com/alexmyczko)) +* [openSUSE](https://build.opensuse.org/package/show/filesystems/ntfs2btrfs) (thanks to David Sterba) For other distributions or operating systems, you will need to compile it yourself - see below. @@ -48,6 +50,11 @@ Changelog --------- +* 20230501 + * Fixed inline extent items being written out of order (not diagnosed by `btrfs check`) + * Fixed metadata items being written with wrong level value (not diagnosed by `btrfs check`) + * ADSes with overly-long names now get skipped + * 20220812 * Added --no-datasum option, to skip calculating checksums * LXSS / WSL metadata is now preserved @@ -93,7 +100,9 @@ On Linux: - cmake . + mkdir build + cd build + cmake .. make You'll also need [libfmt](https://github.com/fmtlib/fmt) installed - it should be diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/ntfs2btrfs-20210923.ebuild new/ntfs2btrfs-20230501/ntfs2btrfs-20210923.ebuild --- old/ntfs2btrfs-20220812/ntfs2btrfs-20210923.ebuild 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/ntfs2btrfs-20210923.ebuild 1970-01-01 01:00:00.000000000 +0100 @@ -1,42 +0,0 @@ -# Copyright 2021 Gentoo Authors -# Distributed under the terms of the GNU General Public License v2 - -EAPI=8 - -inherit cmake - -DESCRIPTION="Conversion tool from NTFS to Btrfs" -HOMEPAGE="https://github.com/maharmstone/ntfs2btrfs" - -if [[ ${PV} = *9999 ]]; then - inherit git-r3 - EGIT_REPO_URI="https://github.com/maharmstone/ntfs2btrfs.git" -else - SRC_URI="https://github.com/maharmstone/${PN}/archive/${PV}.tar.gz -> ${P}.tar.gz" - KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~x86" -fi - -LICENSE="GPL-2" -SLOT="0" -IUSE="+zlib +lzo +zstd" - -DEPEND="dev-libs/libfmt - zlib? ( sys-libs/zlib ) - lzo? ( dev-libs/lzo ) - zstd? ( app-arch/zstd )" -RDEPEND="${DEPEND}" -BDEPEND="" - -src_prepare() { - cmake_src_prepare -} - -src_configure() { - local mycmakeargs=( - -DWITH_ZLIB=$(usex zlib) - -DWITH_LZO=$(usex lzo) - -DWITH_ZSTD=$(usex zstd) - ) - - cmake_src_configure -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/ntfs2btrfs.8.in new/ntfs2btrfs-20230501/ntfs2btrfs.8.in --- old/ntfs2btrfs-20220812/ntfs2btrfs.8.in 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/ntfs2btrfs.8.in 2023-05-01 22:59:36.000000000 +0200 @@ -1,4 +1,4 @@ -.TH NTFS2BTRFS "8" "August 2022" "ntfs2btrfs @PROJECT_VERSION@" "System Administration" +.TH NTFS2BTRFS "8" "May 2023" "ntfs2btrfs @PROJECT_VERSION@" "System Administration" .SH NAME ntfs2btrfs \- convert ntfs filesystem to btrfs filesystem .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/src/btrfs.h new/ntfs2btrfs-20230501/src/btrfs.h --- old/ntfs2btrfs-20220812/src/btrfs.h 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/src/btrfs.h 2023-05-01 22:59:36.000000000 +0200 @@ -16,36 +16,38 @@ #define MAX_LABEL_SIZE 0x100 #define SUBVOL_ROOT_INODE 0x100 -#define TYPE_INODE_ITEM 0x01 -#define TYPE_INODE_REF 0x0C -#define TYPE_INODE_EXTREF 0x0D -#define TYPE_XATTR_ITEM 0x18 -#define TYPE_ORPHAN_INODE 0x30 -#define TYPE_DIR_ITEM 0x54 -#define TYPE_DIR_INDEX 0x60 -#define TYPE_EXTENT_DATA 0x6C -#define TYPE_EXTENT_CSUM 0x80 -#define TYPE_ROOT_ITEM 0x84 -#define TYPE_ROOT_BACKREF 0x90 -#define TYPE_ROOT_REF 0x9C -#define TYPE_EXTENT_ITEM 0xA8 -#define TYPE_METADATA_ITEM 0xA9 -#define TYPE_TREE_BLOCK_REF 0xB0 -#define TYPE_EXTENT_DATA_REF 0xB2 -#define TYPE_EXTENT_REF_V0 0xB4 -#define TYPE_SHARED_BLOCK_REF 0xB6 -#define TYPE_SHARED_DATA_REF 0xB8 -#define TYPE_BLOCK_GROUP_ITEM 0xC0 -#define TYPE_FREE_SPACE_INFO 0xC6 -#define TYPE_FREE_SPACE_EXTENT 0xC7 -#define TYPE_FREE_SPACE_BITMAP 0xC8 -#define TYPE_DEV_EXTENT 0xCC -#define TYPE_DEV_ITEM 0xD8 -#define TYPE_CHUNK_ITEM 0xE4 -#define TYPE_TEMP_ITEM 0xF8 -#define TYPE_DEV_STATS 0xF9 -#define TYPE_SUBVOL_UUID 0xFB -#define TYPE_SUBVOL_REC_UUID 0xFC +enum class btrfs_key_type : uint8_t { + INODE_ITEM = 0x01, + INODE_REF = 0x0C, + INODE_EXTREF = 0x0D, + XATTR_ITEM = 0x18, + ORPHAN_INODE = 0x30, + DIR_ITEM = 0x54, + DIR_INDEX = 0x60, + EXTENT_DATA = 0x6C, + EXTENT_CSUM = 0x80, + ROOT_ITEM = 0x84, + ROOT_BACKREF = 0x90, + ROOT_REF = 0x9C, + EXTENT_ITEM = 0xA8, + METADATA_ITEM = 0xA9, + TREE_BLOCK_REF = 0xB0, + EXTENT_DATA_REF = 0xB2, + EXTENT_REF_V0 = 0xB4, + SHARED_BLOCK_REF = 0xB6, + SHARED_DATA_REF = 0xB8, + BLOCK_GROUP_ITEM = 0xC0, + FREE_SPACE_INFO = 0xC6, + FREE_SPACE_EXTENT = 0xC7, + FREE_SPACE_BITMAP = 0xC8, + DEV_EXTENT = 0xCC, + DEV_ITEM = 0xD8, + CHUNK_ITEM = 0xE4, + TEMP_ITEM = 0xF8, + DEV_STATS = 0xF9, + SUBVOL_UUID = 0xFB, + SUBVOL_REC_UUID = 0xFC +}; #define BTRFS_ROOT_ROOT 1 #define BTRFS_ROOT_EXTENT 2 @@ -141,7 +143,7 @@ typedef struct { uint64_t obj_id; - uint8_t obj_type; + btrfs_key_type obj_type; uint64_t offset; } KEY; @@ -437,8 +439,8 @@ uint32_t count; } SHARED_DATA_REF; -#define FREE_SPACE_EXTENT 1 -#define FREE_SPACE_BITMAP 2 +static const uint8_t FREE_SPACE_EXTENT = 1; +static const uint8_t FREE_SPACE_BITMAP = 2; typedef struct { uint64_t offset; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/src/ntfs.cpp new/ntfs2btrfs-20230501/src/ntfs.cpp --- old/ntfs2btrfs-20220812/src/ntfs.cpp 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/src/ntfs.cpp 2023-05-01 22:59:36.000000000 +0200 @@ -32,7 +32,7 @@ using namespace std; -void process_fixups(MULTI_SECTOR_HEADER* header, uint64_t length, unsigned int sector_size) { +static void process_fixups(MULTI_SECTOR_HEADER* header, uint64_t length, unsigned int sector_size) { uint64_t sectors; uint16_t* seq; uint8_t* ptr; @@ -465,7 +465,7 @@ } static void walk_btree(const index_root& ir, const list<mapping>& mappings, const index_node_header& inh, ntfs& dev, - const function<void(const index_entry&, string_view)>& func, unsigned int level) { + const invocable<const index_entry&, string_view> auto& func, unsigned int level) { auto ent = reinterpret_cast<const index_entry*>((uint8_t*)&inh + inh.first_entry); do { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/src/ntfs.h new/ntfs2btrfs-20230501/src/ntfs.h --- old/ntfs2btrfs-20220812/src/ntfs.h 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/src/ntfs.h 2023-05-01 22:59:36.000000000 +0200 @@ -81,7 +81,7 @@ INDEX_ROOT = 0x90, INDEX_ALLOCATION = 0xA0, BITMAP = 0xB0, - SYMBOLIC_LINK = 0xC0, + REPARSE_POINT = 0xC0, EA_INFORMATION = 0xD0, EA = 0xE0, PROPERTY_SET = 0xF0, @@ -135,8 +135,8 @@ case ntfs_attribute::BITMAP: return fmt::format_to(ctx.out(), "BITMAP"); - case ntfs_attribute::SYMBOLIC_LINK: - return fmt::format_to(ctx.out(), "SYMBOLIC_LINK"); + case ntfs_attribute::REPARSE_POINT: + return fmt::format_to(ctx.out(), "REPARSE_POINT"); case ntfs_attribute::EA_INFORMATION: return fmt::format_to(ctx.out(), "EA_INFORMATION"); @@ -551,4 +551,3 @@ void read_nonresident_mappings(const ATTRIBUTE_RECORD_HEADER& att, std::list<mapping>& mappings, uint32_t cluster_size, uint64_t vdl); void populate_skip_list(ntfs& dev, uint64_t inode, std::list<uint64_t>& skiplist); -void process_fixups(MULTI_SECTOR_HEADER* header, uint64_t length, unsigned int sector_size); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/src/ntfs2btrfs.cpp new/ntfs2btrfs-20230501/src/ntfs2btrfs.cpp --- old/ntfs2btrfs-20220812/src/ntfs2btrfs.cpp 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/src/ntfs2btrfs.cpp 2023-05-01 22:59:36.000000000 +0200 @@ -451,29 +451,29 @@ last_chunk_end = chunks.back().offset - chunk_virt_offset + chunks.back().length; } -static void add_item(root& r, uint64_t obj_id, uint8_t obj_type, uint64_t offset, const buffer_t& buf) { +static void add_item(root& r, uint64_t obj_id, btrfs_key_type obj_type, uint64_t offset, const buffer_t& buf) { auto ret = r.items.emplace(KEY{obj_id, obj_type, offset}, buf); if (!ret.second) - throw formatted_error("Could not insert entry ({:x}, {:x}, {:x}) into root items list.", obj_id, obj_type, offset); + throw formatted_error("Could not insert entry ({:x}, {}, {:x}) into root items list.", obj_id, obj_type, offset); } -static void add_item_move(root& r, uint64_t obj_id, uint8_t obj_type, uint64_t offset, buffer_t& buf) { +static void add_item_move(root& r, uint64_t obj_id, btrfs_key_type obj_type, uint64_t offset, buffer_t& buf) { auto ret = r.items.emplace(KEY{obj_id, obj_type, offset}, buffer_t{}); if (!ret.second) - throw formatted_error("Could not insert entry ({:x}, {:x}, {:x}) into root items list.", obj_id, obj_type, offset); + throw formatted_error("Could not insert entry ({:x}, {}, {:x}) into root items list.", obj_id, obj_type, offset); auto& it = ret.first->second; it.swap(buf); } -static void add_item(root& r, uint64_t obj_id, uint8_t obj_type, uint64_t offset, const void* data, uint16_t len) { +static void add_item(root& r, uint64_t obj_id, btrfs_key_type obj_type, uint64_t offset, const void* data, uint16_t len) { auto ret = r.items.emplace(KEY{obj_id, obj_type, offset}, buffer_t(len)); if (!ret.second) - throw formatted_error("Could not insert entry ({:x}, {:x}, {:x}) into root items list.", obj_id, obj_type, offset); + throw formatted_error("Could not insert entry ({:x}, {}, {:x}) into root items list.", obj_id, obj_type, offset); auto& it = ret.first->second; @@ -500,7 +500,7 @@ ci1s.stripe.offset = c.disk_start; ci1s.stripe.dev_uuid = dev_uuid; - add_item(chunk_root, 0x100, TYPE_CHUNK_ITEM, c.offset, &ci1s, sizeof(ci1s)); + add_item(chunk_root, 0x100, btrfs_key_type::CHUNK_ITEM, c.offset, &ci1s, sizeof(ci1s)); de.chunktree = BTRFS_ROOT_CHUNK; de.objid = 0x100; @@ -508,13 +508,13 @@ de.length = c.length; de.chunktree_uuid = chunk_uuid; - add_item(devtree_root, 1, TYPE_DEV_EXTENT, c.disk_start, &de, sizeof(DEV_EXTENT)); + add_item(devtree_root, 1, btrfs_key_type::DEV_EXTENT, c.disk_start, &de, sizeof(DEV_EXTENT)); bgi.chunk_tree = 0x100; bgi.flags = c.type; // bgi.used gets set in update_extent_root - add_item(extent_root, c.offset, TYPE_BLOCK_GROUP_ITEM, c.length, &bgi, sizeof(BLOCK_GROUP_ITEM)); + add_item(extent_root, c.offset, btrfs_key_type::BLOCK_GROUP_ITEM, c.length, &bgi, sizeof(BLOCK_GROUP_ITEM)); } static uint64_t allocate_metadata(uint64_t r, root& extent_root, uint8_t level) { @@ -526,7 +526,7 @@ mi.extent_item.refcount = 1; mi.extent_item.generation = 1; mi.extent_item.flags = EXTENT_ITEM_TREE_BLOCK; - mi.type = TYPE_TREE_BLOCK_REF; + mi.type = btrfs_key_type::TREE_BLOCK_REF; mi.tbr.offset = r; for (auto& c : chunks) { @@ -544,7 +544,7 @@ c.used += tree_size; - add_item(extent_root, addr, TYPE_METADATA_ITEM, level, &mi, sizeof(metadata_item)); + add_item(extent_root, addr, btrfs_key_type::METADATA_ITEM, level, &mi, sizeof(metadata_item)); return addr; } @@ -594,7 +594,7 @@ c.used = tree_size; - add_item(extent_root, addr, TYPE_METADATA_ITEM, level, &mi, sizeof(metadata_item)); + add_item(extent_root, addr, btrfs_key_type::METADATA_ITEM, level, &mi, sizeof(metadata_item)); return addr; } @@ -713,21 +713,39 @@ th.tree_id = id; th.level = 0; + auto get_address = [this](root& extent_root, uint8_t level) { + uint64_t addr; + + if (!old_addresses.empty()) { + addr = old_addresses.front().first; + + if (level != old_addresses.front().second) { // change metadata level in extent tree + if (auto f = extent_root.items.find(KEY{addr, btrfs_key_type::METADATA_ITEM, old_addresses.front().second}); f != extent_root.items.end()) { + auto d = move(f->second); + + extent_root.items.erase(f); + extent_root.items.emplace(make_pair(KEY{addr, btrfs_key_type::METADATA_ITEM, level}, d)); + } + } + + old_addresses.pop_front(); + } else { + addr = allocate_metadata(id, extent_root, level); + allocations_done = true; + } + + addresses.emplace_back(addr, level); + + return addr; + }; + { auto ln = (leaf_node*)((uint8_t*)buf.data() + sizeof(tree_header)); uint32_t data_off = tree_size - (uint32_t)sizeof(tree_header); for (const auto& i : items) { if (sizeof(leaf_node) + i.second.size() > space_left) { // tree complete, add to list - if (!old_addresses.empty()) { - th.address = old_addresses.front(); - old_addresses.pop_front(); - } else { - th.address = allocate_metadata(id, extent_root, th.level); - allocations_done = true; - } - - addresses.push_back(th.address); + th.address = get_address(extent_root, 0); th.num_items = num_items; calc_tree_hash(th, csum_type); @@ -769,15 +787,7 @@ } if (num_items > 0 || items.size() == 0) { // flush remaining tree - if (!old_addresses.empty()) { - th.address = old_addresses.front(); - old_addresses.pop_front(); - } else { - th.address = allocate_metadata(id, extent_root, th.level); - allocations_done = true; - } - - addresses.push_back(th.address); + th.address = get_address(extent_root, 0); th.num_items = num_items; calc_tree_hash(th, csum_type); @@ -825,15 +835,7 @@ continue; if (sizeof(internal_node) > space_left) { // tree complete, add to list - if (!old_addresses.empty()) { - th.address = old_addresses.front(); - old_addresses.pop_front(); - } else { - th.address = allocate_metadata(id, extent_root, th.level); - allocations_done = true; - } - - addresses.push_back(th.address); + th.address = get_address(extent_root, level); th.num_items = num_items; calc_tree_hash(th, csum_type); @@ -870,15 +872,7 @@ } if (num_items > 0) { // flush remaining tree - if (!old_addresses.empty()) { - th.address = old_addresses.front(); - old_addresses.pop_front(); - } else { - th.address = allocate_metadata(id, extent_root, th.level); - allocations_done = true; - } - - addresses.push_back(th.address); + th.address = get_address(extent_root, level); th.num_items = num_items; calc_tree_hash(th, csum_type); @@ -894,8 +888,6 @@ } while (true); tree_addr = ((tree_header*)trees.back().data())->address; - - // FIXME - make sure level of METADATA_ITEMs is correct } void root::write_trees(ntfs& dev) { @@ -970,7 +962,7 @@ sys_chunk_size = 0; for (const auto& c : chunk_root.items) { - if (c.first.obj_type == TYPE_CHUNK_ITEM) { + if (c.first.obj_type == btrfs_key_type::CHUNK_ITEM) { auto& ci = *(CHUNK_ITEM*)c.second.data(); if (ci.type & BLOCK_FLAG_SYSTEM) { @@ -1018,7 +1010,7 @@ set_volume_label(sb, dev); for (const auto& c : chunk_root.items) { - if (c.first.obj_type == TYPE_DEV_ITEM) { + if (c.first.obj_type == btrfs_key_type::DEV_ITEM) { memcpy(&sb.dev_item, c.second.data(), sizeof(DEV_ITEM)); break; } @@ -1030,7 +1022,7 @@ uint8_t* ptr = sb.sys_chunk_array; for (const auto& c : chunk_root.items) { - if (c.first.obj_type == TYPE_CHUNK_ITEM) { + if (c.first.obj_type == btrfs_key_type::CHUNK_ITEM) { auto& ci = *(CHUNK_ITEM*)c.second.data(); if (ci.type & BLOCK_FLAG_SYSTEM) { @@ -1097,7 +1089,7 @@ di.device_uuid = dev_uuid; di.fs_uuid = fs_uuid; - add_item(chunk_root, 1, TYPE_DEV_ITEM, 1, &di, sizeof(DEV_ITEM)); + add_item(chunk_root, 1, btrfs_key_type::DEV_ITEM, 1, &di, sizeof(DEV_ITEM)); } static void add_to_root_root(const root& r, root& root_root) { @@ -1121,7 +1113,7 @@ // block_number, bytes_used, and root_level are set in update_root_root - add_item(root_root, r.id, TYPE_ROOT_ITEM, 0, &ri, sizeof(ROOT_ITEM)); + add_item(root_root, r.id, btrfs_key_type::ROOT_ITEM, 0, &ri, sizeof(ROOT_ITEM)); } static void update_root_root(root& root_root, enum btrfs_csum_type csum_type) { @@ -1135,7 +1127,7 @@ bool changed = true; for (unsigned int i = 0; i < th.num_items; i++) { - if (ln[i].key.obj_type == TYPE_ROOT_ITEM) { + if (ln[i].key.obj_type == btrfs_key_type::ROOT_ITEM) { auto& ri = *(ROOT_ITEM*)((uint8_t*)t.data() + sizeof(tree_header) + ln[i].offset); for (const auto& r : roots) { @@ -1160,7 +1152,7 @@ memset(ds, 0, sizeof(ds)); - add_item(r, 0, TYPE_DEV_STATS, 1, &ds, sizeof(ds)); + add_item(r, 0, btrfs_key_type::DEV_STATS, 1, &ds, sizeof(ds)); } static BTRFS_UUID generate_uuid(default_random_engine& gen) { @@ -1185,7 +1177,7 @@ bool changed = true; for (unsigned int i = 0; i < th.num_items; i++) { - if (ln[i].key.obj_type == TYPE_BLOCK_GROUP_ITEM) { + if (ln[i].key.obj_type == btrfs_key_type::BLOCK_GROUP_ITEM) { auto& bgi = *(BLOCK_GROUP_ITEM*)((uint8_t*)t.data() + sizeof(tree_header) + ln[i].offset); for (const auto& c : chunks) { @@ -1204,8 +1196,8 @@ } static void add_inode_ref(root& r, uint64_t inode, uint64_t parent, uint64_t index, string_view name) { - if (r.items.count(KEY{inode, TYPE_INODE_REF, parent}) != 0) { // collision, append to the end - auto& old = r.items.at(KEY{inode, TYPE_INODE_REF, parent}); + if (r.items.count(KEY{inode, btrfs_key_type::INODE_REF, parent}) != 0) { // collision, append to the end + auto& old = r.items.at(KEY{inode, btrfs_key_type::INODE_REF, parent}); size_t irlen = offsetof(INODE_REF, name[0]) + name.length(); @@ -1229,7 +1221,7 @@ ir.n = (uint16_t)name.length(); memcpy(ir.name, name.data(), name.length()); - add_item_move(r, inode, TYPE_INODE_REF, parent, buf); + add_item_move(r, inode, btrfs_key_type::INODE_REF, parent, buf); } static void populate_fstree(root& r) { @@ -1243,7 +1235,7 @@ ii.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; ii.sequence = 1; - add_item(r, SUBVOL_ROOT_INODE, TYPE_INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); + add_item(r, SUBVOL_ROOT_INODE, btrfs_key_type::INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); add_inode_ref(r, SUBVOL_ROOT_INODE, SUBVOL_ROOT_INODE, 0, ".."); } @@ -1258,7 +1250,7 @@ auto ln = (leaf_node*)((uint8_t*)t.data() + sizeof(tree_header)); for (unsigned int i = 0; i < th.num_items; i++) { - if (ln[i].key.obj_id == 1 && ln[i].key.obj_type == TYPE_DEV_ITEM && ln[i].key.offset == 1) { + if (ln[i].key.obj_id == 1 && ln[i].key.obj_type == btrfs_key_type::DEV_ITEM && ln[i].key.offset == 1) { auto& di = *(DEV_ITEM*)((uint8_t*)t.data() + sizeof(tree_header) + ln[i].offset); di.bytes_used = 0; @@ -1294,8 +1286,8 @@ rr.n = sizeof(subvol_name) - 1; memcpy(rr.name, subvol_name, sizeof(subvol_name) - 1); - add_item(root_root, BTRFS_ROOT_FSTREE, TYPE_ROOT_REF, image_subvol_id, buf); - add_item_move(root_root, image_subvol_id, TYPE_ROOT_BACKREF, BTRFS_ROOT_FSTREE, buf); + add_item(root_root, BTRFS_ROOT_FSTREE, btrfs_key_type::ROOT_REF, image_subvol_id, buf); + add_item_move(root_root, image_subvol_id, btrfs_key_type::ROOT_BACKREF, BTRFS_ROOT_FSTREE, buf); } // add DIR_ITEM and DIR_INDEX @@ -1305,7 +1297,7 @@ auto& di = *(DIR_ITEM*)buf.data(); di.key.obj_id = image_subvol_id; - di.key.obj_type = TYPE_ROOT_ITEM; + di.key.obj_type = btrfs_key_type::ROOT_ITEM; di.key.offset = 0xffffffffffffffff; di.transid = 1; di.m = 0; @@ -1315,8 +1307,8 @@ auto hash = calc_crc32c(0xfffffffe, (const uint8_t*)subvol_name, sizeof(subvol_name) - 1); - add_item(fstree_root, SUBVOL_ROOT_INODE, TYPE_DIR_ITEM, hash, buf); - add_item_move(fstree_root, SUBVOL_ROOT_INODE, TYPE_DIR_INDEX, 2, buf); + add_item(fstree_root, SUBVOL_ROOT_INODE, btrfs_key_type::DIR_ITEM, hash, buf); + add_item_move(fstree_root, SUBVOL_ROOT_INODE, btrfs_key_type::DIR_INDEX, 2, buf); } // increase st_size in parent dir @@ -1361,7 +1353,7 @@ } } - add_item(r, inode, TYPE_INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); + add_item(r, inode, btrfs_key_type::INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); // add DIR_ITEM and DIR_INDEX @@ -1370,7 +1362,7 @@ auto& di = *(DIR_ITEM*)buf.data(); di.key.obj_id = inode; - di.key.obj_type = TYPE_INODE_ITEM; + di.key.obj_type = btrfs_key_type::INODE_ITEM; di.key.offset = 0; di.transid = 1; di.m = 0; @@ -1380,8 +1372,8 @@ auto hash = calc_crc32c(0xfffffffe, (const uint8_t*)image_filename, sizeof(image_filename) - 1); - add_item(r, SUBVOL_ROOT_INODE, TYPE_DIR_ITEM, hash, buf); - add_item_move(r, SUBVOL_ROOT_INODE, TYPE_DIR_INDEX, 2, buf); + add_item(r, SUBVOL_ROOT_INODE, btrfs_key_type::DIR_ITEM, hash, buf); + add_item_move(r, SUBVOL_ROOT_INODE, btrfs_key_type::DIR_INDEX, 2, buf); } // add INODE_REF @@ -1391,7 +1383,7 @@ // increase st_size in parent dir for (auto& it : r.items) { - if (it.first.obj_id == SUBVOL_ROOT_INODE && it.first.obj_type == TYPE_INODE_ITEM) { + if (it.first.obj_id == SUBVOL_ROOT_INODE && it.first.obj_type == btrfs_key_type::INODE_ITEM) { auto& ii2 = *(INODE_ITEM*)it.second.data(); ii2.st_size += (sizeof(image_filename) - 1) * 2; @@ -1434,7 +1426,7 @@ ed2.offset = 0; - add_item(r, inode, TYPE_EXTENT_DATA, addr, buf); + add_item(r, inode, btrfs_key_type::EXTENT_DATA, addr, buf); data_size += ed2.size; } @@ -1690,7 +1682,7 @@ auto& di = *(DIR_ITEM*)buf.data(); di.key.obj_id = inode; - di.key.obj_type = TYPE_INODE_ITEM; + di.key.obj_type = btrfs_key_type::INODE_ITEM; di.key.offset = 0; di.transid = 1; di.m = 0; @@ -1700,10 +1692,10 @@ auto hash = calc_crc32c(0xfffffffe, (const uint8_t*)name.data(), (uint32_t)name.length()); - if (r.items.count(KEY{dir, TYPE_DIR_ITEM, hash}) == 0) - add_item(r, dir, TYPE_DIR_ITEM, hash, buf); + if (r.items.count(KEY{dir, btrfs_key_type::DIR_ITEM, hash}) == 0) + add_item(r, dir, btrfs_key_type::DIR_ITEM, hash, buf); else { // hash collision - auto& ent = r.items.at(KEY{dir, TYPE_DIR_ITEM, hash}); + auto& ent = r.items.at(KEY{dir, btrfs_key_type::DIR_ITEM, hash}); if (!ent.empty()) { ent.resize(ent.size() + buf.size()); @@ -1714,7 +1706,7 @@ } } - add_item_move(r, dir, TYPE_DIR_INDEX, seq, buf); + add_item_move(r, dir, btrfs_key_type::DIR_INDEX, seq, buf); } // add INODE_REF @@ -1978,7 +1970,7 @@ auto& di = *(DIR_ITEM*)buf.data(); di.key.obj_id = di.key.offset = 0; - di.key.obj_type = 0; + di.key.obj_type = (btrfs_key_type)0; di.transid = 1; di.m = (uint16_t)data.size(); di.n = (uint16_t)name.size(); @@ -1986,7 +1978,7 @@ memcpy(di.name, name.data(), name.size()); memcpy(di.name + name.size(), data.data(), data.size()); - add_item_move(r, inode, TYPE_XATTR_ITEM, hash, buf); + add_item_move(r, inode, btrfs_key_type::XATTR_ITEM, hash, buf); } static void clear_line() { @@ -2181,6 +2173,11 @@ auto name2 = xattr_prefix + ads_name; + if (name2.size() > 255) { + add_warning("Skipping ADS :{} as name too long", ads_name); + break; + } + uint32_t hash = calc_crc32c(0xfffffffe, (const uint8_t*)name2.data(), (uint32_t)name2.length()); if (att.FormCode == NTFS_ATTRIBUTE_FORM::RESIDENT_FORM && (ads_name != "WofCompressedData" || !processed_wof_data)) { @@ -2300,12 +2297,25 @@ break; } - case ntfs_attribute::SYMBOLIC_LINK: { - if (att.FormCode == NTFS_ATTRIBUTE_FORM::NONRESIDENT_FORM) - throw formatted_error("Error - SYMBOLIC_LINK is non-resident"); // FIXME - can this happen? + case ntfs_attribute::REPARSE_POINT: { + if (att.FormCode == NTFS_ATTRIBUTE_FORM::RESIDENT_FORM) { + reparse_point.resize(res_data.size()); + memcpy(reparse_point.data(), res_data.data(), res_data.size()); + } else { + list<mapping> rp_mappings; + + read_nonresident_mappings(att, rp_mappings, cluster_size, att.Form.Nonresident.ValidDataLength); - reparse_point.resize(res_data.size()); - memcpy(reparse_point.data(), res_data.data(), res_data.size()); + reparse_point.resize((size_t)sector_align(att.Form.Nonresident.FileSize, cluster_size)); + memset(reparse_point.data(), 0, reparse_point.size()); + + for (const auto& m : rp_mappings) { + dev.seek(m.lcn * cluster_size); + dev.read(reparse_point.data() + (m.vcn * cluster_size), (size_t)(m.length * cluster_size)); + } + + reparse_point.resize((size_t)att.Form.Nonresident.FileSize); + } symlink.clear(); @@ -2607,12 +2617,37 @@ memcpy(v2.data(), v.data() + lxea.length(), v2.size()); xattrs.emplace(EA_CAP, make_pair(EA_CAP_HASH, v2)); - } else if (n != "$KERNEL.PURGE.APPXFICACHE" && n != "$KERNEL.PURGE.ESBCACHE" && n != "$CI.CATALOGHINT" && - n != "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.DATABASE" && n != "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.DATABASEEX1" && - n != "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.EPOCHEA" && n != "APPLICENSING" && - n != "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.COMMON" && n != "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.COMMONEX" && - n != "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.COMMONEX_1" && n != "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.USER") { - add_warning("Unrecognized EA {}", ea.first); + } else { + static const string_view recognized_eas[] = { + "$KERNEL.PURGE.APPXFICACHE", + "$KERNEL.PURGE.ESBCACHE", + "$CI.CATALOGHINT", + "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.DATABASE", + "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.DATABASEEX1", + "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.EPOCHEA", + "APPLICENSING", + "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.COMMON", + "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.COMMONEX", + "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.COMMONEX_1" + "C8A05BC0-3FA8-49E9-8148-61EE14A67687.CSC.USER", + "$KERNEL.PURGE.SMARTLOCKER.VALID", + "$KERNEL.SMARTLOCKER.ORIGINCLAIM", + "$KERNEL.PURGE.APPID.HASHINFO", + "$KERNEL.SMARTLOCKER.HASH", + "$KERNEL.PURGE.CIPCACHE", + "$KERNEL.SMARTLOCKER.UNINSTALLSTRINGS" + }; + + bool found = false; + for (const auto& r : recognized_eas) { + if (r == n) { + found = true; + break; + } + } + + if (!found) + add_warning("Unrecognized EA {}", n); } } @@ -2796,7 +2831,7 @@ rph->ReparseDataLength, sizeof(wof_external_info) + sizeof(file_provider_external_info_v0)); } - auto fpei = *(file_provider_external_info_v0*)&wofei[1]; + const auto& fpei = *(file_provider_external_info_v0*)&wofei[1]; if (fpei.Version != FILE_PROVIDER_CURRENT_VERSION) { throw formatted_error("rph->FILE_PROVIDER_EXTERNAL_INFO_V0 Version was {}, expected {}.", @@ -2944,7 +2979,7 @@ ed2.address = (m.lcn * dev.boot_sector->BytesPerSector * dev.boot_sector->SectorsPerCluster) + chunk_virt_offset; ed2.offset = 0; - add_item(r, inode, TYPE_EXTENT_DATA, m.vcn * dev.boot_sector->BytesPerSector * dev.boot_sector->SectorsPerCluster, buf); + add_item(r, inode, btrfs_key_type::EXTENT_DATA, m.vcn * dev.boot_sector->BytesPerSector * dev.boot_sector->SectorsPerCluster, buf); } } } else if (!inline_data.empty()) { @@ -3050,7 +3085,7 @@ else dev.write(compdata.data(), compdata.size()); - add_item(r, inode, TYPE_EXTENT_DATA, pos, buf); + add_item(r, inode, btrfs_key_type::EXTENT_DATA, pos, buf); lcn = (ed2.address - chunk_virt_offset) / cluster_size; cl = ed2.size / cluster_size; @@ -3099,13 +3134,13 @@ if (vdl < inline_data.size()) memset(ed.data + vdl, 0, (size_t)(inline_data.size() - vdl)); - add_item_move(r, inode, TYPE_EXTENT_DATA, 0, buf); + add_item_move(r, inode, btrfs_key_type::EXTENT_DATA, 0, buf); ii.st_blocks = inline_data.size(); } } - add_item(r, inode, TYPE_INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); + add_item(r, inode, btrfs_key_type::INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); if (item_type == btrfs_inode_type::unknown) { if (is_dir) @@ -3207,6 +3242,16 @@ fmt::print("\n"); } +static uint64_t get_extent_data_ref_hash2(uint64_t root, uint64_t objid, uint64_t offset) { + uint32_t high_crc = 0xffffffff, low_crc = 0xffffffff; + + high_crc = calc_crc32c(high_crc, (uint8_t*)&root, sizeof(uint64_t)); + low_crc = calc_crc32c(low_crc, (uint8_t*)&objid, sizeof(uint64_t)); + low_crc = calc_crc32c(low_crc, (uint8_t*)&offset, sizeof(uint64_t)); + + return ((uint64_t)high_crc << 31) ^ (uint64_t)low_crc; +} + static void create_data_extent_items(root& extent_root, const runs_t& runs, uint32_t cluster_size, uint64_t image_subvol_id, uint64_t image_inode) { for (const auto& rs : runs) { @@ -3232,13 +3277,13 @@ di.extent_item.refcount = 1; di.extent_item.generation = 1; di.extent_item.flags = EXTENT_ITEM_DATA; - di.type = TYPE_EXTENT_DATA_REF; + di.type = btrfs_key_type::EXTENT_DATA_REF; di.edr.root = image_subvol_id; di.edr.objid = image_inode; di.edr.count = 1; di.edr.offset = img_addr; - add_item(extent_root, (r.offset * cluster_size) + chunk_virt_offset, TYPE_EXTENT_ITEM, r.length * cluster_size, + add_item(extent_root, (r.offset * cluster_size) + chunk_virt_offset, btrfs_key_type::EXTENT_ITEM, r.length * cluster_size, &di, sizeof(data_item)); } else if (r.not_in_img) { data_item di; @@ -3246,32 +3291,46 @@ di.extent_item.refcount = 1; di.extent_item.generation = 1; di.extent_item.flags = EXTENT_ITEM_DATA; - di.type = TYPE_EXTENT_DATA_REF; + di.type = btrfs_key_type::EXTENT_DATA_REF; di.edr.root = BTRFS_ROOT_FSTREE; di.edr.objid = r.inode; di.edr.count = 1; di.edr.offset = r.file_offset * cluster_size; - add_item(extent_root, (r.offset * cluster_size) + chunk_virt_offset, TYPE_EXTENT_ITEM, r.length * cluster_size, + add_item(extent_root, (r.offset * cluster_size) + chunk_virt_offset, btrfs_key_type::EXTENT_ITEM, r.length * cluster_size, &di, sizeof(data_item)); } else { data_item2 di2; + EXTENT_DATA_REF* e1; + EXTENT_DATA_REF* e2; di2.extent_item.refcount = 2; di2.extent_item.generation = 1; di2.extent_item.flags = EXTENT_ITEM_DATA; - di2.type1 = TYPE_EXTENT_DATA_REF; - di2.edr1.root = image_subvol_id; - di2.edr1.objid = image_inode; - di2.edr1.count = 1; - di2.edr1.offset = img_addr; - di2.type2 = TYPE_EXTENT_DATA_REF; - di2.edr2.root = BTRFS_ROOT_FSTREE; - di2.edr2.objid = r.inode; - di2.edr2.count = 1; - di2.edr2.offset = r.file_offset * cluster_size; + di2.type1 = btrfs_key_type::EXTENT_DATA_REF; + di2.type2 = btrfs_key_type::EXTENT_DATA_REF; + + auto hash1 = get_extent_data_ref_hash2(image_subvol_id, image_inode, img_addr); + auto hash2 = get_extent_data_ref_hash2(BTRFS_ROOT_FSTREE, r.inode, r.file_offset * cluster_size); + + if (hash2 > hash1) { + e1 = &di2.edr2; + e2 = &di2.edr1; + } else { + e1 = &di2.edr1; + e2 = &di2.edr2; + } + + e1->root = image_subvol_id; + e1->objid = image_inode; + e1->count = 1; + e1->offset = img_addr; + e2->root = BTRFS_ROOT_FSTREE; + e2->objid = r.inode; + e2->count = 1; + e2->offset = r.file_offset * cluster_size; - add_item(extent_root, (r.offset * cluster_size) + chunk_virt_offset, TYPE_EXTENT_ITEM, r.length * cluster_size, + add_item(extent_root, (r.offset * cluster_size) + chunk_virt_offset, btrfs_key_type::EXTENT_ITEM, r.length * cluster_size, &di2, sizeof(data_item2)); } } @@ -3476,7 +3535,7 @@ } } - add_item(csum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, (r.offset * cluster_size) + chunk_virt_offset, &csums[0], (uint16_t)(r.length * cluster_size * csum_size / sector_size)); + add_item(csum_root, EXTENT_CSUM_ID, btrfs_key_type::EXTENT_CSUM, (r.offset * cluster_size) + chunk_virt_offset, &csums[0], (uint16_t)(r.length * cluster_size * csum_size / sector_size)); } fmt::print("\n"); @@ -3616,7 +3675,7 @@ ii.st_nlink = 1; ii.st_mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - add_item(root_root, BTRFS_ROOT_TREEDIR, TYPE_INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); + add_item(root_root, BTRFS_ROOT_TREEDIR, btrfs_key_type::INODE_ITEM, 0, &ii, sizeof(INODE_ITEM)); add_inode_ref(root_root, BTRFS_ROOT_TREEDIR, BTRFS_ROOT_TREEDIR, 0, ".."); @@ -3624,7 +3683,7 @@ auto& di = *(DIR_ITEM*)buf.data(); di.key.obj_id = BTRFS_ROOT_FSTREE; - di.key.obj_type = TYPE_ROOT_ITEM; + di.key.obj_type = btrfs_key_type::ROOT_ITEM; di.key.offset = 0xffffffffffffffff; di.transid = 0; di.m = 0; @@ -3632,17 +3691,17 @@ di.type = btrfs_inode_type::directory; memcpy(di.name, default_subvol, sizeof(default_subvol) - 1); - add_item_move(root_root, BTRFS_ROOT_TREEDIR, TYPE_DIR_ITEM, default_hash, buf); + add_item_move(root_root, BTRFS_ROOT_TREEDIR, btrfs_key_type::DIR_ITEM, default_hash, buf); } static void add_subvol_uuid(root& r) { - add_item(r, *(uint64_t*)&subvol_uuid, TYPE_SUBVOL_UUID, *(uint64_t*)&subvol_uuid.uuid[sizeof(uint64_t)], + add_item(r, *(uint64_t*)&subvol_uuid, btrfs_key_type::SUBVOL_UUID, *(uint64_t*)&subvol_uuid.uuid[sizeof(uint64_t)], &image_subvol_id, sizeof(image_subvol_id)); } static void update_dir_sizes(root& r) { for (auto& it : r.items) { - if (it.first.obj_type == TYPE_INODE_ITEM && r.dir_size.count(it.first.obj_id) != 0) { + if (it.first.obj_type == btrfs_key_type::INODE_ITEM && r.dir_size.count(it.first.obj_id) != 0) { auto& ii = *(INODE_ITEM*)it.second.data(); // FIXME - would it speed things up if we removed the entry from dir_size map here? @@ -3795,7 +3854,7 @@ for (auto& r : roots) { if (r.id == BTRFS_ROOT_EXTENT || r.id == BTRFS_ROOT_CHUNK || r.id == BTRFS_ROOT_DEVTREE) { - r.old_addresses = r.addresses; + r.old_addresses.swap(r.addresses); r.addresses.clear(); // FIXME - unallocate metadata and changed used value in chunks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/src/ntfs2btrfs.h new/ntfs2btrfs-20230501/src/ntfs2btrfs.h --- old/ntfs2btrfs-20220812/src/ntfs2btrfs.h 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/src/ntfs2btrfs.h 2023-05-01 22:59:36.000000000 +0200 @@ -205,7 +205,7 @@ uint64_t tree_addr; uint8_t level; uint64_t metadata_size = 0; - std::list<uint64_t> addresses, old_addresses; + std::list<std::pair<uint64_t, uint8_t>> addresses, old_addresses; bool allocations_done = false; bool readonly = false; std::map<uint64_t, uint64_t> dir_seqs; @@ -284,21 +284,21 @@ typedef struct { EXTENT_ITEM extent_item; - uint8_t type; + btrfs_key_type type; TREE_BLOCK_REF tbr; } metadata_item; typedef struct { EXTENT_ITEM extent_item; - uint8_t type; + btrfs_key_type type; EXTENT_DATA_REF edr; } data_item; typedef struct { EXTENT_ITEM extent_item; - uint8_t type1; + btrfs_key_type type1; EXTENT_DATA_REF edr1; - uint8_t type2; + btrfs_key_type type2; EXTENT_DATA_REF edr2; } data_item2; @@ -316,6 +316,86 @@ return ((v + s - 1) / s) * s; } +template<> +struct fmt::formatter<enum btrfs_key_type> { + constexpr auto parse(format_parse_context& ctx) { + auto it = ctx.begin(); + + if (it != ctx.end() && *it != '}') + throw format_error("invalid format"); + + return it; + } + + template<typename format_context> + auto format(enum btrfs_key_type k, format_context& ctx) const { + switch (k) { + case btrfs_key_type::INODE_ITEM: + return fmt::format_to(ctx.out(), "INODE_ITEM"); + case btrfs_key_type::INODE_REF: + return fmt::format_to(ctx.out(), "INODE_REF"); + case btrfs_key_type::INODE_EXTREF: + return fmt::format_to(ctx.out(), "INODE_EXTREF"); + case btrfs_key_type::XATTR_ITEM: + return fmt::format_to(ctx.out(), "XATTR_ITEM"); + case btrfs_key_type::ORPHAN_INODE: + return fmt::format_to(ctx.out(), "ORPHAN_INODE"); + case btrfs_key_type::DIR_ITEM: + return fmt::format_to(ctx.out(), "DIR_ITEM"); + case btrfs_key_type::DIR_INDEX: + return fmt::format_to(ctx.out(), "DIR_INDEX"); + case btrfs_key_type::EXTENT_DATA: + return fmt::format_to(ctx.out(), "EXTENT_DATA"); + case btrfs_key_type::EXTENT_CSUM: + return fmt::format_to(ctx.out(), "EXTENT_CSUM"); + case btrfs_key_type::ROOT_ITEM: + return fmt::format_to(ctx.out(), "ROOT_ITEM"); + case btrfs_key_type::ROOT_BACKREF: + return fmt::format_to(ctx.out(), "ROOT_BACKREF"); + case btrfs_key_type::ROOT_REF: + return fmt::format_to(ctx.out(), "ROOT_REF"); + case btrfs_key_type::EXTENT_ITEM: + return fmt::format_to(ctx.out(), "EXTENT_ITEM"); + case btrfs_key_type::METADATA_ITEM: + return fmt::format_to(ctx.out(), "METADATA_ITEM"); + case btrfs_key_type::TREE_BLOCK_REF: + return fmt::format_to(ctx.out(), "TREE_BLOCK_REF"); + case btrfs_key_type::EXTENT_DATA_REF: + return fmt::format_to(ctx.out(), "EXTENT_DATA_REF"); + case btrfs_key_type::EXTENT_REF_V0: + return fmt::format_to(ctx.out(), "EXTENT_REF_V0"); + case btrfs_key_type::SHARED_BLOCK_REF: + return fmt::format_to(ctx.out(), "SHARED_BLOCK_REF"); + case btrfs_key_type::SHARED_DATA_REF: + return fmt::format_to(ctx.out(), "SHARED_DATA_REF"); + case btrfs_key_type::BLOCK_GROUP_ITEM: + return fmt::format_to(ctx.out(), "BLOCK_GROUP_ITEM"); + case btrfs_key_type::FREE_SPACE_INFO: + return fmt::format_to(ctx.out(), "FREE_SPACE_INFO"); + case btrfs_key_type::FREE_SPACE_EXTENT: + return fmt::format_to(ctx.out(), "FREE_SPACE_EXTENT"); + case btrfs_key_type::FREE_SPACE_BITMAP: + return fmt::format_to(ctx.out(), "FREE_SPACE_BITMAP"); + case btrfs_key_type::DEV_EXTENT: + return fmt::format_to(ctx.out(), "DEV_EXTENT"); + case btrfs_key_type::DEV_ITEM: + return fmt::format_to(ctx.out(), "DEV_ITEM"); + case btrfs_key_type::CHUNK_ITEM: + return fmt::format_to(ctx.out(), "CHUNK_ITEM"); + case btrfs_key_type::TEMP_ITEM: + return fmt::format_to(ctx.out(), "TEMP_ITEM"); + case btrfs_key_type::DEV_STATS: + return fmt::format_to(ctx.out(), "DEV_STATS"); + case btrfs_key_type::SUBVOL_UUID: + return fmt::format_to(ctx.out(), "SUBVOL_UUID"); + case btrfs_key_type::SUBVOL_REC_UUID: + return fmt::format_to(ctx.out(), "SUBVOL_REC_UUID"); + default: + return fmt::format_to(ctx.out(), "{:x}", (uint8_t)k); + } + } +}; + static const uint64_t image_subvol_id = 0x100; static const char image_filename[] = "ntfs.img"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ntfs2btrfs-20220812/src/rollback.cpp new/ntfs2btrfs-20230501/src/rollback.cpp --- old/ntfs2btrfs-20220812/src/rollback.cpp 2022-08-12 02:07:00.000000000 +0200 +++ new/ntfs2btrfs-20230501/src/rollback.cpp 2023-05-01 22:59:36.000000000 +0200 @@ -304,7 +304,7 @@ do { auto& key = *(KEY*)ptr; - if (key.obj_type != TYPE_CHUNK_ITEM) + if (key.obj_type != btrfs_key_type::CHUNK_ITEM) break; auto& ci = *(CHUNK_ITEM*)(ptr + sizeof(key)); @@ -336,7 +336,7 @@ chunks_t chunks2; walk_tree(sb.chunk_tree_addr, [&](const KEY& key, string_view data) { - if (key.obj_type != TYPE_CHUNK_ITEM) + if (key.obj_type != btrfs_key_type::CHUNK_ITEM) return true; chunks2.emplace(key.offset, buffer_t{data.data(), data.data() + data.size()}); @@ -351,7 +351,7 @@ optional<uint64_t> ret; walk_tree(sb.root_tree_addr, [&](const KEY& key, string_view data) { - if (key.obj_id != root || key.obj_type != TYPE_ROOT_ITEM) + if (key.obj_id != root || key.obj_type != btrfs_key_type::ROOT_ITEM) return true; const auto& ri = *(ROOT_ITEM*)data.data(); @@ -378,17 +378,17 @@ uint32_t hash = calc_crc32c(0xfffffffe, (const uint8_t*)image_filename, sizeof(image_filename) - 1); b.walk_tree(img_root_addr, [&](const KEY& key, string_view data) { - if (key.obj_id > SUBVOL_ROOT_INODE || (key.obj_id == SUBVOL_ROOT_INODE && key.obj_type > TYPE_DIR_ITEM)) + if (key.obj_id > SUBVOL_ROOT_INODE || (key.obj_id == SUBVOL_ROOT_INODE && key.obj_type > btrfs_key_type::DIR_ITEM)) return false; - if (key.obj_id == SUBVOL_ROOT_INODE && key.obj_type == TYPE_DIR_ITEM && key.offset == hash) { + if (key.obj_id == SUBVOL_ROOT_INODE && key.obj_type == btrfs_key_type::DIR_ITEM && key.offset == hash) { auto& di = *(DIR_ITEM*)data.data(); // FIXME - handle hash collisions if (di.n == sizeof(image_filename) - 1 && !memcmp(di.name, image_filename, di.n)) { - if (di.key.obj_type != TYPE_INODE_ITEM) - throw formatted_error("DIR_ITEM for {} pointed to object type {:x}, expected TYPE_INODE_ITEM.", + if (di.key.obj_type != btrfs_key_type::INODE_ITEM) + throw formatted_error("DIR_ITEM for {} pointed to object type {}, expected INODE_ITEM.", string_view(di.name, di.n), di.key.obj_type); inode = di.key.obj_id; @@ -408,10 +408,10 @@ map<uint64_t, pair<uint64_t, uint64_t>> extents; b.walk_tree(img_root_addr, [&](const KEY& key, string_view data) { - if (key.obj_id > inode || (key.obj_id == inode && key.obj_type > TYPE_EXTENT_DATA)) + if (key.obj_id > inode || (key.obj_id == inode && key.obj_type > btrfs_key_type::EXTENT_DATA)) return false; - if (key.obj_id != inode || key.obj_type != TYPE_EXTENT_DATA) + if (key.obj_id != inode || key.obj_type != btrfs_key_type::EXTENT_DATA) return true; const auto& ed = *(EXTENT_DATA*)data.data();
participants (1)
-
Source-Sync