github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/types.go (about)

     1  // Filesystem related types and interfaces
     2  // Note that optional interfaces are found in features.go
     3  
     4  package fs
     5  
     6  import (
     7  	"context"
     8  	"io"
     9  	"time"
    10  
    11  	"github.com/rclone/rclone/fs/hash"
    12  )
    13  
    14  // Fs is the interface a cloud storage system must provide
    15  type Fs interface {
    16  	Info
    17  
    18  	// List the objects and directories in dir into entries.  The
    19  	// entries can be returned in any order but should be for a
    20  	// complete directory.
    21  	//
    22  	// dir should be "" to list the root, and should not have
    23  	// trailing slashes.
    24  	//
    25  	// This should return ErrDirNotFound if the directory isn't
    26  	// found.
    27  	List(ctx context.Context, dir string) (entries DirEntries, err error)
    28  
    29  	// NewObject finds the Object at remote.  If it can't be found
    30  	// it returns the error ErrorObjectNotFound.
    31  	//
    32  	// If remote points to a directory then it should return
    33  	// ErrorIsDir if possible without doing any extra work,
    34  	// otherwise ErrorObjectNotFound.
    35  	NewObject(ctx context.Context, remote string) (Object, error)
    36  
    37  	// Put in to the remote path with the modTime given of the given size
    38  	//
    39  	// When called from outside an Fs by rclone, src.Size() will always be >= 0.
    40  	// But for unknown-sized objects (indicated by src.Size() == -1), Put should either
    41  	// return an error or upload it properly (rather than e.g. calling panic).
    42  	//
    43  	// May create the object even if it returns an error - if so
    44  	// will return the object and the error, otherwise will return
    45  	// nil and the error
    46  	Put(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
    47  
    48  	// Mkdir makes the directory (container, bucket)
    49  	//
    50  	// Shouldn't return an error if it already exists
    51  	Mkdir(ctx context.Context, dir string) error
    52  
    53  	// Rmdir removes the directory (container, bucket) if empty
    54  	//
    55  	// Return an error if it doesn't exist or isn't empty
    56  	Rmdir(ctx context.Context, dir string) error
    57  }
    58  
    59  // Info provides a read only interface to information about a filesystem.
    60  type Info interface {
    61  	// Name of the remote (as passed into NewFs)
    62  	Name() string
    63  
    64  	// Root of the remote (as passed into NewFs)
    65  	Root() string
    66  
    67  	// String returns a description of the FS
    68  	String() string
    69  
    70  	// Precision of the ModTimes in this Fs
    71  	Precision() time.Duration
    72  
    73  	// Returns the supported hash types of the filesystem
    74  	Hashes() hash.Set
    75  
    76  	// Features returns the optional features of this Fs
    77  	Features() *Features
    78  }
    79  
    80  // Object is a filesystem like object provided by an Fs
    81  type Object interface {
    82  	ObjectInfo
    83  
    84  	// SetModTime sets the metadata on the object to set the modification date
    85  	SetModTime(ctx context.Context, t time.Time) error
    86  
    87  	// Open opens the file for read.  Call Close() on the returned io.ReadCloser
    88  	Open(ctx context.Context, options ...OpenOption) (io.ReadCloser, error)
    89  
    90  	// Update in to the object with the modTime given of the given size
    91  	//
    92  	// When called from outside an Fs by rclone, src.Size() will always be >= 0.
    93  	// But for unknown-sized objects (indicated by src.Size() == -1), Upload should either
    94  	// return an error or update the object properly (rather than e.g. calling panic).
    95  	Update(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) error
    96  
    97  	// Removes this object
    98  	Remove(ctx context.Context) error
    99  }
   100  
   101  // ObjectInfo provides read only information about an object.
   102  type ObjectInfo interface {
   103  	DirEntry
   104  
   105  	// Hash returns the selected checksum of the file
   106  	// If no checksum is available it returns ""
   107  	Hash(ctx context.Context, ty hash.Type) (string, error)
   108  
   109  	// Storable says whether this object can be stored
   110  	Storable() bool
   111  }
   112  
   113  // DirEntry provides read only information about the common subset of
   114  // a Dir or Object.  These are returned from directory listings - type
   115  // assert them into the correct type.
   116  type DirEntry interface {
   117  	// Fs returns read only access to the Fs that this object is part of
   118  	Fs() Info
   119  
   120  	// String returns a description of the Object
   121  	String() string
   122  
   123  	// Remote returns the remote path
   124  	Remote() string
   125  
   126  	// ModTime returns the modification date of the file
   127  	// It should return a best guess if one isn't available
   128  	ModTime(context.Context) time.Time
   129  
   130  	// Size returns the size of the file
   131  	Size() int64
   132  }
   133  
   134  // Directory is a filesystem like directory provided by an Fs
   135  type Directory interface {
   136  	DirEntry
   137  
   138  	// Items returns the count of items in this directory or this
   139  	// directory and subdirectories if known, -1 for unknown
   140  	Items() int64
   141  
   142  	// ID returns the internal ID of this directory if known, or
   143  	// "" otherwise
   144  	ID() string
   145  }
   146  
   147  // FullDirectory contains all the optional interfaces for Directory
   148  //
   149  // Use for checking making wrapping Directories implement everything
   150  type FullDirectory interface {
   151  	Directory
   152  	Metadataer
   153  	SetMetadataer
   154  	SetModTimer
   155  }
   156  
   157  // MimeTyper is an optional interface for Object
   158  type MimeTyper interface {
   159  	// MimeType returns the content type of the Object if
   160  	// known, or "" if not
   161  	MimeType(ctx context.Context) string
   162  }
   163  
   164  // IDer is an optional interface for Object
   165  type IDer interface {
   166  	// ID returns the ID of the Object if known, or "" if not
   167  	ID() string
   168  }
   169  
   170  // ParentIDer is an optional interface for Object
   171  type ParentIDer interface {
   172  	// ParentID returns the ID of the parent directory if known or nil if not
   173  	ParentID() string
   174  }
   175  
   176  // ObjectUnWrapper is an optional interface for Object
   177  type ObjectUnWrapper interface {
   178  	// UnWrap returns the Object that this Object is wrapping or
   179  	// nil if it isn't wrapping anything
   180  	UnWrap() Object
   181  }
   182  
   183  // SetTierer is an optional interface for Object
   184  type SetTierer interface {
   185  	// SetTier performs changing storage tier of the Object if
   186  	// multiple storage classes supported
   187  	SetTier(tier string) error
   188  }
   189  
   190  // GetTierer is an optional interface for Object
   191  type GetTierer interface {
   192  	// GetTier returns storage tier or class of the Object
   193  	GetTier() string
   194  }
   195  
   196  // Metadataer is an optional interface for DirEntry
   197  type Metadataer interface {
   198  	// Metadata returns metadata for an DirEntry
   199  	//
   200  	// It should return nil if there is no Metadata
   201  	Metadata(ctx context.Context) (Metadata, error)
   202  }
   203  
   204  // SetMetadataer is an optional interface for DirEntry
   205  type SetMetadataer interface {
   206  	// SetMetadata sets metadata for an DirEntry
   207  	//
   208  	// It should return fs.ErrorNotImplemented if it can't set metadata
   209  	SetMetadata(ctx context.Context, metadata Metadata) error
   210  }
   211  
   212  // SetModTimer is an optional interface for Directory.
   213  //
   214  // Object implements this as part of its requires set of interfaces.
   215  type SetModTimer interface {
   216  	// SetModTime sets the metadata on the DirEntry to set the modification date
   217  	//
   218  	// If there is any other metadata it does not overwrite it.
   219  	SetModTime(ctx context.Context, t time.Time) error
   220  }
   221  
   222  // FullObjectInfo contains all the read-only optional interfaces
   223  //
   224  // Use for checking making wrapping ObjectInfos implement everything
   225  type FullObjectInfo interface {
   226  	ObjectInfo
   227  	MimeTyper
   228  	IDer
   229  	ObjectUnWrapper
   230  	GetTierer
   231  	Metadataer
   232  }
   233  
   234  // FullObject contains all the optional interfaces for Object
   235  //
   236  // Use for checking making wrapping Objects implement everything
   237  type FullObject interface {
   238  	Object
   239  	MimeTyper
   240  	IDer
   241  	ObjectUnWrapper
   242  	GetTierer
   243  	SetTierer
   244  	Metadataer
   245  	SetMetadataer
   246  }
   247  
   248  // ObjectOptionalInterfaces returns the names of supported and
   249  // unsupported optional interfaces for an Object
   250  func ObjectOptionalInterfaces(o Object) (supported, unsupported []string) {
   251  	store := func(ok bool, name string) {
   252  		if ok {
   253  			supported = append(supported, name)
   254  		} else {
   255  			unsupported = append(unsupported, name)
   256  		}
   257  	}
   258  
   259  	_, ok := o.(MimeTyper)
   260  	store(ok, "MimeType")
   261  
   262  	_, ok = o.(IDer)
   263  	store(ok, "ID")
   264  
   265  	_, ok = o.(ObjectUnWrapper)
   266  	store(ok, "UnWrap")
   267  
   268  	_, ok = o.(SetTierer)
   269  	store(ok, "SetTier")
   270  
   271  	_, ok = o.(GetTierer)
   272  	store(ok, "GetTier")
   273  
   274  	_, ok = o.(Metadataer)
   275  	store(ok, "Metadata")
   276  
   277  	_, ok = o.(SetMetadataer)
   278  	store(ok, "SetMetadata")
   279  
   280  	return supported, unsupported
   281  }
   282  
   283  // DirectoryOptionalInterfaces returns the names of supported and
   284  // unsupported optional interfaces for a Directory
   285  func DirectoryOptionalInterfaces(d Directory) (supported, unsupported []string) {
   286  	store := func(ok bool, name string) {
   287  		if ok {
   288  			supported = append(supported, name)
   289  		} else {
   290  			unsupported = append(unsupported, name)
   291  		}
   292  	}
   293  
   294  	_, ok := d.(Metadataer)
   295  	store(ok, "Metadata")
   296  
   297  	_, ok = d.(SetMetadataer)
   298  	store(ok, "SetMetadata")
   299  
   300  	_, ok = d.(SetModTimer)
   301  	store(ok, "SetModTime")
   302  
   303  	return supported, unsupported
   304  }
   305  
   306  // ListRCallback defines a callback function for ListR to use
   307  //
   308  // It is called for each tranche of entries read from the listing and
   309  // if it returns an error, the listing stops.
   310  type ListRCallback func(entries DirEntries) error
   311  
   312  // ListRFn is defines the call used to recursively list a directory
   313  type ListRFn func(ctx context.Context, dir string, callback ListRCallback) error
   314  
   315  // NewUsageValue makes a valid value
   316  func NewUsageValue(value int64) *int64 {
   317  	p := new(int64)
   318  	*p = value
   319  	return p
   320  }
   321  
   322  // Usage is returned by the About call
   323  //
   324  // If a value is nil then it isn't supported by that backend
   325  type Usage struct {
   326  	Total   *int64 `json:"total,omitempty"`   // quota of bytes that can be used
   327  	Used    *int64 `json:"used,omitempty"`    // bytes in use
   328  	Trashed *int64 `json:"trashed,omitempty"` // bytes in trash
   329  	Other   *int64 `json:"other,omitempty"`   // other usage e.g. gmail in drive
   330  	Free    *int64 `json:"free,omitempty"`    // bytes which can be uploaded before reaching the quota
   331  	Objects *int64 `json:"objects,omitempty"` // objects in the storage system
   332  }
   333  
   334  // WriterAtCloser wraps io.WriterAt and io.Closer
   335  type WriterAtCloser interface {
   336  	io.WriterAt
   337  	io.Closer
   338  }
   339  
   340  type unknownFs struct{}
   341  
   342  // Name of the remote (as passed into NewFs)
   343  func (unknownFs) Name() string { return "unknown" }
   344  
   345  // Root of the remote (as passed into NewFs)
   346  func (unknownFs) Root() string { return "" }
   347  
   348  // String returns a description of the FS
   349  func (unknownFs) String() string { return "unknown" }
   350  
   351  // Precision of the ModTimes in this Fs
   352  func (unknownFs) Precision() time.Duration { return ModTimeNotSupported }
   353  
   354  // Returns the supported hash types of the filesystem
   355  func (unknownFs) Hashes() hash.Set { return hash.Set(hash.None) }
   356  
   357  // Features returns the optional features of this Fs
   358  func (unknownFs) Features() *Features { return &Features{} }
   359  
   360  // Unknown holds an Info for an unknown Fs
   361  //
   362  // This is used when we need an Fs but don't have one.
   363  var Unknown Info = unknownFs{}