4 * Implement a fixed mapping of forbidden NT characters in filenames that are
5 * used a lot by the CAD package Catia.
7 * Yes, this a BAD BAD UGLY INCOMPLETE hack, but it helps quite some people
8 * out there. Catia V4 on AIX uses characters like "<*$ a *lot*, all forbidden
11 * Copyright (C) Volker Lendecke, 2005
12 * Copyright (C) Aravind Srinivasan, 2009
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <http://www.gnu.org/licenses/>.
30 #include "smbd/smbd.h"
32 #define GLOBAL_SNUM 0xFFFFFFF
34 #define MAP_NUM 0x101 /* max unicode charval / MAP_SIZE */
35 #define T_OFFSET(_v_) ((_v_ % MAP_SIZE))
36 #define T_START(_v_) (((_v_ / MAP_SIZE) * MAP_SIZE))
37 #define T_PICK(_v_) ((_v_ / MAP_SIZE))
39 struct char_mappings
{
40 smb_ucs2_t entry
[MAP_SIZE
][2];
43 struct share_mapping_entry
{
45 struct share_mapping_entry
*next
;
46 struct char_mappings
**mappings
;
49 struct share_mapping_entry
*srt_head
= NULL
;
51 static bool build_table(struct char_mappings
**cmaps
, int value
)
54 int start
= T_START(value
);
56 (*cmaps
) = talloc_zero(NULL
, struct char_mappings
);
61 for (i
= 0; i
< MAP_SIZE
;i
++) {
62 (*cmaps
)->entry
[i
][vfs_translate_to_unix
] = start
+ i
;
63 (*cmaps
)->entry
[i
][vfs_translate_to_windows
] = start
+ i
;
69 static void set_tables(struct char_mappings
**cmaps
,
75 /* set unix -> windows */
76 i
= T_OFFSET(unix_map
);
77 cmaps
[T_PICK(unix_map
)]->entry
[i
][vfs_translate_to_windows
] = windows_map
;
79 /* set windows -> unix */
80 i
= T_OFFSET(windows_map
);
81 cmaps
[T_PICK(windows_map
)]->entry
[i
][vfs_translate_to_unix
] = unix_map
;
84 static bool build_ranges(struct char_mappings
**cmaps
,
89 if (!cmaps
[T_PICK(unix_map
)]) {
90 if (!build_table(&cmaps
[T_PICK(unix_map
)], unix_map
))
94 if (!cmaps
[T_PICK(windows_map
)]) {
95 if (!build_table(&cmaps
[T_PICK(windows_map
)], windows_map
))
99 set_tables(cmaps
, unix_map
, windows_map
);
104 static struct share_mapping_entry
*get_srt(connection_struct
*conn
,
105 struct share_mapping_entry
**global
)
107 struct share_mapping_entry
*share
;
109 for (share
= srt_head
; share
!= NULL
; share
= share
->next
) {
110 if (share
->snum
== GLOBAL_SNUM
)
113 if (share
->snum
== SNUM(conn
))
120 static struct share_mapping_entry
*add_srt(int snum
, const char **mappings
)
126 long unix_map
, windows_map
;
127 struct share_mapping_entry
*ret
= NULL
;
129 ret
= (struct share_mapping_entry
*)
130 TALLOC_ZERO(NULL
, sizeof(struct share_mapping_entry
) +
131 (mappings
? (MAP_NUM
* sizeof(struct char_mappings
*)) : 0));
139 ret
->mappings
= (struct char_mappings
**) ((unsigned char*) ret
+
140 sizeof(struct share_mapping_entry
));
141 memset(ret
->mappings
, 0,
142 MAP_NUM
* sizeof(struct char_mappings
*));
144 ret
->mappings
= NULL
;
149 * catia mappings are of the form :
150 * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
152 * multiple mappings are comma seperated in smb.conf
154 for (i
=0;mappings
[i
];i
++) {
155 fstrcpy(mapping
, mappings
[i
]);
156 unix_map
= strtol(mapping
, &tmp
, 16);
157 if (unix_map
== 0 && errno
== EINVAL
) {
158 DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping
));
161 windows_map
= strtol(++tmp
, NULL
, 16);
162 if (windows_map
== 0 && errno
== EINVAL
) {
163 DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping
));
167 if (!build_ranges(ret
->mappings
, unix_map
, windows_map
)) {
168 DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping
));
173 ret
->next
= srt_head
;
179 static bool init_mappings(connection_struct
*conn
,
180 struct share_mapping_entry
**selected_out
)
182 const char **mappings
= NULL
;
183 struct share_mapping_entry
*share_level
= NULL
;
184 struct share_mapping_entry
*global
= NULL
;
186 /* check srt cache */
187 share_level
= get_srt(conn
, &global
);
189 *selected_out
= share_level
;
190 return (share_level
->mappings
!= NULL
);
193 /* see if we have a global setting */
196 mappings
= lp_parm_string_list(-1, "catia", "mappings", NULL
);
197 global
= add_srt(GLOBAL_SNUM
, mappings
);
200 /* no global setting - what about share level ? */
201 mappings
= lp_parm_string_list(SNUM(conn
), "catia", "mappings", NULL
);
202 share_level
= add_srt(SNUM(conn
), mappings
);
204 if (share_level
->mappings
) {
205 (*selected_out
) = share_level
;
207 } else if (global
->mappings
) {
208 share_level
->mappings
= global
->mappings
;
209 (*selected_out
) = share_level
;
216 static NTSTATUS
catia_string_replace_allocate(connection_struct
*conn
,
221 static smb_ucs2_t
*tmpbuf
= NULL
;
223 struct share_mapping_entry
*selected
;
224 struct char_mappings
*map
= NULL
;
225 size_t converted_size
;
226 TALLOC_CTX
*ctx
= talloc_tos();
228 if (!init_mappings(conn
, &selected
)) {
229 /* No mappings found. Just use the old name */
230 *mapped_name
= talloc_strdup(NULL
, name_in
);
233 return NT_STATUS_NO_MEMORY
;
238 if ((push_ucs2_talloc(ctx
, &tmpbuf
, name_in
,
239 &converted_size
)) == false) {
240 return map_nt_error_from_unix(errno
);
246 map
= selected
->mappings
[T_PICK((*ptr
))];
252 *ptr
= map
->entry
[T_OFFSET((*ptr
))][direction
];
255 if ((pull_ucs2_talloc(ctx
, mapped_name
, tmpbuf
,
256 &converted_size
)) == false) {
258 return map_nt_error_from_unix(errno
);
264 static DIR *catia_opendir(vfs_handle_struct
*handle
,
269 char *name_mapped
= NULL
;
273 status
= catia_string_replace_allocate(handle
->conn
, fname
,
274 &name_mapped
, vfs_translate_to_unix
);
275 if (!NT_STATUS_IS_OK(status
)) {
276 errno
= map_errno_from_nt_status(status
);
280 ret
= SMB_VFS_NEXT_OPENDIR(handle
, name_mapped
, mask
, attr
);
281 TALLOC_FREE(name_mapped
);
287 * TRANSLATE_NAME call which converts the given name to
288 * "WINDOWS displayable" name
290 static NTSTATUS
catia_translate_name(struct vfs_handle_struct
*handle
,
291 const char *orig_name
,
292 enum vfs_translate_direction direction
,
301 * Copy the supplied name and free the memory for mapped_name,
302 * already allocated by the caller.
303 * We will be allocating new memory for mapped_name in
304 * catia_string_replace_allocate
306 name
= talloc_strdup(talloc_tos(), orig_name
);
309 return NT_STATUS_NO_MEMORY
;
311 ret
= catia_string_replace_allocate(handle
->conn
, name
,
312 &mapped_name
, direction
);
315 if (!NT_STATUS_IS_OK(ret
)) {
319 ret
= SMB_VFS_NEXT_TRANSLATE_NAME(handle
, mapped_name
, direction
,
320 mem_ctx
, pmapped_name
);
322 if (NT_STATUS_EQUAL(ret
, NT_STATUS_NONE_MAPPED
)) {
323 *pmapped_name
= talloc_move(mem_ctx
, &mapped_name
);
325 TALLOC_FREE(mapped_name
);
331 static int catia_open(vfs_handle_struct
*handle
,
332 struct smb_filename
*smb_fname
,
337 char *name_mapped
= NULL
;
342 tmp_base_name
= smb_fname
->base_name
;
343 status
= catia_string_replace_allocate(handle
->conn
,
344 smb_fname
->base_name
,
345 &name_mapped
, vfs_translate_to_unix
);
346 if (!NT_STATUS_IS_OK(status
)) {
347 errno
= map_errno_from_nt_status(status
);
351 smb_fname
->base_name
= name_mapped
;
352 ret
= SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
353 smb_fname
->base_name
= tmp_base_name
;
354 TALLOC_FREE(name_mapped
);
359 static int catia_rename(vfs_handle_struct
*handle
,
360 const struct smb_filename
*smb_fname_src
,
361 const struct smb_filename
*smb_fname_dst
)
363 TALLOC_CTX
*ctx
= talloc_tos();
364 struct smb_filename
*smb_fname_src_tmp
= NULL
;
365 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
366 char *src_name_mapped
= NULL
;
367 char *dst_name_mapped
= NULL
;
371 status
= catia_string_replace_allocate(handle
->conn
,
372 smb_fname_src
->base_name
,
373 &src_name_mapped
, vfs_translate_to_unix
);
374 if (!NT_STATUS_IS_OK(status
)) {
375 errno
= map_errno_from_nt_status(status
);
379 status
= catia_string_replace_allocate(handle
->conn
,
380 smb_fname_dst
->base_name
,
381 &dst_name_mapped
, vfs_translate_to_unix
);
382 if (!NT_STATUS_IS_OK(status
)) {
383 errno
= map_errno_from_nt_status(status
);
387 /* Setup temporary smb_filename structs. */
388 status
= copy_smb_filename(ctx
, smb_fname_src
, &smb_fname_src_tmp
);
390 if (!NT_STATUS_IS_OK(status
)) {
391 errno
= map_errno_from_nt_status(status
);
395 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
396 if (!NT_STATUS_IS_OK(status
)) {
397 errno
= map_errno_from_nt_status(status
);
401 smb_fname_src_tmp
->base_name
= src_name_mapped
;
402 smb_fname_dst_tmp
->base_name
= dst_name_mapped
;
403 DEBUG(10, ("converted old name: %s\n",
404 smb_fname_str_dbg(smb_fname_src_tmp
)));
405 DEBUG(10, ("converted new name: %s\n",
406 smb_fname_str_dbg(smb_fname_dst_tmp
)));
408 ret
= SMB_VFS_NEXT_RENAME(handle
, smb_fname_src_tmp
,
411 TALLOC_FREE(src_name_mapped
);
412 TALLOC_FREE(dst_name_mapped
);
413 TALLOC_FREE(smb_fname_src_tmp
);
414 TALLOC_FREE(smb_fname_dst_tmp
);
418 static int catia_stat(vfs_handle_struct
*handle
,
419 struct smb_filename
*smb_fname
)
426 status
= catia_string_replace_allocate(handle
->conn
,
427 smb_fname
->base_name
,
428 &name
, vfs_translate_to_unix
);
429 if (!NT_STATUS_IS_OK(status
)) {
430 errno
= map_errno_from_nt_status(status
);
434 tmp_base_name
= smb_fname
->base_name
;
435 smb_fname
->base_name
= name
;
437 ret
= SMB_VFS_NEXT_STAT(handle
, smb_fname
);
438 smb_fname
->base_name
= tmp_base_name
;
444 static int catia_lstat(vfs_handle_struct
*handle
,
445 struct smb_filename
*smb_fname
)
452 status
= catia_string_replace_allocate(handle
->conn
,
453 smb_fname
->base_name
,
454 &name
, vfs_translate_to_unix
);
455 if (!NT_STATUS_IS_OK(status
)) {
456 errno
= map_errno_from_nt_status(status
);
460 tmp_base_name
= smb_fname
->base_name
;
461 smb_fname
->base_name
= name
;
463 ret
= SMB_VFS_NEXT_LSTAT(handle
, smb_fname
);
464 smb_fname
->base_name
= tmp_base_name
;
470 static int catia_unlink(vfs_handle_struct
*handle
,
471 const struct smb_filename
*smb_fname
)
473 struct smb_filename
*smb_fname_tmp
= NULL
;
478 status
= catia_string_replace_allocate(handle
->conn
,
479 smb_fname
->base_name
,
480 &name
, vfs_translate_to_unix
);
481 if (!NT_STATUS_IS_OK(status
)) {
482 errno
= map_errno_from_nt_status(status
);
486 /* Setup temporary smb_filename structs. */
487 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
488 if (!NT_STATUS_IS_OK(status
)) {
489 errno
= map_errno_from_nt_status(status
);
493 smb_fname_tmp
->base_name
= name
;
494 ret
= SMB_VFS_NEXT_UNLINK(handle
, smb_fname_tmp
);
495 TALLOC_FREE(smb_fname_tmp
);
501 static int catia_chown(vfs_handle_struct
*handle
,
510 status
= catia_string_replace_allocate(handle
->conn
, path
,
511 &name
, vfs_translate_to_unix
);
512 if (!NT_STATUS_IS_OK(status
)) {
513 errno
= map_errno_from_nt_status(status
);
517 ret
= SMB_VFS_NEXT_CHOWN(handle
, name
, uid
, gid
);
523 static int catia_lchown(vfs_handle_struct
*handle
,
532 status
= catia_string_replace_allocate(handle
->conn
, path
,
533 &name
, vfs_translate_to_unix
);
534 if (!NT_STATUS_IS_OK(status
)) {
535 errno
= map_errno_from_nt_status(status
);
539 ret
= SMB_VFS_NEXT_LCHOWN(handle
, name
, uid
, gid
);
545 static int catia_rmdir(vfs_handle_struct
*handle
,
552 status
= catia_string_replace_allocate(handle
->conn
, path
,
553 &name
, vfs_translate_to_unix
);
554 if (!NT_STATUS_IS_OK(status
)) {
555 errno
= map_errno_from_nt_status(status
);
559 ret
= SMB_VFS_NEXT_RMDIR(handle
, name
);
565 static int catia_mkdir(vfs_handle_struct
*handle
,
573 status
= catia_string_replace_allocate(handle
->conn
, path
,
574 &name
, vfs_translate_to_unix
);
575 if (!NT_STATUS_IS_OK(status
)) {
576 errno
= map_errno_from_nt_status(status
);
580 ret
= SMB_VFS_NEXT_MKDIR(handle
, name
, mode
);
586 static int catia_chdir(vfs_handle_struct
*handle
,
593 status
= catia_string_replace_allocate(handle
->conn
, path
,
594 &name
, vfs_translate_to_unix
);
595 if (!NT_STATUS_IS_OK(status
)) {
596 errno
= map_errno_from_nt_status(status
);
600 ret
= SMB_VFS_NEXT_CHDIR(handle
, name
);
606 static int catia_ntimes(vfs_handle_struct
*handle
,
607 const struct smb_filename
*smb_fname
,
608 struct smb_file_time
*ft
)
610 struct smb_filename
*smb_fname_tmp
= NULL
;
615 status
= catia_string_replace_allocate(handle
->conn
,
616 smb_fname
->base_name
,
617 &name
, vfs_translate_to_unix
);
618 if (!NT_STATUS_IS_OK(status
)) {
619 errno
= map_errno_from_nt_status(status
);
623 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
624 if (!NT_STATUS_IS_OK(status
)) {
625 errno
= map_errno_from_nt_status(status
);
629 smb_fname_tmp
->base_name
= name
;
630 ret
= SMB_VFS_NEXT_NTIMES(handle
, smb_fname_tmp
, ft
);
632 TALLOC_FREE(smb_fname_tmp
);
638 catia_realpath(vfs_handle_struct
*handle
, const char *path
)
640 char *mapped_name
= NULL
;
644 status
= catia_string_replace_allocate(handle
->conn
, path
,
645 &mapped_name
, vfs_translate_to_unix
);
646 if (!NT_STATUS_IS_OK(status
)) {
647 errno
= map_errno_from_nt_status(status
);
651 ret
= SMB_VFS_NEXT_REALPATH(handle
, mapped_name
);
652 TALLOC_FREE(mapped_name
);
657 static int catia_chflags(struct vfs_handle_struct
*handle
,
658 const char *path
, unsigned int flags
)
660 char *mapped_name
= NULL
;
664 status
= catia_string_replace_allocate(handle
->conn
, path
,
665 &mapped_name
, vfs_translate_to_unix
);
666 if (!NT_STATUS_IS_OK(status
)) {
667 errno
= map_errno_from_nt_status(status
);
671 ret
= SMB_VFS_NEXT_CHFLAGS(handle
, mapped_name
, flags
);
672 TALLOC_FREE(mapped_name
);
678 catia_streaminfo(struct vfs_handle_struct
*handle
,
679 struct files_struct
*fsp
,
682 unsigned int *num_streams
,
683 struct stream_struct
**streams
)
685 char *mapped_name
= NULL
;
688 status
= catia_string_replace_allocate(handle
->conn
, path
,
689 &mapped_name
, vfs_translate_to_unix
);
690 if (!NT_STATUS_IS_OK(status
)) {
691 errno
= map_errno_from_nt_status(status
);
695 status
= SMB_VFS_NEXT_STREAMINFO(handle
, fsp
, mapped_name
,
696 mem_ctx
, num_streams
,streams
);
697 TALLOC_FREE(mapped_name
);
703 catia_get_nt_acl(struct vfs_handle_struct
*handle
,
705 uint32 security_info
,
707 struct security_descriptor
**ppdesc
)
709 char *mapped_name
= NULL
;
712 status
= catia_string_replace_allocate(handle
->conn
,
713 path
, &mapped_name
, vfs_translate_to_unix
);
714 if (!NT_STATUS_IS_OK(status
)) {
715 errno
= map_errno_from_nt_status(status
);
718 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
, mapped_name
,
719 security_info
, mem_ctx
, ppdesc
);
720 TALLOC_FREE(mapped_name
);
726 catia_chmod_acl(vfs_handle_struct
*handle
,
730 char *mapped_name
= NULL
;
734 status
= catia_string_replace_allocate(handle
->conn
,
735 path
, &mapped_name
, vfs_translate_to_unix
);
736 if (!NT_STATUS_IS_OK(status
)) {
737 errno
= map_errno_from_nt_status(status
);
741 ret
= SMB_VFS_NEXT_CHMOD_ACL(handle
, mapped_name
, mode
);
742 TALLOC_FREE(mapped_name
);
747 catia_sys_acl_get_file(vfs_handle_struct
*handle
,
752 char *mapped_name
= NULL
;
756 status
= catia_string_replace_allocate(handle
->conn
,
757 path
, &mapped_name
, vfs_translate_to_unix
);
758 if (!NT_STATUS_IS_OK(status
)) {
759 errno
= map_errno_from_nt_status(status
);
763 ret
= SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle
, mapped_name
, type
, mem_ctx
);
764 TALLOC_FREE(mapped_name
);
770 catia_sys_acl_set_file(vfs_handle_struct
*handle
,
775 char *mapped_name
= NULL
;
779 status
= catia_string_replace_allocate(handle
->conn
,
780 path
, &mapped_name
, vfs_translate_to_unix
);
781 if (!NT_STATUS_IS_OK(status
)) {
782 errno
= map_errno_from_nt_status(status
);
786 ret
= SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle
, mapped_name
, type
, theacl
);
787 TALLOC_FREE(mapped_name
);
793 catia_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
796 char *mapped_name
= NULL
;
800 status
= catia_string_replace_allocate(handle
->conn
,
801 path
, &mapped_name
, vfs_translate_to_unix
);
802 if (!NT_STATUS_IS_OK(status
)) {
803 errno
= map_errno_from_nt_status(status
);
807 ret
= SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle
, mapped_name
);
808 TALLOC_FREE(mapped_name
);
814 catia_getxattr(vfs_handle_struct
*handle
, const char *path
,
815 const char *name
, void *value
, size_t size
)
817 char *mapped_name
= NULL
;
821 status
= catia_string_replace_allocate(handle
->conn
,
822 name
, &mapped_name
, vfs_translate_to_unix
);
823 if (!NT_STATUS_IS_OK(status
)) {
824 errno
= map_errno_from_nt_status(status
);
829 ret
= SMB_VFS_NEXT_GETXATTR(handle
, path
, mapped_name
, value
, size
);
830 TALLOC_FREE(mapped_name
);
836 catia_listxattr(vfs_handle_struct
*handle
, const char *path
,
837 char *list
, size_t size
)
839 char *mapped_name
= NULL
;
843 status
= catia_string_replace_allocate(handle
->conn
,
844 path
, &mapped_name
, vfs_translate_to_unix
);
845 if (!NT_STATUS_IS_OK(status
)) {
846 errno
= map_errno_from_nt_status(status
);
851 ret
= SMB_VFS_NEXT_LISTXATTR(handle
, mapped_name
, list
, size
);
852 TALLOC_FREE(mapped_name
);
858 catia_removexattr(vfs_handle_struct
*handle
, const char *path
,
861 char *mapped_name
= NULL
;
865 status
= catia_string_replace_allocate(handle
->conn
,
866 name
, &mapped_name
, vfs_translate_to_unix
);
867 if (!NT_STATUS_IS_OK(status
)) {
868 errno
= map_errno_from_nt_status(status
);
873 ret
= SMB_VFS_NEXT_REMOVEXATTR(handle
, path
, mapped_name
);
874 TALLOC_FREE(mapped_name
);
880 catia_setxattr(vfs_handle_struct
*handle
, const char *path
,
881 const char *name
, const void *value
, size_t size
,
884 char *mapped_name
= NULL
;
888 status
= catia_string_replace_allocate(handle
->conn
,
889 name
, &mapped_name
, vfs_translate_to_unix
);
890 if (!NT_STATUS_IS_OK(status
)) {
891 errno
= map_errno_from_nt_status(status
);
896 ret
= SMB_VFS_NEXT_SETXATTR(handle
, path
, mapped_name
, value
, size
, flags
);
897 TALLOC_FREE(mapped_name
);
902 static struct vfs_fn_pointers vfs_catia_fns
= {
903 .mkdir_fn
= catia_mkdir
,
904 .rmdir_fn
= catia_rmdir
,
905 .opendir_fn
= catia_opendir
,
906 .open_fn
= catia_open
,
907 .rename_fn
= catia_rename
,
908 .stat_fn
= catia_stat
,
909 .lstat_fn
= catia_lstat
,
910 .unlink_fn
= catia_unlink
,
911 .chown_fn
= catia_chown
,
912 .lchown_fn
= catia_lchown
,
913 .chdir_fn
= catia_chdir
,
914 .ntimes_fn
= catia_ntimes
,
915 .realpath_fn
= catia_realpath
,
916 .chflags_fn
= catia_chflags
,
917 .streaminfo_fn
= catia_streaminfo
,
918 .translate_name_fn
= catia_translate_name
,
919 .get_nt_acl_fn
= catia_get_nt_acl
,
920 .chmod_acl_fn
= catia_chmod_acl
,
921 .sys_acl_get_file_fn
= catia_sys_acl_get_file
,
922 .sys_acl_set_file_fn
= catia_sys_acl_set_file
,
923 .sys_acl_delete_def_file_fn
= catia_sys_acl_delete_def_file
,
924 .getxattr_fn
= catia_getxattr
,
925 .listxattr_fn
= catia_listxattr
,
926 .removexattr_fn
= catia_removexattr
,
927 .setxattr_fn
= catia_setxattr
,
930 NTSTATUS
vfs_catia_init(void)
932 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "catia",