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.68.1"><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#id2525317">The Samba (Posix) VFS layer</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id2525323">The general interface</a></span></dt><dt><span class="sect2"><a href="vfs.html#id2525419">Possible VFS operation layers</a></span></dt></dl></dd><dt><span class="sect1"><a href="vfs.html#id2525480">The Interaction between the Samba VFS subsystem and the modules</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id2525487">Initialization and registration</a></span></dt><dt><span class="sect2"><a href="vfs.html#id2525637">How the Modules handle per connection data</a></span></dt></dl></dd><dt><span class="sect1"><a href="vfs.html#id2525842">Upgrading to the New VFS Interface</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id2525848">Upgrading from 2.2.* and 3.0aplha modules</a></span></dt></dl></dd><dt><span class="sect1"><a href="vfs.html#id2526400">Some Notes</a></span></dt><dd><dl><dt><span class="sect2"><a href="vfs.html#id2526406">Implement TRANSPARENT functions</a></span></dt><dt><span class="sect2"><a href="vfs.html#id2526426">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="id2525317"></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="id2525323"></a>The general interface</h3></div></div></div><p>
2 Each VFS operation has a vfs_op_type, a function pointer and a handle pointer in the
3 struct 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">
6 typedef enum _vfs_op_type {
24 </pre><p>This struct contains the function and handle pointers for all operations.</p><pre class="programlisting">
26 struct vfs_fn_pointers {
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);
51 struct vfs_handles_pointers {
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;
67 This macros SHOULD be used to call any vfs operation.
68 DO NOT ACCESS conn->vfs.ops.* directly !!!
69 </p><pre class="programlisting">
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)))
97 </pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2525419"></a>Possible VFS operation layers</h3></div></div></div><p>
98 These values are used by the VFS subsystem when building the conn->vfs
99 and conn->vfs_opaque structs for a connection with multiple VFS modules.
100 Internally, Samba differentiates only opaque and transparent layers at this process.
101 Other types are used for providing better diagnosing facilities.
103 Most modules will provide transparent layers. Opaque layer is for modules
104 which implement actual file system calls (like DB-based VFS). For example,
105 default POSIX VFS which is built in into Samba is an opaque VFS module.
107 Other layer types (logger, splitter, scanner) were designed to provide different
108 degree of transparency and for diagnosing VFS module behaviour.
110 Each module can implement several layers at the same time provided that only
111 one layer is used per each operation.
112 </p><pre class="programlisting">
113 typedef 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 */
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 */
126 </pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2525480"></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="id2525487"></a>Initialization and registration</h3></div></div></div><p>
127 As 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.
131 This should be the only non static function inside the module.
132 Global variables should also be static!
134 The module should register its functions via the
135 </p><pre class="programlisting">
136 NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples);
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 <span><strong class="command">vfs objects</strong></span> parameter to use this module.</p></dd><dt><span class="term">vfs_op_tuples</span></dt><dd><p>
140 this is an array of vfs_op_tuple's.
141 (vfs_op_tuples is descripted in details below.)
142 </p></dd></dl></div><p>
143 For each operation the module wants to provide it has a entry in the
145 </p><pre class="programlisting">
146 typedef struct _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">
152 static 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},
156 {SMB_VFS_OP(example_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_OPAQUE},
158 /* This indicates the end of the array */
159 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
162 NTSTATUS init_module(void)
164 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "example", example_op_tuples);
166 </pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2525637"></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">
168 typedef struct vfs_handle_struct {
169 struct vfs_handle_struct *next, *prev;
171 struct vfs_ops vfs_next;
172 struct connection_struct *conn;
174 void (*free_data)(void **data);
176 </pre><div class="variablelist"><dl><dt><span class="term">param</span></dt><dd><p>this is the module parameter specified in the <span><strong class="command">vfs objects</strong></span> 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.
177 Use the SMB_VFS_NEXT_* macros to call a next module operations and
178 don'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.
179 You can alloc data with connection life time on the handle->conn->mem_ctx TALLOC_CTX.
180 But 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.
181 If you talloc your private data on the TALLOC_CTX handle->conn->mem_ctx,
182 you 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)); \
191 #define SMB_VFS_HANDLE_SET_DATA(handle, datap, free_fn, type, ret) { \
193 DEBUG(0,("%s() failed to set handle->data!\n",FUNCTION_MACRO)); \
196 if ((handle)->free_data) { \
197 (handle)->free_data(&(handle)->data); \
199 (handle)->data = (void *)datap; \
200 (handle)->free_data = free_fn; \
204 #define SMB_VFS_HANDLE_FREE_DATA(handle) { \
205 if ((handle) && (handle)->free_data) { \
206 (handle)->free_data(&(handle)->data); \
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">
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,\
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)))
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">
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,\
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)))
267 </pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2525842"></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="id2525848"></a>Upgrading from 2.2.* and 3.0aplha modules</h3></div></div></div><div class="orderedlist"><ol type="1"><li><p>
268 Add "vfs_handle_struct *handle, " as first parameter to all vfs operation functions.
269 e.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);
272 Replace "default_vfs_ops." with "smb_vfs_next_".
273 e.g. default_vfs_ops.connect(conn, service, user);
274 -> smb_vfs_next_connect(conn, service, user);
276 Uppercase all "smb_vfs_next_*" functions.
277 e.g. smb_vfs_next_connect(conn, service, user);
278 -> SMB_VFS_NEXT_CONNECT(conn, service, user);
280 Add "handle, " as first parameter to all SMB_VFS_NEXT_*() calls.
281 e.g. SMB_VFS_NEXT_CONNECT(conn, service, user);
282 -> SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
284 (Only for 2.2.* modules)
285 Convert the old struct vfs_ops example_ops to
286 a vfs_op_tuple example_op_tuples[] array.
288 </p><pre class="programlisting">
289 struct vfs_ops example_ops = {
290 /* Disk operations */
291 example_connect, /* connect */
292 example_disconnect, /* disconnect */
294 /* Directory operations */
300 /* File operations */
309 example_stat, /* stat */
310 example_fstat, /* fstat */
311 example_lstat, /* lstat */
320 NULL, /* ftruncate */
327 NULL, /* fget_nt_acl */
328 NULL, /* get_nt_acl */
329 NULL, /* fset_nt_acl */
330 NULL, /* set_nt_acl */
332 NULL, /* chmod_acl */
333 NULL, /* fchmod_acl */
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 */
360 </p><pre class="programlisting">
361 static 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},
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},
369 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
373 Move the example_op_tuples[] array to the end of the file.
375 Add the init_module() function at the end of the file.
377 </p><pre class="programlisting">
378 NTSTATUS init_module(void)
380 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,"example",example_op_tuples);
384 Check if your vfs_init() function does more then just prepare the vfs_ops structs or
385 remember 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>
389 (Only for 3.0alpha* modules)
390 Check 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>
394 Check if you have any global variables left.
395 Decide 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>
398 e.g. if you have such a struct:
399 </p><pre class="programlisting">
400 struct example_privates {
405 first way of doing it:
406 </p><pre class="programlisting">
407 static int example_connect(vfs_handle_struct *handle,
408 connection_struct *conn, const char *service,
411 struct example_privates *data = NULL;
413 /* alloc our private data */
414 data = (struct example_privates *)talloc_zero(conn->mem_ctx, sizeof(struct example_privates));
416 DEBUG(0,("talloc_zero() failed\n"));
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"));
427 data->db_connection = open_db_conn();
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.)
434 VFS_HANDLE_SET_DATA(handle, data, NULL, struct example_privates, return -1);
436 return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
439 static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
441 struct example_privates *data = NULL;
443 /* get the pointer to our private data
444 * return -1 if something failed
446 SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1);
448 /* do something here...*/
449 DEBUG(0,("some_string: %s\n",data->some_string));
451 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
454 second way of doing it:
455 </p><pre class="programlisting">
456 static void free_example_privates(void **datap)
458 struct example_privates *data = (struct example_privates *)*datap;
460 SAFE_FREE(data->some_string);
468 static int example_connect(vfs_handle_struct *handle,
469 connection_struct *conn, const char *service,
472 struct example_privates *data = NULL;
474 /* alloc our private data */
475 data = (struct example_privates *)malloc(sizeof(struct example_privates));
477 DEBUG(0,("malloc() failed\n"));
481 /* init out private data */
482 data->some_string = strdup("test");
483 if (!data->some_string) {
484 DEBUG(0,("strdup() failed\n"));
488 data->db_connection = open_db_conn();
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.)
494 SMB_VFS_HANDLE_SET_DATA(handle, data, free_example_privates, struct example_privates, return -1);
496 return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
499 static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
501 struct example_privates *data = NULL;
503 /* get the pointer to our private data
504 * return -1 if something failed
506 SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1);
508 /* do something here...*/
509 DEBUG(0,("some_string: %s\n",data->some_string));
511 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
515 To make it easy to build 3rd party modules it would be usefull to provide
516 configure.in, (configure), install.sh and Makefile.in with the module.
517 (Take a look at the example in <code class="filename">examples/VFS</code>.)
519 The configure script accepts <code class="option">--with-samba-source</code> to specify
520 the path to the samba source tree.
521 It also accept <code class="option">--enable-developer</code> which lets the compiler
522 give you more warnings.
524 The idea is that you can extend this
525 <code class="filename">configure.in</code> and <code class="filename">Makefile.in</code> scripts
528 Compiling & 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="id2526400"></a>Some Notes</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2526406"></a>Implement TRANSPARENT functions</h3></div></div></div><p>
531 Avoid writing functions like this:
533 </p><pre class="programlisting">
534 static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
536 return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
540 Overload 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="id2526426"></a>Implement OPAQUE functions</h3></div></div></div><p>
542 If you want to just implement a better version of a
543 default samba opaque function
544 (e.g. like a disk_free() function for a special filesystem)
545 it's ok to just overload that specific function.
547 If you want to implement a database filesystem or
548 something different from a posix filesystem.
549 Make sure that you overload every vfs operation!!!
551 Functions your FS does not support should be overloaded by something like this:
552 e.g. for a readonly filesystem.
553 </p><pre class="programlisting">
554 static int example_rename(vfs_handle_struct *handle, connection_struct *conn,
555 char *oldname, char *newname)
557 DEBUG(10,("function rename() not allowed on vfs 'example'\n"));
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>