mirror of
https://github.com/restic/restic.git
synced 2024-09-06 11:29:26 +02:00
410 lines
10 KiB
Go
410 lines
10 KiB
Go
package record // import "bazil.org/fuse/fs/fstestutil/record"
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"bazil.org/fuse"
|
|
"bazil.org/fuse/fs"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// Writes gathers data from FUSE Write calls.
|
|
type Writes struct {
|
|
buf Buffer
|
|
}
|
|
|
|
var _ = fs.HandleWriter(&Writes{})
|
|
|
|
func (w *Writes) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
|
|
n, err := w.buf.Write(req.Data)
|
|
resp.Size = n
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *Writes) RecordedWriteData() []byte {
|
|
return w.buf.Bytes()
|
|
}
|
|
|
|
// Counter records number of times a thing has occurred.
|
|
type Counter struct {
|
|
count uint32
|
|
}
|
|
|
|
func (r *Counter) Inc() {
|
|
atomic.AddUint32(&r.count, 1)
|
|
}
|
|
|
|
func (r *Counter) Count() uint32 {
|
|
return atomic.LoadUint32(&r.count)
|
|
}
|
|
|
|
// MarkRecorder records whether a thing has occurred.
|
|
type MarkRecorder struct {
|
|
count Counter
|
|
}
|
|
|
|
func (r *MarkRecorder) Mark() {
|
|
r.count.Inc()
|
|
}
|
|
|
|
func (r *MarkRecorder) Recorded() bool {
|
|
return r.count.Count() > 0
|
|
}
|
|
|
|
// Flushes notes whether a FUSE Flush call has been seen.
|
|
type Flushes struct {
|
|
rec MarkRecorder
|
|
}
|
|
|
|
var _ = fs.HandleFlusher(&Flushes{})
|
|
|
|
func (r *Flushes) Flush(ctx context.Context, req *fuse.FlushRequest) error {
|
|
r.rec.Mark()
|
|
return nil
|
|
}
|
|
|
|
func (r *Flushes) RecordedFlush() bool {
|
|
return r.rec.Recorded()
|
|
}
|
|
|
|
type Recorder struct {
|
|
mu sync.Mutex
|
|
val interface{}
|
|
}
|
|
|
|
// Record that we've seen value. A nil value is indistinguishable from
|
|
// no value recorded.
|
|
func (r *Recorder) Record(value interface{}) {
|
|
r.mu.Lock()
|
|
r.val = value
|
|
r.mu.Unlock()
|
|
}
|
|
|
|
func (r *Recorder) Recorded() interface{} {
|
|
r.mu.Lock()
|
|
val := r.val
|
|
r.mu.Unlock()
|
|
return val
|
|
}
|
|
|
|
type RequestRecorder struct {
|
|
rec Recorder
|
|
}
|
|
|
|
// Record a fuse.Request, after zeroing header fields that are hard to
|
|
// reproduce.
|
|
//
|
|
// Make sure to record a copy, not the original request.
|
|
func (r *RequestRecorder) RecordRequest(req fuse.Request) {
|
|
hdr := req.Hdr()
|
|
*hdr = fuse.Header{}
|
|
r.rec.Record(req)
|
|
}
|
|
|
|
func (r *RequestRecorder) Recorded() fuse.Request {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return nil
|
|
}
|
|
return val.(fuse.Request)
|
|
}
|
|
|
|
// Setattrs records a Setattr request and its fields.
|
|
type Setattrs struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeSetattrer(&Setattrs{})
|
|
|
|
func (r *Setattrs) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil
|
|
}
|
|
|
|
func (r *Setattrs) RecordedSetattr() fuse.SetattrRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.SetattrRequest{}
|
|
}
|
|
return *(val.(*fuse.SetattrRequest))
|
|
}
|
|
|
|
// Fsyncs records an Fsync request and its fields.
|
|
type Fsyncs struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeFsyncer(&Fsyncs{})
|
|
|
|
func (r *Fsyncs) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil
|
|
}
|
|
|
|
func (r *Fsyncs) RecordedFsync() fuse.FsyncRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.FsyncRequest{}
|
|
}
|
|
return *(val.(*fuse.FsyncRequest))
|
|
}
|
|
|
|
// Mkdirs records a Mkdir request and its fields.
|
|
type Mkdirs struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeMkdirer(&Mkdirs{})
|
|
|
|
// Mkdir records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Mkdirs) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil, fuse.EIO
|
|
}
|
|
|
|
// RecordedMkdir returns information about the Mkdir request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Mkdirs) RecordedMkdir() fuse.MkdirRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.MkdirRequest{}
|
|
}
|
|
return *(val.(*fuse.MkdirRequest))
|
|
}
|
|
|
|
// Symlinks records a Symlink request and its fields.
|
|
type Symlinks struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeSymlinker(&Symlinks{})
|
|
|
|
// Symlink records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Symlinks) Symlink(ctx context.Context, req *fuse.SymlinkRequest) (fs.Node, error) {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil, fuse.EIO
|
|
}
|
|
|
|
// RecordedSymlink returns information about the Symlink request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Symlinks) RecordedSymlink() fuse.SymlinkRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.SymlinkRequest{}
|
|
}
|
|
return *(val.(*fuse.SymlinkRequest))
|
|
}
|
|
|
|
// Links records a Link request and its fields.
|
|
type Links struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeLinker(&Links{})
|
|
|
|
// Link records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Links) Link(ctx context.Context, req *fuse.LinkRequest, old fs.Node) (fs.Node, error) {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil, fuse.EIO
|
|
}
|
|
|
|
// RecordedLink returns information about the Link request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Links) RecordedLink() fuse.LinkRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.LinkRequest{}
|
|
}
|
|
return *(val.(*fuse.LinkRequest))
|
|
}
|
|
|
|
// Mknods records a Mknod request and its fields.
|
|
type Mknods struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeMknoder(&Mknods{})
|
|
|
|
// Mknod records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Mknods) Mknod(ctx context.Context, req *fuse.MknodRequest) (fs.Node, error) {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil, fuse.EIO
|
|
}
|
|
|
|
// RecordedMknod returns information about the Mknod request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Mknods) RecordedMknod() fuse.MknodRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.MknodRequest{}
|
|
}
|
|
return *(val.(*fuse.MknodRequest))
|
|
}
|
|
|
|
// Opens records a Open request and its fields.
|
|
type Opens struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeOpener(&Opens{})
|
|
|
|
// Open records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Opens) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil, fuse.EIO
|
|
}
|
|
|
|
// RecordedOpen returns information about the Open request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Opens) RecordedOpen() fuse.OpenRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.OpenRequest{}
|
|
}
|
|
return *(val.(*fuse.OpenRequest))
|
|
}
|
|
|
|
// Getxattrs records a Getxattr request and its fields.
|
|
type Getxattrs struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeGetxattrer(&Getxattrs{})
|
|
|
|
// Getxattr records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Getxattrs) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse) error {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return fuse.ErrNoXattr
|
|
}
|
|
|
|
// RecordedGetxattr returns information about the Getxattr request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Getxattrs) RecordedGetxattr() fuse.GetxattrRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.GetxattrRequest{}
|
|
}
|
|
return *(val.(*fuse.GetxattrRequest))
|
|
}
|
|
|
|
// Listxattrs records a Listxattr request and its fields.
|
|
type Listxattrs struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeListxattrer(&Listxattrs{})
|
|
|
|
// Listxattr records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Listxattrs) Listxattr(ctx context.Context, req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse) error {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return fuse.ErrNoXattr
|
|
}
|
|
|
|
// RecordedListxattr returns information about the Listxattr request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Listxattrs) RecordedListxattr() fuse.ListxattrRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.ListxattrRequest{}
|
|
}
|
|
return *(val.(*fuse.ListxattrRequest))
|
|
}
|
|
|
|
// Setxattrs records a Setxattr request and its fields.
|
|
type Setxattrs struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeSetxattrer(&Setxattrs{})
|
|
|
|
// Setxattr records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Setxattrs) Setxattr(ctx context.Context, req *fuse.SetxattrRequest) error {
|
|
tmp := *req
|
|
// The byte slice points to memory that will be reused, so make a
|
|
// deep copy.
|
|
tmp.Xattr = append([]byte(nil), req.Xattr...)
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil
|
|
}
|
|
|
|
// RecordedSetxattr returns information about the Setxattr request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Setxattrs) RecordedSetxattr() fuse.SetxattrRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.SetxattrRequest{}
|
|
}
|
|
return *(val.(*fuse.SetxattrRequest))
|
|
}
|
|
|
|
// Removexattrs records a Removexattr request and its fields.
|
|
type Removexattrs struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeRemovexattrer(&Removexattrs{})
|
|
|
|
// Removexattr records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Removexattrs) Removexattr(ctx context.Context, req *fuse.RemovexattrRequest) error {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil
|
|
}
|
|
|
|
// RecordedRemovexattr returns information about the Removexattr request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Removexattrs) RecordedRemovexattr() fuse.RemovexattrRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.RemovexattrRequest{}
|
|
}
|
|
return *(val.(*fuse.RemovexattrRequest))
|
|
}
|
|
|
|
// Creates records a Create request and its fields.
|
|
type Creates struct {
|
|
rec RequestRecorder
|
|
}
|
|
|
|
var _ = fs.NodeCreater(&Creates{})
|
|
|
|
// Create records the request and returns an error. Most callers should
|
|
// wrap this call in a function that returns a more useful result.
|
|
func (r *Creates) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) {
|
|
tmp := *req
|
|
r.rec.RecordRequest(&tmp)
|
|
return nil, nil, fuse.EIO
|
|
}
|
|
|
|
// RecordedCreate returns information about the Create request.
|
|
// If no request was seen, returns a zero value.
|
|
func (r *Creates) RecordedCreate() fuse.CreateRequest {
|
|
val := r.rec.Recorded()
|
|
if val == nil {
|
|
return fuse.CreateRequest{}
|
|
}
|
|
return *(val.(*fuse.CreateRequest))
|
|
}
|