s3-vfs: Remove unused llistxattr call from VFS modules, system.c and configure
[kai/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 "smbd/smbd.h"
26 #include "onefs_shadow_copy.h"
27
28 static int vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
29
30 #undef DBGC_CLASS
31 #define DBGC_CLASS vfs_onefs_shadow_copy_debug_level
32
33 #define SHADOW_COPY_PREFIX "@GMT-"
34 #define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
35
36 bool
37 shadow_copy_match_name(const char *name, char **snap_component)
38 {
39         uint32  i = 0;
40         char delim[] = SHADOW_COPY_PREFIX;
41         char* start;
42
43         start = strstr( name, delim );
44
45         /*
46          * The name could have SHADOW_COPY_PREFIX in it so we need to keep
47          * trying until we get something that is the full length of the
48          * SHADOW_COPY_SAMPLE.
49          */
50         while (start != NULL) {
51
52                 DEBUG(10,("Processing %s\n", name));
53
54                 /* size / correctness check */
55                 *snap_component = start;
56                 for ( i = sizeof(SHADOW_COPY_PREFIX);
57                       i < sizeof(SHADOW_COPY_SAMPLE); i++) {
58                         if (start[i] == '/') {
59                                 if (i == sizeof(SHADOW_COPY_SAMPLE) - 1)
60                                         return true;
61                                 else
62                                         break;
63                         } else if (start[i] == '\0')
64                                 return (i == sizeof(SHADOW_COPY_SAMPLE) - 1);
65                 }
66
67                 start = strstr( start, delim );
68         }
69
70         return false;
71 }
72
73 static int
74 onefs_shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle,
75                                        files_struct *fsp,
76                                        SHADOW_COPY_DATA *shadow_copy_data,
77                                        bool labels)
78 {
79         void *p = osc_version_opendir();
80         char *snap_component = NULL;
81         shadow_copy_data->num_volumes = 0;
82         shadow_copy_data->labels = NULL;
83
84         if (!p) {
85                 DEBUG(0, ("shadow_copy_get_shadow_copy_data: osc_opendir() "
86                           "failed for [%s]\n",fsp->conn->connectpath));
87                 return -1;
88         }
89
90         while (true) {
91                 SHADOW_COPY_LABEL *tlabels;
92                 char *d;
93
94                 d = osc_version_readdir(p);
95                 if (d == NULL)
96                         break;
97
98                 if (!shadow_copy_match_name(d, &snap_component)) {
99                         DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore "
100                                   "[%s]\n",d));
101                         continue;
102                 }
103
104                 DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore "
105                          "[%s]\n",d));
106
107                 if (!labels) {
108                         shadow_copy_data->num_volumes++;
109                         continue;
110                 }
111
112                 tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(
113                         shadow_copy_data->mem_ctx,
114                         shadow_copy_data->labels,
115                         (shadow_copy_data->num_volumes+1) *
116                         sizeof(SHADOW_COPY_LABEL));
117
118                 if (tlabels == NULL) {
119                         DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of "
120                                  "memory\n"));
121                         osc_version_closedir(p);
122                         return -1;
123                 }
124
125                 snprintf(tlabels[shadow_copy_data->num_volumes++],
126                          sizeof(*tlabels), "%s",d);
127
128                 shadow_copy_data->labels = tlabels;
129         }
130
131         osc_version_closedir(p);
132
133         return 0;
134 }
135
136 #define SHADOW_NEXT(op, args, rtype) do {                             \
137         char *cpath = NULL;                                           \
138         char *snap_component = NULL;                                  \
139         rtype ret;                                                    \
140         if (shadow_copy_match_name(path, &snap_component))            \
141                 cpath = osc_canonicalize_path(path, snap_component); \
142         ret = SMB_VFS_NEXT_ ## op args;                               \
143         SAFE_FREE(cpath);                                             \
144         return ret;                                                   \
145         } while (0)                                                   \
146
147 /*
148  * XXX: Convert osc_canonicalize_path to use talloc instead of malloc.
149  */
150 #define SHADOW_NEXT_SMB_FNAME(op, args, rtype) do {                   \
151                 char *smb_base_name_tmp = NULL;                       \
152                 char *cpath = NULL;                                   \
153                 char *snap_component = NULL;                          \
154                 rtype ret;                                            \
155                 smb_base_name_tmp = smb_fname->base_name;             \
156                 if (shadow_copy_match_name(smb_fname->base_name,      \
157                         &snap_component)) {                             \
158                         cpath = osc_canonicalize_path(smb_fname->base_name, \
159                             snap_component);                            \
160                         smb_fname->base_name = cpath;                   \
161                 }                                                       \
162                 ret = SMB_VFS_NEXT_ ## op args;                         \
163                 smb_fname->base_name = smb_base_name_tmp;               \
164                 SAFE_FREE(cpath);                                       \
165                 return ret;                                             \
166         } while (0)                                                     \
167
168 static uint64_t
169 onefs_shadow_copy_disk_free(vfs_handle_struct *handle, const char *path,
170                             bool small_query, uint64_t *bsize, uint64_t *dfree,
171                             uint64_t *dsize)
172 {
173
174         SHADOW_NEXT(DISK_FREE,
175                     (handle, cpath ?: path, small_query, bsize, dfree, dsize),
176                     uint64_t);
177
178 }
179
180 static int
181 onefs_shadow_copy_statvfs(struct vfs_handle_struct *handle, const char *path,
182                           struct vfs_statvfs_struct *statbuf)
183 {
184         SHADOW_NEXT(STATVFS,
185                     (handle, cpath ?: path, statbuf),
186                     int);
187 }
188
189 static DIR *
190 onefs_shadow_copy_opendir(vfs_handle_struct *handle, const char *path,
191                           const char *mask, uint32_t attr)
192 {
193         SHADOW_NEXT(OPENDIR,
194                     (handle, cpath ?: path, mask, attr),
195                     DIR *);
196 }
197
198 static int
199 onefs_shadow_copy_mkdir(vfs_handle_struct *handle, const char *path,
200                         mode_t mode)
201 {
202         SHADOW_NEXT(MKDIR,
203                     (handle, cpath ?: path, mode),
204                     int);
205 }
206
207 static int
208 onefs_shadow_copy_rmdir(vfs_handle_struct *handle, const char *path)
209 {
210         SHADOW_NEXT(RMDIR,
211                     (handle, cpath ?: path),
212                     int);
213 }
214
215 static int
216 onefs_shadow_copy_open(vfs_handle_struct *handle,
217                        struct smb_filename *smb_fname, files_struct *fsp,
218                        int flags, mode_t mode)
219 {
220         SHADOW_NEXT_SMB_FNAME(OPEN,
221                               (handle, smb_fname, fsp, flags, mode),
222                               int);
223 }
224
225 static NTSTATUS
226 onefs_shadow_copy_create_file(vfs_handle_struct *handle,
227                               struct smb_request *req,
228                               uint16_t root_dir_fid,
229                               struct smb_filename *smb_fname,
230                               uint32_t access_mask,
231                               uint32_t share_access,
232                               uint32_t create_disposition,
233                               uint32_t create_options,
234                               uint32_t file_attributes,
235                               uint32_t oplock_request,
236                               uint64_t allocation_size,
237                               uint32_t private_flags,
238                               struct security_descriptor *sd,
239                               struct ea_list *ea_list,
240                               files_struct **result,
241                               int *pinfo)
242 {
243         SHADOW_NEXT_SMB_FNAME(CREATE_FILE,
244                               (handle, req, root_dir_fid, smb_fname,
245                                   access_mask, share_access,
246                                   create_disposition, create_options,
247                                   file_attributes, oplock_request,
248                                   allocation_size, private_flags,
249                                   sd, ea_list, result, pinfo),
250                               NTSTATUS);
251 }
252
253 /**
254  * XXX: macro-ize
255  */
256 static int
257 onefs_shadow_copy_rename(vfs_handle_struct *handle,
258                          const struct smb_filename *smb_fname_src,
259                          const struct smb_filename *smb_fname_dst)
260 {
261         char *old_cpath = NULL;
262         char *old_snap_component = NULL;
263         char *new_cpath = NULL;
264         char *new_snap_component = NULL;
265         struct smb_filename *smb_fname_src_tmp = NULL;
266         struct smb_filename *smb_fname_dst_tmp = NULL;
267         NTSTATUS status;
268         int ret = -1;
269
270         status = copy_smb_filename(talloc_tos(), smb_fname_src,
271                                    &smb_fname_src_tmp);
272         if (!NT_STATUS_IS_OK(status)) {
273                 errno = map_errno_from_nt_status(status);
274                 goto out;
275         }
276         status = copy_smb_filename(talloc_tos(), smb_fname_dst,
277                                    &smb_fname_dst_tmp);
278         if (!NT_STATUS_IS_OK(status)) {
279                 errno = map_errno_from_nt_status(status);
280                 goto out;
281         }
282
283         if (shadow_copy_match_name(smb_fname_src_tmp->base_name,
284                                    &old_snap_component)) {
285                 old_cpath = osc_canonicalize_path(smb_fname_src_tmp->base_name,
286                                           old_snap_component);
287                 smb_fname_src_tmp->base_name = old_cpath;
288         }
289
290         if (shadow_copy_match_name(smb_fname_dst_tmp->base_name,
291                                    &new_snap_component)) {
292                 new_cpath = osc_canonicalize_path(smb_fname_dst_tmp->base_name,
293                                           new_snap_component);
294                 smb_fname_dst_tmp->base_name = new_cpath;
295         }
296
297         ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
298                                   smb_fname_dst_tmp);
299
300  out:
301         SAFE_FREE(old_cpath);
302         SAFE_FREE(new_cpath);
303         TALLOC_FREE(smb_fname_src_tmp);
304         TALLOC_FREE(smb_fname_dst_tmp);
305
306         return ret;
307 }
308
309 static int
310 onefs_shadow_copy_stat(vfs_handle_struct *handle,
311                        struct smb_filename *smb_fname)
312 {
313         SHADOW_NEXT_SMB_FNAME(STAT,
314                               (handle, smb_fname),
315                               int);
316 }
317
318 static int
319 onefs_shadow_copy_lstat(vfs_handle_struct *handle,
320                         struct smb_filename *smb_fname)
321 {
322         SHADOW_NEXT_SMB_FNAME(LSTAT,
323                               (handle, smb_fname),
324                               int);
325 }
326
327 static int
328 onefs_shadow_copy_unlink(vfs_handle_struct *handle,
329                          const struct smb_filename *smb_fname_in)
330 {
331         struct smb_filename *smb_fname = NULL;
332         NTSTATUS status;
333
334         status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname);
335         if (!NT_STATUS_IS_OK(status)) {
336                 errno = map_errno_from_nt_status(status);
337                 return -1;
338         }
339
340         SHADOW_NEXT_SMB_FNAME(UNLINK,
341                               (handle, smb_fname),
342                               int);
343 }
344
345 static int
346 onefs_shadow_copy_chmod(vfs_handle_struct *handle, const char *path,
347                         mode_t mode)
348 {
349         SHADOW_NEXT(CHMOD,
350                     (handle, cpath ?: path, mode),
351                     int);
352 }
353
354 static int
355 onefs_shadow_copy_chown(vfs_handle_struct *handle, const char *path,
356                         uid_t uid, gid_t gid)
357 {
358         SHADOW_NEXT(CHOWN,
359                     (handle, cpath ?: path, uid, gid),
360                     int);
361 }
362
363 static int
364 onefs_shadow_copy_lchown(vfs_handle_struct *handle, const char *path,
365                          uid_t uid, gid_t gid)
366 {
367         SHADOW_NEXT(LCHOWN,
368                     (handle, cpath ?: path, uid, gid),
369                     int);
370 }
371
372 static int
373 onefs_shadow_copy_chdir(vfs_handle_struct *handle, const char *path)
374 {
375         SHADOW_NEXT(CHDIR,
376                     (handle, cpath ?: path),
377                     int);
378 }
379
380 static int
381 onefs_shadow_copy_ntimes(vfs_handle_struct *handle,
382                         const struct smb_filename *smb_fname_in,
383                         struct smb_file_time *ft)
384 {
385         struct smb_filename *smb_fname = NULL;
386         NTSTATUS status;
387
388         status = copy_smb_filename(talloc_tos(), smb_fname_in, &smb_fname);
389         if (!NT_STATUS_IS_OK(status)) {
390                 errno = map_errno_from_nt_status(status);
391                 return -1;
392         }
393
394         SHADOW_NEXT_SMB_FNAME(NTIMES,
395                               (handle, smb_fname, ft),
396                               int);
397
398 }
399
400 /**
401  * XXX: macro-ize
402  */
403 static int
404 onefs_shadow_copy_symlink(vfs_handle_struct *handle,
405     const char *oldpath, const char *newpath)
406 {
407         char *old_cpath = NULL;
408         char *old_snap_component = NULL;
409         char *new_cpath = NULL;
410         char *new_snap_component = NULL;
411         bool ret;
412
413         if (shadow_copy_match_name(oldpath, &old_snap_component))
414                 old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
415
416         if (shadow_copy_match_name(newpath, &new_snap_component))
417                 new_cpath = osc_canonicalize_path(newpath, new_snap_component);
418
419         ret = SMB_VFS_NEXT_SYMLINK(handle, old_cpath ?: oldpath,
420             new_cpath ?: newpath);
421
422         SAFE_FREE(old_cpath);
423         SAFE_FREE(new_cpath);
424
425         return ret;
426 }
427
428 static int
429 onefs_shadow_copy_readlink(vfs_handle_struct *handle, const char *path,
430                            char *buf, size_t bufsiz)
431 {
432         SHADOW_NEXT(READLINK,
433                     (handle, cpath ?: path, buf, bufsiz),
434                     int);
435 }
436
437 /**
438  * XXX: macro-ize
439  */
440 static int
441 onefs_shadow_copy_link(vfs_handle_struct *handle, const char *oldpath,
442                        const char *newpath)
443 {
444         char *old_cpath = NULL;
445         char *old_snap_component = NULL;
446         char *new_cpath = NULL;
447         char *new_snap_component = NULL;
448         int ret;
449
450         if (shadow_copy_match_name(oldpath, &old_snap_component))
451                 old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
452
453         if (shadow_copy_match_name(newpath, &new_snap_component))
454                 new_cpath = osc_canonicalize_path(newpath, new_snap_component);
455
456         ret = SMB_VFS_NEXT_LINK(handle, old_cpath ?: oldpath,
457             new_cpath ?: newpath);
458
459         SAFE_FREE(old_cpath);
460         SAFE_FREE(new_cpath);
461
462         return ret;
463 }
464
465 static int
466 onefs_shadow_copy_mknod(vfs_handle_struct *handle, const char *path,
467                         mode_t mode, SMB_DEV_T dev)
468 {
469         SHADOW_NEXT(MKNOD,
470                     (handle, cpath ?: path, mode, dev),
471                     int);
472 }
473
474 static char *
475 onefs_shadow_copy_realpath(vfs_handle_struct *handle, const char *path)
476 {
477         SHADOW_NEXT(REALPATH,
478                     (handle, cpath ?: 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_listxattr(vfs_handle_struct *handle, const char *path,
573                             char *list, size_t size)
574 {
575         SHADOW_NEXT(LISTXATTR,
576                     (handle, cpath ?: path, list, size),
577                     ssize_t);
578 }
579
580 static int
581 onefs_shadow_copy_removexattr(vfs_handle_struct *handle, const char *path,
582                               const char *name)
583 {
584         SHADOW_NEXT(REMOVEXATTR,
585                     (handle, cpath ?: path, name),
586                     int);
587 }
588
589 static int
590 onefs_shadow_copy_lremovexattr(vfs_handle_struct *handle, const char *path,
591                                const char *name)
592 {
593         SHADOW_NEXT(LREMOVEXATTR,
594                     (handle, cpath ?: path, name),
595                     int);
596 }
597
598 static int
599 onefs_shadow_copy_setxattr(vfs_handle_struct *handle, const char *path,
600                            const char *name, const void *value, size_t size,
601                            int flags)
602 {
603         SHADOW_NEXT(SETXATTR,
604                     (handle, cpath ?: path, name, value, size, flags),
605                     int);
606 }
607
608 static int
609 onefs_shadow_copy_lsetxattr(vfs_handle_struct *handle, const char *path,
610                             const char *name, const void *value, size_t size,
611                             int flags)
612 {
613         SHADOW_NEXT(LSETXATTR,
614                     (handle, cpath ?: path, name, value, size, flags),
615                     int);
616 }
617
618 static bool
619 onefs_shadow_copy_is_offline(struct vfs_handle_struct *handle,
620                              const struct smb_fname *fname,
621                              SMB_STRUCT_STAT *sbuf)
622 {
623 #error Isilon, please convert "char *path" to "struct smb_fname *fname"
624         SHADOW_NEXT(IS_OFFLINE,
625                     (handle, cpath ?: path, sbuf),
626                     bool);
627 }
628
629 static int
630 onefs_shadow_copy_set_offline(struct vfs_handle_struct *handle,
631                                const struct smb_filename *fname)
632 {
633 #error Isilon, please convert "char *path" to "struct smb_fname *fname"
634         SHADOW_NEXT(SET_OFFLINE,
635                     (handle, cpath ?: path),
636                     int);
637 }
638
639 /* VFS operations structure */
640
641 static struct vfs_fn_pointers onefs_shadow_copy_fns = {
642         .disk_free_fn = onefs_shadow_copy_disk_free,
643         .get_shadow_copy_data_fn = onefs_shadow_copy_get_shadow_copy_data,
644         .statvfs_fn = onefs_shadow_copy_statvfs,
645         .opendir_fn = onefs_shadow_copy_opendir,
646         .mkdir_fn = onefs_shadow_copy_mkdir,
647         .rmdir_fn = onefs_shadow_copy_rmdir,
648         .open_fn = onefs_shadow_copy_open,
649         .create_file_fn = onefs_shadow_copy_create_file,
650         .rename_fn = onefs_shadow_copy_rename,
651         .stat_fn = onefs_shadow_copy_stat,
652         .stat_fn = onefs_shadow_copy_stat,
653         .lstat_fn = onefs_shadow_copy_lstat,
654         .unlink_fn = onefs_shadow_copy_unlink,
655         .chmod_fn = onefs_shadow_copy_chmod,
656         .chown_fn = onefs_shadow_copy_chown,
657         .lchown_fn = onefs_shadow_copy_lchown,
658         .chdir_fn = onefs_shadow_copy_chdir,
659         .ntimes_fn = onefs_shadow_copy_ntimes,
660         .symlink_fn = onefs_shadow_copy_symlink,
661         .readlink_fn = onefs_shadow_copy_readlink,
662         .link_fn = onefs_shadow_copy_link,
663         .mknod_fn = onefs_shadow_copy_mknod,
664         .realpath_fn = onefs_shadow_copy_realpath,
665         .chflags_fn = onefs_shadow_copy_chflags,
666         .streaminfo_fn = onefs_shadow_copy_streaminfo,
667         .get_real_filename_fn = onefs_shadow_copy_get_real_filename,
668         .get_nt_acl_fn = onefs_shadow_copy_get_nt_acl,
669         .chmod_acl_fn = onefs_shadow_copy_chmod_acl,
670         .sys_acl_get_file_fn = onefs_shadow_copy_sys_acl_get_file,
671         .sys_acl_set_file_fn = onefs_shadow_copy_sys_acl_set_file,
672         .sys_acl_delete_def_file_fn = onefs_shadow_copy_sys_acl_delete_def_file,
673         .getxattr_fn = onefs_shadow_copy_getxattr,
674         .listxattr_fn = onefs_shadow_copy_listxattr,
675         .removexattr_fn = onefs_shadow_copy_removexattr,
676         .lremovexattr_fn = onefs_shadow_copy_lremovexattr,
677         .setxattr_fn = onefs_shadow_copy_setxattr,
678         .lsetxattr_fn = onefs_shadow_copy_lsetxattr,
679         .is_offline_fn = onefs_shadow_copy_is_offline,
680         .set_offline_fn = onefs_shadow_copy_set_offline,
681 };
682
683 NTSTATUS vfs_shadow_copy_init(void)
684 {
685         NTSTATUS ret;
686
687         ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
688                                "onefs_shadow_copy",
689                                &onefs_shadow_copy_fns);
690
691         if (!NT_STATUS_IS_OK(ret))
692                 return ret;
693
694         vfs_onefs_shadow_copy_debug_level = debug_add_class("onefs_shadow_copy");
695
696         if (vfs_onefs_shadow_copy_debug_level == -1) {
697                 vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
698                 DEBUG(0, ("Couldn't register custom debugging class!\n"));
699         } else {
700                 DEBUG(10, ("Debug class number of 'onefs_shadow_copy': %d\n",
701                            vfs_onefs_shadow_copy_debug_level));
702         }
703
704         return ret;
705 }