tailfs: replace webdavfs with reverse proxies

Instead of modeling remote WebDAV servers as actual
webdav.FS instances, we now just proxy traffic to them.
This not only simplifies the code, but it also allows
WebDAV locking to work correctly by making sure locks are
handled by the servers that need to (i.e. the ones actually
serving the files).

Updates tailscale/corp#16827

Signed-off-by: Percy Wegmann <percy@tailscale.com>
This commit is contained in:
Percy Wegmann
2024-02-21 06:40:12 -06:00
committed by Percy Wegmann
parent e1bd7488d0
commit 50fb8b9123
33 changed files with 1186 additions and 2008 deletions

View File

@ -0,0 +1,63 @@
// 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
}