root/source3/modules/vfs_shadow_copy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. shadow_copy_match_name
  2. shadow_copy_opendir
  3. shadow_copy_readdir
  4. shadow_copy_seekdir
  5. shadow_copy_telldir
  6. shadow_copy_rewinddir
  7. shadow_copy_closedir
  8. shadow_copy_get_shadow_copy_data
  9. vfs_shadow_copy_init

   1 /* 
   2  * implementation of an Shadow Copy module
   3  *
   4  * Copyright (C) Stefan Metzmacher      2003-2004
   5  *
   6  * This program is free software; you can redistribute it and/or modify
   7  * it under the terms of the GNU General Public License as published by
   8  * the Free Software Foundation; either version 3 of the License, or
   9  * (at your option) any later version.
  10  *  
  11  * This program is distributed in the hope that it will be useful,
  12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  * GNU General Public License for more details.
  15  *  
  16  * You should have received a copy of the GNU General Public License
  17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  18  */
  19 
  20 #include "includes.h"
  21 
  22 /*
  23     Please read the VFS module Samba-HowTo-Collection.
  24     there's a chapter about this module
  25 
  26     For this share
  27     Z:\
  28 
  29     the ShadowCopies are in this directories
  30 
  31     Z:\@GMT-2003.08.05-12.00.00\
  32     Z:\@GMT-2003.08.05-12.01.00\
  33     Z:\@GMT-2003.08.05-12.02.00\
  34 
  35     e.g.
  36     
  37     Z:\testfile.txt
  38     Z:\@GMT-2003.08.05-12.02.00\testfile.txt
  39 
  40     or:
  41 
  42     Z:\testdir\testfile.txt
  43     Z:\@GMT-2003.08.05-12.02.00\testdir\testfile.txt
  44 
  45 
  46     Note: Files must differ to be displayed via Windows Explorer!
  47           Directories are always displayed...    
  48 */
  49 
  50 static int vfs_shadow_copy_debug_level = DBGC_VFS;
  51 
  52 #undef DBGC_CLASS
  53 #define DBGC_CLASS vfs_shadow_copy_debug_level
  54 
  55 #define SHADOW_COPY_PREFIX "@GMT-"
  56 #define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
  57 
  58 typedef struct {
  59         int pos;
  60         int num;
  61         SMB_STRUCT_DIRENT *dirs;
  62 } shadow_copy_Dir;
  63 
  64 static bool shadow_copy_match_name(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
  65 {
  66         if (strncmp(SHADOW_COPY_PREFIX,name, sizeof(SHADOW_COPY_PREFIX)-1)==0 &&
  67                 (strlen(SHADOW_COPY_SAMPLE) == strlen(name))) {
  68                 return True;
  69         }
  70 
  71         return False;
  72 }
  73 
  74 static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
     /* [<][>][^][v][top][bottom][index][help] */
  75 {
  76         shadow_copy_Dir *dirp;
  77         SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fname,mask,attr);
  78 
  79         if (!p) {
  80                 DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fname));
  81                 return NULL;
  82         }
  83 
  84         dirp = SMB_MALLOC_P(shadow_copy_Dir);
  85         if (!dirp) {
  86                 DEBUG(0,("shadow_copy_opendir: Out of memory\n"));
  87                 SMB_VFS_NEXT_CLOSEDIR(handle,p);
  88                 return NULL;
  89         }
  90 
  91         ZERO_STRUCTP(dirp);
  92 
  93         while (True) {
  94                 SMB_STRUCT_DIRENT *d;
  95 
  96                 d = SMB_VFS_NEXT_READDIR(handle, p, NULL);
  97                 if (d == NULL) {
  98                         break;
  99                 }
 100 
 101                 if (shadow_copy_match_name(d->d_name)) {
 102                         DEBUG(8,("shadow_copy_opendir: hide [%s]\n",d->d_name));
 103                         continue;
 104                 }
 105 
 106                 DEBUG(10,("shadow_copy_opendir: not hide [%s]\n",d->d_name));
 107 
 108                 dirp->dirs = SMB_REALLOC_ARRAY(dirp->dirs,SMB_STRUCT_DIRENT, dirp->num+1);
 109                 if (!dirp->dirs) {
 110                         DEBUG(0,("shadow_copy_opendir: Out of memory\n"));
 111                         break;
 112                 }
 113 
 114                 dirp->dirs[dirp->num++] = *d;
 115         }
 116 
 117         SMB_VFS_NEXT_CLOSEDIR(handle,p);
 118         return((SMB_STRUCT_DIR *)dirp);
 119 }
 120 
 121 static SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 122 {
 123         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 124 
 125         if (dirp->pos < dirp->num) {
 126                 return &(dirp->dirs[dirp->pos++]);
 127         }
 128 
 129         return NULL;
 130 }
 131 
 132 static void shadow_copy_seekdir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp, long offset)
     /* [<][>][^][v][top][bottom][index][help] */
 133 {
 134         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 135 
 136         if (offset < dirp->num) {
 137                 dirp->pos = offset ;
 138         }
 139 }
 140 
 141 static long shadow_copy_telldir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 142 {
 143         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 144         return( dirp->pos ) ;
 145 }
 146 
 147 static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 148 {
 149         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 150         dirp->pos = 0 ;
 151 }
 152 
 153 static int shadow_copy_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155         shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
 156 
 157         SAFE_FREE(dirp->dirs);
 158         SAFE_FREE(dirp);
 159  
 160         return 0;       
 161 }
 162 
 163 static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, bool labels)
     /* [<][>][^][v][top][bottom][index][help] */
 164 {
 165         SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn->connectpath,NULL,0);
 166 
 167         shadow_copy_data->num_volumes = 0;
 168         shadow_copy_data->labels = NULL;
 169 
 170         if (!p) {
 171                 DEBUG(0,("shadow_copy_get_shadow_copy_data: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fsp->conn->connectpath));
 172                 return -1;
 173         }
 174 
 175         while (True) {
 176                 SHADOW_COPY_LABEL *tlabels;
 177                 SMB_STRUCT_DIRENT *d;
 178 
 179                 d = SMB_VFS_NEXT_READDIR(handle, p, NULL);
 180                 if (d == NULL) {
 181                         break;
 182                 }
 183 
 184                 /* */
 185                 if (!shadow_copy_match_name(d->d_name)) {
 186                         DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore [%s]\n",d->d_name));
 187                         continue;
 188                 }
 189 
 190                 DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore [%s]\n",d->d_name));
 191 
 192                 if (!labels) {
 193                         shadow_copy_data->num_volumes++;
 194                         continue;
 195                 }
 196 
 197                 tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(shadow_copy_data->mem_ctx,
 198                                                                         shadow_copy_data->labels,
 199                                                                         (shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL));
 200                 if (tlabels == NULL) {
 201                         DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n"));
 202                         SMB_VFS_NEXT_CLOSEDIR(handle,p);
 203                         return -1;
 204                 }
 205 
 206                 snprintf(tlabels[shadow_copy_data->num_volumes++], sizeof(*tlabels), "%s",d->d_name);
 207 
 208                 shadow_copy_data->labels = tlabels;
 209         }
 210 
 211         SMB_VFS_NEXT_CLOSEDIR(handle,p);
 212         return 0;
 213 }
 214 
 215 /* VFS operations structure */
 216 
 217 static vfs_op_tuple shadow_copy_ops[] = {
 218         {SMB_VFS_OP(shadow_copy_opendir),               SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_TRANSPARENT},
 219         {SMB_VFS_OP(shadow_copy_readdir),               SMB_VFS_OP_READDIR,             SMB_VFS_LAYER_TRANSPARENT},
 220         {SMB_VFS_OP(shadow_copy_seekdir),               SMB_VFS_OP_SEEKDIR,             SMB_VFS_LAYER_TRANSPARENT},
 221         {SMB_VFS_OP(shadow_copy_telldir),               SMB_VFS_OP_TELLDIR,             SMB_VFS_LAYER_TRANSPARENT},
 222         {SMB_VFS_OP(shadow_copy_rewinddir),             SMB_VFS_OP_REWINDDIR,           SMB_VFS_LAYER_TRANSPARENT},
 223         {SMB_VFS_OP(shadow_copy_closedir),              SMB_VFS_OP_CLOSEDIR,            SMB_VFS_LAYER_TRANSPARENT},
 224 
 225         {SMB_VFS_OP(shadow_copy_get_shadow_copy_data),  SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE},
 226 
 227         {SMB_VFS_OP(NULL),                              SMB_VFS_OP_NOOP,                SMB_VFS_LAYER_NOOP}
 228 };
 229 
 230 NTSTATUS vfs_shadow_copy_init(void);
 231 NTSTATUS vfs_shadow_copy_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 232 {
 233         NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy", shadow_copy_ops);
 234 
 235         if (!NT_STATUS_IS_OK(ret))
 236                 return ret;
 237 
 238         vfs_shadow_copy_debug_level = debug_add_class("shadow_copy");
 239         if (vfs_shadow_copy_debug_level == -1) {
 240                 vfs_shadow_copy_debug_level = DBGC_VFS;
 241                 DEBUG(0, ("%s: Couldn't register custom debugging class!\n",
 242                         "vfs_shadow_copy_init"));
 243         } else {
 244                 DEBUG(10, ("%s: Debug class number of '%s': %d\n", 
 245                         "vfs_shadow_copy_init","shadow_copy",vfs_shadow_copy_debug_level));
 246         }
 247 
 248         return ret;
 249 }

/* [<][>][^][v][top][bottom][index][help] */