smbd: Remove unused [push_pull]_file_id_24
[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 {
476         SHADOW_NEXT(REALPATH,
477                     (handle, cpath ?: path),
478                     char *);
479 }
480
481 static int onefs_shadow_copy_chflags(struct vfs_handle_struct *handle,
482                                      const char *path, unsigned int flags)
483 {
484         SHADOW_NEXT(CHFLAGS,
485                     (handle, cpath ?: path, flags),
486                     int);
487 }
488
489 static NTSTATUS
490 onefs_shadow_copy_streaminfo(struct vfs_handle_struct *handle,
491                              struct files_struct *fsp,
492                              const char *path,
493                              TALLOC_CTX *mem_ctx,
494                              unsigned int *num_streams,
495                              struct stream_struct **streams)
496 {
497         SHADOW_NEXT(STREAMINFO,
498                     (handle, fsp, cpath ?: path, mem_ctx, num_streams,
499                         streams),
500                     NTSTATUS);
501 }
502
503 static int
504 onefs_shadow_copy_get_real_filename(struct vfs_handle_struct *handle,
505                                     const char *full_path,
506                                     const char *path,
507                                     TALLOC_CTX *mem_ctx,
508                                     char **found_name)
509 {
510         SHADOW_NEXT(GET_REAL_FILENAME,
511                     (handle, full_path, cpath ?: path, mem_ctx, found_name),
512                     int);
513 }
514
515 static NTSTATUS
516 onefs_shadow_copy_get_nt_acl(struct vfs_handle_struct *handle,
517                             const char *path, uint32 security_info,
518                             struct security_descriptor **ppdesc)
519 {
520         SHADOW_NEXT(GET_NT_ACL,
521                     (handle, cpath ?: path, security_info, ppdesc),
522                     NTSTATUS);
523 }
524
525 static int
526 onefs_shadow_copy_chmod_acl(vfs_handle_struct *handle, const char *path,
527                             mode_t mode)
528 {
529         SHADOW_NEXT(CHMOD_ACL,
530                     (handle, cpath ?: path, mode),
531                     int);
532 }
533
534 static SMB_ACL_T
535 onefs_shadow_copy_sys_acl_get_file(vfs_handle_struct *handle,
536                                    const char *path, SMB_ACL_TYPE_T type)
537 {
538         SHADOW_NEXT(SYS_ACL_GET_FILE,
539                     (handle, cpath ?: path, type),
540                     SMB_ACL_T);
541 }
542
543 static int
544 onefs_shadow_copy_sys_acl_set_file(vfs_handle_struct *handle, const char *path,
545                                    SMB_ACL_TYPE_T type, SMB_ACL_T theacl)
546 {
547         SHADOW_NEXT(SYS_ACL_SET_FILE,
548                     (handle, cpath ?: path, type, theacl),
549                     int);
550 }
551
552 static int
553 onefs_shadow_copy_sys_acl_delete_def_file(vfs_handle_struct *handle,
554                                           const char *path)
555 {
556         SHADOW_NEXT(SYS_ACL_DELETE_DEF_FILE,
557                     (handle, cpath ?: path),
558                     int);
559 }
560
561 static ssize_t
562 onefs_shadow_copy_getxattr(vfs_handle_struct *handle, const char *path,
563                            const char *name, void *value, size_t size)
564 {
565         SHADOW_NEXT(GETXATTR,
566                     (handle, cpath ?: path, name, value, size),
567                     ssize_t);
568 }
569
570 static ssize_t
571 onefs_shadow_copy_lgetxattr(vfs_handle_struct *handle, const char *path,
572                             const char *name, void *value, size_t size)
573 {
574         SHADOW_NEXT(LGETXATTR,
575                     (handle, cpath ?: path, name, value, size),
576                     ssize_t);
577 }
578
579 static ssize_t
580 onefs_shadow_copy_listxattr(vfs_handle_struct *handle, const char *path,
581                             char *list, size_t size)
582 {
583         SHADOW_NEXT(LISTXATTR,
584                     (handle, cpath ?: path, list, size),
585                     ssize_t);
586 }
587
588 static ssize_t
589 onefs_shadow_copy_llistxattr(vfs_handle_struct *handle, const char *path,
590                              char *list, size_t size)
591 {
592         SHADOW_NEXT(LLISTXATTR,
593                     (handle, cpath ?: path, list, size),
594                     ssize_t);
595 }
596
597 static int
598 onefs_shadow_copy_removexattr(vfs_handle_struct *handle, const char *path,
599                               const char *name)
600 {
601         SHADOW_NEXT(REMOVEXATTR,
602                     (handle, cpath ?: path, name),
603                     int);
604 }
605
606 static int
607 onefs_shadow_copy_lremovexattr(vfs_handle_struct *handle, const char *path,
608                                const char *name)
609 {
610         SHADOW_NEXT(LREMOVEXATTR,
611                     (handle, cpath ?: path, name),
612                     int);
613 }
614
615 static int
616 onefs_shadow_copy_setxattr(vfs_handle_struct *handle, const char *path,
617                            const char *name, const void *value, size_t size,
618                            int flags)
619 {
620         SHADOW_NEXT(SETXATTR,
621                     (handle, cpath ?: path, name, value, size, flags),
622                     int);
623 }
624
625 static int
626 onefs_shadow_copy_lsetxattr(vfs_handle_struct *handle, const char *path,
627                             const char *name, const void *value, size_t size,
628                             int flags)
629 {
630         SHADOW_NEXT(LSETXATTR,
631                     (handle, cpath ?: path, name, value, size, flags),
632                     int);
633 }
634
635 static bool
636 onefs_shadow_copy_is_offline(struct vfs_handle_struct *handle,
637                              const struct smb_fname *fname,
638                              SMB_STRUCT_STAT *sbuf)
639 {
640 #error Isilon, please convert "char *path" to "struct smb_fname *fname"
641         SHADOW_NEXT(IS_OFFLINE,
642                     (handle, cpath ?: path, sbuf),
643                     bool);
644 }
645
646 static int
647 onefs_shadow_copy_set_offline(struct vfs_handle_struct *handle,
648                                const struct smb_filename *fname)
649 {
650 #error Isilon, please convert "char *path" to "struct smb_fname *fname"
651         SHADOW_NEXT(SET_OFFLINE,
652                     (handle, cpath ?: path),
653                     int);
654 }
655
656 /* VFS operations structure */
657
658 static struct vfs_fn_pointers onefs_shadow_copy_fns = {
659         .disk_free = onefs_shadow_copy_disk_free,
660         .get_shadow_copy_data = onefs_shadow_copy_get_shadow_copy_data,
661         .statvfs = onefs_shadow_copy_statvfs,
662         .opendir = onefs_shadow_copy_opendir,
663         .mkdir = onefs_shadow_copy_mkdir,
664         .rmdir = onefs_shadow_copy_rmdir,
665         .open = onefs_shadow_copy_open,
666         .create_file = onefs_shadow_copy_create_file,
667         .rename = onefs_shadow_copy_rename,
668         .stat = onefs_shadow_copy_stat,
669         .stat = onefs_shadow_copy_stat,
670         .lstat = onefs_shadow_copy_lstat,
671         .unlink = onefs_shadow_copy_unlink,
672         .chmod = onefs_shadow_copy_chmod,
673         .chown = onefs_shadow_copy_chown,
674         .lchown = onefs_shadow_copy_lchown,
675         .chdir = onefs_shadow_copy_chdir,
676         .ntimes = onefs_shadow_copy_ntimes,
677         .symlink = onefs_shadow_copy_symlink,
678         .vfs_readlink = onefs_shadow_copy_readlink,
679         .link = onefs_shadow_copy_link,
680         .mknod = onefs_shadow_copy_mknod,
681         .realpath = onefs_shadow_copy_realpath,
682         .chflags = onefs_shadow_copy_chflags,
683         .streaminfo = onefs_shadow_copy_streaminfo,
684         .get_real_filename = onefs_shadow_copy_get_real_filename,
685         .get_nt_acl = onefs_shadow_copy_get_nt_acl,
686         .chmod_acl = onefs_shadow_copy_chmod_acl,
687         .sys_acl_get_file = onefs_shadow_copy_sys_acl_get_file,
688         .sys_acl_set_file = onefs_shadow_copy_sys_acl_set_file,
689         .sys_acl_delete_def_file = onefs_shadow_copy_sys_acl_delete_def_file,
690         .getxattr = onefs_shadow_copy_getxattr,
691         .lgetxattr = onefs_shadow_copy_lgetxattr,
692         .listxattr = onefs_shadow_copy_listxattr,
693         .llistxattr = onefs_shadow_copy_llistxattr,
694         .removexattr = onefs_shadow_copy_removexattr,
695         .lremovexattr = onefs_shadow_copy_lremovexattr,
696         .setxattr = onefs_shadow_copy_setxattr,
697         .lsetxattr = onefs_shadow_copy_lsetxattr,
698         .is_offline = onefs_shadow_copy_is_offline,
699         .set_offline = onefs_shadow_copy_set_offline,
700 };
701
702 NTSTATUS vfs_shadow_copy_init(void)
703 {
704         NTSTATUS ret;
705
706         ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
707                                "onefs_shadow_copy",
708                                &onefs_shadow_copy_fns);
709
710         if (!NT_STATUS_IS_OK(ret))
711                 return ret;
712
713         vfs_onefs_shadow_copy_debug_level = debug_add_class("onefs_shadow_copy");
714
715         if (vfs_onefs_shadow_copy_debug_level == -1) {
716                 vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
717                 DEBUG(0, ("Couldn't register custom debugging class!\n"));
718         } else {
719                 DEBUG(10, ("Debug class number of 'onefs_shadow_copy': %d\n",
720                            vfs_onefs_shadow_copy_debug_level));
721         }
722
723         return ret;
724 }