tailscale/tailfs/tailfsimpl/dirfs/openfile.go

64 lines
1.7 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package dirfs
import (
"context"
"io/fs"
"os"
"github.com/tailscale/xnet/webdav"
"tailscale.com/tailfs/tailfsimpl/shared"
)
// OpenFile implements interface webdav.Filesystem.
func (dfs *FS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
_, isStaticRoot := dfs.trimStaticRoot(name)
if !isStaticRoot && !shared.IsRoot(name) {
// Show a folder with no children to represent the requested child. In
// practice, the children of this folder are never read, we just need
// to give webdav a file here which it uses to call file.Stat(). So,
// even though the Child may in fact have its own children, it doesn't
// matter here.
return &shared.DirFile{
Info: shared.ReadOnlyDirInfo(name, dfs.now()),
LoadChildren: func() ([]fs.FileInfo, error) {
return nil, nil
},
}, nil
}
di, err := dfs.Stat(ctx, name)
if err != nil {
return nil, err
}
if dfs.StaticRoot != "" && !isStaticRoot {
// Show a folder with a single subfolder that is the static root.
return &shared.DirFile{
Info: di,
LoadChildren: func() ([]fs.FileInfo, error) {
return []fs.FileInfo{
shared.ReadOnlyDirInfo(dfs.StaticRoot, dfs.now()),
}, nil
},
}, nil
}
// Show a folder with one subfolder for each Child of this FS.
return &shared.DirFile{
Info: di,
LoadChildren: func() ([]fs.FileInfo, error) {
childInfos := make([]fs.FileInfo, 0, len(dfs.Children))
for _, c := range dfs.Children {
if c.isAvailable() {
childInfo := shared.ReadOnlyDirInfo(c.Name, dfs.now())
childInfos = append(childInfos, childInfo)
}
}
return childInfos, nil
},
}, nil
}