Initial import
[samba] / docs / htmldocs / Samba3-Developers-Guide / vfs.html
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">&lt;<a href="mailto:ab@samba.org">ab@samba.org</a>&gt;</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">&lt;<a href="mailto:metze@samba.org">metze@samba.org</a>&gt;</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 {
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">
25 struct 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>
67 This macros SHOULD be used to call any vfs operation.
68 DO NOT ACCESS conn-&gt;vfs.ops.* directly !!!
69 </p><pre class="programlisting">
70 ...
71         
72 /* File operations */
73 #define SMB_VFS_OPEN(conn, fname, flags, mode) \
74         ((conn)-&gt;vfs.ops.open((conn)-&gt;vfs.handles.open,\
75          (conn), (fname), (flags), (mode)))
76 #define SMB_VFS_CLOSE(fsp, fd) \
77         ((fsp)-&gt;conn-&gt;vfs.ops.close(\
78         (fsp)-&gt;conn-&gt;vfs.handles.close, (fsp), (fd)))
79 #define SMB_VFS_READ(fsp, fd, data, n) \
80         ((fsp)-&gt;conn-&gt;vfs.ops.read(\
81         (fsp)-&gt;conn-&gt;vfs.handles.read,\
82          (fsp), (fd), (data), (n)))
83 #define SMB_VFS_WRITE(fsp, fd, data, n) \
84         ((fsp)-&gt;conn-&gt;vfs.ops.write(\
85         (fsp)-&gt;conn-&gt;vfs.handles.write,\
86          (fsp), (fd), (data), (n)))
87 #define SMB_VFS_LSEEK(fsp, fd, offset, whence) \
88         ((fsp)-&gt;conn-&gt;vfs.ops.lseek(\
89         (fsp)-&gt;conn-&gt;vfs.handles.lseek,\
90          (fsp), (fd), (offset), (whence)))
91 #define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
92         ((fsp)-&gt;conn-&gt;vfs.ops.sendfile(\
93         (fsp)-&gt;conn-&gt;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="id2525419"></a>Possible VFS operation layers</h3></div></div></div><p>
98 These values are used by the VFS subsystem when building the conn-&gt;vfs 
99 and conn-&gt;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.
102 </p><p>
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.
106 </p><p>    
107 Other layer types (logger, splitter, scanner) were designed to provide different 
108 degree of transparency and for diagnosing VFS module behaviour.
109 </p><p>
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 */
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="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.
130 </p><p>
131 This should be the only non static function inside the module.
132 Global variables should also be static!
133 </p><p>
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);
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 <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 
144 vfs_op_tuple array.
145 </p><pre class="programlisting">
146 typedef 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">
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},
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
162 NTSTATUS 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="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;
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 <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-&gt;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-&gt;conn-&gt;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-&gt;conn-&gt;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)-&gt;data)==NULL)) { \
186                 DEBUG(0,("%s() failed to get vfs_handle-&gt;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-&gt;data!\n",FUNCTION_MACRO)); \
194                 ret; \
195         } else { \
196                 if ((handle)-&gt;free_data) { \
197                         (handle)-&gt;free_data(&amp;(handle)-&gt;data); \
198                 } \
199                 (handle)-&gt;data = (void *)datap; \
200                 (handle)-&gt;free_data = free_fn; \
201         } \
202 }
203
204 #define SMB_VFS_HANDLE_FREE_DATA(handle) { \
205         if ((handle) &amp;&amp; (handle)-&gt;free_data) { \
206                 (handle)-&gt;free_data(&amp;(handle)-&gt;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)-&gt;vfs_opaque.ops.open(\
215         (conn)-&gt;vfs_opaque.handles.open,\
216          (conn), (fname), (flags), (mode)))
217 #define SMB_VFS_OPAQUE_CLOSE(fsp, fd) \
218         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.close(\
219         (fsp)-&gt;conn-&gt;vfs_opaque.handles.close,\
220          (fsp), (fd)))
221 #define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) \
222         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.read(\
223         (fsp)-&gt;conn-&gt;vfs_opaque.handles.read,\
224          (fsp), (fd), (data), (n)))
225 #define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) \
226         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.write(\
227         (fsp)-&gt;conn-&gt;vfs_opaque.handles.write,\
228          (fsp), (fd), (data), (n)))
229 #define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) \
230         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.lseek(\
231         (fsp)-&gt;conn-&gt;vfs_opaque.handles.lseek,\
232          (fsp), (fd), (offset), (whence)))
233 #define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
234         ((fsp)-&gt;conn-&gt;vfs_opaque.ops.sendfile(\
235         (fsp)-&gt;conn-&gt;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)-&gt;vfs_next.ops.open(\
244         (handle)-&gt;vfs_next.handles.open,\
245          (conn), (fname), (flags), (mode)))
246 #define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) \
247         ((handle)-&gt;vfs_next.ops.close(\
248         (handle)-&gt;vfs_next.handles.close,\
249          (fsp), (fd)))
250 #define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) \
251         ((handle)-&gt;vfs_next.ops.read(\
252         (handle)-&gt;vfs_next.handles.read,\
253          (fsp), (fd), (data), (n)))
254 #define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) \
255         ((handle)-&gt;vfs_next.ops.write(\
256         (handle)-&gt;vfs_next.handles.write,\
257          (fsp), (fd), (data), (n)))
258 #define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) \
259         ((handle)-&gt;vfs_next.ops.lseek(\
260         (handle)-&gt;vfs_next.handles.lseek,\
261          (fsp), (fd), (offset), (whence)))
262 #define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) \
263         ((handle)-&gt;vfs_next.ops.sendfile(\
264         (handle)-&gt;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="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 -&gt;   example_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user);
271 </p></li><li><p>
272 Replace "default_vfs_ops." with "smb_vfs_next_".
273 e.g. default_vfs_ops.connect(conn, service, user);
274 -&gt;   smb_vfs_next_connect(conn, service, user);
275 </p></li><li><p>
276 Uppercase all "smb_vfs_next_*" functions.
277 e.g. smb_vfs_next_connect(conn, service, user);
278 -&gt;   SMB_VFS_NEXT_CONNECT(conn, service, user);
279 </p></li><li><p>
280 Add "handle, " as first parameter to all SMB_VFS_NEXT_*() calls.
281 e.g. SMB_VFS_NEXT_CONNECT(conn, service, user);
282 -&gt;   SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
283 </p></li><li><p>
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.
287 e.g.
288 </p><pre class="programlisting">
289 struct 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 -&gt;
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},
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>
373 Move the example_op_tuples[] array to the end of the file. 
374 </p></li><li><p>
375 Add the init_module() function at the end of the file.
376 e.g.
377 </p><pre class="programlisting">
378 NTSTATUS 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>
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>
388 </p></li><li><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>
393 </p></li><li><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-&gt;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">    
400 struct example_privates {
401         char *some_string;
402         int db_connection;
403 };
404 </pre><p>       
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, 
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-&gt;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-&gt;some_string = talloc_strdup(conn-&gt;mem_ctx,"test");
422         if (!data-&gt;some_string) {
423                 DEBUG(0,("talloc_strdup() failed\n"));
424                 return -1;
425         }
426
427         data-&gt;db_connection = open_db_conn();
428
429         /* and now store the private data pointer in handle-&gt;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
439 static 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-&gt;some_string));
450         
451         return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
452 }
453 </pre><p>
454 second way of doing it:
455 </p><pre class="programlisting">
456 static void free_example_privates(void **datap)
457 {
458         struct example_privates *data = (struct example_privates *)*datap;
459         
460         SAFE_FREE(data-&gt;some_string);
461         SAFE_FREE(data);
462         
463         *datap = NULL;
464         
465         return;
466 }
467
468 static 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-&gt;some_string = strdup("test");
483         if (!data-&gt;some_string) {
484                 DEBUG(0,("strdup() failed\n"));
485                 return -1;
486         }
487
488         data-&gt;db_connection = open_db_conn();
489
490         /* and now store the private data pointer in handle-&gt;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
499 static 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-&gt;some_string));
510         
511         return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
512 }
513 </pre><p>
514 </p></li><li><p>
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>.)
518 </p><p>
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.  
523 </p><p>
524 The idea is that you can extend this 
525 <code class="filename">configure.in</code> and <code class="filename">Makefile.in</code> scripts
526 for your module.
527 </p></li><li><p>
528 Compiling &amp; 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:
532
533 </p><pre class="programlisting">
534 static 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
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.
546 </p><p>
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!!!
550 </p><p>
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)
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>