/*

  silcsftp_fs.h

  Author: Pekka Riikonen <priikone@silcnet.org>

  Copyright (C) 2001 - 2007 Pekka Riikonen

  The contents of this file are subject to one of the Licenses specified 
  in the COPYING file;  You may not use this file except in compliance 
  with the License.

  The software distributed under the License is distributed on an "AS IS"
  basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
  KIND, either expressed or implied.  See the COPYING file for more
  information.

*/

#ifndef SILCSFTP_FS_H
#define SILCSFTP_FS_H

/****h* silcsftp/SFTP Filesystems Interface
 *
 * DESCRIPTION
 *
 *    SILC SFTP Filesystem interface defines filesystems for the SFTP server
 *    usage.  The filesystems may be for example virtual memory filesystem
 *    or real filesystem access.
 *
 *    Currently only implemented filesystem is memory file system.
 *
 *    Memory Filesystem:
 *
 *    Memory filesystem is a virtual filesystem which provides safe access
 *    to files without actually revealing the underlaying physical filesystem
 *    hierarchy or real filenames. Virtual directories can be added to the
 *    filesystem and freely create filesystem hierarchy. The directories
 *    can have subdirectories and files. The filesystem also provides limited
 *    status information for files.  The files in the filesystem are
 *    virtual but they include the path to the real file.  The real path
 *    includes always a schema which indicates where the file really is
 *    available.  The only supported schema currently is "file://".  In
 *    the future it could support various others like "http://" and "ldap://".
 *
 *    The filesystem also provides security and permission handling for
 *    directories and files.  Normal POSIX style permissions can be set
 *    giving thus rights to reading, writing and/or executing.  They behave
 *    same way as defined in POSIX.  It is also guaranteed that if the
 *    writing to a file is not allowed in the memory filesystem, but it is
 *    allowed in real physical filesystem the file still cannot be written.
 *    However, the real physical filesystem permissions still matter, for
 *    example if writing is enabled in the memory filesystem but it is not
 *    enabled on physical filesystem, the file cannot be written.
 *
 *    The directories cannot be removed from remote access using the
 *    filesystem access function sftp_rmdir.  This is because the filesystem
 *    is one-user filesystem and differentiating between users is not
 *    possible.  Thus, it would allow anyone to remove directories and
 *    their contents.  Removing directories is possible only locally using
 *    the silc_sftp_fs_memory_del_dir function.  The same thing is with
 *    removing files as well.  Files too can be removed only locally using
 *    the silc_sftp_fs_memory_del_file function.  Also, files can not ever
 *    be executed from remote access.
 *
 *    Also some of the file operation flags are not supported, such as
 *    SILC_SFTP_FXF_CREAT, SILC_SFTP_FXF_TRUNC and SILC_SFTP_FXF_EXCL
 *    since they would require access to a real filesystem file which does
 *    not exist yet, or would mean destroying the file.  However, the
 *    SILC_SFTP_FXF_WRITE is supported since the file aready exists.
 *
 *    The memory filesystem does not provide symbolic links.
 *
 ***/

/****s* silcsftp/SilcSFTPFSAPI/SilcSFTPFilesystemOps
 *
 * NAME
 *
 *    typedef struct SilcSFTPFilesystemOpsStruct { ... }
 *                     *SilcSFTPFilesystemOps;
 *
 * DESCRIPTION
 *
 *    This structure defines the generic filesystem access.  When the
 *    filesystem is accessed these functions are called to do the requested
 *    filesystem operation.  The level that implements the actual filesystem
 *    must fill this structure with the callback functions providing the
 *    access to the filesystem.
 *
 * SOURCE
 */
typedef struct SilcSFTPFilesystemOpsStruct {
  /* Find a file handle by the file handle data indicated by the `data'.
     If the handle is not found this returns NULL. */
  SilcSFTPHandle (*sftp_get_handle)(void *context, SilcSFTP sftp,
				    const unsigned char *data,
				    SilcUInt32 data_len);

  /* Return encoded handle of `handle' or NULL on error. The caller
     must free the returned buffer. */
  unsigned char *(*sftp_encode_handle)(void *context, SilcSFTP sftp,
				       SilcSFTPHandle handle,
				       SilcUInt32 *handle_len);

  /* Open a file indicated by the `filename' with flags indicated by the
     `pflags', and with attributes indicated by the `attr'.  Calls the
     `callback' to return the opened file handle. */
  void (*sftp_open)(void *context, SilcSFTP sftp,
		    const char *filename,
		    SilcSFTPFileOperation pflags,
		    SilcSFTPAttributes attr,
		    SilcSFTPHandleCallback callback,
		    void *callback_context);

  /* Closes the file indicated by the file handle `handle'.  Calls the
     `callback' to indicate the status of the closing. */
  void (*sftp_close)(void *context, SilcSFTP sftp,
		     SilcSFTPHandle handle,
		     SilcSFTPStatusCallback callback,
		     void *callback_context);

  /* Reads data from the file indicated by the file handle `handle' starting
     from the offset of `offset' at most `len' bytes.  The `callback' is
     called to return the read data. */
  void (*sftp_read)(void *context, SilcSFTP sftp,
		    SilcSFTPHandle handle,
		    SilcUInt64 offset,
		    SilcUInt32 len,
		    SilcSFTPDataCallback callback,
		    void *callback_context);

  /* Writes to a file indicated by the file handle `handle' starting from
     offset of `offset' at most `data_len' bytes of `data'.  The `callback'
     is called to indicate the status of the writing. */
  void (*sftp_write)(void *context, SilcSFTP sftp,
		     SilcSFTPHandle handle,
		     SilcUInt64 offset,
		     const unsigned char *data,
		     SilcUInt32 data_len,
		     SilcSFTPStatusCallback callback,
		     void *callback_context);

  /* Removes a file indicated by the `filename'.  Calls the `callback'
     to indicate the status of the removing. */
  void (*sftp_remove)(void *context, SilcSFTP sftp,
		      const char *filename,
		      SilcSFTPStatusCallback callback,
		      void *callback_context);

  /* Renames a file indicated by the `oldname' to the name `newname'.  The
     `callback' is called to indicate the status of the renaming. */
  void (*sftp_rename)(void *context, SilcSFTP sftp,
		      const char *oldname,
		      const char *newname,
		      SilcSFTPStatusCallback callback,
		      void *callback_context);

  /* Creates a new directory indicated by the `path' with attributes indicated
     by the `attrs'. The `callback' is called to indicate the status of the
     creation. */
  void (*sftp_mkdir)(void *context, SilcSFTP sftp,
		     const char *path,
		     SilcSFTPAttributes attrs,
		     SilcSFTPStatusCallback callback,
		     void *callback_context);

  /* Removes a directory indicated by the `path' and calls the `callback'
     to indicate the status of the removal. */
  void (*sftp_rmdir)(void *context, SilcSFTP sftp,
		     const char *path,
		     SilcSFTPStatusCallback callback,
		     void *callback_context);

  /* Opens a directory indicated by the `path'.  The `callback' is called
     to return the opened file handle. */
  void (*sftp_opendir)(void *context, SilcSFTP sftp,
		       const char *path,
		       SilcSFTPHandleCallback callback,
		       void *callback_context);

  /* Reads the contents of the directory indicated by the `handle' and
     calls the `callback' to return the read file(s) from the directory. */
  void (*sftp_readdir)(void *context, SilcSFTP sftp,
		       SilcSFTPHandle handle,
		       SilcSFTPNameCallback callback,
		       void *callback_context);

  /* Gets the file attributes for a file indicated by the `path'. This
     will follow symbolic links also. Calls the `callback' to return the
     file attributes. */
  void (*sftp_stat)(void *context, SilcSFTP sftp,
		    const char *path,
		    SilcSFTPAttrCallback callback,
		    void *callback_context);

  /* Gets the file attributes for a file indicated by the `path'. This
     will not follow symbolic links. Calls the `callback' to return the
     file attributes. */
  void (*sftp_lstat)(void *context, SilcSFTP sftp,
		     const char *path,
		     SilcSFTPAttrCallback callback,
		     void *callback_context);

  /* Gets a file attributes for a opened file indicated by the `handle'.
     Calls the `callback' to return the file attributes. */
  void (*sftp_fstat)(void *context, SilcSFTP sftp,
		     SilcSFTPHandle handle,
		     SilcSFTPAttrCallback callback,
		     void *callback_context);

  /* Sets a file attributes to a file indicated by the `path' with the
     attributes indicated by the `attrs'.  Calls the `callback' to indicate
     the status of the setting. */
  void (*sftp_setstat)(void *context, SilcSFTP sftp,
		       const char *path,
		       SilcSFTPAttributes attrs,
		       SilcSFTPStatusCallback callback,
		       void *callback_context);

  /* Sets a file attributes to a opened file indicated by the `handle' with
     the attributes indicated by the `attrs'.  Calls the `callback' to
     indicate the status of the setting. */
  void (*sftp_fsetstat)(void *context, SilcSFTP sftp,
			SilcSFTPHandle handle,
			SilcSFTPAttributes attrs,
			SilcSFTPStatusCallback callback,
			void *callback_context);

  /* Reads the target of a symbolic link indicated by the `path'.  The
     `callback' is called to return the target of the symbolic link. */
  void (*sftp_readlink)(void *context, SilcSFTP sftp,
			const char *path,
			SilcSFTPNameCallback callback,
			void *callback_context);

  /* Creates a new symbolic link indicated by the `linkpath' to the target
     indicated by the `targetpath'.  The `callback' is called to indicate
     the status of creation. */
  void (*sftp_symlink)(void *context, SilcSFTP sftp,
		       const char *linkpath,
		       const char *targetpath,
		       SilcSFTPStatusCallback callback,
		       void *callback_context);

  /* Canonicalizes the path indicated by the `path' to a absolute path.
     The `callback' is called to return the absolute path. */
  void (*sftp_realpath)(void *context, SilcSFTP sftp,
			const char *path,
			SilcSFTPNameCallback callback,
			void *callback_context);

  /* Performs an extended operation indicated by the `request' with
     optional extended operation data indicated by the `data'.  The callback
     is called to return any data associated with the extended request. */
  void (*sftp_extended)(void *context, SilcSFTP sftp,
			const char *request,
			const unsigned char *data,
			SilcUInt32 data_len,
			SilcSFTPExtendedCallback callback,
			void *callback_context);
} *SilcSFTPFilesystemOps;
/****/

/****s* silcsftp/SilcSFTPFSAPI/SilcSFTPFilesystem
 *
 * NAME
 *
 *    typedef struct { ... } *SilcSFTPFilesystem;
 *
 * DESCRIPTION
 *
 *    This context is allocated and returned by all filesystem allocation
 *    routines.  The returned context is given as argument to the
 *    silc_sftp_server_start function.  The caller must also free the
 *    context after the SFTP server is shutdown.
 *
 * SOURCE
 */
typedef struct SilcSFTPFilesystemStruct {
  SilcSFTPFilesystemOps fs;
  void *fs_context;
} *SilcSFTPFilesystem;
/***/

/* Memory filesystem */

/****d* silcsftp/SilcSFTPFSAPI/SilcSFTPFSMemoryPerm
 *
 * NAME
 *
 *    typedef enum { ... } SilcSFTPFSMemoryPerm;
 *
 * DESCRIPTION
 *
 *    Memory filesystem permission definition.  These enumerations can
 *    be used to set the permission mask for directories and files.
 *    The permissions behave in POSIX style.
 *
 * SOURCE
 */
typedef enum {
  SILC_SFTP_FS_PERM_READ    = 0x0001,    /* Reading allowed */
  SILC_SFTP_FS_PERM_WRITE   = 0x0002,	 /* Writing allowed */
  SILC_SFTP_FS_PERM_EXEC    = 0x0004,	 /* Execution allowed */
} SilcSFTPFSMemoryPerm;
/***/

/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_alloc
 *
 * SYNOPSIS
 *
 *    void *silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm);
 *
 * DESCRIPTION
 *
 *    Allocates memory filesystem context and returns the context.  The
 *    context can be given as argument to the silc_sftp_server_start
 *    function. The context must be freed by the caller using the function
 *    silc_sftp_fs_memory_free. The `perm' is the permissions for the root
 *    directory of the filesystem (/ dir).
 *
 ***/
SilcSFTPFilesystem silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm);

/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_free
 *
 * SYNOPSIS
 *
 *    void silc_sftp_fs_memory_free(void *context);
 *
 * DESCRIPTION
 *
 *    Frees the memory filesystem context.
 *
 ***/
void silc_sftp_fs_memory_free(SilcSFTPFilesystem fs);

/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_add_dir
 *
 * SYNOPSIS
 *
 *    void *silc_sftp_fs_memory_add_dir(SilcSFTPFilesystem fs, void *dir,
 *                                      SilcSFTPFSMemoryPerm perm,
 *                                      const char *name);
 *
 * DESCRIPTION
 *
 *    Adds a new directory to the memory filesystem. Returns the directory
 *    context that can be used to add for example files to the directory
 *    or new subdirectories under the directory. The `dir' is the parent
 *    directory of the directory to be added. If this directory is to be
 *    added to the root directory the `dir' is NULL.  The `name' is the name
 *    of the directory. If error occurs this returns NULL. The `perm' will
 *    indicate the permissions for the directory and they work in POSIX
 *    style.
 *
 ***/
void *silc_sftp_fs_memory_add_dir(SilcSFTPFilesystem fs, void *dir,
				  SilcSFTPFSMemoryPerm perm,
				  const char *name);

/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_del_dir
 *
 * SYNOPSIS
 *
 *    SilcBool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir);
 *
 * DESCRIPTION
 *
 *    Deletes a directory indicated by the `dir'. All files and
 *    subdirectories in this directory is also removed.  If the `dir' is
 *    NULL then all directories and files are removed from the filesystem.
 *    Returns TRUE if the removing was success. This is the only way to
 *    remove directories in memory file system. The filesystem does not
 *    allow removing directories with remote access using the filesystem
 *    access function sftp_rmdir.
 *
 ***/
SilcBool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir);

/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_add_file
 *
 * SYNOPSIS
 *
 *    SilcBool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
 *                                          SilcSFTPFSMemoryPerm perm,
 *                                          const char *filename,
 *                                          const char *realpath);
 *
 * DESCRIPTION
 *
 *    Adds a new file to the directory indicated by the `dir'.  If the `dir'
 *    is NULL the file is added to the root directory. The `filename' is the
 *    filename in the directory. The `realpath' is the real filepath in the
 *    physical filesystem. The real path must include the schema to
 *    indicate where the file is actually located.  The only supported
 *    schema currently is "file://".  It is used to actually access the fil
 *    from the memory filesystem. The `perm' will indicate the permissions
 *    for the file and they work in POSIX style. Returns TRUE if the file
 *    was added to the directory.
 *
 ***/
SilcBool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
				      SilcSFTPFSMemoryPerm perm,
				      const char *filename,
				      const char *realpath);

/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_del_file
 *
 * SYNOPSIS
 *
 *    SilcBool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
 *                                          const char *filename);
 *
 * DESCRIPTION
 *
 *    Removes a file indicated by the `filename' from the directory
 *    indicated by the `dir'. Returns TRUE if the removing was success. This
 *    is the only way to remove files in the filesystem.  The filesystem does
 *    not allow removing files with remote access using the filesystem
 *    access function sftp_remove.
 *
 ***/
SilcBool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
				      const char *filename);

#endif /* SILCSFTP_FS_H */
