...

Source file src/github.com/spf13/afero/tarfs/fs.go

Documentation: github.com/spf13/afero/tarfs

     1  // package tarfs implements a read-only in-memory representation of a tar archive
     2  package tarfs
     3  
     4  import (
     5  	"archive/tar"
     6  	"bytes"
     7  	"io"
     8  	"os"
     9  	"path/filepath"
    10  	"syscall"
    11  	"time"
    12  
    13  	"github.com/spf13/afero"
    14  )
    15  
    16  type Fs struct {
    17  	files map[string]map[string]*File
    18  }
    19  
    20  func splitpath(name string) (dir, file string) {
    21  	name = filepath.ToSlash(name)
    22  	if len(name) == 0 || name[0] != '/' {
    23  		name = "/" + name
    24  	}
    25  	name = filepath.Clean(name)
    26  	dir, file = filepath.Split(name)
    27  	dir = filepath.Clean(dir)
    28  	return
    29  }
    30  
    31  func New(t *tar.Reader) *Fs {
    32  	fs := &Fs{files: make(map[string]map[string]*File)}
    33  	for {
    34  		hdr, err := t.Next()
    35  		if err == io.EOF {
    36  			break
    37  		}
    38  		if err != nil {
    39  			return nil
    40  		}
    41  
    42  		d, f := splitpath(hdr.Name)
    43  		if _, ok := fs.files[d]; !ok {
    44  			fs.files[d] = make(map[string]*File)
    45  		}
    46  
    47  		var buf bytes.Buffer
    48  		size, err := buf.ReadFrom(t)
    49  		if err != nil {
    50  			panic("tarfs: reading from tar:" + err.Error())
    51  		}
    52  
    53  		if size != hdr.Size {
    54  			panic("tarfs: size mismatch")
    55  		}
    56  
    57  		file := &File{
    58  			h:    hdr,
    59  			data: bytes.NewReader(buf.Bytes()),
    60  			fs:   fs,
    61  		}
    62  		fs.files[d][f] = file
    63  
    64  	}
    65  
    66  	if fs.files[afero.FilePathSeparator] == nil {
    67  		fs.files[afero.FilePathSeparator] = make(map[string]*File)
    68  	}
    69  	// Add a pseudoroot
    70  	fs.files[afero.FilePathSeparator][""] = &File{
    71  		h: &tar.Header{
    72  			Name:     afero.FilePathSeparator,
    73  			Typeflag: tar.TypeDir,
    74  			Size:     0,
    75  		},
    76  		data: bytes.NewReader(nil),
    77  		fs:   fs,
    78  	}
    79  
    80  	return fs
    81  }
    82  
    83  func (fs *Fs) Open(name string) (afero.File, error) {
    84  	d, f := splitpath(name)
    85  	if _, ok := fs.files[d]; !ok {
    86  		return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT}
    87  	}
    88  
    89  	file, ok := fs.files[d][f]
    90  	if !ok {
    91  		return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT}
    92  	}
    93  
    94  	nf := *file
    95  
    96  	return &nf, nil
    97  }
    98  
    99  func (fs *Fs) Name() string { return "tarfs" }
   100  
   101  func (fs *Fs) Create(name string) (afero.File, error) { return nil, syscall.EROFS }
   102  
   103  func (fs *Fs) Mkdir(name string, perm os.FileMode) error { return syscall.EROFS }
   104  
   105  func (fs *Fs) MkdirAll(path string, perm os.FileMode) error { return syscall.EROFS }
   106  
   107  func (fs *Fs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
   108  	if flag != os.O_RDONLY {
   109  		return nil, &os.PathError{Op: "open", Path: name, Err: syscall.EPERM}
   110  	}
   111  
   112  	return fs.Open(name)
   113  }
   114  
   115  func (fs *Fs) Remove(name string) error { return syscall.EROFS }
   116  
   117  func (fs *Fs) RemoveAll(path string) error { return syscall.EROFS }
   118  
   119  func (fs *Fs) Rename(oldname string, newname string) error { return syscall.EROFS }
   120  
   121  func (fs *Fs) Stat(name string) (os.FileInfo, error) {
   122  	d, f := splitpath(name)
   123  	if _, ok := fs.files[d]; !ok {
   124  		return nil, &os.PathError{Op: "stat", Path: name, Err: syscall.ENOENT}
   125  	}
   126  
   127  	file, ok := fs.files[d][f]
   128  	if !ok {
   129  		return nil, &os.PathError{Op: "stat", Path: name, Err: syscall.ENOENT}
   130  	}
   131  
   132  	return file.h.FileInfo(), nil
   133  }
   134  
   135  func (fs *Fs) Chmod(name string, mode os.FileMode) error { return syscall.EROFS }
   136  
   137  func (fs *Fs) Chown(name string, uid, gid int) error { return syscall.EROFS }
   138  
   139  func (fs *Fs) Chtimes(name string, atime time.Time, mtime time.Time) error { return syscall.EROFS }
   140  

View as plain text