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
5 +##########################################################################
6 +# Makefile for Samba VFS modules
7 +###########################################################################
10 +LIBTOOL=/usr/bin/libtool
11 +# REPLACE with samba source
12 +SMB=/u/redhat/paris/cvs/samba/smb3.0a20
14 +# REPLACE with samba build folder
15 +BUILD=/mnt/hdd/build/smb.1.3
17 +CFLAGS=-Wall -I $(BUILD)/include \
18 +-I$(SMB)/source -I$(SMB)/source/include -I$(SMB)/source/ubiqx -I$(SMB)/source/smbwrapper
33 + @$(LIBTOOL) --mode=link $(CC) -o $@ $< $(LDFLAGS)
37 + @$(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
42 + rm -rf .libs */.libs
43 + rm -f core *~ *% *.bak *.o */*.o *.lo $(VFS_OBJS)
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
49 +This a vfs for NT ADS
50 +you must set SMB and BUILD variables in Makefile.
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
64 +new one (current svn tree)
65 +copy vfs_ads.so as ads.so in <prefix>/lib/vfs/
67 +cp vfs_ads.so /opt/lib/vfs/ads.so
71 + comment = test ADS Mac/PC directory
72 + path=/home/test_ads/
74 +# /.AppleD* is mandatory
75 + veto files = /.AppleD*/Network Trash Folder/Icon\r/
76 + delete veto files = True
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
88 + * CAP VFS module for Samba 3.x Version 0.3
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
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.
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.
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.
109 + * modified for alternate data stream
110 + * Copyright (C) Didier Gautheron 2004
112 + * this module should compile with old 3.0 API and 2004-07 svn API
116 +#include "includes.h"
119 +#define DBGC_CLASS DBGC_VFS
121 +#define ADS_FOLDER ".AppleDouble"
122 +#define ADOUBLEMODE 0777
124 +/* FIXME found a better test */
126 +#define ADS_NEW_MODULE
128 +/* for current svn tree */
129 +#define ADS_TALLOC_INIT(a) talloc_init(a)
131 +#define HANDLE_PARAMETER vfs_handle_struct *handle,
132 +#define HANDLE handle,
134 +/* ------------------- */
137 +#define ADS_TALLOC_INIT(a) talloc_init()
139 +#define HANDLE_PARAMETER
142 +/* VFS operations */
143 +static struct vfs_ops default_vfs_ops; /* For passthrough operation */
144 +static struct smb_vfs_handle_struct *ads_handle;
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)
174 +/* -------------------------
176 + * .AppleDouble/filename/stream name
178 + * return the *LAST* '/' in path
180 +static int ads_get_path_ptr(char *path)
185 + for (i = 0; path[i]; i ++) {
186 + if (path[i] == '/')
193 +/* ------------------------------
194 + * return the *FIRST* ':' in path
196 +static int ads_get_stream_ptr(const char *path)
201 + for (i = 0; path[i]; i ++) {
202 + if (path[i] == ':') {
211 + * fname is only a filename
214 +static char *ads_canonical_dir(TALLOC_CTX *ctx, const char *path, const char *fname, int isdir)
217 + return talloc_asprintf(ctx, "%s/%s/%s/.Parent", path, fname, ADS_FOLDER);
219 + return talloc_asprintf(ctx, "%s/%s/%s", path, ADS_FOLDER, fname);
224 + * return directory pathname for an alternate data stream
225 + * fname is *NOT* an altername name (ie foo:bar)
227 +static char *ads_dir(TALLOC_CTX *ctx, const char *path, const char *fname, int isdir)
234 + if (fname[0] == '.') ptr0 ++;
235 + if (fname[1] == '/') ptr0 ++;
237 + temp = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]);
238 + ptr1 = ads_get_path_ptr(temp);
240 + return ads_canonical_dir(ctx, temp, &temp[ptr1 + 1], isdir);
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
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
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)
264 + SMB_STRUCT_STAT ads_info;
266 + if (!ctx || !path || !fname || !ads_path || !main_path || !main_info || !*main_info)
269 + DEBUG(3, ("ADS: PATH: %s[%s]\n", path, fname));
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));
277 + if (fname[0] == '.') ptr0 ++;
278 + if (fname[1] == '/') ptr0 ++;
281 + *main_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]);
284 + /* get pointer to last '/' */
285 + ptr1 = ads_get_path_ptr(*main_path);
286 + ptr2 = ads_get_stream_ptr(*main_path +ptr1 +1);
288 + * what about ::$DATA or :name:$DATA
292 + /* it's an alternate stream */
294 + (*main_path)[ptr2] = 0;
295 + ptr3 = ads_get_stream_ptr(*main_path +ptr2 +1);
298 + /* check it's $DATA */
299 + if (!strcmp("$DATA", &(*main_path)[ptr3+1])) {
300 + (*main_path)[ptr3] = 0;
304 + DEBUG(3, ("ADS: MAIN DATA %s\n", *main_path));
306 + if (sys_lstat(*main_path, *main_info) < 0) {
307 + /* if we can't get the main file give up */
310 + (*main_path)[ptr2] = ':';
311 + dname = talloc_strdup(ctx, *main_path);
312 + dname[ptr1] = '\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]);
319 + *ads_path = talloc_asprintf(ctx, "%s/%s/%s/%s", dname, ADS_FOLDER, &name[ptr1 + 1], &name[ptr2 + 1]);
321 + /* XXX are we always the right user ?*/
322 + if (sys_lstat(*ads_path, &ads_info) < 0) {
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));
329 + st_ret = mkdir(ads_base, 0777);
331 + if (errno == ENOENT) {
333 + if (S_ISDIR((*main_info)->st_mode)) {
334 + ads_double = talloc_asprintf(ctx, "%s/%s/%s", dname, &name[ptr1 + 1], ADS_FOLDER);
337 + ads_double = talloc_asprintf(ctx, "%s/%s", dname, ADS_FOLDER);
339 + if (mkdir(ads_double, 0777) < 0)
341 + if ((st_ret = mkdir(ads_base, 0777)) < 0)
344 + /* we just created .AppleDouble/file/ update mode with dir search
345 + * XXX what about acl?
347 + mode = (*main_info)->st_mode;
348 + if ((mode & (S_IRUSR | S_IWUSR )))
350 + if ((mode & (S_IRGRP | S_IWGRP )))
352 + if ((mode & (S_IROTH | S_IWOTH )))
354 + chmod(ads_base, mode);
366 + *ads_path = *main_path;
367 + if (sys_lstat(*main_path, *main_info) < 0) {
372 + DEBUG(3, ("ADS: DEBUG:[%s] [%s]\n", *main_path, *ads_path));
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)
382 + return SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, dfree, dsize);
385 +static DIR *ads_opendir(HANDLE_PARAMETER connection_struct *conn, const char *fname)
387 + return SMB_VFS_NEXT_OPENDIR(handle, conn, fname);
390 +static struct dirent *ads_readdir(HANDLE_PARAMETER connection_struct *conn, DIR *dirp)
392 + struct dirent *result;
393 + DEBUG(3,("ads: ads_readdir\n"));
394 + result = SMB_VFS_NEXT_READDIR(handle, conn, dirp);
396 + DEBUG(3,("ads: ads_readdir: %s\n", result->d_name));
401 +/* ------------------------- */
402 +static int ads_mkdir(HANDLE_PARAMETER connection_struct *conn, const char *path, mode_t mode)
404 + return SMB_VFS_NEXT_MKDIR(handle, conn, path, mode);
407 +/* ------------------------- */
408 +static int unlink_file(const char *path)
413 + ret = unlink(path);
418 +/* ------------------------- */
419 +static int unlink_folder(const char *path)
429 +/* -------------------------
430 + remove all files in an AppleDouble folder
432 +static void rrmdir(TALLOC_CTX *ctx, char *path)
436 + struct dirent **namelist;
440 + n = scandir(path, &namelist, 0, alphasort);
445 + if (strcmp(namelist[n]->d_name, ".") == 0 || strcmp(namelist[n]->d_name, "..") == 0) {
449 + if ((dpath = talloc_asprintf(ctx, "%s/%s",path, namelist[n]->d_name))) {
450 + unlink_file(dpath);
455 + unlink_folder(path);
458 +/* --------------------------- */
459 +static void rrm_adsdir(TALLOC_CTX *ctx, char *path)
463 + struct dirent **namelist;
467 + n = scandir(path, &namelist, 0, alphasort);
472 + if (strcmp(namelist[n]->d_name, ".") == 0 || strcmp(namelist[n]->d_name, "..") == 0) {
476 + if ((dpath = talloc_asprintf(ctx, "%s/%s",path, namelist[n]->d_name))) {
477 + rrmdir(ctx, dpath);
482 + unlink_folder(path);
485 +/* -------------------------
487 + * if in smb.conf there's :
488 + * delete veto files = True
489 + * veto files = /.AppleD* /
491 +static int ads_rmdir( HANDLE_PARAMETER connection_struct *conn, const char *path)
494 + TALLOC_CTX *ctx = 0;
498 + if (!conn || !conn->origpath || !path) goto exit_rmdir;
501 + strstr(path, ADS_FOLDER) ? (add = False) : (add = True);
503 + if (!(ctx = ADS_TALLOC_INIT("ads_rmdir")))
506 + if (!(dpath = talloc_asprintf(ctx, "%s/%s%s",conn->origpath, path, add ? "/"ADS_FOLDER : "")))
509 + /* remove folder .AppleDouble */
510 + rrm_adsdir(ctx, dpath);
513 + ret = SMB_VFS_NEXT_RMDIR(handle, conn, path);
514 + talloc_destroy(ctx);
519 +/* ------------------------- */
520 +static int ads_open(HANDLE_PARAMETER connection_struct *conn, const char *fname, int flags, mode_t mode)
523 + char *ads_path = 0;
524 + char *main_path = 0;
526 + SMB_STRUCT_STAT st;
527 + SMB_STRUCT_STAT *main_info = &st;
529 + DEBUG(3,("ads: ads_open for %s %x\n", fname, flags));
530 + if (!(ctx = ADS_TALLOC_INIT("ads_open")))
533 + if (ads_build_paths(ctx, conn->origpath, fname, &ads_path, &main_path, &main_info, flags) < 0) {
534 + talloc_destroy(ctx);
538 + ret = SMB_VFS_NEXT_OPEN(handle, conn, ads_path, flags, mode);
539 + talloc_destroy(ctx);
544 +static int isDir(SMB_STRUCT_STAT *st)
549 + return S_ISDIR(st->st_mode);
552 +/* ------------------------- */
553 +static int ads_rename(HANDLE_PARAMETER connection_struct *conn, const char *old, const char *new)
557 + char *ads_path = 0;
558 + char *main_path = 0;
559 + SMB_STRUCT_STAT st;
560 + SMB_STRUCT_STAT *main_info = &st;
562 + DEBUG(3,("ads: ads_rename %s --> %sx\n", old, new));
564 + if (!(ctx = ADS_TALLOC_INIT("ads_rename")))
567 + if (ads_build_paths(ctx, conn->origpath, old, &ads_path, &main_path, &main_info, 0) < 0) {
568 + talloc_destroy(ctx);
572 + if (ads_path != main_path) {
573 + /* you can't rename an ads ! */
574 + talloc_destroy(ctx);
579 + ret = SMB_VFS_NEXT_RENAME(handle, conn, old, new);
580 + if (!ret && !isDir(main_info)) {
584 + char *ads_old = ads_dir(ctx, conn->origpath, old, 0);
585 + char *ads_new = ads_dir(ctx, conn->origpath, new, 0);
587 + /* is dest folder .Adouble there ? */
588 + ptr1 = ads_get_path_ptr(ads_new);
589 + ptr2 = ads_get_path_ptr(ads_old);
591 + ads_new[ptr1] = '\0';
592 + ads_old[ptr2] = '\0';
593 + if (strcmp(ads_new, ads_old)) {
594 + mkdir(ads_new, 0777);
597 + ads_new[ptr1] = '/';
598 + ads_old[ptr2] = '/';
600 + SMB_VFS_NEXT_RENAME(handle, conn, ads_old, ads_new);
603 + talloc_destroy(ctx);
607 +/* -------------------------
608 + * For an ADS what do we need to return , ADS ? main DATA?
610 +static int ads_stat(HANDLE_PARAMETER connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
613 + char *ads_path = 0;
614 + char *main_path = 0;
616 + SMB_STRUCT_STAT st;
617 + SMB_STRUCT_STAT *main_info = &st;
619 + DEBUG(3,("ads: ads_stat for %s\n", fname));
621 + if (!(ctx = ADS_TALLOC_INIT("ads_stat")))
625 + if (ads_build_paths(ctx, conn->origpath, fname, &ads_path, &main_path, &main_info, 0) < 0) {
626 + talloc_destroy(ctx);
630 + ret = SMB_VFS_NEXT_STAT(handle, conn, ads_path, sbuf);
631 + talloc_destroy(ctx);
635 +/* ------------------------- */
636 +static int ads_lstat(HANDLE_PARAMETER connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
639 + char *ads_path = 0;
640 + char *main_path = 0;
642 + SMB_STRUCT_STAT st;
643 + SMB_STRUCT_STAT *main_info = &st;
645 + if (!(ctx = ADS_TALLOC_INIT("ads_lstat")))
649 + if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
650 + talloc_destroy(ctx);
654 + return SMB_VFS_NEXT_LSTAT(handle, conn, ads_path, sbuf);
655 + talloc_destroy(ctx);
659 +/* ------------------------- */
660 +static int ads_unlink(HANDLE_PARAMETER connection_struct *conn, const char *path)
664 + char *ads_path = 0;
665 + char *main_path = 0;
667 + SMB_STRUCT_STAT st;
668 + SMB_STRUCT_STAT *main_info = &st;
670 + DEBUG(3,("ads: ads_unlink %s\n", path));
671 + if (!(ctx = ADS_TALLOC_INIT("ads_unlink")))
674 + if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
675 + talloc_destroy(ctx);
679 + ret = SMB_VFS_NEXT_UNLINK(handle, conn, ads_path);
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);
693 + while (NULL != (dent = readdir(dir))) {
694 + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
696 + if (!(dpath = talloc_asprintf(ctx, "%s/%s", ads_base, dent->d_name)))
698 + /* XXX need to be root ? */
699 + SMB_VFS_NEXT_UNLINK(handle, conn, dpath);
706 + talloc_destroy(ctx);
710 +/* ------------------------- */
711 +static int ads_chmod(HANDLE_PARAMETER connection_struct *conn, const char *path, mode_t mode)
714 + char *ads_path = 0;
715 + char *main_path = 0;
717 + SMB_STRUCT_STAT st;
718 + SMB_STRUCT_STAT *main_info = &st;
720 + DEBUG(3,("ads: ads_chmod %s\n", path));
722 + error ?, change only the stream
724 + if (!(ctx = ADS_TALLOC_INIT("ads_chmod")))
727 + if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
728 + talloc_destroy(ctx);
732 + ret = SMB_VFS_NEXT_CHMOD(handle, conn, ads_path, mode);
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);
746 + while (NULL != (dent = readdir(dir))) {
747 + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
749 + if (!(dpath = talloc_asprintf(ctx, "%s/%s", ads_base, dent->d_name)))
751 + /* XXX need to be root ? */
752 + SMB_VFS_NEXT_CHMOD(handle, conn, dpath, mode);
755 + /* XXX need to change ads_base too*/
759 + talloc_destroy(ctx);
763 +/* ------------------------- */
764 +static int ads_chown(HANDLE_PARAMETER connection_struct *conn, const char *path, uid_t uid, gid_t gid)
767 + char *ads_path = 0;
768 + char *main_path = 0;
770 + SMB_STRUCT_STAT st;
771 + SMB_STRUCT_STAT *main_info = &st;
773 + DEBUG(3,("ads: ads_chown %s\n", path));
775 + error ?, change only the stream
777 + if (!(ctx = ADS_TALLOC_INIT("ads_chown")))
780 + if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
781 + talloc_destroy(ctx);
785 + ret = SMB_VFS_NEXT_CHOWN(handle, conn, ads_path, uid, gid);
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);
798 + while (NULL != (dent = readdir(dir))) {
799 + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
801 + if (!(dpath = talloc_asprintf(ctx, "%s/%s", ads_base, dent->d_name)))
803 + /* XXX need to be root ?, what do we do in case of error? */
804 + SMB_VFS_NEXT_CHOWN(handle, conn, dpath, uid, gid);
807 + SMB_VFS_NEXT_CHOWN(handle, conn, ads_path, uid, gid);
811 + talloc_destroy(ctx);
815 +/* ------------------------- */
816 +static int ads_chdir(HANDLE_PARAMETER connection_struct *conn, const char *path)
818 + DEBUG(3,("ads: ads_chdir for %s\n", path));
819 + return SMB_VFS_NEXT_CHDIR(handle, conn, path);
822 +static int ads_utime(HANDLE_PARAMETER connection_struct *conn, const char *path, struct utimbuf *times)
824 + return SMB_VFS_NEXT_UTIME(handle, conn, path, times);
828 +static BOOL ads_symlink(HANDLE_PARAMETER connection_struct *conn, const char *oldpath, const char *newpath)
830 + return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
833 +static BOOL ads_readlink(HANDLE_PARAMETER connection_struct *conn, const char *path, char *buf, size_t bufsiz)
835 + return SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz);
838 +static int ads_link( HANDLE_PARAMETER connection_struct *conn, const char *oldpath, const char *newpath)
840 + return SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath);
843 +static int ads_mknod(HANDLE_PARAMETER connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev)
845 + return SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev);
848 +static char *ads_realpath(HANDLE_PARAMETER connection_struct *conn, const char *path, char *resolved_path)
850 + return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path);
853 +static BOOL ads_set_nt_acl(HANDLE_PARAMETER files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
855 + return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd);
858 +static int ads_chmod_acl(HANDLE_PARAMETER connection_struct *conn, const char *name, mode_t mode)
860 + /* If the underlying VFS doesn't have ACL support... */
861 +#ifdef ADS_NEW_MODULE
862 + if (!handle->vfs_next.ops.chmod_acl) {
864 + if (!default_vfs_ops.chmod_acl) {
869 + return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode);
872 +static SMB_ACL_T ads_sys_acl_get_file(HANDLE_PARAMETER connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
874 + return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type);
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)
879 + return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, theacl);
882 +static int ads_sys_acl_delete_def_file(HANDLE_PARAMETER connection_struct *conn, const char *path)
884 + return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path);
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)
890 + return SMB_VFS_NEXT_GETXATTR(handle, conn, path, name, value, size);
893 +static ssize_t ads_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t
896 + return SMB_VFS_NEXT_LGETXATTR(handle, conn, path, name, value, size);
899 +static ssize_t ads_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
901 + return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, name, value, size);
904 +static ssize_t ads_listxattr(vfs_handle_struct *handle, connection_struct *conn,const char *path, char *list, size_t size)
906 + return SMB_VFS_NEXT_LISTXATTR(handle, conn, path, list, size);
909 +static ssize_t ads_llistxattr(vfs_handle_struct *handle,struct connection_struct *conn,const char *path, char *list, size_t size)
911 + return SMB_VFS_NEXT_LLISTXATTR(handle, conn, path, list, size);
914 +static int ads_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
916 + return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, path, name);
919 +static int ads_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
921 + return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, path, name);
924 +static int ads_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
926 + return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, name);
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)
931 + return SMB_VFS_NEXT_SETXATTR(handle, conn, path, name, value, size, flags);
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)
936 + return SMB_VFS_NEXT_LSETXATTR(handle, conn, path, name, value, size, flags);
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)
941 + return SMB_VFS_NEXT_FSETXATTR(handle, fsp, fd, name, value, size, flags);
946 +/* ----------------------------------
949 +static ssize_t ads_listads(HANDLE_PARAMETER struct connection_struct *conn,const char *path, char *list, size_t size)
951 + char *ads_path = 0;
952 + char *main_path = 0;
954 + size_t len, total = 0;
955 + SMB_STRUCT_STAT st;
956 + SMB_STRUCT_STAT *main_info = &st;
959 + if (!list || !path) {
960 + /* aka we have ads functionnality */
964 + DEBUG(3,("ads: ads_listads %s\n", path));
966 + if (!(ctx = ADS_TALLOC_INIT("ads_listads")))
969 + if (ads_build_paths(ctx, conn->origpath, path, &ads_path, &main_path, &main_info, 0) < 0) {
970 + talloc_destroy(ctx);
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);
983 + /* XXX need to be root ? */
986 + while (NULL != (dent = readdir(dir))) {
987 + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
989 + len = strlen(dent->d_name) +8 ;
991 + if (total >= size) {
992 + talloc_destroy(ctx);
996 + snprintf (list, len, ":%s:$DATA", dent->d_name);
1003 + talloc_destroy(ctx);
1007 +/* ------------------------------------
1008 + * VFS operations structure */
1011 +#define SMB_VFS_OP(x) ((void *) x)
1014 +static vfs_op_tuple ads_op_tuples[] = {
1016 + /* Disk operations */
1018 + {SMB_VFS_OP(ads_disk_free), SMB_VFS_OP_DISK_FREE, SMB_VFS_LAYER_TRANSPARENT},
1020 + /* Directory operations */
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},
1027 + /* File operations */
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},
1044 + /* NT File ACL operations */
1046 + {SMB_VFS_OP(ads_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
1048 + /* POSIX ACL operations */
1050 + {SMB_VFS_OP(ads_chmod_acl), SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT},
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},
1069 + /* ADS operations */
1070 + {SMB_VFS_OP(ads_listads), SMB_VFS_OP_LISTADS, SMB_VFS_LAYER_TRANSPARENT},
1072 + {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
1075 +#ifdef ADS_NEW_MODULE
1078 +NTSTATUS vfs_ads_init(void)
1080 + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "ads", ads_op_tuples);
1084 +NTSTATUS vfs_ads_init(void)
1086 + DEBUG(3, ("ADS: vfs_ads_init\n"));
1087 + return NT_STATUS_OK;
1091 +NTSTATUS init_module(void)
1093 + DEBUG(3, ("ADS: init_module\n" ));
1094 + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "ads", ads_op_tuples);
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)
1101 + *vfs_version = SMB_VFS_INTERFACE_VERSION;
1102 + memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
1104 + ads_handle = vfs_handle;
1105 + DEBUG(3, ("ADS: vfs module loaded\n"));
1106 + return ads_op_tuples;
1109 +/* VFS finalization function. */
1110 +void vfs_done(connection_struct *conn)
1112 + DEBUG(3, ("ADS: vfs module unloaded\n"));