ProFTPD Developer's Guide: FSIO API Functions

ProFTPD Version 1.2


Table of Contents

FSIO API Functions

  pr_fs_t *pr_register_fs(pool *pool, const char *name, const char *path);
  pr_fs_t *pr_create_fs(pool *pool, const char *name);
  pr_fs_t *pr_get_fs(const char *path, int *exact);
  int pr_insert_fs(pr_fs_t *fs, const char *path);
  int pr_unregister_fs(const char *path);

The pr_register_fs() function is the one that FSIO modules should use primarily, for it handles the creation and registration of an pr_fs_t in one shot. The pr_fs_t * returned allows the caller to store that pointer for other, module-specific, purposes. The name argument is merely a descriptive label for the created pr_fs_t. The path argument declares where the created pr_fs_t is to be registered in the filesystem, and is specific only to the created pr_fs_t; an FSIO module may call pr_register_fs() multiple times for multiple paths. Functionally, pr_register_fs() is equivalent to calling pr_create_fs() and pr_insert_fs().

The pr_fs_t * returned by both pr_register_fs() and pr_create_fs() has all of its function pointers initialized to the system defaults. To put the FSIO module's custom versions into effect, merely overwrite the appropriate function pointer. Note that the FSIO access functions will check for NULL function pointers and return EPERM if need be, meaning that a given filesystem operation can easily be disabled by setting its pr_fs_t function pointer to NULL.

The pr_create_fs() function instantiates an pr_fs_t with the given name. This pr_fs_t * could then be used multiple times, passing the same pointer to pr_insert_fs() for multiple paths.

The pr_insert_fs() function inserts the given pr_fs_t * into a mapping of pr_fs_ts maintained by the FSIO layer. This mapping is sorted and searched according to the given path; it is highly recommended that the path field of a created pr_fs_t be left alone. If the given path argument ends in a trailing slash, then that path will be treated a little differently than non-trailing-slash paths by pr_get_fs(). Deferred-resolution paths, e.g. relative paths, and "~" and "." prefixed paths (but not ".." prefixed paths), are allowed. They will be resolved into full paths at login time, after successful authentication by the user. This function will return TRUE upon successful insertion of the pointer into the map, FALSE otherwise. At this point, the FSIO layer does not handle layering of FSIO modules, multiple modules that register identical paths; this function returns FALSE if there is already an pr_fs_t in the map for handling the requested path.

The pr_get_fs() function serves as the pr_fs_t lookup/retrieval function, searching for the pr_fs_t that should handle the given path. If the returned pr_fs_t * is an exact match for the given path, meaning that there was an pr_fs_t in the FSIO layer's map whose path member matches the given path exactly, then *exact will have a TRUE when pr_get_fs() returns. Otherwise, *exact will be FALSE, meaning that the returned pr_fs_t * is a best-match pr_fs_t that probably handles paths higher up the filesystem hierarchy from the given path. This function never returns NULL, for there is always a root pr_fs_t to handle /, meaning all paths.

When searching for an pr_fs_t to handle path, pr_get_fs() searches the map, starting at the root of path and looking for more path-specific pr_fs_ts. It keeps tracks of pr_fs_ts for directories, as opposed to specific files, and distinguishes between them by looking for a trailing slash. For example, if there was only two pr_fs_ts in the FSIO map, the root pr_fs_t and one registered to handle

  /path/to/dir
and the path given to pr_get_fs() is
  /path/to/dir/file1
then the root pr_fs_t will be returned, as that is the best-matching path. /path/to/dir is considered to be a file, not a directory, by this function. However, if instead of:
  /path/to/dir
the other pr_fs_t was registered to handle:
  /path/to/dir/
then that pr_fs_t would be considered best-matching by the lookup algorithm.

Finally, the pr_unregister_fs() function does just that -- it searches the FSIO layer's map for pr_fs_ts whose paths match, removes them from the map, and destroys them. It returns TRUE upon removing any matching pr_fs_ts, FALSE if there was no matching pr_fs_t in the map, if the given path was NULL, or if there is an attempt to remove the root pr_fs_t.

Custom FSIO Functions
The following are the function prototypes to which any custom FSIO functions must adhere:

File function prototypes

  int (*stat)(pr_fs_t *fs, const char *filename, struct stat *sbuf);
  int (*lstat)(pr_fs_t *fs, const char *filename, struct stat *sbuf);
  int (*rename)(pr_fs_t *fs, const char *oldpath, const char *newpath);
  int (*unlink)(pr_fs_t *fs, const char *path);
  int (*open)(pr_fs_t *fs, const char *path, int flags);
  int (*creat)(pr_fs_t *fs, const char *path, mode_t mode);
  int (*close)(pr_fs_t *fs, int fd);
  int (*read)(pr_fs_t *fs, int fd, char *buf, size_t count);
  int (*write)(pr_fs_t *fs, int fd, const char *buf, size_t count);
  off_t (*lseek)(pr_fs_t *fs, int fd, off_t offset, int whence);
  int (*link)(pr_fs_t *fs, const char *oldpath, const char *newpath);
  int (*symlink)(pr_fs_t *fs, const char *oldpath, const char *newpath);
  int (*readlink)(pr_fs_t *fs, const char *path, char *buf, size_t buflen);
  int (*truncate)(pr_fs_t *fs, off_t length);
  int (*chmod)(pr_fs_t *fs, const char *path, mode_t mode);
  int (*chown)(pr_fs_t *fs, const char *path, uid_t owner, gid_t group);

The open() and creat() prototypes are a little different because, in the system version, they return and operate on file descriptors. As the FSIO abstraction layer uses pr_fh_ts instead of ints as "file handles", these functions return pr_fh_ts, which must be captured by the caller for later use with the other custom FSIO functions.

Directory function prototypes

  int (*chroot)(pr_fs_t *fs, const char *path);
  int (*chdir)(pr_fs_t *fs, const char *path);
  void *(*opendir)(pr_fs_t *fs, const char *name);
  int (*closedir)(pr_fs_t *fs, void *dir);
  struct dirent *(*readdir)(pr_fs_t *fs, void *dir);
  int (*mkdir)(pr_fs_t *fs, const char *path, mode_t mode);
  int (*rmdir)(pr_fs_t *fs, const char *path);

Note that the opendir(3) function returns a DIR *, while the corresponding FSIO access function returns a void *. This is to allow FSIO modules to use their own data types for directory listings.

FSIO Access Functions
The FSIO access functions, the functions the present the unified front to the core code (and to any modules who care to use the FSIO layer), are divided into two groups, file-oriented functions and directory-oriented functions. The difference is simply whether the function is intended to act on a file, or a directory. The access arguments are similar to their normal system or library counterpart functions. These functions are listed in include/fsio.h.

Table of Contents



Author: $Author: castaglia $
Last Updated: $Date: 2003/10/22 06:31:40 $


© Copyright 2000-2002 TJ Saunders
All Rights Reserved