1// Copyright 2016 Keybase Inc. All rights reserved.
2// Use of this source code is governed by a BSD
3// license that can be found in the LICENSE file.
4
5package libdokan
6
7import (
8	"time"
9
10	"github.com/keybase/client/go/kbfs/dokan"
11	"golang.org/x/net/context"
12)
13
14// SpecialReadFile represents a file whose contents are determined by
15// a function.
16type SpecialReadFile struct {
17	read func(context.Context) ([]byte, time.Time, error)
18	fs   *FS
19	emptyFile
20}
21
22// GetFileInformation does stats for dokan.
23func (f *SpecialReadFile) GetFileInformation(ctx context.Context, fi *dokan.FileInfo) (*dokan.Stat, error) {
24	f.fs.logEnter(ctx, "SpecialReadFile GetFileInformation")
25	data, t, err := f.read(ctx)
26	if err != nil {
27		return nil, err
28	}
29
30	// Some apps (e.g., Chrome) get confused if we use a 0 size
31	// here, as is usual for pseudofiles. So return the actual
32	// size, even though it may be racy.
33	a, err := defaultFileInformation()
34	if err != nil {
35		return nil, err
36	}
37	a.FileAttributes |= dokan.FileAttributeReadonly
38	a.FileSize = int64(len(data))
39	a.LastWrite = t
40	a.LastAccess = t
41	a.Creation = t
42	return a, nil
43}
44
45// ReadFile does reads for dokan.
46func (f *SpecialReadFile) ReadFile(ctx context.Context, fi *dokan.FileInfo, bs []byte, offset int64) (int, error) {
47	f.fs.logEnter(ctx, "SpecialReadFile ReadFile")
48	data, _, err := f.read(ctx)
49	if err != nil {
50		return 0, err
51	}
52
53	if offset >= int64(len(data)) {
54		return 0, nil
55	}
56
57	data = data[int(offset):]
58
59	return copy(bs, data), nil
60}
61