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
6 * Copyright (C) Stefan Metzmacher 2003-2004
7 * Copyright (C) Tim Prouty 2009
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.
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.
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.
25 #include "onefs_shadow_copy.h"
27 static int vfs_onefs_shadow_copy_debug_level
= DBGC_VFS
;
30 #define DBGC_CLASS vfs_onefs_shadow_copy_debug_level
32 #define SHADOW_COPY_PREFIX "@GMT-"
33 #define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
36 shadow_copy_match_name(const char *name
, char **snap_component
)
39 char delim
[] = SHADOW_COPY_PREFIX
;
42 start
= strstr( name
, delim
);
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
49 while (start
!= NULL
) {
51 DEBUG(10,("Processing %s\n", name
));
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)
62 } else if (start
[i
] == '\0')
63 return (i
== sizeof(SHADOW_COPY_SAMPLE
) - 1);
66 start
= strstr( start
, delim
);
73 onefs_shadow_copy_get_shadow_copy_data(vfs_handle_struct
*handle
,
75 SHADOW_COPY_DATA
*shadow_copy_data
,
78 void *p
= osc_version_opendir();
79 char *snap_component
= NULL
;
80 shadow_copy_data
->num_volumes
= 0;
81 shadow_copy_data
->labels
= NULL
;
84 DEBUG(0, ("shadow_copy_get_shadow_copy_data: osc_opendir() "
85 "failed for [%s]\n",fsp
->conn
->connectpath
));
90 SHADOW_COPY_LABEL
*tlabels
;
93 d
= osc_version_readdir(p
);
97 if (!shadow_copy_match_name(d
, &snap_component
)) {
98 DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore "
103 DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore "
107 shadow_copy_data
->num_volumes
++;
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
));
117 if (tlabels
== NULL
) {
118 DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of "
120 osc_version_closedir(p
);
124 snprintf(tlabels
[shadow_copy_data
->num_volumes
++],
125 sizeof(*tlabels
), "%s",d
);
127 shadow_copy_data
->labels
= tlabels
;
130 osc_version_closedir(p
);
135 #define SHADOW_NEXT(op, args, rtype) do { \
136 char *cpath = NULL; \
137 char *snap_component = NULL; \
139 if (shadow_copy_match_name(path, &snap_component)) \
140 cpath = osc_canonicalize_path(path, snap_component); \
141 ret = SMB_VFS_NEXT_ ## op args; \
149 onefs_shadow_copy_disk_free(vfs_handle_struct
*handle
, const char *path
,
150 bool small_query
, uint64_t *bsize
, uint64_t *dfree
,
154 SHADOW_NEXT(DISK_FREE
,
155 (handle
, cpath
?: path
, small_query
, bsize
, dfree
, dsize
),
161 onefs_shadow_copy_statvfs(struct vfs_handle_struct
*handle
, const char *path
,
162 struct vfs_statvfs_struct
*statbuf
)
165 (handle
, cpath
?: path
, statbuf
),
169 static SMB_STRUCT_DIR
*
170 onefs_shadow_copy_opendir(vfs_handle_struct
*handle
, const char *path
,
171 const char *mask
, uint32_t attr
)
174 (handle
, cpath
?: path
, mask
, attr
),
179 onefs_shadow_copy_mkdir(vfs_handle_struct
*handle
, const char *path
,
183 (handle
, cpath
?: path
, mode
),
188 onefs_shadow_copy_rmdir(vfs_handle_struct
*handle
, const char *path
)
191 (handle
, cpath
?: path
),
196 onefs_shadow_copy_open(vfs_handle_struct
*handle
, const char *path
,
197 files_struct
*fsp
, int flags
, mode_t mode
)
200 (handle
, cpath
?: path
, fsp
, flags
, mode
),
205 onefs_shadow_copy_create_file(vfs_handle_struct
*handle
,
206 struct smb_request
*req
,
207 uint16_t root_dir_fid
,
209 uint32_t create_file_flags
,
210 uint32_t access_mask
,
211 uint32_t share_access
,
212 uint32_t create_disposition
,
213 uint32_t create_options
,
214 uint32_t file_attributes
,
215 uint32_t oplock_request
,
216 uint64_t allocation_size
,
217 struct security_descriptor
*sd
,
218 struct ea_list
*ea_list
,
219 files_struct
**result
,
221 SMB_STRUCT_STAT
*psbuf
)
223 SHADOW_NEXT(CREATE_FILE
,
224 (handle
, req
, root_dir_fid
, cpath
?: path
,
225 create_file_flags
, access_mask
, share_access
,
226 create_disposition
, create_options
, file_attributes
,
227 oplock_request
, allocation_size
, sd
, ea_list
, result
,
236 onefs_shadow_copy_rename(vfs_handle_struct
*handle
, const char *old_name
,
237 const char *new_name
)
239 char *old_cpath
= NULL
;
240 char *old_snap_component
= NULL
;
241 char *new_cpath
= NULL
;
242 char *new_snap_component
= NULL
;
245 if (shadow_copy_match_name(old_name
, &old_snap_component
))
246 old_cpath
= osc_canonicalize_path(old_name
, old_snap_component
);
248 if (shadow_copy_match_name(new_name
, &new_snap_component
))
249 new_cpath
= osc_canonicalize_path(new_name
, new_snap_component
);
251 ret
= SMB_VFS_NEXT_RENAME(handle
, old_cpath
?: old_name
,
252 new_cpath
?: new_name
);
254 SAFE_FREE(old_cpath
);
255 SAFE_FREE(new_cpath
);
261 onefs_shadow_copy_stat(vfs_handle_struct
*handle
, const char *path
,
262 SMB_STRUCT_STAT
*sbuf
)
265 (handle
, cpath
?: path
, sbuf
),
270 onefs_shadow_copy_lstat(vfs_handle_struct
*handle
, const char *path
,
271 SMB_STRUCT_STAT
*sbuf
)
274 (handle
, cpath
?: path
, sbuf
),
279 onefs_shadow_copy_unlink(vfs_handle_struct
*handle
, const char *path
)
282 (handle
, cpath
?: path
),
287 onefs_shadow_copy_chmod(vfs_handle_struct
*handle
, const char *path
,
291 (handle
, cpath
?: path
, mode
),
296 onefs_shadow_copy_chown(vfs_handle_struct
*handle
, const char *path
,
297 uid_t uid
, gid_t gid
)
300 (handle
, cpath
?: path
, uid
, gid
),
305 onefs_shadow_copy_lchown(vfs_handle_struct
*handle
, const char *path
,
306 uid_t uid
, gid_t gid
)
309 (handle
, cpath
?: path
, uid
, gid
),
314 onefs_shadow_copy_chdir(vfs_handle_struct
*handle
, const char *path
)
317 (handle
, cpath
?: path
),
322 onefs_shadow_copy_ntimes(vfs_handle_struct
*handle
, const char *path
,
323 struct smb_file_time
*ft
)
326 (handle
, cpath
?: path
, ft
),
335 onefs_shadow_copy_symlink(vfs_handle_struct
*handle
,
336 const char *oldpath
, const char *newpath
)
338 char *old_cpath
= NULL
;
339 char *old_snap_component
= NULL
;
340 char *new_cpath
= NULL
;
341 char *new_snap_component
= NULL
;
344 if (shadow_copy_match_name(oldpath
, &old_snap_component
))
345 old_cpath
= osc_canonicalize_path(oldpath
, old_snap_component
);
347 if (shadow_copy_match_name(newpath
, &new_snap_component
))
348 new_cpath
= osc_canonicalize_path(newpath
, new_snap_component
);
350 ret
= SMB_VFS_NEXT_SYMLINK(handle
, old_cpath
?: oldpath
,
351 new_cpath
?: newpath
);
353 SAFE_FREE(old_cpath
);
354 SAFE_FREE(new_cpath
);
360 onefs_shadow_copy_readlink(vfs_handle_struct
*handle
, const char *path
,
361 char *buf
, size_t bufsiz
)
363 SHADOW_NEXT(READLINK
,
364 (handle
, cpath
?: path
, buf
, bufsiz
),
372 onefs_shadow_copy_link(vfs_handle_struct
*handle
, const char *oldpath
,
375 char *old_cpath
= NULL
;
376 char *old_snap_component
= NULL
;
377 char *new_cpath
= NULL
;
378 char *new_snap_component
= NULL
;
381 if (shadow_copy_match_name(oldpath
, &old_snap_component
))
382 old_cpath
= osc_canonicalize_path(oldpath
, old_snap_component
);
384 if (shadow_copy_match_name(newpath
, &new_snap_component
))
385 new_cpath
= osc_canonicalize_path(newpath
, new_snap_component
);
387 ret
= SMB_VFS_NEXT_LINK(handle
, old_cpath
?: oldpath
,
388 new_cpath
?: newpath
);
390 SAFE_FREE(old_cpath
);
391 SAFE_FREE(new_cpath
);
397 onefs_shadow_copy_mknod(vfs_handle_struct
*handle
, const char *path
,
398 mode_t mode
, SMB_DEV_T dev
)
401 (handle
, cpath
?: path
, mode
, dev
),
406 onefs_shadow_copy_realpath(vfs_handle_struct
*handle
, const char *path
,
409 SHADOW_NEXT(REALPATH
,
410 (handle
, cpath
?: path
, resolved_path
),
414 static int onefs_shadow_copy_chflags(struct vfs_handle_struct
*handle
,
415 const char *path
, unsigned int flags
)
418 (handle
, cpath
?: path
, flags
),
423 onefs_shadow_copy_streaminfo(struct vfs_handle_struct
*handle
,
424 struct files_struct
*fsp
,
427 unsigned int *num_streams
,
428 struct stream_struct
**streams
)
430 SHADOW_NEXT(STREAMINFO
,
431 (handle
, fsp
, cpath
?: path
, mem_ctx
, num_streams
,
437 onefs_shadow_copy_get_real_filename(struct vfs_handle_struct
*handle
,
438 const char *full_path
,
443 SHADOW_NEXT(GET_REAL_FILENAME
,
444 (handle
, full_path
, cpath
?: path
, mem_ctx
, found_name
),
449 onefs_shadow_copy_get_nt_acl(struct vfs_handle_struct
*handle
,
450 const char *path
, uint32 security_info
,
451 struct security_descriptor
**ppdesc
)
453 SHADOW_NEXT(GET_NT_ACL
,
454 (handle
, cpath
?: path
, security_info
, ppdesc
),
459 onefs_shadow_copy_chmod_acl(vfs_handle_struct
*handle
, const char *path
,
462 SHADOW_NEXT(CHMOD_ACL
,
463 (handle
, cpath
?: path
, mode
),
468 onefs_shadow_copy_sys_acl_get_file(vfs_handle_struct
*handle
,
469 const char *path
, SMB_ACL_TYPE_T type
)
471 SHADOW_NEXT(SYS_ACL_GET_FILE
,
472 (handle
, cpath
?: path
, type
),
477 onefs_shadow_copy_sys_acl_set_file(vfs_handle_struct
*handle
, const char *path
,
478 SMB_ACL_TYPE_T type
, SMB_ACL_T theacl
)
480 SHADOW_NEXT(SYS_ACL_SET_FILE
,
481 (handle
, cpath
?: path
, type
, theacl
),
486 onefs_shadow_copy_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
489 SHADOW_NEXT(SYS_ACL_DELETE_DEF_FILE
,
490 (handle
, cpath
?: path
),
495 onefs_shadow_copy_getxattr(vfs_handle_struct
*handle
, const char *path
,
496 const char *name
, void *value
, size_t size
)
498 SHADOW_NEXT(GETXATTR
,
499 (handle
, cpath
?: path
, name
, value
, size
),
504 onefs_shadow_copy_lgetxattr(vfs_handle_struct
*handle
, const char *path
,
505 const char *name
, void *value
, size_t size
)
507 SHADOW_NEXT(LGETXATTR
,
508 (handle
, cpath
?: path
, name
, value
, size
),
513 onefs_shadow_copy_listxattr(vfs_handle_struct
*handle
, const char *path
,
514 char *list
, size_t size
)
516 SHADOW_NEXT(LISTXATTR
,
517 (handle
, cpath
?: path
, list
, size
),
522 onefs_shadow_copy_llistxattr(vfs_handle_struct
*handle
, const char *path
,
523 char *list
, size_t size
)
525 SHADOW_NEXT(LLISTXATTR
,
526 (handle
, cpath
?: path
, list
, size
),
531 onefs_shadow_copy_removexattr(vfs_handle_struct
*handle
, const char *path
,
534 SHADOW_NEXT(REMOVEXATTR
,
535 (handle
, cpath
?: path
, name
),
540 onefs_shadow_copy_lremovexattr(vfs_handle_struct
*handle
, const char *path
,
543 SHADOW_NEXT(LREMOVEXATTR
,
544 (handle
, cpath
?: path
, name
),
549 onefs_shadow_copy_setxattr(vfs_handle_struct
*handle
, const char *path
,
550 const char *name
, const void *value
, size_t size
,
553 SHADOW_NEXT(SETXATTR
,
554 (handle
, cpath
?: path
, name
, value
, size
, flags
),
559 onefs_shadow_copy_lsetxattr(vfs_handle_struct
*handle
, const char *path
,
560 const char *name
, const void *value
, size_t size
,
563 SHADOW_NEXT(LSETXATTR
,
564 (handle
, cpath
?: path
, name
, value
, size
, flags
),
569 onefs_shadow_copy_is_offline(struct vfs_handle_struct
*handle
,
570 const char *path
, SMB_STRUCT_STAT
*sbuf
)
572 SHADOW_NEXT(IS_OFFLINE
,
573 (handle
, cpath
?: path
, sbuf
),
578 onefs_shadow_copy_set_offline(struct vfs_handle_struct
*handle
,
581 SHADOW_NEXT(SET_OFFLINE
,
582 (handle
, cpath
?: path
),
586 /* VFS operations structure */
588 static vfs_op_tuple onefs_shadow_copy_ops
[] = {
590 /* Disk operations */
592 {SMB_VFS_OP(onefs_shadow_copy_disk_free
), SMB_VFS_OP_DISK_FREE
,
593 SMB_VFS_LAYER_TRANSPARENT
},
594 {SMB_VFS_OP(onefs_shadow_copy_get_shadow_copy_data
),
595 SMB_VFS_OP_GET_SHADOW_COPY_DATA
, SMB_VFS_LAYER_OPAQUE
},
596 {SMB_VFS_OP(onefs_shadow_copy_statvfs
), SMB_VFS_OP_STATVFS
,
597 SMB_VFS_LAYER_TRANSPARENT
},
599 /* Directory operations */
601 {SMB_VFS_OP(onefs_shadow_copy_opendir
), SMB_VFS_OP_OPENDIR
,
602 SMB_VFS_LAYER_TRANSPARENT
},
603 {SMB_VFS_OP(onefs_shadow_copy_mkdir
), SMB_VFS_OP_MKDIR
,
604 SMB_VFS_LAYER_TRANSPARENT
},
605 {SMB_VFS_OP(onefs_shadow_copy_rmdir
), SMB_VFS_OP_RMDIR
,
606 SMB_VFS_LAYER_TRANSPARENT
},
608 /* File operations */
610 {SMB_VFS_OP(onefs_shadow_copy_open
), SMB_VFS_OP_OPEN
,
611 SMB_VFS_LAYER_TRANSPARENT
},
612 {SMB_VFS_OP(onefs_shadow_copy_create_file
), SMB_VFS_OP_CREATE_FILE
,
613 SMB_VFS_LAYER_TRANSPARENT
},
614 {SMB_VFS_OP(onefs_shadow_copy_rename
), SMB_VFS_OP_RENAME
,
615 SMB_VFS_LAYER_TRANSPARENT
},
616 {SMB_VFS_OP(onefs_shadow_copy_stat
), SMB_VFS_OP_STAT
,
617 SMB_VFS_LAYER_TRANSPARENT
},
618 {SMB_VFS_OP(onefs_shadow_copy_stat
), SMB_VFS_OP_STAT
,
619 SMB_VFS_LAYER_TRANSPARENT
},
620 {SMB_VFS_OP(onefs_shadow_copy_lstat
), SMB_VFS_OP_LSTAT
,
621 SMB_VFS_LAYER_TRANSPARENT
},
622 {SMB_VFS_OP(onefs_shadow_copy_unlink
), SMB_VFS_OP_UNLINK
,
623 SMB_VFS_LAYER_TRANSPARENT
},
624 {SMB_VFS_OP(onefs_shadow_copy_chmod
), SMB_VFS_OP_CHMOD
,
625 SMB_VFS_LAYER_TRANSPARENT
},
626 {SMB_VFS_OP(onefs_shadow_copy_chown
), SMB_VFS_OP_CHOWN
,
627 SMB_VFS_LAYER_TRANSPARENT
},
628 {SMB_VFS_OP(onefs_shadow_copy_lchown
), SMB_VFS_OP_LCHOWN
,
629 SMB_VFS_LAYER_TRANSPARENT
},
630 {SMB_VFS_OP(onefs_shadow_copy_chdir
), SMB_VFS_OP_CHDIR
,
631 SMB_VFS_LAYER_TRANSPARENT
},
632 {SMB_VFS_OP(onefs_shadow_copy_ntimes
), SMB_VFS_OP_NTIMES
,
633 SMB_VFS_LAYER_TRANSPARENT
},
634 {SMB_VFS_OP(onefs_shadow_copy_symlink
), SMB_VFS_OP_SYMLINK
,
635 SMB_VFS_LAYER_TRANSPARENT
},
636 {SMB_VFS_OP(onefs_shadow_copy_readlink
), SMB_VFS_OP_READLINK
,
637 SMB_VFS_LAYER_TRANSPARENT
},
638 {SMB_VFS_OP(onefs_shadow_copy_link
), SMB_VFS_OP_LINK
,
639 SMB_VFS_LAYER_TRANSPARENT
},
640 {SMB_VFS_OP(onefs_shadow_copy_mknod
), SMB_VFS_OP_MKNOD
,
641 SMB_VFS_LAYER_TRANSPARENT
},
642 {SMB_VFS_OP(onefs_shadow_copy_realpath
), SMB_VFS_OP_REALPATH
,
643 SMB_VFS_LAYER_TRANSPARENT
},
644 {SMB_VFS_OP(onefs_shadow_copy_chflags
), SMB_VFS_OP_CHFLAGS
,
645 SMB_VFS_LAYER_TRANSPARENT
},
646 {SMB_VFS_OP(onefs_shadow_copy_streaminfo
), SMB_VFS_OP_STREAMINFO
,
647 SMB_VFS_LAYER_TRANSPARENT
},
648 {SMB_VFS_OP(onefs_shadow_copy_get_real_filename
),
649 SMB_VFS_OP_GET_REAL_FILENAME
, SMB_VFS_LAYER_TRANSPARENT
},
651 /* NT File ACL operations */
653 {SMB_VFS_OP(onefs_shadow_copy_get_nt_acl
), SMB_VFS_OP_GET_NT_ACL
,
654 SMB_VFS_LAYER_TRANSPARENT
},
656 /* POSIX ACL operations */
658 {SMB_VFS_OP(onefs_shadow_copy_chmod_acl
), SMB_VFS_OP_CHMOD_ACL
,
659 SMB_VFS_LAYER_TRANSPARENT
},
660 {SMB_VFS_OP(onefs_shadow_copy_sys_acl_get_file
),
661 SMB_VFS_OP_SYS_ACL_GET_FILE
, SMB_VFS_LAYER_TRANSPARENT
},
662 {SMB_VFS_OP(onefs_shadow_copy_sys_acl_set_file
),
663 SMB_VFS_OP_SYS_ACL_SET_FILE
, SMB_VFS_LAYER_TRANSPARENT
},
664 {SMB_VFS_OP(onefs_shadow_copy_sys_acl_delete_def_file
),
665 SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE
, SMB_VFS_LAYER_TRANSPARENT
},
669 {SMB_VFS_OP(onefs_shadow_copy_getxattr
), SMB_VFS_OP_GETXATTR
,
670 SMB_VFS_LAYER_TRANSPARENT
},
671 {SMB_VFS_OP(onefs_shadow_copy_lgetxattr
), SMB_VFS_OP_LGETXATTR
,
672 SMB_VFS_LAYER_TRANSPARENT
},
673 {SMB_VFS_OP(onefs_shadow_copy_listxattr
), SMB_VFS_OP_LISTXATTR
,
674 SMB_VFS_LAYER_TRANSPARENT
},
675 {SMB_VFS_OP(onefs_shadow_copy_llistxattr
), SMB_VFS_OP_LLISTXATTR
,
676 SMB_VFS_LAYER_TRANSPARENT
},
677 {SMB_VFS_OP(onefs_shadow_copy_removexattr
), SMB_VFS_OP_REMOVEXATTR
,
678 SMB_VFS_LAYER_TRANSPARENT
},
679 {SMB_VFS_OP(onefs_shadow_copy_lremovexattr
), SMB_VFS_OP_LREMOVEXATTR
,
680 SMB_VFS_LAYER_TRANSPARENT
},
681 {SMB_VFS_OP(onefs_shadow_copy_setxattr
), SMB_VFS_OP_SETXATTR
,
682 SMB_VFS_LAYER_TRANSPARENT
},
683 {SMB_VFS_OP(onefs_shadow_copy_lsetxattr
), SMB_VFS_OP_LSETXATTR
,
684 SMB_VFS_LAYER_TRANSPARENT
},
686 /* offline operations */
687 {SMB_VFS_OP(onefs_shadow_copy_is_offline
), SMB_VFS_OP_IS_OFFLINE
,
688 SMB_VFS_LAYER_TRANSPARENT
},
689 {SMB_VFS_OP(onefs_shadow_copy_set_offline
), SMB_VFS_OP_SET_OFFLINE
,
690 SMB_VFS_LAYER_TRANSPARENT
},
692 {SMB_VFS_OP(NULL
), SMB_VFS_OP_NOOP
, SMB_VFS_LAYER_NOOP
}
695 NTSTATUS
vfs_shadow_copy_init(void)
699 ret
= smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
701 onefs_shadow_copy_ops
);
703 if (!NT_STATUS_IS_OK(ret
))
706 vfs_onefs_shadow_copy_debug_level
= debug_add_class("onefs_shadow_copy");
708 if (vfs_onefs_shadow_copy_debug_level
== -1) {
709 vfs_onefs_shadow_copy_debug_level
= DBGC_VFS
;
710 DEBUG(0, ("Couldn't register custom debugging class!\n"));
712 DEBUG(10, ("Debug class number of 'onefs_shadow_copy': %d\n",
713 vfs_onefs_shadow_copy_debug_level
));