Software: Apache/2.0.54 (Fedora). PHP/5.0.4 uname -a: Linux mina-info.me 2.6.17-1.2142_FC4smp #1 SMP Tue Jul 11 22:57:02 EDT 2006 i686 uid=48(apache) gid=48(apache) groups=48(apache) Safe-mode: OFF (not secure) /usr/bin/X11/./../../share/doc/samba-3.0.23a/htmldocs/Samba3-HOWTO/../Samba3-Developers-Guide/ drwxr-xr-x |
Viewing file: Select action/file-type: Table of Contents
Each VFS operation has a vfs_op_type, a function pointer and a handle pointer in the
struct vfs_ops and tree macros to make it easier to call the operations.
(Take a look at typedef enum _vfs_op_type { SMB_VFS_OP_NOOP = -1, ... /* File operations */ SMB_VFS_OP_OPEN, SMB_VFS_OP_CLOSE, SMB_VFS_OP_READ, SMB_VFS_OP_WRITE, SMB_VFS_OP_LSEEK, SMB_VFS_OP_SENDFILE, ... SMB_VFS_OP_LAST } vfs_op_type; This struct contains the function and handle pointers for all operations. struct vfs_ops { struct vfs_fn_pointers { ... /* File operations */ int (*open)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, int flags, mode_t mode); int (*close)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); ssize_t (*read)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n); ssize_t (*write)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n); SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence); ssize_t (*sendfile)(struct vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count); ... } ops; struct vfs_handles_pointers { ... /* File operations */ struct vfs_handle_struct *open; struct vfs_handle_struct *close; struct vfs_handle_struct *read; struct vfs_handle_struct *write; struct vfs_handle_struct *lseek; struct vfs_handle_struct *sendfile; ... } handles; }; This macros SHOULD be used to call any vfs operation. DO NOT ACCESS conn->vfs.ops.* directly !!! ... /* File operations */ #define SMB_VFS_OPEN(conn, fname, flags, mode) \ ((conn)->vfs.ops.open((conn)->vfs.handles.open,\ (conn), (fname), (flags), (mode))) #define SMB_VFS_CLOSE(fsp, fd) \ ((fsp)->conn->vfs.ops.close(\ (fsp)->conn->vfs.handles.close, (fsp), (fd))) #define SMB_VFS_READ(fsp, fd, data, n) \ ((fsp)->conn->vfs.ops.read(\ (fsp)->conn->vfs.handles.read,\ (fsp), (fd), (data), (n))) #define SMB_VFS_WRITE(fsp, fd, data, n) \ ((fsp)->conn->vfs.ops.write(\ (fsp)->conn->vfs.handles.write,\ (fsp), (fd), (data), (n))) #define SMB_VFS_LSEEK(fsp, fd, offset, whence) \ ((fsp)->conn->vfs.ops.lseek(\ (fsp)->conn->vfs.handles.lseek,\ (fsp), (fd), (offset), (whence))) #define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) \ ((fsp)->conn->vfs.ops.sendfile(\ (fsp)->conn->vfs.handles.sendfile,\ (tofd), (fsp), (fromfd), (header), (offset), (count))) ... These values are used by the VFS subsystem when building the conn->vfs and conn->vfs_opaque structs for a connection with multiple VFS modules. Internally, Samba differentiates only opaque and transparent layers at this process. Other types are used for providing better diagnosing facilities. Most modules will provide transparent layers. Opaque layer is for modules which implement actual file system calls (like DB-based VFS). For example, default POSIX VFS which is built in into Samba is an opaque VFS module. Other layer types (logger, splitter, scanner) were designed to provide different degree of transparency and for diagnosing VFS module behaviour. Each module can implement several layers at the same time provided that only one layer is used per each operation. typedef enum _vfs_op_layer { SMB_VFS_LAYER_NOOP = -1, /* - For using in VFS module to indicate end of array */ /* of operations description */ SMB_VFS_LAYER_OPAQUE = 0, /* - Final level, does not call anything beyond itself */ SMB_VFS_LAYER_TRANSPARENT, /* - Normal operation, calls underlying layer after */ /* possibly changing passed data */ SMB_VFS_LAYER_LOGGER, /* - Logs data, calls underlying layer, logging may not */ /* use Samba VFS */ SMB_VFS_LAYER_SPLITTER, /* - Splits operation, calls underlying layer _and_ own facility, */ /* then combines result */ SMB_VFS_LAYER_SCANNER /* - Checks data and possibly initiates additional */ /* file activity like logging to files _inside_ samba VFS */ } vfs_op_layer; As each Samba module a VFS module should have a NTSTATUS vfs_example_init(void); function if it's staticly linked to samba or NTSTATUS init_module(void); function if it's a shared module. This should be the only non static function inside the module. Global variables should also be static! The module should register its functions via the NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples); function.
For each operation the module wants to provide it has a entry in the vfs_op_tuple array. typedef struct _vfs_op_tuple { void* op; vfs_op_type type; vfs_op_layer layer; } vfs_op_tuple;
A simple example: static vfs_op_tuple example_op_tuples[] = { {SMB_VFS_OP(example_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(example_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(example_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_OPAQUE}, /* This indicates the end of the array */ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; NTSTATUS init_module(void) { return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "example", example_op_tuples); } Each VFS function has as first parameter a pointer to the modules vfs_handle_struct. typedef struct vfs_handle_struct { struct vfs_handle_struct *next, *prev; const char *param; struct vfs_ops vfs_next; struct connection_struct *conn; void *data; void (*free_data)(void **data); } vfs_handle_struct;
Some useful MACROS for handle private data. #define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \ if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \ DEBUG(0,("%s() failed to get vfs_handle->data!\n",FUNCTION_MACRO)); \ ret; \ } \ } #define SMB_VFS_HANDLE_SET_DATA(handle, datap, free_fn, type, ret) { \ if (!(handle)) { \ DEBUG(0,("%s() failed to set handle->data!\n",FUNCTION_MACRO)); \ ret; \ } else { \ if ((handle)->free_data) { \ (handle)->free_data(&(handle)->data); \ } \ (handle)->data = (void *)datap; \ (handle)->free_data = free_fn; \ } \ } #define SMB_VFS_HANDLE_FREE_DATA(handle) { \ if ((handle) && (handle)->free_data) { \ (handle)->free_data(&(handle)->data); \ } \ } How SMB_VFS_LAYER_TRANSPARENT functions can call the SMB_VFS_LAYER_OPAQUE functions. The easiest way to do this is to use the SMB_VFS_OPAQUE_* macros. ... /* File operations */ #define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) \ ((conn)->vfs_opaque.ops.open(\ (conn)->vfs_opaque.handles.open,\ (conn), (fname), (flags), (mode))) #define SMB_VFS_OPAQUE_CLOSE(fsp, fd) \ ((fsp)->conn->vfs_opaque.ops.close(\ (fsp)->conn->vfs_opaque.handles.close,\ (fsp), (fd))) #define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) \ ((fsp)->conn->vfs_opaque.ops.read(\ (fsp)->conn->vfs_opaque.handles.read,\ (fsp), (fd), (data), (n))) #define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) \ ((fsp)->conn->vfs_opaque.ops.write(\ (fsp)->conn->vfs_opaque.handles.write,\ (fsp), (fd), (data), (n))) #define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) \ ((fsp)->conn->vfs_opaque.ops.lseek(\ (fsp)->conn->vfs_opaque.handles.lseek,\ (fsp), (fd), (offset), (whence))) #define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) \ ((fsp)->conn->vfs_opaque.ops.sendfile(\ (fsp)->conn->vfs_opaque.handles.sendfile,\ (tofd), (fsp), (fromfd), (header), (offset), (count))) ... How SMB_VFS_LAYER_TRANSPARENT functions can call the next modules functions. The easiest way to do this is to use the SMB_VFS_NEXT_* macros. ... /* File operations */ #define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) \ ((handle)->vfs_next.ops.open(\ (handle)->vfs_next.handles.open,\ (conn), (fname), (flags), (mode))) #define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) \ ((handle)->vfs_next.ops.close(\ (handle)->vfs_next.handles.close,\ (fsp), (fd))) #define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) \ ((handle)->vfs_next.ops.read(\ (handle)->vfs_next.handles.read,\ (fsp), (fd), (data), (n))) #define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) \ ((handle)->vfs_next.ops.write(\ (handle)->vfs_next.handles.write,\ (fsp), (fd), (data), (n))) #define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) \ ((handle)->vfs_next.ops.lseek(\ (handle)->vfs_next.handles.lseek,\ (fsp), (fd), (offset), (whence))) #define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) \ ((handle)->vfs_next.ops.sendfile(\ (handle)->vfs_next.handles.sendfile,\ (tofd), (fsp), (fromfd), (header), (offset), (count))) ...
Avoid writing functions like this: static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd) { return SMB_VFS_NEXT_CLOSE(handle, fsp, fd); } Overload only the functions you really need to! If you want to just implement a better version of a default samba opaque function (e.g. like a disk_free() function for a special filesystem) it's ok to just overload that specific function. If you want to implement a database filesystem or something different from a posix filesystem. Make sure that you overload every vfs operation!!! Functions your FS does not support should be overloaded by something like this: e.g. for a readonly filesystem. static int example_rename(vfs_handle_struct *handle, connection_struct *conn, char *oldname, char *newname) { DEBUG(10,("function rename() not allowed on vfs 'example'\n")); errno = ENOSYS; return -1; } |
:: Command execute :: | |
--[ c99shell v. 1.0 pre-release build #16 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0037 ]-- |