2024-02-02 18:45:32 +00:00
|
|
|
// Copyright (c) Tailscale Inc & AUTHORS
|
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
|
|
|
|
package webdavfs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"io/fs"
|
|
|
|
"os"
|
|
|
|
|
2024-02-09 17:26:43 +00:00
|
|
|
"tailscale.com/tailfs/tailfsimpl/shared"
|
2024-02-02 18:45:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type writeOnlyFile struct {
|
|
|
|
io.WriteCloser
|
|
|
|
name string
|
|
|
|
perm os.FileMode
|
|
|
|
fs *webdavFS
|
|
|
|
finalError chan error
|
|
|
|
}
|
|
|
|
|
|
|
|
// Readdir implements webdav.File. As this is a file, this always fails with an
|
|
|
|
// os.PathError.
|
|
|
|
func (f *writeOnlyFile) Readdir(count int) ([]fs.FileInfo, error) {
|
|
|
|
return nil, &os.PathError{
|
|
|
|
Op: "readdir",
|
|
|
|
Path: f.name,
|
|
|
|
Err: errors.New("is a file"), // TODO(oxtoacart): make sure this and below errors match what a regular os.File does
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Seek implements webdav.File. This always fails with an os.PathError.
|
|
|
|
func (f *writeOnlyFile) Seek(offset int64, whence int) (int64, error) {
|
|
|
|
return 0, &os.PathError{
|
|
|
|
Op: "seek",
|
|
|
|
Path: f.name,
|
|
|
|
Err: errors.New("seek not supported"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stat implements webdav.File.
|
|
|
|
func (f *writeOnlyFile) Stat() (fs.FileInfo, error) {
|
|
|
|
fi, err := f.fs.Stat(context.Background(), f.name)
|
|
|
|
if err != nil {
|
|
|
|
// use static info for newly created file
|
|
|
|
now := f.fs.now()
|
|
|
|
fi = &shared.StaticFileInfo{
|
|
|
|
Named: f.name,
|
|
|
|
Sized: 0,
|
|
|
|
Moded: f.perm,
|
|
|
|
BirthedTime: now,
|
|
|
|
ModdedTime: now,
|
|
|
|
Dir: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fi, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read implements webdav.File. As this is a write-only file, it always fails
|
|
|
|
// with an os.PathError.
|
|
|
|
func (f *writeOnlyFile) Read(p []byte) (int, error) {
|
|
|
|
return 0, &os.PathError{
|
|
|
|
Op: "write",
|
|
|
|
Path: f.name,
|
|
|
|
Err: errors.New("write-only"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write implements webdav.File.
|
|
|
|
func (f *writeOnlyFile) Write(p []byte) (int, error) {
|
|
|
|
select {
|
|
|
|
case err := <-f.finalError:
|
|
|
|
return 0, err
|
|
|
|
default:
|
|
|
|
return f.WriteCloser.Write(p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close implements webdav.File.
|
|
|
|
func (f *writeOnlyFile) Close() error {
|
|
|
|
err := f.WriteCloser.Close()
|
|
|
|
writeErr := <-f.finalError
|
|
|
|
if writeErr != nil {
|
|
|
|
return writeErr
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|