From ec91716cb79ee0ac059f29cbcc331c114313f1ef Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 18 Aug 2002 20:12:43 +0000 Subject: Add entry about block.so (This used to be commit 6973344fb5207341e98576b1ddbe58a745225e10) --- examples/VFS/README | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'examples/VFS') diff --git a/examples/VFS/README b/examples/VFS/README index c2f39f9727..7a2152fc4d 100644 --- a/examples/VFS/README +++ b/examples/VFS/README @@ -17,6 +17,13 @@ construction. The following VFS modules are given: connect/disconnect, directory opens/create/remove, file open/close/rename/unlink/chmod. + block + A simple module to block access to certain mount points or + directories. This module only hides the specified directories + and all directories beneath them. It should NOT be used to secure + directories. If the name of a file in one of those directories is + known, the file can still be opened. + The libtool program, available from your favourite GNU software archive, is required to compile these programs. -- cgit From 7251f6b9ecf6f4c797baf4cd5390cf2bf310d179 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 27 Aug 2002 09:14:21 +0000 Subject: avoid using libtool for VFS modules change a name in block.c it was hiding a function name add a comment in configure (This used to be commit 05038f44717ff07ed7d4a3afbdd8f072a3c058cc) --- examples/VFS/Makefile.in | 34 ++++++++++------------------------ examples/VFS/README | 23 +++++++++++++++++------ examples/VFS/block/Makefile.in | 34 ++++++++++------------------------ examples/VFS/block/block.c | 21 ++++++++++----------- 4 files changed, 47 insertions(+), 65 deletions(-) (limited to 'examples/VFS') diff --git a/examples/VFS/Makefile.in b/examples/VFS/Makefile.in index 3126dfa3b8..6ae4f49434 100644 --- a/examples/VFS/Makefile.in +++ b/examples/VFS/Makefile.in @@ -1,42 +1,28 @@ -MAKEFILE = Makefile.vfs - -include $(MAKEFILE) - CC = @CC@ -LIBTOOL = libtool -CFLAGS = @CFLAGS@ $(VFS_CFLAGS) -CPPFLAGS = @CPPFLAGS@ $(VFS_CPPFLAGS) -LDFLAGS = @LDFLAGS@ $(VFS_LDFLAGS) +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ LDSHFLAGS = -shared srcdir = @builddir@ FLAGS = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper -I. $(CPPFLAGS) -I$(srcdir) +VFS_OBJS = audit.so recycle.so + # Default target default: $(VFS_OBJS) -# if file doesn't exist try to create one; -# it is possible that some variables will be -# defined correctly -Makefile.vfs: - @echo -ne "VFS_OBJS\t= " > $(MAKEFILE); \ - for i in *.c; do \ - echo -n $$i" " | sed -e 's/\(.*\)\.c\(.*\)/\1\.so\2/g' >> $(MAKEFILE); \ - done; \ - echo -ne "\nVFS_CFLAGS\t= \nVFS_CPPFLAGS\t= \nVFS_LDFLAGS\t= \n" >> $(MAKEFILE) - make - # Pattern rules -%.so: %.lo - $(LIBTOOL) $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $< +%.so: %.o + $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $< -%.lo: %.c - $(LIBTOOL) $(CC) $(FLAGS) -c $< +%.o: %.c + $(CC) $(FLAGS) -c $< # Misc targets clean: rm -rf .libs rm -f core *~ *% *.bak \ - $(VFS_OBJS) $(VFS_OBJS:.so=.o) $(VFS_OBJS:.so=.lo) + $(VFS_OBJ) $(VFS_OBJS) diff --git a/examples/VFS/README b/examples/VFS/README index 7a2152fc4d..1b09929059 100644 --- a/examples/VFS/README +++ b/examples/VFS/README @@ -17,15 +17,26 @@ construction. The following VFS modules are given: connect/disconnect, directory opens/create/remove, file open/close/rename/unlink/chmod. + recycle + A recycle-bin like modules. When used any unlink call + will be intercepted and files moved to the recycle + directory nstead of beeing deleted. + block A simple module to block access to certain mount points or directories. This module only hides the specified directories - and all directories beneath them. It should NOT be used to secure - directories. If the name of a file in one of those directories is - known, the file can still be opened. - -The libtool program, available from your favourite GNU software -archive, is required to compile these programs. + and all directories beneath them. It should NOT be used to + secure directories. If the name of a file in one of those + directories is known, the file can still be opened. + + netatalk + A netatalk module, that will ease co-existence of samba and + netatalk file sharing services. + Looka t the README for more informations. + +You may have problems to compile these modules, as shared libraries are +compiled and linked in different ways on different systems. +I currently tested them against GNU/linux and IRIX. To use the VFS modules, create a share similar to the one below. The important parameter is the 'vfs object' parameter which must point to diff --git a/examples/VFS/block/Makefile.in b/examples/VFS/block/Makefile.in index 3126dfa3b8..3deb17c596 100644 --- a/examples/VFS/block/Makefile.in +++ b/examples/VFS/block/Makefile.in @@ -1,42 +1,28 @@ -MAKEFILE = Makefile.vfs - -include $(MAKEFILE) - CC = @CC@ -LIBTOOL = libtool -CFLAGS = @CFLAGS@ $(VFS_CFLAGS) -CPPFLAGS = @CPPFLAGS@ $(VFS_CPPFLAGS) -LDFLAGS = @LDFLAGS@ $(VFS_LDFLAGS) +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ LDSHFLAGS = -shared srcdir = @builddir@ FLAGS = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper -I. $(CPPFLAGS) -I$(srcdir) +VFS_OBJS = block.so + # Default target default: $(VFS_OBJS) -# if file doesn't exist try to create one; -# it is possible that some variables will be -# defined correctly -Makefile.vfs: - @echo -ne "VFS_OBJS\t= " > $(MAKEFILE); \ - for i in *.c; do \ - echo -n $$i" " | sed -e 's/\(.*\)\.c\(.*\)/\1\.so\2/g' >> $(MAKEFILE); \ - done; \ - echo -ne "\nVFS_CFLAGS\t= \nVFS_CPPFLAGS\t= \nVFS_LDFLAGS\t= \n" >> $(MAKEFILE) - make - # Pattern rules -%.so: %.lo - $(LIBTOOL) $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $< +%.so: %.o + $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $< -%.lo: %.c - $(LIBTOOL) $(CC) $(FLAGS) -c $< +%.o: %.c + $(CC) $(FLAGS) -c $< # Misc targets clean: rm -rf .libs rm -f core *~ *% *.bak \ - $(VFS_OBJS) $(VFS_OBJS:.so=.o) $(VFS_OBJS:.so=.lo) + $(VFS_OBJ) $(VFS_OBJS) diff --git a/examples/VFS/block/block.c b/examples/VFS/block/block.c index 9478b75f0f..6566bf3d8c 100644 --- a/examples/VFS/block/block.c +++ b/examples/VFS/block/block.c @@ -87,7 +87,7 @@ static BOOL get_section(char *sect); static BOOL get_parameter_value(char *param, char *value); static BOOL load_param(void); static BOOL search(struct stat *stat_buf); -static BOOL dir_search(char *link, char *dir); +static BOOL dir_search(char *linkstr, char *dir); static BOOL enter_pblock_dir(char *dir); @@ -346,12 +346,11 @@ static DIR *block_opendir(struct connection_struct *conn, char *fname) char *dir_name = NULL; struct stat stat_buf; + size_t len; - dir_name = alloca((strlen(conn->origpath) + strlen(fname) + 2) * sizeof(char)); - - pstrcpy(dir_name,conn->origpath); - pstrcat(dir_name, "/"); - strncat(dir_name, fname, strcspn(fname,"/")); + len = strlen(conn->origpath) + 1 + strcspn(fname, "/"); + asprintf(&dir_name, "%s/%s", conn->origpath, fname); + dir_name[len] = '\0'; if((lstat(dir_name,&stat_buf)) == 0) { @@ -397,13 +396,13 @@ static BOOL search(struct stat *stat_buf) * Find dir in list to block id the starting point is link from a share */ -static BOOL dir_search(char *link, char *dir) +static BOOL dir_search(char *linkstr, char *dir) { char buf[PATH_MAX +1], *ext_path; int len = 0; struct block_dir *tmp_pblock = pblock_dir; - if((len = readlink(link,buf,sizeof(buf))) == -1) + if((len = readlink(linkstr, buf, sizeof(buf))) == -1) { return TRUE; @@ -413,9 +412,9 @@ static BOOL dir_search(char *link, char *dir) } - if((ext_path = strchr(dir,'/')) != NULL) + if((ext_path = strchr(dir, '/')) != NULL) { - pstrcat(buf,&ext_path[1]); + pstrcat(buf, &ext_path[1]); len = strlen(buf); } @@ -427,7 +426,7 @@ static BOOL dir_search(char *link, char *dir) continue; } - if((strstr(buf,tmp_pblock->dir_name)) != NULL) + if((strstr(buf, tmp_pblock->dir_name)) != NULL) { return TRUE; } -- cgit From 709c7c1674f43d38e38a6616c173ec87e632971f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 27 Aug 2002 09:30:17 +0000 Subject: add the netatalk module (This used to be commit 2a156995329699c776772fe01672cfe763b3f988) --- examples/VFS/block/smb.conf | 7 - examples/VFS/netatalk/Makefile.in | 28 +++ examples/VFS/netatalk/README | 18 ++ examples/VFS/netatalk/netatalk.c | 430 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 476 insertions(+), 7 deletions(-) create mode 100644 examples/VFS/netatalk/Makefile.in create mode 100644 examples/VFS/netatalk/README create mode 100644 examples/VFS/netatalk/netatalk.c (limited to 'examples/VFS') diff --git a/examples/VFS/block/smb.conf b/examples/VFS/block/smb.conf index 368155f1f8..931196f402 100644 --- a/examples/VFS/block/smb.conf +++ b/examples/VFS/block/smb.conf @@ -4,10 +4,3 @@ browseable = yes writable = yes - - - - - - - diff --git a/examples/VFS/netatalk/Makefile.in b/examples/VFS/netatalk/Makefile.in new file mode 100644 index 0000000000..a9a5d69b51 --- /dev/null +++ b/examples/VFS/netatalk/Makefile.in @@ -0,0 +1,28 @@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LDSHFLAGS = -shared +srcdir = @builddir@ +FLAGS = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper -I. $(CPPFLAGS) -I$(srcdir) + +VFS_OBJS = netatalk.so + +# Default target + +default: $(VFS_OBJS) + +# Pattern rules + +%.so: %.o + $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $< + +%.o: %.c + $(CC) $(FLAGS) -c $< + +# Misc targets + +clean: + rm -rf .libs + rm -f core *~ *% *.bak \ + $(VFS_OBJ) $(VFS_OBJS) diff --git a/examples/VFS/netatalk/README b/examples/VFS/netatalk/README new file mode 100644 index 0000000000..70f6eea316 --- /dev/null +++ b/examples/VFS/netatalk/README @@ -0,0 +1,18 @@ +There is the new netatalk module both for HEAD. +This one has some difference from previous module: + +-- it doesn't care about creating of .AppleDouble forks, just keeps ones in +sync; + +-- if share in smb.conf doesn't contain .AppleDouble item in hide or veto +list, it will be added automatically. + +To my way of thinking, module became more lightweight and speedy. + +How to compile: + +you should place proper netatalk.c into examples/VFS/ then run 'configure' +from source/ and then run 'make' from examples/VFS/. + +add string 'vfs object = /netatlk.so' to smb.conf. It may +be defined either as global or as share-specific parameter. diff --git a/examples/VFS/netatalk/netatalk.c b/examples/VFS/netatalk/netatalk.c new file mode 100644 index 0000000000..353be36e6f --- /dev/null +++ b/examples/VFS/netatalk/netatalk.c @@ -0,0 +1,430 @@ +/* + * AppleTalk VFS module for Samba-3.x + * + * Copyright (C) Alexei Kotovich, 2002 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "config.h" +#include +#include +#ifdef HAVE_UTIME_H +#include +#endif +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#include +#include +#include +#include + +#define APPLEDOUBLE ".AppleDouble" +#define ADOUBLEMODE 0777 + +/* atalk functions */ + +static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, + const char *fname, char **adbl_path, char **orig_path, + SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info); + +static int atalk_unlink_file(const char *path); + +static struct vfs_ops default_vfs_ops; /* For passthrough operation */ +static struct smb_vfs_handle_struct *atalk_handle; + +static int atalk_get_path_ptr(char *path) +{ + int i = 0; + int ptr = 0; + + for (i = 0; path[i]; i ++) { + if (path[i] == '/') + ptr = i; + /* get out some 'spam';) from win32's file name */ + else if (path[i] == ':') { + path[i] = '\0'; + break; + } + } + + return ptr; +} + +static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, const char *fname, + char **adbl_path, char **orig_path, + SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info) +{ + int ptr0 = 0; + int ptr1 = 0; + char *dname = 0; + char *name = 0; + + if (!ctx || !path || !fname || !adbl_path || !orig_path || + !adbl_info || !orig_info) + return -1; +#if 0 + DEBUG(3, ("ATALK: PATH: %s[%s]\n", path, fname)); +#endif + if (strstr(path, APPLEDOUBLE) || strstr(fname, APPLEDOUBLE)) { + DEBUG(3, ("ATALK: path %s[%s] already contains %s\n", path, fname, APPLEDOUBLE)); + return -1; + } + + if (fname[0] == '.') ptr0 ++; + if (fname[1] == '/') ptr0 ++; + + *orig_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]); + + /* get pointer to last '/' */ + ptr1 = atalk_get_path_ptr(*orig_path); + + sys_lstat(*orig_path, orig_info); + + if (S_ISDIR(orig_info->st_mode)) { + *adbl_path = talloc_asprintf(ctx, "%s/%s/%s/", + path, &fname[ptr0], APPLEDOUBLE); + } else { + dname = talloc_strdup(ctx, *orig_path); + dname[ptr1] = '\0'; + name = *orig_path; + *adbl_path = talloc_asprintf(ctx, "%s/%s/%s", + dname, APPLEDOUBLE, &name[ptr1 + 1]); + } +#if 0 + DEBUG(3, ("ATALK: DEBUG:\n%s\n%s\n", *orig_path, *adbl_path)); +#endif + sys_lstat(*adbl_path, adbl_info); + return 0; +} + +static int atalk_unlink_file(const char *path) +{ + int ret = 0; + + become_root(); + ret = unlink(path); + unbecome_root(); + + return ret; +} + +static void atalk_add_to_list(name_compare_entry **list) +{ + int i, count = 0; + name_compare_entry *new_list = 0; + name_compare_entry *cur_list = 0; + + cur_list = *list; + + if (cur_list) { + for (i = 0, count = 0; cur_list[i].name; i ++, count ++) { + if (strstr(cur_list[i].name, APPLEDOUBLE)) + return; + } + } + + if (!(new_list = calloc(1, + (count == 0 ? 1 : count + 1) * sizeof(name_compare_entry)))) + return; + + for (i = 0; i < count; i ++) { + new_list[i].name = strdup(cur_list[i].name); + new_list[i].is_wild = cur_list[i].is_wild; + } + + new_list[i].name = strdup(APPLEDOUBLE); + new_list[i].is_wild = False; + + free_namearray(*list); + + *list = new_list; + new_list = 0; + cur_list = 0; +} + +static void atalk_rrmdir(TALLOC_CTX *ctx, char *path) +{ + int n; + char *dpath; + struct dirent **namelist; + + if (!path) return; + + n = scandir(path, &namelist, 0, alphasort); + if (n < 0) { + return; + } else { + while (n --) { + if (strcmp(namelist[n]->d_name, ".") == 0 || + strcmp(namelist[n]->d_name, "..") == 0) + continue; + if (!(dpath = talloc_asprintf(ctx, "%s/%s", + path, namelist[n]->d_name))) + continue; + atalk_unlink_file(dpath); + free(namelist[n]); + } + } +} + +/* Disk operations */ + +/* Directory operations */ + +DIR *atalk_opendir(struct connection_struct *conn, const char *fname) +{ + DIR *ret = 0; + + ret = default_vfs_ops.opendir(conn, fname); + + /* + * when we try to perform delete operation upon file which has fork + * in ./.AppleDouble and this directory wasn't hidden by Samba, + * MS Windows explorer causes the error: "Cannot find the specified file" + * There is some workaround to avoid this situation, i.e. if + * connection has not .AppleDouble entry in either veto or hide + * list then it would be nice to add one. + */ + + atalk_add_to_list(&conn->hide_list); + atalk_add_to_list(&conn->veto_list); + + return ret; +} + +static int atalk_rmdir(struct connection_struct *conn, const char *path) +{ + BOOL add = False; + TALLOC_CTX *ctx = 0; + char *dpath; + + if (!conn || !conn->origpath || !path) goto exit_rmdir; + + /* due to there is no way to change bDeleteVetoFiles variable + * from this module, gotta use talloc stuff.. + */ + + strstr(path, APPLEDOUBLE) ? (add = False) : (add = True); + + if (!(ctx = talloc_init_named("remove_directory"))) + goto exit_rmdir; + + if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", + conn->origpath, path, add ? "/"APPLEDOUBLE : ""))) + goto exit_rmdir; + + atalk_rrmdir(ctx, dpath); + +exit_rmdir: + talloc_destroy(ctx); + return default_vfs_ops.rmdir(conn, path); +} + +/* File operations */ + +static int atalk_rename(struct connection_struct *conn, const char *old, const char *new) +{ + int ret = 0; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.rename(conn, old, new); + + if (!conn || !old) return ret; + + if (!(ctx = talloc_init_named("rename_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, old, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); + goto exit_rename; + } + + atalk_unlink_file(adbl_path); + +exit_rename: + talloc_destroy(ctx); + return ret; +} + +static int atalk_unlink(struct connection_struct *conn, const char *path) +{ + int ret = 0, i; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.unlink(conn, path); + + if (!conn || !path) return ret; + + /* no .AppleDouble sync if veto or hide list is empty, + * otherwise "Cannot find the specified file" error will be caused + */ + + if (!conn->veto_list) return ret; + if (!conn->hide_list) return ret; + + for (i = 0; conn->veto_list[i].name; i ++) { + if (strstr(conn->veto_list[i].name, APPLEDOUBLE)) + break; + } + + if (!conn->veto_list[i].name) { + for (i = 0; conn->hide_list[i].name; i ++) { + if (strstr(conn->hide_list[i].name, APPLEDOUBLE)) + break; + else { + DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", + APPLEDOUBLE)); + return ret; + } + } + } + + if (!(ctx = talloc_init_named("unlink_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); + goto exit_unlink; + } + + atalk_unlink_file(adbl_path); + +exit_unlink: + talloc_destroy(ctx); + return ret; +} + +static int atalk_chmod(struct connection_struct *conn, const char *path, mode_t mode) +{ + int ret = 0; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.chmod(conn, path, mode); + + if (!conn || !path) return ret; + + if (!(ctx = talloc_init_named("chmod_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); + goto exit_chmod; + } + + chmod(adbl_path, ADOUBLEMODE); + +exit_chmod: + talloc_destroy(ctx); + return ret; +} + +static int atalk_chown(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid) +{ + int ret = 0; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.chown(conn, path, uid, gid); + + if (!conn || !path) return ret; + + if (!(ctx = talloc_init_named("chown_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); + goto exit_chown; + } + + chown(adbl_path, uid, gid); + +exit_chown: + talloc_destroy(ctx); + return ret; +} + +static vfs_op_tuple atalk_ops[] = { + + /* Directory operations */ + + {atalk_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, + + /* File operations */ + + {atalk_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_chown, SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, + + /* Finish VFS operations definition */ + + {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ +vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, + struct smb_vfs_handle_struct *vfs_handle) +{ + *vfs_version = SMB_VFS_INTERFACE_VERSION; + memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); + + atalk_handle = vfs_handle; + + DEBUG(3, ("ATALK: vfs module loaded\n")); + return atalk_ops; +} + +/* VFS finalization function. */ +void vfs_done(connection_struct *conn) +{ + DEBUG(3, ("ATALK: vfs module unloaded\n")); +} -- cgit From 995bf62aae0329750b2fff62db4f2b113a9f93e0 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 27 Aug 2002 09:45:26 +0000 Subject: patch from metze (This used to be commit cc8e6ebc0ec840d882211c8327cafdcafbcafbd7) --- examples/VFS/recycle.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'examples/VFS') diff --git a/examples/VFS/recycle.c b/examples/VFS/recycle.c index ed89e59abf..0a261c20df 100644 --- a/examples/VFS/recycle.c +++ b/examples/VFS/recycle.c @@ -57,7 +57,7 @@ static vfs_op_tuple recycle_ops[] = { /* File operations */ {recycle_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_OPAQUE}, - + {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; @@ -68,6 +68,8 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, { *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); + + DEBUG(5,("vfs_init: for recycle!\n")); /* Remember vfs_id for storing private information at connect */ recycle_handle = vfs_handle; @@ -78,20 +80,23 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, /* VFS finalization function. */ void vfs_done(connection_struct *conn) { - DEBUG(3,("vfs_done_recycle: called for connection %p\n",conn)); + DEBUG(5,("vfs_done_recycle: called for connection %p\n",conn)); } static int recycle_connect(struct connection_struct *conn, const char *service, const char *user) { fstring recycle_bin; - DEBUG(3,("recycle_connect: called for service %s as user %s\n", service, user)); + DEBUG(4,("recycle_connect: called for service %s as user %s\n", service, user)); fstrcpy(recycle_bin, (const char *)lp_parm_string(lp_servicename(SNUM(conn)),"vfs","recycle bin")); if (!*recycle_bin) { - DEBUG(3,("recycle_connect: No options listed (vfs:recycle bin).\n" )); + DEBUG(0,("recycle_connect: No options listed (vfs:recycle bin).\n" )); return 0; /* No options. */ } + + standard_sub_conn(conn,recycle_bin,sizeof(fstring)); + DEBUG(3,("recycle_connect: recycle name is %s\n", recycle_bin )); @@ -158,7 +163,7 @@ static int recycle_unlink(connection_struct *conn, const char *inname) fstrcpy(recycle_bin, (const char *)recycle_handle->data); if(!*recycle_bin) { - DEBUG(3, ("recycle bin: share parameter not set, purging %s...\n", fname)); + DEBUG(1, ("recycle bin: share parameter not set, purging %s...\n", fname)); return default_vfs_ops.unlink(conn,fname); } @@ -178,7 +183,7 @@ static int recycle_unlink(connection_struct *conn, const char *inname) ext = strrchr(base, '.'); pstrcat(bin, base+1); } - DEBUG(3, ("recycle bin: base %s, ext %s, fname %s, bin %s\n", base, ext, fname, bin)); + DEBUG(4, ("recycle bin: base %s, ext %s, fname %s, bin %s\n", base, ext, fname, bin)); if(strcmp(fname,bin) == 0) { DEBUG(3, ("recycle bin: file %s exists, purging...\n", fname)); @@ -202,7 +207,7 @@ static int recycle_unlink(connection_struct *conn, const char *inname) if(!recycle_directory_exist(conn,recycle_bin)) { DEBUG(3, ("recycle bin: directory %s nonexistant, creating...\n", recycle_bin)); if (default_vfs_ops.mkdir(conn,recycle_bin,dir_mask) == -1) { - DEBUG(3, ("recycle bin: unable to create directory %s. Error was %s\n", + DEBUG(0, ("recycle bin: unable to create directory %s. Error was %s\n", recycle_bin, strerror(errno) )); } } @@ -210,13 +215,13 @@ static int recycle_unlink(connection_struct *conn, const char *inname) ret = default_vfs_ops.rename(conn, fname, bin); if (ret == -1) { - DEBUG(3, ("recycle bin: move error %d (%s)\n", errno, strerror(errno) )); - DEBUG(3, ("recycle bin: move failed, purging...\n")); + DEBUG(1, ("recycle bin: move error %d (%s)\n", errno, strerror(errno) )); + DEBUG(0, ("recycle bin: move failed, purging...\n")); return default_vfs_ops.unlink(conn,fname); } return ret; } else { - DEBUG(3, ("recycle bin: move failed, purging...\n")); + DEBUG(1, ("recycle bin: move failed, purging...\n")); return default_vfs_ops.unlink(conn,fname); } } -- cgit From 84a8efbf1a14e9ce36aa4347ada8973392e96330 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 28 Aug 2002 12:55:20 +0000 Subject: Removed C++ style comment. Jeremy. (This used to be commit 3803770edaf4212ceac826e039bb075f098a4fab) --- examples/VFS/block/block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/VFS') diff --git a/examples/VFS/block/block.c b/examples/VFS/block/block.c index 6566bf3d8c..eb388a97ea 100644 --- a/examples/VFS/block/block.c +++ b/examples/VFS/block/block.c @@ -80,7 +80,7 @@ static vfs_op_tuple block_vfs_ops[] = { extern BOOL pm_process(char *FileName, BOOL (*sfunc)(char *), BOOL(*pfunc)(char * , char *)); -//functions +/* functions */ static BOOL enter_pblock_mount(char *dir); static BOOL get_section(char *sect); -- cgit From afc1a220b74bfbfa68541d3595038bcf138606c0 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 6 Sep 2002 13:37:40 +0000 Subject: move everything to flat VFS/ directory (This used to be commit d383c309d4a259fb28d7541777a8b3b53cca23bf) --- examples/VFS/Makefile.in | 2 +- examples/VFS/README.netatalk | 18 ++ examples/VFS/netatalk.c | 430 ++++++++++++++++++++++++++++++++++++++ examples/VFS/netatalk/Makefile.in | 28 --- examples/VFS/netatalk/README | 18 -- examples/VFS/netatalk/netatalk.c | 430 -------------------------------------- 6 files changed, 449 insertions(+), 477 deletions(-) create mode 100644 examples/VFS/README.netatalk create mode 100644 examples/VFS/netatalk.c delete mode 100644 examples/VFS/netatalk/Makefile.in delete mode 100644 examples/VFS/netatalk/README delete mode 100644 examples/VFS/netatalk/netatalk.c (limited to 'examples/VFS') diff --git a/examples/VFS/Makefile.in b/examples/VFS/Makefile.in index 6ae4f49434..2ffd23b853 100644 --- a/examples/VFS/Makefile.in +++ b/examples/VFS/Makefile.in @@ -6,7 +6,7 @@ LDSHFLAGS = -shared srcdir = @builddir@ FLAGS = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper -I. $(CPPFLAGS) -I$(srcdir) -VFS_OBJS = audit.so recycle.so +VFS_OBJS = audit.so recycle.so netatalk.so # Default target diff --git a/examples/VFS/README.netatalk b/examples/VFS/README.netatalk new file mode 100644 index 0000000000..70f6eea316 --- /dev/null +++ b/examples/VFS/README.netatalk @@ -0,0 +1,18 @@ +There is the new netatalk module both for HEAD. +This one has some difference from previous module: + +-- it doesn't care about creating of .AppleDouble forks, just keeps ones in +sync; + +-- if share in smb.conf doesn't contain .AppleDouble item in hide or veto +list, it will be added automatically. + +To my way of thinking, module became more lightweight and speedy. + +How to compile: + +you should place proper netatalk.c into examples/VFS/ then run 'configure' +from source/ and then run 'make' from examples/VFS/. + +add string 'vfs object = /netatlk.so' to smb.conf. It may +be defined either as global or as share-specific parameter. diff --git a/examples/VFS/netatalk.c b/examples/VFS/netatalk.c new file mode 100644 index 0000000000..353be36e6f --- /dev/null +++ b/examples/VFS/netatalk.c @@ -0,0 +1,430 @@ +/* + * AppleTalk VFS module for Samba-3.x + * + * Copyright (C) Alexei Kotovich, 2002 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "config.h" +#include +#include +#ifdef HAVE_UTIME_H +#include +#endif +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#include +#include +#include +#include + +#define APPLEDOUBLE ".AppleDouble" +#define ADOUBLEMODE 0777 + +/* atalk functions */ + +static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, + const char *fname, char **adbl_path, char **orig_path, + SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info); + +static int atalk_unlink_file(const char *path); + +static struct vfs_ops default_vfs_ops; /* For passthrough operation */ +static struct smb_vfs_handle_struct *atalk_handle; + +static int atalk_get_path_ptr(char *path) +{ + int i = 0; + int ptr = 0; + + for (i = 0; path[i]; i ++) { + if (path[i] == '/') + ptr = i; + /* get out some 'spam';) from win32's file name */ + else if (path[i] == ':') { + path[i] = '\0'; + break; + } + } + + return ptr; +} + +static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, const char *fname, + char **adbl_path, char **orig_path, + SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info) +{ + int ptr0 = 0; + int ptr1 = 0; + char *dname = 0; + char *name = 0; + + if (!ctx || !path || !fname || !adbl_path || !orig_path || + !adbl_info || !orig_info) + return -1; +#if 0 + DEBUG(3, ("ATALK: PATH: %s[%s]\n", path, fname)); +#endif + if (strstr(path, APPLEDOUBLE) || strstr(fname, APPLEDOUBLE)) { + DEBUG(3, ("ATALK: path %s[%s] already contains %s\n", path, fname, APPLEDOUBLE)); + return -1; + } + + if (fname[0] == '.') ptr0 ++; + if (fname[1] == '/') ptr0 ++; + + *orig_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]); + + /* get pointer to last '/' */ + ptr1 = atalk_get_path_ptr(*orig_path); + + sys_lstat(*orig_path, orig_info); + + if (S_ISDIR(orig_info->st_mode)) { + *adbl_path = talloc_asprintf(ctx, "%s/%s/%s/", + path, &fname[ptr0], APPLEDOUBLE); + } else { + dname = talloc_strdup(ctx, *orig_path); + dname[ptr1] = '\0'; + name = *orig_path; + *adbl_path = talloc_asprintf(ctx, "%s/%s/%s", + dname, APPLEDOUBLE, &name[ptr1 + 1]); + } +#if 0 + DEBUG(3, ("ATALK: DEBUG:\n%s\n%s\n", *orig_path, *adbl_path)); +#endif + sys_lstat(*adbl_path, adbl_info); + return 0; +} + +static int atalk_unlink_file(const char *path) +{ + int ret = 0; + + become_root(); + ret = unlink(path); + unbecome_root(); + + return ret; +} + +static void atalk_add_to_list(name_compare_entry **list) +{ + int i, count = 0; + name_compare_entry *new_list = 0; + name_compare_entry *cur_list = 0; + + cur_list = *list; + + if (cur_list) { + for (i = 0, count = 0; cur_list[i].name; i ++, count ++) { + if (strstr(cur_list[i].name, APPLEDOUBLE)) + return; + } + } + + if (!(new_list = calloc(1, + (count == 0 ? 1 : count + 1) * sizeof(name_compare_entry)))) + return; + + for (i = 0; i < count; i ++) { + new_list[i].name = strdup(cur_list[i].name); + new_list[i].is_wild = cur_list[i].is_wild; + } + + new_list[i].name = strdup(APPLEDOUBLE); + new_list[i].is_wild = False; + + free_namearray(*list); + + *list = new_list; + new_list = 0; + cur_list = 0; +} + +static void atalk_rrmdir(TALLOC_CTX *ctx, char *path) +{ + int n; + char *dpath; + struct dirent **namelist; + + if (!path) return; + + n = scandir(path, &namelist, 0, alphasort); + if (n < 0) { + return; + } else { + while (n --) { + if (strcmp(namelist[n]->d_name, ".") == 0 || + strcmp(namelist[n]->d_name, "..") == 0) + continue; + if (!(dpath = talloc_asprintf(ctx, "%s/%s", + path, namelist[n]->d_name))) + continue; + atalk_unlink_file(dpath); + free(namelist[n]); + } + } +} + +/* Disk operations */ + +/* Directory operations */ + +DIR *atalk_opendir(struct connection_struct *conn, const char *fname) +{ + DIR *ret = 0; + + ret = default_vfs_ops.opendir(conn, fname); + + /* + * when we try to perform delete operation upon file which has fork + * in ./.AppleDouble and this directory wasn't hidden by Samba, + * MS Windows explorer causes the error: "Cannot find the specified file" + * There is some workaround to avoid this situation, i.e. if + * connection has not .AppleDouble entry in either veto or hide + * list then it would be nice to add one. + */ + + atalk_add_to_list(&conn->hide_list); + atalk_add_to_list(&conn->veto_list); + + return ret; +} + +static int atalk_rmdir(struct connection_struct *conn, const char *path) +{ + BOOL add = False; + TALLOC_CTX *ctx = 0; + char *dpath; + + if (!conn || !conn->origpath || !path) goto exit_rmdir; + + /* due to there is no way to change bDeleteVetoFiles variable + * from this module, gotta use talloc stuff.. + */ + + strstr(path, APPLEDOUBLE) ? (add = False) : (add = True); + + if (!(ctx = talloc_init_named("remove_directory"))) + goto exit_rmdir; + + if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", + conn->origpath, path, add ? "/"APPLEDOUBLE : ""))) + goto exit_rmdir; + + atalk_rrmdir(ctx, dpath); + +exit_rmdir: + talloc_destroy(ctx); + return default_vfs_ops.rmdir(conn, path); +} + +/* File operations */ + +static int atalk_rename(struct connection_struct *conn, const char *old, const char *new) +{ + int ret = 0; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.rename(conn, old, new); + + if (!conn || !old) return ret; + + if (!(ctx = talloc_init_named("rename_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, old, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); + goto exit_rename; + } + + atalk_unlink_file(adbl_path); + +exit_rename: + talloc_destroy(ctx); + return ret; +} + +static int atalk_unlink(struct connection_struct *conn, const char *path) +{ + int ret = 0, i; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.unlink(conn, path); + + if (!conn || !path) return ret; + + /* no .AppleDouble sync if veto or hide list is empty, + * otherwise "Cannot find the specified file" error will be caused + */ + + if (!conn->veto_list) return ret; + if (!conn->hide_list) return ret; + + for (i = 0; conn->veto_list[i].name; i ++) { + if (strstr(conn->veto_list[i].name, APPLEDOUBLE)) + break; + } + + if (!conn->veto_list[i].name) { + for (i = 0; conn->hide_list[i].name; i ++) { + if (strstr(conn->hide_list[i].name, APPLEDOUBLE)) + break; + else { + DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", + APPLEDOUBLE)); + return ret; + } + } + } + + if (!(ctx = talloc_init_named("unlink_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); + goto exit_unlink; + } + + atalk_unlink_file(adbl_path); + +exit_unlink: + talloc_destroy(ctx); + return ret; +} + +static int atalk_chmod(struct connection_struct *conn, const char *path, mode_t mode) +{ + int ret = 0; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.chmod(conn, path, mode); + + if (!conn || !path) return ret; + + if (!(ctx = talloc_init_named("chmod_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); + goto exit_chmod; + } + + chmod(adbl_path, ADOUBLEMODE); + +exit_chmod: + talloc_destroy(ctx); + return ret; +} + +static int atalk_chown(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid) +{ + int ret = 0; + char *adbl_path = 0; + char *orig_path = 0; + SMB_STRUCT_STAT adbl_info; + SMB_STRUCT_STAT orig_info; + TALLOC_CTX *ctx; + + ret = default_vfs_ops.chown(conn, path, uid, gid); + + if (!conn || !path) return ret; + + if (!(ctx = talloc_init_named("chown_file"))) + return ret; + + if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + return ret; + + if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { + DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); + goto exit_chown; + } + + chown(adbl_path, uid, gid); + +exit_chown: + talloc_destroy(ctx); + return ret; +} + +static vfs_op_tuple atalk_ops[] = { + + /* Directory operations */ + + {atalk_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, + + /* File operations */ + + {atalk_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, + {atalk_chown, SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, + + /* Finish VFS operations definition */ + + {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ +vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, + struct smb_vfs_handle_struct *vfs_handle) +{ + *vfs_version = SMB_VFS_INTERFACE_VERSION; + memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); + + atalk_handle = vfs_handle; + + DEBUG(3, ("ATALK: vfs module loaded\n")); + return atalk_ops; +} + +/* VFS finalization function. */ +void vfs_done(connection_struct *conn) +{ + DEBUG(3, ("ATALK: vfs module unloaded\n")); +} diff --git a/examples/VFS/netatalk/Makefile.in b/examples/VFS/netatalk/Makefile.in deleted file mode 100644 index a9a5d69b51..0000000000 --- a/examples/VFS/netatalk/Makefile.in +++ /dev/null @@ -1,28 +0,0 @@ -CC = @CC@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LDSHFLAGS = -shared -srcdir = @builddir@ -FLAGS = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper -I. $(CPPFLAGS) -I$(srcdir) - -VFS_OBJS = netatalk.so - -# Default target - -default: $(VFS_OBJS) - -# Pattern rules - -%.so: %.o - $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $< - -%.o: %.c - $(CC) $(FLAGS) -c $< - -# Misc targets - -clean: - rm -rf .libs - rm -f core *~ *% *.bak \ - $(VFS_OBJ) $(VFS_OBJS) diff --git a/examples/VFS/netatalk/README b/examples/VFS/netatalk/README deleted file mode 100644 index 70f6eea316..0000000000 --- a/examples/VFS/netatalk/README +++ /dev/null @@ -1,18 +0,0 @@ -There is the new netatalk module both for HEAD. -This one has some difference from previous module: - --- it doesn't care about creating of .AppleDouble forks, just keeps ones in -sync; - --- if share in smb.conf doesn't contain .AppleDouble item in hide or veto -list, it will be added automatically. - -To my way of thinking, module became more lightweight and speedy. - -How to compile: - -you should place proper netatalk.c into examples/VFS/ then run 'configure' -from source/ and then run 'make' from examples/VFS/. - -add string 'vfs object = /netatlk.so' to smb.conf. It may -be defined either as global or as share-specific parameter. diff --git a/examples/VFS/netatalk/netatalk.c b/examples/VFS/netatalk/netatalk.c deleted file mode 100644 index 353be36e6f..0000000000 --- a/examples/VFS/netatalk/netatalk.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * AppleTalk VFS module for Samba-3.x - * - * Copyright (C) Alexei Kotovich, 2002 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "config.h" -#include -#include -#ifdef HAVE_UTIME_H -#include -#endif -#ifdef HAVE_DIRENT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#include -#include -#include -#include - -#define APPLEDOUBLE ".AppleDouble" -#define ADOUBLEMODE 0777 - -/* atalk functions */ - -static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, - const char *fname, char **adbl_path, char **orig_path, - SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info); - -static int atalk_unlink_file(const char *path); - -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *atalk_handle; - -static int atalk_get_path_ptr(char *path) -{ - int i = 0; - int ptr = 0; - - for (i = 0; path[i]; i ++) { - if (path[i] == '/') - ptr = i; - /* get out some 'spam';) from win32's file name */ - else if (path[i] == ':') { - path[i] = '\0'; - break; - } - } - - return ptr; -} - -static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, const char *fname, - char **adbl_path, char **orig_path, - SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info) -{ - int ptr0 = 0; - int ptr1 = 0; - char *dname = 0; - char *name = 0; - - if (!ctx || !path || !fname || !adbl_path || !orig_path || - !adbl_info || !orig_info) - return -1; -#if 0 - DEBUG(3, ("ATALK: PATH: %s[%s]\n", path, fname)); -#endif - if (strstr(path, APPLEDOUBLE) || strstr(fname, APPLEDOUBLE)) { - DEBUG(3, ("ATALK: path %s[%s] already contains %s\n", path, fname, APPLEDOUBLE)); - return -1; - } - - if (fname[0] == '.') ptr0 ++; - if (fname[1] == '/') ptr0 ++; - - *orig_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]); - - /* get pointer to last '/' */ - ptr1 = atalk_get_path_ptr(*orig_path); - - sys_lstat(*orig_path, orig_info); - - if (S_ISDIR(orig_info->st_mode)) { - *adbl_path = talloc_asprintf(ctx, "%s/%s/%s/", - path, &fname[ptr0], APPLEDOUBLE); - } else { - dname = talloc_strdup(ctx, *orig_path); - dname[ptr1] = '\0'; - name = *orig_path; - *adbl_path = talloc_asprintf(ctx, "%s/%s/%s", - dname, APPLEDOUBLE, &name[ptr1 + 1]); - } -#if 0 - DEBUG(3, ("ATALK: DEBUG:\n%s\n%s\n", *orig_path, *adbl_path)); -#endif - sys_lstat(*adbl_path, adbl_info); - return 0; -} - -static int atalk_unlink_file(const char *path) -{ - int ret = 0; - - become_root(); - ret = unlink(path); - unbecome_root(); - - return ret; -} - -static void atalk_add_to_list(name_compare_entry **list) -{ - int i, count = 0; - name_compare_entry *new_list = 0; - name_compare_entry *cur_list = 0; - - cur_list = *list; - - if (cur_list) { - for (i = 0, count = 0; cur_list[i].name; i ++, count ++) { - if (strstr(cur_list[i].name, APPLEDOUBLE)) - return; - } - } - - if (!(new_list = calloc(1, - (count == 0 ? 1 : count + 1) * sizeof(name_compare_entry)))) - return; - - for (i = 0; i < count; i ++) { - new_list[i].name = strdup(cur_list[i].name); - new_list[i].is_wild = cur_list[i].is_wild; - } - - new_list[i].name = strdup(APPLEDOUBLE); - new_list[i].is_wild = False; - - free_namearray(*list); - - *list = new_list; - new_list = 0; - cur_list = 0; -} - -static void atalk_rrmdir(TALLOC_CTX *ctx, char *path) -{ - int n; - char *dpath; - struct dirent **namelist; - - if (!path) return; - - n = scandir(path, &namelist, 0, alphasort); - if (n < 0) { - return; - } else { - while (n --) { - if (strcmp(namelist[n]->d_name, ".") == 0 || - strcmp(namelist[n]->d_name, "..") == 0) - continue; - if (!(dpath = talloc_asprintf(ctx, "%s/%s", - path, namelist[n]->d_name))) - continue; - atalk_unlink_file(dpath); - free(namelist[n]); - } - } -} - -/* Disk operations */ - -/* Directory operations */ - -DIR *atalk_opendir(struct connection_struct *conn, const char *fname) -{ - DIR *ret = 0; - - ret = default_vfs_ops.opendir(conn, fname); - - /* - * when we try to perform delete operation upon file which has fork - * in ./.AppleDouble and this directory wasn't hidden by Samba, - * MS Windows explorer causes the error: "Cannot find the specified file" - * There is some workaround to avoid this situation, i.e. if - * connection has not .AppleDouble entry in either veto or hide - * list then it would be nice to add one. - */ - - atalk_add_to_list(&conn->hide_list); - atalk_add_to_list(&conn->veto_list); - - return ret; -} - -static int atalk_rmdir(struct connection_struct *conn, const char *path) -{ - BOOL add = False; - TALLOC_CTX *ctx = 0; - char *dpath; - - if (!conn || !conn->origpath || !path) goto exit_rmdir; - - /* due to there is no way to change bDeleteVetoFiles variable - * from this module, gotta use talloc stuff.. - */ - - strstr(path, APPLEDOUBLE) ? (add = False) : (add = True); - - if (!(ctx = talloc_init_named("remove_directory"))) - goto exit_rmdir; - - if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", - conn->origpath, path, add ? "/"APPLEDOUBLE : ""))) - goto exit_rmdir; - - atalk_rrmdir(ctx, dpath); - -exit_rmdir: - talloc_destroy(ctx); - return default_vfs_ops.rmdir(conn, path); -} - -/* File operations */ - -static int atalk_rename(struct connection_struct *conn, const char *old, const char *new) -{ - int ret = 0; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.rename(conn, old, new); - - if (!conn || !old) return ret; - - if (!(ctx = talloc_init_named("rename_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, old, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); - goto exit_rename; - } - - atalk_unlink_file(adbl_path); - -exit_rename: - talloc_destroy(ctx); - return ret; -} - -static int atalk_unlink(struct connection_struct *conn, const char *path) -{ - int ret = 0, i; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.unlink(conn, path); - - if (!conn || !path) return ret; - - /* no .AppleDouble sync if veto or hide list is empty, - * otherwise "Cannot find the specified file" error will be caused - */ - - if (!conn->veto_list) return ret; - if (!conn->hide_list) return ret; - - for (i = 0; conn->veto_list[i].name; i ++) { - if (strstr(conn->veto_list[i].name, APPLEDOUBLE)) - break; - } - - if (!conn->veto_list[i].name) { - for (i = 0; conn->hide_list[i].name; i ++) { - if (strstr(conn->hide_list[i].name, APPLEDOUBLE)) - break; - else { - DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", - APPLEDOUBLE)); - return ret; - } - } - } - - if (!(ctx = talloc_init_named("unlink_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); - goto exit_unlink; - } - - atalk_unlink_file(adbl_path); - -exit_unlink: - talloc_destroy(ctx); - return ret; -} - -static int atalk_chmod(struct connection_struct *conn, const char *path, mode_t mode) -{ - int ret = 0; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.chmod(conn, path, mode); - - if (!conn || !path) return ret; - - if (!(ctx = talloc_init_named("chmod_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); - goto exit_chmod; - } - - chmod(adbl_path, ADOUBLEMODE); - -exit_chmod: - talloc_destroy(ctx); - return ret; -} - -static int atalk_chown(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid) -{ - int ret = 0; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.chown(conn, path, uid, gid); - - if (!conn || !path) return ret; - - if (!(ctx = talloc_init_named("chown_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); - goto exit_chown; - } - - chown(adbl_path, uid, gid); - -exit_chown: - talloc_destroy(ctx); - return ret; -} - -static vfs_op_tuple atalk_ops[] = { - - /* Directory operations */ - - {atalk_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, - - /* File operations */ - - {atalk_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_chown, SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, - - /* Finish VFS operations definition */ - - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} -}; - -/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - *vfs_version = SMB_VFS_INTERFACE_VERSION; - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - atalk_handle = vfs_handle; - - DEBUG(3, ("ATALK: vfs module loaded\n")); - return atalk_ops; -} - -/* VFS finalization function. */ -void vfs_done(connection_struct *conn) -{ - DEBUG(3, ("ATALK: vfs module unloaded\n")); -} -- cgit From d0cef25c27d180b6f864e942058e1b6805971a76 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 6 Sep 2002 13:39:46 +0000 Subject: the current block module is completely broken, jelmer will commit a new one later. simo (This used to be commit 830f9910bb77562aa2dbef2f479c01493928692d) --- examples/VFS/block/Makefile.in | 28 --- examples/VFS/block/block.c | 439 ------------------------------------ examples/VFS/block/samba-block.conf | 6 - examples/VFS/block/smb.conf | 6 - 4 files changed, 479 deletions(-) delete mode 100644 examples/VFS/block/Makefile.in delete mode 100644 examples/VFS/block/block.c delete mode 100644 examples/VFS/block/samba-block.conf delete mode 100644 examples/VFS/block/smb.conf (limited to 'examples/VFS') diff --git a/examples/VFS/block/Makefile.in b/examples/VFS/block/Makefile.in deleted file mode 100644 index 3deb17c596..0000000000 --- a/examples/VFS/block/Makefile.in +++ /dev/null @@ -1,28 +0,0 @@ -CC = @CC@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LDSHFLAGS = -shared -srcdir = @builddir@ -FLAGS = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper -I. $(CPPFLAGS) -I$(srcdir) - -VFS_OBJS = block.so - -# Default target - -default: $(VFS_OBJS) - -# Pattern rules - -%.so: %.o - $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $< - -%.o: %.c - $(CC) $(FLAGS) -c $< - -# Misc targets - -clean: - rm -rf .libs - rm -f core *~ *% *.bak \ - $(VFS_OBJ) $(VFS_OBJS) diff --git a/examples/VFS/block/block.c b/examples/VFS/block/block.c deleted file mode 100644 index eb388a97ea..0000000000 --- a/examples/VFS/block/block.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * - * Block access from links to dev mount points specified in PARAMCONF file - * - * Copyright (C) Ronald Kuetemeier, 2001 - * Copyright (C) Alexander Bokovoy, 2002 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef HAVE_UTIME_H -#include -#endif -#ifdef HAVE_DIRENT_H -#include -#endif -#include -#ifdef HAVE_FCNTL_H -#include -#endif - - -#include -#include - - - -static DIR *block_opendir(connection_struct *conn, char *fname); -static int block_connect(connection_struct *conn, const char *service, const char *user); -static void block_disconnect(connection_struct *conn); - -static struct smb_vfs_handle_struct *block_handle; - -/* VFS operations */ - - -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ - -static vfs_op_tuple block_vfs_ops[] = { - - /* Disk operations */ - - {block_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, - {block_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, - - /* Directory operations */ - - {block_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, - - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} -}; - - -#ifndef PARAMCONF -#define PARAMCONF "/etc/samba-block.conf" -#endif - -extern BOOL pm_process(char *FileName, BOOL (*sfunc)(char *), BOOL(*pfunc)(char * , char *)); - -/* functions */ - -static BOOL enter_pblock_mount(char *dir); -static BOOL get_section(char *sect); -static BOOL get_parameter_value(char *param, char *value); -static BOOL load_param(void); -static BOOL search(struct stat *stat_buf); -static BOOL dir_search(char *linkstr, char *dir); -static BOOL enter_pblock_dir(char *dir); - - - -typedef struct block_dir -{ - dev_t st_dev; - int str_len; - char *dir_name; - struct block_dir *next; -} block_dir; - - -static char *params[] = {"mount_point","dir_name"}; -enum { MOUNT_POINT , DIR_NAME }; - -static struct block_dir *pblock_mountp = NULL; -static struct block_dir *pblock_dir = NULL; - - - -/* - * Load the conf file into a table - */ - -static BOOL load_param(void) -{ - - if ((pm_process(PARAMCONF,&get_section,&get_parameter_value)) == TRUE) - { - return TRUE; - - } - return FALSE; -} - - - -/* - * Enter the key and data into the list - * - */ - -static BOOL enter_pblock_mount(char *dir) -{ - struct stat stat_buf; - static struct block_dir *tmp_pblock; - - - if((stat(dir,&stat_buf)) != 0) - { - return FALSE; - } - - if(pblock_mountp == NULL) - { - pblock_mountp = calloc(1, sizeof(block_dir)); - if( pblock_mountp == NULL) - { - return FALSE; - } - tmp_pblock = pblock_mountp; - tmp_pblock->next = NULL; - - }else - { - tmp_pblock->next = calloc(1, sizeof(block_dir)); - if(tmp_pblock->next == NULL) - { - return FALSE; - } - tmp_pblock = tmp_pblock->next; - tmp_pblock->next = NULL; - - } - - - tmp_pblock->st_dev = stat_buf.st_dev; - tmp_pblock->dir_name = strdup(dir); - - - return TRUE; - -} - - -/* - * Enter the key and data into the list - * - */ - -static BOOL enter_pblock_dir(char *dir) -{ - static struct block_dir *tmp_pblock; - - - if(pblock_dir == NULL) - { - pblock_dir = calloc(1, sizeof(block_dir)); - if( pblock_dir == NULL) - { - return FALSE; - } - tmp_pblock = pblock_dir; - tmp_pblock->next = NULL; - - }else - { - tmp_pblock->next = calloc(1, sizeof(block_dir)); - if(tmp_pblock->next == NULL) - { - return FALSE; - } - tmp_pblock = tmp_pblock->next; - tmp_pblock->next = NULL; - - } - - - tmp_pblock->dir_name = strdup(dir); - tmp_pblock->str_len = strlen(dir); - - - return TRUE; - -} - - - - -/* - * Function callback for config section names - */ - -static BOOL get_section(char *sect) -{ - return TRUE; -} - - - -/* - * Function callback for config parameter value pairs - * - */ - -static BOOL get_parameter_value(char *param, char *value) -{ - int i = 0, maxargs = sizeof(params) / sizeof(char *); - - - for( i= 0; i < maxargs; i++) - { - if (strcmp(param,params[i]) == 0) - { - switch(i) - { - case MOUNT_POINT : - enter_pblock_mount(value); - break; - case DIR_NAME : - enter_pblock_dir(value); - break; - default : - break; - } - } - } - - return TRUE; - -} - - - - -/* VFS initialisation function. Return initialised vfs_op_tuple array - back to SAMBA. */ - -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - *vfs_version = SMB_VFS_INTERFACE_VERSION; - - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - block_handle = vfs_handle; - - return block_vfs_ops; -} - - -/* VFS finalization function. */ -void vfs_done(connection_struct *conn) -{ -} - - -/* - * VFS connect and param file loading - */ - -static int block_connect(connection_struct *conn, const char *service, const char *user) -{ - if((load_param()) == FALSE) - { - - return -1; - - } - - DEBUG(0,("%s connecting \n",conn->user)); - - return (default_vfs_ops.connect(conn, service,user)); -} - -/* - * Free allocated structures and disconnect - * - */ - - -static void block_disconnect(struct connection_struct *conn) -{ - - struct block_dir *tmp_pblock = (pblock_mountp == NULL ? pblock_dir : pblock_mountp); - struct block_dir *free_pblock = NULL; - - while(tmp_pblock != NULL) - { - free(tmp_pblock->dir_name); - free_pblock = tmp_pblock; - tmp_pblock = tmp_pblock->next; - free(free_pblock); - - if(tmp_pblock == NULL && pblock_dir != NULL) - { - tmp_pblock = (pblock_mountp == NULL ? pblock_dir : NULL); - pblock_dir = NULL; - - } - - } - - - - default_vfs_ops.disconnect(conn); -} - -/* - * VFS opendir - */ - -static DIR *block_opendir(struct connection_struct *conn, char *fname) -{ - - char *dir_name = NULL; - struct stat stat_buf; - size_t len; - - len = strlen(conn->origpath) + 1 + strcspn(fname, "/"); - asprintf(&dir_name, "%s/%s", conn->origpath, fname); - dir_name[len] = '\0'; - - if((lstat(dir_name,&stat_buf)) == 0) - { - if((S_ISLNK(stat_buf.st_mode)) == 1) - { - stat(dir_name,&stat_buf); - if((search(&stat_buf) || dir_search(dir_name, fname) ) == TRUE) - { - DEBUG(0,("%s used link to blocked dir: %s \n", conn->user, dir_name)); - errno = EACCES; - return NULL; - } - } - } - - return (default_vfs_ops.opendir(conn, fname)); -} - - -/* - * Find mount point to block in list - */ - -static BOOL search(struct stat *stat_buf) -{ - struct block_dir *tmp_pblock = pblock_mountp; - - while(tmp_pblock != NULL) - { - - if(tmp_pblock->st_dev == stat_buf->st_dev) - { - return TRUE; - } - tmp_pblock = tmp_pblock->next; - } - - return FALSE; - -} - -/* - * Find dir in list to block id the starting point is link from a share - */ - -static BOOL dir_search(char *linkstr, char *dir) -{ - char buf[PATH_MAX +1], *ext_path; - int len = 0; - struct block_dir *tmp_pblock = pblock_dir; - - if((len = readlink(linkstr, buf, sizeof(buf))) == -1) - { - return TRUE; - - }else - { - buf[len] = '\0'; - } - - - if((ext_path = strchr(dir, '/')) != NULL) - { - pstrcat(buf, &ext_path[1]); - len = strlen(buf); - } - - while(tmp_pblock != NULL) - { - if(len < tmp_pblock->str_len) - { - tmp_pblock = tmp_pblock->next; - continue; - } - - if((strstr(buf, tmp_pblock->dir_name)) != NULL) - { - return TRUE; - } - tmp_pblock = tmp_pblock->next; - } - - - return FALSE; - -} diff --git a/examples/VFS/block/samba-block.conf b/examples/VFS/block/samba-block.conf deleted file mode 100644 index 7a137980b7..0000000000 --- a/examples/VFS/block/samba-block.conf +++ /dev/null @@ -1,6 +0,0 @@ -[ blocked ] -mount_point = / -mount_point = /boot -mount_point = /proc -dir_name = /usr/local/src/samba -dir_name = /usr/bin diff --git a/examples/VFS/block/smb.conf b/examples/VFS/block/smb.conf deleted file mode 100644 index 931196f402..0000000000 --- a/examples/VFS/block/smb.conf +++ /dev/null @@ -1,6 +0,0 @@ -[homes] - comment = Home Directories - vfs object = /usr/local/samba/lib/block.so - browseable = yes - writable = yes - -- cgit From 27cc26cec83f685c6d1dc73f855e01c082a09ca2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 7 Sep 2002 04:05:42 +0000 Subject: recycle.c: merged in modifications made my differnt people, cleaned up things, yet some work todo the code works but there are still some cases to be handled properly Makefile.in: this one seem much simpler and effective than the previous hack with file inclusion it should also be more portable we still need to find a solution to support multiple platforms or go back to libtool (This used to be commit e9f4bc77f84eeece82dea25f9c693cfb1d0a8464) --- examples/VFS/Makefile.in | 10 +- examples/VFS/recycle.c | 582 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 454 insertions(+), 138 deletions(-) (limited to 'examples/VFS') diff --git a/examples/VFS/Makefile.in b/examples/VFS/Makefile.in index 2ffd23b853..46e1a90263 100644 --- a/examples/VFS/Makefile.in +++ b/examples/VFS/Makefile.in @@ -6,11 +6,8 @@ LDSHFLAGS = -shared srcdir = @builddir@ FLAGS = $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper -I. $(CPPFLAGS) -I$(srcdir) -VFS_OBJS = audit.so recycle.so netatalk.so - -# Default target - -default: $(VFS_OBJS) +# Auto target +default: $(patsubst %.c,%.so,$(wildcard *.c)) # Pattern rules @@ -24,5 +21,4 @@ default: $(VFS_OBJS) clean: rm -rf .libs - rm -f core *~ *% *.bak \ - $(VFS_OBJ) $(VFS_OBJS) + rm -f core *~ *% *.bak *.o *.so diff --git a/examples/VFS/recycle.c b/examples/VFS/recycle.c index 0a261c20df..bcf5f898cc 100644 --- a/examples/VFS/recycle.c +++ b/examples/VFS/recycle.c @@ -1,227 +1,547 @@ -/* - * Auditing VFS module for samba. Log selected file operations to syslog - * facility. +/* + * Recycle bin VFS module for Samba. * * Copyright (C) 2001, Brandon Stone, Amherst College, . * Copyright (C) 2002, Jeremy Allison - modified to make a VFS module. * Copyright (C) 2002, Alexander Bokovoy - cascaded VFS adoption, + * Copyright (C) 2002, Juergen Hasch - added some options. + * Copyright (C) 2002, Simo Sorce * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" -#include -#include -#ifdef HAVE_UTIME_H -#include -#endif -#ifdef HAVE_DIRENT_H -#include -#endif -#include -#ifdef HAVE_FCNTL_H -#include -#endif -#include -#include -#include -#include - -/* VFS operations */ +#include "includes.h" + +#define ALLOC_CHECK(ptr, label) do { if ((ptr) == NULL) { DEBUG(0, ("recycle.bin: out of memory!\n")); errno = ENOMEM; goto label; } } while(0) + +static int vfs_recycle_debug_level = DBGC_VFS; + +#undef DBGC_CLASS +#define DBGC_CLASS vfs_recycle_debug_level +static const char *delimiter = "|"; /* delimiter for options */ + +/* One per connection */ + +typedef struct recycle_bin_struct +{ + TALLOC_CTX *ctx; + char *repository; /* name of the recycle bin directory */ + BOOL keep_directories; /* keep directory structure of deleted file in recycle bin */ + BOOL versions; /* create versions of deleted files with identical name */ + BOOL touch; /* touch access date of deleted file */ + char *exclude; /* which files to exclude */ + char *exclude_dir; /* which directories to exclude */ + char *noversions; /* which files to exclude from versioning */ + SMB_OFF_T maxsize; /* maximum file size to be saved */ +} recycle_bin_struct; + +static BOOL checkparam(char *haystack,char *needle); + +/* VFS operations */ static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *recycle_handle; -static int recycle_unlink(connection_struct *, const char *); + static int recycle_connect(struct connection_struct *conn, const char *service, const char *user); static void recycle_disconnect(struct connection_struct *conn); +static int recycle_unlink(connection_struct *, const char *); + +#define VFS_OP(x) ((void *) x) static vfs_op_tuple recycle_ops[] = { /* Disk operations */ - - {recycle_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_OPAQUE}, - {recycle_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_OPAQUE}, + {VFS_OP(recycle_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, + {VFS_OP(recycle_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, /* File operations */ - - {recycle_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_OPAQUE}, + {VFS_OP(recycle_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} + {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -/* VFS initialisation function. Return initialised vfs_op_tuple array back to SAMBA. */ - -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) +/** + * VFS initialisation function. + * + * @retval initialised vfs_op_tuple array + **/ +vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops) { + DEBUG(10, ("Initializing VFS module recycle\n")); *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - DEBUG(5,("vfs_init: for recycle!\n")); - - /* Remember vfs_id for storing private information at connect */ - recycle_handle = vfs_handle; + vfs_recycle_debug_level = debug_add_class("recycle.bin"); + if (vfs_recycle_debug_level == -1) { + vfs_recycle_debug_level = DBGC_VFS; + DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n")); + } else { + DEBUG(0, ("vfs_recycle: Debug class number of 'vfs_recycle': %d\n", vfs_recycle_debug_level)); + } return recycle_ops; } -/* VFS finalization function. */ +/** + * VFS finalization function. + * + **/ void vfs_done(connection_struct *conn) { - DEBUG(5,("vfs_done_recycle: called for connection %p\n",conn)); + DEBUG(10,("Called for connection %d\n", SNUM(conn))); } static int recycle_connect(struct connection_struct *conn, const char *service, const char *user) { - fstring recycle_bin; + TALLOC_CTX *ctx = NULL; + recycle_bin_struct *recbin; + char *servicename; + char *tmp_str; - DEBUG(4,("recycle_connect: called for service %s as user %s\n", service, user)); + DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user)); - fstrcpy(recycle_bin, (const char *)lp_parm_string(lp_servicename(SNUM(conn)),"vfs","recycle bin")); - if (!*recycle_bin) { - DEBUG(0,("recycle_connect: No options listed (vfs:recycle bin).\n" )); - return 0; /* No options. */ + if (!(ctx = talloc_init_named("recycle bin"))) { + DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); + return 0; } - - standard_sub_conn(conn,recycle_bin,sizeof(fstring)); + recbin = talloc(ctx,sizeof(recycle_bin_struct)); + if ( recbin == NULL) { + DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); + return -1; + } + recbin->ctx = ctx; + + /* Set defaults */ + recbin->repository = talloc_strdup(ctx, ".recycle"); + ALLOC_CHECK(recbin->repository, error); + recbin->keep_directories = False; + recbin->versions = False; + recbin->touch = False; + recbin->exclude = ""; + recbin->exclude_dir = ""; + recbin->noversions = ""; + recbin->maxsize = 0; + + /* parse configuration options */ + servicename = talloc_strdup(recbin->ctx, lp_servicename(SNUM(conn))); + DEBUG(10, ("servicename = %s\n",servicename)); + if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "repository")) != NULL) { + recbin->repository = talloc_sub_conn(ctx, conn, tmp_str); + ALLOC_CHECK(recbin->repository, error); + trim_string(recbin->repository, "/", "/"); + DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository)); + } + if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "mode")) != NULL) { + if (checkparam(tmp_str, "KEEP_DIRECTORIES") == True) + recbin->keep_directories = True; + if (checkparam(tmp_str, "VERSIONS") == True) + recbin->versions = True; + if (checkparam(tmp_str, "TOUCH") == True) + recbin->touch = True; + DEBUG(5, ("recycle.bin: mode = %s\n", tmp_str)); + } + if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "maxsize")) != NULL) { + recbin->maxsize = strtoul(tmp_str, NULL, 10); + if (recbin->maxsize == 0) { + recbin->maxsize = -1; + DEBUG(5, ("recycle.bin: maxsize = -infinite-\n")); + } else { + DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize)); + } + } + if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "exclude")) != NULL) { + recbin->exclude = talloc_strdup(ctx, tmp_str); + ALLOC_CHECK(recbin->exclude, error); + DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude)); + } + if ((tmp_str = lp_parm_string(servicename,"recycle.bin", "exclude_dir")) != NULL) { + recbin->exclude_dir = talloc_strdup(ctx, tmp_str); + ALLOC_CHECK(recbin->exclude_dir, error); + DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir)); + } + if ((tmp_str = lp_parm_string(servicename,"recycle.bin", "noversions")) != NULL) { + recbin->noversions = talloc_strdup(ctx, tmp_str); + ALLOC_CHECK(recbin->noversions, error); + DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions)); + } - DEBUG(3,("recycle_connect: recycle name is %s\n", recycle_bin )); + conn->vfs_private = (void *)recbin; + return default_vfs_ops.connect(conn, service, user); - recycle_handle->data = (void *)strdup(recycle_bin); - return 0; +error: + talloc_destroy(ctx); + return -1; } static void recycle_disconnect(struct connection_struct *conn) { - SAFE_FREE(recycle_handle->data); + DEBUG(10, ("Disconnecting VFS module recycle bin\n")); + if (conn->vfs_private) { + talloc_destroy(((recycle_bin_struct *)conn->vfs_private)->ctx); + conn->vfs_private = NULL; + } + default_vfs_ops.disconnect(conn); } -static BOOL recycle_XXX_exist(connection_struct *conn, const char *dname, BOOL isdir) +static BOOL recycle_directory_exist(connection_struct *conn, const char *dname) { SMB_STRUCT_STAT st; - if (default_vfs_ops.stat(conn,dname,&st) != 0) - return(False); + if (default_vfs_ops.stat(conn, dname, &st) == 0) { + if (S_ISDIR(st.st_mode)) { + return True; + } + } - if (isdir) - return S_ISDIR(st.st_mode) ? True : False; - else - return S_ISREG(st.st_mode) ? True : False; -} - -static BOOL recycle_directory_exist(connection_struct *conn, const char *dname) -{ - return recycle_XXX_exist(conn, dname, True); + return False; } static BOOL recycle_file_exist(connection_struct *conn, const char *fname) { - return recycle_XXX_exist(conn, fname, False); + SMB_STRUCT_STAT st; + + if (default_vfs_ops.stat(conn, fname, &st) == 0) { + if (S_ISREG(st.st_mode)) { + return True; + } + } + + return False; } +/** + * Return file size + * @param conn connection + * @param fname file name + * @return size in bytes + **/ static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname) { SMB_STRUCT_STAT st; + if (default_vfs_ops.stat(conn, fname, &st) != 0) { + DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno))); + return (SMB_OFF_T)0; + } + return(st.st_size); +} - if (default_vfs_ops.stat(conn,fname,&st) != 0) - return (SMB_OFF_T)-1; +/** + * Create directory tree + * @param conn connection + * @param dname Directory tree to be created + * @return Returns True for success + **/ +static BOOL recycle_create_dir(connection_struct *conn, const char *dname) +{ + int len; + mode_t mode; + char *new_dir = NULL; + char *tmp_str = NULL; + char *token; + char *tok_str; + BOOL ret = False; + + mode = S_IREAD | S_IWRITE | S_IEXEC; + + tmp_str = strdup(dname); + ALLOC_CHECK(tmp_str, done); + tok_str = tmp_str; + + len = strlen(dname); + new_dir = (char *)malloc(len + 1); + ALLOC_CHECK(new_dir, done); + *new_dir = '\0'; + + /* Create directory tree if neccessary */ + for(token = strtok(tok_str, "/"); token; token = strtok(NULL, "/")) { + safe_strcat(new_dir, token, len); + if (recycle_directory_exist(conn, new_dir)) + DEBUG(10, ("recycle.bin: dir %s already exists\n", new_dir)); + else { + DEBUG(5, ("recycle.bin: creating new dir %s\n", new_dir)); + if (default_vfs_ops.mkdir(conn, new_dir, mode) != 0) { + DEBUG(1,("recycle.bin: mkdir failed for %s with error: %s\n", new_dir, strerror(errno))); + ret = False; + goto done; + } + } + safe_strcat(new_dir, "/", len); + } - return(st.st_size); + ret = True; +done: + SAFE_FREE(tmp_str); + SAFE_FREE(new_dir); + return ret; } -/******************************************************************** - Check if file should be recycled -*********************************************************************/ +/** + * Check if needle is contained exactly in haystack + * @param haystack list of parameters separated by delimimiter character + * @param needle string to be matched exactly to haystack + * @return True if found + **/ +static BOOL checkparam(char *haystack, char *needle) +{ + char *token; + char *tok_str; + char *tmp_str; + BOOL ret = False; + + if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) { + return False; + } + + tmp_str = strdup(haystack); + ALLOC_CHECK(tmp_str, done); + token = tok_str = tmp_str; + + for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) { + if(strcmp(token, needle) == 0) { + ret = True; + goto done; + } + } +done: + SAFE_FREE(tmp_str); + return ret; +} + +/** + * Check if needle is contained in haystack, * and ? patterns are resolved + * @param haystack list of parameters separated by delimimiter character + * @param needle string to be matched exectly to haystack including pattern matching + * @return True if found + **/ +static BOOL matchparam(char *haystack, char *needle) +{ + char *token; + char *tok_str; + char *tmp_str; + BOOL ret = False; + + if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) { + return False; + } + + tmp_str = strdup(haystack); + ALLOC_CHECK(tmp_str, done); + token = tok_str = tmp_str; + + for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) { + if (!unix_wild_match(token, needle)) { + ret = True; + goto done; + } + } +done: + SAFE_FREE(tmp_str); + return ret; +} + +/** + * Touch access date + **/ +static void recycle_touch(connection_struct *conn, const char *fname) +{ + SMB_STRUCT_STAT st; + struct utimbuf tb; + time_t currtime; + + if (default_vfs_ops.stat(conn, fname, &st) != 0) { + DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno))); + return; + } + currtime = time(&currtime); + tb.actime = currtime; + tb.modtime = st.st_mtime; + + if (default_vfs_ops.utime(conn, fname, &tb) == -1 ) + DEBUG(0, ("recycle.bin: touching %s failed, reason = %s\n", fname, strerror(errno))); + } +/** + * Check if file should be recycled + **/ static int recycle_unlink(connection_struct *conn, const char *inname) { - fstring recycle_bin; - pstring fname; - char *base, *ext; - pstring bin; - int i=1, len, addlen; - int dir_mask=0770; - SMB_BIG_UINT dfree,dsize,bsize; + recycle_bin_struct *recbin; + char *file_name = NULL; + char *path_name = NULL; + char *temp_name = NULL; + char *final_name = NULL; + char *base; + int i; + SMB_BIG_UINT dfree, dsize, bsize; + SMB_OFF_T file_size, space_avail; + BOOL exist; + int rc; + + file_name = strdup(inname); + ALLOC_CHECK(file_name, done); + + if (conn->vfs_private) + recbin = (recycle_bin_struct *)conn->vfs_private; + else { + DEBUG(0, ("Recycle bin not initialized!\n")); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; + } - *recycle_bin = '\0'; - pstrcpy(fname, inname); + if(!recbin->repository || *(recbin->repository) == '\0') { + DEBUG(3, ("Recycle path not set, purging %s...\n", file_name)); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; + } - if (recycle_handle->data) - fstrcpy(recycle_bin, (const char *)recycle_handle->data); + /* we don't recycle the recycle bin... */ + if (strncmp(file_name, recbin->repository, strlen(recbin->repository)) == 0) { + DEBUG(3, ("File is within recycling bin, unlinking ...\n")); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; + } - if(!*recycle_bin) { - DEBUG(1, ("recycle bin: share parameter not set, purging %s...\n", fname)); - return default_vfs_ops.unlink(conn,fname); + file_size = recycle_get_file_size(conn, file_name); + /* it is wrong to purge filenames only because they are empty imho + * --- simo + * + if(fsize == 0) { + DEBUG(3, ("File %s is empty, purging...\n", file_name)); + rc = default_vfs_ops.unlink(conn,file_name); + goto done; + } + */ + + /* FIXME: this is wrong, we should check the hole size of the recycle bin is + * not greater then maxsize, not the size of the single file, also it is better + * to remove older files + */ + if(recbin->maxsize > 0 && file_size > recbin->maxsize) { + DEBUG(3, ("File %s exceeds maximum recycle size, purging... \n", file_name)); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; } - if(recycle_get_file_size(conn, fname) == 0) { - DEBUG(3, ("recycle bin: file %s is empty, purging...\n", fname)); - return default_vfs_ops.unlink(conn,fname); + /* FIXME: this is wrong: moving files with rename does not change the disk space + * allocation + * + space_avail = default_vfs_ops.disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L; + DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size)); + if(space_avail < file_size) { + DEBUG(3, ("Not enough diskspace, purging file %s\n", file_name)); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; + } + */ + + /* extract filename and path */ + path_name = (char *)malloc(PATH_MAX); + ALLOC_CHECK(path_name, done); + *path_name = '\0'; + safe_strcpy(path_name, file_name, PATH_MAX); + base = strrchr(path_name, '/'); + if (base == NULL) { + base = file_name; + safe_strcpy(path_name, "/", PATH_MAX); + } + else { + *base = '\0'; + base++; } - base = strrchr(fname, '/'); - pstrcpy(bin, recycle_bin); - pstrcat(bin, "/"); + DEBUG(10, ("recycle.bin: fname = %s\n", file_name)); /* original filename with path */ + DEBUG(10, ("recycle.bin: fpath = %s\n", path_name)); /* original path */ + DEBUG(10, ("recycle.bin: base = %s\n", base)); /* filename without path */ - if(base == NULL) { - ext = strrchr(fname, '.'); - pstrcat(bin, fname); - } else { - ext = strrchr(base, '.'); - pstrcat(bin, base+1); + if (matchparam(recbin->exclude, base)) { + DEBUG(3, ("recycle.bin: file %s is excluded \n", base)); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; } - DEBUG(4, ("recycle bin: base %s, ext %s, fname %s, bin %s\n", base, ext, fname, bin)); - if(strcmp(fname,bin) == 0) { - DEBUG(3, ("recycle bin: file %s exists, purging...\n", fname)); - return default_vfs_ops.unlink(conn,fname); + /* FIXME: this check will fail if we have more than one level of directories, + * we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 .... + * ---simo + */ + if (checkparam(recbin->exclude_dir, path_name)) { + DEBUG(3, ("recycle.bin: directory %s is excluded \n", path_name)); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; } - len = strlen(bin); - if ( ext != NULL) - len = len - strlen(ext); + temp_name = (char *)malloc(PATH_MAX); + ALLOC_CHECK(temp_name, done); + safe_strcpy(temp_name, recbin->repository, PATH_MAX); - addlen = sizeof(pstring)-len-1; - while(recycle_file_exist(conn,bin)) { - slprintf(bin+len, addlen, " (Copy #%d)", i++); - pstrcat(bin, ext); + /* see if we need to recreate the original directory structure in the recycle bin */ + if (recbin->keep_directories == True) { + safe_strcat(temp_name, "/", PATH_MAX); + safe_strcat(temp_name, path_name, PATH_MAX); } - DEBUG(3, ("recycle bin: moving source=%s to dest=%s\n", fname, bin)); - default_vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize); - if((unsigned int)dfree > 0) { - int ret; - if(!recycle_directory_exist(conn,recycle_bin)) { - DEBUG(3, ("recycle bin: directory %s nonexistant, creating...\n", recycle_bin)); - if (default_vfs_ops.mkdir(conn,recycle_bin,dir_mask) == -1) { - DEBUG(0, ("recycle bin: unable to create directory %s. Error was %s\n", - recycle_bin, strerror(errno) )); - } + exist = recycle_directory_exist(conn, temp_name); + if (exist) { + DEBUG(10, ("recycle.bin: Directory already exists\n")); + } else { + DEBUG(10, ("recycle.bin: Creating directory %s\n", temp_name)); + if (recycle_create_dir(conn, temp_name) == False) { + DEBUG(3, ("Could not create directory, purging %s...\n", file_name)); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; } - DEBUG(3, ("recycle bin: move %s -> %s\n", fname, bin)); + } - ret = default_vfs_ops.rename(conn, fname, bin); - if (ret == -1) { - DEBUG(1, ("recycle bin: move error %d (%s)\n", errno, strerror(errno) )); - DEBUG(0, ("recycle bin: move failed, purging...\n")); - return default_vfs_ops.unlink(conn,fname); + safe_strcat(temp_name, "/", PATH_MAX); + safe_strcat(temp_name, base, PATH_MAX); + DEBUG(10, ("recycle.bin: recycled file name%s\n", temp_name)); /* new filename with path */ + + /* check if we should delete file from recycle bin */ + if (recycle_file_exist(conn, temp_name)) { + if (recbin->versions == False || matchparam(recbin->noversions, base) == True) { + DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", temp_name)); + if (default_vfs_ops.unlink(conn, temp_name) != 0) { + DEBUG(1, ("recycle.bin: Error deleting old file: %s\n", strerror(errno))); + } } - return ret; - } else { - DEBUG(1, ("recycle bin: move failed, purging...\n")); - return default_vfs_ops.unlink(conn,fname); } + + /* rename file we move to recycle bin */ + i = 1; + final_name = (char *)malloc(PATH_MAX); + ALLOC_CHECK(final_name, done); + final_name = safe_strcpy(final_name, temp_name, PATH_MAX); + while (recycle_file_exist(conn, final_name)) { + snprintf(final_name, PATH_MAX, "Copy #%d of ", i++); + safe_strcat(final_name, temp_name, PATH_MAX); + } + + DEBUG(10, ("recycle.bin: Moving %s to %s\n", file_name, final_name)); + rc = default_vfs_ops.rename(conn, file_name, final_name); + if (rc != 0) { + DEBUG(3, ("recycle.bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name)); + rc = default_vfs_ops.unlink(conn, file_name); + goto done; + } + + /* touch access date of moved file */ + if (recbin->touch == True ) + recycle_touch(conn, final_name); + +done: + SAFE_FREE(file_name); + SAFE_FREE(path_name); + SAFE_FREE(temp_name); + SAFE_FREE(final_name); + return rc; } -- cgit From 79f54d28f8dd7aae636c2c2c857c98ad35fc747f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 8 Sep 2002 03:55:37 +0000 Subject: change parametric option name to vfs_recycle_bin it is more sane and do not pollute standard options namespace too much changed also the mode options to be indipendente boolean values, make it easier to understand how to configure them eg: vfs_recycle_bin:keeptree=yes vfs_recycle_bin:versions=yes (This used to be commit d904d50d3945f5f6a80b59850a82f3e37863c125) --- examples/VFS/recycle.c | 71 +++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 30 deletions(-) (limited to 'examples/VFS') diff --git a/examples/VFS/recycle.c b/examples/VFS/recycle.c index bcf5f898cc..a56619af31 100644 --- a/examples/VFS/recycle.c +++ b/examples/VFS/recycle.c @@ -39,7 +39,7 @@ typedef struct recycle_bin_struct { TALLOC_CTX *ctx; char *repository; /* name of the recycle bin directory */ - BOOL keep_directories; /* keep directory structure of deleted file in recycle bin */ + BOOL keep_dir_tree; /* keep directory structure of deleted file in recycle bin */ BOOL versions; /* create versions of deleted files with identical name */ BOOL touch; /* touch access date of deleted file */ char *exclude; /* which files to exclude */ @@ -48,8 +48,6 @@ typedef struct recycle_bin_struct SMB_OFF_T maxsize; /* maximum file size to be saved */ } recycle_bin_struct; -static BOOL checkparam(char *haystack,char *needle); - /* VFS operations */ static struct vfs_ops default_vfs_ops; /* For passthrough operation */ @@ -71,6 +69,16 @@ static vfs_op_tuple recycle_ops[] = { {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; +static BOOL check_bool_param(const char *value) +{ + if (strwicmp(value, "yes") == 0 || + strwicmp(value, "true") == 0 || + strwicmp(value, "1") == 0) + return True; + + return False; +} + /** * VFS initialisation function. * @@ -81,7 +89,7 @@ vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops) DEBUG(10, ("Initializing VFS module recycle\n")); *vfs_version = SMB_VFS_INTERFACE_VERSION; memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - vfs_recycle_debug_level = debug_add_class("recycle.bin"); + vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin"); if (vfs_recycle_debug_level == -1) { vfs_recycle_debug_level = DBGC_VFS; DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n")); @@ -125,7 +133,7 @@ static int recycle_connect(struct connection_struct *conn, const char *service, /* Set defaults */ recbin->repository = talloc_strdup(ctx, ".recycle"); ALLOC_CHECK(recbin->repository, error); - recbin->keep_directories = False; + recbin->keep_dir_tree = False; recbin->versions = False; recbin->touch = False; recbin->exclude = ""; @@ -136,22 +144,28 @@ static int recycle_connect(struct connection_struct *conn, const char *service, /* parse configuration options */ servicename = talloc_strdup(recbin->ctx, lp_servicename(SNUM(conn))); DEBUG(10, ("servicename = %s\n",servicename)); - if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "repository")) != NULL) { + if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "repository")) != NULL) { recbin->repository = talloc_sub_conn(ctx, conn, tmp_str); ALLOC_CHECK(recbin->repository, error); trim_string(recbin->repository, "/", "/"); DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository)); } - if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "mode")) != NULL) { - if (checkparam(tmp_str, "KEEP_DIRECTORIES") == True) - recbin->keep_directories = True; - if (checkparam(tmp_str, "VERSIONS") == True) + if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "keeptree")) != NULL) { + if (check_bool_param(tmp_str) == True) + recbin->keep_dir_tree = True; + DEBUG(5, ("recycle.bin: keeptree = %s\n", tmp_str)); + } + if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "versions")) != NULL) { + if (check_bool_param(tmp_str) == True) recbin->versions = True; - if (checkparam(tmp_str, "TOUCH") == True) + DEBUG(5, ("recycle.bin: versions = %s\n", tmp_str)); + } + if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "touch")) != NULL) { + if (check_bool_param(tmp_str) == True) recbin->touch = True; - DEBUG(5, ("recycle.bin: mode = %s\n", tmp_str)); + DEBUG(5, ("recycle.bin: touch = %s\n", tmp_str)); } - if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "maxsize")) != NULL) { + if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "maxsize")) != NULL) { recbin->maxsize = strtoul(tmp_str, NULL, 10); if (recbin->maxsize == 0) { recbin->maxsize = -1; @@ -160,17 +174,17 @@ static int recycle_connect(struct connection_struct *conn, const char *service, DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize)); } } - if ((tmp_str = lp_parm_string(servicename, "recycle.bin", "exclude")) != NULL) { + if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "exclude")) != NULL) { recbin->exclude = talloc_strdup(ctx, tmp_str); ALLOC_CHECK(recbin->exclude, error); DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude)); } - if ((tmp_str = lp_parm_string(servicename,"recycle.bin", "exclude_dir")) != NULL) { + if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "exclude_dir")) != NULL) { recbin->exclude_dir = talloc_strdup(ctx, tmp_str); ALLOC_CHECK(recbin->exclude_dir, error); DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir)); } - if ((tmp_str = lp_parm_string(servicename,"recycle.bin", "noversions")) != NULL) { + if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "noversions")) != NULL) { recbin->noversions = talloc_strdup(ctx, tmp_str); ALLOC_CHECK(recbin->noversions, error); DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions)); @@ -292,7 +306,7 @@ done: * @param needle string to be matched exactly to haystack * @return True if found **/ -static BOOL checkparam(char *haystack, char *needle) +static BOOL checkparam(const char *haystack, const char *needle) { char *token; char *tok_str; @@ -324,7 +338,7 @@ done: * @param needle string to be matched exectly to haystack including pattern matching * @return True if found **/ -static BOOL matchparam(char *haystack, char *needle) +static BOOL matchparam(const char *haystack, const char *needle) { char *token; char *tok_str; @@ -386,7 +400,7 @@ static int recycle_unlink(connection_struct *conn, const char *inname) SMB_BIG_UINT dfree, dsize, bsize; SMB_OFF_T file_size, space_avail; BOOL exist; - int rc; + int rc = -1; file_name = strdup(inname); ALLOC_CHECK(file_name, done); @@ -485,7 +499,7 @@ static int recycle_unlink(connection_struct *conn, const char *inname) safe_strcpy(temp_name, recbin->repository, PATH_MAX); /* see if we need to recreate the original directory structure in the recycle bin */ - if (recbin->keep_directories == True) { + if (recbin->keep_dir_tree == True) { safe_strcat(temp_name, "/", PATH_MAX); safe_strcat(temp_name, path_name, PATH_MAX); } @@ -502,15 +516,16 @@ static int recycle_unlink(connection_struct *conn, const char *inname) } } - safe_strcat(temp_name, "/", PATH_MAX); - safe_strcat(temp_name, base, PATH_MAX); + final_name = (char *)malloc(PATH_MAX); + ALLOC_CHECK(final_name, done); + snprintf(final_name, PATH_MAX, "%s/%s", temp_name, base); DEBUG(10, ("recycle.bin: recycled file name%s\n", temp_name)); /* new filename with path */ /* check if we should delete file from recycle bin */ - if (recycle_file_exist(conn, temp_name)) { + if (recycle_file_exist(conn, final_name)) { if (recbin->versions == False || matchparam(recbin->noversions, base) == True) { - DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", temp_name)); - if (default_vfs_ops.unlink(conn, temp_name) != 0) { + DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", final_name)); + if (default_vfs_ops.unlink(conn, final_name) != 0) { DEBUG(1, ("recycle.bin: Error deleting old file: %s\n", strerror(errno))); } } @@ -518,12 +533,8 @@ static int recycle_unlink(connection_struct *conn, const char *inname) /* rename file we move to recycle bin */ i = 1; - final_name = (char *)malloc(PATH_MAX); - ALLOC_CHECK(final_name, done); - final_name = safe_strcpy(final_name, temp_name, PATH_MAX); while (recycle_file_exist(conn, final_name)) { - snprintf(final_name, PATH_MAX, "Copy #%d of ", i++); - safe_strcat(final_name, temp_name, PATH_MAX); + snprintf(final_name, PATH_MAX, "%s/Copy #%d of %s", temp_name, i++, base); } DEBUG(10, ("recycle.bin: Moving %s to %s\n", file_name, final_name)); -- cgit