1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter�10.�VFS Modules</title><link rel="stylesheet" href="samba.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.71.0"><link rel="start" href="index.html" title="SAMBA Developers Guide"><link rel="up" href="pt03.html" title="Part�III.�Samba Subsystems"><link rel="prev" href="rpc-plugin.html" title="Chapter�9.�RPC Pluggable Modules"><link rel="next" href="parsing.html" title="Chapter�11.�The smb.conf file"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter�10.�VFS Modules</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="rpc-plugin.html">Prev</a>�</td><th width="60%" align="center">Part�III.�Samba Subsystems</th><td width="20%" align="right">�<a accesskey="n" href="parsing.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="vfs"></a>Chapter�10.�VFS Modules</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Alexander</span> <span class="surname">Bokovoy</span></h3><div class="affiliation"><div class="address"><p><code class="email"><<a href="mailto:ab@samba.org">ab@samba.org</a>></code></p></div></div></div></div><div><div class="author"><h3 class="author"><span class="firstname">Stefan</span> <span class="surname">Metzmacher</span></h3><div class="affiliation"><div class="address"><p><code class="email"><<a href="mailto:metze@samba.org">metze@samba.org</a>></code></p></div></div></div></div><div><p class="pubdate"> 27 May 2003 </p></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="vfs.html#id324691">The Samba (Posix) VFS layer</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id324696">The general interface</a></span></dt><dt><span class="sect2"><a href="vfs.html#id324766">Possible VFS operation layers</a></span></dt></dl></dd><dt><span class="sect1"><a href="vfs.html#id324811">The Interaction between the Samba VFS subsystem and the modules</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id324817">Initialization and registration</a></span></dt><dt><span class="sect2"><a href="vfs.html#id324954">How the Modules handle per connection data</a></span></dt></dl></dd><dt><span class="sect1"><a href="vfs.html#id325112">Upgrading to the New VFS Interface</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id325117">Upgrading from 2.2.* and 3.0aplha modules</a></span></dt></dl></dd><dt><span class="sect1"><a href="vfs.html#id325448">Some Notes</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id325454">Implement TRANSPARENT functions</a></span></dt><dt><span class="sect2"><a href="vfs.html#id325472">Implement OPAQUE functions</a></span></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id324691"></a>The Samba (Posix) VFS layer</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id324696"></a>The general interface</h3></div></div></div><p> 2Each VFS operation has a vfs_op_type, a function pointer and a handle pointer in the 3struct vfs_ops and tree macros to make it easier to call the operations. 4(Take a look at <code class="filename">include/vfs.h</code> and <code class="filename">include/vfs_macros.h</code>.) 5</p><pre class="programlisting"> 6typedef enum _vfs_op_type { 7 SMB_VFS_OP_NOOP = -1, 8 9 ... 10 11 /* File operations */ 12 13 SMB_VFS_OP_OPEN, 14 SMB_VFS_OP_CLOSE, 15 SMB_VFS_OP_READ, 16 SMB_VFS_OP_WRITE, 17 SMB_VFS_OP_LSEEK, 18 SMB_VFS_OP_SENDFILE, 19 20 ... 21 22 SMB_VFS_OP_LAST 23} vfs_op_type; 24</pre><p>This struct contains the function and handle pointers for all operations.</p><pre class="programlisting"> 25struct vfs_ops { 26 struct vfs_fn_pointers { 27 ... 28 29 /* File operations */ 30 31 int (*open)(struct vfs_handle_struct *handle, 32 struct connection_struct *conn, 33 const char *fname, int flags, mode_t mode); 34 int (*close)(struct vfs_handle_struct *handle, 35 struct files_struct *fsp, int fd); 36 ssize_t (*read)(struct vfs_handle_struct *handle, 37 struct files_struct *fsp, int fd, void *data, size_t n); 38 ssize_t (*write)(struct vfs_handle_struct *handle, 39 struct files_struct *fsp, int fd, 40 const void *data, size_t n); 41 SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, 42 struct files_struct *fsp, int fd, 43 SMB_OFF_T offset, int whence); 44 ssize_t (*sendfile)(struct vfs_handle_struct *handle, 45 int tofd, files_struct *fsp, int fromfd, 46 const DATA_BLOB *header, SMB_OFF_T offset, size_t count); 47 48 ... 49 } ops; 50 51 struct vfs_handles_pointers { 52 ... 53 54 /* File operations */ 55 56 struct vfs_handle_struct *open; 57 struct vfs_handle_struct *close; 58 struct vfs_handle_struct *read; 59 struct vfs_handle_struct *write; 60 struct vfs_handle_struct *lseek; 61 struct vfs_handle_struct *sendfile; 62 63 ... 64 } handles; 65}; 66</pre><p> 67This macros SHOULD be used to call any vfs operation. 68DO NOT ACCESS conn->vfs.ops.* directly !!! 69</p><pre class="programlisting"> 70... 71 72/* File operations */ 73#define SMB_VFS_OPEN(conn, fname, flags, mode) \ 74 ((conn)->vfs.ops.open((conn)->vfs.handles.open,\ 75 (conn), (fname), (flags), (mode))) 76#define SMB_VFS_CLOSE(fsp, fd) \ 77 ((fsp)->conn->vfs.ops.close(\ 78 (fsp)->conn->vfs.handles.close, (fsp), (fd))) 79#define SMB_VFS_READ(fsp, fd, data, n) \ 80 ((fsp)->conn->vfs.ops.read(\ 81 (fsp)->conn->vfs.handles.read,\ 82 (fsp), (fd), (data), (n))) 83#define SMB_VFS_WRITE(fsp, fd, data, n) \ 84 ((fsp)->conn->vfs.ops.write(\ 85 (fsp)->conn->vfs.handles.write,\ 86 (fsp), (fd), (data), (n))) 87#define SMB_VFS_LSEEK(fsp, fd, offset, whence) \ 88 ((fsp)->conn->vfs.ops.lseek(\ 89 (fsp)->conn->vfs.handles.lseek,\ 90 (fsp), (fd), (offset), (whence))) 91#define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) \ 92 ((fsp)->conn->vfs.ops.sendfile(\ 93 (fsp)->conn->vfs.handles.sendfile,\ 94 (tofd), (fsp), (fromfd), (header), (offset), (count))) 95 96... 97</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id324766"></a>Possible VFS operation layers</h3></div></div></div><p> 98These values are used by the VFS subsystem when building the conn->vfs 99and conn->vfs_opaque structs for a connection with multiple VFS modules. 100Internally, Samba differentiates only opaque and transparent layers at this process. 101Other types are used for providing better diagnosing facilities. 102</p><p> 103Most modules will provide transparent layers. Opaque layer is for modules 104which implement actual file system calls (like DB-based VFS). For example, 105default POSIX VFS which is built in into Samba is an opaque VFS module. 106</p><p> 107Other layer types (logger, splitter, scanner) were designed to provide different 108degree of transparency and for diagnosing VFS module behaviour. 109</p><p> 110Each module can implement several layers at the same time provided that only 111one layer is used per each operation. 112</p><pre class="programlisting"> 113typedef enum _vfs_op_layer { 114 SMB_VFS_LAYER_NOOP = -1, /* - For using in VFS module to indicate end of array */ 115 /* of operations description */ 116 SMB_VFS_LAYER_OPAQUE = 0, /* - Final level, does not call anything beyond itself */ 117 SMB_VFS_LAYER_TRANSPARENT, /* - Normal operation, calls underlying layer after */ 118 /* possibly changing passed data */ 119 SMB_VFS_LAYER_LOGGER, /* - Logs data, calls underlying layer, logging may not */ 120 /* use Samba VFS */ 121 SMB_VFS_LAYER_SPLITTER, /* - Splits operation, calls underlying layer _and_ own facility, */ 122 /* then combines result */ 123 SMB_VFS_LAYER_SCANNER /* - Checks data and possibly initiates additional */ 124 /* file activity like logging to files _inside_ samba VFS */ 125} vfs_op_layer; 126</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id324811"></a>The Interaction between the Samba VFS subsystem and the modules</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id324817"></a>Initialization and registration</h3></div></div></div><p> 127As each Samba module a VFS module should have a 128</p><pre class="programlisting">NTSTATUS vfs_example_init(void);</pre><p> function if it's staticly linked to samba or 129</p><pre class="programlisting">NTSTATUS init_module(void);</pre><p> function if it's a shared module. 130</p><p> 131This should be the only non static function inside the module. 132Global variables should also be static! 133</p><p> 134The module should register its functions via the 135</p><pre class="programlisting"> 136NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples); 137</pre><p> function. 138</p><div class="variablelist"><dl><dt><span class="term">version</span></dt><dd><p>should be filled with SMB_VFS_INTERFACE_VERSION</p></dd><dt><span class="term">name</span></dt><dd><p>this is the name witch can be listed in the 139<code class="literal">vfs objects</code> parameter to use this module.</p></dd><dt><span class="term">vfs_op_tuples</span></dt><dd><p> 140this is an array of vfs_op_tuple's. 141(vfs_op_tuples is descripted in details below.) 142</p></dd></dl></div><p> 143For each operation the module wants to provide it has a entry in the 144vfs_op_tuple array. 145</p><pre class="programlisting"> 146typedef struct _vfs_op_tuple { 147 void* op; 148 vfs_op_type type; 149 vfs_op_layer layer; 150} vfs_op_tuple; 151</pre><div class="variablelist"><dl><dt><span class="term">op</span></dt><dd><p>the function pointer to the specified function.</p></dd><dt><span class="term">type</span></dt><dd><p>the vfs_op_type of the function to specified witch operation the function provides.</p></dd><dt><span class="term">layer</span></dt><dd><p>the vfs_op_layer in whitch the function operates.</p></dd></dl></div><p>A simple example:</p><pre class="programlisting"> 152static vfs_op_tuple example_op_tuples[] = { 153 {SMB_VFS_OP(example_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, 154 {SMB_VFS_OP(example_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, 155 156 {SMB_VFS_OP(example_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_OPAQUE}, 157 158 /* This indicates the end of the array */ 159 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} 160}; 161 162NTSTATUS init_module(void) 163{ 164 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "example", example_op_tuples); 165} 166</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id324954"></a>How the Modules handle per connection data</h3></div></div></div><p>Each VFS function has as first parameter a pointer to the modules vfs_handle_struct. 167</p><pre class="programlisting"> 168typedef struct vfs_handle_struct { 169 struct vfs_handle_struct *next, *prev; 170 const char *param; 171 struct vfs_ops vfs_next; 172 struct connection_struct *conn; 173 void *data; 174 void (*free_data)(void **data); 175} vfs_handle_struct; 176</pre><div class="variablelist"><dl><dt><span class="term">param</span></dt><dd><p>this is the module parameter specified in the <code class="literal">vfs objects</code> parameter.</p><p>e.g. for 'vfs objects = example:test' param would be "test".</p></dd><dt><span class="term">vfs_next</span></dt><dd><p>This vfs_ops struct contains the information for calling the next module operations. 177Use the SMB_VFS_NEXT_* macros to call a next module operations and 178don't access handle->vfs_next.ops.* directly!</p></dd><dt><span class="term">conn</span></dt><dd><p>This is a pointer back to the connection_struct to witch the handle belongs.</p></dd><dt><span class="term">data</span></dt><dd><p>This is a pointer for holding module private data. 179You can alloc data with connection life time on the handle->conn->mem_ctx TALLOC_CTX. 180But you can also manage the memory allocation yourself.</p></dd><dt><span class="term">free_data</span></dt><dd><p>This is a function pointer to a function that free's the module private data. 181If you talloc your private data on the TALLOC_CTX handle->conn->mem_ctx, 182you can set this function pointer to NULL.</p></dd></dl></div><p>Some useful MACROS for handle private data. 183</p><pre class="programlisting"> 184#define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \ 185 if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \ 186 DEBUG(0,("%s() failed to get vfs_handle->data!\n",FUNCTION_MACRO)); \ 187 ret; \ 188 } \ 189} 190 191#define SMB_VFS_HANDLE_SET_DATA(handle, datap, free_fn, type, ret) { \ 192 if (!(handle)) { \ 193 DEBUG(0,("%s() failed to set handle->data!\n",FUNCTION_MACRO)); \ 194 ret; \ 195 } else { \ 196 if ((handle)->free_data) { \ 197 (handle)->free_data(&(handle)->data); \ 198 } \ 199 (handle)->data = (void *)datap; \ 200 (handle)->free_data = free_fn; \ 201 } \ 202} 203 204#define SMB_VFS_HANDLE_FREE_DATA(handle) { \ 205 if ((handle) && (handle)->free_data) { \ 206 (handle)->free_data(&(handle)->data); \ 207 } \ 208} 209</pre><p>How SMB_VFS_LAYER_TRANSPARENT functions can call the SMB_VFS_LAYER_OPAQUE functions.</p><p>The easiest way to do this is to use the SMB_VFS_OPAQUE_* macros. 210</p><pre class="programlisting"> 211... 212/* File operations */ 213#define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) \ 214 ((conn)->vfs_opaque.ops.open(\ 215 (conn)->vfs_opaque.handles.open,\ 216 (conn), (fname), (flags), (mode))) 217#define SMB_VFS_OPAQUE_CLOSE(fsp, fd) \ 218 ((fsp)->conn->vfs_opaque.ops.close(\ 219 (fsp)->conn->vfs_opaque.handles.close,\ 220 (fsp), (fd))) 221#define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) \ 222 ((fsp)->conn->vfs_opaque.ops.read(\ 223 (fsp)->conn->vfs_opaque.handles.read,\ 224 (fsp), (fd), (data), (n))) 225#define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) \ 226 ((fsp)->conn->vfs_opaque.ops.write(\ 227 (fsp)->conn->vfs_opaque.handles.write,\ 228 (fsp), (fd), (data), (n))) 229#define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) \ 230 ((fsp)->conn->vfs_opaque.ops.lseek(\ 231 (fsp)->conn->vfs_opaque.handles.lseek,\ 232 (fsp), (fd), (offset), (whence))) 233#define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) \ 234 ((fsp)->conn->vfs_opaque.ops.sendfile(\ 235 (fsp)->conn->vfs_opaque.handles.sendfile,\ 236 (tofd), (fsp), (fromfd), (header), (offset), (count))) 237... 238</pre><p>How SMB_VFS_LAYER_TRANSPARENT functions can call the next modules functions.</p><p>The easiest way to do this is to use the SMB_VFS_NEXT_* macros. 239</p><pre class="programlisting"> 240... 241/* File operations */ 242#define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) \ 243 ((handle)->vfs_next.ops.open(\ 244 (handle)->vfs_next.handles.open,\ 245 (conn), (fname), (flags), (mode))) 246#define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) \ 247 ((handle)->vfs_next.ops.close(\ 248 (handle)->vfs_next.handles.close,\ 249 (fsp), (fd))) 250#define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) \ 251 ((handle)->vfs_next.ops.read(\ 252 (handle)->vfs_next.handles.read,\ 253 (fsp), (fd), (data), (n))) 254#define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) \ 255 ((handle)->vfs_next.ops.write(\ 256 (handle)->vfs_next.handles.write,\ 257 (fsp), (fd), (data), (n))) 258#define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) \ 259 ((handle)->vfs_next.ops.lseek(\ 260 (handle)->vfs_next.handles.lseek,\ 261 (fsp), (fd), (offset), (whence))) 262#define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) \ 263 ((handle)->vfs_next.ops.sendfile(\ 264 (handle)->vfs_next.handles.sendfile,\ 265 (tofd), (fsp), (fromfd), (header), (offset), (count))) 266... 267</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id325112"></a>Upgrading to the New VFS Interface</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id325117"></a>Upgrading from 2.2.* and 3.0aplha modules</h3></div></div></div><div class="orderedlist"><ol type="1"><li><p> 268Add "vfs_handle_struct *handle, " as first parameter to all vfs operation functions. 269e.g. example_connect(connection_struct *conn, const char *service, const char *user); 270-> example_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user); 271</p></li><li><p> 272Replace "default_vfs_ops." with "smb_vfs_next_". 273e.g. default_vfs_ops.connect(conn, service, user); 274-> smb_vfs_next_connect(conn, service, user); 275</p></li><li><p> 276Uppercase all "smb_vfs_next_*" functions. 277e.g. smb_vfs_next_connect(conn, service, user); 278-> SMB_VFS_NEXT_CONNECT(conn, service, user); 279</p></li><li><p> 280Add "handle, " as first parameter to all SMB_VFS_NEXT_*() calls. 281e.g. SMB_VFS_NEXT_CONNECT(conn, service, user); 282-> SMB_VFS_NEXT_CONNECT(handle, conn, service, user); 283</p></li><li><p> 284(Only for 2.2.* modules) 285Convert the old struct vfs_ops example_ops to 286a vfs_op_tuple example_op_tuples[] array. 287e.g. 288</p><pre class="programlisting"> 289struct vfs_ops example_ops = { 290 /* Disk operations */ 291 example_connect, /* connect */ 292 example_disconnect, /* disconnect */ 293 NULL, /* disk free * 294 /* Directory operations */ 295 NULL, /* opendir */ 296 NULL, /* readdir */ 297 NULL, /* mkdir */ 298 NULL, /* rmdir */ 299 NULL, /* closedir */ 300 /* File operations */ 301 NULL, /* open */ 302 NULL, /* close */ 303 NULL, /* read */ 304 NULL, /* write */ 305 NULL, /* lseek */ 306 NULL, /* sendfile */ 307 NULL, /* rename */ 308 NULL, /* fsync */ 309 example_stat, /* stat */ 310 example_fstat, /* fstat */ 311 example_lstat, /* lstat */ 312 NULL, /* unlink */ 313 NULL, /* chmod */ 314 NULL, /* fchmod */ 315 NULL, /* chown */ 316 NULL, /* fchown */ 317 NULL, /* chdir */ 318 NULL, /* getwd */ 319 NULL, /* utime */ 320 NULL, /* ftruncate */ 321 NULL, /* lock */ 322 NULL, /* symlink */ 323 NULL, /* readlink */ 324 NULL, /* link */ 325 NULL, /* mknod */ 326 NULL, /* realpath */ 327 NULL, /* fget_nt_acl */ 328 NULL, /* get_nt_acl */ 329 NULL, /* fset_nt_acl */ 330 NULL, /* set_nt_acl */ 331 332 NULL, /* chmod_acl */ 333 NULL, /* fchmod_acl */ 334 335 NULL, /* sys_acl_get_entry */ 336 NULL, /* sys_acl_get_tag_type */ 337 NULL, /* sys_acl_get_permset */ 338 NULL, /* sys_acl_get_qualifier */ 339 NULL, /* sys_acl_get_file */ 340 NULL, /* sys_acl_get_fd */ 341 NULL, /* sys_acl_clear_perms */ 342 NULL, /* sys_acl_add_perm */ 343 NULL, /* sys_acl_to_text */ 344 NULL, /* sys_acl_init */ 345 NULL, /* sys_acl_create_entry */ 346 NULL, /* sys_acl_set_tag_type */ 347 NULL, /* sys_acl_set_qualifier */ 348 NULL, /* sys_acl_set_permset */ 349 NULL, /* sys_acl_valid */ 350 NULL, /* sys_acl_set_file */ 351 NULL, /* sys_acl_set_fd */ 352 NULL, /* sys_acl_delete_def_file */ 353 NULL, /* sys_acl_get_perm */ 354 NULL, /* sys_acl_free_text */ 355 NULL, /* sys_acl_free_acl */ 356 NULL /* sys_acl_free_qualifier */ 357}; 358</pre><p> 359-> 360</p><pre class="programlisting"> 361static vfs_op_tuple example_op_tuples[] = { 362 {SMB_VFS_OP(example_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, 363 {SMB_VFS_OP(example_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, 364 365 {SMB_VFS_OP(example_fstat), SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_TRANSPARENT}, 366 {SMB_VFS_OP(example_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT}, 367 {SMB_VFS_OP(example_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_TRANSPARENT}, 368 369 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} 370}; 371</pre><p> 372</p></li><li><p> 373Move the example_op_tuples[] array to the end of the file. 374</p></li><li><p> 375Add the init_module() function at the end of the file. 376e.g. 377</p><pre class="programlisting"> 378NTSTATUS init_module(void) 379{ 380 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,"example",example_op_tuples); 381} 382</pre><p> 383</p></li><li><p> 384Check if your vfs_init() function does more then just prepare the vfs_ops structs or 385remember the struct smb_vfs_handle_struct. 386</p><table class="simplelist" border="0" summary="Simple list"><tr><td>If NOT you can remove the vfs_init() function.</td></tr><tr><td>If YES decide if you want to move the code to the example_connect() operation or to the init_module(). And then remove vfs_init(). 387 e.g. a debug class registration should go into init_module() and the allocation of private data should go to example_connect().</td></tr></table><p> 388</p></li><li><p> 389(Only for 3.0alpha* modules) 390Check if your vfs_done() function contains needed code. 391</p><table class="simplelist" border="0" summary="Simple list"><tr><td>If NOT you can remove the vfs_done() function.</td></tr><tr><td>If YES decide if you can move the code to the example_disconnect() operation. Otherwise register a SMB_EXIT_EVENT with smb_register_exit_event(); (Described in the <a href="modules.html" title="Chapter�8.�Modules">modules section</a>) And then remove vfs_done(). e.g. the freeing of private data should go to example_disconnect(). 392</td></tr></table><p> 393</p></li><li><p> 394Check if you have any global variables left. 395Decide if it wouldn't be better to have this data on a connection basis. 396</p><table class="simplelist" border="0" summary="Simple list"><tr><td>If NOT leave them as they are. (e.g. this could be the variable for the private debug class.)</td></tr><tr><td>If YES pack all this data into a struct. You can use handle->data to point to such a struct on a per connection basis.</td></tr></table><p> 397 398 e.g. if you have such a struct: 399</p><pre class="programlisting"> 400struct example_privates { 401 char *some_string; 402 int db_connection; 403}; 404</pre><p> 405first way of doing it: 406</p><pre class="programlisting"> 407static int example_connect(vfs_handle_struct *handle, 408 connection_struct *conn, const char *service, 409 const char* user) 410{ 411 struct example_privates *data = NULL; 412 413 /* alloc our private data */ 414 data = (struct example_privates *)talloc_zero(conn->mem_ctx, sizeof(struct example_privates)); 415 if (!data) { 416 DEBUG(0,("talloc_zero() failed\n")); 417 return -1; 418 } 419 420 /* init out private data */ 421 data->some_string = talloc_strdup(conn->mem_ctx,"test"); 422 if (!data->some_string) { 423 DEBUG(0,("talloc_strdup() failed\n")); 424 return -1; 425 } 426 427 data->db_connection = open_db_conn(); 428 429 /* and now store the private data pointer in handle->data 430 * we don't need to specify a free_function here because 431 * we use the connection TALLOC context. 432 * (return -1 if something failed.) 433 */ 434 VFS_HANDLE_SET_DATA(handle, data, NULL, struct example_privates, return -1); 435 436 return SMB_VFS_NEXT_CONNECT(handle,conn,service,user); 437} 438 439static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd) 440{ 441 struct example_privates *data = NULL; 442 443 /* get the pointer to our private data 444 * return -1 if something failed 445 */ 446 SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1); 447 448 /* do something here...*/ 449 DEBUG(0,("some_string: %s\n",data->some_string)); 450 451 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd); 452} 453</pre><p> 454second way of doing it: 455</p><pre class="programlisting"> 456static void free_example_privates(void **datap) 457{ 458 struct example_privates *data = (struct example_privates *)*datap; 459 460 SAFE_FREE(data->some_string); 461 SAFE_FREE(data); 462 463 *datap = NULL; 464 465 return; 466} 467 468static int example_connect(vfs_handle_struct *handle, 469 connection_struct *conn, const char *service, 470 const char* user) 471{ 472 struct example_privates *data = NULL; 473 474 /* alloc our private data */ 475 data = (struct example_privates *)malloc(sizeof(struct example_privates)); 476 if (!data) { 477 DEBUG(0,("malloc() failed\n")); 478 return -1; 479 } 480 481 /* init out private data */ 482 data->some_string = strdup("test"); 483 if (!data->some_string) { 484 DEBUG(0,("strdup() failed\n")); 485 return -1; 486 } 487 488 data->db_connection = open_db_conn(); 489 490 /* and now store the private data pointer in handle->data 491 * we need to specify a free_function because we used malloc() and strdup(). 492 * (return -1 if something failed.) 493 */ 494 SMB_VFS_HANDLE_SET_DATA(handle, data, free_example_privates, struct example_privates, return -1); 495 496 return SMB_VFS_NEXT_CONNECT(handle,conn,service,user); 497} 498 499static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd) 500{ 501 struct example_privates *data = NULL; 502 503 /* get the pointer to our private data 504 * return -1 if something failed 505 */ 506 SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1); 507 508 /* do something here...*/ 509 DEBUG(0,("some_string: %s\n",data->some_string)); 510 511 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd); 512} 513</pre><p> 514</p></li><li><p> 515To make it easy to build 3rd party modules it would be usefull to provide 516configure.in, (configure), install.sh and Makefile.in with the module. 517(Take a look at the example in <code class="filename">examples/VFS</code>.) 518</p><p> 519The configure script accepts <code class="option">--with-samba-source</code> to specify 520the path to the samba source tree. 521It also accept <code class="option">--enable-developer</code> which lets the compiler 522give you more warnings. 523</p><p> 524The idea is that you can extend this 525<code class="filename">configure.in</code> and <code class="filename">Makefile.in</code> scripts 526for your module. 527</p></li><li><p> 528Compiling & Testing... 529</p><table class="simplelist" border="0" summary="Simple list"><tr><td><strong class="userinput"><code>./configure <code class="option">--enable-developer</code></code></strong> ...</td></tr><tr><td><strong class="userinput"><code>make</code></strong></td></tr><tr><td>Try to fix all compiler warnings</td></tr><tr><td><strong class="userinput"><code>make</code></strong></td></tr><tr><td>Testing, Testing, Testing ...</td></tr></table><p> 530</p></li></ol></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id325448"></a>Some Notes</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id325454"></a>Implement TRANSPARENT functions</h3></div></div></div><p> 531Avoid writing functions like this: 532 533</p><pre class="programlisting"> 534static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd) 535{ 536 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd); 537} 538</pre><p> 539 540Overload only the functions you really need to! 541</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id325472"></a>Implement OPAQUE functions</h3></div></div></div><p> 542If you want to just implement a better version of a 543default samba opaque function 544(e.g. like a disk_free() function for a special filesystem) 545it's ok to just overload that specific function. 546</p><p> 547If you want to implement a database filesystem or 548something different from a posix filesystem. 549Make sure that you overload every vfs operation!!! 550</p><p> 551Functions your FS does not support should be overloaded by something like this: 552e.g. for a readonly filesystem. 553</p><pre class="programlisting"> 554static int example_rename(vfs_handle_struct *handle, connection_struct *conn, 555 char *oldname, char *newname) 556{ 557 DEBUG(10,("function rename() not allowed on vfs 'example'\n")); 558 errno = ENOSYS; 559 return -1; 560} 561</pre></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="rpc-plugin.html">Prev</a>�</td><td width="20%" align="center"><a accesskey="u" href="pt03.html">Up</a></td><td width="40%" align="right">�<a accesskey="n" href="parsing.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter�9.�RPC Pluggable Modules�</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">�Chapter�11.�The smb.conf file</td></tr></table></div></body></html> 562