ProFTPD Developer's Guide: FSIO API Structures

ProFTPD Version 1.2


Table of Contents

FSIO API Structures
At the core, the FSIO API uses and manipulates a structure called an pr_fs_t, which represents a "filesystem" by storing callback function pointers to the actual filesystem to be used. The FSIO access functions lookup the right pr_fs_t for the operation, and invoke the proper callback. Simple.

The code definining the structure of an pr_fs_t is in include/fsio.h, but is included here for your reading pleasure:


/* Modular filesystem object */
struct fs_rec {

  /* These pointers will be effective once layered FSIO modules are
   * supported
   */
  pr_fs_t *fs_next, *fs_prev;

  /* Descriptive tag for this pr_fs_t */
  char *fs_name;

  char *fs_path;

  /* Slot for module-specific data */
  void *fs_data;

  /* Pool for this object's use */
  pool *fs_pool;

  /* FSIO callback pointers */
  int (*stat)(pr_fs_t *, const char *, struct stat *);
  int (*lstat)(pr_fs_t *, const char *, struct stat *);
  int (*rename)(pr_fs_t *, const char *, const char *);
  int (*unlink)(pr_fs_t *, const char *);
  int (*open)(pr_fs_t *, const char *, int);
  int (*creat)(pr_fs_t *, const char *, mode_t);
  int (*close)(pr_fs_t *, int);
  int (*read)(pr_fs_t *, int, char *, size_t);
  int (*write)(pr_fs_t *, int, const char *, size_t);
  off_t (*lseek)(pr_fs_t *, int, off_t, int);
  int (*link)(pr_fs_t *, const char *, const char *);
  int (*symlink)(pr_fs_t *, const char *, const char *);
  int (*readlink)(pr_fs_t *, const char *, char *, size_t);
  int (*truncate)(pr_fs_t *, const char *, off_t);
  int (*chmod)(pr_fs_t *, const char *, mode_t);
  int (*chown)(pr_fs_t *, const char *, uid_t, gid_t);

  /* For actual operations on the directory (or subdirs)
   * we cast the return from opendir to DIR* in src/fsio.c, so
   * modules can use their own data type
   */

  int (*chdir)(pr_fs_t *, const char *);
  int (*chroot)(pr_fs_t *, const char *);
  void *(*opendir)(pr_fs_t *, const char *);
  int (*closedir)(pr_fs_t *, void *);
  struct dirent *(*readdir)(pr_fs_t *, void *);
  int (*mkdir)(pr_fs_t *, const char *, mode_t);
  int (*rmdir)(pr_fs_t *, const char *);
};

The most noteworthy points of this structure are the next, prev pointers (currently unused), and the data field. The pointers are there for when layered FSIO modules - multiple modules that are register an interest in handling identical paths - are supported; at that point, the pr_fs_ts for that path will be maintained in a linked-list, which could then be walked for any FSIO operation.

The data is where FSIO modules can store and pass around data specific to that module, e.g. database handles, connection information, ACLs, ciphers, etc etc.

Also note that, when instantiated, a subpool is allocated from the given parent pool, and it is from this subpool (stored as pr_fs_t->fs_pool) that the object is actually allocated. Therefore, to destroy an pr_fs_t, one needs merely to call destroy_pool() on the pr_fs_t's pool.

The open and creat callbacks return a pointer to a pr_fh_t, a proftpd filehandle. This filehandle is then passed to the close, lseek, read, and write callbacks, very similar to a normal file descriptor. This filehandle contains a pointer to the filesystem in which the file is located, and a buffer pointer, for core routines that may need to make use of buffered I/O.

Table of Contents



Author: $Author: castaglia $
Last Updated: $Date: 2003/03/28 21:10:44 $


© Copyright 2000-2002 TJ Saunders
All Rights Reserved