2017-03-23 10 views
1

Unixでは、tarユーティリティには、リンクのターゲットをアーカイブする-hオプションがあります。私はGoでこれを行う方法があるのだろうかと思っています。現在、リンクの内容をシンボリックリンクファイルに設定されたヘッダ名でtarにコピーしようとすると、tar: Damaged tar archiveというエラーが出ます。以下のコードは私が現在使っているものです。この関数の目的は、現在のディレクトリのすべてを再帰的にtarすることです。Goにtar -hオプションを複製する方法はありますか?

私は、シンボリックリンクのサイズをターゲットファイルのサイズに設定するだけで、まだエラーが発生する可能性があると思います。

func createTarFile() { 
    tarfile, _ := os.Create(buildCtxTar) 
    defer tarfile.Close() 

    tarball := tar.NewWriter(tarfile) 
    defer tarball.Close() 

    //get the working directory 
    rootDir, _ := os.Getwd() 

    //add all the files in the current directory to the tarball 
    walkFn := func(path string, info os.FileInfo, err error) error { 
     //don't add the tar file to itself, don't add the working directory either 
     if info.Name() == buildCtxTar || info.Name() == filepath.Base(rootDir) { 
      return nil 
     } 

     //no absolute paths in the tar file, the "+1" strips the leading file separator 
     relativePath := path[len(rootDir)+1:] 

     isSymlink := info.Mode()&os.ModeSymlink == os.ModeSymlink 
     var size int64 = -1 
     //evaluate symbolic links 
     if isSymlink { 
      path, size, err = handleSymlink(path) 
      if err != nil { 
       return err 
      } 
     } 

     header, err := tar.FileInfoHeader(info, path) 
     if err != nil { 
      return err 
     } 

     //if the OS is windows we need to convert the '\' to '/' 
     relativePath = filepath.ToSlash(relativePath) 

     //rename the name of the file to its path for a structured tarball 
     header.Name = relativePath 
     if isSymlink { 
      header.Size = size 
     } 
     if err := tarball.WriteHeader(header); err != nil { 
      return err 
     } 

     //don't attempt copy data from special files (like directories) 
     if !isSymlink && !info.Mode().IsRegular() { 
      return nil 
     } 
     f, err := os.Open(path) 
     if err != nil { 
      return err 
     } 
     defer f.Close() 

     // copy the file data to the tarball 
     if _, err := io.Copy(tarball, f); err != nil { 
      return err 
     } 
     return nil 
    } 

    //walks through all files and subdirectories of the current directory 
    err := filepath.Walk(rootDir, walkFn) 
} 

//get the filepath for the symbolic link 
func handleSymlink(path string) (string, int64, error) { 
    //read the link 
    link, err := os.Readlink(path) 
    if err != nil { 
     return "", -1, err 
    } 
    //if the filepath isn't an absolute path we need to 
    //reconstruct it so that it is 
    if !filepath.IsAbs(link) { 
     link = filepath.Join(filepath.Dir(path), link) 
     if err != nil { 
      return "", -1, err 
     } 
    } 
    fi, err := os.Stat(link) 
    if err != nil { 
     return "", -1, err 
    } 
    size := fi.Size() 
    return link, size, nil 
} 
+0

シンボリックリンクからヘッダーを使用していて、意味がない名前とサイズを変更しています。実ファイルから新しいヘッダーを作成します。 – JimB

+0

@JimB、ヘッダの名前をシンボリックリンクの名前に変更しましたか? – sreya

+0

はい、私はそれがあなたが望むものだと思います。私はもっ​​と見る時間がなかった。 – JimB

答えて

1

あなたはまだシンボリックリンクのTypeflagModeを持っているとしているシンボリックリンクFileInfoからtar.Headerを作成しています。

ターゲットファイルから新しいヘッダーを作成し、[名前]フィールドをシンボリックリンクの名前に変更してアーカイブに移動します。

関連する問題