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
,
706 struct security_descriptor
**ppdesc
)
708 char *mapped_name
= NULL
;
711 status
= catia_string_replace_allocate(handle
->conn
,
712 path
, &mapped_name
, vfs_translate_to_unix
);
713 if (!NT_STATUS_IS_OK(status
)) {
714 errno
= map_errno_from_nt_status(status
);
717 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
, mapped_name
,
718 security_info
, ppdesc
);
719 TALLOC_FREE(mapped_name
);
725 catia_chmod_acl(vfs_handle_struct
*handle
,
729 char *mapped_name
= NULL
;
733 status
= catia_string_replace_allocate(handle
->conn
,
734 path
, &mapped_name
, vfs_translate_to_unix
);
735 if (!NT_STATUS_IS_OK(status
)) {
736 errno
= map_errno_from_nt_status(status
);
740 ret
= SMB_VFS_NEXT_CHMOD_ACL(handle
, mapped_name
, mode
);
741 TALLOC_FREE(mapped_name
);
746 catia_sys_acl_get_file(vfs_handle_struct
*handle
,
750 char *mapped_name
= NULL
;
754 status
= catia_string_replace_allocate(handle
->conn
,
755 path
, &mapped_name
, vfs_translate_to_unix
);
756 if (!NT_STATUS_IS_OK(status
)) {
757 errno
= map_errno_from_nt_status(status
);
761 ret
= SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle
, mapped_name
, type
);
762 TALLOC_FREE(mapped_name
);
768 catia_sys_acl_set_file(vfs_handle_struct
*handle
,
773 char *mapped_name
= NULL
;
777 status
= catia_string_replace_allocate(handle
->conn
,
778 path
, &mapped_name
, vfs_translate_to_unix
);
779 if (!NT_STATUS_IS_OK(status
)) {
780 errno
= map_errno_from_nt_status(status
);
784 ret
= SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle
, mapped_name
, type
, theacl
);
785 TALLOC_FREE(mapped_name
);
791 catia_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
794 char *mapped_name
= NULL
;
798 status
= catia_string_replace_allocate(handle
->conn
,
799 path
, &mapped_name
, vfs_translate_to_unix
);
800 if (!NT_STATUS_IS_OK(status
)) {
801 errno
= map_errno_from_nt_status(status
);
805 ret
= SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle
, mapped_name
);
806 TALLOC_FREE(mapped_name
);
812 catia_getxattr(vfs_handle_struct
*handle
, const char *path
,
813 const char *name
, void *value
, size_t size
)
815 char *mapped_name
= NULL
;
819 status
= catia_string_replace_allocate(handle
->conn
,
820 name
, &mapped_name
, vfs_translate_to_unix
);
821 if (!NT_STATUS_IS_OK(status
)) {
822 errno
= map_errno_from_nt_status(status
);
827 ret
= SMB_VFS_NEXT_GETXATTR(handle
, path
, mapped_name
, value
, size
);
828 TALLOC_FREE(mapped_name
);
834 catia_listxattr(vfs_handle_struct
*handle
, const char *path
,
835 char *list
, size_t size
)
837 char *mapped_name
= NULL
;
841 status
= catia_string_replace_allocate(handle
->conn
,
842 path
, &mapped_name
, vfs_translate_to_unix
);
843 if (!NT_STATUS_IS_OK(status
)) {
844 errno
= map_errno_from_nt_status(status
);
849 ret
= SMB_VFS_NEXT_LISTXATTR(handle
, mapped_name
, list
, size
);
850 TALLOC_FREE(mapped_name
);
856 catia_removexattr(vfs_handle_struct
*handle
, const char *path
,
859 char *mapped_name
= NULL
;
863 status
= catia_string_replace_allocate(handle
->conn
,
864 name
, &mapped_name
, vfs_translate_to_unix
);
865 if (!NT_STATUS_IS_OK(status
)) {
866 errno
= map_errno_from_nt_status(status
);
871 ret
= SMB_VFS_NEXT_REMOVEXATTR(handle
, path
, mapped_name
);
872 TALLOC_FREE(mapped_name
);
878 catia_setxattr(vfs_handle_struct
*handle
, const char *path
,
879 const char *name
, const void *value
, size_t size
,
882 char *mapped_name
= NULL
;
886 status
= catia_string_replace_allocate(handle
->conn
,
887 name
, &mapped_name
, vfs_translate_to_unix
);
888 if (!NT_STATUS_IS_OK(status
)) {
889 errno
= map_errno_from_nt_status(status
);
894 ret
= SMB_VFS_NEXT_SETXATTR(handle
, path
, mapped_name
, value
, size
, flags
);
895 TALLOC_FREE(mapped_name
);
900 static struct vfs_fn_pointers vfs_catia_fns
= {
901 .mkdir_fn
= catia_mkdir
,
902 .rmdir_fn
= catia_rmdir
,
903 .opendir_fn
= catia_opendir
,
904 .open_fn
= catia_open
,
905 .rename_fn
= catia_rename
,
906 .stat_fn
= catia_stat
,
907 .lstat_fn
= catia_lstat
,
908 .unlink_fn
= catia_unlink
,
909 .chown_fn
= catia_chown
,
910 .lchown_fn
= catia_lchown
,
911 .chdir_fn
= catia_chdir
,
912 .ntimes_fn
= catia_ntimes
,
913 .realpath_fn
= catia_realpath
,
914 .chflags_fn
= catia_chflags
,
915 .streaminfo_fn
= catia_streaminfo
,
916 .translate_name_fn
= catia_translate_name
,
917 .get_nt_acl_fn
= catia_get_nt_acl
,
918 .chmod_acl_fn
= catia_chmod_acl
,
919 .sys_acl_get_file_fn
= catia_sys_acl_get_file
,
920 .sys_acl_set_file_fn
= catia_sys_acl_set_file
,
921 .sys_acl_delete_def_file_fn
= catia_sys_acl_delete_def_file
,
922 .getxattr_fn
= catia_getxattr
,
923 .listxattr_fn
= catia_listxattr
,
924 .removexattr_fn
= catia_removexattr
,
925 .setxattr_fn
= catia_setxattr
,
928 NTSTATUS
vfs_catia_init(void)
930 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "catia",