4 * Implement a fixed mapping of forbidden NT characters in filenames that are
5 * used a lot by the CAD package Catia.
7 * Catia V4 on AIX uses characters like "<*$ a *lot*, all forbidden under
10 * Copyright (C) Volker Lendecke, 2005
11 * Copyright (C) Aravind Srinivasan, 2009
12 * Copyright (C) Guenter Kukkukk, 2013
13 * Copyright (C) Ralph Boehme, 2017
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31 #include "smbd/smbd.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
35 static int vfs_catia_debug_level
= DBGC_VFS
;
38 #define DBGC_CLASS vfs_catia_debug_level
40 #define GLOBAL_SNUM 0xFFFFFFF
42 #define MAP_NUM 0x101 /* max unicode charval / MAP_SIZE */
43 #define T_OFFSET(_v_) ((_v_ % MAP_SIZE))
44 #define T_START(_v_) (((_v_ / MAP_SIZE) * MAP_SIZE))
45 #define T_PICK(_v_) ((_v_ / MAP_SIZE))
47 struct char_mappings
{
48 smb_ucs2_t entry
[MAP_SIZE
][2];
51 struct share_mapping_entry
{
53 struct share_mapping_entry
*next
;
54 struct char_mappings
**mappings
;
59 const struct catia_cache
* const *busy
;
62 char *orig_base_fname
;
66 struct share_mapping_entry
*srt_head
= NULL
;
68 static bool build_table(struct char_mappings
**cmaps
, int value
)
71 int start
= T_START(value
);
73 (*cmaps
) = talloc_zero(NULL
, struct char_mappings
);
78 for (i
= 0; i
< MAP_SIZE
;i
++) {
79 (*cmaps
)->entry
[i
][vfs_translate_to_unix
] = start
+ i
;
80 (*cmaps
)->entry
[i
][vfs_translate_to_windows
] = start
+ i
;
86 static void set_tables(struct char_mappings
**cmaps
,
92 /* set unix -> windows */
93 i
= T_OFFSET(unix_map
);
94 cmaps
[T_PICK(unix_map
)]->entry
[i
][vfs_translate_to_windows
] = windows_map
;
96 /* set windows -> unix */
97 i
= T_OFFSET(windows_map
);
98 cmaps
[T_PICK(windows_map
)]->entry
[i
][vfs_translate_to_unix
] = unix_map
;
101 static bool build_ranges(struct char_mappings
**cmaps
,
106 if (!cmaps
[T_PICK(unix_map
)]) {
107 if (!build_table(&cmaps
[T_PICK(unix_map
)], unix_map
))
111 if (!cmaps
[T_PICK(windows_map
)]) {
112 if (!build_table(&cmaps
[T_PICK(windows_map
)], windows_map
))
116 set_tables(cmaps
, unix_map
, windows_map
);
121 static struct share_mapping_entry
*get_srt(connection_struct
*conn
,
122 struct share_mapping_entry
**global
)
124 struct share_mapping_entry
*share
;
126 for (share
= srt_head
; share
!= NULL
; share
= share
->next
) {
127 if (share
->snum
== GLOBAL_SNUM
)
130 if (share
->snum
== SNUM(conn
))
137 static struct share_mapping_entry
*add_srt(int snum
, const char **mappings
)
143 long unix_map
, windows_map
;
144 struct share_mapping_entry
*ret
= NULL
;
146 ret
= (struct share_mapping_entry
*)
147 TALLOC_ZERO(NULL
, sizeof(struct share_mapping_entry
) +
148 (mappings
? (MAP_NUM
* sizeof(struct char_mappings
*)) : 0));
155 ret
->next
= srt_head
;
159 ret
->mappings
= (struct char_mappings
**) ((unsigned char*) ret
+
160 sizeof(struct share_mapping_entry
));
161 memset(ret
->mappings
, 0,
162 MAP_NUM
* sizeof(struct char_mappings
*));
164 ret
->mappings
= NULL
;
169 * catia mappings are of the form :
170 * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
172 * multiple mappings are comma separated in smb.conf
174 for (i
=0;mappings
[i
];i
++) {
175 fstrcpy(mapping
, mappings
[i
]);
176 unix_map
= strtol(mapping
, &tmp
, 16);
177 if (unix_map
== 0 && errno
== EINVAL
) {
178 DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping
));
181 windows_map
= strtol(++tmp
, NULL
, 16);
182 if (windows_map
== 0 && errno
== EINVAL
) {
183 DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping
));
187 if (!build_ranges(ret
->mappings
, unix_map
, windows_map
)) {
188 DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping
));
196 static bool init_mappings(connection_struct
*conn
,
197 struct share_mapping_entry
**selected_out
)
199 const char **mappings
= NULL
;
200 struct share_mapping_entry
*share_level
= NULL
;
201 struct share_mapping_entry
*global
= NULL
;
203 /* check srt cache */
204 share_level
= get_srt(conn
, &global
);
206 *selected_out
= share_level
;
207 return (share_level
->mappings
!= NULL
);
210 /* see if we have a global setting */
213 mappings
= lp_parm_string_list(-1, "catia", "mappings", NULL
);
214 global
= add_srt(GLOBAL_SNUM
, mappings
);
217 /* no global setting - what about share level ? */
218 mappings
= lp_parm_string_list(SNUM(conn
), "catia", "mappings", NULL
);
219 share_level
= add_srt(SNUM(conn
), mappings
);
221 if (share_level
->mappings
) {
222 (*selected_out
) = share_level
;
225 if (global
->mappings
) {
226 share_level
->mappings
= global
->mappings
;
227 (*selected_out
) = share_level
;
234 static NTSTATUS
catia_string_replace_allocate(connection_struct
*conn
,
237 enum vfs_translate_direction direction
)
239 static smb_ucs2_t
*tmpbuf
= NULL
;
241 struct share_mapping_entry
*selected
;
242 struct char_mappings
*map
= NULL
;
243 size_t converted_size
;
244 TALLOC_CTX
*ctx
= talloc_tos();
246 if (!init_mappings(conn
, &selected
)) {
247 /* No mappings found. Just use the old name */
248 *mapped_name
= talloc_strdup(NULL
, name_in
);
251 return NT_STATUS_NO_MEMORY
;
256 if ((push_ucs2_talloc(ctx
, &tmpbuf
, name_in
,
257 &converted_size
)) == false) {
258 return map_nt_error_from_unix(errno
);
264 map
= selected
->mappings
[T_PICK((*ptr
))];
270 *ptr
= map
->entry
[T_OFFSET((*ptr
))][direction
];
273 if ((pull_ucs2_talloc(ctx
, mapped_name
, tmpbuf
,
274 &converted_size
)) == false) {
276 return map_nt_error_from_unix(errno
);
282 static DIR *catia_opendir(vfs_handle_struct
*handle
,
283 const struct smb_filename
*smb_fname
,
287 char *name_mapped
= NULL
;
290 struct smb_filename
*mapped_smb_fname
= NULL
;
292 status
= catia_string_replace_allocate(handle
->conn
,
293 smb_fname
->base_name
,
295 vfs_translate_to_unix
);
296 if (!NT_STATUS_IS_OK(status
)) {
297 errno
= map_errno_from_nt_status(status
);
301 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
306 if (mapped_smb_fname
== NULL
) {
307 TALLOC_FREE(mapped_smb_fname
);
312 ret
= SMB_VFS_NEXT_OPENDIR(handle
, mapped_smb_fname
, mask
, attr
);
314 TALLOC_FREE(name_mapped
);
315 TALLOC_FREE(mapped_smb_fname
);
321 * TRANSLATE_NAME call which converts the given name to
322 * "WINDOWS displayable" name
324 static NTSTATUS
catia_translate_name(struct vfs_handle_struct
*handle
,
325 const char *orig_name
,
326 enum vfs_translate_direction direction
,
332 NTSTATUS status
, ret
;
335 * Copy the supplied name and free the memory for mapped_name,
336 * already allocated by the caller.
337 * We will be allocating new memory for mapped_name in
338 * catia_string_replace_allocate
340 name
= talloc_strdup(talloc_tos(), orig_name
);
343 return NT_STATUS_NO_MEMORY
;
345 status
= catia_string_replace_allocate(handle
->conn
, name
,
346 &mapped_name
, direction
);
349 if (!NT_STATUS_IS_OK(status
)) {
353 ret
= SMB_VFS_NEXT_TRANSLATE_NAME(handle
, mapped_name
, direction
,
354 mem_ctx
, pmapped_name
);
356 if (NT_STATUS_EQUAL(ret
, NT_STATUS_NONE_MAPPED
)) {
357 *pmapped_name
= talloc_move(mem_ctx
, &mapped_name
);
358 /* we need to return the former translation result here */
361 TALLOC_FREE(mapped_name
);
367 #define CATIA_DEBUG_CC(lvl, cc, fsp) \
368 catia_debug_cc((lvl), (cc), (fsp), __location__);
370 static void catia_debug_cc(int lvl
,
371 struct catia_cache
*cc
,
373 const char *location
)
375 DEBUG(lvl
, ("%s: cc [0x%p] cc->busy [0x%p] "
377 "fsp [0x%p] fsp name [%s] "
380 "orig_base_fname [%s] "
384 cc
->is_fsp_ext
? "yes" : "no",
385 fsp
, fsp_str_dbg(fsp
),
386 cc
->orig_fname
, cc
->fname
,
387 cc
->orig_base_fname
, cc
->base_fname
));
390 static void catia_free_cc(struct catia_cache
**_cc
,
391 vfs_handle_struct
*handle
,
394 struct catia_cache
*cc
= *_cc
;
396 if (cc
->is_fsp_ext
) {
397 VFS_REMOVE_FSP_EXTENSION(handle
, fsp
);
406 static struct catia_cache
*catia_validate_and_apply_cc(
407 vfs_handle_struct
*handle
,
409 const struct catia_cache
* const *busy
,
410 bool *make_tmp_cache
)
412 struct catia_cache
*cc
= NULL
;
414 *make_tmp_cache
= false;
416 cc
= (struct catia_cache
*)VFS_FETCH_FSP_EXTENSION(handle
, fsp
);
421 if (cc
->busy
!= NULL
) {
422 if (cc
->busy
== busy
) {
423 /* This should never happen */
424 CATIA_DEBUG_CC(0, cc
, fsp
);
425 smb_panic(__location__
);
429 * Recursion. Validate names, the names in the fsp's should be
430 * the translated names we had set.
433 if ((cc
->fname
!= fsp
->fsp_name
->base_name
)
435 ((fsp
->base_fsp
!= NULL
) &&
436 (cc
->base_fname
!= fsp
->base_fsp
->fsp_name
->base_name
)))
438 CATIA_DEBUG_CC(10, cc
, fsp
);
441 * Names changed. Setting don't expose the cache on the
442 * fsp and ask the caller to create a temporary cache.
444 *make_tmp_cache
= true;
449 * Ok, a validated cache while in a recursion, just let the
450 * caller detect that cc->busy is != busy and there's
451 * nothing else to do.
453 CATIA_DEBUG_CC(10, cc
, fsp
);
457 /* Not in a recursion */
459 if ((cc
->orig_fname
!= fsp
->fsp_name
->base_name
)
461 ((fsp
->base_fsp
!= NULL
) &&
462 (cc
->orig_base_fname
!= fsp
->base_fsp
->fsp_name
->base_name
)))
465 * fsp names changed, this can happen in an rename op.
466 * Trigger recreation as a full fledged fsp extension.
469 CATIA_DEBUG_CC(10, cc
, fsp
);
470 catia_free_cc(&cc
, handle
, fsp
);
476 * Ok, we found a valid cache entry, no recursion. Just set translated
477 * names from the cache and mark the cc as busy.
479 fsp
->fsp_name
->base_name
= cc
->fname
;
480 if (fsp
->base_fsp
!= NULL
) {
481 fsp
->base_fsp
->fsp_name
->base_name
= cc
->base_fname
;
485 CATIA_DEBUG_CC(10, cc
, fsp
);
489 #define CATIA_FETCH_FSP_PRE_NEXT(mem_ctx, handle, fsp, _cc) \
490 catia_fetch_fsp_pre_next((mem_ctx), (handle), (fsp), (_cc), __func__);
492 static int catia_fetch_fsp_pre_next(TALLOC_CTX
*mem_ctx
,
493 vfs_handle_struct
*handle
,
495 struct catia_cache
**_cc
,
496 const char *function
)
498 const struct catia_cache
* const *busy
=
499 (const struct catia_cache
* const *)_cc
;
500 struct catia_cache
*cc
= NULL
;
502 bool make_tmp_cache
= false;
506 DBG_DEBUG("Called from [%s]\n", function
);
508 cc
= catia_validate_and_apply_cc(handle
,
513 if (cc
->busy
!= busy
) {
520 if (!make_tmp_cache
) {
521 cc
= (struct catia_cache
*)VFS_ADD_FSP_EXTENSION(
522 handle
, fsp
, struct catia_cache
, NULL
);
526 *cc
= (struct catia_cache
) {
530 mem_ctx
= VFS_MEMCTX_FSP_EXTENSION(handle
, fsp
);
531 if (mem_ctx
== NULL
) {
532 DBG_ERR("VFS_MEMCTX_FSP_EXTENSION failed\n");
533 catia_free_cc(&cc
, handle
, fsp
);
537 cc
= talloc_zero(mem_ctx
, struct catia_cache
);
545 status
= catia_string_replace_allocate(handle
->conn
,
546 fsp
->fsp_name
->base_name
,
548 vfs_translate_to_unix
);
549 if (!NT_STATUS_IS_OK(status
)) {
550 catia_free_cc(&cc
, handle
, fsp
);
551 errno
= map_errno_from_nt_status(status
);
554 talloc_steal(mem_ctx
, cc
->fname
);
556 if (fsp
->base_fsp
!= NULL
) {
557 status
= catia_string_replace_allocate(
559 fsp
->base_fsp
->fsp_name
->base_name
,
561 vfs_translate_to_unix
);
562 if (!NT_STATUS_IS_OK(status
)) {
563 catia_free_cc(&cc
, handle
, fsp
);
564 errno
= map_errno_from_nt_status(status
);
567 talloc_steal(mem_ctx
, cc
->base_fname
);
570 cc
->orig_fname
= fsp
->fsp_name
->base_name
;
571 fsp
->fsp_name
->base_name
= cc
->fname
;
573 if (fsp
->base_fsp
!= NULL
) {
574 cc
->orig_base_fname
= fsp
->base_fsp
->fsp_name
->base_name
;
575 fsp
->base_fsp
->fsp_name
->base_name
= cc
->base_fname
;
579 CATIA_DEBUG_CC(10, cc
, fsp
);
586 #define CATIA_FETCH_FSP_POST_NEXT(_cc, fsp) do { \
587 int saved_errno = errno; \
588 catia_fetch_fsp_post_next((_cc), (fsp), __func__); \
589 errno = saved_errno; \
592 static void catia_fetch_fsp_post_next(struct catia_cache
**_cc
,
594 const char *function
)
596 const struct catia_cache
* const *busy
=
597 (const struct catia_cache
* const *)_cc
;
598 struct catia_cache
*cc
= *_cc
;
600 DBG_DEBUG("Called from [%s]\n", function
);
604 * This can happen when recursing in the VFS on the fsp when the
605 * pre_next func noticed the recursion and set out cc pointer to
611 if (cc
->busy
!= busy
) {
612 CATIA_DEBUG_CC(0, cc
, fsp
);
613 smb_panic(__location__
);
620 fsp
->fsp_name
->base_name
= cc
->orig_fname
;
621 if (fsp
->base_fsp
!= NULL
) {
622 fsp
->base_fsp
->fsp_name
->base_name
= cc
->orig_base_fname
;
625 CATIA_DEBUG_CC(10, cc
, fsp
);
627 if (!cc
->is_fsp_ext
) {
634 static int catia_open(vfs_handle_struct
*handle
,
635 struct smb_filename
*smb_fname
,
640 struct catia_cache
*cc
= NULL
;
641 char *orig_smb_fname
= smb_fname
->base_name
;
642 char *mapped_smb_fname
= NULL
;
646 status
= catia_string_replace_allocate(handle
->conn
,
647 smb_fname
->base_name
,
649 vfs_translate_to_unix
);
650 if (!NT_STATUS_IS_OK(status
)) {
654 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
656 TALLOC_FREE(mapped_smb_fname
);
660 smb_fname
->base_name
= mapped_smb_fname
;
661 ret
= SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
662 smb_fname
->base_name
= orig_smb_fname
;
664 TALLOC_FREE(mapped_smb_fname
);
665 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
670 static int catia_rename(vfs_handle_struct
*handle
,
671 const struct smb_filename
*smb_fname_src
,
672 const struct smb_filename
*smb_fname_dst
)
674 TALLOC_CTX
*ctx
= talloc_tos();
675 struct smb_filename
*smb_fname_src_tmp
= NULL
;
676 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
677 char *src_name_mapped
= NULL
;
678 char *dst_name_mapped
= NULL
;
682 status
= catia_string_replace_allocate(handle
->conn
,
683 smb_fname_src
->base_name
,
684 &src_name_mapped
, vfs_translate_to_unix
);
685 if (!NT_STATUS_IS_OK(status
)) {
686 errno
= map_errno_from_nt_status(status
);
690 status
= catia_string_replace_allocate(handle
->conn
,
691 smb_fname_dst
->base_name
,
692 &dst_name_mapped
, vfs_translate_to_unix
);
693 if (!NT_STATUS_IS_OK(status
)) {
694 errno
= map_errno_from_nt_status(status
);
698 /* Setup temporary smb_filename structs. */
699 smb_fname_src_tmp
= cp_smb_filename(ctx
, smb_fname_src
);
700 if (smb_fname_src_tmp
== NULL
) {
705 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
706 if (smb_fname_dst_tmp
== NULL
) {
711 smb_fname_src_tmp
->base_name
= src_name_mapped
;
712 smb_fname_dst_tmp
->base_name
= dst_name_mapped
;
713 DEBUG(10, ("converted old name: %s\n",
714 smb_fname_str_dbg(smb_fname_src_tmp
)));
715 DEBUG(10, ("converted new name: %s\n",
716 smb_fname_str_dbg(smb_fname_dst_tmp
)));
718 ret
= SMB_VFS_NEXT_RENAME(handle
, smb_fname_src_tmp
,
721 TALLOC_FREE(src_name_mapped
);
722 TALLOC_FREE(dst_name_mapped
);
723 TALLOC_FREE(smb_fname_src_tmp
);
724 TALLOC_FREE(smb_fname_dst_tmp
);
728 static int catia_stat(vfs_handle_struct
*handle
,
729 struct smb_filename
*smb_fname
)
736 status
= catia_string_replace_allocate(handle
->conn
,
737 smb_fname
->base_name
,
738 &name
, vfs_translate_to_unix
);
739 if (!NT_STATUS_IS_OK(status
)) {
740 errno
= map_errno_from_nt_status(status
);
744 tmp_base_name
= smb_fname
->base_name
;
745 smb_fname
->base_name
= name
;
747 ret
= SMB_VFS_NEXT_STAT(handle
, smb_fname
);
748 smb_fname
->base_name
= tmp_base_name
;
754 static int catia_lstat(vfs_handle_struct
*handle
,
755 struct smb_filename
*smb_fname
)
762 status
= catia_string_replace_allocate(handle
->conn
,
763 smb_fname
->base_name
,
764 &name
, vfs_translate_to_unix
);
765 if (!NT_STATUS_IS_OK(status
)) {
766 errno
= map_errno_from_nt_status(status
);
770 tmp_base_name
= smb_fname
->base_name
;
771 smb_fname
->base_name
= name
;
773 ret
= SMB_VFS_NEXT_LSTAT(handle
, smb_fname
);
774 smb_fname
->base_name
= tmp_base_name
;
780 static int catia_unlink(vfs_handle_struct
*handle
,
781 const struct smb_filename
*smb_fname
)
783 struct smb_filename
*smb_fname_tmp
= NULL
;
788 status
= catia_string_replace_allocate(handle
->conn
,
789 smb_fname
->base_name
,
790 &name
, vfs_translate_to_unix
);
791 if (!NT_STATUS_IS_OK(status
)) {
792 errno
= map_errno_from_nt_status(status
);
796 /* Setup temporary smb_filename structs. */
797 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
798 if (smb_fname_tmp
== NULL
) {
803 smb_fname_tmp
->base_name
= name
;
804 ret
= SMB_VFS_NEXT_UNLINK(handle
, smb_fname_tmp
);
805 TALLOC_FREE(smb_fname_tmp
);
811 static int catia_chown(vfs_handle_struct
*handle
,
812 const struct smb_filename
*smb_fname
,
820 struct smb_filename
*catia_smb_fname
= NULL
;
822 status
= catia_string_replace_allocate(handle
->conn
,
823 smb_fname
->base_name
,
825 vfs_translate_to_unix
);
826 if (!NT_STATUS_IS_OK(status
)) {
827 errno
= map_errno_from_nt_status(status
);
830 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
835 if (catia_smb_fname
== NULL
) {
841 ret
= SMB_VFS_NEXT_CHOWN(handle
, catia_smb_fname
, uid
, gid
);
844 TALLOC_FREE(catia_smb_fname
);
849 static int catia_lchown(vfs_handle_struct
*handle
,
850 const struct smb_filename
*smb_fname
,
858 struct smb_filename
*catia_smb_fname
= NULL
;
860 status
= catia_string_replace_allocate(handle
->conn
,
861 smb_fname
->base_name
,
863 vfs_translate_to_unix
);
864 if (!NT_STATUS_IS_OK(status
)) {
865 errno
= map_errno_from_nt_status(status
);
868 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
873 if (catia_smb_fname
== NULL
) {
879 ret
= SMB_VFS_NEXT_LCHOWN(handle
, catia_smb_fname
, uid
, gid
);
882 TALLOC_FREE(catia_smb_fname
);
887 static int catia_chmod(vfs_handle_struct
*handle
,
888 const struct smb_filename
*smb_fname
,
895 struct smb_filename
*catia_smb_fname
= NULL
;
897 status
= catia_string_replace_allocate(handle
->conn
,
898 smb_fname
->base_name
,
900 vfs_translate_to_unix
);
901 if (!NT_STATUS_IS_OK(status
)) {
902 errno
= map_errno_from_nt_status(status
);
905 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
910 if (catia_smb_fname
== NULL
) {
916 ret
= SMB_VFS_NEXT_CHMOD(handle
, catia_smb_fname
, mode
);
919 TALLOC_FREE(catia_smb_fname
);
924 static int catia_rmdir(vfs_handle_struct
*handle
,
925 const struct smb_filename
*smb_fname
)
930 struct smb_filename
*catia_smb_fname
= NULL
;
932 status
= catia_string_replace_allocate(handle
->conn
,
933 smb_fname
->base_name
,
935 vfs_translate_to_unix
);
936 if (!NT_STATUS_IS_OK(status
)) {
937 errno
= map_errno_from_nt_status(status
);
940 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
945 if (catia_smb_fname
== NULL
) {
951 ret
= SMB_VFS_NEXT_RMDIR(handle
, catia_smb_fname
);
953 TALLOC_FREE(catia_smb_fname
);
958 static int catia_mkdir(vfs_handle_struct
*handle
,
959 const struct smb_filename
*smb_fname
,
965 struct smb_filename
*catia_smb_fname
= NULL
;
967 status
= catia_string_replace_allocate(handle
->conn
,
968 smb_fname
->base_name
,
970 vfs_translate_to_unix
);
971 if (!NT_STATUS_IS_OK(status
)) {
972 errno
= map_errno_from_nt_status(status
);
975 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
980 if (catia_smb_fname
== NULL
) {
986 ret
= SMB_VFS_NEXT_MKDIR(handle
, catia_smb_fname
, mode
);
988 TALLOC_FREE(catia_smb_fname
);
993 static int catia_chdir(vfs_handle_struct
*handle
,
994 const struct smb_filename
*smb_fname
)
997 struct smb_filename
*catia_smb_fname
= NULL
;
1001 status
= catia_string_replace_allocate(handle
->conn
,
1002 smb_fname
->base_name
,
1004 vfs_translate_to_unix
);
1005 if (!NT_STATUS_IS_OK(status
)) {
1006 errno
= map_errno_from_nt_status(status
);
1010 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
1015 if (catia_smb_fname
== NULL
) {
1020 ret
= SMB_VFS_NEXT_CHDIR(handle
, catia_smb_fname
);
1022 TALLOC_FREE(catia_smb_fname
);
1027 static int catia_ntimes(vfs_handle_struct
*handle
,
1028 const struct smb_filename
*smb_fname
,
1029 struct smb_file_time
*ft
)
1031 struct smb_filename
*smb_fname_tmp
= NULL
;
1036 status
= catia_string_replace_allocate(handle
->conn
,
1037 smb_fname
->base_name
,
1038 &name
, vfs_translate_to_unix
);
1039 if (!NT_STATUS_IS_OK(status
)) {
1040 errno
= map_errno_from_nt_status(status
);
1044 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
1045 if (smb_fname_tmp
== NULL
) {
1050 smb_fname_tmp
->base_name
= name
;
1051 ret
= SMB_VFS_NEXT_NTIMES(handle
, smb_fname_tmp
, ft
);
1053 TALLOC_FREE(smb_fname_tmp
);
1058 static struct smb_filename
*
1059 catia_realpath(vfs_handle_struct
*handle
,
1061 const struct smb_filename
*smb_fname
)
1063 char *mapped_name
= NULL
;
1064 struct smb_filename
*catia_smb_fname
= NULL
;
1065 struct smb_filename
*return_fname
= NULL
;
1068 status
= catia_string_replace_allocate(handle
->conn
,
1069 smb_fname
->base_name
,
1070 &mapped_name
, vfs_translate_to_unix
);
1071 if (!NT_STATUS_IS_OK(status
)) {
1072 errno
= map_errno_from_nt_status(status
);
1076 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
1081 if (catia_smb_fname
== NULL
) {
1082 TALLOC_FREE(mapped_name
);
1086 return_fname
= SMB_VFS_NEXT_REALPATH(handle
, ctx
, catia_smb_fname
);
1087 TALLOC_FREE(mapped_name
);
1088 TALLOC_FREE(catia_smb_fname
);
1089 return return_fname
;
1092 static int catia_chflags(struct vfs_handle_struct
*handle
,
1093 const struct smb_filename
*smb_fname
,
1097 struct smb_filename
*catia_smb_fname
= NULL
;
1101 status
= catia_string_replace_allocate(handle
->conn
,
1102 smb_fname
->base_name
,
1104 vfs_translate_to_unix
);
1105 if (!NT_STATUS_IS_OK(status
)) {
1106 errno
= map_errno_from_nt_status(status
);
1109 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
1114 if (catia_smb_fname
== NULL
) {
1120 ret
= SMB_VFS_NEXT_CHFLAGS(handle
, catia_smb_fname
, flags
);
1122 TALLOC_FREE(catia_smb_fname
);
1128 catia_streaminfo(struct vfs_handle_struct
*handle
,
1129 struct files_struct
*fsp
,
1130 const struct smb_filename
*smb_fname
,
1131 TALLOC_CTX
*mem_ctx
,
1132 unsigned int *_num_streams
,
1133 struct stream_struct
**_streams
)
1135 char *mapped_name
= NULL
;
1138 struct smb_filename
*catia_smb_fname
= NULL
;
1139 unsigned int num_streams
= 0;
1140 struct stream_struct
*streams
= NULL
;
1145 status
= catia_string_replace_allocate(handle
->conn
,
1146 smb_fname
->base_name
,
1148 vfs_translate_to_unix
);
1149 if (!NT_STATUS_IS_OK(status
)) {
1150 errno
= map_errno_from_nt_status(status
);
1154 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
1159 if (catia_smb_fname
== NULL
) {
1160 TALLOC_FREE(mapped_name
);
1161 return NT_STATUS_NO_MEMORY
;
1164 status
= SMB_VFS_NEXT_STREAMINFO(handle
, fsp
, catia_smb_fname
,
1165 mem_ctx
, &num_streams
, &streams
);
1166 TALLOC_FREE(mapped_name
);
1167 TALLOC_FREE(catia_smb_fname
);
1168 if (!NT_STATUS_IS_OK(status
)) {
1173 * Translate stream names just like the base names
1175 for (i
= 0; i
< num_streams
; i
++) {
1177 * Strip ":" prefix and ":$DATA" suffix to get a
1178 * "pure" stream name and only translate that.
1180 void *old_ptr
= streams
[i
].name
;
1181 char *stream_name
= streams
[i
].name
+ 1;
1182 char *stream_type
= strrchr_m(stream_name
, ':');
1184 if (stream_type
!= NULL
) {
1185 *stream_type
= '\0';
1189 status
= catia_string_replace_allocate(handle
->conn
, stream_name
,
1190 &mapped_name
, vfs_translate_to_windows
);
1191 if (!NT_STATUS_IS_OK(status
)) {
1192 TALLOC_FREE(streams
);
1196 if (stream_type
!= NULL
) {
1197 streams
[i
].name
= talloc_asprintf(streams
, ":%s:%s",
1198 mapped_name
, stream_type
);
1200 streams
[i
].name
= talloc_asprintf(streams
, ":%s",
1203 TALLOC_FREE(mapped_name
);
1204 TALLOC_FREE(old_ptr
);
1205 if (streams
[i
].name
== NULL
) {
1206 TALLOC_FREE(streams
);
1207 return NT_STATUS_NO_MEMORY
;
1211 *_num_streams
= num_streams
;
1212 *_streams
= streams
;
1213 return NT_STATUS_OK
;
1217 catia_get_nt_acl(struct vfs_handle_struct
*handle
,
1218 const struct smb_filename
*smb_fname
,
1219 uint32_t security_info
,
1220 TALLOC_CTX
*mem_ctx
,
1221 struct security_descriptor
**ppdesc
)
1223 char *mapped_name
= NULL
;
1224 const char *path
= smb_fname
->base_name
;
1225 struct smb_filename
*mapped_smb_fname
= NULL
;
1228 status
= catia_string_replace_allocate(handle
->conn
,
1229 path
, &mapped_name
, vfs_translate_to_unix
);
1230 if (!NT_STATUS_IS_OK(status
)) {
1231 errno
= map_errno_from_nt_status(status
);
1234 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1239 if (mapped_smb_fname
== NULL
) {
1240 TALLOC_FREE(mapped_name
);
1241 return NT_STATUS_NO_MEMORY
;
1244 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
, mapped_smb_fname
,
1245 security_info
, mem_ctx
, ppdesc
);
1246 TALLOC_FREE(mapped_name
);
1247 TALLOC_FREE(mapped_smb_fname
);
1253 catia_chmod_acl(vfs_handle_struct
*handle
,
1254 const struct smb_filename
*smb_fname
,
1257 char *mapped_name
= NULL
;
1258 struct smb_filename
*mapped_smb_fname
= NULL
;
1263 status
= catia_string_replace_allocate(handle
->conn
,
1264 smb_fname
->base_name
,
1266 vfs_translate_to_unix
);
1267 if (!NT_STATUS_IS_OK(status
)) {
1268 errno
= map_errno_from_nt_status(status
);
1272 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1277 if (mapped_smb_fname
== NULL
) {
1278 TALLOC_FREE(mapped_name
);
1282 ret
= SMB_VFS_NEXT_CHMOD_ACL(handle
, mapped_smb_fname
, mode
);
1283 saved_errno
= errno
;
1284 TALLOC_FREE(mapped_name
);
1285 TALLOC_FREE(mapped_smb_fname
);
1286 errno
= saved_errno
;
1291 catia_sys_acl_get_file(vfs_handle_struct
*handle
,
1292 const struct smb_filename
*smb_fname
,
1293 SMB_ACL_TYPE_T type
,
1294 TALLOC_CTX
*mem_ctx
)
1296 char *mapped_name
= NULL
;
1297 struct smb_filename
*mapped_smb_fname
= NULL
;
1300 int saved_errno
= 0;
1302 status
= catia_string_replace_allocate(handle
->conn
,
1303 smb_fname
->base_name
,
1305 vfs_translate_to_unix
);
1306 if (!NT_STATUS_IS_OK(status
)) {
1307 errno
= map_errno_from_nt_status(status
);
1308 return (SMB_ACL_T
)NULL
;
1311 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1316 if (mapped_smb_fname
== NULL
) {
1317 TALLOC_FREE(mapped_name
);
1319 return (SMB_ACL_T
)NULL
;
1322 ret
= SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle
, mapped_smb_fname
,
1324 if (ret
== (SMB_ACL_T
)NULL
) {
1325 saved_errno
= errno
;
1327 TALLOC_FREE(mapped_smb_fname
);
1328 TALLOC_FREE(mapped_name
);
1329 if (saved_errno
!= 0) {
1330 errno
= saved_errno
;
1336 catia_sys_acl_set_file(vfs_handle_struct
*handle
,
1337 const struct smb_filename
*smb_fname
,
1338 SMB_ACL_TYPE_T type
,
1341 struct smb_filename
*mapped_smb_fname
= NULL
;
1342 int saved_errno
= 0;
1343 char *mapped_name
= NULL
;
1347 status
= catia_string_replace_allocate(handle
->conn
,
1348 smb_fname
->base_name
,
1350 vfs_translate_to_unix
);
1351 if (!NT_STATUS_IS_OK(status
)) {
1352 errno
= map_errno_from_nt_status(status
);
1356 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1361 if (mapped_smb_fname
== NULL
) {
1362 TALLOC_FREE(mapped_name
);
1367 ret
= SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle
, mapped_smb_fname
,
1370 saved_errno
= errno
;
1372 TALLOC_FREE(mapped_smb_fname
);
1373 TALLOC_FREE(mapped_name
);
1374 if (saved_errno
!= 0) {
1375 errno
= saved_errno
;
1381 catia_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
1382 const struct smb_filename
*smb_fname
)
1384 struct smb_filename
*mapped_smb_fname
= NULL
;
1385 int saved_errno
= 0;
1386 char *mapped_name
= NULL
;
1390 status
= catia_string_replace_allocate(handle
->conn
,
1391 smb_fname
->base_name
,
1393 vfs_translate_to_unix
);
1394 if (!NT_STATUS_IS_OK(status
)) {
1395 errno
= map_errno_from_nt_status(status
);
1399 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1404 if (mapped_smb_fname
== NULL
) {
1405 TALLOC_FREE(mapped_name
);
1409 ret
= SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle
, mapped_smb_fname
);
1411 saved_errno
= errno
;
1413 TALLOC_FREE(mapped_smb_fname
);
1414 TALLOC_FREE(mapped_name
);
1415 if (saved_errno
!= 0) {
1416 errno
= saved_errno
;
1422 catia_getxattr(vfs_handle_struct
*handle
,
1423 const struct smb_filename
*smb_fname
,
1428 struct smb_filename
*mapped_smb_fname
= NULL
;
1429 char *mapped_name
= NULL
;
1430 char *mapped_ea_name
= NULL
;
1433 int saved_errno
= 0;
1435 status
= catia_string_replace_allocate(handle
->conn
,
1436 smb_fname
->base_name
,
1438 vfs_translate_to_unix
);
1439 if (!NT_STATUS_IS_OK(status
)) {
1440 errno
= map_errno_from_nt_status(status
);
1444 status
= catia_string_replace_allocate(handle
->conn
,
1445 name
, &mapped_ea_name
, vfs_translate_to_unix
);
1446 if (!NT_STATUS_IS_OK(status
)) {
1447 TALLOC_FREE(mapped_name
);
1448 errno
= map_errno_from_nt_status(status
);
1452 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1457 if (mapped_smb_fname
== NULL
) {
1458 TALLOC_FREE(mapped_name
);
1459 TALLOC_FREE(mapped_ea_name
);
1464 ret
= SMB_VFS_NEXT_GETXATTR(handle
, mapped_smb_fname
,
1465 mapped_ea_name
, value
, size
);
1467 saved_errno
= errno
;
1469 TALLOC_FREE(mapped_name
);
1470 TALLOC_FREE(mapped_ea_name
);
1471 TALLOC_FREE(mapped_smb_fname
);
1472 if (saved_errno
!= 0) {
1473 errno
= saved_errno
;
1480 catia_listxattr(vfs_handle_struct
*handle
,
1481 const struct smb_filename
*smb_fname
,
1482 char *list
, size_t size
)
1484 struct smb_filename
*mapped_smb_fname
= NULL
;
1485 char *mapped_name
= NULL
;
1488 int saved_errno
= 0;
1490 status
= catia_string_replace_allocate(handle
->conn
,
1491 smb_fname
->base_name
,
1493 vfs_translate_to_unix
);
1494 if (!NT_STATUS_IS_OK(status
)) {
1495 errno
= map_errno_from_nt_status(status
);
1499 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1504 if (mapped_smb_fname
== NULL
) {
1505 TALLOC_FREE(mapped_name
);
1510 ret
= SMB_VFS_NEXT_LISTXATTR(handle
, mapped_smb_fname
, list
, size
);
1512 saved_errno
= errno
;
1514 TALLOC_FREE(mapped_name
);
1515 TALLOC_FREE(mapped_smb_fname
);
1516 if (saved_errno
!= 0) {
1517 errno
= saved_errno
;
1524 catia_removexattr(vfs_handle_struct
*handle
,
1525 const struct smb_filename
*smb_fname
,
1528 struct smb_filename
*mapped_smb_fname
= NULL
;
1529 char *mapped_name
= NULL
;
1530 char *mapped_ea_name
= NULL
;
1533 int saved_errno
= 0;
1535 status
= catia_string_replace_allocate(handle
->conn
,
1536 smb_fname
->base_name
,
1538 vfs_translate_to_unix
);
1539 if (!NT_STATUS_IS_OK(status
)) {
1540 errno
= map_errno_from_nt_status(status
);
1544 status
= catia_string_replace_allocate(handle
->conn
,
1545 name
, &mapped_ea_name
, vfs_translate_to_unix
);
1546 if (!NT_STATUS_IS_OK(status
)) {
1547 TALLOC_FREE(mapped_name
);
1548 errno
= map_errno_from_nt_status(status
);
1552 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1557 if (mapped_smb_fname
== NULL
) {
1558 TALLOC_FREE(mapped_name
);
1559 TALLOC_FREE(mapped_ea_name
);
1564 ret
= SMB_VFS_NEXT_REMOVEXATTR(handle
, mapped_smb_fname
,
1567 saved_errno
= errno
;
1569 TALLOC_FREE(mapped_name
);
1570 TALLOC_FREE(mapped_ea_name
);
1571 TALLOC_FREE(mapped_smb_fname
);
1572 if (saved_errno
!= 0) {
1573 errno
= saved_errno
;
1580 catia_setxattr(vfs_handle_struct
*handle
,
1581 const struct smb_filename
*smb_fname
,
1587 struct smb_filename
*mapped_smb_fname
= NULL
;
1588 char *mapped_name
= NULL
;
1589 char *mapped_ea_name
= NULL
;
1592 int saved_errno
= 0;
1594 status
= catia_string_replace_allocate(handle
->conn
,
1595 smb_fname
->base_name
,
1597 vfs_translate_to_unix
);
1598 if (!NT_STATUS_IS_OK(status
)) {
1599 errno
= map_errno_from_nt_status(status
);
1603 status
= catia_string_replace_allocate(handle
->conn
,
1604 name
, &mapped_ea_name
, vfs_translate_to_unix
);
1605 if (!NT_STATUS_IS_OK(status
)) {
1606 TALLOC_FREE(mapped_name
);
1607 errno
= map_errno_from_nt_status(status
);
1611 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1616 if (mapped_smb_fname
== NULL
) {
1617 TALLOC_FREE(mapped_name
);
1618 TALLOC_FREE(mapped_ea_name
);
1623 ret
= SMB_VFS_NEXT_SETXATTR(handle
, mapped_smb_fname
, mapped_ea_name
,
1624 value
, size
, flags
);
1626 saved_errno
= errno
;
1628 TALLOC_FREE(mapped_name
);
1629 TALLOC_FREE(mapped_ea_name
);
1630 TALLOC_FREE(mapped_smb_fname
);
1631 if (saved_errno
!= 0) {
1632 errno
= saved_errno
;
1638 static int catia_fstat(vfs_handle_struct
*handle
,
1640 SMB_STRUCT_STAT
*sbuf
)
1642 struct catia_cache
*cc
= NULL
;
1645 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1650 ret
= SMB_VFS_NEXT_FSTAT(handle
, fsp
, sbuf
);
1652 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1657 static ssize_t
catia_pread(vfs_handle_struct
*handle
,
1658 files_struct
*fsp
, void *data
,
1659 size_t n
, off_t offset
)
1661 struct catia_cache
*cc
= NULL
;
1665 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1670 result
= SMB_VFS_NEXT_PREAD(handle
, fsp
, data
, n
, offset
);
1672 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1677 static ssize_t
catia_pwrite(vfs_handle_struct
*handle
,
1678 files_struct
*fsp
, const void *data
,
1679 size_t n
, off_t offset
)
1681 struct catia_cache
*cc
= NULL
;
1685 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1690 result
= SMB_VFS_NEXT_PWRITE(handle
, fsp
, data
, n
, offset
);
1692 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1697 static int catia_ftruncate(struct vfs_handle_struct
*handle
,
1698 struct files_struct
*fsp
,
1701 struct catia_cache
*cc
= NULL
;
1704 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1709 ret
= SMB_VFS_NEXT_FTRUNCATE(handle
, fsp
, offset
);
1711 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1716 static int catia_fallocate(struct vfs_handle_struct
*handle
,
1717 struct files_struct
*fsp
,
1722 struct catia_cache
*cc
= NULL
;
1725 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1730 ret
= SMB_VFS_NEXT_FALLOCATE(handle
, fsp
, mode
, offset
, len
);
1732 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1737 static ssize_t
catia_fgetxattr(struct vfs_handle_struct
*handle
,
1738 struct files_struct
*fsp
,
1743 char *mapped_xattr_name
= NULL
;
1747 status
= catia_string_replace_allocate(handle
->conn
,
1748 name
, &mapped_xattr_name
,
1749 vfs_translate_to_unix
);
1750 if (!NT_STATUS_IS_OK(status
)) {
1751 errno
= map_errno_from_nt_status(status
);
1755 result
= SMB_VFS_NEXT_FGETXATTR(handle
, fsp
, mapped_xattr_name
,
1758 TALLOC_FREE(mapped_xattr_name
);
1763 static ssize_t
catia_flistxattr(struct vfs_handle_struct
*handle
,
1764 struct files_struct
*fsp
,
1768 struct catia_cache
*cc
= NULL
;
1772 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1777 result
= SMB_VFS_NEXT_FLISTXATTR(handle
, fsp
, list
, size
);
1779 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1784 static int catia_fremovexattr(struct vfs_handle_struct
*handle
,
1785 struct files_struct
*fsp
,
1788 char *mapped_name
= NULL
;
1792 status
= catia_string_replace_allocate(handle
->conn
,
1793 name
, &mapped_name
, vfs_translate_to_unix
);
1794 if (!NT_STATUS_IS_OK(status
)) {
1795 errno
= map_errno_from_nt_status(status
);
1799 ret
= SMB_VFS_NEXT_FREMOVEXATTR(handle
, fsp
, mapped_name
);
1801 TALLOC_FREE(mapped_name
);
1806 static int catia_fsetxattr(struct vfs_handle_struct
*handle
,
1807 struct files_struct
*fsp
,
1813 char *mapped_xattr_name
= NULL
;
1817 status
= catia_string_replace_allocate(
1818 handle
->conn
, name
, &mapped_xattr_name
, vfs_translate_to_unix
);
1819 if (!NT_STATUS_IS_OK(status
)) {
1820 errno
= map_errno_from_nt_status(status
);
1824 ret
= SMB_VFS_NEXT_FSETXATTR(handle
, fsp
, mapped_xattr_name
,
1825 value
, size
, flags
);
1827 TALLOC_FREE(mapped_xattr_name
);
1832 static SMB_ACL_T
catia_sys_acl_get_fd(vfs_handle_struct
*handle
,
1834 TALLOC_CTX
*mem_ctx
)
1836 struct catia_cache
*cc
= NULL
;
1837 struct smb_acl_t
*result
= NULL
;
1840 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1845 result
= SMB_VFS_NEXT_SYS_ACL_GET_FD(handle
, fsp
, mem_ctx
);
1847 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1852 static int catia_sys_acl_blob_get_fd(vfs_handle_struct
*handle
,
1854 TALLOC_CTX
*mem_ctx
,
1855 char **blob_description
,
1858 struct catia_cache
*cc
= NULL
;
1861 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1866 ret
= SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle
, fsp
, mem_ctx
,
1867 blob_description
, blob
);
1869 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1874 static int catia_sys_acl_set_fd(vfs_handle_struct
*handle
,
1878 struct catia_cache
*cc
= NULL
;
1881 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1886 ret
= SMB_VFS_NEXT_SYS_ACL_SET_FD(handle
, fsp
, theacl
);
1888 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1893 static int catia_fchmod_acl(vfs_handle_struct
*handle
,
1897 struct catia_cache
*cc
= NULL
;
1900 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1905 ret
= SMB_VFS_NEXT_FCHMOD_ACL(handle
, fsp
, mode
);
1907 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1912 static NTSTATUS
catia_fget_nt_acl(vfs_handle_struct
*handle
,
1914 uint32_t security_info
,
1915 TALLOC_CTX
*mem_ctx
,
1916 struct security_descriptor
**ppdesc
)
1918 struct catia_cache
*cc
= NULL
;
1922 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1924 return map_nt_error_from_unix(errno
);
1927 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
, fsp
, security_info
,
1930 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1935 static NTSTATUS
catia_fset_nt_acl(vfs_handle_struct
*handle
,
1937 uint32_t security_info_sent
,
1938 const struct security_descriptor
*psd
)
1940 struct catia_cache
*cc
= NULL
;
1944 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1946 return map_nt_error_from_unix(errno
);
1949 status
= SMB_VFS_NEXT_FSET_NT_ACL(handle
, fsp
, security_info_sent
, psd
);
1951 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1956 static NTSTATUS
catia_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1957 struct files_struct
*fsp
,
1960 struct catia_cache
*cc
= NULL
;
1964 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1966 return map_nt_error_from_unix(errno
);
1969 status
= SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle
, fsp
, dosmode
);
1971 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1976 static NTSTATUS
catia_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1977 struct files_struct
*fsp
,
1980 struct catia_cache
*cc
= NULL
;
1984 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1986 return map_nt_error_from_unix(errno
);
1989 status
= SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle
, fsp
, dosmode
);
1991 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1996 static int catia_fchown(vfs_handle_struct
*handle
,
2001 struct catia_cache
*cc
= NULL
;
2004 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2009 ret
= SMB_VFS_NEXT_FCHOWN(handle
, fsp
, uid
, gid
);
2011 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2016 static int catia_fchmod(vfs_handle_struct
*handle
,
2020 struct catia_cache
*cc
= NULL
;
2023 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2028 ret
= SMB_VFS_NEXT_FCHMOD(handle
, fsp
, mode
);
2030 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2035 struct catia_pread_state
{
2037 struct vfs_aio_state vfs_aio_state
;
2038 struct files_struct
*fsp
;
2039 struct catia_cache
*cc
;
2042 static void catia_pread_done(struct tevent_req
*subreq
);
2044 static struct tevent_req
*catia_pread_send(struct vfs_handle_struct
*handle
,
2045 TALLOC_CTX
*mem_ctx
,
2046 struct tevent_context
*ev
,
2047 struct files_struct
*fsp
,
2052 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2053 struct catia_pread_state
*state
= NULL
;
2056 req
= tevent_req_create(mem_ctx
, &state
,
2057 struct catia_pread_state
);
2063 ret
= CATIA_FETCH_FSP_PRE_NEXT(state
, handle
, fsp
, &state
->cc
);
2065 tevent_req_error(req
, errno
);
2066 return tevent_req_post(req
, ev
);
2069 subreq
= SMB_VFS_NEXT_PREAD_SEND(state
, ev
, handle
, fsp
, data
,
2071 if (tevent_req_nomem(subreq
, req
)) {
2072 return tevent_req_post(req
, ev
);
2074 tevent_req_set_callback(subreq
, catia_pread_done
, req
);
2079 static void catia_pread_done(struct tevent_req
*subreq
)
2081 struct tevent_req
*req
= tevent_req_callback_data(
2082 subreq
, struct tevent_req
);
2083 struct catia_pread_state
*state
= tevent_req_data(
2084 req
, struct catia_pread_state
);
2086 state
->ret
= SMB_VFS_PREAD_RECV(subreq
, &state
->vfs_aio_state
);
2087 TALLOC_FREE(subreq
);
2089 CATIA_FETCH_FSP_POST_NEXT(&state
->cc
, state
->fsp
);
2091 tevent_req_done(req
);
2094 static ssize_t
catia_pread_recv(struct tevent_req
*req
,
2095 struct vfs_aio_state
*vfs_aio_state
)
2097 struct catia_pread_state
*state
= tevent_req_data(
2098 req
, struct catia_pread_state
);
2100 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
2104 *vfs_aio_state
= state
->vfs_aio_state
;
2108 struct catia_pwrite_state
{
2110 struct vfs_aio_state vfs_aio_state
;
2111 struct files_struct
*fsp
;
2112 struct catia_cache
*cc
;
2115 static void catia_pwrite_done(struct tevent_req
*subreq
);
2117 static struct tevent_req
*catia_pwrite_send(struct vfs_handle_struct
*handle
,
2118 TALLOC_CTX
*mem_ctx
,
2119 struct tevent_context
*ev
,
2120 struct files_struct
*fsp
,
2125 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2126 struct catia_pwrite_state
*state
= NULL
;
2129 req
= tevent_req_create(mem_ctx
, &state
,
2130 struct catia_pwrite_state
);
2136 ret
= CATIA_FETCH_FSP_PRE_NEXT(state
, handle
, fsp
, &state
->cc
);
2138 tevent_req_error(req
, errno
);
2139 return tevent_req_post(req
, ev
);
2142 subreq
= SMB_VFS_NEXT_PWRITE_SEND(state
, ev
, handle
, fsp
, data
,
2144 if (tevent_req_nomem(subreq
, req
)) {
2145 return tevent_req_post(req
, ev
);
2147 tevent_req_set_callback(subreq
, catia_pwrite_done
, req
);
2152 static void catia_pwrite_done(struct tevent_req
*subreq
)
2154 struct tevent_req
*req
= tevent_req_callback_data(
2155 subreq
, struct tevent_req
);
2156 struct catia_pwrite_state
*state
= tevent_req_data(
2157 req
, struct catia_pwrite_state
);
2159 state
->ret
= SMB_VFS_PWRITE_RECV(subreq
, &state
->vfs_aio_state
);
2160 TALLOC_FREE(subreq
);
2162 CATIA_FETCH_FSP_POST_NEXT(&state
->cc
, state
->fsp
);
2164 tevent_req_done(req
);
2167 static ssize_t
catia_pwrite_recv(struct tevent_req
*req
,
2168 struct vfs_aio_state
*vfs_aio_state
)
2170 struct catia_pwrite_state
*state
= tevent_req_data(
2171 req
, struct catia_pwrite_state
);
2173 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
2177 *vfs_aio_state
= state
->vfs_aio_state
;
2181 static off_t
catia_lseek(vfs_handle_struct
*handle
,
2186 struct catia_cache
*cc
= NULL
;
2190 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2195 result
= SMB_VFS_NEXT_LSEEK(handle
, fsp
, offset
, whence
);
2197 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2202 static int catia_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
2204 struct catia_cache
*cc
= NULL
;
2207 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2212 ret
= SMB_VFS_NEXT_FSYNC(handle
, fsp
);
2214 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2219 struct catia_fsync_state
{
2221 struct vfs_aio_state vfs_aio_state
;
2222 struct files_struct
*fsp
;
2223 struct catia_cache
*cc
;
2226 static void catia_fsync_done(struct tevent_req
*subreq
);
2228 static struct tevent_req
*catia_fsync_send(struct vfs_handle_struct
*handle
,
2229 TALLOC_CTX
*mem_ctx
,
2230 struct tevent_context
*ev
,
2231 struct files_struct
*fsp
)
2233 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2234 struct catia_fsync_state
*state
= NULL
;
2237 req
= tevent_req_create(mem_ctx
, &state
,
2238 struct catia_fsync_state
);
2244 ret
= CATIA_FETCH_FSP_PRE_NEXT(state
, handle
, fsp
, &state
->cc
);
2246 tevent_req_error(req
, errno
);
2247 return tevent_req_post(req
, ev
);
2250 subreq
= SMB_VFS_NEXT_FSYNC_SEND(state
, ev
, handle
, fsp
);
2251 if (tevent_req_nomem(subreq
, req
)) {
2252 return tevent_req_post(req
, ev
);
2254 tevent_req_set_callback(subreq
, catia_fsync_done
, req
);
2259 static void catia_fsync_done(struct tevent_req
*subreq
)
2261 struct tevent_req
*req
= tevent_req_callback_data(
2262 subreq
, struct tevent_req
);
2263 struct catia_fsync_state
*state
= tevent_req_data(
2264 req
, struct catia_fsync_state
);
2266 state
->ret
= SMB_VFS_FSYNC_RECV(subreq
, &state
->vfs_aio_state
);
2267 TALLOC_FREE(subreq
);
2269 CATIA_FETCH_FSP_POST_NEXT(&state
->cc
, state
->fsp
);
2271 tevent_req_done(req
);
2274 static int catia_fsync_recv(struct tevent_req
*req
,
2275 struct vfs_aio_state
*vfs_aio_state
)
2277 struct catia_fsync_state
*state
= tevent_req_data(
2278 req
, struct catia_fsync_state
);
2280 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
2284 *vfs_aio_state
= state
->vfs_aio_state
;
2288 static bool catia_lock(vfs_handle_struct
*handle
,
2295 struct catia_cache
*cc
= NULL
;
2299 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2304 ok
= SMB_VFS_NEXT_LOCK(handle
, fsp
, op
, offset
, count
, type
);
2306 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2311 static int catia_kernel_flock(struct vfs_handle_struct
*handle
,
2312 struct files_struct
*fsp
,
2313 uint32_t share_mode
,
2314 uint32_t access_mask
)
2316 struct catia_cache
*cc
= NULL
;
2319 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2324 ret
= SMB_VFS_NEXT_KERNEL_FLOCK(handle
, fsp
, share_mode
, access_mask
);
2326 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2331 static int catia_linux_setlease(vfs_handle_struct
*handle
,
2335 struct catia_cache
*cc
= NULL
;
2338 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2343 ret
= SMB_VFS_NEXT_LINUX_SETLEASE(handle
, fsp
, leasetype
);
2345 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2350 static bool catia_getlock(vfs_handle_struct
*handle
,
2357 struct catia_cache
*cc
= NULL
;
2361 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2366 ok
= SMB_VFS_NEXT_GETLOCK(handle
, fsp
, poffset
, pcount
, ptype
, ppid
);
2368 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2373 static bool catia_strict_lock_check(struct vfs_handle_struct
*handle
,
2374 struct files_struct
*fsp
,
2375 struct lock_struct
*plock
)
2377 struct catia_cache
*cc
= NULL
;
2381 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2386 ok
= SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle
, fsp
, plock
);
2388 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2393 static NTSTATUS
catia_fsctl(struct vfs_handle_struct
*handle
,
2394 struct files_struct
*fsp
,
2398 const uint8_t *_in_data
,
2400 uint8_t **_out_data
,
2401 uint32_t max_out_len
,
2405 struct catia_cache
*cc
= NULL
;
2408 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2410 return map_nt_error_from_unix(errno
);
2413 result
= SMB_VFS_NEXT_FSCTL(handle
,
2424 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2429 static NTSTATUS
catia_get_compression(vfs_handle_struct
*handle
,
2430 TALLOC_CTX
*mem_ctx
,
2431 struct files_struct
*fsp
,
2432 struct smb_filename
*smb_fname
,
2433 uint16_t *_compression_fmt
)
2436 struct catia_cache
*cc
= NULL
;
2439 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2441 return map_nt_error_from_unix(errno
);
2444 result
= SMB_VFS_NEXT_GET_COMPRESSION(handle
, mem_ctx
, fsp
, smb_fname
,
2447 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2452 static NTSTATUS
catia_set_compression(vfs_handle_struct
*handle
,
2453 TALLOC_CTX
*mem_ctx
,
2454 struct files_struct
*fsp
,
2455 uint16_t compression_fmt
)
2458 struct catia_cache
*cc
= NULL
;
2461 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2463 return map_nt_error_from_unix(errno
);
2466 result
= SMB_VFS_NEXT_SET_COMPRESSION(handle
, mem_ctx
, fsp
,
2469 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2474 static NTSTATUS
catia_readdir_attr(struct vfs_handle_struct
*handle
,
2475 const struct smb_filename
*smb_fname_in
,
2476 TALLOC_CTX
*mem_ctx
,
2477 struct readdir_attr_data
**pattr_data
)
2479 struct smb_filename
*smb_fname
;
2483 status
= catia_string_replace_allocate(handle
->conn
,
2484 smb_fname_in
->base_name
,
2486 vfs_translate_to_unix
);
2487 if (!NT_STATUS_IS_OK(status
)) {
2488 errno
= map_errno_from_nt_status(status
);
2492 smb_fname
= synthetic_smb_fname(talloc_tos(), fname
, NULL
,
2493 &smb_fname_in
->st
, 0);
2495 status
= SMB_VFS_NEXT_READDIR_ATTR(handle
, smb_fname
, mem_ctx
, pattr_data
);
2497 TALLOC_FREE(smb_fname
);
2501 static NTSTATUS
catia_get_dos_attributes(struct vfs_handle_struct
*handle
,
2502 struct smb_filename
*smb_fname
,
2505 char *mapped_name
= NULL
;
2506 const char *path
= smb_fname
->base_name
;
2507 struct smb_filename
*mapped_smb_fname
= NULL
;
2510 status
= catia_string_replace_allocate(handle
->conn
,
2511 path
, &mapped_name
, vfs_translate_to_unix
);
2512 if (!NT_STATUS_IS_OK(status
)) {
2513 errno
= map_errno_from_nt_status(status
);
2516 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
2521 if (mapped_smb_fname
== NULL
) {
2522 TALLOC_FREE(mapped_name
);
2523 return NT_STATUS_NO_MEMORY
;
2526 status
= SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle
,
2529 TALLOC_FREE(mapped_name
);
2530 TALLOC_FREE(mapped_smb_fname
);
2535 static NTSTATUS
catia_set_dos_attributes(struct vfs_handle_struct
*handle
,
2536 const struct smb_filename
*smb_fname
,
2539 char *mapped_name
= NULL
;
2540 const char *path
= smb_fname
->base_name
;
2541 struct smb_filename
*mapped_smb_fname
= NULL
;
2544 status
= catia_string_replace_allocate(handle
->conn
,
2545 path
, &mapped_name
, vfs_translate_to_unix
);
2546 if (!NT_STATUS_IS_OK(status
)) {
2547 errno
= map_errno_from_nt_status(status
);
2550 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
2555 if (mapped_smb_fname
== NULL
) {
2556 TALLOC_FREE(mapped_name
);
2557 return NT_STATUS_NO_MEMORY
;
2560 status
= SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle
,
2563 TALLOC_FREE(mapped_name
);
2564 TALLOC_FREE(mapped_smb_fname
);
2569 static struct vfs_fn_pointers vfs_catia_fns
= {
2570 /* Directory operations */
2571 .mkdir_fn
= catia_mkdir
,
2572 .rmdir_fn
= catia_rmdir
,
2573 .opendir_fn
= catia_opendir
,
2574 .readdir_attr_fn
= catia_readdir_attr
,
2576 /* File operations */
2577 .open_fn
= catia_open
,
2578 .pread_fn
= catia_pread
,
2579 .pread_send_fn
= catia_pread_send
,
2580 .pread_recv_fn
= catia_pread_recv
,
2581 .pwrite_fn
= catia_pwrite
,
2582 .pwrite_send_fn
= catia_pwrite_send
,
2583 .pwrite_recv_fn
= catia_pwrite_recv
,
2584 .lseek_fn
= catia_lseek
,
2585 .rename_fn
= catia_rename
,
2586 .fsync_fn
= catia_fsync
,
2587 .fsync_send_fn
= catia_fsync_send
,
2588 .fsync_recv_fn
= catia_fsync_recv
,
2589 .stat_fn
= catia_stat
,
2590 .fstat_fn
= catia_fstat
,
2591 .lstat_fn
= catia_lstat
,
2592 .unlink_fn
= catia_unlink
,
2593 .chmod_fn
= catia_chmod
,
2594 .fchmod_fn
= catia_fchmod
,
2595 .chown_fn
= catia_chown
,
2596 .fchown_fn
= catia_fchown
,
2597 .lchown_fn
= catia_lchown
,
2598 .chdir_fn
= catia_chdir
,
2599 .ntimes_fn
= catia_ntimes
,
2600 .ftruncate_fn
= catia_ftruncate
,
2601 .fallocate_fn
= catia_fallocate
,
2602 .lock_fn
= catia_lock
,
2603 .kernel_flock_fn
= catia_kernel_flock
,
2604 .linux_setlease_fn
= catia_linux_setlease
,
2605 .getlock_fn
= catia_getlock
,
2606 .realpath_fn
= catia_realpath
,
2607 .chflags_fn
= catia_chflags
,
2608 .streaminfo_fn
= catia_streaminfo
,
2609 .strict_lock_check_fn
= catia_strict_lock_check
,
2610 .translate_name_fn
= catia_translate_name
,
2611 .fsctl_fn
= catia_fsctl
,
2612 .get_dos_attributes_fn
= catia_get_dos_attributes
,
2613 .set_dos_attributes_fn
= catia_set_dos_attributes
,
2614 .fset_dos_attributes_fn
= catia_fset_dos_attributes
,
2615 .fget_dos_attributes_fn
= catia_fget_dos_attributes
,
2616 .get_compression_fn
= catia_get_compression
,
2617 .set_compression_fn
= catia_set_compression
,
2619 /* NT ACL operations. */
2620 .get_nt_acl_fn
= catia_get_nt_acl
,
2621 .fget_nt_acl_fn
= catia_fget_nt_acl
,
2622 .fset_nt_acl_fn
= catia_fset_nt_acl
,
2624 /* POSIX ACL operations. */
2625 .chmod_acl_fn
= catia_chmod_acl
,
2626 .fchmod_acl_fn
= catia_fchmod_acl
,
2628 .sys_acl_get_file_fn
= catia_sys_acl_get_file
,
2629 .sys_acl_get_fd_fn
= catia_sys_acl_get_fd
,
2630 .sys_acl_blob_get_fd_fn
= catia_sys_acl_blob_get_fd
,
2631 .sys_acl_set_file_fn
= catia_sys_acl_set_file
,
2632 .sys_acl_set_fd_fn
= catia_sys_acl_set_fd
,
2633 .sys_acl_delete_def_file_fn
= catia_sys_acl_delete_def_file
,
2635 /* EA operations. */
2636 .getxattr_fn
= catia_getxattr
,
2637 .listxattr_fn
= catia_listxattr
,
2638 .removexattr_fn
= catia_removexattr
,
2639 .setxattr_fn
= catia_setxattr
,
2640 .fgetxattr_fn
= catia_fgetxattr
,
2641 .flistxattr_fn
= catia_flistxattr
,
2642 .fremovexattr_fn
= catia_fremovexattr
,
2643 .fsetxattr_fn
= catia_fsetxattr
,
2647 NTSTATUS
vfs_catia_init(TALLOC_CTX
*ctx
)
2651 ret
= smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "catia",
2653 if (!NT_STATUS_IS_OK(ret
))
2656 vfs_catia_debug_level
= debug_add_class("catia");
2657 if (vfs_catia_debug_level
== -1) {
2658 vfs_catia_debug_level
= DBGC_VFS
;
2659 DEBUG(0, ("vfs_catia: Couldn't register custom debugging "
2662 DEBUG(10, ("vfs_catia: Debug class number of "
2663 "'catia': %d\n", vfs_catia_debug_level
));