dongnuo2879 2015-02-14 15:00
浏览 52
已采纳

Golang:从tar中提取的文件引发权限错误

I've written the following code to tar a file, code works but strangely if I untar the archive the file permissions are gone so I can't read it unless I then chmod the file:

package main

import (
    "archive/tar"
    "io/ioutil"
    "log"
    "os"
)

func main() {

    c, err := os.Create("/path/to/tar/file/test.tar")
    if err != nil {
        log.Fatalln(err)
    }

    tw := tar.NewWriter(c)

    f, err := os.Open("sample.txt")
    if err != nil {
        log.Fatalln(err)
    }

    fi, err := f.Stat()
    if err != nil {
        log.Fatalln(err)
    }

    hdr := &tar.Header{Name: f.Name(),
        Size: fi.Size(),
    }
    if err := tw.WriteHeader(hdr); err != nil {
        log.Fatalln(err)
    }

    r, err := ioutil.ReadFile("sample.txt")
    if err != nil {
        log.Fatalln(err)
    }

    if _, err := tw.Write(r); err != nil {
        log.Fatalln(err)
    }
    if err := tw.Close(); err != nil {
        log.Fatalln(err)
    }

}

Any idea what I'm doing wrong?

  • 写回答

1条回答 默认 最新

  • doyp9057 2015-02-14 16:32
    关注

    You're not preserving the original permissions of the file. You're manually creating a header, and specifying only the name and size. Instead, use tar.FileInfoHeader to build the header.

    package main
    
    import (
        "archive/tar"
        "io/ioutil"
        "log"
        "os"
    )
    
    func main() {
        c, err := os.Create("/path/to/tar/file/test.tar")
        if err != nil {
            log.Fatalln(err)
        }
    
        tw := tar.NewWriter(c)
    
        f, err := os.Open("sample.txt")
        if err != nil {
            log.Fatalln(err)
        }
    
        fi, err := f.Stat()
        if err != nil {
            log.Fatalln(err)
        }
        // create header from FileInfo
        hdr, err := tar.FileInfoHeader(fi, "")
        if err != nil {
            log.Fatalln(err)
        }
        if err := tw.WriteHeader(hdr); err != nil {
            log.Fatalln(err)
        }
        // instead of reading the whole file into memory, prefer io.Copy
        r, err := io.Copy(tw, f)
        if err != nil {
            log.Fatalln(err)
        }
        log.Printf("Wrote %d bytes
    ", r)
    }
    

    Also note that I used io.Copy to copy data from the file (an io.Reader) to the tar writer (an io.Writer). This will work much better for larger files.

    Also - pay special attention to this note from the docs:

    Because os.FileInfo's Name method returns only the base name of the file it describes, it may be necessary to modify the Name field of the returned header to provide the full path name of the file.

    In this simple example, you're just using sample.txt so you shouldn't run into trouble. If you wanted to preserve a directory structure in your tar, you may have to modify the Name field in the header.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 基于RTKLIB框架写的精密单点定位-AR
  • ¥15 PFENet的预训练权重
  • ¥15 程序哪有错误怎么改?
  • ¥15 交换机和交换机之间的链路带宽以及主机带宽的理解
  • ¥15 ai创想家对战模式代码
  • ¥15 集合A由3个2行4列二维数组构成,从集合A中任意取一个二维数组元素、如果该二维数组元素的对应列位置的上、下两数都是奇数,而且仅有2个列是奇数/奇数,则该数组有意义,并放入集合B中打印输出。
  • ¥15 电信IPV6 无法外网访问吗
  • ¥15 有偿求效果比较好的遥感影像匹配的c++代码
  • ¥15 博主,你好,我下载了你的智能网联汽车辅助驾驶安全信息检测系统,现在不会运行,可以教我吗,
  • ¥15 怎么在excle输入下列公式