~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/modules/vfs_shadow_copy.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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
}