Add small preface to a VFS guide. More to come.
[import/samba-docs-svnimport.git] / Samba3-Developers-Guide / vfs.xml
1 <?xml version="1.0" encoding="iso-8859-1"?>
2 <!DOCTYPE chapter PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
3 <chapter id="vfs">
4 <chapterinfo>
5         <author>
6                 <firstname>Alexander</firstname><surname>Bokovoy</surname>
7                 <affiliation>
8                         <address><email>ab@samba.org</email></address>
9                 </affiliation>
10         </author>
11         <author>
12                 <firstname>Stefan</firstname><surname>Metzmacher</surname>
13                 <affiliation>
14                         <address><email>metze@samba.org</email></address>
15                 </affiliation>
16         </author>
17         <pubdate> 27 May 2003 </pubdate>
18 </chapterinfo>
19
20 <title>VFS Modules</title>
21
22 <sect1>
23 <title>The Samba (Posix) VFS layer</title>
24
25 <para>While most of Samba deployments are done using POSIX-compatible operating systems,
26 there is clearly more to a file system than what is required by POSIX when it comes to
27 adopting semantics of NT file system. Since Samba 2.2 all file-system related operations
28 go through an abstraction layer for virtual file system (VFS) that is modelled after
29 both POSIX and additional functions needed to transform NTFS semantics.
30 </para>
31
32 <para>
33 This abstraction layer now provides more features than a regular POSIX file system could
34 fill in. It is not required that all of them should be implemented by your
35 particular file system.  However, when those features are available, Samba would advertize them to a
36 CIFS client and they might be used by an application and in case of Windows client that
37 might mean a client expects even more additional functionality when it encounters
38 those features. There is a practical reason to allow handling of this snowfall without modifying
39 the Samba core and it is fulfilled by providing an infrastructure to dynamically load
40 VFS modules at run time.
41 </para>
42
43 <para>Each VFS module could implement a number of VFS operations. The way it does it is
44 irrelevant, only two things actually matter: whether specific implementation wants to cooperate
45 with other modules' implementations or not, and whether module needs to store additional
46 information that is specific to a context it is operating in. Multiple VFS modules could
47 be loaded at the same time and it is even possible to load several instances of the same
48 VFS module with different parameters.
49 </para>
50
51 <sect2>
52 <title>The general interface</title>
53
54 <para>
55 Each VFS operation has a vfs_op_type, a function pointer and a handle pointer in the
56 struct vfs_ops and tree macros to make it easier to call the operations.
57 (Take a look at <filename>include/vfs.h</filename> and <filename>include/vfs_macros.h</filename>.)
58 </para>
59
60 <para><programlisting>
61 typedef enum _vfs_op_type {
62         SMB_VFS_OP_NOOP = -1,
63
64         ...
65
66         /* File operations */
67
68         SMB_VFS_OP_OPEN,
69         SMB_VFS_OP_CLOSE,
70         SMB_VFS_OP_READ,
71         SMB_VFS_OP_WRITE,
72         SMB_VFS_OP_LSEEK,
73         SMB_VFS_OP_SENDFILE,
74
75         ...
76
77         SMB_VFS_OP_LAST
78 } vfs_op_type;
79 </programlisting></para>
80
81 <para>This struct contains the function and handle pointers for all operations.<programlisting>
82 struct vfs_ops {
83         struct vfs_fn_pointers {
84                 ...
85                 
86                 /* File operations */
87                 
88                 int (*open)(struct vfs_handle_struct *handle,
89                         struct connection_struct *conn,
90                         const char *fname, int flags, mode_t mode);
91                 int (*close)(struct vfs_handle_struct *handle,
92                         struct files_struct *fsp, int fd);
93                 ssize_t (*read)(struct vfs_handle_struct *handle, 
94                         struct files_struct *fsp, int fd, void *data, size_t n);
95                 ssize_t (*write)(struct vfs_handle_struct *handle, 
96                         struct files_struct *fsp, int fd, 
97                         const void *data, size_t n);
98                 SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, 
99                         struct files_struct *fsp, int fd, 
100                         SMB_OFF_T offset, int whence);
101                 ssize_t (*sendfile)(struct vfs_handle_struct *handle, 
102                         int tofd, files_struct *fsp, int fromfd, 
103                         const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
104
105                 ...
106         } ops;
107         
108         struct vfs_handles_pointers {
109                 ...
110                 
111                 /* File operations */
112                 
113                 struct vfs_handle_struct *open;
114                 struct vfs_handle_struct *close;
115                 struct vfs_handle_struct *read;
116                 struct vfs_handle_struct *write;
117                 struct vfs_handle_struct *lseek;
118                 struct vfs_handle_struct *sendfile;
119                 
120                 ...
121         } handles;
122 };
123 </programlisting></para>
124
125 <para>
126 This macros SHOULD be used to call any vfs operation.
127 DO NOT ACCESS conn-&gt;vfs.ops.* directly !!!
128 <programlisting>
129 ...
130         
131 /* File operations */
132 #define SMB_VFS_OPEN(conn, fname, flags, mode) \
133         ((conn)-&gt;vfs.ops.open((conn)-&gt;vfs.handles.open,\
134          (conn), (fname), (flags), (mode)))
135 #define SMB_VFS_CLOSE(fsp, fd) \
136         ((fsp)-&gt;conn-&gt;vfs.ops.close(\
137         (fsp)-&gt;conn-&gt;vfs.handles.close, (fsp), (fd)))
138 #define SMB_VFS_READ(fsp, fd, data, n) \
139         ((fsp)-&gt;conn-&gt;vfs.ops.read(\
140         (fsp)-&gt;conn-&gt;vfs.handles.read,\
141          (fsp), (fd), (data), (n)))
142 #define SMB_VFS_WRITE(fsp, fd, data, n) \
143         ((fsp)-&gt;conn-&gt;vfs.ops.write(\
144         (fsp)-&gt;conn-&gt;vfs.handles.write,\
145          (fsp), (fd), (data), (n)))
146 #define SMB_VFS_LSEEK(fsp, fd, offset, whence) \
147         ((fsp)-&gt;conn-&gt;vfs.ops.lseek(\
148         (fsp)-&gt;conn-&gt;vfs.handles.lseek,\
149          (fsp), (fd), (offset), (whence)))
150 #define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
151         ((fsp)-&gt;conn-&gt;vfs.ops.sendfile(\
152         (fsp)-&gt;conn-&gt;vfs.handles.sendfile,\
153          (tofd), (fsp), (fromfd), (header), (offset), (count)))
154
155 ...
156 </programlisting></para>
157
158 </sect2>
159
160 <sect2>
161 <title>Possible VFS operation layers</title>
162
163 <para>
164 These values are used by the VFS subsystem when building the conn-&gt;vfs 
165 and conn-&gt;vfs_opaque structs for a connection with multiple VFS modules. 
166 Internally, Samba differentiates only opaque and transparent layers at this process.
167 Other types are used for providing better diagnosing facilities.
168 </para>
169
170 <para>
171 Most modules will provide transparent layers. Opaque layer is for modules
172 which implement actual file system calls (like DB-based VFS). For example,
173 default POSIX VFS which is built in into Samba is an opaque VFS module.
174 </para>
175
176 <para>    
177 Other layer types (logger, splitter, scanner) were designed to provide different 
178 degree of transparency and for diagnosing VFS module behaviour.
179 </para>
180
181 <para>
182 Each module can implement several layers at the same time provided that only
183 one layer is used per each operation.
184 </para>
185
186 <para><programlisting>
187 typedef enum _vfs_op_layer {
188         SMB_VFS_LAYER_NOOP = -1,        /* - For using in VFS module to indicate end of array */
189                                         /*   of operations description */
190         SMB_VFS_LAYER_OPAQUE = 0,       /* - Final level, does not call anything beyond itself */
191         SMB_VFS_LAYER_TRANSPARENT,      /* - Normal operation, calls underlying layer after */
192                                         /*   possibly changing passed data */
193         SMB_VFS_LAYER_LOGGER,           /* - Logs data, calls underlying layer, logging may not */
194                                         /*   use Samba VFS */
195         SMB_VFS_LAYER_SPLITTER,         /* - Splits operation, calls underlying layer _and_ own facility, */
196                                         /*   then combines result */
197         SMB_VFS_LAYER_SCANNER           /* - Checks data and possibly initiates additional */
198                                         /*   file activity like logging to files _inside_ samba VFS */
199 } vfs_op_layer;
200 </programlisting></para>
201
202 </sect2>
203
204 </sect1>
205
206 <sect1>
207 <title>The Interaction between the Samba VFS subsystem and the modules</title>
208
209 <sect2>
210 <title>Initialization and registration</title>
211
212 <para>
213 As each Samba module a VFS module should have a 
214 <programlisting>NTSTATUS vfs_example_init(void);</programlisting> function if it's staticly linked to samba or
215 <programlisting>NTSTATUS init_module(void);</programlisting> function if it's a shared module.
216 </para>
217
218 <para>
219 This should be the only non static function inside the module.
220 Global variables should also be static!
221 </para>
222
223 <para>
224 The module should register its functions via the
225 <programlisting>
226 NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples);
227 </programlisting> function.
228 </para>
229
230 <variablelist>
231
232 <varlistentry><term>version</term>
233 <listitem><para>should be filled with SMB_VFS_INTERFACE_VERSION</para></listitem>
234 </varlistentry>
235
236 <varlistentry><term>name</term>
237 <listitem><para>this is the name witch can be listed in the 
238 <command>vfs objects</command> parameter to use this module.</para></listitem>
239 </varlistentry>
240
241 <varlistentry><term>vfs_op_tuples</term>
242 <listitem><para>
243 this is an array of vfs_op_tuple's.
244 (vfs_op_tuples is descripted in details below.)
245 </para></listitem>
246 </varlistentry>
247
248 </variablelist>
249
250 <para>
251 For each operation the module wants to provide it has a entry in the 
252 vfs_op_tuple array.
253 </para>
254
255 <programlisting>
256 typedef struct _vfs_op_tuple {
257         void* op;
258         vfs_op_type type;
259         vfs_op_layer layer;
260 } vfs_op_tuple;
261 </programlisting>
262
263 <variablelist>
264
265 <varlistentry><term>op</term>
266 <listitem><para>the function pointer to the specified function.</para></listitem>
267 </varlistentry>
268
269 <varlistentry><term>type</term>
270 <listitem><para>the vfs_op_type of the function to specified witch operation the function provides.</para></listitem>
271 </varlistentry>
272
273 <varlistentry><term>layer</term>
274 <listitem><para>the vfs_op_layer in whitch the function operates.</para></listitem>
275 </varlistentry>
276
277 </variablelist>
278
279 <para>A simple example:</para>
280
281 <programlisting>
282 static vfs_op_tuple example_op_tuples[] = {     
283         {SMB_VFS_OP(example_connect),   SMB_VFS_OP_CONNECT,     SMB_VFS_LAYER_TRANSPARENT},
284         {SMB_VFS_OP(example_disconnect),        SMB_VFS_OP_DISCONNECT,  SMB_VFS_LAYER_TRANSPARENT},
285
286         {SMB_VFS_OP(example_rename),    SMB_VFS_OP_RENAME,      SMB_VFS_LAYER_OPAQUE},
287
288         /* This indicates the end of the array */
289         {SMB_VFS_OP(NULL),                              SMB_VFS_OP_NOOP,        SMB_VFS_LAYER_NOOP}
290 };
291
292 NTSTATUS init_module(void)
293 {
294         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, &quot;example&quot;, example_op_tuples);
295 }
296 </programlisting>
297
298 </sect2>
299
300 <sect2>
301 <title>How the Modules handle per connection data</title>
302
303 <para>Each VFS function has as first parameter a pointer to the modules vfs_handle_struct.
304 </para>
305
306 <programlisting>
307 typedef struct vfs_handle_struct {
308         struct vfs_handle_struct  *next, *prev;
309         const char *param;
310         struct vfs_ops vfs_next;
311         struct connection_struct *conn;
312         void *data;
313         void (*free_data)(void **data);
314 } vfs_handle_struct;
315 </programlisting>
316
317 <variablelist>
318
319 <varlistentry><term>param</term>
320 <listitem><para>this is the module parameter specified in the <command>vfs objects</command> parameter.</para>
321 <para>e.g. for 'vfs objects = example:test' param would be &quot;test&quot;.</para></listitem>
322 </varlistentry>
323
324 <varlistentry><term>vfs_next</term>
325 <listitem><para>This vfs_ops struct contains the information for calling the next module operations.
326 Use the SMB_VFS_NEXT_* macros to call a next module operations and
327 don't access handle-&gt;vfs_next.ops.* directly!</para></listitem>
328 </varlistentry>
329
330 <varlistentry><term>conn</term>
331 <listitem><para>This is a pointer back to the connection_struct to witch the handle belongs.</para></listitem>
332 </varlistentry>
333
334 <varlistentry><term>data</term>
335 <listitem><para>This is a pointer for holding module private data.
336 You can alloc data with connection life time on the handle-&gt;conn-&gt;mem_ctx TALLOC_CTX.
337 But you can also manage the memory allocation yourself.</para></listitem>
338 </varlistentry>
339
340 <varlistentry><term>free_data</term>
341 <listitem><para>This is a function pointer to a function that free's the module private data.
342 If you talloc your private data on the TALLOC_CTX handle-&gt;conn-&gt;mem_ctx,
343 you can set this function pointer to NULL.</para></listitem>
344 </varlistentry>
345
346 </variablelist>
347
348 <para>Some useful MACROS for handle private data.
349 </para>
350
351 <programlisting>
352 #define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \
353         if (!(handle)||((datap=(type *)(handle)-&gt;data)==NULL)) { \
354                 DEBUG(0,(&quot;%s() failed to get vfs_handle-&gt;data!\n&quot;,FUNCTION_MACRO)); \
355                 ret; \
356         } \
357 }
358
359 #define SMB_VFS_HANDLE_SET_DATA(handle, datap, free_fn, type, ret) { \
360         if (!(handle)) { \
361                 DEBUG(0,(&quot;%s() failed to set handle-&gt;data!\n&quot;,FUNCTION_MACRO)); \
362                 ret; \
363         } else { \
364                 if ((handle)-&gt;free_data) { \
365                         (handle)-&gt;free_data(&amp;(handle)-&gt;data); \
366                 } \
367                 (handle)-&gt;data = (void *)datap; \
368                 (handle)-&gt;free_data = free_fn; \
369         } \
370 }
371
372 #define SMB_VFS_HANDLE_FREE_DATA(handle) { \
373         if ((handle) &amp;&amp; (handle)-&gt;free_data) { \
374                 (handle)-&gt;free_data(&amp;(handle)-&gt;data); \
375         } \
376 }
377 </programlisting>
378
379 <para>How SMB_VFS_LAYER_TRANSPARENT functions can call the SMB_VFS_LAYER_OPAQUE functions.</para>
380
381 <para>The easiest way to do this is to use the SMB_VFS_OPAQUE_* macros.
382 </para>
383
384 <programlisting>
385 ...
386 /* File operations */
387 #define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) \
388         ((conn)-&gt;vfs_opaque.ops.open(\
389         (conn)-&gt;vfs_opaque.handles.open,\
390          (conn), (fname), (flags), (mode)))
391 #define SMB_VFS_OPAQUE_CLOSE(fsp, fd) \
392         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.close(\
393         (fsp)-&gt;conn-&gt;vfs_opaque.handles.close,\
394          (fsp), (fd)))
395 #define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) \
396         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.read(\
397         (fsp)-&gt;conn-&gt;vfs_opaque.handles.read,\
398          (fsp), (fd), (data), (n)))
399 #define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) \
400         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.write(\
401         (fsp)-&gt;conn-&gt;vfs_opaque.handles.write,\
402          (fsp), (fd), (data), (n)))
403 #define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) \
404         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.lseek(\
405         (fsp)-&gt;conn-&gt;vfs_opaque.handles.lseek,\
406          (fsp), (fd), (offset), (whence)))
407 #define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
408         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.sendfile(\
409         (fsp)-&gt;conn-&gt;vfs_opaque.handles.sendfile,\
410          (tofd), (fsp), (fromfd), (header), (offset), (count)))
411 ...
412 </programlisting>
413
414 <para>How SMB_VFS_LAYER_TRANSPARENT functions can call the next modules functions.</para>
415
416 <para>The easiest way to do this is to use the SMB_VFS_NEXT_* macros.
417 </para>
418
419 <programlisting>
420 ...
421 /* File operations */
422 #define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) \
423         ((handle)-&gt;vfs_next.ops.open(\
424         (handle)-&gt;vfs_next.handles.open,\
425          (conn), (fname), (flags), (mode)))
426 #define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) \
427         ((handle)-&gt;vfs_next.ops.close(\
428         (handle)-&gt;vfs_next.handles.close,\
429          (fsp), (fd)))
430 #define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) \
431         ((handle)-&gt;vfs_next.ops.read(\
432         (handle)-&gt;vfs_next.handles.read,\
433          (fsp), (fd), (data), (n)))
434 #define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) \
435         ((handle)-&gt;vfs_next.ops.write(\
436         (handle)-&gt;vfs_next.handles.write,\
437          (fsp), (fd), (data), (n)))
438 #define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) \
439         ((handle)-&gt;vfs_next.ops.lseek(\
440         (handle)-&gt;vfs_next.handles.lseek,\
441          (fsp), (fd), (offset), (whence)))
442 #define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) \
443         ((handle)-&gt;vfs_next.ops.sendfile(\
444         (handle)-&gt;vfs_next.handles.sendfile,\
445          (tofd), (fsp), (fromfd), (header), (offset), (count)))
446 ...
447 </programlisting>
448
449 </sect2>
450
451 </sect1>
452
453 <sect1>
454 <title>Upgrading to the New VFS Interface</title>
455
456 <sect2>
457 <title>Upgrading from 2.2.* and 3.0aplha modules</title>
458
459 <orderedlist>
460 <listitem><para>
461 Add &quot;vfs_handle_struct *handle, &quot; as first parameter to all vfs operation functions.
462 e.g. example_connect(connection_struct *conn, const char *service, const char *user);
463 -&gt;   example_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user);
464 </para></listitem>
465
466 <listitem><para>
467 Replace &quot;default_vfs_ops.&quot; with &quot;smb_vfs_next_&quot;.
468 e.g. default_vfs_ops.connect(conn, service, user);
469 -&gt;   smb_vfs_next_connect(conn, service, user);
470 </para></listitem>
471
472 <listitem><para>
473 Uppercase all &quot;smb_vfs_next_*&quot; functions.
474 e.g. smb_vfs_next_connect(conn, service, user);
475 -&gt;   SMB_VFS_NEXT_CONNECT(conn, service, user);
476 </para></listitem>
477
478 <listitem><para>
479 Add &quot;handle, &quot; as first parameter to all SMB_VFS_NEXT_*() calls.
480 e.g. SMB_VFS_NEXT_CONNECT(conn, service, user);
481 -&gt;   SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
482 </para></listitem>
483
484 <listitem><para>
485 (Only for 2.2.* modules) 
486 Convert the old struct vfs_ops example_ops to 
487 a vfs_op_tuple example_op_tuples[] array.
488 e.g.
489 <programlisting>
490 struct vfs_ops example_ops = {
491         /* Disk operations */
492         example_connect,                /* connect */
493         example_disconnect,             /* disconnect */
494         NULL,                           /* disk free *
495         /* Directory operations */
496         NULL,                           /* opendir */
497         NULL,                           /* readdir */
498         NULL,                           /* mkdir */
499         NULL,                           /* rmdir */
500         NULL,                           /* closedir */
501         /* File operations */
502         NULL,                           /* open */
503         NULL,                           /* close */
504         NULL,                           /* read  */
505         NULL,                           /* write */
506         NULL,                           /* lseek */
507         NULL,                           /* sendfile */
508         NULL,                           /* rename */
509         NULL,                           /* fsync */
510         example_stat,                   /* stat  */
511         example_fstat,                  /* fstat */
512         example_lstat,                  /* lstat */
513         NULL,                           /* unlink */
514         NULL,                           /* chmod */
515         NULL,                           /* fchmod */
516         NULL,                           /* chown */
517         NULL,                           /* fchown */
518         NULL,                           /* chdir */
519         NULL,                           /* getwd */
520         NULL,                           /* utime */
521         NULL,                           /* ftruncate */
522         NULL,                           /* lock */
523         NULL,                           /* symlink */
524         NULL,                           /* readlink */
525         NULL,                           /* link */
526         NULL,                           /* mknod */
527         NULL,                           /* realpath */
528         NULL,                           /* fget_nt_acl */
529         NULL,                           /* get_nt_acl */
530         NULL,                           /* fset_nt_acl */
531         NULL,                           /* set_nt_acl */
532
533         NULL,                           /* chmod_acl */
534         NULL,                           /* fchmod_acl */
535
536         NULL,                           /* sys_acl_get_entry */
537         NULL,                           /* sys_acl_get_tag_type */
538         NULL,                           /* sys_acl_get_permset */
539         NULL,                           /* sys_acl_get_qualifier */
540         NULL,                           /* sys_acl_get_file */
541         NULL,                           /* sys_acl_get_fd */
542         NULL,                           /* sys_acl_clear_perms */
543         NULL,                           /* sys_acl_add_perm */
544         NULL,                           /* sys_acl_to_text */
545         NULL,                           /* sys_acl_init */
546         NULL,                           /* sys_acl_create_entry */
547         NULL,                           /* sys_acl_set_tag_type */
548         NULL,                           /* sys_acl_set_qualifier */
549         NULL,                           /* sys_acl_set_permset */
550         NULL,                           /* sys_acl_valid */
551         NULL,                           /* sys_acl_set_file */
552         NULL,                           /* sys_acl_set_fd */
553         NULL,                           /* sys_acl_delete_def_file */
554         NULL,                           /* sys_acl_get_perm */
555         NULL,                           /* sys_acl_free_text */
556         NULL,                           /* sys_acl_free_acl */
557         NULL                            /* sys_acl_free_qualifier */
558 };
559 </programlisting>
560 -&gt;
561 <programlisting> 
562 static vfs_op_tuple example_op_tuples[] = {
563         {SMB_VFS_OP(example_connect),   SMB_VFS_OP_CONNECT,     SMB_VFS_LAYER_TRANSPARENT},
564         {SMB_VFS_OP(example_disconnect),        SMB_VFS_OP_DISCONNECT,  SMB_VFS_LAYER_TRANSPARENT},
565         
566         {SMB_VFS_OP(example_fstat),     SMB_VFS_OP_FSTAT,       SMB_VFS_LAYER_TRANSPARENT},
567         {SMB_VFS_OP(example_stat),              SMB_VFS_OP_STAT,        SMB_VFS_LAYER_TRANSPARENT},
568         {SMB_VFS_OP(example_lstat),     SMB_VFS_OP_LSTAT,       SMB_VFS_LAYER_TRANSPARENT},
569
570         {SMB_VFS_OP(NULL),                              SMB_VFS_OP_NOOP,        SMB_VFS_LAYER_NOOP}
571 };
572 </programlisting>
573 </para></listitem>
574
575 <listitem><para>
576 Move the example_op_tuples[] array to the end of the file. 
577 </para></listitem>
578
579 <listitem><para>
580 Add the init_module() function at the end of the file.
581 e.g.
582 <programlisting>
583 NTSTATUS init_module(void)
584 {
585         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,&quot;example&quot;,example_op_tuples);
586 }
587 </programlisting>
588 </para></listitem>
589
590 <listitem><para>
591 Check if your vfs_init() function does more then just prepare the vfs_ops structs or
592 remember the struct smb_vfs_handle_struct.
593 <simplelist>
594 <member>If NOT you can remove the vfs_init() function.</member>
595 <member>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().
596   e.g. a debug class registration should go into init_module() and the allocation of private data should go to example_connect().</member>
597 </simplelist>
598 </para></listitem>
599
600 <listitem><para>
601 (Only for 3.0alpha* modules) 
602 Check if your vfs_done() function contains needed code.
603 <simplelist>
604 <member>If NOT you can remove the vfs_done() function.</member>
605 <member>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 <link linkend="modules">modules section</link>) And then remove vfs_done(). e.g. the freeing of private data should go to example_disconnect().
606 </member>
607 </simplelist>
608 </para></listitem>
609
610 <listitem><para>
611 Check if you have any global variables left.
612 Decide if it wouldn't be better to have this data on a connection basis.
613 <simplelist>
614   <member>If NOT leave them as they are. (e.g. this could be the variable for the private debug class.)</member>
615   <member>If YES pack all this data into a struct. You can use handle-&gt;data to point to such a struct on a per connection basis.</member>
616 </simplelist>
617
618   e.g. if you have such a struct:
619 <programlisting>    
620 struct example_privates {
621         char *some_string;
622         int db_connection;
623 };
624 </programlisting>       
625 first way of doing it:
626 <programlisting>
627 static int example_connect(vfs_handle_struct *handle,
628         connection_struct *conn, const char *service, 
629         const char* user)
630 {
631         struct example_privates *data = NULL;
632
633         /* alloc our private data */
634         data = (struct example_privates *)talloc_zero(conn-&gt;mem_ctx, sizeof(struct example_privates));
635         if (!data) {
636                 DEBUG(0,(&quot;talloc_zero() failed\n&quot;));
637                 return -1;
638         }
639
640         /* init out private data */
641         data-&gt;some_string = talloc_strdup(conn-&gt;mem_ctx,&quot;test&quot;);
642         if (!data-&gt;some_string) {
643                 DEBUG(0,(&quot;talloc_strdup() failed\n&quot;));
644                 return -1;
645         }
646
647         data-&gt;db_connection = open_db_conn();
648
649         /* and now store the private data pointer in handle-&gt;data
650          * we don't need to specify a free_function here because
651          * we use the connection TALLOC context.
652          * (return -1 if something failed.)
653          */
654         VFS_HANDLE_SET_DATA(handle, data, NULL, struct example_privates, return -1);
655
656         return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
657 }
658
659 static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
660 {
661         struct example_privates *data = NULL;
662         
663         /* get the pointer to our private data
664          * return -1 if something failed
665          */
666         SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1);
667         
668         /* do something here...*/
669         DEBUG(0,(&quot;some_string: %s\n&quot;,data-&gt;some_string));
670         
671         return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
672 }
673 </programlisting>
674 second way of doing it:
675 <programlisting>
676 static void free_example_privates(void **datap)
677 {
678         struct example_privates *data = (struct example_privates *)*datap;
679         
680         SAFE_FREE(data-&gt;some_string);
681         SAFE_FREE(data);
682         
683         *datap = NULL;
684         
685         return;
686 }
687
688 static int example_connect(vfs_handle_struct *handle, 
689         connection_struct *conn, const char *service, 
690         const char* user)
691 {
692         struct example_privates *data = NULL;
693
694         /* alloc our private data */
695         data = (struct example_privates *)malloc(sizeof(struct example_privates));
696         if (!data) {
697                 DEBUG(0,(&quot;malloc() failed\n&quot;));
698                 return -1;
699         }
700
701         /* init out private data */
702         data-&gt;some_string = strdup(&quot;test&quot;);
703         if (!data-&gt;some_string) {
704                 DEBUG(0,(&quot;strdup() failed\n&quot;));
705                 return -1;
706         }
707
708         data-&gt;db_connection = open_db_conn();
709
710         /* and now store the private data pointer in handle-&gt;data
711          * we need to specify a free_function because we used malloc() and strdup().
712          * (return -1 if something failed.)
713          */
714         SMB_VFS_HANDLE_SET_DATA(handle, data, free_example_privates, struct example_privates, return -1);
715
716         return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
717 }
718
719 static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
720 {
721         struct example_privates *data = NULL;
722         
723         /* get the pointer to our private data
724          * return -1 if something failed
725          */
726         SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1);
727         
728         /* do something here...*/
729         DEBUG(0,(&quot;some_string: %s\n&quot;,data-&gt;some_string));
730         
731         return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
732 }
733 </programlisting>
734 </para></listitem>
735
736 <listitem><para>
737 To make it easy to build 3rd party modules it would be usefull to provide
738 configure.in, (configure), install.sh and Makefile.in with the module.
739 (Take a look at the example in <filename>examples/VFS</filename>.)
740 </para>
741
742 <para>
743 The configure script accepts <option>--with-samba-source</option> to specify 
744 the path to the samba source tree.
745 It also accept <option>--enable-developer</option> which lets the compiler 
746 give you more warnings.  
747 </para>
748
749 <para>
750 The idea is that you can extend this 
751 <filename>configure.in</filename> and <filename>Makefile.in</filename> scripts
752 for your module.
753 </para></listitem>
754
755 <listitem><para>
756 Compiling &amp; Testing...
757 <simplelist>
758 <member><userinput>./configure <option>--enable-developer</option></userinput> ...</member>
759 <member><userinput>make</userinput></member>
760 <member>Try to fix all compiler warnings</member>
761 <member><userinput>make</userinput></member>
762 <member>Testing, Testing, Testing ...</member>
763 </simplelist>
764 </para></listitem>
765 </orderedlist>
766 </sect2>
767
768 </sect1>
769
770 <sect1>
771 <title>Some Notes</title>
772
773 <sect2>
774 <title>Implement TRANSPARENT functions</title>
775
776 <para>
777 Avoid writing functions like this:
778
779 <programlisting>
780 static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
781 {
782         return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
783 }
784 </programlisting>
785
786 Overload only the functions you really need to!
787 </para>
788
789 </sect2>
790
791 <sect2>
792 <title>Implement OPAQUE functions</title>
793
794 <para>
795 If you want to just implement a better version of a 
796 default samba opaque function
797 (e.g. like a disk_free() function for a special filesystem) 
798 it's ok to just overload that specific function.
799 </para>
800
801 <para>
802 If you want to implement a database filesystem or
803 something different from a posix filesystem.
804 Make sure that you overload every vfs operation!!!
805 </para>
806 <para>
807 Functions your FS does not support should be overloaded by something like this:
808 e.g. for a readonly filesystem.
809 </para>
810
811 <programlisting>
812 static int example_rename(vfs_handle_struct *handle, connection_struct *conn,
813                         char *oldname, char *newname)
814 {
815         DEBUG(10,(&quot;function rename() not allowed on vfs 'example'\n&quot;));
816         errno = ENOSYS;
817         return -1;
818 }
819 </programlisting>
820
821 </sect2>
822
823 </sect1>
824
825 </chapter>