mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-26 11:35:35 +00:00
993acf4475
Add a WebDAV-based folder sharing mechanism that is exposed to local clients at 100.100.100.100:8080 and to remote peers via a new peerapi endpoint at /v0/tailfs. Add the ability to manage folder sharing via the new 'share' CLI sub-command. Updates tailscale/corp#16827 Signed-off-by: Percy Wegmann <percy@tailscale.com>
72 lines
1.5 KiB
Go
72 lines
1.5 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package webdavfs
|
|
|
|
import (
|
|
"io/fs"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/jellydator/ttlcache/v3"
|
|
)
|
|
|
|
// statCache provides a cache for file directory and file metadata. Especially
|
|
// when used from the command-line, mapped WebDAV drives can generate
|
|
// repetitive requests for the same file metadata. This cache helps reduce the
|
|
// number of round-trips to the WebDAV server for such requests.
|
|
type statCache struct {
|
|
// mu guards the below values.
|
|
mu sync.Mutex
|
|
cache *ttlcache.Cache[string, fs.FileInfo]
|
|
}
|
|
|
|
func newStatCache(ttl time.Duration) *statCache {
|
|
cache := ttlcache.New(
|
|
ttlcache.WithTTL[string, fs.FileInfo](ttl),
|
|
)
|
|
go cache.Start()
|
|
return &statCache{cache: cache}
|
|
}
|
|
|
|
func (c *statCache) getOrFetch(name string, fetch func(string) (fs.FileInfo, error)) (fs.FileInfo, error) {
|
|
c.mu.Lock()
|
|
item := c.cache.Get(name)
|
|
c.mu.Unlock()
|
|
|
|
if item != nil {
|
|
return item.Value(), nil
|
|
}
|
|
|
|
fi, err := fetch(name)
|
|
if err == nil {
|
|
c.mu.Lock()
|
|
c.cache.Set(name, fi, ttlcache.DefaultTTL)
|
|
c.mu.Unlock()
|
|
}
|
|
|
|
return fi, err
|
|
}
|
|
|
|
func (c *statCache) set(parentPath string, infos []fs.FileInfo) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
for _, info := range infos {
|
|
path := filepath.Join(parentPath, filepath.Base(info.Name()))
|
|
c.cache.Set(path, info, ttlcache.DefaultTTL)
|
|
}
|
|
}
|
|
|
|
func (c *statCache) invalidate() {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
c.cache.DeleteAll()
|
|
}
|
|
|
|
func (c *statCache) stop() {
|
|
c.cache.Stop()
|
|
}
|