#ifndef __SFS_INTERFACE_H__
#define __SFS_INTERFACE_H__
/******************************************************************************/
/*                                                                            */
/*                    X r d S f s I n t e r f a c e . h h                     */
/*                                                                            */
/* (c) 2018 by the Board of Trustees of the Leland Stanford, Jr., University  */
/*   Produced by Andrew Hanushevsky for Stanford University under contract    */
/*              DE-AC02-76-SFO0515 with the Department of Energy              */
/*                                                                            */
/* This file is part of the XRootD software suite.                            */
/*                                                                            */
/* XRootD is free software: you can redistribute it and/or modify it under    */
/* the terms of the GNU Lesser General Public License as published by the     */
/* Free Software Foundation, either version 3 of the License, or (at your     */
/* option) any later version.                                                 */
/*                                                                            */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT      */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      */
/* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public       */
/* License for more details.                                                  */
/*                                                                            */
/* You should have received a copy of the GNU Lesser General Public License   */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file  */
/* COPYING (GPL license).  If not, see <http://www.gnu.org/licenses/>.        */
/*                                                                            */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without  */
/* specific prior written permission of the institution or contributor.       */
/******************************************************************************/

#include <cstring>      // For strlcpy()
#include <cerrno>
#include <cstdint>
#include <sys/types.h>
#include <sys/stat.h>

#include "XrdOuc/XrdOucErrInfo.hh"
#include "XrdOuc/XrdOucIOVec.hh"
#include "XrdOuc/XrdOucSFVec.hh"

#include "XrdSfs/XrdSfsGPFile.hh"

#include "XrdSys/XrdSysPageSize.hh"

/******************************************************************************/
/*                            O p e n   M o d e s                             */
/******************************************************************************/

#define SFS_O_RDONLY           0         // open read/only
#define SFS_O_WRONLY           1         // open write/only
#define SFS_O_RDWR             2         // open read/write
#define SFS_O_CREAT   0x00000100         // used for file creation
#define SFS_O_TRUNC   0x00000200         // used for file truncation
#define SFS_O_MULTIW  0x00000400         // used for multi-write locations
#define SFS_O_NOTPC   0x00000800         // used to suppress TPC opens
#define SFS_O_DIRLIST 0x00010000         // used for locate only
#define SFS_O_POSC    0x00100000         // persist on successful close
#define SFS_O_FORCE   0x00200000         // used for locate only
#define SFS_O_HNAME   0x00400000         // used for locate only
#define SFS_O_LOCAL   0x00800000         // used for locate only (local cmd)
#define SFS_O_NOWAIT  0x01000000         // do not impose operational delays
#define SFS_O_RAWIO   0x02000000         // allow client-side decompression
#define SFS_O_RESET   0x04000000         // Reset any cached information
#define SFS_O_REPLICA 0x08000000         // Open for replication

// The following flag may be set in the access mode arg for open() & mkdir()
// Note that on some systems mode_t is 16-bits so we use a careful value!
//
#define SFS_O_MKPTH   0x00004000         // Make directory path if missing

// The following options are here to provide a uniform clustering interface.
// They may be passed through open/locate/stat, as applicable.
//
#define SFS_O_LOCATE  0x10000000         // This request generated by locate()
#define SFS_O_STAT    0x20000000         // This request generated by stat()
#define SFS_O_META    0x40000000         // This request generated by metaop

/******************************************************************************/
/*                               D e f i n e s                                */
/******************************************************************************/

// Common fctl  command values (0 to 255)
//
#define SFS_FCTL_GETFD    1 // Return file descriptor if possible
#define SFS_FCTL_STATV    2 // Return visa information
#define SFS_FCTL_SPEC1    3 // Return implementation defined information

#define SFS_SFIO_FDVAL 0x80000000 // Use SendData() method GETFD response value

// Common fsctl command values (0 to 255)
//
#define SFS_FSCTL_CMD   255

#define SFS_FSCTL_LOCATE  1 // Locate a file
#define SFS_FSCTL_STATFS  2 // Return FS data
#define SFS_FSCTL_STATLS  3 // Return LS data
#define SFS_FSCTL_STATXA  4 // Return XA data
#define SFS_FSCTL_STATCC  5 // Return Cluster Config status
#define SFS_FSCTL_PLUGIN  8 // Return Implementation Dependent Data
#define SFS_FSCTL_PLUGIO 16 // Return Implementation Dependent Data

// Return values for integer & XrdSfsXferSize returning XrdSfs methods
//
#define SFS_STALL         1 // Return value -> Seconds to stall client
#define SFS_OK            0 // ErrInfo code -> All is well
#define SFS_ERROR        -1 // ErrInfo code -> Error occurred
#define SFS_REDIRECT   -256 // ErrInfo code -> Port number to redirect to
#define SFS_STARTED    -512 // ErrInfo code -> Estimated seconds to completion
#define SFS_DATA      -1024 // ErrInfo code -> Length of data
#define SFS_DATAVEC   -2048 // ErrInfo code -> Num iovec elements in msgbuff

// The following macros are used for dealing with special local paths
//
#define SFS_LCLPRFX    "/=/"
#define SFS_LCLPLEN    3
#define SFS_LCLPATH(x) !strncmp(x, SFS_LCLPRFX, SFS_LCLPLEN)
#define SFS_LCLPRFY    "/="
#define SFS_LCLROOT(x) !strncmp(x, SFS_LCLPRFX, SFS_LCLPLEN-1) \
                       && (*(x+SFS_LCLPLEN-1) == '/' || *(x+SFS_LCLPLEN-1) == 0)

/******************************************************************************/
/*                 S t r u c t u r e s   &   T y p e d e f s                  */
/******************************************************************************/

typedef long long     XrdSfsFileOffset;
typedef int           XrdSfsFileOpenMode;
typedef int           XrdSfsMode;
typedef int           XrdSfsXferSize;

enum XrdSfsFileExistence 
{
     XrdSfsFileExistNo,
     XrdSfsFileExistIsFile,
     XrdSfsFileExistIsDirectory,
     XrdSfsFileExistIsOffline,
     XrdSfsFileExistIsOther
};
//------------------------------------------------

#define Prep_PRTY0 0
#define Prep_PRTY1 1
#define Prep_PRTY2 2
#define Prep_PRTY3 3
#define Prep_PMASK 3
#define Prep_SENDAOK 4
#define Prep_SENDERR 8
#define Prep_SENDACK 12
#define Prep_WMODE   16
#define Prep_STAGE   32
#define Prep_COLOC   64
#define Prep_FRESH  128
#define Prep_CANCEL 256
#define Prep_QUERY  512
#define Prep_EVICT 1024

class XrdOucTList;

struct XrdSfsFSctl //!< SFS_FSCTL_PLUGIN/PLUGIO parms
{
 const char            *Arg1;      //!< PLUGIO, PLUGIN
       int              Arg1Len;   //!< Length
       int              Arg2Len;   //!< Length
 const char            *Arg2;      //!< PLUGIN  opaque string
};

struct XrdSfsPrep  //!< Prepare parameters
{
       char            *reqid;     //!< Request ID
       char            *notify;    //!< Notification path or 0
       int              opts;      //!< Prep_xxx
       XrdOucTList     *paths;     //!< List of paths
       XrdOucTList     *oinfo;     //!< 1-to-1 correspondence of opaque info
};

/******************************************************************************/
/*                  F o r w a r d   D e c l a r a t i o n s                   */
/******************************************************************************/

class  XrdOucEnv;
class  XrdSecEntity;
struct XrdSfsFACtl;

/******************************************************************************/
/*                 O b j e c t   W r a p p i n g   G u i d e                  */
/******************************************************************************/

/* The XrdSfsDirectory and XrdSfsFile objects can be wrapped. Wraping can be
   used to add functionality. The process is common and pretty muche rote.
   There is only one caveat: all wrappers must use the same XrdOucErrInfo
   object. This is because the ErrInfo object contains client parameters that
   are used to control how things are done to be backward compatible. Newer
   client can then use more efficient internal processing. The SFS provides
   two ways to make sure the same ErrInfo object is used by all objects in
   the wrapped chain. Forward propagation (the one typically used) and
   backward propagation (used in certain unusual cases). In forward mode,
   the ErrInfo object of the last object in the chain is propagated to the
   front of the chain. In backward mode the reverse happens. Let's assume
   the following scenarion. Object-A wraps object-B (the object here can be
   directory or file object). In forward mode weneed to create objects in
   reverse order (bottom to top) which is typically what you would do anyway
   as you need to capture the pinter to the object your wrapping. So, using
   newFile() as an example where sfsP points to the Interface being wrapped:

   XrdSfsFile *newFile(const char *user, int MonID)
   {
      XrdSfsFile *wrapped_file = sfsP->newFile(user, MonID);
      if (!wrapped_file) return 0;
      return new mySfsFile(wrapped_file,...);
   }
   class mySfsFile : public XrdSfsFile
   {public:
      mySfsFile(XrdSfsFile *wrapped_file,...) : XrdSfsFile(*wrapped_file)
               {....}
    ....
   };

   Notice we are allocating the wrapped file ahead of the wrapper so that
   the wrapper can use the ErrInfo object of the wrapped file.

   In backward mode we want to use the ErrInfo object of the front-most
   wrapper for all wrappers after it. This mechanism is far more complicated
   due to error handling requirements. However, it's useful when a wrapped
   object is not necessarily instantiated to accomplish the needs of the
   wrapper. An example of this is the newFile and newDir implementations for
   XrdSsi where wrapped object creation is subject to the resource name.
*/

/******************************************************************************/
/*                       X r d S f s D i r e c t o r y                        */
/******************************************************************************/

//------------------------------------------------------------------------------
//! The XrdSfsDirectory object is returned by XrdSfsFileSystem::newFile() when
//! the caller wants to be able to perform directory oriented operations.
//------------------------------------------------------------------------------
  
class XrdSfsDirectory
{
public:

//-----------------------------------------------------------------------------
//! The error object is used to return details whenever something other than
//! SFS_OK is returned from the methods in this class, when noted.
//-----------------------------------------------------------------------------

        XrdOucErrInfo &error;

//-----------------------------------------------------------------------------
//! Open a directory.
//!
//! @param  path   - Pointer to the path of the directory to be opened.
//! @param  client - Client's identify (see common description).
//! @param  opaque - path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, ir SFS_STALL
//-----------------------------------------------------------------------------

virtual int         open(const char              *path,
                         const XrdSecEntity      *client = 0,
                         const char              *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Get the next directory entry.
//!
//! @return A null terminated string with the directory name. Normally, "."
//!         ".." are not returned. If a null pointer is returned then if this
//!         is due to an error, error.code should contain errno. Otherwise,
//!         error.code should contain zero to indicate that no more entries
//!         exist (i.e. end of list). See autoStat() for additional caveats.
//-----------------------------------------------------------------------------

virtual const char *nextEntry() = 0;

//-----------------------------------------------------------------------------
//! Close the directory.
//!
//! @return One of SFS_OK or SFS_ERROR
//-----------------------------------------------------------------------------

virtual int         close() = 0;

//-----------------------------------------------------------------------------
//! Get the directory path.
//!
//! @return Null terminated string of the path used in open().
//-----------------------------------------------------------------------------

virtual const char *FName() = 0;

//-----------------------------------------------------------------------------
//! Set the stat() buffer where stat information is to be placed corresponding
//! to the directory entry returned by nextEntry().
//!
//! @return If supported, SFS_OK should be returned. If not supported, then
//!         SFS_ERROR should be returned with error.code set to ENOTSUP.
//!
//! @note: When autoStat() is in effect, directory entries that have been
//!        deleted from the target directory are quietly skipped.
//-----------------------------------------------------------------------------

virtual int         autoStat(struct stat *buf);

//-----------------------------------------------------------------------------
//! Constructor (user and MonID are the ones passed to newDir()!). This
//! constructor should only be used by base plugins. Plugins that wrap an
//! SfsDirectory should use the second version of the constructor shown below.
//!
//! @param  user   - Text identifying the client responsible for this call.
//!                  The pointer may be null if identification is missing.
//! @param  MonID  - The monitoring identifier assigned to this and all
//!                  future requests using the returned object.
//-----------------------------------------------------------------------------

                    XrdSfsDirectory(const char *user=0, int MonID=0)
                                   : error(*(new XrdOucErrInfo(user, MonID)))
                                   {lclEI = &error;}

//-----------------------------------------------------------------------------
//! Constructor for plugins that wrap another SfsDirectory. This constructor
//! inherits the error object from a wrapped SfsDirectory object so that only
//! one identical error object exists for all directory objects in the chain.
//!
//! @param  wrapD  - Reference to the directory object being wrapped.
//-----------------------------------------------------------------------------

                    XrdSfsDirectory(XrdSfsDirectory &wrapD)
                                   : error(wrapD.error), lclEI(0) {}

//-----------------------------------------------------------------------------
//! Constructor for base plugins that predefined an error object. This is a
//! convenience constructor for base plugins only.
//!
//! @param  eInfo  - Reference to the error object to use.
//-----------------------------------------------------------------------------

                    XrdSfsDirectory(XrdOucErrInfo &eInfo)
                                   : error(eInfo), lclEI(0) {}

//-----------------------------------------------------------------------------
//! Destructor
//-----------------------------------------------------------------------------

virtual            ~XrdSfsDirectory() {if (lclEI) delete lclEI;}

private:
XrdOucErrInfo* lclEI;

}; // class XrdSfsDirectory

/******************************************************************************/
/*                            X r d S f s F i l e                             */
/******************************************************************************/

//------------------------------------------------------------------------------
//! The XrdSfsFile object is returned by XrdSfsFileSystem::newFile() when
//! the caller wants to be able to perform file oriented operations.
//------------------------------------------------------------------------------

class XrdSfsAio;
class XrdSfsDio;
class XrdSfsXio;
  
class XrdSfsFile
{
public:

//-----------------------------------------------------------------------------
//! The error object is used to return details whenever something other than
//! SFS_OK is returned from the methods in this class, when noted.
//-----------------------------------------------------------------------------

        XrdOucErrInfo  &error;

//-----------------------------------------------------------------------------
//! Open a file.
//!
//! @param  path   - Pointer to the path of the file to be opened.
//! @param  oMode  - Flags indicating how the open is to be handled.
//!                  SFS_O_CREAT   create the file
//!                  SFS_O_MKPTH   Make directory path if missing
//!                  SFS_O_NOWAIT  do not impose operational delays
//!                  SFS_O_NOTPC   do not allow TPC operation
//!                  SFS_O_POSC    persist only on successful close
//!                  SFS_O_RAWIO   allow client-side decompression
//!                  SFS_O_RDONLY  open read/only
//!                  SFS_O_RDWR    open read/write
//!                  SFS_O_REPLICA Open for replication
//!                  SFS_O_RESET   Reset any cached information
//!                  SFS_O_TRUNC   truncate existing file to zero length
//!                  SFS_O_WRONLY  open write/only
//! @param  cMode  - The file's mode if it will be created.
//! @param  client - Client's identify (see common description).
//! @param  opaque - path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, SFS_STALL, or SFS_STARTED
//-----------------------------------------------------------------------------

virtual int            open(const char                *fileName,
                                  XrdSfsFileOpenMode   openMode,
                                  mode_t               createMode,
                            const XrdSecEntity        *client = 0,
                            const char                *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Create, delete, query, rollback a file checkpoint or perform an action.
//!
//! @param  act   - The operation to be performed (see cpAct enum below).
//! @param  range - Use and requirement vary by function:
//!                 cpCreate  - Create a new checkpoint, one must not exist.
//!                             Parameters ignored, not applicable.
//!                 cpDelete  - Delete an existing checkpoint, one must exist.
//!                             Parameters ignored, not applicable.
//!                 cpQuery   - Where result is to be returned:
//!                             range[0].offset - Amount currently in use.
//!                             range[0].length - Maximum total length
//!                 cpRestore - Restore data from checkpoint and delete it.
//!                             Parameters ignored, not applicable.
//!                 cpTrunc   - Offset target for truncation.
//!                             range[0].offset - Offset for truncations.
//!                 cpWrite   - Offset/lengths of the file to be checkpointed.
//!                             The checkpoint must exist via previous cpCreate.
//! @param  n     - Number of elements in range. Applies only to cpWrite.
//!
//! @return One of SFS_OK or SFS_ERROR only.
//-----------------------------------------------------------------------------

enum cpAct {cpCreate=0,   //!< Create a checkpoint, one must not be active.
            cpDelete,     //!< Delete an existing checkpoint
            cpRestore,    //!< Restore an active checkpoint and delete it.
            cpQuery,      //!< Return checkpoint limits
            cpTrunc,      //!< Truncate a file within  checkpoint.
            cpWrite       //!< Add data to an existing checkpoint.
           };

virtual int            checkpoint(cpAct act, struct iov *range=0, int n=0);

//-----------------------------------------------------------------------------
//! Close the file.
//!
//! @return One of SFS_OK or SFS_ERROR.
//-----------------------------------------------------------------------------

virtual int            close() = 0;

//-----------------------------------------------------------------------------
//! Execute a special operation on the file (version 1)
//!
//! @param  cmd   - The operation to be performed (see below).
//!                 SFS_FCTL_GETFD    Return file descriptor if possible
//!                 SFS_FCTL_STATV    Reserved for future use.
//! @param  args  - specific arguments to cmd
//!                 SFS_FCTL_GETFD    Set to zero.
//! @param  eInfo  - The object where error info or results are to be returned.
//!                  This is legacy and the error onject may be used as well.
//!
//! @return If an error occurs or the operation is not support, SFS_ERROR
//!         should be returned with error.code set to errno. Otherwise,
//!         SFS_FCTL_GETFD  error.code holds the real file descriptor number
//!                         If the value is negative, sendfile() is not used.
//!                         If the value is SFS_SFIO_FDVAL then the SendData()
//!                         method is used for future read requests.
//-----------------------------------------------------------------------------

virtual int            fctl(const int               cmd,
                            const char             *args,
                                  XrdOucErrInfo    &eInfo) = 0;

//-----------------------------------------------------------------------------
//! Execute a special operation on the file (version 2)
//!
//! @param  cmd    - The operation to be performed:
//!                  SFS_FCTL_SPEC1    Perform implementation defined action
//! @param  alen   - Length of data pointed to by args.
//! @param  args   - Data sent with request, zero if alen is zero.
//! @param  client - Client's identify (see common description).
//!
//! @return SFS_OK   a null response is sent.
//! @return SFS_DATA error.code    length of the data to be sent.
//!                  error.message contains the data to be sent.
//!         o/w      one of SFS_ERROR, SFS_REDIRECT, or SFS_STALL.
//-----------------------------------------------------------------------------

virtual int            fctl(const int               cmd,
                                  int               alen,
                                  const char       *args,
                            const XrdSecEntity     *client = 0);

//-----------------------------------------------------------------------------
//! Get the file path.
//!
//! @return Null terminated string of the path used in open().
//-----------------------------------------------------------------------------

virtual const char    *FName() = 0;

//-----------------------------------------------------------------------------
//! Get file's memory mapping if one exists (memory mapped files only).
//!
//! @param  addr   - Place where the starting memory address is returned.
//! @param  size   - Place where the file's size is returned.
//!
//! @return SFS_OK when the file is memory mapped or any other code otherwise.
//-----------------------------------------------------------------------------

virtual int            getMmap(void **Addr, off_t &Size) = 0;

//-----------------------------------------------------------------------------
//! Options for pgRead() and pgWrite() as noted below.
//-----------------------------------------------------------------------------

static const uint64_t
Verify       = 0x8000000000000000ULL; //!< all: Verify checksums

//-----------------------------------------------------------------------------
//! Read file pages into a buffer and return corresponding checksums.
//!
//! @param  offset  - The offset where the read is to start. It may be
//!                   unaligned with certain caveats relative to csvec.
//! @param  buffer  - pointer to buffer where the bytes are to be placed.
//! @param  rdlen   - The number of bytes to read. The amount must be an
//!                   integral number of XrdSfsPage::Size bytes.
//! @param  csvec   - A vector of entries to be filled with the cooresponding
//!                   CRC32C checksum for each page. However, if the offset is
//!                   unaligned, then csvec[0] contains the crc for the page
//!                   fragment that brings it to alignment for csvec[1].
//!                   It must be sized to hold all aligned XrdSys::Pagesize
//!                   crc's plus additional ones for leading and ending page
//!                   fragments, if any.
//! @param  opts    - Processing options (see above).
//!
//! @return >= 0      The number of bytes that placed in buffer.
//! @return SFS_ERROR File could not be read, error holds the reason.
//-----------------------------------------------------------------------------

virtual XrdSfsXferSize pgRead(XrdSfsFileOffset   offset,
                              char              *buffer,
                              XrdSfsXferSize     rdlen,
                              uint32_t          *csvec,
                              uint64_t           opts=0);

//-----------------------------------------------------------------------------
//! Read file pages and checksums using asynchronous I/O.
//!
//! @param  aioparm - Pointer to async I/O object controlling the I/O.
//! @param  opts    - Processing options (see above).
//!
//! @return SFS_OK    Request accepted and will be scheduled.
//! @return SFS_ERROR File could not be read, error holds the reason.
//-----------------------------------------------------------------------------

virtual int            pgRead(XrdSfsAio *aioparm, uint64_t opts=0);

//-----------------------------------------------------------------------------
//! Write file pages into a file with corresponding checksums.
//!
//! @param  offset  - The offset where the write is to start. It may be
//!                   unaligned with certain caveats relative to csvec.
//! @param  buffer  - pointer to buffer containing the bytes to write.
//! @param  wrlen   - The number of bytes to write. If amount is not an
//!                   integral number of XrdSys::PageSize bytes, then this must
//!                   be the last write to the file at or above the offset.
//! @param  csvec   - A vector which contains the corresponding CRC32 checksum
//!                   for each page or page fragment. If offset is unaligned
//!                   then csvec[0] is the crc of the leading fragment to
//!                   align the subsequent full page who's crc is in csvec[1].
//!                   It must be sized to hold all aligned XrdSys::Pagesize
//!                   crc's plus additional ones for leading and ending page
//!                   fragments, if any.
//! @param  opts    - Processing options (see above).
//!
//! @return >= 0      The number of bytes written.
//! @return SFS_ERROR File could not be read, error holds the reason.
//-----------------------------------------------------------------------------

virtual XrdSfsXferSize pgWrite(XrdSfsFileOffset   offset,
                               char              *buffer,
                               XrdSfsXferSize     wrlen,
                               uint32_t          *csvec,
                               uint64_t           opts=0);

//-----------------------------------------------------------------------------
//! Write file pages and checksums using asynchronous I/O.
//!
//! @param  aioparm - Pointer to async I/O object controlling the I/O.
//! @param  opts    - Processing options (see above).
//!
//! @return SFS_OK    Request accepted and will be scheduled.
//! @return SFS_ERROR File could not be read, error holds the reason.
//-----------------------------------------------------------------------------

virtual int            pgWrite(XrdSfsAio *aioparm, uint64_t opts=0);

//-----------------------------------------------------------------------------
//! Preread file blocks into the file system cache.
//!
//! @param  offset  - The offset where the read is to start.
//! @param  size    - The number of bytes to pre-read.
//!
//! @return >= 0      The number of bytes that will be pre-read.
//! @return SFS_ERROR File could not be preread, error holds the reason.
//-----------------------------------------------------------------------------

virtual XrdSfsXferSize read(XrdSfsFileOffset   offset,
                            XrdSfsXferSize     size) = 0;

//-----------------------------------------------------------------------------
//! Read file bytes into a buffer.
//!
//! @param  offset  - The offset where the read is to start.
//! @param  buffer  - pointer to buffer where the bytes are to be placed.
//! @param  size    - The number of bytes to read.
//!
//! @return >= 0      The number of bytes that placed in buffer.
//! @return SFS_ERROR File could not be read, error holds the reason.
//-----------------------------------------------------------------------------

virtual XrdSfsXferSize read(XrdSfsFileOffset   offset,
                            char              *buffer,
                            XrdSfsXferSize     size) = 0;

//-----------------------------------------------------------------------------
//! Read file bytes using asynchronous I/O.
//!
//! @param  aioparm - Pointer to async I/O object controlling the I/O.
//!
//! @return SFS_OK    Request accepted and will be scheduled.
//! @return SFS_ERROR File could not be read, error holds the reason.
//-----------------------------------------------------------------------------

virtual int            read(XrdSfsAio *aioparm) = 0;

//-----------------------------------------------------------------------------
//! Given an array of read requests (size rdvCnt), read them from the file
//! and place the contents consecutively in the provided buffer. A dumb default
//! implementation is supplied but should be replaced to increase performance.
//!
//! @param  readV     pointer to the array of read requests.
//! @param  rdvcnt    the number of elements in readV.
//!
//! @return >=0       The numbe of bytes placed into the buffer.
//! @return SFS_ERROR File could not be read, error holds the reason.
//-----------------------------------------------------------------------------

virtual XrdSfsXferSize readv(XrdOucIOVec      *readV,
                             int               rdvCnt);

//-----------------------------------------------------------------------------
//! Send file bytes via a XrdSfsDio sendfile object to a client (optional).
//!
//! @param  sfDio   - Pointer to the sendfile object for data transfer.
//! @param  offset  - The offset where the read is to start.
//! @param  size    - The number of bytes to read and send.
//!
//! @return SFS_ERROR File not read, error object has reason.
//! @return SFS_OK    Either data has been successfully sent via sfDio or no
//!                   data has been sent and a normal read() should be issued.
//-----------------------------------------------------------------------------

virtual int            SendData(XrdSfsDio         *sfDio,
                                XrdSfsFileOffset   offset,
                                XrdSfsXferSize     size);

//-----------------------------------------------------------------------------
//! Write file bytes from a buffer.
//!
//! @param  offset  - The offset where the write is to start.
//! @param  buffer  - pointer to buffer where the bytes reside.
//! @param  size    - The number of bytes to write.
//!
//! @return >= 0      The number of bytes that were written.
//! @return SFS_ERROR File could not be written, error holds the reason.
//-----------------------------------------------------------------------------

virtual XrdSfsXferSize write(XrdSfsFileOffset  offset,
                             const char       *buffer,
                             XrdSfsXferSize    size) = 0;

//-----------------------------------------------------------------------------
//! Write file bytes using asynchronous I/O.
//!
//! @param  aioparm - Pointer to async I/O object controlling the I/O.
//!
//! @return  0       Request accepted and will be scheduled.
//! @return !0       Request not accepted, returned value is errno.
//-----------------------------------------------------------------------------

virtual int            write(XrdSfsAio *aioparm) = 0;

//-----------------------------------------------------------------------------
//! Given an array of write requests (size wdvcnt), write them to the file
//! from the provided associated buffer. A dumb default implementation is
//! supplied but should be replaced to increase performance.
//!
//! @param  writeV    pointer to the array of write requests.
//! @param  wdvcnt    the number of elements in writeV.
//!
//! @return >=0       The total number of bytes written to the file.
//! @return SFS_ERROR File could not be written, error holds the reason.
//-----------------------------------------------------------------------------

virtual XrdSfsXferSize writev(XrdOucIOVec      *writeV,
                              int               wdvCnt);

//-----------------------------------------------------------------------------
//! Return state information on the file.
//!
//! @param  buf    - Pointer to the structure where info it to be returned.
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL. When SFS_OK
//!         is returned, buf must hold stat information.
//-----------------------------------------------------------------------------

virtual int            stat(struct stat *buf) = 0;

//-----------------------------------------------------------------------------
//! Make sure all outstanding data is actually written to the file (sync).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, SFS_STALL, or SFS_STARTED
//-----------------------------------------------------------------------------

virtual int            sync() = 0;

//-----------------------------------------------------------------------------
//! Make sure all outstanding data is actually written to the file (async).
//!
//! @return SFS_OK    Request accepted and will be scheduled.
//! @return SFS_ERROR Request could not be accepted, return error has reason.
//-----------------------------------------------------------------------------

virtual int            sync(XrdSfsAio *aiop) = 0;

//-----------------------------------------------------------------------------
//! Truncate the file.
//!
//! @param  fsize  - The size that the file is to have.
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            truncate(XrdSfsFileOffset fsize) = 0;

//-----------------------------------------------------------------------------
//! Get compression information for the file.
//!
//! @param  cxtype - Place where the compression algorithm name is to be placed
//! @param  cxrsz  - Place where the compression page size is to be returned
//!
//! @return One of the valid SFS return codes described above. If the file
//!         is not compressed or an error is returned, cxrsz must be set to 0.
//-----------------------------------------------------------------------------

virtual int            getCXinfo(char cxtype[4], int &cxrsz) = 0;

//-----------------------------------------------------------------------------
//! Enable exchange buffer I/O for write calls.
//!
//! @param  - Pointer to the XrdSfsXio object to be used for buffer exchanges.
//-----------------------------------------------------------------------------

virtual void           setXio(XrdSfsXio *xioP) { (void)xioP; }

//-----------------------------------------------------------------------------
//! Constructor (user and MonID are the ones passed to newFile()!). This
//! constructor should only be used by base plugins. Plugins that wrap an
//! SfsFile should use the second version of the constructor shown below.
//!
//! @param  user   - Text identifying the client responsible for this call.
//!                  The pointer may be null if identification is missing.
//! @param  MonID  - The monitoring identifier assigned to this and all
//!                  future requests using the returned object.
//-----------------------------------------------------------------------------

                       XrdSfsFile(const char *user=0, int MonID=0)
                                 : error(*(new XrdOucErrInfo(user, MonID)))
                                 {lclEI = &error; pgwrEOF = 0;}

//-----------------------------------------------------------------------------
//! Constructor for plugins that wrap another SFS plugin. This constructor
//! inherits the error object from a wrapped XrdSfsFile object so that only
//! one identical error object exists for all file objects in the chain.
//!
//! @param  wrapF  - Reference to the file object being wrapped.
//-----------------------------------------------------------------------------

                       XrdSfsFile(XrdSfsFile &wrapF)
                                 : error(wrapF.error), lclEI(0), pgwrEOF(0) {}

//-----------------------------------------------------------------------------
//! Constructor for base plugins that predefined an error object. This is a
//! convenience constructor for base plugins only.
//!
//! @param  eInfo  - Reference to the error object to use.
//-----------------------------------------------------------------------------

                       XrdSfsFile(XrdOucErrInfo &eInfo)
                                 : error(eInfo), lclEI(0), pgwrEOF(0) {}

//-----------------------------------------------------------------------------
//! Destructor
//-----------------------------------------------------------------------------

virtual               ~XrdSfsFile() {if (lclEI) delete lclEI;}

private:
XrdOucErrInfo*   lclEI;
XrdSfsFileOffset pgwrEOF;
}; // class XrdSfsFile

/******************************************************************************/
/*                      X r d S f s F i l e S y s t e m                       */
/******************************************************************************/
  
//-----------------------------------------------------------------------------
//! Common parameters: Many of the methods have certain common parameters.
//! These are documented here to avoid lengthy duplicate descriptions.
//!
//! @param  eInfo  - The object where error info or results are to be returned.
//!                  For errors, you should return information as follows:
//!                  SFS_OK       eInfo may contain results, as described in
//!                               specified method description that follows.
//!                  SFS_ERROR    eInfo.code    - errno number
//!                               eInfo.message - error message text
//!                  SFS_REDIRECT eInfo.code    - target port number
//!                               eInfo.message - target host address/name
//!                  SFS_STALL    eInfo.code    - expected seconds to stall
//!                               eInfo.message - reason for the delay
//!                  SFS_STARTED  eInfo.code    - expected seconds to completion
//!                               eInfo.message - reason for the delay
//!                  SFS_DATA     eInfo.code    - length of data in message
//!                               eInfo.message - the request data
//!
//! @param  client - Pointer to the client's identity information or nil if
//!                  the identity is not known.
//!
//! @param  opaque - Pointer to the CGI information associated with Path or
//!                  nil if there is no opaque information.
//-----------------------------------------------------------------------------

class XrdSfsFileSystem
{
public:

//-----------------------------------------------------------------------------
//! Obtain a new director object to be used for future directory requests.
//!
//! @param  user   - Text identifying the client responsible for this call.
//!                  The pointer may be null if identification is missing.
//! @param  MonID  - The monitoring identifier assigned to this and all
//!                  future requests using the returned object.
//!
//! @return pointer- Pointer to an XrdSfsDirectory object.
//! @return nil    - Insufficient memory to allocate an object.
//-----------------------------------------------------------------------------

virtual XrdSfsDirectory *newDir(char *user=0, int MonID=0)  = 0;

//-----------------------------------------------------------------------------
//! Obtain a new wrapped directory object to be used for future requests.
//!
//! @param  eInfo  - Reference to the error object to be used by the new
//!                  directory object. Note that an implementation is supplied
//!                  for compatibility purposes but it returns a nil pointer
//!                  which is considered to be a failure. You must supply an
//!                  implementation for this to work correctly.
//!
//! @return pointer- Pointer to an XrdSfsDirectory object.
//! @return nil    - Insufficient memory to allocate an object.
//-----------------------------------------------------------------------------

virtual XrdSfsDirectory *newDir(XrdOucErrInfo &eInfo) {(void)eInfo; return 0;}

//-----------------------------------------------------------------------------
//! Obtain a new file object to be used for a future file requests.
//!
//! @param  user   - Text identifying the client responsible for this call.
//!                  The pointer may be null if identification is missing.
//! @param  MonID  - The monitoring identifier assigned to this and all
//!                  future requests using the returned object.
//!
//! @return pointer- Pointer to an XrdSfsFile object.
//! @return nil    - Insufficient memory to allocate an object.
//-----------------------------------------------------------------------------

virtual XrdSfsFile      *newFile(char *user=0, int MonID=0) = 0;

//-----------------------------------------------------------------------------
//! Obtain a new wrapped file object to be used for a future requests.
//!
//! @param  eInfo  - Reference to the error object to be used by the new file
//!                  object. Note that an implementation is supplied for
//!                  compatibility purposes but it returns a nil pointer
//!                  which is considered to be a failure. You must supply an
//!                  implementation for this to work correctly.
//!
//! @return pointer- Pointer to an XrdSfsFile object.
//! @return nil    - Insufficient memory to allocate an object.
//-----------------------------------------------------------------------------

virtual XrdSfsFile      *newFile(XrdOucErrInfo &eInfo) {(void)eInfo; return 0;}

//-----------------------------------------------------------------------------
//! Obtain checksum information for a file.
//!
//! @param  Func   - The checksum operation to be performed:
//!                  csCalc  - (re)calculate and return the checksum value
//!                  csGet   - return the existing checksum value, if any
//!                  csSize  - return the size of the checksum value that
//!                            corresponds to csName (path may be null).
//! @param  csName - The name of the checksum value wanted.
//! @param  path   - Pointer to the path of the file in question.
//! @param  eInfo  - The object where error info or results are to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - Path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, or SFS_REDIRECT. When SFS_OK is returned,
//!         eInfo should contain results, as follows:
//!         csCalc/csGet eInfo.message - null terminated string with the
//!                                      checksum value in ASCII hex.
//!         csSize       eInfo.code    - size of binary checksum value.
//-----------------------------------------------------------------------------

enum    csFunc {csCalc = 0, csGet, csSize};

virtual int            chksum(      csFunc            Func,
                              const char             *csName,
                              const char             *path,
                                    XrdOucErrInfo    &eInfo,
                              const XrdSecEntity     *client = 0,
                              const char             *opaque = 0);

//-----------------------------------------------------------------------------
//! Change file mode settings.
//!
//! @param  path   - Pointer to the path of the file in question.
//! @param  mode   - The new file mode setting.
//! @param  eInfo  - The object where error info or results are to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - Path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            chmod(const char             *path,
                                   XrdSfsMode        mode,
                                   XrdOucErrInfo    &eInfo,
                             const XrdSecEntity     *client = 0,
                             const char             *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Notify filesystem that a client has connected.
//!
//! @param  client - Client's identify (see common description).
//-----------------------------------------------------------------------------

virtual void           Connect(const XrdSecEntity     *client = 0)
{
  (void)client;
}

//-----------------------------------------------------------------------------
//! Notify filesystem that a client has disconnected.
//!
//! @param  client - Client's identify (see common description).
//-----------------------------------------------------------------------------

virtual void           Disc(const XrdSecEntity *client = 0) {(void)client;}

//-----------------------------------------------------------------------------
//! Notify filesystem about implmentation dependent environment. This method
//! may be called only once, if at all, right after obtaining this object.
//!
//! @param  envP   - Pointer to environmental information.
//-----------------------------------------------------------------------------

virtual void           EnvInfo(XrdOucEnv *envP) {(void)envP;}

//-----------------------------------------------------------------------------
//! Return directory/file existence information (short stat).
//!
//! @param  path   - Pointer to the path of the file/directory in question.
//! @param  eFlag  - Where the results are to be returned.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - Path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, SFS_STALL, or SFS_STARTED
//!         When SFS_OK is returned, eFlag must be properly set, as follows:
//!         XrdSfsFileExistNo            - path does not exist
//!         XrdSfsFileExistIsFile        - path refers to an  online file
//!         XrdSfsFileExistIsDirectory   - path refers to an  online directory
//!         XrdSfsFileExistIsOffline     - path refers to an offline file
//!         XrdSfsFileExistIsOther       - path is neither a file nor directory
//-----------------------------------------------------------------------------

virtual int            exists(const char                *path,
                                    XrdSfsFileExistence &eFlag,
                                    XrdOucErrInfo       &eInfo,
                              const XrdSecEntity        *client = 0,
                              const char                *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Perform a filesystem extended attribute function.
//!
//! @param  faReq  - pointer to the request object (see XrdSfsFAttr.hh). If the
//!                  pointer is nill, simply return whether or not extended
//!                  attributes are supported.
//! @param  eInfo  - The object where error info or results are to be returned.
//! @param  client - Client's identify (see common description).
//!
//! @return SFS_OK   a null response is sent.
//! @return SFS_DATA error.code    length of the data to be sent.
//!                  error.message contains the data to be sent.
//! @return SFS_STARTED Operation started result will be returned via callback.
//!         o/w      one of SFS_ERROR, SFS_REDIRECT, or SFS_STALL.
//-----------------------------------------------------------------------------

virtual int            FAttr(      XrdSfsFACtl      *faReq,
                                   XrdOucErrInfo    &eInfo,
                             const XrdSecEntity     *client = 0);

//-----------------------------------------------------------------------------
//! Obtain file system feature set.
//!
//! @return The bit-wise feature set (i.e. supported or configured).
//!         See include file XrdSfsFlags.hh for actual bit values.
//-----------------------------------------------------------------------------

        uint64_t       Features() {return FeatureSet;}

//-----------------------------------------------------------------------------
//! Perform a filesystem control operation (version 2)
//!
//! @param  cmd    - The operation to be performed:
//!                  SFS_FSCTL_PLUGIN  Return Implementation Dependent Data v1
//!                  SFS_FSCTL_PLUGIO  Return Implementation Dependent Data v2
//! @param  args   - Arguments specific to cmd.
//!                  SFS_FSCTL_PLUGIN  path and opaque information.
//!                  SFS_FSCTL_PLUGIO  Unscreened argument string.
//! @param  eInfo  - The object where error info or results are to be returned.
//! @param  client - Client's identify (see common description).
//!
//! @return SFS_OK   a null response is sent.
//!         SFS_DATA error.code    length of the data to be sent.
//!                  error.message contains the data to be sent.
//!         o/w      one of SFS_ERROR, SFS_REDIRECT, or SFS_STALL.
//-----------------------------------------------------------------------------

virtual int            FSctl(const int               cmd,
                                   XrdSfsFSctl      &args,
                                   XrdOucErrInfo    &eInfo,
                             const XrdSecEntity     *client = 0);

//-----------------------------------------------------------------------------
//! Perform a filesystem control operation (version 1)
//!
//! @param  cmd    - The operation to be performed:
//!                  SFS_FSCTL_LOCATE  Locate a file or file servers
//!                  SFS_FSCTL_STATCC  Return cluster config status
//!                  SFS_FSCTL_STATFS  Return physical filesystem information
//!                  SFS_FSCTL_STATLS  Return logical  filesystem information
//!                  SFS_FSCTL_STATXA  Return extended attributes
//! @param  args   - Arguments specific to cmd.
//!                  SFS_FSCTL_LOCATE  args points to the path to be located
//!                                    ""   path is the first exported path
//!                                    "*"  return all current servers
//!                                    "*/" return servers exporting path
//!                                    o/w  return servers having the path
//!                  SFS_FSCTL_STATFS  Path in the filesystem in question.
//!                  SFS_FSCTL_STATLS  Path in the filesystem in question.
//!                  SFS_FSCTL_STATXA  Path of the file whose xattr is wanted.
//! @param  eInfo  - The object where error info or results are to be returned.
//! @param  client - Client's identify (see common description).
//!
//! @return SFS_OK   a null response is sent.
//! @return SFS_DATA error.code    length of the data to be sent.
//!                  error.message contains the data to be sent.
//! @return SFS_STARTED Operation started result will be returned via callback.
//!                  Valid only for for SFS_FSCTL_LOCATE, SFS_FSCTL_STATFS, and
//!                  SFS_FSCTL_STATXA
//!         o/w      one of SFS_ERROR, SFS_REDIRECT, or SFS_STALL.
//-----------------------------------------------------------------------------

virtual int            fsctl(const int               cmd,
                             const char             *args,
                                   XrdOucErrInfo    &eInfo,
                             const XrdSecEntity     *client = 0) = 0;

//-----------------------------------------------------------------------------
//! Return maximum checkpoint size.
//!
//! @return Maximum size of a checkpoint.
//-----------------------------------------------------------------------------

virtual int            getChkPSize() {return 0;}

//-----------------------------------------------------------------------------
//! Return statistical information.
//!
//! @param  buff   - Pointer to the buffer where results are to be returned.
//!                  Statistics should be in standard XML format. If buff is
//!                  nil then only maximum size information is wanted.
//! @param  blen   - The length available in buff.
//!
//! @return Number of bytes placed in buff. When buff is nil, the maximum
//!         number of bytes that could have been placed in buff.
//-----------------------------------------------------------------------------

virtual int            getStats(char *buff, int blen) = 0;

//-----------------------------------------------------------------------------
//! Get version string.
//!
//! @return The version string. Normally this is the XrdVERSION value.
//-----------------------------------------------------------------------------

virtual const char    *getVersion() = 0;

//-----------------------------------------------------------------------------
//! Perform a third party file transfer or cancel one.
//!
//! @param  gpAct  - What to do as one of the enums listed below.
//! @param  gpReq  - reference tothe object describing the request. This object
//!                  is also used communicate the request status.
//! @param  eInfo  - The object where error info or results are to be returned.
//! @param  client - Client's identify (see common description).
//!
//! @return SFS_OK   Request accepted (same as SFS_STARTED). Otherwise, one of
//!                  SFS_ERROR, SFS_REDIRECT, or SFS_STALL.
//-----------------------------------------------------------------------------

enum gpfFunc {gpfCancel=0, //!< Cancel this request
              gpfGet,      //!< Perform a file retrieval
              gpfPut       //!< Perform a file push
             };

virtual int            gpFile(      gpfFunc          &gpAct,
                                    XrdSfsGPFile     &gpReq,
                                    XrdOucErrInfo    &eInfo,
                              const XrdSecEntity     *client = 0);

//-----------------------------------------------------------------------------
//! Create a directory.
//!
//! @param  path   - Pointer to the path of the directory to be created.
//! @param  mode   - The directory mode setting.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - Path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            mkdir(const char              *path,
                                   XrdSfsMode         mode,
                                   XrdOucErrInfo     &eInfo,
                             const XrdSecEntity      *client = 0,
                             const char              *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Prepare a file for future processing.
//!
//! @param  pargs  - The preapre arguments.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            prepare(      XrdSfsPrep      &pargs,
                                     XrdOucErrInfo   &eInfo,
                               const XrdSecEntity    *client = 0) = 0;

//-----------------------------------------------------------------------------
//! Remove a file.
//!
//! @param  path   - Pointer to the path of the file to be removed.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - Path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            rem(const char                *path,
                                 XrdOucErrInfo       &eInfo,
                           const XrdSecEntity        *client = 0,
                           const char                *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Remove a directory.
//!
//! @param  path   - Pointer to the path of the directory to be removed.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - Path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            remdir(const char             *path,
                                    XrdOucErrInfo    &eInfo,
                              const XrdSecEntity     *client = 0,
                              const char             *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Rename a file or directory.
//!
//! @param  oPath   - Pointer to the path to be renamed.
//! @param  nPath   - Pointer to the path oPath is to have.
//! @param  eInfo   - The object where error info is to be returned.
//! @param  client  - Client's identify (see common description).
//! @param  opaqueO - oPath's CGI information (see common description).
//! @param  opaqueN - nPath's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            rename(const char             *oPath,
                              const char             *nPath,
                                    XrdOucErrInfo    &eInfo,
                              const XrdSecEntity     *client = 0,
                              const char             *opaqueO = 0,
                              const char             *opaqueN = 0) = 0;

//-----------------------------------------------------------------------------
//! Return state information on a file or directory.
//!
//! @param  path   - Pointer to the path in question.
//! @param  buf    - Pointer to the structure where info it to be returned.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, SFS_STALL, or SFS_STARTED
//!         When SFS_OK is returned, buf must contain stat information.
//-----------------------------------------------------------------------------

virtual int            stat(const char               *Name,
                                  struct stat        *buf,
                                  XrdOucErrInfo      &eInfo,
                            const XrdSecEntity       *client = 0,
                            const char               *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Return mode information on a file or directory.
//!
//! @param  path   - Pointer to the path in question.
//! @param  mode   - Where full mode information is to be returned.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, SFS_STALL, or SFS_STARTED
//!         When SFS_OK is returned, mode must contain mode information. If
//!         teh mode is -1 then it is taken as an offline file.
//-----------------------------------------------------------------------------

virtual int            stat(const char               *path,
                                  mode_t             &mode,
                                  XrdOucErrInfo      &eInfo,
                            const XrdSecEntity       *client = 0,
                            const char               *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Truncate a file.
//!
//! @param  path   - Pointer to the path of the file to be truncated.
//! @param  fsize  - The size that the file is to have.
//! @param  eInfo  - The object where error info is to be returned.
//! @param  client - Client's identify (see common description).
//! @param  opaque - path's CGI information (see common description).
//!
//! @return One of SFS_OK, SFS_ERROR, SFS_REDIRECT, or SFS_STALL
//-----------------------------------------------------------------------------

virtual int            truncate(const char             *path,
                                      XrdSfsFileOffset  fsize,
                                      XrdOucErrInfo    &eInfo,
                                const XrdSecEntity     *client = 0,
                                const char             *opaque = 0) = 0;

//-----------------------------------------------------------------------------
//! Constructor and Destructor
//-----------------------------------------------------------------------------

                       XrdSfsFileSystem();
virtual               ~XrdSfsFileSystem() {}

protected:

uint64_t               FeatureSet; //!< Adjust features at initialization
};

/******************************************************************************/
/*              F i l e   S y s t e m   I n s t a n t i a t o r               */
/******************************************************************************/

//-----------------------------------------------------------------------------
/*! When building a shared library plugin, the following "C" entry point must
    exist in the library:

    @param  nativeFS - the filesystem that would have been used. You may return
                       this pointer if you wish.
    @param  Logger   - The message logging object to be used for messages.
    @param  configFN - pointer to the path of the configuration file. If nil
                       there is no configuration file.
    @param  envP     - Pointer to the environment containing implementation
                       specific information.

    @return Pointer to the file system object to be used or nil if an error
            occurred.

    extern "C"
         {XrdSfsFileSystem *XrdSfsGetFileSystem2(XrdSfsFileSystem *nativeFS,
                                                 XrdSysLogger     *Logger,
                                                 const char       *configFn,
                                                 XrdOucEnv        *envP);
         }
*/

typedef XrdSfsFileSystem *(*XrdSfsFileSystem2_t)(XrdSfsFileSystem *nativeFS,
                                                 XrdSysLogger     *Logger,
                                                 const char       *configFn,
                                                 XrdOucEnv        *envP);

//-----------------------------------------------------------------------------
/*! The old-style entry-point is still supported as a fallback. Should the
    version '2' entry point is not found, the system attempts to use the
    version '1' entry point.

    extern "C"
         {XrdSfsFileSystem *XrdSfsGetFileSystem(XrdSfsFileSystem *nativeFS,
                                                XrdSysLogger     *Logger,
                                                const char       *configFn);
         }
*/

typedef XrdSfsFileSystem *(*XrdSfsFileSystem_t) (XrdSfsFileSystem *nativeFS,
                                                 XrdSysLogger     *Logger,
                                                 const char       *configFn);

//------------------------------------------------------------------------------
/*! Specify the compilation version.

    Additionally, you *should* declare the xrootd version you used to compile
    your plug-in. The plugin manager automatically checks for compatibility.
    Declare it as follows:

    #include "XrdVersion.hh"
    XrdVERSIONINFO(XrdSfsGetFileSystem,<name>);

    where <name> is a 1- to 15-character unquoted name identifying your plugin.
*/
//------------------------------------------------------------------------------
#endif
