00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 static int vfs_shadow_copy_debug_level = DBGC_VFS;
00052
00053 #undef DBGC_CLASS
00054 #define DBGC_CLASS vfs_shadow_copy_debug_level
00055
00056 #define SHADOW_COPY_PREFIX "@GMT-"
00057 #define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
00058
00059 typedef struct {
00060 int pos;
00061 int num;
00062 SMB_STRUCT_DIRENT *dirs;
00063 } shadow_copy_Dir;
00064
00065 static BOOL shadow_copy_match_name(const char *name)
00066 {
00067 if (strncmp(SHADOW_COPY_PREFIX,name, sizeof(SHADOW_COPY_PREFIX)-1)==0 &&
00068 (strlen(SHADOW_COPY_SAMPLE) == strlen(name))) {
00069 return True;
00070 }
00071
00072 return False;
00073 }
00074
00075 static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
00076 {
00077 shadow_copy_Dir *dirp;
00078 SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fname,mask,attr);
00079
00080 if (!p) {
00081 DEBUG(0,("shadow_copy_opendir: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fname));
00082 return NULL;
00083 }
00084
00085 dirp = SMB_MALLOC_P(shadow_copy_Dir);
00086 if (!dirp) {
00087 DEBUG(0,("shadow_copy_opendir: Out of memory\n"));
00088 SMB_VFS_NEXT_CLOSEDIR(handle,p);
00089 return NULL;
00090 }
00091
00092 ZERO_STRUCTP(dirp);
00093
00094 while (True) {
00095 SMB_STRUCT_DIRENT *d;
00096
00097 d = SMB_VFS_NEXT_READDIR(handle, p);
00098 if (d == NULL) {
00099 break;
00100 }
00101
00102 if (shadow_copy_match_name(d->d_name)) {
00103 DEBUG(8,("shadow_copy_opendir: hide [%s]\n",d->d_name));
00104 continue;
00105 }
00106
00107 DEBUG(10,("shadow_copy_opendir: not hide [%s]\n",d->d_name));
00108
00109 dirp->dirs = SMB_REALLOC_ARRAY(dirp->dirs,SMB_STRUCT_DIRENT, dirp->num+1);
00110 if (!dirp->dirs) {
00111 DEBUG(0,("shadow_copy_opendir: Out of memory\n"));
00112 break;
00113 }
00114
00115 dirp->dirs[dirp->num++] = *d;
00116 }
00117
00118 SMB_VFS_NEXT_CLOSEDIR(handle,p);
00119 return((SMB_STRUCT_DIR *)dirp);
00120 }
00121
00122 static SMB_STRUCT_DIRENT *shadow_copy_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
00123 {
00124 shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
00125
00126 if (dirp->pos < dirp->num) {
00127 return &(dirp->dirs[dirp->pos++]);
00128 }
00129
00130 return NULL;
00131 }
00132
00133 static void shadow_copy_seekdir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp, long offset)
00134 {
00135 shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
00136
00137 if (offset < dirp->num) {
00138 dirp->pos = offset ;
00139 }
00140 }
00141
00142 static long shadow_copy_telldir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
00143 {
00144 shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
00145 return( dirp->pos ) ;
00146 }
00147
00148 static void shadow_copy_rewinddir(struct vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
00149 {
00150 shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
00151 dirp->pos = 0 ;
00152 }
00153
00154 static int shadow_copy_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *_dirp)
00155 {
00156 shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp;
00157
00158 SAFE_FREE(dirp->dirs);
00159 SAFE_FREE(dirp);
00160
00161 return 0;
00162 }
00163
00164 static int shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
00165 {
00166 SMB_STRUCT_DIR *p = SMB_VFS_NEXT_OPENDIR(handle,fsp->conn->connectpath,NULL,0);
00167
00168 shadow_copy_data->num_volumes = 0;
00169 shadow_copy_data->labels = NULL;
00170
00171 if (!p) {
00172 DEBUG(0,("shadow_copy_get_shadow_copy_data: SMB_VFS_NEXT_OPENDIR() failed for [%s]\n",fsp->conn->connectpath));
00173 return -1;
00174 }
00175
00176 while (True) {
00177 SHADOW_COPY_LABEL *tlabels;
00178 SMB_STRUCT_DIRENT *d;
00179
00180 d = SMB_VFS_NEXT_READDIR(handle, p);
00181 if (d == NULL) {
00182 break;
00183 }
00184
00185
00186 if (!shadow_copy_match_name(d->d_name)) {
00187 DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore [%s]\n",d->d_name));
00188 continue;
00189 }
00190
00191 DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore [%s]\n",d->d_name));
00192
00193 if (!labels) {
00194 shadow_copy_data->num_volumes++;
00195 continue;
00196 }
00197
00198 tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(shadow_copy_data->mem_ctx,
00199 shadow_copy_data->labels,
00200 (shadow_copy_data->num_volumes+1)*sizeof(SHADOW_COPY_LABEL));
00201 if (tlabels == NULL) {
00202 DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of memory\n"));
00203 SMB_VFS_NEXT_CLOSEDIR(handle,p);
00204 return -1;
00205 }
00206
00207 snprintf(tlabels[shadow_copy_data->num_volumes++], sizeof(*tlabels), "%s",d->d_name);
00208
00209 shadow_copy_data->labels = tlabels;
00210 }
00211
00212 SMB_VFS_NEXT_CLOSEDIR(handle,p);
00213 return 0;
00214 }
00215
00216
00217
00218 static vfs_op_tuple shadow_copy_ops[] = {
00219 {SMB_VFS_OP(shadow_copy_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT},
00220 {SMB_VFS_OP(shadow_copy_readdir), SMB_VFS_OP_READDIR, SMB_VFS_LAYER_TRANSPARENT},
00221 {SMB_VFS_OP(shadow_copy_seekdir), SMB_VFS_OP_SEEKDIR, SMB_VFS_LAYER_TRANSPARENT},
00222 {SMB_VFS_OP(shadow_copy_telldir), SMB_VFS_OP_TELLDIR, SMB_VFS_LAYER_TRANSPARENT},
00223 {SMB_VFS_OP(shadow_copy_rewinddir), SMB_VFS_OP_REWINDDIR, SMB_VFS_LAYER_TRANSPARENT},
00224 {SMB_VFS_OP(shadow_copy_closedir), SMB_VFS_OP_CLOSEDIR, SMB_VFS_LAYER_TRANSPARENT},
00225
00226 {SMB_VFS_OP(shadow_copy_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE},
00227
00228 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
00229 };
00230
00231 NTSTATUS vfs_shadow_copy_init(void);
00232 NTSTATUS vfs_shadow_copy_init(void)
00233 {
00234 NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy", shadow_copy_ops);
00235
00236 if (!NT_STATUS_IS_OK(ret))
00237 return ret;
00238
00239 vfs_shadow_copy_debug_level = debug_add_class("shadow_copy");
00240 if (vfs_shadow_copy_debug_level == -1) {
00241 vfs_shadow_copy_debug_level = DBGC_VFS;
00242 DEBUG(0, ("%s: Couldn't register custom debugging class!\n",
00243 "vfs_shadow_copy_init"));
00244 } else {
00245 DEBUG(10, ("%s: Debug class number of '%s': %d\n",
00246 "vfs_shadow_copy_init","shadow_copy",vfs_shadow_copy_debug_level));
00247 }
00248
00249 return ret;
00250 }