]> arthur.barton.de Git - netatalk.git/blob - contrib/patches/patch.vfs
call readt with ONE_DELAY = 5 s
[netatalk.git] / contrib / patches / patch.vfs
1 diff -Nur vfs/Makefile vfs.new/Makefile
2 --- vfs/Makefile        Thu Jan  1 00:00:00 1970
3 +++ vfs.new/Makefile    Mon Jul 12 10:48:56 2004
4 @@ -0,0 +1,40 @@
5 +##########################################################################
6 +# Makefile for Samba VFS modules 
7 +###########################################################################
8 +
9 +CC=gcc -g
10 +LIBTOOL=/usr/bin/libtool
11 +# REPLACE with samba source 
12 +SMB=/u/redhat/paris/cvs/samba/smb3.0a20
13 +
14 +# REPLACE with samba build folder
15 +BUILD=/mnt/hdd/build/smb.1.3
16 +
17 +CFLAGS=-Wall -I $(BUILD)/include \
18 +-I$(SMB)/source -I$(SMB)/source/include -I$(SMB)/source/ubiqx -I$(SMB)/source/smbwrapper
19 +
20 +
21 +LDFLAGS=-shared
22 +
23 +VFS_OBJS=vfs_ads.so
24 +
25 +SHELL=/bin/sh
26 +
27 +default: $(VFS_OBJS)
28 +
29 +# Pattern rules
30 +
31 +%.so: %.lo
32 +       @echo Linking $<
33 +       @$(LIBTOOL) --mode=link $(CC) -o $@ $< $(LDFLAGS)
34 +
35 +%.lo: %.c
36 +       @echo Compiling $<
37 +       @$(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
38 +
39 +# Misc targets
40 +
41 +clean:
42 +       rm -rf .libs */.libs
43 +       rm -f core *~ *% *.bak *.o */*.o *.lo $(VFS_OBJS)
44 +
45 diff -Nur vfs/README vfs.new/README
46 --- vfs/README  Thu Jan  1 00:00:00 1970
47 +++ vfs.new/README      Tue Jul 13 02:28:21 2004
48 @@ -0,0 +1,34 @@
49 +This a vfs for NT ADS 
50 +you must set SMB and BUILD variables in Makefile.
51 +
52 +old smb.conf
53 +[test_ads]
54 +   comment = test ADS Mac/PC directory
55 +   path=/home/test_ads/
56 +#  /.AppleD* is mandatory 
57 +   veto files = /.AppleD*/Network Trash Folder/Icon\r/
58 +   delete veto files = True
59 +# full path to vfs_ads.so 
60 +   vfs object = /usr/src/samba/vfs/vfs_ads.so
61 +   browseable = yes
62 +   writable = yes
63 +
64 +new one (current svn tree)
65 +copy vfs_ads.so as ads.so in <prefix>/lib/vfs/
66 +eg
67 +cp vfs_ads.so /opt/lib/vfs/ads.so
68 +
69 +smb.conf
70 +[test_ads]
71 +   comment = test ADS Mac/PC directory
72 +   path=/home/test_ads/
73
74 +#  /.AppleD* is mandatory 
75 +   veto files = /.AppleD*/Network Trash Folder/Icon\r/
76 +   delete veto files = True
77 +   vfs objects = ads
78 +   browseable = yes
79 +   writable = yes
80 +
81 +
82 +Didier
83 diff -Nur vfs/vfs_ads.c vfs.new/vfs_ads.c
84 --- vfs/vfs_ads.c       Thu Jan  1 00:00:00 1970
85 +++ vfs.new/vfs_ads.c   Wed Jul 14 16:37:15 2004
86 @@ -0,0 +1,1029 @@
87 +/* 
88 + * CAP VFS module for Samba 3.x Version 0.3
89 + *
90 + * Copyright (C) Tim Potter, 1999-2000
91 + * Copyright (C) Alexander Bokovoy, 2002-2003
92 + * Copyright (C) Stefan (metze) Metzmacher, 2003
93 + * Copyright (C) TAKAHASHI Motonobu (monyo), 2003
94 + *
95 + * This program is free software; you can redistribute it and/or modify
96 + * it under the terms of the GNU General Public License as published by
97 + * the Free Software Foundation; either version 2 of the License, or
98 + * (at your option) any later version.
99 + *  
100 + * This program is distributed in the hope that it will be useful,
101 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
102 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
103 + * GNU General Public License for more details.
104 + *  
105 + * You should have received a copy of the GNU General Public License
106 + * along with this program; if not, write to the Free Software
107 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
108 + *
109 + * modified for alternate data stream
110 + * Copyright (C) Didier Gautheron 2004
111 + * 
112 + * this module should compile with old 3.0 API and 2004-07 svn API
113 + */
114 +
115 +
116 +#include "includes.h"
117 +
118 +#undef DBGC_CLASS
119 +#define DBGC_CLASS DBGC_VFS
120 +
121 +#define ADS_FOLDER     ".AppleDouble"
122 +#define ADOUBLEMODE    0777
123 +
124 +/* FIXME found a better test */
125 +#ifdef         SMB_VFS_OP
126 +#define ADS_NEW_MODULE
127 +
128 +/* for current svn tree */
129 +#define ADS_TALLOC_INIT(a) talloc_init(a)
130 +
131 +#define HANDLE_PARAMETER vfs_handle_struct *handle,
132 +#define HANDLE handle,
133 +
134 +/* ------------------- */
135 +#else
136 +
137 +#define ADS_TALLOC_INIT(a) talloc_init()
138 +
139 +#define HANDLE_PARAMETER 
140 +#define HANDLE
141 +
142 +/* VFS operations */
143 +static struct vfs_ops default_vfs_ops;   /* For passthrough operation */
144 +static struct smb_vfs_handle_struct *ads_handle; 
145 +
146 +#define SMB_VFS_NEXT_DISK_FREE(a,b,c,d,e,f,g)       default_vfs_ops.disk_free(b,c,d,e,f,g)
147 +#define SMB_VFS_NEXT_OPENDIR(a,b,c)                 default_vfs_ops.opendir(b,c)
148 +#define SMB_VFS_NEXT_READDIR(a,b,c)                 default_vfs_ops.readdir(b,c)
149 +#define SMB_VFS_NEXT_MKDIR(a,b,c,d)                 default_vfs_ops.mkdir(b,c,d)
150 +#define SMB_VFS_NEXT_RMDIR(a,b,c)                   default_vfs_ops.rmdir(b,c)
151 +#define SMB_VFS_NEXT_OPEN(a,b,c,d,e)                default_vfs_ops.open(b,c,d,e)
152 +#define SMB_VFS_NEXT_RENAME(a,b,c,d)                default_vfs_ops.rename(b,c,d)
153 +#define SMB_VFS_NEXT_STAT(a,b,c,d)                  default_vfs_ops.stat(b,c,d)
154 +#define SMB_VFS_NEXT_LSTAT(a,b,c,d)                 default_vfs_ops.lstat(b,c,d)
155 +#define SMB_VFS_NEXT_UNLINK(a,b,c)                  default_vfs_ops.unlink(b,c)
156 +#define SMB_VFS_NEXT_CHMOD(a,b,c,d)                 default_vfs_ops.chmod(b,c,d)
157 +#define SMB_VFS_NEXT_CHOWN(a,b,c,d,e)               default_vfs_ops.chown(b,c,d,e) 
158 +#define SMB_VFS_NEXT_CHDIR(a,b,c)                   default_vfs_ops.chdir(b,c)
159 +#define SMB_VFS_NEXT_UTIME(a,b,c,d)                 default_vfs_ops.utime(b,c,d)
160 +#define SMB_VFS_NEXT_SYMLINK(a,b,c,d)               default_vfs_ops.symlink(b,c,d)
161 +#define SMB_VFS_NEXT_READLINK(a,b,c,d,e)            default_vfs_ops.readlink(b,c,d,e)
162 +#define SMB_VFS_NEXT_LINK(a,b,c,d)                  default_vfs_ops.link(b,c,d)
163 +#define SMB_VFS_NEXT_MKNOD(a,b,c,d,e)               default_vfs_ops.mknod(b,c,d,e)
164 +#define SMB_VFS_NEXT_REALPATH(a,b,c,d)              default_vfs_ops.realpath(b,c,d)
165 +#define SMB_VFS_NEXT_SET_NT_ACL(a,b,c,d,e)          default_vfs_ops.set_nt_acl(b,c,d,e)
166 +#define SMB_VFS_NEXT_CHMOD_ACL(a,b,c,d)             default_vfs_ops.chmod_acl(b,c,d)
167 +#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(a,b,c,d)      default_vfs_ops.sys_acl_get_file(b,c,d)
168 +#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(a,b,c,d,e)    default_vfs_ops.sys_acl_set_file(b,c,d,e)
169 +#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(a,b,c) default_vfs_ops.sys_acl_delete_def_file(b,c)
170 +/* ads functions */
171 +
172 +#endif
173 +
174 +/* ------------------------- 
175 + * format
176 + * .AppleDouble/filename/stream name
177 + * 
178 + * return the *LAST* '/' in path
179 + */
180 +static int ads_get_path_ptr(char *path)
181 +{
182 +       int i   = 0;
183 +       int ptr = 0;
184 +       
185 +       for (i = 0; path[i]; i ++) {
186 +               if (path[i] == '/')
187 +                       ptr = i;
188 +       }
189 +       
190 +       return ptr;
191 +}
192 +
193 +/* ------------------------------
194 + * return the *FIRST* ':' in path
195 +*/
196 +static int ads_get_stream_ptr(const char *path)
197 +{
198 +       int i   = 0;
199 +       int ptr = 0;
200 +       
201 +       for (i = 0; path[i]; i ++) {
202 +               if (path[i] == ':') {
203 +                       ptr = i;
204 +                       break;
205 +               }
206 +       }
207 +       return ptr;
208 +}
209 +
210 +/* ---------------- 
211 + * fname is only a filename
212 +*/
213 +
214 +static char *ads_canonical_dir(TALLOC_CTX *ctx, const char *path, const char *fname, int isdir)
215 +{
216 +    if (isdir) {
217 +        return talloc_asprintf(ctx, "%s/%s/%s/.Parent", path, fname, ADS_FOLDER);
218 +    }
219 +    return talloc_asprintf(ctx, "%s/%s/%s", path, ADS_FOLDER, fname);
220 +    
221 +}
222 +
223 +/* ---------------- 
224 + * return directory pathname for an alternate data stream
225 + * fname is *NOT* an altername name (ie foo:bar)
226 +*/
227 +static char *ads_dir(TALLOC_CTX *ctx, const char *path, const char *fname, int isdir)
228 +{
229 +    int ptr0 = 0;
230 +    int ptr1 = 0;
231 +    char *temp;
232 +
233 +#if 0
234 +    if (fname[0] == '.') ptr0 ++;
235 +    if (fname[1] == '/') ptr0 ++;
236 +#endif    
237 +    temp = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]);
238 +    ptr1 = ads_get_path_ptr(temp);
239 +    temp[ptr1] = '\0';
240 +    return ads_canonical_dir(ctx, temp, &temp[ptr1 + 1], isdir);
241 +}
242 +
243 +/* ----------------------------------
244 + * build the pathname for stream, create folder if (mode & O_CREAT)
245 + * return -1 on error
246 + * 0 it's not a stream
247 + * 1 it's a stream
248 + *
249 + * main_path : file fullpathname with :$DATA removed
250 + * ads_path: unix pathname 
251 + * if it's not an ADS then main_path == ads_path
252 + *
253 + */
254 +static int ads_build_paths(TALLOC_CTX *ctx, const char *path, const char *fname,
255 +                              char **ads_path, char **main_path, SMB_STRUCT_STAT **main_info, int flag)
256 +{
257 +        int ret = 0;
258 +       int ptr0 = 0;
259 +       int ptr1 = 0;
260 +       int ptr2 = 0;
261 +       int ptr3 = 0;
262 +       char *dname = 0;
263 +       char *name  = 0;
264 +       SMB_STRUCT_STAT ads_info;
265 +
266 +       if (!ctx || !path || !fname || !ads_path || !main_path || !main_info || !*main_info)
267 +               return -1;
268 +#if 1
269 +       DEBUG(3, ("ADS: PATH: %s[%s]\n", path, fname));
270 +#endif
271 +       if (strstr(path, ADS_FOLDER) || strstr(fname, ADS_FOLDER)) {
272 +               DEBUG(1, ("ADS: path %s[%s] already contains %s\n", path, fname, ADS_FOLDER));
273 +               return -1;
274 +       }
275 +
276 +#if 0
277 +       if (fname[0] == '.') ptr0 ++;
278 +       if (fname[1] == '/') ptr0 ++;
279 +#endif
280 +
281 +       *main_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]);
282 +       *ads_path = NULL;
283 +
284 +       /* get pointer to last '/' */
285 +       ptr1 = ads_get_path_ptr(*main_path);
286 +       ptr2 = ads_get_stream_ptr(*main_path +ptr1 +1);
287 +       /* FIXME
288 +        * what about ::$DATA or :name:$DATA
289 +       */
290 +
291 +       if (ptr2) {
292 +           /* it's an alternate stream */
293 +           ptr2 += ptr1 +1;
294 +           (*main_path)[ptr2] = 0;
295 +           ptr3 = ads_get_stream_ptr(*main_path +ptr2 +1);
296 +           if (ptr3) {
297 +               ptr3 += ptr2 +1;
298 +               /* check it's $DATA */
299 +               if (!strcmp("$DATA", &(*main_path)[ptr3+1])) {
300 +                   (*main_path)[ptr3] = 0;
301 +               }
302 +           }
303 +
304 +           DEBUG(3, ("ADS: MAIN DATA %s\n", *main_path));
305 +
306 +           if (sys_lstat(*main_path, *main_info) < 0) {
307 +               /* if we can't get the main file give up */
308 +               return -1;
309 +           }
310 +           (*main_path)[ptr2] = ':';
311 +           dname = talloc_strdup(ctx, *main_path);
312 +           dname[ptr1] = '\0'; 
313 +           name = *main_path;
314 +           name[ptr2] = '\0';
315 +           if (S_ISDIR((*main_info)->st_mode)) {
316 +               *ads_path = talloc_asprintf(ctx, "%s/%s/%s/.Parent/%s", dname, &name[ptr1 + 1], ADS_FOLDER, &name[ptr2 + 1]);
317 +           }
318 +           else {
319 +               *ads_path = talloc_asprintf(ctx, "%s/%s/%s/%s", dname, ADS_FOLDER, &name[ptr1 + 1], &name[ptr2 + 1]);
320 +           }
321 +           /* XXX are we always the right user ?*/
322 +           if (sys_lstat(*ads_path, &ads_info) < 0) {
323 +               int st_ret;
324 +               /* */
325 +               if (errno == ENOENT && (flag & O_CREAT))  {
326 +                   char *ads_base = ads_canonical_dir(ctx, dname, &name[ptr1 + 1], S_ISDIR((*main_info)->st_mode));
327 +                   mode_t mode;
328 +                   
329 +                   st_ret = mkdir(ads_base, 0777);
330 +                   if (st_ret < 0) {
331 +                       if (errno == ENOENT) {
332 +                           char *ads_double;
333 +                           if (S_ISDIR((*main_info)->st_mode)) {
334 +                               ads_double = talloc_asprintf(ctx, "%s/%s/%s", dname, &name[ptr1 + 1], ADS_FOLDER);
335 +                           }
336 +                           else {
337 +                               ads_double = talloc_asprintf(ctx, "%s/%s", dname, ADS_FOLDER);
338 +                           }
339 +                           if (mkdir(ads_double, 0777) < 0)
340 +                               return -1;
341 +                           if ((st_ret = mkdir(ads_base, 0777)) < 0)
342 +                               return -1;
343 +                           
344 +                           /* we just created .AppleDouble/file/ update mode with dir search 
345 +                            * XXX what about acl?
346 +                           */
347 +                           mode = (*main_info)->st_mode;
348 +                           if ((mode & (S_IRUSR | S_IWUSR )))
349 +                               mode |= S_IXUSR;
350 +                           if ((mode & (S_IRGRP | S_IWGRP )))
351 +                               mode |= S_IXGRP;
352 +                           if ((mode & (S_IROTH | S_IWOTH ))) 
353 +                               mode |= S_IXOTH;
354 +                           chmod(ads_base, mode);
355 +                       }
356 +                       else 
357 +                           errno = ENOENT;
358 +                   }
359 +               }
360 +               else 
361 +                   return -1;
362 +           }
363 +           ret = 1;
364 +       }
365 +       else {
366 +           *ads_path = *main_path;
367 +           if (sys_lstat(*main_path, *main_info) < 0) {
368 +               *main_info = NULL;
369 +           }
370 +       }
371 +#if 1
372 +       DEBUG(3, ("ADS: DEBUG:[%s] [%s]\n", *main_path, *ads_path)); 
373 +#endif
374 +       return ret;
375 +}
376 +
377 +/* ------------------------ */
378 +static SMB_BIG_UINT ads_disk_free(HANDLE_PARAMETER connection_struct *conn, const char *path,
379 +       BOOL small_query, SMB_BIG_UINT *bsize,
380 +       SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
381 +{
382 +       return SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, dfree, dsize);
383 +}
384 +
385 +static DIR *ads_opendir(HANDLE_PARAMETER connection_struct *conn, const char *fname)
386 +{
387 +       return SMB_VFS_NEXT_OPENDIR(handle, conn, fname);
388 +}
389 +
390 +static struct dirent *ads_readdir(HANDLE_PARAMETER connection_struct *conn, DIR *dirp)
391 +{
392 +        struct dirent *result;
393 +       DEBUG(3,("ads: ads_readdir\n"));
394 +       result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
395 +       if (result) {
396 +         DEBUG(3,("ads: ads_readdir: %s\n", result->d_name));
397 +        }
398 +        return result;
399 +}
400 +
401 +/* ------------------------- */
402 +static int ads_mkdir(HANDLE_PARAMETER connection_struct *conn, const char *path, mode_t mode)
403 +{
404 +       return SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
405 +}
406 +
407 +/* ------------------------- */
408 +static int unlink_file(const char *path)
409 +{
410 +int ret = 0;
411 +         
412 +       become_root();
413 +        ret = unlink(path);
414 +        unbecome_root();
415 +        return ret;
416 +}
417 +
418 +/* ------------------------- */
419 +static int unlink_folder(const char *path)
420 +{
421 +int ret = 0;
422 +         
423 +       become_root();
424 +        ret = rmdir(path);
425 +        unbecome_root();
426 +        return ret;
427 +}
428 +
429 +/* ------------------------- 
430 +   remove all files in an AppleDouble folder
431 +*/
432 +static void rrmdir(TALLOC_CTX *ctx, char *path)
433 +{
434 +        int n;
435 +        char *dpath;
436 +        struct dirent **namelist;
437
438 +        if (!path) return;
439
440 +        n = scandir(path, &namelist, 0, alphasort);
441 +        if (n < 0) {
442 +                return;
443 +        } 
444 +        while (n --) {
445 +               if (strcmp(namelist[n]->d_name, ".") == 0 || strcmp(namelist[n]->d_name, "..") == 0) {
446 +                       free(namelist[n]);
447 +                        continue;
448 +                }
449 +                if ((dpath = talloc_asprintf(ctx, "%s/%s",path, namelist[n]->d_name))) {
450 +                       unlink_file(dpath);
451 +                }
452 +                free(namelist[n]);
453 +        }
454 +        free(namelist);
455 +        unlink_folder(path);
456 +}
457 +
458 +/* --------------------------- */
459 +static void rrm_adsdir(TALLOC_CTX *ctx, char *path)
460 +{
461 +        int n;
462 +        char *dpath;
463 +        struct dirent **namelist;
464
465 +        if (!path) return;
466
467 +        n = scandir(path, &namelist, 0, alphasort);
468 +        if (n < 0) {
469 +                return;
470 +        } 
471 +        while (n --) {
472 +               if (strcmp(namelist[n]->d_name, ".") == 0 || strcmp(namelist[n]->d_name, "..") == 0) {
473 +                       free(namelist[n]);
474 +                        continue;
475 +                }
476 +                if ((dpath = talloc_asprintf(ctx, "%s/%s",path, namelist[n]->d_name))) {
477 +                       rrmdir(ctx, dpath);
478 +                }
479 +                free(namelist[n]);
480 +        }
481 +        free(namelist);
482 +        unlink_folder(path);
483 +}
484 +
485 +/* ------------------------- 
486 + * XXX 
487 + * if in smb.conf there's :
488 + * delete veto files = True
489 + * veto files = /.AppleD* /
490 +*/
491 +static int ads_rmdir( HANDLE_PARAMETER connection_struct *conn, const char *path)
492 +{
493 +        BOOL add = False;
494 +        TALLOC_CTX *ctx = 0;
495 +        char *dpath;
496 +        int  ret = 0;
497
498 +        if (!conn || !conn->origpath || !path) goto exit_rmdir;
499 +
500 +       /* .AppleD* */
501 +        strstr(path, ADS_FOLDER) ? (add = False) : (add = True);
502
503 +        if (!(ctx = ADS_TALLOC_INIT("ads_rmdir")))
504 +                goto exit_rmdir;
505
506 +        if (!(dpath = talloc_asprintf(ctx, "%s/%s%s",conn->origpath, path, add ? "/"ADS_FOLDER : "")))
507 +               goto exit_rmdir;
508 +               
509 +       /* remove folder .AppleDouble */
510 +        rrm_adsdir(ctx, dpath);
511
512 +exit_rmdir:
513 +       ret = SMB_VFS_NEXT_RMDIR(handle, conn, path);
514 +        talloc_destroy(ctx);
515 +
516 +       return ret;
517 +}
518 +
519 +/* ------------------------- */
520 +static int ads_open(HANDLE_PARAMETER connection_struct *conn, const char *fname, int flags, mode_t mode)
521 +{
522 +       int ret = 0;
523 +       char *ads_path = 0;
524 +       char *main_path = 0;
525 +       TALLOC_CTX *ctx;
526 +       SMB_STRUCT_STAT st;
527 +       SMB_STRUCT_STAT *main_info = &st;
528 +       
529 +       DEBUG(3,("ads: ads_open for %s %x\n", fname, flags));
530 +       if (!(ctx = ADS_TALLOC_INIT("ads_open")))
531 +               return -1;
532 +       /* convert to */
533 +       if (ads_build_paths(ctx, conn->origpath, fname, &ads_path, &main_path, &main_info, flags) < 0) {
534 +           talloc_destroy(ctx);
535 +           return -1;
536 +       }
537 +
538 +       ret = SMB_VFS_NEXT_OPEN(handle, conn, ads_path, flags, mode);
539 +       talloc_destroy(ctx);
540 +       return ret;
541 +
542 +}
543 +
544 +static int isDir(SMB_STRUCT_STAT *st)
545 +{
546 +     if (st == NULL) {
547 +         return 0;
548 +     }
549 +     return S_ISDIR(st->st_mode);
550 +}
551 +
552 +/* ------------------------- */
553 +static int ads_rename(HANDLE_PARAMETER connection_struct *conn, const char *old, const char *new)
554 +{
555 +       int ret = 0;
556 +       TALLOC_CTX *ctx;
557 +       char *ads_path = 0;
558 +       char *main_path = 0;
559 +       SMB_STRUCT_STAT st;
560 +       SMB_STRUCT_STAT *main_info = &st;
561 +       
562 +       DEBUG(3,("ads: ads_rename %s --> %sx\n", old, new));
563 +       
564 +       if (!(ctx = ADS_TALLOC_INIT("ads_rename")))
565 +           return -1;
566 +
567 +       if (ads_build_paths(ctx, conn->origpath, old, &ads_path, &main_path, &main_info, 0) < 0) {
568 +           talloc_destroy(ctx);
569 +           return -1;
570 +       }
571 +
572 +       if (ads_path != main_path) {
573 +           /* you can't rename an ads ! */
574 +           talloc_destroy(ctx);
575 +           errno = EINVAL;
576 +           return -1;
577 +       }
578 +
579 +       ret = SMB_VFS_NEXT_RENAME(handle, conn, old, new);
580 +       if (!ret && !isDir(main_info)) {
581 +           int  ptr1;
582 +           int  ptr2;
583 +           
584 +           char *ads_old  = ads_dir(ctx, conn->origpath, old, 0);
585 +           char *ads_new  = ads_dir(ctx, conn->origpath, new, 0);
586 +
587 +           /* is dest folder .Adouble there ? */
588 +           ptr1 = ads_get_path_ptr(ads_new);
589 +           ptr2 = ads_get_path_ptr(ads_old);
590 +
591 +           ads_new[ptr1] = '\0';
592 +           ads_old[ptr2] = '\0';
593 +           if (strcmp(ads_new, ads_old)) {
594 +               mkdir(ads_new, 0777);
595 +           }
596 +
597 +           ads_new[ptr1] = '/';
598 +           ads_old[ptr2] = '/';
599 +           
600 +           SMB_VFS_NEXT_RENAME(handle, conn, ads_old, ads_new);
601 +       }
602 +
603 +       talloc_destroy(ctx);
604 +       return ret;
605 +}
606 +
607 +/* ------------------------- 
608 + * For an ADS what do we need to return , ADS ? main DATA?
609 +*/
610 +static int ads_stat(HANDLE_PARAMETER connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
611 +{
612 +       int ret = 0;
613 +       char *ads_path = 0;
614 +       char *main_path = 0;
615 +       TALLOC_CTX *ctx;
616 +       SMB_STRUCT_STAT st;
617 +       SMB_STRUCT_STAT *main_info = &st;
618 +
619 +       DEBUG(3,("ads: ads_stat for %s\n", fname));
620 +
621 +       if (!(ctx = ADS_TALLOC_INIT("ads_stat")))
622 +           return -1;
623 +       /* which inode ?
624 +       */
625 +       if (ads_build_paths(ctx, conn->origpath, fname, &ads_path, &main_path, &main_info, 0) < 0) {
626 +           talloc_destroy(ctx);
627 +           return -1;
628 +       }
629 +
630 +       ret = SMB_VFS_NEXT_STAT(handle, conn, ads_path, sbuf);
631 +       talloc_destroy(ctx);
632 +       return ret;
633 +}
634 +
635 +/* ------------------------- */
636 +static int ads_lstat(HANDLE_PARAMETER connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
637 +{
638 +       int ret = 0;
639 +       char *ads_path = 0;
640 +       char *main_path = 0;
641 +       TALLOC_CTX *ctx;
642 +       SMB_STRUCT_STAT st;
643 +       SMB_STRUCT_STAT *main_info = &st;
644 +       
645 +       if (!(ctx = ADS_TALLOC_INIT("ads_lstat")))
646 +               return -1;
647 +       /* which inode ?
648 +       */
649 +       if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
650 +           talloc_destroy(ctx);
651 +           return -1;
652 +       }
653 +
654 +       return SMB_VFS_NEXT_LSTAT(handle, conn, ads_path, sbuf);
655 +       talloc_destroy(ctx);
656 +       return ret;
657 +}
658 +
659 +/* ------------------------- */
660 +static int ads_unlink(HANDLE_PARAMETER connection_struct *conn, const char *path)
661 +{
662 +       int ret = 0;
663 +
664 +       char *ads_path = 0;
665 +       char *main_path = 0;
666 +       TALLOC_CTX *ctx;
667 +       SMB_STRUCT_STAT st;
668 +       SMB_STRUCT_STAT *main_info = &st;
669 +       
670 +       DEBUG(3,("ads: ads_unlink %s\n", path));
671 +       if (!(ctx = ADS_TALLOC_INIT("ads_unlink")))
672 +               return -1;
673 +
674 +       if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
675 +           talloc_destroy(ctx);
676 +           return -1;
677 +       }
678 +
679 +       ret = SMB_VFS_NEXT_UNLINK(handle, conn, ads_path);
680 +       /*
681 +          if data stream
682 +             for each stream
683 +                 unlink
684 +       */
685 +       if (!ret && ads_path == main_path) {
686 +           char *ads_base  = ads_dir(ctx, conn->origpath, path, isDir(main_info));
687 +           struct dirent *dent = 0;
688 +           DIR *dir = opendir(ads_base);
689 +           
690 +           if (dir) {
691 +               char *dpath;
692 +               
693 +               while (NULL != (dent = readdir(dir))) {
694 +                   if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
695 +                       continue;
696 +                   if (!(dpath = talloc_asprintf(ctx, "%s/%s", ads_base, dent->d_name)))
697 +                       continue;
698 +                   /* XXX need to be root ?  */
699 +                   SMB_VFS_NEXT_UNLINK(handle, conn, dpath);               
700 +               }
701 +               closedir(dir);
702 +               rmdir(ads_base);
703 +           }
704 +       }
705 +
706 +       talloc_destroy(ctx);
707 +       return ret;
708 +}
709 +
710 +/* ------------------------- */
711 +static int ads_chmod(HANDLE_PARAMETER connection_struct *conn, const char *path, mode_t mode)
712 +{
713 +       int ret = 0;
714 +       char *ads_path = 0;
715 +       char *main_path = 0;
716 +       TALLOC_CTX *ctx;
717 +       SMB_STRUCT_STAT st;
718 +       SMB_STRUCT_STAT *main_info = &st;
719 +
720 +       DEBUG(3,("ads: ads_chmod %s\n", path));
721 +       /* if stream 
722 +              error ?, change only the stream
723 +       */
724 +       if (!(ctx = ADS_TALLOC_INIT("ads_chmod")))
725 +               return -1;
726 +
727 +       if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
728 +           talloc_destroy(ctx);
729 +           return -1;
730 +       }
731 +
732 +       ret = SMB_VFS_NEXT_CHMOD(handle, conn, ads_path, mode);
733 +       /*
734 +          if data stream
735 +             for each stream
736 +                 chmod
737 +       */
738 +       if (!ret && ads_path == main_path) {
739 +           char *ads_base  = ads_dir(ctx, conn->origpath, path, isDir(main_info));
740 +           struct dirent *dent = 0;
741 +           DIR *dir = opendir(ads_base);
742 +           
743 +           if (dir) {
744 +               char *dpath;
745 +               
746 +               while (NULL != (dent = readdir(dir))) {
747 +                   if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
748 +                       continue;
749 +                   if (!(dpath = talloc_asprintf(ctx, "%s/%s", ads_base, dent->d_name)))
750 +                       continue;
751 +                   /* XXX need to be root ? */
752 +                   SMB_VFS_NEXT_CHMOD(handle, conn, dpath, mode);
753 +               }
754 +               closedir(dir);
755 +               /* XXX need to change ads_base too*/
756 +           }
757 +       }
758 +
759 +       talloc_destroy(ctx);
760 +       return ret;
761 +}
762 +
763 +/* ------------------------- */
764 +static int ads_chown(HANDLE_PARAMETER connection_struct *conn, const char *path, uid_t uid, gid_t gid)
765 +{
766 +       int ret = 0;
767 +       char *ads_path = 0;
768 +       char *main_path = 0;
769 +       TALLOC_CTX *ctx;
770 +       SMB_STRUCT_STAT st;
771 +       SMB_STRUCT_STAT *main_info = &st;
772 +
773 +       DEBUG(3,("ads: ads_chown %s\n", path));
774 +       /* if stream 
775 +              error ?, change only the stream
776 +       */
777 +       if (!(ctx = ADS_TALLOC_INIT("ads_chown")))
778 +               return -1;
779 +
780 +       if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
781 +           talloc_destroy(ctx);
782 +           return -1;
783 +       }
784 +
785 +       ret = SMB_VFS_NEXT_CHOWN(handle, conn, ads_path, uid, gid);
786 +       /* if data stream
787 +             for each stream
788 +                 chmod
789 +       */
790 +       if (!ret && ads_path == main_path) {
791 +           char *ads_base  = ads_dir(ctx, conn->origpath, path, isDir(main_info));
792 +           struct dirent *dent = 0;
793 +           DIR *dir = opendir(ads_base);
794 +           
795 +           if (dir) {
796 +               char *dpath;
797 +               
798 +               while (NULL != (dent = readdir(dir))) {
799 +                   if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
800 +                       continue;
801 +                   if (!(dpath = talloc_asprintf(ctx, "%s/%s", ads_base, dent->d_name)))
802 +                       continue;
803 +                   /* XXX need to be root ?, what do we do in case of error? */
804 +                   SMB_VFS_NEXT_CHOWN(handle, conn, dpath, uid, gid);
805 +               }
806 +               closedir(dir);
807 +               SMB_VFS_NEXT_CHOWN(handle, conn, ads_path, uid, gid);
808 +           }
809 +       }
810 +
811 +       talloc_destroy(ctx);
812 +       return ret;
813 +}
814 +
815 +/* ------------------------- */
816 +static int ads_chdir(HANDLE_PARAMETER connection_struct *conn, const char *path)
817 +{
818 +       DEBUG(3,("ads: ads_chdir for %s\n", path));
819 +       return SMB_VFS_NEXT_CHDIR(handle, conn, path);
820 +}
821 +
822 +static int ads_utime(HANDLE_PARAMETER connection_struct *conn, const char *path, struct utimbuf *times)
823 +{
824 +       return SMB_VFS_NEXT_UTIME(handle, conn, path, times);
825 +}
826 +
827 +
828 +static BOOL ads_symlink(HANDLE_PARAMETER connection_struct *conn, const char *oldpath, const char *newpath)
829 +{
830 +       return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
831 +}
832 +
833 +static BOOL ads_readlink(HANDLE_PARAMETER connection_struct *conn, const char *path, char *buf, size_t bufsiz)
834 +{
835 +       return SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz);
836 +}
837 +
838 +static int ads_link( HANDLE_PARAMETER connection_struct *conn, const char *oldpath, const char *newpath)
839 +{
840 +       return SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath);
841 +}
842 +
843 +static int ads_mknod(HANDLE_PARAMETER connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev)
844 +{
845 +       return SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev);
846 +}
847 +
848 +static char *ads_realpath(HANDLE_PARAMETER connection_struct *conn, const char *path, char *resolved_path)
849 +{
850 +       return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
851 +}
852 +
853 +static BOOL ads_set_nt_acl(HANDLE_PARAMETER files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
854 +{
855 +       return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd);
856 +}
857 +
858 +static int ads_chmod_acl(HANDLE_PARAMETER connection_struct *conn, const char *name, mode_t mode)
859 +{
860 +       /* If the underlying VFS doesn't have ACL support... */
861 +#ifdef ADS_NEW_MODULE
862 +        if (!handle->vfs_next.ops.chmod_acl) {                                                                          
863 +#else
864 +       if (!default_vfs_ops.chmod_acl) {
865 +#endif
866 +               errno = ENOSYS;
867 +               return -1;
868 +       }
869 +       return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode);
870 +}
871 +
872 +static SMB_ACL_T ads_sys_acl_get_file(HANDLE_PARAMETER connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
873 +{
874 +       return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type);
875 +}
876 +
877 +static int ads_sys_acl_set_file(HANDLE_PARAMETER connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
878 +{
879 +       return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, theacl);
880 +}
881 +
882 +static int ads_sys_acl_delete_def_file(HANDLE_PARAMETER connection_struct *conn, const char *path)
883 +{
884 +       return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path);
885 +}
886 +
887 +#ifdef         ADS_NEW_MODULE 
888 +static ssize_t ads_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
889 +{
890 +        return SMB_VFS_NEXT_GETXATTR(handle, conn, path, name, value, size);
891 +}
892 +
893 +static ssize_t ads_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t
894 +size)
895 +{
896 +        return SMB_VFS_NEXT_LGETXATTR(handle, conn, path, name, value, size);
897 +}
898 +
899 +static ssize_t ads_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
900 +{
901 +        return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, name, value, size);
902 +}
903 +
904 +static ssize_t ads_listxattr(vfs_handle_struct *handle, connection_struct *conn,const char *path, char *list, size_t size)
905 +{
906 +        return SMB_VFS_NEXT_LISTXATTR(handle, conn, path, list, size);
907 +}
908 +
909 +static ssize_t ads_llistxattr(vfs_handle_struct *handle,struct connection_struct *conn,const char *path, char *list, size_t size)
910 +{
911 +        return SMB_VFS_NEXT_LLISTXATTR(handle, conn, path, list, size);
912 +}
913 +
914 +static int ads_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
915 +{
916 +        return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, path, name);
917 +}
918 +
919 +static int ads_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
920 +{
921 +        return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, path, name);
922 +}
923 +
924 +static int ads_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
925 +{
926 +        return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, name);
927 +}
928 +
929 +static int ads_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
930 +{
931 +        return SMB_VFS_NEXT_SETXATTR(handle, conn, path, name, value, size, flags);
932 +}
933 +
934 +static int ads_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
935 +{
936 +        return SMB_VFS_NEXT_LSETXATTR(handle, conn, path, name, value, size, flags);
937 +}
938 +
939 +static int ads_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
940 +{
941 +        return SMB_VFS_NEXT_FSETXATTR(handle, fsp, fd, name, value, size, flags);
942 +}
943 +
944 +#endif
945 +
946 +/* ---------------------------------- 
947 + * enumerate 
948 +*/
949 +static ssize_t ads_listads(HANDLE_PARAMETER struct connection_struct *conn,const char *path, char *list, size_t size)
950 +{
951 +       char *ads_path = 0;
952 +       char *main_path = 0;
953 +       TALLOC_CTX *ctx;
954 +       size_t     len, total = 0;
955 +       SMB_STRUCT_STAT st;
956 +       SMB_STRUCT_STAT *main_info = &st;
957 +       
958 +
959 +       if (!list || !path) {
960 +               /* aka we have ads functionnality */
961 +               return 0;
962 +       }
963 +
964 +       DEBUG(3,("ads: ads_listads %s\n", path));
965 +
966 +       if (!(ctx = ADS_TALLOC_INIT("ads_listads")))
967 +               return -1;
968 +
969 +       if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
970 +           talloc_destroy(ctx);
971 +           return -1;
972 +       }
973 +
974 +       /*
975 +          if data stream
976 +             for each stream
977 +       */
978 +       if (ads_path == main_path) {
979 +           char *ads_base  = ads_dir(ctx, conn->origpath, path, isDir(main_info));
980 +           struct dirent *dent = 0;
981 +           DIR *dir = opendir(ads_base);
982 +           
983 +           /* XXX need to be root ? */
984 +           if (dir) {
985 +               
986 +               while (NULL != (dent = readdir(dir))) {
987 +                   if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
988 +                       continue;
989 +                   len = strlen(dent->d_name) +8 ;
990 +                   total += len;
991 +                   if (total >= size) {
992 +                       talloc_destroy(ctx);
993 +                       errno = ERANGE;
994 +                       return -1;
995 +                   }
996 +                   snprintf (list, len, ":%s:$DATA", dent->d_name);
997 +                   list += len;
998 +               }
999 +               closedir(dir);
1000 +           }
1001 +       }
1002 +
1003 +       talloc_destroy(ctx);
1004 +       return total;
1005 +}
1006 +
1007 +/* ------------------------------------
1008 + * VFS operations structure */
1009 +
1010 +#ifndef SMB_VFS_OP
1011 +#define SMB_VFS_OP(x) ((void *) x)  
1012 +#endif
1013 +
1014 +static vfs_op_tuple ads_op_tuples[] = {
1015 +
1016 +       /* Disk operations */
1017 +
1018 +       {SMB_VFS_OP(ads_disk_free),                     SMB_VFS_OP_DISK_FREE,           SMB_VFS_LAYER_TRANSPARENT},
1019 +       
1020 +       /* Directory operations */
1021 +
1022 +       {SMB_VFS_OP(ads_opendir),                       SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_TRANSPARENT},
1023 +       {SMB_VFS_OP(ads_readdir),                       SMB_VFS_OP_READDIR,             SMB_VFS_LAYER_TRANSPARENT},
1024 +       {SMB_VFS_OP(ads_mkdir),                         SMB_VFS_OP_MKDIR,               SMB_VFS_LAYER_TRANSPARENT},
1025 +       {SMB_VFS_OP(ads_rmdir),                         SMB_VFS_OP_RMDIR,               SMB_VFS_LAYER_TRANSPARENT},
1026 +
1027 +       /* File operations */
1028 +
1029 +       {SMB_VFS_OP(ads_open),                          SMB_VFS_OP_OPEN,                SMB_VFS_LAYER_TRANSPARENT},
1030 +       {SMB_VFS_OP(ads_rename),                        SMB_VFS_OP_RENAME,              SMB_VFS_LAYER_TRANSPARENT},
1031 +       {SMB_VFS_OP(ads_stat),                          SMB_VFS_OP_STAT,                SMB_VFS_LAYER_TRANSPARENT},
1032 +       {SMB_VFS_OP(ads_lstat),                         SMB_VFS_OP_LSTAT,               SMB_VFS_LAYER_TRANSPARENT},
1033 +       {SMB_VFS_OP(ads_unlink),                        SMB_VFS_OP_UNLINK,              SMB_VFS_LAYER_TRANSPARENT},
1034 +       {SMB_VFS_OP(ads_chmod),                         SMB_VFS_OP_CHMOD,               SMB_VFS_LAYER_TRANSPARENT},
1035 +       {SMB_VFS_OP(ads_chown),                         SMB_VFS_OP_CHOWN,               SMB_VFS_LAYER_TRANSPARENT},
1036 +       {SMB_VFS_OP(ads_chdir),                         SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_TRANSPARENT},
1037 +       {SMB_VFS_OP(ads_utime),                         SMB_VFS_OP_UTIME,               SMB_VFS_LAYER_TRANSPARENT},
1038 +       {SMB_VFS_OP(ads_symlink),                       SMB_VFS_OP_SYMLINK,             SMB_VFS_LAYER_TRANSPARENT},
1039 +       {SMB_VFS_OP(ads_readlink),                      SMB_VFS_OP_READLINK,            SMB_VFS_LAYER_TRANSPARENT},
1040 +       {SMB_VFS_OP(ads_link),                          SMB_VFS_OP_LINK,                SMB_VFS_LAYER_TRANSPARENT},
1041 +       {SMB_VFS_OP(ads_mknod),                         SMB_VFS_OP_MKNOD,               SMB_VFS_LAYER_TRANSPARENT},
1042 +       {SMB_VFS_OP(ads_realpath),                      SMB_VFS_OP_REALPATH,            SMB_VFS_LAYER_TRANSPARENT},
1043 +
1044 +       /* NT File ACL operations */
1045 +
1046 +       {SMB_VFS_OP(ads_set_nt_acl),                    SMB_VFS_OP_SET_NT_ACL,          SMB_VFS_LAYER_TRANSPARENT},
1047 +
1048 +       /* POSIX ACL operations */
1049 +
1050 +       {SMB_VFS_OP(ads_chmod_acl),                     SMB_VFS_OP_CHMOD_ACL,           SMB_VFS_LAYER_TRANSPARENT},
1051 +
1052 +       {SMB_VFS_OP(ads_sys_acl_get_file),              SMB_VFS_OP_SYS_ACL_GET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
1053 +       {SMB_VFS_OP(ads_sys_acl_set_file),              SMB_VFS_OP_SYS_ACL_SET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
1054 +       {SMB_VFS_OP(ads_sys_acl_delete_def_file),       SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,     SMB_VFS_LAYER_TRANSPARENT},
1055 +#ifdef         ADS_NEW_MODULE
1056 +       /* EA operations. */
1057 +       {SMB_VFS_OP(ads_getxattr),                      SMB_VFS_OP_GETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
1058 +       {SMB_VFS_OP(ads_lgetxattr),                     SMB_VFS_OP_LGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
1059 +       {SMB_VFS_OP(ads_fgetxattr),                     SMB_VFS_OP_FGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
1060 +       {SMB_VFS_OP(ads_listxattr),                     SMB_VFS_OP_LISTXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
1061 +       {SMB_VFS_OP(ads_llistxattr),                    SMB_VFS_OP_LLISTXATTR,                  SMB_VFS_LAYER_TRANSPARENT},
1062 +       {SMB_VFS_OP(ads_removexattr),                   SMB_VFS_OP_REMOVEXATTR,                 SMB_VFS_LAYER_TRANSPARENT},
1063 +       {SMB_VFS_OP(ads_lremovexattr),                  SMB_VFS_OP_LREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
1064 +       {SMB_VFS_OP(ads_fremovexattr),                  SMB_VFS_OP_FREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
1065 +       {SMB_VFS_OP(ads_setxattr),                      SMB_VFS_OP_SETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
1066 +       {SMB_VFS_OP(ads_lsetxattr),                     SMB_VFS_OP_LSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
1067 +       {SMB_VFS_OP(ads_fsetxattr),                     SMB_VFS_OP_FSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
1068 +#endif
1069 +       /* ADS operations */
1070 +       {SMB_VFS_OP(ads_listads),                       SMB_VFS_OP_LISTADS,                     SMB_VFS_LAYER_TRANSPARENT},
1071 +
1072 +       {NULL,                                          SMB_VFS_OP_NOOP,                        SMB_VFS_LAYER_NOOP}
1073 +};
1074 +
1075 +#ifdef ADS_NEW_MODULE
1076 +
1077 +#if 0
1078 +NTSTATUS vfs_ads_init(void)
1079 +{
1080 +        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "ads", ads_op_tuples);
1081 +}
1082 +#endif
1083 +
1084 +NTSTATUS vfs_ads_init(void)
1085 +{
1086 +        DEBUG(3, ("ADS: vfs_ads_init\n"));
1087 +        return NT_STATUS_OK;
1088 +}
1089 +         
1090 +
1091 +NTSTATUS init_module(void)
1092 +{
1093 +       DEBUG(3, ("ADS: init_module\n" ));
1094 +        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "ads", ads_op_tuples);
1095 +}
1096 +
1097 +#else
1098 +/* VFS initialisation function.  Return vfs_op_tuple array back to SAMBA. */
1099 +vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,struct smb_vfs_handle_struct *vfs_handle)
1100 +{
1101 +       *vfs_version = SMB_VFS_INTERFACE_VERSION;
1102 +        memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
1103 +                   
1104 +        ads_handle = vfs_handle;
1105 +        DEBUG(3, ("ADS: vfs module loaded\n"));
1106 +        return ads_op_tuples;
1107 +}
1108 +                                             
1109 +/* VFS finalization function. */
1110 +void vfs_done(connection_struct *conn)
1111 +{
1112 +       DEBUG(3, ("ADS: vfs module unloaded\n"));
1113 +}
1114 +
1115 +#endif