2016-09-22 2 views
1

Ich habe Probleme herauszufinden, wie man ein Verzeichnis in Tarball's Headerinfo schreibt. Zum Beispiel habe ich diese Verzeichnisstruktur:Golang tarring Verzeichnis

test [dir] 
-- test1.txt 
    -- subDirA [sub dir] 
     -- test2.txt 

Wenn ich Teer up-Test meine Go Teer ausführbare verwenden, wird es entpacken und die ursprüngliche Struktur haben. Wenn ich ein tar -tvf auf dem Tarball tun, wird der Eintrag sein:

test/test1.txt 
test/subDirA/test2.txt 

Allerdings, wenn ich manuell -cvf von Test Teer tun und dann eine tar -tvf tun, wird der Eintrag sein:

test/ 
test/test1.txt 
test/subDirA/ 
test/subDirA/test2.txt 

Das ist, was ich auch mein Go-Tarring-Programm tun soll. In meinem Go-Programm habe ich versucht, eine neue Methode writeDirToTar hinzuzufügen, um mit dem Hinzufügen von Verzeichnissen in den tarWriter umzugehen. Ich rufe entweder writeFileToTar oder writeDirToTar aus einer fileWalk-Funktion auf. Ich bekomme einen Fehler "test/subDirA ist ein Verzeichnis", wenn ich io.Copy(tarWriter, file) in writeDirToTar aufrufen, die Art von Sinn. Gibt es einen Workaround dafür?

func writeToTar(fileDir string, 
     sourceBase string, 
     tarWriter *tar.Writer, 
     f os.FileInfo) error { 

     file, err := os.Open(fileDir) 
     if err != nil { 
       log.Print("error opening file") 
       return err 
     } 
     defer file.Close() 

     // relative paths are used to preserve the directory paths in each file path 
     relativePath, err := filepath.Rel(sourceBase, fileDir) 

     tarheader := new(tar.Header) 
     tarheader.Name = relativePath 
     tarheader.Size = f.Size() 
     tarheader.Mode = int64(f.Mode()) 
     tarheader.ModTime = f.ModTime() 

     err = tarWriter.WriteHeader(tarheader) 
     if err != nil { 
       log.Print("error writing tarHeader") 
       return err 
     } 
     _, err = io.Copy(tarWriter, file) 
     if err != nil { 
       log.Print("error writing to tarWriter") 
       return err 
     } 
     return nil 
} 

func writeDirToTar(fileDir string, 
     sourceBase string, 
     tarWriter *tar.Writer, 
     f os.FileInfo) error { 

     file, err := os.Open(fileDir) 
     if err != nil { 
       log.Print("error opening file") 
       return err 
     } 
     defer file.Close() 

     // relative paths are used to preserve the directory paths in each file path 
     relativePath, err := filepath.Rel(sourceBase, fileDir) 

     if tarHeader, err := tar.FileInfoHeader(f, relativePath); err != nil { 
       log.Print("error writing tarHeader") 
       return err 
     } 

     tarHeader.Name = relativePath 
     tarheader.Mode = int64(f.Mode()) 
     tarheader.ModTime = f.ModTime() 

     _, err = io.Copy(tarWriter, file) 
     if err != nil { 
       log.Print("error writing to tarWriter") 
       return err 
     } 
     return nil 

} 

Antwort

1

Sie verpassen die Typeflag Feld in der tar.Header.

Für das Verzeichnis, das Sie wollen zumindest werden:

tarheader := &tar.Header{ 
    Name:  relativePath, 
    Mode:  int64(f.Mode()), 
    ModTime: f.ModTime(), 
    Typeflag: tar.TypeDir, 
} 

Sie keine Größe hier wollen, noch müssen Sie die Verzeichnisdaten zu kopieren, da die internen Verzeichnisdatenstrukturen nichts zu bedeuten tar .

Sie können auch einen / zu dem Dateinamen hinzufügen, um anzuzeigen, dass es ein Verzeichnis ist und das POSIX-tar-Verhalten übereinstimmt.

Alternativ können Sie auch einfach die tar.FileInfoHeader Funktion verwenden, wie Sie es mit den Dateien getan haben, um die richtige Header-Struktur zu erstellen.