cf84e581713c0151a282650e942bd1f98d41fd09
[samba.git] / source3 / modules / vfs_onefs_shadow_copy.c
1 /*
2  * OneFS shadow copy implementation that utilizes the file system's native
3  * snapshot support. This is based on the original shadow copy module from
4  * 2004.
5  *
6  * Copyright (C) Stefan Metzmacher      2003-2004
7  * Copyright (C) Tim Prouty             2009
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "includes.h"
25 #include "onefs_shadow_copy.h"
26
27 static int vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS vfs_onefs_shadow_copy_debug_level
31
32 #define SHADOW_COPY_PREFIX "@GMT-"
33 #define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
34
35 bool
36 shadow_copy_match_name(const char *name, char **snap_component)
37 {
38         uint32  i = 0;
39         char delim[] = SHADOW_COPY_PREFIX;
40         char* start;
41
42         start = strstr( name, delim );
43
44         /*
45          * The name could have SHADOW_COPY_PREFIX in it so we need to keep
46          * trying until we get something that is the full length of the
47          * SHADOW_COPY_SAMPLE.
48          */
49         while (start != NULL) {
50
51                 DEBUG(10,("Processing %s\n", name));
52
53                 /* size / correctness check */
54                 *snap_component = start;
55                 for ( i = sizeof(SHADOW_COPY_PREFIX);
56                       i < sizeof(SHADOW_COPY_SAMPLE); i++) {
57                         if (start[i] == '/') {
58                                 if (i == sizeof(SHADOW_COPY_SAMPLE) - 1)
59                                         return true;
60                                 else
61                                         break;
62                         } else if (start[i] == '\0')
63                                 return (i == sizeof(SHADOW_COPY_SAMPLE) - 1);
64                 }
65
66                 start = strstr( start, delim );
67         }
68
69         return false;
70 }
71
72 static int
73 onefs_shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle,
74                                        files_struct *fsp,
75                                        SHADOW_COPY_DATA *shadow_copy_data,
76                                        bool labels)
77 {
78         void *p = osc_version_opendir();
79         char *snap_component = NULL;
80         shadow_copy_data->num_volumes = 0;
81         shadow_copy_data->labels = NULL;
82
83         if (!p) {
84                 DEBUG(0, ("shadow_copy_get_shadow_copy_data: osc_opendir() "
85                           "failed for [%s]\n",fsp->conn->connectpath));
86                 return -1;
87         }
88
89         while (true) {
90                 SHADOW_COPY_LABEL *tlabels;
91                 char *d;
92
93                 d = osc_version_readdir(p);
94                 if (d == NULL)
95                         break;
96
97                 if (!shadow_copy_match_name(d, &snap_component)) {
98                         DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore "
99                                   "[%s]\n",d));
100                         continue;
101                 }
102
103                 DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore "
104                          "[%s]\n",d));
105
106                 if (!labels) {
107                         shadow_copy_data->num_volumes++;
108                         continue;
109                 }
110
111                 tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(
112                         shadow_copy_data->mem_ctx,
113                         shadow_copy_data->labels,
114                         (shadow_copy_data->num_volumes+1) *
115                         sizeof(SHADOW_COPY_LABEL));
116
117                 if (tlabels == NULL) {
118                         DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of "
119                                  "memory\n"));
120                         osc_version_closedir(p);
121                         return -1;
122                 }
123
124                 snprintf(tlabels[shadow_copy_data->num_volumes++],
125                          sizeof(*tlabels), "%s",d);
126
127                 shadow_copy_data->labels = tlabels;
128         }
129
130         osc_version_closedir(p);
131
132         return 0;
133 }
134
135 #define SHADOW_NEXT(op, args, rtype) do {                             \
136         char *cpath = NULL;                                           \
137         char *snap_component = NULL;                                  \
138         rtype ret;                                                    \
139         if (shadow_copy_match_name(path, &snap_component))            \
140                 cpath = osc_canonicalize_path(path, snap_component); \
141         ret = SMB_VFS_NEXT_ ## op args;                               \
142         SAFE_FREE(cpath);                                             \
143         return ret;                                                   \
144         } while (0)                                                   \
145
146 /*
147  * XXX: Convert osc_canonicalize_path to use talloc instead of malloc.
148  */
149 #define SHADOW_NEXT_SMB_FNAME(op, args, rtype) do {                   \
150                 char *smb_base_name_tmp = NULL;                       \
151                 char *cpath = NULL;                                   \
152                 char *snap_component = NULL;                          \
153                 rtype ret;                                            \
154                 smb_base_name_tmp = smb_fname->base_name;             \
155                 if (shadow_copy_match_name(smb_fname->base_name,      \
156                         &snap_component)) {                             \
157                         cpath = osc_canonicalize_path(smb_fname->base_name, \
158                             snap_component);                            \
159                         smb_fname->base_name = cpath;                   \
160                 }                                                       \
161                 ret = SMB_VFS_NEXT_ ## op args;                         \
162                 smb_fname->base_name = smb_base_name_tmp;               \
163                 SAFE_FREE(cpath);                                       \
164                 return ret;                                             \
165         } while (0)                                                     \
166
167 static uint64_t
168 onefs_shadow_copy_disk_free(vfs_handle_struct *handle, const char *path,
169                             bool small_query, uint64_t *bsize, uint64_t *dfree,
170                             uint64_t *dsize)
171 {
172
173         SHADOW_NEXT(DISK_FREE,
174                     (handle, cpath ?: path, small_query, bsize, dfree, dsize),
175                     uint64_t);
176
177 }
178
179 static int
180 onefs_shadow_copy_statvfs(struct vfs_handle_struct *handle, const char *path,
181                           struct vfs_statvfs_struct *statbuf)
182 {
183         SHADOW_NEXT(STATVFS,
184                     (handle, cpath ?: path, statbuf),
185                     int);
186 }
187
188 static SMB_STRUCT_DIR *
189 onefs_shadow_copy_opendir(vfs_handle_struct *handle, const char *path,
190                           const char *mask, uint32_t attr)
191 {
192         SHADOW_NEXT(OPENDIR,
193                     (handle, cpath ?: path, mask, attr),
194                     SMB_STRUCT_DIR *);
195 }
196
197 static int
198 onefs_shadow_copy_mkdir(vfs_handle_struct *handle, const char *path,
199                         mode_t mode)
200 {
201         SHADOW_NEXT(MKDIR,
202                     (handle, cpath ?: path, mode),
203                     int);
204 }
205
206 static int
207 onefs_shadow_copy_rmdir(vfs_handle_struct *handle, const char *path)
208 {
209         SHADOW_NEXT(RMDIR,
210                     (handle, cpath ?: path),
211                     int);
212 }
213
214 static int
215 onefs_shadow_copy_open(vfs_handle_struct *handle,
216                        struct smb_filename *smb_fname, files_struct *fsp,
217                        int flags, mode_t mode)
218 {
219         SHADOW_NEXT_SMB_FNAME(OPEN,
220                               (handle, smb_fname, fsp, flags, mode),
221                               int);
222 }
223
224 static NTSTATUS
225 onefs_shadow_copy_create_file(vfs_handle_struct *handle,
226                               struct smb_request *req,
227                               uint16_t root_dir_fid,
228                               struct smb_filename *smb_fname,
229                               uint32_t access_mask,
230                               uint32_t share_access,
231                               uint32_t create_disposition,
232                               uint32_t create_options,
233                               uint32_t file_attributes,
234                               uint32_t oplock_request,
235                               uint64_t allocation_size,
236                               uint32_t private_flags,
237                               struct security_descriptor *sd,
238                               struct ea_list *ea_list,
239                               files_struct **result,
240                               int *pinfo)
241 {
242         SHADOW_NEXT_SMB_FNAME(CREATE_FILE,
243                               (handle, req, root_dir_fid, smb_fname,
244                                   access_mask, share_access,
245                                   create_disposition, create_options,
246                                   file_attributes, oplock_request,
247                                   allocation_size, private_flags,
248                                   sd, ea_list, result, pinfo),
249                               NTSTATUS);
250 }
251
252 /**
253  * XXX: macro-ize
254  */
255 static int
256 onefs_shadow_copy_rename(vfs_handle_struct *handle,
257                          const struct smb_filename *smb_fname_src,
258                          const struct smb_filename *smb_fname_dst)
259 {
260         char *old_cpath = NULL;
261         char *old_snap_component = NULL;
262         char *new_cpath = NULL;
263         char *new_snap_component = NULL;
264         struct smb_filename *smb_fname_src_tmp = NULL;
265         struct smb_filename *smb_fname_dst_tmp = NULL;
266         NTSTATUS status;
267         int ret = -1;
268
269         status = copy_smb_filename(talloc_tos(), smb_fname_src,
270                                    &smb_fname_src_tmp);
271         if (!NT_STATUS_IS_OK(status)) {
272                 errno = map_errno_from_nt_status(status);
273                 goto out;
274         }
275         status = copy_smb_filename(talloc_tos(), smb_fname_dst,
276                                    &smb_fname_dst_tmp);
277         if (!NT_STATUS_IS_OK(status)) {
278                 errno = map_errno_from_nt_status(status);
279                 goto out;
280         }
281
282         if (shadow_copy_match_name(smb_fname_src_tmp->base_name,
283                                    &old_snap_component)) {
284                 old_cpath = osc_canonicalize_path(smb_fname_src_tmp->base_name,
285                                           old_snap_component);
286                 smb_fname_src_tmp->base_name = old_cpath;
287         }
288
289         if (shadow_copy_match_name(smb_fname_dst_tmp->base_name,
290                                    &new_snap_component)) {
291                 new_cpath = osc_canonicalize_path(smb_fname_dst_tmp->base_name,
292                                           new_snap_component);
293                 smb_fname_dst_tmp->base_name = new_cpath;
294         }
295
296         ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
297                                   smb_fname_dst_tmp);
298
299  out:
300         SAFE_FREE(old_cpath);
301         SAFE_FREE(new_cpath);
302         TALLOC_FREE(smb_fname_src_tmp);
303         TALLOC_FREE(smb_fname_dst_tmp);
304
305         return ret;
306 }
307
308 static int
309 onefs_shadow_copy_stat(vfs_handle_struct *handle,
310                        struct smb_filename *smb_fname)
311 {
312         SHADOW_NEXT_SMB_FNAME(STAT,
313                               (handle, smb_fname),
314                               int);
315 }
316
317 static int
318 onefs_shadow_copy_lstat(vfs_handle_struct *handle,
319                         struct smb_filename *smb_fname)
320 {
321         SHADOW_NEXT_SMB_FNAME(LSTAT,
322                               (handle, smb_fname),
323                               int);
324 }
325
326 static int
327 onefs_shadow_copy_unlink(vfs_handle_struct *handle,
328                          const struct smb_filename *smb_fname_in)
329 {
330         struct smb_filename *smb_fname = NULL;
331         NTSTATUS status;
332
333         status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname);
334         if (!NT_STATUS_IS_OK(status)) {
335                 errno = map_errno_from_nt_status(status);
336                 return -1;
337         }
338
339         SHADOW_NEXT_SMB_FNAME(UNLINK,
340                               (handle, smb_fname),
341                               int);
342 }
343
344 static int
345 onefs_shadow_copy_chmod(vfs_handle_struct *handle, const char *path,
346                         mode_t mode)
347 {
348         SHADOW_NEXT(CHMOD,
349                     (handle, cpath ?: path, mode),
350                     int);
351 }
352
353 static int
354 onefs_shadow_copy_chown(vfs_handle_struct *handle, const char *path,
355                         uid_t uid, gid_t gid)
356 {
357         SHADOW_NEXT(CHOWN,
358                     (handle, cpath ?: path, uid, gid),
359                     int);
360 }
361
362 static int
363 onefs_shadow_copy_lchown(vfs_handle_struct *handle, const char *path,
364                          uid_t uid, gid_t gid)
365 {
366         SHADOW_NEXT(LCHOWN,
367                     (handle, cpath ?: path, uid, gid),
368                     int);
369 }
370
371 static int
372 onefs_shadow_copy_chdir(vfs_handle_struct *handle, const char *path)
373 {
374         SHADOW_NEXT(CHDIR,
375                     (handle, cpath ?: path),
376                     int);
377 }
378
379 static int
380 onefs_shadow_copy_ntimes(vfs_handle_struct *handle,
381                         const struct smb_filename *smb_fname_in,
382                         struct smb_file_time *ft)
383 {
384         struct smb_filename *smb_fname = NULL;
385         NTSTATUS status;
386
387         status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname);
388         if (!NT_STATUS_IS_OK(status)) {
389                 errno = map_errno_from_nt_status(status);
390                 return -1;
391         }
392
393         SHADOW_NEXT_SMB_FNAME(NTIMES,
394                               (handle, smb_fname, ft),
395                               int);
396
397 }
398
399 /**
400  * XXX: macro-ize
401  */
402 static int
403 onefs_shadow_copy_symlink(vfs_handle_struct *handle,
404     const char *oldpath, const char *newpath)
405 {
406         char *old_cpath = NULL;
407         char *old_snap_component = NULL;
408         char *new_cpath = NULL;
409         char *new_snap_component = NULL;
410         bool ret;
411
412         if (shadow_copy_match_name(oldpath, &old_snap_component))
413                 old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
414
415         if (shadow_copy_match_name(newpath, &new_snap_component))
416                 new_cpath = osc_canonicalize_path(newpath, new_snap_component);
417
418         ret = SMB_VFS_NEXT_SYMLINK(handle, old_cpath ?: oldpath,
419             new_cpath ?: newpath);
420
421         SAFE_FREE(old_cpath);
422         SAFE_FREE(new_cpath);
423
424         return ret;
425 }
426
427 static int
428 onefs_shadow_copy_readlink(vfs_handle_struct *handle, const char *path,
429                            char *buf, size_t bufsiz)
430 {
431         SHADOW_NEXT(READLINK,
432                     (handle, cpath ?: path, buf, bufsiz),
433                     int);
434 }
435
436 /**
437  * XXX: macro-ize
438  */
439 static int
440 onefs_shadow_copy_link(vfs_handle_struct *handle, const char *oldpath,
441                        const char *newpath)
442 {
443         char *old_cpath = NULL;
444         char *old_snap_component = NULL;
445         char *new_cpath = NULL;
446         char *new_snap_component = NULL;
447         int ret;
448
449         if (shadow_copy_match_name(oldpath, &old_snap_component))
450                 old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
451
452         if (shadow_copy_match_name(newpath, &new_snap_component))
453                 new_cpath = osc_canonicalize_path(newpath, new_snap_component);
454
455         ret = SMB_VFS_NEXT_LINK(handle, old_cpath ?: oldpath,
456             new_cpath ?: newpath);
457
458         SAFE_FREE(old_cpath);
459         SAFE_FREE(new_cpath);
460
461         return ret;
462 }
463
464 static int
465 onefs_shadow_copy_mknod(vfs_handle_struct *handle, const char *path,
466                         mode_t mode, SMB_DEV_T dev)
467 {
468         SHADOW_NEXT(MKNOD,
469                     (handle, cpath ?: path, mode, dev),
470                     int);
471 }
472
473 static char *
474 onefs_shadow_copy_realpath(vfs_handle_struct *handle, const char *path,
475                            char *resolved_path)
476 {
477         SHADOW_NEXT(REALPATH,
478                     (handle, cpath ?: path, resolved_path),
479                     char *);
480 }
481
482 static int onefs_shadow_copy_chflags(struct vfs_handle_struct *handle,
483                                      const char *path, unsigned int flags)
484 {
485         SHADOW_NEXT(CHFLAGS,
486                     (handle, cpath ?: path, flags),
487                     int);
488 }
489
490 static NTSTATUS
491 onefs_shadow_copy_streaminfo(struct vfs_handle_struct *handle,
492                              struct files_struct *fsp,
493                              const char *path,
494                              TALLOC_CTX *mem_ctx,
495                              unsigned int *num_streams,
496                              struct stream_struct **streams)
497 {
498         SHADOW_NEXT(STREAMINFO,
499                     (handle, fsp, cpath ?: path, mem_ctx, num_streams,
500                         streams),
501                     NTSTATUS);
502 }
503
504 static int
505 onefs_shadow_copy_get_real_filename(struct vfs_handle_struct *handle,
506                                     const char *full_path,
507                                     const char *path,
508                                     TALLOC_CTX *mem_ctx,
509                                     char **found_name)
510 {
511         SHADOW_NEXT(GET_REAL_FILENAME,
512                     (handle, full_path, cpath ?: path, mem_ctx, found_name),
513                     int);
514 }
515
516 static NTSTATUS
517 onefs_shadow_copy_get_nt_acl(struct vfs_handle_struct *handle,
518                             const char *path, uint32 security_info,
519                             struct security_descriptor **ppdesc)
520 {
521         SHADOW_NEXT(GET_NT_ACL,
522                     (handle, cpath ?: path, security_info, ppdesc),
523                     NTSTATUS);
524 }
525
526 static int
527 onefs_shadow_copy_chmod_acl(vfs_handle_struct *handle, const char *path,
528                             mode_t mode)
529 {
530         SHADOW_NEXT(CHMOD_ACL,
531                     (handle, cpath ?: path, mode),
532                     int);
533 }
534
535 static SMB_ACL_T
536 onefs_shadow_copy_sys_acl_get_file(vfs_handle_struct *handle,
537                                    const char *path, SMB_ACL_TYPE_T type)
538 {
539         SHADOW_NEXT(SYS_ACL_GET_FILE,
540                     (handle, cpath ?: path, type),
541                     SMB_ACL_T);
542 }
543
544 static int
545 onefs_shadow_copy_sys_acl_set_file(vfs_handle_struct *handle, const char *path,
546                                    SMB_ACL_TYPE_T type, SMB_ACL_T theacl)
547 {
548         SHADOW_NEXT(SYS_ACL_SET_FILE,
549                     (handle, cpath ?: path, type, theacl),
550                     int);
551 }
552
553 static int
554 onefs_shadow_copy_sys_acl_delete_def_file(vfs_handle_struct *handle,
555                                           const char *path)
556 {
557         SHADOW_NEXT(SYS_ACL_DELETE_DEF_FILE,
558                     (handle, cpath ?: path),
559                     int);
560 }
561
562 static ssize_t
563 onefs_shadow_copy_getxattr(vfs_handle_struct *handle, const char *path,
564                            const char *name, void *value, size_t size)
565 {
566         SHADOW_NEXT(GETXATTR,
567                     (handle, cpath ?: path, name, value, size),
568                     ssize_t);
569 }
570
571 static ssize_t
572 onefs_shadow_copy_lgetxattr(vfs_handle_struct *handle, const char *path,
573                             const char *name, void *value, size_t size)
574 {
575         SHADOW_NEXT(LGETXATTR,
576                     (handle, cpath ?: path, name, value, size),
577                     ssize_t);
578 }
579
580 static ssize_t
581 onefs_shadow_copy_listxattr(vfs_handle_struct *handle, const char *path,
582                             char *list, size_t size)
583 {
584         SHADOW_NEXT(LISTXATTR,
585                     (handle, cpath ?: path, list, size),
586                     ssize_t);
587 }
588
589 static ssize_t
590 onefs_shadow_copy_llistxattr(vfs_handle_struct *handle, const char *path,
591                              char *list, size_t size)
592 {
593         SHADOW_NEXT(LLISTXATTR,
594                     (handle, cpath ?: path, list, size),
595                     ssize_t);
596 }
597
598 static int
599 onefs_shadow_copy_removexattr(vfs_handle_struct *handle, const char *path,
600                               const char *name)
601 {
602         SHADOW_NEXT(REMOVEXATTR,
603                     (handle, cpath ?: path, name),
604                     int);
605 }
606
607 static int
608 onefs_shadow_copy_lremovexattr(vfs_handle_struct *handle, const char *path,
609                                const char *name)
610 {
611         SHADOW_NEXT(LREMOVEXATTR,
612                     (handle, cpath ?: path, name),
613                     int);
614 }
615
616 static int
617 onefs_shadow_copy_setxattr(vfs_handle_struct *handle, const char *path,
618                            const char *name, const void *value, size_t size,
619                            int flags)
620 {
621         SHADOW_NEXT(SETXATTR,
622                     (handle, cpath ?: path, name, value, size, flags),
623                     int);
624 }
625
626 static int
627 onefs_shadow_copy_lsetxattr(vfs_handle_struct *handle, const char *path,
628                             const char *name, const void *value, size_t size,
629                             int flags)
630 {
631         SHADOW_NEXT(LSETXATTR,
632                     (handle, cpath ?: path, name, value, size, flags),
633                     int);
634 }
635
636 static bool
637 onefs_shadow_copy_is_offline(struct vfs_handle_struct *handle,
638                              const char *path, SMB_STRUCT_STAT *sbuf)
639 {
640         SHADOW_NEXT(IS_OFFLINE,
641                     (handle, cpath ?: path, sbuf),
642                     bool);
643 }
644
645 static int
646 onefs_shadow_copy_set_offline(struct vfs_handle_struct *handle,
647                               const char *path)
648 {
649         SHADOW_NEXT(SET_OFFLINE,
650                     (handle, cpath ?: path),
651                     int);
652 }
653
654 /* VFS operations structure */
655
656 static struct vfs_fn_pointers onefs_shadow_copy_fns = {
657         .disk_free = onefs_shadow_copy_disk_free,
658         .get_shadow_copy_data = onefs_shadow_copy_get_shadow_copy_data,
659         .statvfs = onefs_shadow_copy_statvfs,
660         .opendir = onefs_shadow_copy_opendir,
661         .mkdir = onefs_shadow_copy_mkdir,
662         .rmdir = onefs_shadow_copy_rmdir,
663         .open = onefs_shadow_copy_open,
664         .create_file = onefs_shadow_copy_create_file,
665         .rename = onefs_shadow_copy_rename,
666         .stat = onefs_shadow_copy_stat,
667         .stat = onefs_shadow_copy_stat,
668         .lstat = onefs_shadow_copy_lstat,
669         .unlink = onefs_shadow_copy_unlink,
670         .chmod = onefs_shadow_copy_chmod,
671         .chown = onefs_shadow_copy_chown,
672         .lchown = onefs_shadow_copy_lchown,
673         .chdir = onefs_shadow_copy_chdir,
674         .ntimes = onefs_shadow_copy_ntimes,
675         .symlink = onefs_shadow_copy_symlink,
676         .vfs_readlink = onefs_shadow_copy_readlink,
677         .link = onefs_shadow_copy_link,
678         .mknod = onefs_shadow_copy_mknod,
679         .realpath = onefs_shadow_copy_realpath,
680         .chflags = onefs_shadow_copy_chflags,
681         .streaminfo = onefs_shadow_copy_streaminfo,
682         .get_real_filename = onefs_shadow_copy_get_real_filename,
683         .get_nt_acl = onefs_shadow_copy_get_nt_acl,
684         .chmod_acl = onefs_shadow_copy_chmod_acl,
685         .sys_acl_get_file = onefs_shadow_copy_sys_acl_get_file,
686         .sys_acl_set_file = onefs_shadow_copy_sys_acl_set_file,
687         .sys_acl_delete_def_file = onefs_shadow_copy_sys_acl_delete_def_file,
688         .getxattr = onefs_shadow_copy_getxattr,
689         .lgetxattr = onefs_shadow_copy_lgetxattr,
690         .listxattr = onefs_shadow_copy_listxattr,
691         .llistxattr = onefs_shadow_copy_llistxattr,
692         .removexattr = onefs_shadow_copy_removexattr,
693         .lremovexattr = onefs_shadow_copy_lremovexattr,
694         .setxattr = onefs_shadow_copy_setxattr,
695         .lsetxattr = onefs_shadow_copy_lsetxattr,
696         .is_offline = onefs_shadow_copy_is_offline,
697         .set_offline = onefs_shadow_copy_set_offline,
698 };
699
700 NTSTATUS vfs_shadow_copy_init(void)
701 {
702         NTSTATUS ret;
703
704         ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
705                                "onefs_shadow_copy",
706                                &onefs_shadow_copy_fns);
707
708         if (!NT_STATUS_IS_OK(ret))
709                 return ret;
710
711         vfs_onefs_shadow_copy_debug_level = debug_add_class("onefs_shadow_copy");
712
713         if (vfs_onefs_shadow_copy_debug_level == -1) {
714                 vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
715                 DEBUG(0, ("Couldn't register custom debugging class!\n"));
716         } else {
717                 DEBUG(10, ("Debug class number of 'onefs_shadow_copy': %d\n",
718                            vfs_onefs_shadow_copy_debug_level));
719         }
720
721         return ret;
722 }