bup(基于Git的图像备份)如何计算存储对象的哈希值

3

有一个备份程序bup (https://github.com/bup/bup),它基于一些来自版本控制系统git的想法和一些功能,用于紧凑存储虚拟机镜像。

bup中有一个子命令bup ls,当传递-s选项时可以显示存储在备份内部的一些类似sha1的哈希值(十六进制相同长度)(在man bup-ls中只有"-s,--hash:为每个文件 / 目录显示哈希值")。但是这个类似sha1的哈希值不等于原始文件的sha1sum输出。

原始的git通过在数据前加上“blob NNN \ 0”字符串计算数据的sha1哈希值,其中NNN以十进制方式表示对象大小(字节),根据How does git compute file hashes?https://dev59.com/BGw05IYBdhLWcg3weBpF#28881708/

我测试了前缀'blob NNN \ 0',仍然无法获得相同的sha1哈希值。

bup中用于文件计算哈希值的方法是什么?它是类似Merkle树的线性sha1还是某种树变量?目录的哈希值是什么?

bup命令的源代码在https://github.com/bup/bup/blob/master/lib/bup/ls.py中,哈希值以十六进制打印,但是哈希值是在哪里生成的呢?

def node_info(n, name, 
    ''' ....
    if show_hash:
        result += "%s " % n.hash.encode('hex')

在创建 bup 备份时(当文件通过 bup index + bup save 命令放置到备份中),生成的哈希值是在 bup ls 命令上只是打印出来的,还是在每次 bup ls 上重新计算并可用作 bup 备份的完整性测试?


https://github.com/bup/bup/blob/master/DESIGN - torek
Torek,已经检查过了,没有关于哈希计算的确切信息(有sha1类型,但不等于sha1sum结果)。 - osgx
bup将文件数据拆分成许多文件,使用所描述的技术。因此,文件的“bup哈希”不是git文件哈希,因为没有单个git blob对应于正在进行bup-save-d的文件或目录。因此,请参见第556-560行。对于这样的文件,确实存在单个git tree对象,可能就是bup哈希。无论如何,整个备份(甚至其中一个组项)的完整性显然无法在不检查所有基础git对象的情况下进行检查,这需要运行git fsck或等效命令。 - torek
这可能是“在创建备份时生成并仅打印出来”的总和。(顺便说一句,我说“可能”是因为我不确定;如果我知道,我会写一个答案,而不是一个只利用显而易见的推测性评论 :-)) - torek
对于上述设计文档的未来维护者,请紧缩写作风格——当前非正式的聊天式风格并不能给人留下这是一个需要认真对待的项目的印象。 - Thorbjørn Ravn Andersen
torek,bup中有许多哈希值,但我的问题始于bup ls -s中的完整文件哈希值,而不是提交ID哈希值或文件部分(块)的滚动哈希值。 - osgx
1个回答

2

bup将所有数据存储在一个裸的git仓库中(默认位于~/.bup)。因此,bup的哈希计算方法与git使用的方法完全相同。

然而,与git的一个重要区别是,bup可能会将文件分成块。如果bup决定将文件分割成块,则该文件在存储库中表示为树,而不是作为blob表示。在这种情况下,bup文件的哈希值与相应树的git哈希值相同。

以下脚本演示了这一点:

bup_hash_test

#!/bin/bash

bup init
BUPTEST=/tmp/bup_test
function test_bup_hash()
{
    bup index $BUPTEST &> /dev/null
    bup save -n buptest $BUPTEST &> /dev/null
    local buphash=$(bup ls -s buptest/latest$BUPTEST|cut -d' ' -f 1)
    echo "bup's hash: $buphash"
    echo "git's hash: $(git hash-object $BUPTEST)"
    echo git --git-dir \~/.bup cat-file -p $buphash
    git --git-dir ~/.bup cat-file -p $buphash
}

cat > $BUPTEST <<'END'
    http://pkgsrc.se/sysutils/bup
    http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/sysutils/bup/
END

test_bup_hash

echo
echo

echo " -1" >> $BUPTEST

echo "After appending ' -1' line:"
test_bup_hash

echo
echo

echo "After replacing '-' with '#':"
sed -i 's/-/#/' $BUPTEST
test_bup_hash

输出:

$ ./bup_hash_test
Initialized empty Git repository in ~/.bup/
bup's hash: b52baef90c17a508115ce05680bbb91d1d7bfd8d
git's hash: b52baef90c17a508115ce05680bbb91d1d7bfd8d
git --git-dir ~/.bup cat-file -p b52baef90c17a508115ce05680bbb91d1d7bfd8d
    http://pkgsrc.se/sysutils/bup
    http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/sysutils/bup/


After appending ' -1' line:
bup's hash: c95b4a1fe1956418cb0e58e0a2c519622d8ce767
git's hash: b5bc4094328634ce6e2f4c41458514bab5f5cd7e
git --git-dir ~/.bup cat-file -p c95b4a1fe1956418cb0e58e0a2c519622d8ce767
100644 blob aa7770f6a52237f29a5d10b350fe877bf4626bd6    00
100644 blob d00491fd7e5bb6fa28c517a0bb32b8b506539d4d    61


After replacing '-' with '#':
bup's hash: cda9a69f1cbe66ff44ea6530330e51528563e32a
git's hash: cda9a69f1cbe66ff44ea6530330e51528563e32a
git --git-dir ~/.bup cat-file -p cda9a69f1cbe66ff44ea6530330e51528563e32a
    http://pkgsrc.se/sysutils/bup
    http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/sysutils/bup/
 #1

正如我们所看到的,当和的哈希值匹配时,存储库中对应的对象是具有预期内容的blob。当和的哈希值不匹配时,具有哈希值的对象是一个树。该树中blob的内容对应于完整文件的片段:
$ git --git-dir ~/.bup cat-file -p aa7770f6a52237f29a5d10b350fe877bf4626bd6
    http://pkgsrc.se/sysutils/bup
    http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/sysutils/bup/
 -$ git --git-dir ~/.bup cat-file -p d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
1

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - osgx
Bup不是Git!它只是从Git中窃取了一些思想/格式;但它有自己的哈希变体。它隐藏在bup的源代码中,但可以找到。 "sha"变量名不是真正的sha1,它是一些(变量)前缀;就像在git annex中一样;但不是相同的前缀。什么是前缀?哪种sha变体用于提交ID?对于目录呢?你的错误与问题无关,你能直接在github bup/bup上重新发布它吗?PS:这个错误表明bup ls -s打印的哈希值没有记录。(你的bup版本是什么?) - osgx
@osgx 请查看更新的答案。它包含了最终证明,即bup完全依赖于git进行其哈希计算。 - Leon
@osgx calc_hash() 不使用不同的前缀方案。它与 git 中完全相同的方案。否则,为什么分块文件的哈希值会与存储库中相应树对象的哈希值匹配呢? - Leon
1
@osgx git的哈希计算代码:https://github.com/git/git/blob/master/sha1_file.c#L2938 - Leon
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接