tailscale/tailfs/tailfsimpl/compositefs/openfile.go

66 lines
1.6 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package compositefs
import (
"context"
"io/fs"
"os"
"github.com/tailscale/xnet/webdav"
"tailscale.com/tailfs/tailfsimpl/shared"
)
// OpenFile implements interface webdav.Filesystem.
func (cfs *CompositeFileSystem) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
if !shared.IsRoot(name) {
pathInfo, err := cfs.pathInfoFor(name)
if err != nil {
return nil, err
}
if pathInfo.refersToChild {
// this is the child itself, ask it to open its root
return pathInfo.child.FS.OpenFile(ctx, "/", flag, perm)
}
return pathInfo.child.FS.OpenFile(ctx, pathInfo.pathOnChild, flag, perm)
}
// the root directory contains one directory for each child
di, err := cfs.Stat(ctx, name)
if err != nil {
return nil, err
}
return &shared.DirFile{
Info: di,
LoadChildren: func() ([]fs.FileInfo, error) {
cfs.childrenMu.Lock()
children := cfs.children
cfs.childrenMu.Unlock()
childInfos := make([]fs.FileInfo, 0, len(cfs.children))
for _, c := range children {
if c.isAvailable() {
var childInfo fs.FileInfo
if cfs.statChildren {
fi, err := c.FS.Stat(ctx, "/")
if err != nil {
return nil, err
}
// we use the full name
childInfo = shared.RenamedFileInfo(ctx, c.Name, fi)
} else {
// always use now() as the modified time to bust caches
childInfo = shared.ReadOnlyDirInfo(c.Name, cfs.now())
}
childInfos = append(childInfos, childInfo)
}
}
return childInfos, nil
},
}, nil
}