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_t
s 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.