2013-03-02 5 views
5

मैं बस कुछ बैकअप के स्वचालित प्रसंस्करण के लिए संग्रह/टैर और संपीड़न/gzip के साथ प्रयोग कर रहा था।TeeReader के माध्यम से tar.gz के tar-part का md5 हैश गलत क्यों है?

मेरी समस्या इस प्रकार है: मेरे पास विभिन्न .tar फ़ाइलें और .tar.gz फ़ाइलें हैं जो आसपास तैरती हैं, और इस प्रकार मैं .tar.gz फ़ाइल के हैश (एमडी 5) को निकालना चाहता हूं, और हैश (एमडी 5) .tar फ़ाइल भी, आदर्श रूप से एक रन में।

उदाहरण कोड जो मैंने अभी तक किया है, .tar.gz में फ़ाइलों के हैंश के लिए पूरी तरह से ठीक है .gz के लिए, लेकिन .tar के लिए हैश गलत है और मुझे पता नहीं चल रहा परेशानी क्या है।

मैंने tar/reader.go फ़ाइल को देखा और मैंने देखा कि वहां कुछ छोड़ रहा है, फिर भी मैंने सोचा कि सब कुछ आईओ पर चलाना चाहिए। रीडर इंटरफ़ेस और इस प्रकार टी रीडर को अभी भी सभी बाइट्स को पकड़ना चाहिए।

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 

लिनक्स टकसाल 14 (Ubuntu 12.04 के आधार पर) उबंटू से 1.02 जाने के साथ डेटा संग्रह स्थानों मेरे जाने के कार्यक्रम के लिए परिणाम है:

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

तो tb.tar को छोड़कर सभी हैंश की अपेक्षा की जाती है। (बेशक यदि आप उस उदाहरण को पुनः प्रयास करते हैं तो आपके .tar और .tar.gz अलग-अलग टाइमस्टैम्प की वजह से अलग होंगे)

यह काम करने के तरीके के बारे में कोई संकेत बहुत सराहना की जाएगी, मैं वास्तव में पसंद करूंगा हालांकि यह 1 रन में है (टी रीडर के साथ)।

उत्तर

5

समस्या तब होती है क्योंकि टैर आपके पाठक से प्रत्येक बाइट नहीं पढ़ता है। प्रत्येक फ़ाइल को हैश करने के बाद, आपको यह सुनिश्चित करने के लिए पाठक को खाली करने की आवश्यकता है कि प्रत्येक बाइट पढ़ा और धोया जाए। जिस तरह से मैं सामान्य रूप से ऐसा करता हूं वह ईओएफ तक पढ़ने के लिए io.Copy() का उपयोग करता है।

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) जोड़ना है। मुझे लगता है कि पहला तरीका स्पष्ट है भले ही मुझे एक के बजाय चार लाइनों को जोड़ने/संशोधित करने की आवश्यकता हो।

संबंधित मुद्दे