summaryrefslogtreecommitdiffhomepage
path: root/drive/driveimpl/birthtiming.go
blob: d55ea0b83c32287c282e3aab7f606b8d0a8073d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause

package driveimpl

import (
	"context"
	"io/fs"
	"os"
	"time"

	"github.com/djherbis/times"
	"github.com/tailscale/xnet/webdav"
)

// birthTimingFS extends a webdav.FileSystem to return FileInfos that implement
// the webdav.BirthTimer interface.
type birthTimingFS struct {
	webdav.FileSystem
}

func (fs *birthTimingFS) Stat(ctx context.Context, name string) (os.FileInfo, error) {
	fi, err := fs.FileSystem.Stat(ctx, name)
	if err != nil {
		return nil, err
	}
	return &birthTimingFileInfo{fi}, nil
}

func (fs *birthTimingFS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
	f, err := fs.FileSystem.OpenFile(ctx, name, flag, perm)
	if err != nil {
		return nil, err
	}

	return &birthTimingFile{f}, nil
}

// birthTimingFileInfo extends an os.FileInfo to implement the BirthTimer
// interface.
type birthTimingFileInfo struct {
	os.FileInfo
}

func (fi *birthTimingFileInfo) BirthTime(ctx context.Context) (time.Time, error) {
	if fi.Sys() == nil {
		return time.Time{}, webdav.ErrNotImplemented
	}

	if !times.HasBirthTime {
		return time.Time{}, webdav.ErrNotImplemented
	}

	return times.Get(fi.FileInfo).BirthTime(), nil
}

// birthTimingFile extends a webdav.File to return FileInfos that implement the
// BirthTimer interface.
type birthTimingFile struct {
	webdav.File
}

func (f *birthTimingFile) Stat() (fs.FileInfo, error) {
	fi, err := f.File.Stat()
	if err != nil {
		return nil, err
	}

	return &birthTimingFileInfo{fi}, nil
}

func (f *birthTimingFile) Readdir(count int) ([]fs.FileInfo, error) {
	fis, err := f.File.Readdir(count)
	if err != nil {
		return nil, err
	}

	for i, fi := range fis {
		fis[i] = &birthTimingFileInfo{fi}
	}

	return fis, nil
}