diff options
-rw-r--r-- | source3/Makefile.in | 6 | ||||
-rw-r--r-- | source3/configure.in | 3 | ||||
-rw-r--r-- | source3/modules/vfs_shadow_copy.c | 227 |
3 files changed, 235 insertions, 1 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index de7ee10bb4..2203af089b 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -320,6 +320,7 @@ VFS_DEFAULT_QUOTA_OBJ = modules/vfs_default_quota.o VFS_READONLY_OBJ = modules/vfs_readonly.o modules/getdate.o VFS_CAP_OBJ = modules/vfs_cap.o VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o +VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -1169,6 +1170,11 @@ bin/readonly.@SHLIBEXT@: $(VFS_READONLY_OBJ:.o=.@PICSUFFIX@) @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_READONLY_OBJ:.o=.@PICSUFFIX@) \ @SONAMEFLAG@`basename $@` +bin/shadow_copy.@SHLIBEXT@: $(VFS_SHADOW_COPY_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_SHADOW_COPY_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ:.o=.@PICSUFFIX@) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ:.o=.@PICSUFFIX@) \ diff --git a/source3/configure.in b/source3/configure.in index a03b37dd77..eb9b825691 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -360,7 +360,7 @@ dnl These have to be built static: default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" dnl These are preferably build shared, and static if dlopen() is not available -default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs charset_CP850 charset_CP437" +default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437" if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_echo" @@ -4333,6 +4333,7 @@ SMB_MODULE(vfs_default_quota, \$(VFS_DEFAULT_QUOTA_OBJ), "bin/default_quota.$SHL SMB_MODULE(vfs_readonly, \$(VFS_READONLY_OBJ), "bin/readonly.$SHLIBEXT", VFS) SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS) SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBEXT", VFS) +SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) diff --git a/source3/modules/vfs_shadow_copy.c b/source3/modules/vfs_shadow_copy.c new file mode 100644 index 0000000000..7ad7b1f7b1 --- /dev/null +++ b/source3/modules/vfs_shadow_copy.c @@ -0,0 +1,227 @@ +/* + * implementation of an Shadow Copy module + * + * Copyright (C) Stefan Metzmacher 2003-2004 + * + * 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 "includes.h" + +/* + Please read the VFS module Samba-HowTo-Collection. + there's a chapter about this module + + For this share + Z:\ + + the ShadowCopies are in this directories + + Z:\@GMT-2003.08.05-12.00.00\ + Z:\@GMT-2003.08.05-12.01.00\ + Z:\@GMT-2003.08.05-12.02.00\ + + e.g. + + Z:\testfile.txt + Z:\@GMT-2003.08.05-12.02.00\testfile.txt + + or: + + Z:\testdir\testfile.txt + Z:\@GMT-2003.08.05-12.02.00\testdir\testfile.txt + + + Note: Files must differ to be displayed via Windows Explorer! + Directories are always displayed... +*/ + +static int vfs_shadow_copy_debug_level = DBGC_VFS; + +#undef DBGC_CLASS +#define DBGC_CLASS vfs_shadow_copy_debug_level + +#define SHADOW_COPY_PREFIX "@GMT-" +#define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00" + +typedef struct { + int pos; + int num; + struct dirent *dirs; +} shadow_copy_Dir; + +static BOOL shadow_copy_match_name(const char *name) +{ + if (strncmp(SHADOW_COPY_PREFIX,name, sizeof(SHADOW_COPY_PREFIX)-1)==0 && + (strlen(SHADOW_COPY_SAMPLE) == strlen(name))) { + return True; + } + + return False; +} + +static DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) +{ + shadow_copy_Dir *dirp; + DIR *p = SMB_VFS_NEXT_OPENDIR(handle,conn,fname); + + if (!p) { + DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fname)); + return NULL; + } + + dirp = (shadow_copy_Dir *)malloc(sizeof(shadow_copy_Dir)); + if (!dirp) { + DEBUG(0,("shadow_copy_opendir: Out of memory\n")); + SMB_VFS_NEXT_CLOSEDIR(handle,conn,p); + return NULL; + } + + ZERO_STRUCTP(dirp); + + while (True) { + struct dirent *d; + struct dirent *r; + + + d = SMB_VFS_NEXT_READDIR(handle, conn, p); + if (d == NULL) { + break; + } + + if (shadow_copy_match_name(d->d_name)) { + DEBUG(8,("shadow_copy_opendir: hide [%s]\n",d->d_name)); + continue; + } + + DEBUG(10,("shadow_copy_opendir: not hide [%s]\n",d->d_name)); + + r = (struct dirent *)Realloc(dirp->dirs,(dirp->num+1)*sizeof(struct dirent)); + if (!r) { + DEBUG(0,("shadow_copy_opendir: Out of memory\n")); + break; + } + + dirp->dirs = r; + dirp->dirs[dirp->num++] = *d; + } + + SMB_VFS_NEXT_CLOSEDIR(handle,conn,p); + return((DIR *)dirp); +} + +struct dirent *shadow_copy_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *_dirp) +{ + shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; + + if (dirp->pos < dirp->num) { + return &(dirp->dirs[dirp->pos++]); + } + + return NULL; +} + +int shadow_copy_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *_dirp) +{ + shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; + + SAFE_FREE(dirp); + + return 0; +} + +static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels) +{ + DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn,fsp->conn->connectpath); + + shadow_copy_data->num_volumes = 0; + shadow_copy_data->labels = NULL; + + if (!p) { + DEBUG(0,("shadow_copy_get_shadow_copy_data: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fsp->conn->connectpath)); + return -1; + } + + while (True) { + SHADOW_COPY_LABEL *tlabels; + struct dirent *d; + + d = SMB_VFS_NEXT_READDIR(handle, fsp->conn, p); + if (d == NULL) { + break; + } + + /* */ + if (!shadow_copy_match_name(d->d_name)) { + DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore [%s]\n",d->d_name)); + continue; + } + + DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore [%s]\n",d->d_name)); + + if (!labels) { + shadow_copy_data->num_volumes++; + continue; + } + + tlabels = (SHADOW_COPY_LABEL *)talloc_realloc(shadow_copy_data->mem_ctx, + shadow_copy_data->labels, + (shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL)); + if (tlabels == NULL) { + DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n")); + SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p); + return -1; + } + + snprintf(tlabels[shadow_copy_data->num_volumes++], sizeof(*tlabels), "%s",d->d_name); + + shadow_copy_data->labels = tlabels; + } + + SMB_VFS_NEXT_CLOSEDIR(handle,fsp->conn,p); + return 0; +} + +/* VFS operations structure */ + +static vfs_op_tuple shadow_copy_ops[] = { + {SMB_VFS_OP(shadow_copy_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(shadow_copy_readdir), SMB_VFS_OP_READDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(shadow_copy_closedir), SMB_VFS_OP_CLOSEDIR, SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(shadow_copy_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE}, + + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_shadow_copy_init(void) +{ + NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy", shadow_copy_ops); + + if (!NT_STATUS_IS_OK(ret)) + return ret; + + vfs_shadow_copy_debug_level = debug_add_class("shadow_copy"); + if (vfs_shadow_copy_debug_level == -1) { + vfs_shadow_copy_debug_level = DBGC_VFS; + DEBUG(0, ("%s: Couldn't register custom debugging class!\n", + "vfs_shadow_copy_init")); + } else { + DEBUG(10, ("%s: Debug class number of '%s': %d\n", + "vfs_shadow_copy_init","shadow_copy",vfs_shadow_copy_debug_level)); + } + + return ret; +} |