update vendor
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
19a32db84d
commit
94d1cfbfbf
10501 changed files with 2307943 additions and 29279 deletions
322
vendor/github.com/containerd/continuity/continuityfs/fuse.go
generated
vendored
Normal file
322
vendor/github.com/containerd/continuity/continuityfs/fuse.go
generated
vendored
Normal file
|
@ -0,0 +1,322 @@
|
|||
// +build linux darwin freebsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuityfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
"github.com/containerd/continuity"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// File represents any file type (non directory) in the filesystem
|
||||
type File struct {
|
||||
inode uint64
|
||||
uid uint32
|
||||
gid uint32
|
||||
provider FileContentProvider
|
||||
resource continuity.Resource
|
||||
}
|
||||
|
||||
// NewFile creates a new file with the given inode and content provider
|
||||
func NewFile(inode uint64, provider FileContentProvider) *File {
|
||||
return &File{
|
||||
inode: inode,
|
||||
provider: provider,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *File) setResource(r continuity.Resource) (err error) {
|
||||
// TODO: error out if uid excesses uint32?
|
||||
f.uid = uint32(r.UID())
|
||||
f.gid = uint32(r.GID())
|
||||
f.resource = r
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Attr sets the fuse attribute for the file
|
||||
func (f *File) Attr(ctx context.Context, attr *fuse.Attr) (err error) {
|
||||
// Set attributes from resource metadata
|
||||
attr.Mode = f.resource.Mode()
|
||||
attr.Uid = f.uid
|
||||
attr.Gid = f.gid
|
||||
|
||||
if rf, ok := f.resource.(continuity.RegularFile); ok {
|
||||
attr.Nlink = uint32(len(rf.Paths()))
|
||||
attr.Size = uint64(rf.Size())
|
||||
} else {
|
||||
attr.Nlink = 1
|
||||
}
|
||||
|
||||
attr.Inode = f.inode
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Open opens the file for read
|
||||
// currently only regular files can be opened
|
||||
func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
||||
var dgst digest.Digest
|
||||
if rf, ok := f.resource.(continuity.RegularFile); ok {
|
||||
digests := rf.Digests()
|
||||
if len(digests) > 0 {
|
||||
dgst = digests[0]
|
||||
}
|
||||
}
|
||||
// TODO(dmcgowan): else check if device can be opened for read
|
||||
r, err := f.provider.Open(f.resource.Path(), dgst)
|
||||
if err != nil {
|
||||
logrus.Debugf("Error opening handle: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &fileHandler{
|
||||
reader: r,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (f *File) getDirent(name string) (fuse.Dirent, error) {
|
||||
var t fuse.DirentType
|
||||
switch f.resource.(type) {
|
||||
case continuity.RegularFile:
|
||||
t = fuse.DT_File
|
||||
case continuity.SymLink:
|
||||
t = fuse.DT_Link
|
||||
case continuity.Device:
|
||||
t = fuse.DT_Block
|
||||
case continuity.NamedPipe:
|
||||
t = fuse.DT_FIFO
|
||||
default:
|
||||
t = fuse.DT_Unknown
|
||||
}
|
||||
|
||||
return fuse.Dirent{
|
||||
Inode: f.inode,
|
||||
Type: t,
|
||||
Name: name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type fileHandler struct {
|
||||
offset int64
|
||||
reader io.ReadCloser
|
||||
}
|
||||
|
||||
func (h *fileHandler) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
||||
if h.offset != req.Offset {
|
||||
if seeker, ok := h.reader.(io.Seeker); ok {
|
||||
if _, err := seeker.Seek(req.Offset, os.SEEK_SET); err != nil {
|
||||
logrus.Debugf("Error seeking: %v", err)
|
||||
return err
|
||||
}
|
||||
h.offset = req.Offset
|
||||
} else {
|
||||
return errors.New("unable to seek to offset")
|
||||
}
|
||||
}
|
||||
|
||||
n, err := h.reader.Read(resp.Data[:req.Size])
|
||||
if err != nil {
|
||||
logrus.Debugf("Read error: %v", err)
|
||||
return err
|
||||
}
|
||||
h.offset = h.offset + int64(n)
|
||||
|
||||
resp.Data = resp.Data[:n]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *fileHandler) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
|
||||
return h.reader.Close()
|
||||
}
|
||||
|
||||
// Dir represents a file system directory
|
||||
type Dir struct {
|
||||
inode uint64
|
||||
uid uint32
|
||||
gid uint32
|
||||
nodes map[string]fs.Node
|
||||
provider FileContentProvider
|
||||
resource continuity.Resource
|
||||
}
|
||||
|
||||
// Attr sets the fuse attributes for the directory
|
||||
func (d *Dir) Attr(ctx context.Context, attr *fuse.Attr) (err error) {
|
||||
if d.resource == nil {
|
||||
attr.Mode = os.ModeDir | 0555
|
||||
} else {
|
||||
attr.Mode = d.resource.Mode()
|
||||
}
|
||||
|
||||
attr.Uid = d.uid
|
||||
attr.Gid = d.gid
|
||||
attr.Inode = d.inode
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Dir) getDirent(name string) (fuse.Dirent, error) {
|
||||
return fuse.Dirent{
|
||||
Inode: d.inode,
|
||||
Type: fuse.DT_Dir,
|
||||
Name: name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type direnter interface {
|
||||
getDirent(name string) (fuse.Dirent, error)
|
||||
}
|
||||
|
||||
// Lookup looks up the filesystem node for the name within the directory
|
||||
func (d *Dir) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
||||
node, ok := d.nodes[name]
|
||||
if !ok {
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// ReadDirAll reads all the directory entries
|
||||
func (d *Dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
ents := make([]fuse.Dirent, 0, len(d.nodes))
|
||||
for name, node := range d.nodes {
|
||||
if nd, ok := node.(direnter); ok {
|
||||
de, err := nd.getDirent(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ents = append(ents, de)
|
||||
} else {
|
||||
logrus.Errorf("%s does not have a directory entry", name)
|
||||
}
|
||||
}
|
||||
|
||||
return ents, nil
|
||||
}
|
||||
|
||||
func (d *Dir) setResource(r continuity.Resource) (err error) {
|
||||
d.uid = uint32(r.UID())
|
||||
d.gid = uint32(r.GID())
|
||||
d.resource = r
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NewDir creates a new directory object
|
||||
func NewDir(inode uint64, provider FileContentProvider) *Dir {
|
||||
return &Dir{
|
||||
inode: inode,
|
||||
nodes: map[string]fs.Node{},
|
||||
provider: provider,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
rootPath = fmt.Sprintf("%c", filepath.Separator)
|
||||
)
|
||||
|
||||
func addNode(path string, node fs.Node, cache map[string]*Dir, provider FileContentProvider) {
|
||||
dirPath, file := filepath.Split(path)
|
||||
d, ok := cache[dirPath]
|
||||
if !ok {
|
||||
d = NewDir(0, provider)
|
||||
cache[dirPath] = d
|
||||
addNode(filepath.Clean(dirPath), d, cache, provider)
|
||||
}
|
||||
d.nodes[file] = node
|
||||
logrus.Debugf("%s (%#v) added to %s", file, node, dirPath)
|
||||
}
|
||||
|
||||
type treeRoot struct {
|
||||
root *Dir
|
||||
}
|
||||
|
||||
func (t treeRoot) Root() (fs.Node, error) {
|
||||
logrus.Debugf("Returning root with %#v", t.root.nodes)
|
||||
return t.root, nil
|
||||
}
|
||||
|
||||
// NewFSFromManifest creates a fuse filesystem using the given manifest
|
||||
// to create the node tree and the content provider to serve up
|
||||
// content for regular files.
|
||||
func NewFSFromManifest(manifest *continuity.Manifest, mountRoot string, provider FileContentProvider) (fs.FS, error) {
|
||||
tree := treeRoot{
|
||||
root: NewDir(0, provider),
|
||||
}
|
||||
|
||||
fi, err := os.Stat(mountRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, ok := fi.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
return nil, errors.New("could not access directory")
|
||||
}
|
||||
tree.root.uid = st.Uid
|
||||
tree.root.gid = st.Gid
|
||||
|
||||
dirCache := map[string]*Dir{
|
||||
rootPath: tree.root,
|
||||
}
|
||||
|
||||
for i, resource := range manifest.Resources {
|
||||
inode := uint64(i) + 1
|
||||
if _, ok := resource.(continuity.Directory); ok {
|
||||
cleanPath := filepath.Clean(resource.Path())
|
||||
keyPath := fmt.Sprintf("%s%c", cleanPath, filepath.Separator)
|
||||
d, ok := dirCache[keyPath]
|
||||
if !ok {
|
||||
d = NewDir(inode, provider)
|
||||
dirCache[keyPath] = d
|
||||
addNode(cleanPath, d, dirCache, provider)
|
||||
} else {
|
||||
d.inode = inode
|
||||
}
|
||||
if err := d.setResource(resource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
f := NewFile(inode, provider)
|
||||
if err := f.setResource(resource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rf, ok := resource.(continuity.RegularFile); ok {
|
||||
|
||||
for _, p := range rf.Paths() {
|
||||
addNode(p, f, dirCache, provider)
|
||||
}
|
||||
} else {
|
||||
addNode(resource.Path(), f, dirCache, provider)
|
||||
}
|
||||
}
|
||||
|
||||
return tree, nil
|
||||
}
|
59
vendor/github.com/containerd/continuity/continuityfs/provider.go
generated
vendored
Normal file
59
vendor/github.com/containerd/continuity/continuityfs/provider.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
// +build linux darwin freebsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuityfs
|
||||
|
||||
import (
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/continuity/driver"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// FileContentProvider is an object which is used to fetch
|
||||
// data and inode information about a path or digest.
|
||||
// TODO(dmcgowan): Update GetContentPath to provide a
|
||||
// filehandle or ReadWriteCloser.
|
||||
type FileContentProvider interface {
|
||||
Path(string, digest.Digest) (string, error)
|
||||
Open(string, digest.Digest) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
type fsContentProvider struct {
|
||||
root string
|
||||
driver driver.Driver
|
||||
}
|
||||
|
||||
// NewFSFileContentProvider creates a new content provider which
|
||||
// gets content from a directory on an existing filesystem based
|
||||
// on the resource path.
|
||||
func NewFSFileContentProvider(root string, driver driver.Driver) FileContentProvider {
|
||||
return &fsContentProvider{
|
||||
root: root,
|
||||
driver: driver,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *fsContentProvider) Path(path string, dgst digest.Digest) (string, error) {
|
||||
return filepath.Join(p.root, path), nil
|
||||
}
|
||||
|
||||
func (p *fsContentProvider) Open(path string, dgst digest.Digest) (io.ReadCloser, error) {
|
||||
return p.driver.Open(filepath.Join(p.root, path))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue