github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/archive/tar.go (about)

     1  package archive
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"io"
     7  	"os"
     8  	"time"
     9  )
    10  
    11  // 文件类型
    12  const (
    13  	TypeReg           = tar.TypeReg           // 普通文件
    14  	TypeLink          = tar.TypeLink          // 硬链接
    15  	TypeSymlink       = tar.TypeSymlink       // 符号链接
    16  	TypeChar          = tar.TypeChar          // 字符节点
    17  	TypeBlock         = tar.TypeBlock         // 块节点
    18  	TypeDir           = tar.TypeDir           // 目录
    19  	TypeFifo          = tar.TypeFifo          // 先进先出队列节点
    20  	TypeCont          = tar.TypeCont          // 保留位
    21  	TypeXHeader       = tar.TypeXHeader       // 扩展头
    22  	TypeXGlobalHeader = tar.TypeXGlobalHeader // 全局扩展头
    23  	TypeGNULongName   = tar.TypeGNULongName   // 下一个文件记录有个长名字
    24  	TypeGNULongLink   = tar.TypeGNULongLink   // 下一个文件记录指向一个具有长名字的文件
    25  	TypeGNUSparse     = tar.TypeGNUSparse     // 稀疏文件
    26  )
    27  
    28  // TarWrite 实现了tar格式压缩文件的存取
    29  func TarWrite(files []*File) (buf *bytes.Buffer, err error) {
    30  	buf = new(bytes.Buffer)
    31  
    32  	// 初始化writer
    33  	var tw = tar.NewWriter(buf)
    34  	defer tw.Close()
    35  
    36  	for _, file := range files {
    37  
    38  		// 根据结构体的内容实例化一个header
    39  		hdr := &tar.Header{
    40  			Name:       file.Name,             // 记录头域的文件名
    41  			Mode:       0600,                  // 权限和模式位
    42  			Uid:        0,                     // 所有者的用户ID
    43  			Gid:        0,                     // 所有者的组ID
    44  			Size:       int64(len(file.Body)), // 字节数(长度)
    45  			ModTime:    time.Now(),            // 修改时间
    46  			Typeflag:   TypeReg,               // 文件类型
    47  			Linkname:   "",                    // 链接的目标名
    48  			Uname:      "",                    // 所有者的用户名
    49  			Gname:      "",                    // 所有者的组名
    50  			Devmajor:   0,                     // 字符设备或块设备的major number
    51  			Devminor:   0,                     // 字符设备或块设备的minor number
    52  			AccessTime: time.Now(),            // 访问时间
    53  			ChangeTime: time.Now(),            // 状态改变时间
    54  		}
    55  		// writer写入header
    56  		if err = tw.WriteHeader(hdr); err != nil {
    57  			return nil, err
    58  		}
    59  		// writer写入内容
    60  		if _, err = tw.Write(file.Body); err != nil {
    61  			return nil, err
    62  		}
    63  	}
    64  	return
    65  }
    66  
    67  // TarRead 读取.tar压缩文件
    68  func TarRead(path string) ([]*File, error) {
    69  
    70  	// 读取文件内容
    71  	bf, err := os.ReadFile(path)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	// 实例化buffer
    77  	var readBuf = bytes.NewBuffer(bf)
    78  
    79  	// 初始化一个reader去读取tar内容
    80  	tr := tar.NewReader(readBuf)
    81  
    82  	var hdr *tar.Header
    83  	var b []byte
    84  	var files []*File
    85  	// 循环读取多个文件内容
    86  	for {
    87  		// 获取单个文件的header信息
    88  		hdr, err = tr.Next()
    89  
    90  		// 所有文件读取完毕
    91  		if err == io.EOF {
    92  			break
    93  		} else if err != nil {
    94  			return nil, err
    95  		}
    96  
    97  		// 读取数据流信息
    98  		b, err = io.ReadAll(tr)
    99  		if err != nil {
   100  			return nil, err
   101  		}
   102  		files = append(files, &File{
   103  			Name: hdr.Name,
   104  			Body: b,
   105  		})
   106  	}
   107  	return files, nil
   108  }