gpt4 book ai didi

go - 为什么通过 TeeReader 的 tar.gz 的 tar 部分的 md5 散列是错误的?

转载 作者:IT王子 更新时间:2023-10-29 01:27:21 30 4
gpt4 key购买 nike

我刚刚尝试使用 archive/tar 和 compress/gzip 来自动处理我的一些备份。

我的问题是:我周围有各种 .tar 文件和 .tar.gz 文件,因此我想提取 .tar.gz 文件的哈希值 (md5),以及.tar 文件,最好一次运行。

到目前为止,我的示例代码对于 .tar.gz 和 .gz 中文件的哈希值都工作得很好,但是 .tar 的哈希值是错误的,我无法找出是什么问题是。

我查看了 tar/reader.go 文件,发现其中有一些跳过,但我认为一切都应该在 io.Reader 接口(interface)上运行,因此 TeeReader 应该仍然捕获所有字节。

package main

import (
"archive/tar"
"compress/gzip"
"crypto/md5"
"fmt"
"io"
"os"
)

func main() {
tgz, _ := os.Open("tb.tar.gz")
gzMd5 := md5.New()
gz, _ := gzip.NewReader(io.TeeReader(tgz, gzMd5))
tarMd5 := md5.New()
tr := tar.NewReader(io.TeeReader(gz, tarMd5))
for {
fileMd5 := md5.New()
hdr, err := tr.Next()
if err == io.EOF {
break
}
io.Copy(fileMd5, tr)
fmt.Printf("%x %s\n", fileMd5.Sum(nil), hdr.Name)
}
fmt.Printf("%x tb.tar\n", tarMd5.Sum(nil))
fmt.Printf("%x tb.tar.gz\n", gzMd5.Sum(nil))
}

现在来看下面的例子:

$ echo "a" > a.txt
$ echo "b" > b.txt
$ tar cf tb.tar a.txt b.txt
$ gzip -c tb.tar > tb.tar.gz
$ md5sum a.txt b.txt tb.tar tb.tar.gz

60b725f10c9c85c70d97880dfe8191b3 a.txt
3b5d5c3712955042212316173ccf37be b.txt
501352dcd8fbd0b8e3e887f7dafd9392 tb.tar
90d6ba204493d8e54d3b3b155bb7f370 tb.tar.gz

在 Linux Mint 14(基于 Ubuntu 12.04)上,使用 Ubuntu 存储库中的 go 1.02,我的 go 程序的结果是:

$ go run tarmd5.go 
60b725f10c9c85c70d97880dfe8191b3 a.txt
3b5d5c3712955042212316173ccf37be b.txt
a26ddab1c324780ccb5199ef4dc38691 tb.tar
90d6ba204493d8e54d3b3b155bb7f370 tb.tar.gz

所以除了 tb.tar 之外的所有哈希值都符合预期。(当然,如果您重试该示例,您的 .tar 和 .tar.gz 将与此不同,因为时间戳不同)

任何关于如何让它工作的提示都将不胜感激,不过我真的更愿意在 1 次运行中使用它(使用 TeeReaders)。

最佳答案

出现此问题是因为 tar 不会从您的阅读器读取每个字节。对每个文件进行哈希处理后,您需要清空读取器以确保每个字节都被读取和哈希处理。我通常这样做的方法是使用 io.Copy() 读取直到 EOF。

package main

import (
"archive/tar"
"compress/gzip"
"crypto/md5"
"fmt"
"io"
"io/ioutil"
"os"
)

func main() {
tgz, _ := os.Open("tb.tar.gz")
gzMd5 := md5.New()
gz, _ := gzip.NewReader(io.TeeReader(tgz, gzMd5))
tarMd5 := md5.New()
tee := io.TeeReader(gz, tarMd5) // need the reader later
tr := tar.NewReader(tee)
for {
fileMd5 := md5.New()
hdr, err := tr.Next()
if err == io.EOF {
break
}
io.Copy(fileMd5, tr)
fmt.Printf("%x %s\n", fileMd5.Sum(nil), hdr.Name)
}
io.Copy(ioutil.Discard, tee) // read unused portions of the tar file
fmt.Printf("%x tb.tar\n", tarMd5.Sum(nil))
fmt.Printf("%x tb.tar.gz\n", gzMd5.Sum(nil))
}

另一种选择是在调用 tarMd5.Sum() 之前添加 io.Copy(tarMd5, gz)。我认为第一种方法更清晰,即使我需要添加/修改四行而不是一行。

关于go - 为什么通过 TeeReader 的 tar.gz 的 tar 部分的 md5 散列是错误的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15179194/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com