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"
34 #include "string_replace.h"
36 static int vfs_catia_debug_level
= DBGC_VFS
;
39 #define DBGC_CLASS vfs_catia_debug_level
41 struct share_mapping_entry
{
43 struct share_mapping_entry
*next
;
44 struct char_mappings
**mappings
;
49 const struct catia_cache
* const *busy
;
52 char *orig_base_fname
;
56 static struct share_mapping_entry
*srt_head
= NULL
;
58 static struct share_mapping_entry
*get_srt(connection_struct
*conn
,
59 struct share_mapping_entry
**global
)
61 struct share_mapping_entry
*share
;
63 for (share
= srt_head
; share
!= NULL
; share
= share
->next
) {
64 if (share
->snum
== GLOBAL_SECTION_SNUM
)
67 if (share
->snum
== SNUM(conn
))
74 static struct share_mapping_entry
*add_srt(int snum
, const char **mappings
)
76 struct share_mapping_entry
*sme
= NULL
;
78 sme
= TALLOC_ZERO(NULL
, sizeof(struct share_mapping_entry
));
86 if (mappings
== NULL
) {
91 sme
->mappings
= string_replace_init_map(mappings
);
96 static bool init_mappings(connection_struct
*conn
,
97 struct share_mapping_entry
**selected_out
)
99 const char **mappings
= NULL
;
100 struct share_mapping_entry
*share_level
= NULL
;
101 struct share_mapping_entry
*global
= NULL
;
103 /* check srt cache */
104 share_level
= get_srt(conn
, &global
);
106 *selected_out
= share_level
;
107 return (share_level
->mappings
!= NULL
);
110 /* see if we have a global setting */
113 mappings
= lp_parm_string_list(-1, "catia", "mappings", NULL
);
114 global
= add_srt(GLOBAL_SECTION_SNUM
, mappings
);
117 /* no global setting - what about share level ? */
118 mappings
= lp_parm_string_list(SNUM(conn
), "catia", "mappings", NULL
);
119 share_level
= add_srt(SNUM(conn
), mappings
);
121 if (share_level
->mappings
) {
122 (*selected_out
) = share_level
;
125 if (global
->mappings
) {
126 share_level
->mappings
= global
->mappings
;
127 (*selected_out
) = share_level
;
134 static NTSTATUS
catia_string_replace_allocate(connection_struct
*conn
,
137 enum vfs_translate_direction direction
)
139 struct share_mapping_entry
*selected
;
142 if (!init_mappings(conn
, &selected
)) {
143 /* No mappings found. Just use the old name */
144 *mapped_name
= talloc_strdup(talloc_tos(), name_in
);
147 return NT_STATUS_NO_MEMORY
;
152 status
= string_replace_allocate(conn
,
161 static int catia_connect(struct vfs_handle_struct
*handle
,
166 * Unless we have an async implementation of get_dos_attributes turn
169 lp_do_parameter(SNUM(handle
->conn
), "smbd:async dosmode", "false");
171 return SMB_VFS_NEXT_CONNECT(handle
, service
, user
);
174 static DIR *catia_opendir(vfs_handle_struct
*handle
,
175 const struct smb_filename
*smb_fname
,
179 char *name_mapped
= NULL
;
182 struct smb_filename
*mapped_smb_fname
= NULL
;
184 status
= catia_string_replace_allocate(handle
->conn
,
185 smb_fname
->base_name
,
187 vfs_translate_to_unix
);
188 if (!NT_STATUS_IS_OK(status
)) {
189 errno
= map_errno_from_nt_status(status
);
193 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
198 if (mapped_smb_fname
== NULL
) {
199 TALLOC_FREE(mapped_smb_fname
);
204 ret
= SMB_VFS_NEXT_OPENDIR(handle
, mapped_smb_fname
, mask
, attr
);
206 TALLOC_FREE(name_mapped
);
207 TALLOC_FREE(mapped_smb_fname
);
213 * TRANSLATE_NAME call which converts the given name to
214 * "WINDOWS displayable" name
216 static NTSTATUS
catia_translate_name(struct vfs_handle_struct
*handle
,
217 const char *orig_name
,
218 enum vfs_translate_direction direction
,
224 NTSTATUS status
, ret
;
227 * Copy the supplied name and free the memory for mapped_name,
228 * already allocated by the caller.
229 * We will be allocating new memory for mapped_name in
230 * catia_string_replace_allocate
232 name
= talloc_strdup(talloc_tos(), orig_name
);
235 return NT_STATUS_NO_MEMORY
;
237 status
= catia_string_replace_allocate(handle
->conn
, name
,
238 &mapped_name
, direction
);
241 if (!NT_STATUS_IS_OK(status
)) {
245 ret
= SMB_VFS_NEXT_TRANSLATE_NAME(handle
, mapped_name
, direction
,
246 mem_ctx
, pmapped_name
);
248 if (NT_STATUS_EQUAL(ret
, NT_STATUS_NONE_MAPPED
)) {
249 *pmapped_name
= talloc_move(mem_ctx
, &mapped_name
);
250 /* we need to return the former translation result here */
253 TALLOC_FREE(mapped_name
);
259 #define CATIA_DEBUG_CC(lvl, cc, fsp) \
260 catia_debug_cc((lvl), (cc), (fsp), __location__);
262 static void catia_debug_cc(int lvl
,
263 struct catia_cache
*cc
,
265 const char *location
)
267 DEBUG(lvl
, ("%s: cc [%p] cc->busy [%p] "
269 "fsp [%p] fsp name [%s] "
272 "orig_base_fname [%s] "
276 cc
->is_fsp_ext
? "yes" : "no",
277 fsp
, fsp_str_dbg(fsp
),
278 cc
->orig_fname
, cc
->fname
,
279 cc
->orig_base_fname
, cc
->base_fname
));
282 static void catia_free_cc(struct catia_cache
**_cc
,
283 vfs_handle_struct
*handle
,
286 struct catia_cache
*cc
= *_cc
;
288 if (cc
->is_fsp_ext
) {
289 VFS_REMOVE_FSP_EXTENSION(handle
, fsp
);
298 static struct catia_cache
*catia_validate_and_apply_cc(
299 vfs_handle_struct
*handle
,
301 const struct catia_cache
* const *busy
,
302 bool *make_tmp_cache
)
304 struct catia_cache
*cc
= NULL
;
306 *make_tmp_cache
= false;
308 cc
= (struct catia_cache
*)VFS_FETCH_FSP_EXTENSION(handle
, fsp
);
313 if (cc
->busy
!= NULL
) {
314 if (cc
->busy
== busy
) {
315 /* This should never happen */
316 CATIA_DEBUG_CC(0, cc
, fsp
);
317 smb_panic(__location__
);
321 * Recursion. Validate names, the names in the fsp's should be
322 * the translated names we had set.
325 if ((cc
->fname
!= fsp
->fsp_name
->base_name
)
327 ((fsp
->base_fsp
!= NULL
) &&
328 (cc
->base_fname
!= fsp
->base_fsp
->fsp_name
->base_name
)))
330 CATIA_DEBUG_CC(10, cc
, fsp
);
333 * Names changed. Setting don't expose the cache on the
334 * fsp and ask the caller to create a temporary cache.
336 *make_tmp_cache
= true;
341 * Ok, a validated cache while in a recursion, just let the
342 * caller detect that cc->busy is != busy and there's
343 * nothing else to do.
345 CATIA_DEBUG_CC(10, cc
, fsp
);
349 /* Not in a recursion */
351 if ((cc
->orig_fname
!= fsp
->fsp_name
->base_name
)
353 ((fsp
->base_fsp
!= NULL
) &&
354 (cc
->orig_base_fname
!= fsp
->base_fsp
->fsp_name
->base_name
)))
357 * fsp names changed, this can happen in an rename op.
358 * Trigger recreation as a full fledged fsp extension.
361 CATIA_DEBUG_CC(10, cc
, fsp
);
362 catia_free_cc(&cc
, handle
, fsp
);
368 * Ok, we found a valid cache entry, no recursion. Just set translated
369 * names from the cache and mark the cc as busy.
371 fsp
->fsp_name
->base_name
= cc
->fname
;
372 if (fsp
->base_fsp
!= NULL
) {
373 fsp
->base_fsp
->fsp_name
->base_name
= cc
->base_fname
;
377 CATIA_DEBUG_CC(10, cc
, fsp
);
381 #define CATIA_FETCH_FSP_PRE_NEXT(mem_ctx, handle, fsp, _cc) \
382 catia_fetch_fsp_pre_next((mem_ctx), (handle), (fsp), (_cc), __func__);
384 static int catia_fetch_fsp_pre_next(TALLOC_CTX
*mem_ctx
,
385 vfs_handle_struct
*handle
,
387 struct catia_cache
**_cc
,
388 const char *function
)
390 const struct catia_cache
* const *busy
=
391 (const struct catia_cache
* const *)_cc
;
392 struct catia_cache
*cc
= NULL
;
394 bool make_tmp_cache
= false;
398 DBG_DEBUG("Called from [%s]\n", function
);
400 cc
= catia_validate_and_apply_cc(handle
,
405 if (cc
->busy
!= busy
) {
412 if (!make_tmp_cache
) {
413 cc
= VFS_ADD_FSP_EXTENSION(
414 handle
, fsp
, struct catia_cache
, NULL
);
418 *cc
= (struct catia_cache
) {
422 mem_ctx
= VFS_MEMCTX_FSP_EXTENSION(handle
, fsp
);
423 if (mem_ctx
== NULL
) {
424 DBG_ERR("VFS_MEMCTX_FSP_EXTENSION failed\n");
425 catia_free_cc(&cc
, handle
, fsp
);
429 cc
= talloc_zero(mem_ctx
, struct catia_cache
);
437 status
= catia_string_replace_allocate(handle
->conn
,
438 fsp
->fsp_name
->base_name
,
440 vfs_translate_to_unix
);
441 if (!NT_STATUS_IS_OK(status
)) {
442 catia_free_cc(&cc
, handle
, fsp
);
443 errno
= map_errno_from_nt_status(status
);
446 talloc_steal(mem_ctx
, cc
->fname
);
448 if (fsp
->base_fsp
!= NULL
) {
449 status
= catia_string_replace_allocate(
451 fsp
->base_fsp
->fsp_name
->base_name
,
453 vfs_translate_to_unix
);
454 if (!NT_STATUS_IS_OK(status
)) {
455 catia_free_cc(&cc
, handle
, fsp
);
456 errno
= map_errno_from_nt_status(status
);
459 talloc_steal(mem_ctx
, cc
->base_fname
);
462 cc
->orig_fname
= fsp
->fsp_name
->base_name
;
463 fsp
->fsp_name
->base_name
= cc
->fname
;
465 if (fsp
->base_fsp
!= NULL
) {
466 cc
->orig_base_fname
= fsp
->base_fsp
->fsp_name
->base_name
;
467 fsp
->base_fsp
->fsp_name
->base_name
= cc
->base_fname
;
471 CATIA_DEBUG_CC(10, cc
, fsp
);
478 #define CATIA_FETCH_FSP_POST_NEXT(_cc, fsp) do { \
479 int saved_errno = errno; \
480 catia_fetch_fsp_post_next((_cc), (fsp), __func__); \
481 errno = saved_errno; \
484 static void catia_fetch_fsp_post_next(struct catia_cache
**_cc
,
486 const char *function
)
488 const struct catia_cache
* const *busy
=
489 (const struct catia_cache
* const *)_cc
;
490 struct catia_cache
*cc
= *_cc
;
492 DBG_DEBUG("Called from [%s]\n", function
);
496 * This can happen when recursing in the VFS on the fsp when the
497 * pre_next func noticed the recursion and set out cc pointer to
503 if (cc
->busy
!= busy
) {
504 CATIA_DEBUG_CC(0, cc
, fsp
);
505 smb_panic(__location__
);
512 fsp
->fsp_name
->base_name
= cc
->orig_fname
;
513 if (fsp
->base_fsp
!= NULL
) {
514 fsp
->base_fsp
->fsp_name
->base_name
= cc
->orig_base_fname
;
517 CATIA_DEBUG_CC(10, cc
, fsp
);
519 if (!cc
->is_fsp_ext
) {
526 static int catia_open(vfs_handle_struct
*handle
,
527 struct smb_filename
*smb_fname
,
532 struct catia_cache
*cc
= NULL
;
533 char *orig_smb_fname
= smb_fname
->base_name
;
534 char *mapped_smb_fname
= NULL
;
538 status
= catia_string_replace_allocate(handle
->conn
,
539 smb_fname
->base_name
,
541 vfs_translate_to_unix
);
542 if (!NT_STATUS_IS_OK(status
)) {
546 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
548 TALLOC_FREE(mapped_smb_fname
);
552 smb_fname
->base_name
= mapped_smb_fname
;
553 ret
= SMB_VFS_NEXT_OPEN(handle
, smb_fname
, fsp
, flags
, mode
);
554 smb_fname
->base_name
= orig_smb_fname
;
556 TALLOC_FREE(mapped_smb_fname
);
557 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
562 static int catia_rename(vfs_handle_struct
*handle
,
563 const struct smb_filename
*smb_fname_src
,
564 const struct smb_filename
*smb_fname_dst
)
566 TALLOC_CTX
*ctx
= talloc_tos();
567 struct smb_filename
*smb_fname_src_tmp
= NULL
;
568 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
569 char *src_name_mapped
= NULL
;
570 char *dst_name_mapped
= NULL
;
574 status
= catia_string_replace_allocate(handle
->conn
,
575 smb_fname_src
->base_name
,
576 &src_name_mapped
, vfs_translate_to_unix
);
577 if (!NT_STATUS_IS_OK(status
)) {
578 errno
= map_errno_from_nt_status(status
);
582 status
= catia_string_replace_allocate(handle
->conn
,
583 smb_fname_dst
->base_name
,
584 &dst_name_mapped
, vfs_translate_to_unix
);
585 if (!NT_STATUS_IS_OK(status
)) {
586 errno
= map_errno_from_nt_status(status
);
590 /* Setup temporary smb_filename structs. */
591 smb_fname_src_tmp
= cp_smb_filename(ctx
, smb_fname_src
);
592 if (smb_fname_src_tmp
== NULL
) {
597 smb_fname_dst_tmp
= cp_smb_filename(ctx
, smb_fname_dst
);
598 if (smb_fname_dst_tmp
== NULL
) {
603 smb_fname_src_tmp
->base_name
= src_name_mapped
;
604 smb_fname_dst_tmp
->base_name
= dst_name_mapped
;
605 DEBUG(10, ("converted old name: %s\n",
606 smb_fname_str_dbg(smb_fname_src_tmp
)));
607 DEBUG(10, ("converted new name: %s\n",
608 smb_fname_str_dbg(smb_fname_dst_tmp
)));
610 ret
= SMB_VFS_NEXT_RENAME(handle
, smb_fname_src_tmp
,
613 TALLOC_FREE(src_name_mapped
);
614 TALLOC_FREE(dst_name_mapped
);
615 TALLOC_FREE(smb_fname_src_tmp
);
616 TALLOC_FREE(smb_fname_dst_tmp
);
620 static int catia_stat(vfs_handle_struct
*handle
,
621 struct smb_filename
*smb_fname
)
628 status
= catia_string_replace_allocate(handle
->conn
,
629 smb_fname
->base_name
,
630 &name
, vfs_translate_to_unix
);
631 if (!NT_STATUS_IS_OK(status
)) {
632 errno
= map_errno_from_nt_status(status
);
636 tmp_base_name
= smb_fname
->base_name
;
637 smb_fname
->base_name
= name
;
639 ret
= SMB_VFS_NEXT_STAT(handle
, smb_fname
);
640 smb_fname
->base_name
= tmp_base_name
;
646 static int catia_lstat(vfs_handle_struct
*handle
,
647 struct smb_filename
*smb_fname
)
654 status
= catia_string_replace_allocate(handle
->conn
,
655 smb_fname
->base_name
,
656 &name
, vfs_translate_to_unix
);
657 if (!NT_STATUS_IS_OK(status
)) {
658 errno
= map_errno_from_nt_status(status
);
662 tmp_base_name
= smb_fname
->base_name
;
663 smb_fname
->base_name
= name
;
665 ret
= SMB_VFS_NEXT_LSTAT(handle
, smb_fname
);
666 smb_fname
->base_name
= tmp_base_name
;
672 static int catia_unlink(vfs_handle_struct
*handle
,
673 const struct smb_filename
*smb_fname
)
675 struct smb_filename
*smb_fname_tmp
= NULL
;
680 status
= catia_string_replace_allocate(handle
->conn
,
681 smb_fname
->base_name
,
682 &name
, vfs_translate_to_unix
);
683 if (!NT_STATUS_IS_OK(status
)) {
684 errno
= map_errno_from_nt_status(status
);
688 /* Setup temporary smb_filename structs. */
689 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
690 if (smb_fname_tmp
== NULL
) {
695 smb_fname_tmp
->base_name
= name
;
696 ret
= SMB_VFS_NEXT_UNLINK(handle
, smb_fname_tmp
);
697 TALLOC_FREE(smb_fname_tmp
);
703 static int catia_chown(vfs_handle_struct
*handle
,
704 const struct smb_filename
*smb_fname
,
712 struct smb_filename
*catia_smb_fname
= NULL
;
714 status
= catia_string_replace_allocate(handle
->conn
,
715 smb_fname
->base_name
,
717 vfs_translate_to_unix
);
718 if (!NT_STATUS_IS_OK(status
)) {
719 errno
= map_errno_from_nt_status(status
);
722 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
727 if (catia_smb_fname
== NULL
) {
733 ret
= SMB_VFS_NEXT_CHOWN(handle
, catia_smb_fname
, uid
, gid
);
736 TALLOC_FREE(catia_smb_fname
);
741 static int catia_lchown(vfs_handle_struct
*handle
,
742 const struct smb_filename
*smb_fname
,
750 struct smb_filename
*catia_smb_fname
= NULL
;
752 status
= catia_string_replace_allocate(handle
->conn
,
753 smb_fname
->base_name
,
755 vfs_translate_to_unix
);
756 if (!NT_STATUS_IS_OK(status
)) {
757 errno
= map_errno_from_nt_status(status
);
760 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
765 if (catia_smb_fname
== NULL
) {
771 ret
= SMB_VFS_NEXT_LCHOWN(handle
, catia_smb_fname
, uid
, gid
);
774 TALLOC_FREE(catia_smb_fname
);
779 static int catia_chmod(vfs_handle_struct
*handle
,
780 const struct smb_filename
*smb_fname
,
787 struct smb_filename
*catia_smb_fname
= NULL
;
789 status
= catia_string_replace_allocate(handle
->conn
,
790 smb_fname
->base_name
,
792 vfs_translate_to_unix
);
793 if (!NT_STATUS_IS_OK(status
)) {
794 errno
= map_errno_from_nt_status(status
);
797 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
802 if (catia_smb_fname
== NULL
) {
808 ret
= SMB_VFS_NEXT_CHMOD(handle
, catia_smb_fname
, mode
);
811 TALLOC_FREE(catia_smb_fname
);
816 static int catia_rmdir(vfs_handle_struct
*handle
,
817 const struct smb_filename
*smb_fname
)
822 struct smb_filename
*catia_smb_fname
= NULL
;
824 status
= catia_string_replace_allocate(handle
->conn
,
825 smb_fname
->base_name
,
827 vfs_translate_to_unix
);
828 if (!NT_STATUS_IS_OK(status
)) {
829 errno
= map_errno_from_nt_status(status
);
832 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
837 if (catia_smb_fname
== NULL
) {
843 ret
= SMB_VFS_NEXT_RMDIR(handle
, catia_smb_fname
);
845 TALLOC_FREE(catia_smb_fname
);
850 static int catia_mkdir(vfs_handle_struct
*handle
,
851 const struct smb_filename
*smb_fname
,
857 struct smb_filename
*catia_smb_fname
= NULL
;
859 status
= catia_string_replace_allocate(handle
->conn
,
860 smb_fname
->base_name
,
862 vfs_translate_to_unix
);
863 if (!NT_STATUS_IS_OK(status
)) {
864 errno
= map_errno_from_nt_status(status
);
867 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
872 if (catia_smb_fname
== NULL
) {
878 ret
= SMB_VFS_NEXT_MKDIR(handle
, catia_smb_fname
, mode
);
880 TALLOC_FREE(catia_smb_fname
);
885 static int catia_chdir(vfs_handle_struct
*handle
,
886 const struct smb_filename
*smb_fname
)
889 struct smb_filename
*catia_smb_fname
= NULL
;
893 status
= catia_string_replace_allocate(handle
->conn
,
894 smb_fname
->base_name
,
896 vfs_translate_to_unix
);
897 if (!NT_STATUS_IS_OK(status
)) {
898 errno
= map_errno_from_nt_status(status
);
902 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
907 if (catia_smb_fname
== NULL
) {
912 ret
= SMB_VFS_NEXT_CHDIR(handle
, catia_smb_fname
);
914 TALLOC_FREE(catia_smb_fname
);
919 static int catia_ntimes(vfs_handle_struct
*handle
,
920 const struct smb_filename
*smb_fname
,
921 struct smb_file_time
*ft
)
923 struct smb_filename
*smb_fname_tmp
= NULL
;
928 status
= catia_string_replace_allocate(handle
->conn
,
929 smb_fname
->base_name
,
930 &name
, vfs_translate_to_unix
);
931 if (!NT_STATUS_IS_OK(status
)) {
932 errno
= map_errno_from_nt_status(status
);
936 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
937 if (smb_fname_tmp
== NULL
) {
942 smb_fname_tmp
->base_name
= name
;
943 ret
= SMB_VFS_NEXT_NTIMES(handle
, smb_fname_tmp
, ft
);
945 TALLOC_FREE(smb_fname_tmp
);
950 static struct smb_filename
*
951 catia_realpath(vfs_handle_struct
*handle
,
953 const struct smb_filename
*smb_fname
)
955 char *mapped_name
= NULL
;
956 struct smb_filename
*catia_smb_fname
= NULL
;
957 struct smb_filename
*return_fname
= NULL
;
960 status
= catia_string_replace_allocate(handle
->conn
,
961 smb_fname
->base_name
,
962 &mapped_name
, vfs_translate_to_unix
);
963 if (!NT_STATUS_IS_OK(status
)) {
964 errno
= map_errno_from_nt_status(status
);
968 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
973 if (catia_smb_fname
== NULL
) {
974 TALLOC_FREE(mapped_name
);
978 return_fname
= SMB_VFS_NEXT_REALPATH(handle
, ctx
, catia_smb_fname
);
979 TALLOC_FREE(mapped_name
);
980 TALLOC_FREE(catia_smb_fname
);
984 static int catia_chflags(struct vfs_handle_struct
*handle
,
985 const struct smb_filename
*smb_fname
,
989 struct smb_filename
*catia_smb_fname
= NULL
;
993 status
= catia_string_replace_allocate(handle
->conn
,
994 smb_fname
->base_name
,
996 vfs_translate_to_unix
);
997 if (!NT_STATUS_IS_OK(status
)) {
998 errno
= map_errno_from_nt_status(status
);
1001 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
1006 if (catia_smb_fname
== NULL
) {
1012 ret
= SMB_VFS_NEXT_CHFLAGS(handle
, catia_smb_fname
, flags
);
1014 TALLOC_FREE(catia_smb_fname
);
1020 catia_streaminfo(struct vfs_handle_struct
*handle
,
1021 struct files_struct
*fsp
,
1022 const struct smb_filename
*smb_fname
,
1023 TALLOC_CTX
*mem_ctx
,
1024 unsigned int *_num_streams
,
1025 struct stream_struct
**_streams
)
1027 char *mapped_name
= NULL
;
1030 struct smb_filename
*catia_smb_fname
= NULL
;
1031 unsigned int num_streams
= 0;
1032 struct stream_struct
*streams
= NULL
;
1037 status
= catia_string_replace_allocate(handle
->conn
,
1038 smb_fname
->base_name
,
1040 vfs_translate_to_unix
);
1041 if (!NT_STATUS_IS_OK(status
)) {
1042 errno
= map_errno_from_nt_status(status
);
1046 catia_smb_fname
= synthetic_smb_fname(talloc_tos(),
1051 if (catia_smb_fname
== NULL
) {
1052 TALLOC_FREE(mapped_name
);
1053 return NT_STATUS_NO_MEMORY
;
1056 status
= SMB_VFS_NEXT_STREAMINFO(handle
, fsp
, catia_smb_fname
,
1057 mem_ctx
, &num_streams
, &streams
);
1058 TALLOC_FREE(mapped_name
);
1059 TALLOC_FREE(catia_smb_fname
);
1060 if (!NT_STATUS_IS_OK(status
)) {
1065 * Translate stream names just like the base names
1067 for (i
= 0; i
< num_streams
; i
++) {
1069 * Strip ":" prefix and ":$DATA" suffix to get a
1070 * "pure" stream name and only translate that.
1072 void *old_ptr
= streams
[i
].name
;
1073 char *stream_name
= streams
[i
].name
+ 1;
1074 char *stream_type
= strrchr_m(stream_name
, ':');
1076 if (stream_type
!= NULL
) {
1077 *stream_type
= '\0';
1081 status
= catia_string_replace_allocate(handle
->conn
, stream_name
,
1082 &mapped_name
, vfs_translate_to_windows
);
1083 if (!NT_STATUS_IS_OK(status
)) {
1084 TALLOC_FREE(streams
);
1088 if (stream_type
!= NULL
) {
1089 streams
[i
].name
= talloc_asprintf(streams
, ":%s:%s",
1090 mapped_name
, stream_type
);
1092 streams
[i
].name
= talloc_asprintf(streams
, ":%s",
1095 TALLOC_FREE(mapped_name
);
1096 TALLOC_FREE(old_ptr
);
1097 if (streams
[i
].name
== NULL
) {
1098 TALLOC_FREE(streams
);
1099 return NT_STATUS_NO_MEMORY
;
1103 *_num_streams
= num_streams
;
1104 *_streams
= streams
;
1105 return NT_STATUS_OK
;
1109 catia_get_nt_acl(struct vfs_handle_struct
*handle
,
1110 const struct smb_filename
*smb_fname
,
1111 uint32_t security_info
,
1112 TALLOC_CTX
*mem_ctx
,
1113 struct security_descriptor
**ppdesc
)
1115 char *mapped_name
= NULL
;
1116 const char *path
= smb_fname
->base_name
;
1117 struct smb_filename
*mapped_smb_fname
= NULL
;
1120 status
= catia_string_replace_allocate(handle
->conn
,
1121 path
, &mapped_name
, vfs_translate_to_unix
);
1122 if (!NT_STATUS_IS_OK(status
)) {
1123 errno
= map_errno_from_nt_status(status
);
1126 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1131 if (mapped_smb_fname
== NULL
) {
1132 TALLOC_FREE(mapped_name
);
1133 return NT_STATUS_NO_MEMORY
;
1136 status
= SMB_VFS_NEXT_GET_NT_ACL(handle
, mapped_smb_fname
,
1137 security_info
, mem_ctx
, ppdesc
);
1138 TALLOC_FREE(mapped_name
);
1139 TALLOC_FREE(mapped_smb_fname
);
1145 catia_sys_acl_get_file(vfs_handle_struct
*handle
,
1146 const struct smb_filename
*smb_fname
,
1147 SMB_ACL_TYPE_T type
,
1148 TALLOC_CTX
*mem_ctx
)
1150 char *mapped_name
= NULL
;
1151 struct smb_filename
*mapped_smb_fname
= NULL
;
1154 int saved_errno
= 0;
1156 status
= catia_string_replace_allocate(handle
->conn
,
1157 smb_fname
->base_name
,
1159 vfs_translate_to_unix
);
1160 if (!NT_STATUS_IS_OK(status
)) {
1161 errno
= map_errno_from_nt_status(status
);
1162 return (SMB_ACL_T
)NULL
;
1165 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1170 if (mapped_smb_fname
== NULL
) {
1171 TALLOC_FREE(mapped_name
);
1173 return (SMB_ACL_T
)NULL
;
1176 ret
= SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle
, mapped_smb_fname
,
1178 if (ret
== (SMB_ACL_T
)NULL
) {
1179 saved_errno
= errno
;
1181 TALLOC_FREE(mapped_smb_fname
);
1182 TALLOC_FREE(mapped_name
);
1183 if (saved_errno
!= 0) {
1184 errno
= saved_errno
;
1190 catia_sys_acl_set_file(vfs_handle_struct
*handle
,
1191 const struct smb_filename
*smb_fname
,
1192 SMB_ACL_TYPE_T type
,
1195 struct smb_filename
*mapped_smb_fname
= NULL
;
1196 int saved_errno
= 0;
1197 char *mapped_name
= NULL
;
1201 status
= catia_string_replace_allocate(handle
->conn
,
1202 smb_fname
->base_name
,
1204 vfs_translate_to_unix
);
1205 if (!NT_STATUS_IS_OK(status
)) {
1206 errno
= map_errno_from_nt_status(status
);
1210 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1215 if (mapped_smb_fname
== NULL
) {
1216 TALLOC_FREE(mapped_name
);
1221 ret
= SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle
, mapped_smb_fname
,
1224 saved_errno
= errno
;
1226 TALLOC_FREE(mapped_smb_fname
);
1227 TALLOC_FREE(mapped_name
);
1228 if (saved_errno
!= 0) {
1229 errno
= saved_errno
;
1235 catia_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
1236 const struct smb_filename
*smb_fname
)
1238 struct smb_filename
*mapped_smb_fname
= NULL
;
1239 int saved_errno
= 0;
1240 char *mapped_name
= NULL
;
1244 status
= catia_string_replace_allocate(handle
->conn
,
1245 smb_fname
->base_name
,
1247 vfs_translate_to_unix
);
1248 if (!NT_STATUS_IS_OK(status
)) {
1249 errno
= map_errno_from_nt_status(status
);
1253 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1258 if (mapped_smb_fname
== NULL
) {
1259 TALLOC_FREE(mapped_name
);
1263 ret
= SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle
, mapped_smb_fname
);
1265 saved_errno
= errno
;
1267 TALLOC_FREE(mapped_smb_fname
);
1268 TALLOC_FREE(mapped_name
);
1269 if (saved_errno
!= 0) {
1270 errno
= saved_errno
;
1276 catia_getxattr(vfs_handle_struct
*handle
,
1277 const struct smb_filename
*smb_fname
,
1282 struct smb_filename
*mapped_smb_fname
= NULL
;
1283 char *mapped_name
= NULL
;
1284 char *mapped_ea_name
= NULL
;
1287 int saved_errno
= 0;
1289 status
= catia_string_replace_allocate(handle
->conn
,
1290 smb_fname
->base_name
,
1292 vfs_translate_to_unix
);
1293 if (!NT_STATUS_IS_OK(status
)) {
1294 errno
= map_errno_from_nt_status(status
);
1298 status
= catia_string_replace_allocate(handle
->conn
,
1299 name
, &mapped_ea_name
, vfs_translate_to_unix
);
1300 if (!NT_STATUS_IS_OK(status
)) {
1301 TALLOC_FREE(mapped_name
);
1302 errno
= map_errno_from_nt_status(status
);
1306 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1311 if (mapped_smb_fname
== NULL
) {
1312 TALLOC_FREE(mapped_name
);
1313 TALLOC_FREE(mapped_ea_name
);
1318 ret
= SMB_VFS_NEXT_GETXATTR(handle
, mapped_smb_fname
,
1319 mapped_ea_name
, value
, size
);
1321 saved_errno
= errno
;
1323 TALLOC_FREE(mapped_name
);
1324 TALLOC_FREE(mapped_ea_name
);
1325 TALLOC_FREE(mapped_smb_fname
);
1326 if (saved_errno
!= 0) {
1327 errno
= saved_errno
;
1334 catia_listxattr(vfs_handle_struct
*handle
,
1335 const struct smb_filename
*smb_fname
,
1336 char *list
, size_t size
)
1338 struct smb_filename
*mapped_smb_fname
= NULL
;
1339 char *mapped_name
= NULL
;
1342 int saved_errno
= 0;
1344 status
= catia_string_replace_allocate(handle
->conn
,
1345 smb_fname
->base_name
,
1347 vfs_translate_to_unix
);
1348 if (!NT_STATUS_IS_OK(status
)) {
1349 errno
= map_errno_from_nt_status(status
);
1353 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1358 if (mapped_smb_fname
== NULL
) {
1359 TALLOC_FREE(mapped_name
);
1364 ret
= SMB_VFS_NEXT_LISTXATTR(handle
, mapped_smb_fname
, list
, size
);
1366 saved_errno
= errno
;
1368 TALLOC_FREE(mapped_name
);
1369 TALLOC_FREE(mapped_smb_fname
);
1370 if (saved_errno
!= 0) {
1371 errno
= saved_errno
;
1378 catia_removexattr(vfs_handle_struct
*handle
,
1379 const struct smb_filename
*smb_fname
,
1382 struct smb_filename
*mapped_smb_fname
= NULL
;
1383 char *mapped_name
= NULL
;
1384 char *mapped_ea_name
= NULL
;
1387 int saved_errno
= 0;
1389 status
= catia_string_replace_allocate(handle
->conn
,
1390 smb_fname
->base_name
,
1392 vfs_translate_to_unix
);
1393 if (!NT_STATUS_IS_OK(status
)) {
1394 errno
= map_errno_from_nt_status(status
);
1398 status
= catia_string_replace_allocate(handle
->conn
,
1399 name
, &mapped_ea_name
, vfs_translate_to_unix
);
1400 if (!NT_STATUS_IS_OK(status
)) {
1401 TALLOC_FREE(mapped_name
);
1402 errno
= map_errno_from_nt_status(status
);
1406 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1411 if (mapped_smb_fname
== NULL
) {
1412 TALLOC_FREE(mapped_name
);
1413 TALLOC_FREE(mapped_ea_name
);
1418 ret
= SMB_VFS_NEXT_REMOVEXATTR(handle
, mapped_smb_fname
,
1421 saved_errno
= errno
;
1423 TALLOC_FREE(mapped_name
);
1424 TALLOC_FREE(mapped_ea_name
);
1425 TALLOC_FREE(mapped_smb_fname
);
1426 if (saved_errno
!= 0) {
1427 errno
= saved_errno
;
1434 catia_setxattr(vfs_handle_struct
*handle
,
1435 const struct smb_filename
*smb_fname
,
1441 struct smb_filename
*mapped_smb_fname
= NULL
;
1442 char *mapped_name
= NULL
;
1443 char *mapped_ea_name
= NULL
;
1446 int saved_errno
= 0;
1448 status
= catia_string_replace_allocate(handle
->conn
,
1449 smb_fname
->base_name
,
1451 vfs_translate_to_unix
);
1452 if (!NT_STATUS_IS_OK(status
)) {
1453 errno
= map_errno_from_nt_status(status
);
1457 status
= catia_string_replace_allocate(handle
->conn
,
1458 name
, &mapped_ea_name
, vfs_translate_to_unix
);
1459 if (!NT_STATUS_IS_OK(status
)) {
1460 TALLOC_FREE(mapped_name
);
1461 errno
= map_errno_from_nt_status(status
);
1465 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
1470 if (mapped_smb_fname
== NULL
) {
1471 TALLOC_FREE(mapped_name
);
1472 TALLOC_FREE(mapped_ea_name
);
1477 ret
= SMB_VFS_NEXT_SETXATTR(handle
, mapped_smb_fname
, mapped_ea_name
,
1478 value
, size
, flags
);
1480 saved_errno
= errno
;
1482 TALLOC_FREE(mapped_name
);
1483 TALLOC_FREE(mapped_ea_name
);
1484 TALLOC_FREE(mapped_smb_fname
);
1485 if (saved_errno
!= 0) {
1486 errno
= saved_errno
;
1492 static int catia_fstat(vfs_handle_struct
*handle
,
1494 SMB_STRUCT_STAT
*sbuf
)
1496 struct catia_cache
*cc
= NULL
;
1499 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1504 ret
= SMB_VFS_NEXT_FSTAT(handle
, fsp
, sbuf
);
1506 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1511 static ssize_t
catia_pread(vfs_handle_struct
*handle
,
1512 files_struct
*fsp
, void *data
,
1513 size_t n
, off_t offset
)
1515 struct catia_cache
*cc
= NULL
;
1519 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1524 result
= SMB_VFS_NEXT_PREAD(handle
, fsp
, data
, n
, offset
);
1526 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1531 static ssize_t
catia_pwrite(vfs_handle_struct
*handle
,
1532 files_struct
*fsp
, const void *data
,
1533 size_t n
, off_t offset
)
1535 struct catia_cache
*cc
= NULL
;
1539 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1544 result
= SMB_VFS_NEXT_PWRITE(handle
, fsp
, data
, n
, offset
);
1546 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1551 static int catia_ftruncate(struct vfs_handle_struct
*handle
,
1552 struct files_struct
*fsp
,
1555 struct catia_cache
*cc
= NULL
;
1558 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1563 ret
= SMB_VFS_NEXT_FTRUNCATE(handle
, fsp
, offset
);
1565 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1570 static int catia_fallocate(struct vfs_handle_struct
*handle
,
1571 struct files_struct
*fsp
,
1576 struct catia_cache
*cc
= NULL
;
1579 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1584 ret
= SMB_VFS_NEXT_FALLOCATE(handle
, fsp
, mode
, offset
, len
);
1586 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1591 static ssize_t
catia_fgetxattr(struct vfs_handle_struct
*handle
,
1592 struct files_struct
*fsp
,
1597 char *mapped_xattr_name
= NULL
;
1601 status
= catia_string_replace_allocate(handle
->conn
,
1602 name
, &mapped_xattr_name
,
1603 vfs_translate_to_unix
);
1604 if (!NT_STATUS_IS_OK(status
)) {
1605 errno
= map_errno_from_nt_status(status
);
1609 result
= SMB_VFS_NEXT_FGETXATTR(handle
, fsp
, mapped_xattr_name
,
1612 TALLOC_FREE(mapped_xattr_name
);
1617 static ssize_t
catia_flistxattr(struct vfs_handle_struct
*handle
,
1618 struct files_struct
*fsp
,
1622 struct catia_cache
*cc
= NULL
;
1626 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1631 result
= SMB_VFS_NEXT_FLISTXATTR(handle
, fsp
, list
, size
);
1633 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1638 static int catia_fremovexattr(struct vfs_handle_struct
*handle
,
1639 struct files_struct
*fsp
,
1642 char *mapped_name
= NULL
;
1646 status
= catia_string_replace_allocate(handle
->conn
,
1647 name
, &mapped_name
, vfs_translate_to_unix
);
1648 if (!NT_STATUS_IS_OK(status
)) {
1649 errno
= map_errno_from_nt_status(status
);
1653 ret
= SMB_VFS_NEXT_FREMOVEXATTR(handle
, fsp
, mapped_name
);
1655 TALLOC_FREE(mapped_name
);
1660 static int catia_fsetxattr(struct vfs_handle_struct
*handle
,
1661 struct files_struct
*fsp
,
1667 char *mapped_xattr_name
= NULL
;
1671 status
= catia_string_replace_allocate(
1672 handle
->conn
, name
, &mapped_xattr_name
, vfs_translate_to_unix
);
1673 if (!NT_STATUS_IS_OK(status
)) {
1674 errno
= map_errno_from_nt_status(status
);
1678 ret
= SMB_VFS_NEXT_FSETXATTR(handle
, fsp
, mapped_xattr_name
,
1679 value
, size
, flags
);
1681 TALLOC_FREE(mapped_xattr_name
);
1686 static SMB_ACL_T
catia_sys_acl_get_fd(vfs_handle_struct
*handle
,
1688 TALLOC_CTX
*mem_ctx
)
1690 struct catia_cache
*cc
= NULL
;
1691 struct smb_acl_t
*result
= NULL
;
1694 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1699 result
= SMB_VFS_NEXT_SYS_ACL_GET_FD(handle
, fsp
, mem_ctx
);
1701 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1706 static int catia_sys_acl_blob_get_fd(vfs_handle_struct
*handle
,
1708 TALLOC_CTX
*mem_ctx
,
1709 char **blob_description
,
1712 struct catia_cache
*cc
= NULL
;
1715 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1720 ret
= SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle
, fsp
, mem_ctx
,
1721 blob_description
, blob
);
1723 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1728 static int catia_sys_acl_set_fd(vfs_handle_struct
*handle
,
1732 struct catia_cache
*cc
= NULL
;
1735 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1740 ret
= SMB_VFS_NEXT_SYS_ACL_SET_FD(handle
, fsp
, theacl
);
1742 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1747 static NTSTATUS
catia_fget_nt_acl(vfs_handle_struct
*handle
,
1749 uint32_t security_info
,
1750 TALLOC_CTX
*mem_ctx
,
1751 struct security_descriptor
**ppdesc
)
1753 struct catia_cache
*cc
= NULL
;
1757 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1759 return map_nt_error_from_unix(errno
);
1762 status
= SMB_VFS_NEXT_FGET_NT_ACL(handle
, fsp
, security_info
,
1765 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1770 static NTSTATUS
catia_fset_nt_acl(vfs_handle_struct
*handle
,
1772 uint32_t security_info_sent
,
1773 const struct security_descriptor
*psd
)
1775 struct catia_cache
*cc
= NULL
;
1779 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1781 return map_nt_error_from_unix(errno
);
1784 status
= SMB_VFS_NEXT_FSET_NT_ACL(handle
, fsp
, security_info_sent
, psd
);
1786 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1791 static NTSTATUS
catia_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1792 struct files_struct
*fsp
,
1795 struct catia_cache
*cc
= NULL
;
1799 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1801 return map_nt_error_from_unix(errno
);
1804 status
= SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle
, fsp
, dosmode
);
1806 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1811 static NTSTATUS
catia_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1812 struct files_struct
*fsp
,
1815 struct catia_cache
*cc
= NULL
;
1819 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1821 return map_nt_error_from_unix(errno
);
1824 status
= SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle
, fsp
, dosmode
);
1826 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1831 static int catia_fchown(vfs_handle_struct
*handle
,
1836 struct catia_cache
*cc
= NULL
;
1839 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1844 ret
= SMB_VFS_NEXT_FCHOWN(handle
, fsp
, uid
, gid
);
1846 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1851 static int catia_fchmod(vfs_handle_struct
*handle
,
1855 struct catia_cache
*cc
= NULL
;
1858 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
1863 ret
= SMB_VFS_NEXT_FCHMOD(handle
, fsp
, mode
);
1865 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
1870 struct catia_pread_state
{
1872 struct vfs_aio_state vfs_aio_state
;
1873 struct files_struct
*fsp
;
1874 struct catia_cache
*cc
;
1877 static void catia_pread_done(struct tevent_req
*subreq
);
1879 static struct tevent_req
*catia_pread_send(struct vfs_handle_struct
*handle
,
1880 TALLOC_CTX
*mem_ctx
,
1881 struct tevent_context
*ev
,
1882 struct files_struct
*fsp
,
1887 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1888 struct catia_pread_state
*state
= NULL
;
1891 req
= tevent_req_create(mem_ctx
, &state
,
1892 struct catia_pread_state
);
1898 ret
= CATIA_FETCH_FSP_PRE_NEXT(state
, handle
, fsp
, &state
->cc
);
1900 tevent_req_error(req
, errno
);
1901 return tevent_req_post(req
, ev
);
1904 subreq
= SMB_VFS_NEXT_PREAD_SEND(state
, ev
, handle
, fsp
, data
,
1906 if (tevent_req_nomem(subreq
, req
)) {
1907 return tevent_req_post(req
, ev
);
1909 tevent_req_set_callback(subreq
, catia_pread_done
, req
);
1914 static void catia_pread_done(struct tevent_req
*subreq
)
1916 struct tevent_req
*req
= tevent_req_callback_data(
1917 subreq
, struct tevent_req
);
1918 struct catia_pread_state
*state
= tevent_req_data(
1919 req
, struct catia_pread_state
);
1921 state
->ret
= SMB_VFS_PREAD_RECV(subreq
, &state
->vfs_aio_state
);
1922 TALLOC_FREE(subreq
);
1924 CATIA_FETCH_FSP_POST_NEXT(&state
->cc
, state
->fsp
);
1926 tevent_req_done(req
);
1929 static ssize_t
catia_pread_recv(struct tevent_req
*req
,
1930 struct vfs_aio_state
*vfs_aio_state
)
1932 struct catia_pread_state
*state
= tevent_req_data(
1933 req
, struct catia_pread_state
);
1935 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1939 *vfs_aio_state
= state
->vfs_aio_state
;
1943 struct catia_pwrite_state
{
1945 struct vfs_aio_state vfs_aio_state
;
1946 struct files_struct
*fsp
;
1947 struct catia_cache
*cc
;
1950 static void catia_pwrite_done(struct tevent_req
*subreq
);
1952 static struct tevent_req
*catia_pwrite_send(struct vfs_handle_struct
*handle
,
1953 TALLOC_CTX
*mem_ctx
,
1954 struct tevent_context
*ev
,
1955 struct files_struct
*fsp
,
1960 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1961 struct catia_pwrite_state
*state
= NULL
;
1964 req
= tevent_req_create(mem_ctx
, &state
,
1965 struct catia_pwrite_state
);
1971 ret
= CATIA_FETCH_FSP_PRE_NEXT(state
, handle
, fsp
, &state
->cc
);
1973 tevent_req_error(req
, errno
);
1974 return tevent_req_post(req
, ev
);
1977 subreq
= SMB_VFS_NEXT_PWRITE_SEND(state
, ev
, handle
, fsp
, data
,
1979 if (tevent_req_nomem(subreq
, req
)) {
1980 return tevent_req_post(req
, ev
);
1982 tevent_req_set_callback(subreq
, catia_pwrite_done
, req
);
1987 static void catia_pwrite_done(struct tevent_req
*subreq
)
1989 struct tevent_req
*req
= tevent_req_callback_data(
1990 subreq
, struct tevent_req
);
1991 struct catia_pwrite_state
*state
= tevent_req_data(
1992 req
, struct catia_pwrite_state
);
1994 state
->ret
= SMB_VFS_PWRITE_RECV(subreq
, &state
->vfs_aio_state
);
1995 TALLOC_FREE(subreq
);
1997 CATIA_FETCH_FSP_POST_NEXT(&state
->cc
, state
->fsp
);
1999 tevent_req_done(req
);
2002 static ssize_t
catia_pwrite_recv(struct tevent_req
*req
,
2003 struct vfs_aio_state
*vfs_aio_state
)
2005 struct catia_pwrite_state
*state
= tevent_req_data(
2006 req
, struct catia_pwrite_state
);
2008 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
2012 *vfs_aio_state
= state
->vfs_aio_state
;
2016 static off_t
catia_lseek(vfs_handle_struct
*handle
,
2021 struct catia_cache
*cc
= NULL
;
2025 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2030 result
= SMB_VFS_NEXT_LSEEK(handle
, fsp
, offset
, whence
);
2032 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2037 struct catia_fsync_state
{
2039 struct vfs_aio_state vfs_aio_state
;
2040 struct files_struct
*fsp
;
2041 struct catia_cache
*cc
;
2044 static void catia_fsync_done(struct tevent_req
*subreq
);
2046 static struct tevent_req
*catia_fsync_send(struct vfs_handle_struct
*handle
,
2047 TALLOC_CTX
*mem_ctx
,
2048 struct tevent_context
*ev
,
2049 struct files_struct
*fsp
)
2051 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2052 struct catia_fsync_state
*state
= NULL
;
2055 req
= tevent_req_create(mem_ctx
, &state
,
2056 struct catia_fsync_state
);
2062 ret
= CATIA_FETCH_FSP_PRE_NEXT(state
, handle
, fsp
, &state
->cc
);
2064 tevent_req_error(req
, errno
);
2065 return tevent_req_post(req
, ev
);
2068 subreq
= SMB_VFS_NEXT_FSYNC_SEND(state
, ev
, handle
, fsp
);
2069 if (tevent_req_nomem(subreq
, req
)) {
2070 return tevent_req_post(req
, ev
);
2072 tevent_req_set_callback(subreq
, catia_fsync_done
, req
);
2077 static void catia_fsync_done(struct tevent_req
*subreq
)
2079 struct tevent_req
*req
= tevent_req_callback_data(
2080 subreq
, struct tevent_req
);
2081 struct catia_fsync_state
*state
= tevent_req_data(
2082 req
, struct catia_fsync_state
);
2084 state
->ret
= SMB_VFS_FSYNC_RECV(subreq
, &state
->vfs_aio_state
);
2085 TALLOC_FREE(subreq
);
2087 CATIA_FETCH_FSP_POST_NEXT(&state
->cc
, state
->fsp
);
2089 tevent_req_done(req
);
2092 static int catia_fsync_recv(struct tevent_req
*req
,
2093 struct vfs_aio_state
*vfs_aio_state
)
2095 struct catia_fsync_state
*state
= tevent_req_data(
2096 req
, struct catia_fsync_state
);
2098 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
2102 *vfs_aio_state
= state
->vfs_aio_state
;
2106 static bool catia_lock(vfs_handle_struct
*handle
,
2113 struct catia_cache
*cc
= NULL
;
2117 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2122 ok
= SMB_VFS_NEXT_LOCK(handle
, fsp
, op
, offset
, count
, type
);
2124 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2129 static int catia_kernel_flock(struct vfs_handle_struct
*handle
,
2130 struct files_struct
*fsp
,
2131 uint32_t share_mode
,
2132 uint32_t access_mask
)
2134 struct catia_cache
*cc
= NULL
;
2137 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2142 ret
= SMB_VFS_NEXT_KERNEL_FLOCK(handle
, fsp
, share_mode
, access_mask
);
2144 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2149 static int catia_linux_setlease(vfs_handle_struct
*handle
,
2153 struct catia_cache
*cc
= NULL
;
2156 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2161 ret
= SMB_VFS_NEXT_LINUX_SETLEASE(handle
, fsp
, leasetype
);
2163 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2168 static bool catia_getlock(vfs_handle_struct
*handle
,
2175 struct catia_cache
*cc
= NULL
;
2179 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2184 ok
= SMB_VFS_NEXT_GETLOCK(handle
, fsp
, poffset
, pcount
, ptype
, ppid
);
2186 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2191 static bool catia_strict_lock_check(struct vfs_handle_struct
*handle
,
2192 struct files_struct
*fsp
,
2193 struct lock_struct
*plock
)
2195 struct catia_cache
*cc
= NULL
;
2199 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2204 ok
= SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle
, fsp
, plock
);
2206 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2211 static NTSTATUS
catia_fsctl(struct vfs_handle_struct
*handle
,
2212 struct files_struct
*fsp
,
2216 const uint8_t *_in_data
,
2218 uint8_t **_out_data
,
2219 uint32_t max_out_len
,
2223 struct catia_cache
*cc
= NULL
;
2226 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2228 return map_nt_error_from_unix(errno
);
2231 result
= SMB_VFS_NEXT_FSCTL(handle
,
2242 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2247 static NTSTATUS
catia_get_compression(vfs_handle_struct
*handle
,
2248 TALLOC_CTX
*mem_ctx
,
2249 struct files_struct
*fsp
,
2250 struct smb_filename
*smb_fname
,
2251 uint16_t *_compression_fmt
)
2254 struct catia_cache
*cc
= NULL
;
2256 struct smb_filename
*mapped_smb_fname
= NULL
;
2257 char *mapped_name
= NULL
;
2260 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2262 return map_nt_error_from_unix(errno
);
2264 mapped_smb_fname
= fsp
->fsp_name
;
2266 result
= catia_string_replace_allocate(handle
->conn
,
2267 smb_fname
->base_name
,
2269 vfs_translate_to_unix
);
2270 if (!NT_STATUS_IS_OK(result
)) {
2274 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
2279 if (mapped_smb_fname
== NULL
) {
2280 TALLOC_FREE(mapped_name
);
2281 return NT_STATUS_NO_MEMORY
;
2284 TALLOC_FREE(mapped_name
);
2287 result
= SMB_VFS_NEXT_GET_COMPRESSION(handle
,
2294 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2296 TALLOC_FREE(mapped_smb_fname
);
2302 static NTSTATUS
catia_set_compression(vfs_handle_struct
*handle
,
2303 TALLOC_CTX
*mem_ctx
,
2304 struct files_struct
*fsp
,
2305 uint16_t compression_fmt
)
2308 struct catia_cache
*cc
= NULL
;
2311 ret
= CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle
, fsp
, &cc
);
2313 return map_nt_error_from_unix(errno
);
2316 result
= SMB_VFS_NEXT_SET_COMPRESSION(handle
, mem_ctx
, fsp
,
2319 CATIA_FETCH_FSP_POST_NEXT(&cc
, fsp
);
2324 static NTSTATUS
catia_readdir_attr(struct vfs_handle_struct
*handle
,
2325 const struct smb_filename
*smb_fname_in
,
2326 TALLOC_CTX
*mem_ctx
,
2327 struct readdir_attr_data
**pattr_data
)
2329 struct smb_filename
*smb_fname
;
2333 status
= catia_string_replace_allocate(handle
->conn
,
2334 smb_fname_in
->base_name
,
2336 vfs_translate_to_unix
);
2337 if (!NT_STATUS_IS_OK(status
)) {
2338 errno
= map_errno_from_nt_status(status
);
2342 smb_fname
= synthetic_smb_fname(talloc_tos(), fname
, NULL
,
2343 &smb_fname_in
->st
, 0);
2345 status
= SMB_VFS_NEXT_READDIR_ATTR(handle
, smb_fname
, mem_ctx
, pattr_data
);
2347 TALLOC_FREE(smb_fname
);
2352 static NTSTATUS
catia_get_dos_attributes(struct vfs_handle_struct
*handle
,
2353 struct smb_filename
*smb_fname
,
2356 char *mapped_name
= NULL
;
2357 const char *path
= smb_fname
->base_name
;
2358 struct smb_filename
*mapped_smb_fname
= NULL
;
2361 status
= catia_string_replace_allocate(handle
->conn
,
2362 path
, &mapped_name
, vfs_translate_to_unix
);
2363 if (!NT_STATUS_IS_OK(status
)) {
2364 errno
= map_errno_from_nt_status(status
);
2367 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
2372 if (mapped_smb_fname
== NULL
) {
2373 TALLOC_FREE(mapped_name
);
2374 return NT_STATUS_NO_MEMORY
;
2377 status
= SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle
,
2380 TALLOC_FREE(mapped_name
);
2381 TALLOC_FREE(mapped_smb_fname
);
2386 static NTSTATUS
catia_set_dos_attributes(struct vfs_handle_struct
*handle
,
2387 const struct smb_filename
*smb_fname
,
2390 char *mapped_name
= NULL
;
2391 const char *path
= smb_fname
->base_name
;
2392 struct smb_filename
*mapped_smb_fname
= NULL
;
2395 status
= catia_string_replace_allocate(handle
->conn
,
2396 path
, &mapped_name
, vfs_translate_to_unix
);
2397 if (!NT_STATUS_IS_OK(status
)) {
2398 errno
= map_errno_from_nt_status(status
);
2401 mapped_smb_fname
= synthetic_smb_fname(talloc_tos(),
2406 if (mapped_smb_fname
== NULL
) {
2407 TALLOC_FREE(mapped_name
);
2408 return NT_STATUS_NO_MEMORY
;
2411 status
= SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle
,
2414 TALLOC_FREE(mapped_name
);
2415 TALLOC_FREE(mapped_smb_fname
);
2420 static struct vfs_fn_pointers vfs_catia_fns
= {
2421 .connect_fn
= catia_connect
,
2423 /* Directory operations */
2424 .mkdir_fn
= catia_mkdir
,
2425 .rmdir_fn
= catia_rmdir
,
2426 .opendir_fn
= catia_opendir
,
2427 .readdir_attr_fn
= catia_readdir_attr
,
2429 /* File operations */
2430 .open_fn
= catia_open
,
2431 .pread_fn
= catia_pread
,
2432 .pread_send_fn
= catia_pread_send
,
2433 .pread_recv_fn
= catia_pread_recv
,
2434 .pwrite_fn
= catia_pwrite
,
2435 .pwrite_send_fn
= catia_pwrite_send
,
2436 .pwrite_recv_fn
= catia_pwrite_recv
,
2437 .lseek_fn
= catia_lseek
,
2438 .rename_fn
= catia_rename
,
2439 .fsync_send_fn
= catia_fsync_send
,
2440 .fsync_recv_fn
= catia_fsync_recv
,
2441 .stat_fn
= catia_stat
,
2442 .fstat_fn
= catia_fstat
,
2443 .lstat_fn
= catia_lstat
,
2444 .unlink_fn
= catia_unlink
,
2445 .chmod_fn
= catia_chmod
,
2446 .fchmod_fn
= catia_fchmod
,
2447 .chown_fn
= catia_chown
,
2448 .fchown_fn
= catia_fchown
,
2449 .lchown_fn
= catia_lchown
,
2450 .chdir_fn
= catia_chdir
,
2451 .ntimes_fn
= catia_ntimes
,
2452 .ftruncate_fn
= catia_ftruncate
,
2453 .fallocate_fn
= catia_fallocate
,
2454 .lock_fn
= catia_lock
,
2455 .kernel_flock_fn
= catia_kernel_flock
,
2456 .linux_setlease_fn
= catia_linux_setlease
,
2457 .getlock_fn
= catia_getlock
,
2458 .realpath_fn
= catia_realpath
,
2459 .chflags_fn
= catia_chflags
,
2460 .streaminfo_fn
= catia_streaminfo
,
2461 .strict_lock_check_fn
= catia_strict_lock_check
,
2462 .translate_name_fn
= catia_translate_name
,
2463 .fsctl_fn
= catia_fsctl
,
2464 .get_dos_attributes_fn
= catia_get_dos_attributes
,
2465 .get_dos_attributes_send_fn
= vfs_not_implemented_get_dos_attributes_send
,
2466 .get_dos_attributes_recv_fn
= vfs_not_implemented_get_dos_attributes_recv
,
2467 .set_dos_attributes_fn
= catia_set_dos_attributes
,
2468 .fset_dos_attributes_fn
= catia_fset_dos_attributes
,
2469 .fget_dos_attributes_fn
= catia_fget_dos_attributes
,
2470 .get_compression_fn
= catia_get_compression
,
2471 .set_compression_fn
= catia_set_compression
,
2473 /* NT ACL operations. */
2474 .get_nt_acl_fn
= catia_get_nt_acl
,
2475 .fget_nt_acl_fn
= catia_fget_nt_acl
,
2476 .fset_nt_acl_fn
= catia_fset_nt_acl
,
2478 /* POSIX ACL operations. */
2479 .sys_acl_get_file_fn
= catia_sys_acl_get_file
,
2480 .sys_acl_get_fd_fn
= catia_sys_acl_get_fd
,
2481 .sys_acl_blob_get_fd_fn
= catia_sys_acl_blob_get_fd
,
2482 .sys_acl_set_file_fn
= catia_sys_acl_set_file
,
2483 .sys_acl_set_fd_fn
= catia_sys_acl_set_fd
,
2484 .sys_acl_delete_def_file_fn
= catia_sys_acl_delete_def_file
,
2486 /* EA operations. */
2487 .getxattr_fn
= catia_getxattr
,
2488 .getxattrat_send_fn
= vfs_not_implemented_getxattrat_send
,
2489 .getxattrat_recv_fn
= vfs_not_implemented_getxattrat_recv
,
2490 .listxattr_fn
= catia_listxattr
,
2491 .removexattr_fn
= catia_removexattr
,
2492 .setxattr_fn
= catia_setxattr
,
2493 .fgetxattr_fn
= catia_fgetxattr
,
2494 .flistxattr_fn
= catia_flistxattr
,
2495 .fremovexattr_fn
= catia_fremovexattr
,
2496 .fsetxattr_fn
= catia_fsetxattr
,
2500 NTSTATUS
vfs_catia_init(TALLOC_CTX
*ctx
)
2504 ret
= smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "catia",
2506 if (!NT_STATUS_IS_OK(ret
))
2509 vfs_catia_debug_level
= debug_add_class("catia");
2510 if (vfs_catia_debug_level
== -1) {
2511 vfs_catia_debug_level
= DBGC_VFS
;
2512 DEBUG(0, ("vfs_catia: Couldn't register custom debugging "
2515 DEBUG(10, ("vfs_catia: Debug class number of "
2516 "'catia': %d\n", vfs_catia_debug_level
));