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(sme, 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_renameat(vfs_handle_struct *handle,
563 files_struct *srcfsp,
564 const struct smb_filename *smb_fname_src,
565 files_struct *dstfsp,
566 const struct smb_filename *smb_fname_dst)
568 TALLOC_CTX *ctx = talloc_tos();
569 struct smb_filename *smb_fname_src_tmp = NULL;
570 struct smb_filename *smb_fname_dst_tmp = NULL;
571 char *src_name_mapped = NULL;
572 char *dst_name_mapped = NULL;
576 status = catia_string_replace_allocate(handle->conn,
577 smb_fname_src->base_name,
578 &src_name_mapped, vfs_translate_to_unix);
579 if (!NT_STATUS_IS_OK(status)) {
580 errno = map_errno_from_nt_status(status);
584 status = catia_string_replace_allocate(handle->conn,
585 smb_fname_dst->base_name,
586 &dst_name_mapped, vfs_translate_to_unix);
587 if (!NT_STATUS_IS_OK(status)) {
588 errno = map_errno_from_nt_status(status);
592 /* Setup temporary smb_filename structs. */
593 smb_fname_src_tmp = cp_smb_filename(ctx, smb_fname_src);
594 if (smb_fname_src_tmp == NULL) {
599 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
600 if (smb_fname_dst_tmp == NULL) {
605 smb_fname_src_tmp->base_name = src_name_mapped;
606 smb_fname_dst_tmp->base_name = dst_name_mapped;
607 DEBUG(10, ("converted old name: %s\n",
608 smb_fname_str_dbg(smb_fname_src_tmp)));
609 DEBUG(10, ("converted new name: %s\n",
610 smb_fname_str_dbg(smb_fname_dst_tmp)));
612 ret = SMB_VFS_NEXT_RENAMEAT(handle,
619 TALLOC_FREE(src_name_mapped);
620 TALLOC_FREE(dst_name_mapped);
621 TALLOC_FREE(smb_fname_src_tmp);
622 TALLOC_FREE(smb_fname_dst_tmp);
627 static int catia_stat(vfs_handle_struct *handle,
628 struct smb_filename *smb_fname)
635 status = catia_string_replace_allocate(handle->conn,
636 smb_fname->base_name,
637 &name, vfs_translate_to_unix);
638 if (!NT_STATUS_IS_OK(status)) {
639 errno = map_errno_from_nt_status(status);
643 tmp_base_name = smb_fname->base_name;
644 smb_fname->base_name = name;
646 ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
647 smb_fname->base_name = tmp_base_name;
653 static int catia_lstat(vfs_handle_struct *handle,
654 struct smb_filename *smb_fname)
661 status = catia_string_replace_allocate(handle->conn,
662 smb_fname->base_name,
663 &name, vfs_translate_to_unix);
664 if (!NT_STATUS_IS_OK(status)) {
665 errno = map_errno_from_nt_status(status);
669 tmp_base_name = smb_fname->base_name;
670 smb_fname->base_name = name;
672 ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
673 smb_fname->base_name = tmp_base_name;
679 static int catia_unlink(vfs_handle_struct *handle,
680 const struct smb_filename *smb_fname)
682 struct smb_filename *smb_fname_tmp = NULL;
687 status = catia_string_replace_allocate(handle->conn,
688 smb_fname->base_name,
689 &name, vfs_translate_to_unix);
690 if (!NT_STATUS_IS_OK(status)) {
691 errno = map_errno_from_nt_status(status);
695 /* Setup temporary smb_filename structs. */
696 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
697 if (smb_fname_tmp == NULL) {
702 smb_fname_tmp->base_name = name;
703 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
704 TALLOC_FREE(smb_fname_tmp);
710 static int catia_chown(vfs_handle_struct *handle,
711 const struct smb_filename *smb_fname,
719 struct smb_filename *catia_smb_fname = NULL;
721 status = catia_string_replace_allocate(handle->conn,
722 smb_fname->base_name,
724 vfs_translate_to_unix);
725 if (!NT_STATUS_IS_OK(status)) {
726 errno = map_errno_from_nt_status(status);
729 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
734 if (catia_smb_fname == NULL) {
740 ret = SMB_VFS_NEXT_CHOWN(handle, catia_smb_fname, uid, gid);
743 TALLOC_FREE(catia_smb_fname);
748 static int catia_lchown(vfs_handle_struct *handle,
749 const struct smb_filename *smb_fname,
757 struct smb_filename *catia_smb_fname = NULL;
759 status = catia_string_replace_allocate(handle->conn,
760 smb_fname->base_name,
762 vfs_translate_to_unix);
763 if (!NT_STATUS_IS_OK(status)) {
764 errno = map_errno_from_nt_status(status);
767 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
772 if (catia_smb_fname == NULL) {
778 ret = SMB_VFS_NEXT_LCHOWN(handle, catia_smb_fname, uid, gid);
781 TALLOC_FREE(catia_smb_fname);
786 static int catia_chmod(vfs_handle_struct *handle,
787 const struct smb_filename *smb_fname,
794 struct smb_filename *catia_smb_fname = NULL;
796 status = catia_string_replace_allocate(handle->conn,
797 smb_fname->base_name,
799 vfs_translate_to_unix);
800 if (!NT_STATUS_IS_OK(status)) {
801 errno = map_errno_from_nt_status(status);
804 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
809 if (catia_smb_fname == NULL) {
815 ret = SMB_VFS_NEXT_CHMOD(handle, catia_smb_fname, mode);
818 TALLOC_FREE(catia_smb_fname);
823 static int catia_rmdir(vfs_handle_struct *handle,
824 const struct smb_filename *smb_fname)
829 struct smb_filename *catia_smb_fname = NULL;
831 status = catia_string_replace_allocate(handle->conn,
832 smb_fname->base_name,
834 vfs_translate_to_unix);
835 if (!NT_STATUS_IS_OK(status)) {
836 errno = map_errno_from_nt_status(status);
839 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
844 if (catia_smb_fname == NULL) {
850 ret = SMB_VFS_NEXT_RMDIR(handle, catia_smb_fname);
852 TALLOC_FREE(catia_smb_fname);
857 static int catia_mkdirat(vfs_handle_struct *handle,
858 struct files_struct *dirfsp,
859 const struct smb_filename *smb_fname,
865 struct smb_filename *catia_smb_fname = NULL;
867 status = catia_string_replace_allocate(handle->conn,
868 smb_fname->base_name,
870 vfs_translate_to_unix);
871 if (!NT_STATUS_IS_OK(status)) {
872 errno = map_errno_from_nt_status(status);
875 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
880 if (catia_smb_fname == NULL) {
886 ret = SMB_VFS_NEXT_MKDIRAT(handle,
891 TALLOC_FREE(catia_smb_fname);
896 static int catia_chdir(vfs_handle_struct *handle,
897 const struct smb_filename *smb_fname)
900 struct smb_filename *catia_smb_fname = NULL;
904 status = catia_string_replace_allocate(handle->conn,
905 smb_fname->base_name,
907 vfs_translate_to_unix);
908 if (!NT_STATUS_IS_OK(status)) {
909 errno = map_errno_from_nt_status(status);
913 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
918 if (catia_smb_fname == NULL) {
923 ret = SMB_VFS_NEXT_CHDIR(handle, catia_smb_fname);
925 TALLOC_FREE(catia_smb_fname);
930 static int catia_ntimes(vfs_handle_struct *handle,
931 const struct smb_filename *smb_fname,
932 struct smb_file_time *ft)
934 struct smb_filename *smb_fname_tmp = NULL;
939 status = catia_string_replace_allocate(handle->conn,
940 smb_fname->base_name,
941 &name, vfs_translate_to_unix);
942 if (!NT_STATUS_IS_OK(status)) {
943 errno = map_errno_from_nt_status(status);
947 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
948 if (smb_fname_tmp == NULL) {
953 smb_fname_tmp->base_name = name;
954 ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
956 TALLOC_FREE(smb_fname_tmp);
961 static struct smb_filename *
962 catia_realpath(vfs_handle_struct *handle,
964 const struct smb_filename *smb_fname)
966 char *mapped_name = NULL;
967 struct smb_filename *catia_smb_fname = NULL;
968 struct smb_filename *return_fname = NULL;
971 status = catia_string_replace_allocate(handle->conn,
972 smb_fname->base_name,
973 &mapped_name, vfs_translate_to_unix);
974 if (!NT_STATUS_IS_OK(status)) {
975 errno = map_errno_from_nt_status(status);
979 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
984 if (catia_smb_fname == NULL) {
985 TALLOC_FREE(mapped_name);
989 return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, catia_smb_fname);
990 TALLOC_FREE(mapped_name);
991 TALLOC_FREE(catia_smb_fname);
995 static int catia_chflags(struct vfs_handle_struct *handle,
996 const struct smb_filename *smb_fname,
1000 struct smb_filename *catia_smb_fname = NULL;
1004 status = catia_string_replace_allocate(handle->conn,
1005 smb_fname->base_name,
1007 vfs_translate_to_unix);
1008 if (!NT_STATUS_IS_OK(status)) {
1009 errno = map_errno_from_nt_status(status);
1012 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
1017 if (catia_smb_fname == NULL) {
1023 ret = SMB_VFS_NEXT_CHFLAGS(handle, catia_smb_fname, flags);
1025 TALLOC_FREE(catia_smb_fname);
1031 catia_streaminfo(struct vfs_handle_struct *handle,
1032 struct files_struct *fsp,
1033 const struct smb_filename *smb_fname,
1034 TALLOC_CTX *mem_ctx,
1035 unsigned int *_num_streams,
1036 struct stream_struct **_streams)
1038 char *mapped_name = NULL;
1041 struct smb_filename *catia_smb_fname = NULL;
1042 unsigned int num_streams = 0;
1043 struct stream_struct *streams = NULL;
1048 status = catia_string_replace_allocate(handle->conn,
1049 smb_fname->base_name,
1051 vfs_translate_to_unix);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 errno = map_errno_from_nt_status(status);
1057 catia_smb_fname = synthetic_smb_fname(talloc_tos(),
1062 if (catia_smb_fname == NULL) {
1063 TALLOC_FREE(mapped_name);
1064 return NT_STATUS_NO_MEMORY;
1067 status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, catia_smb_fname,
1068 mem_ctx, &num_streams, &streams);
1069 TALLOC_FREE(mapped_name);
1070 TALLOC_FREE(catia_smb_fname);
1071 if (!NT_STATUS_IS_OK(status)) {
1076 * Translate stream names just like the base names
1078 for (i = 0; i < num_streams; i++) {
1080 * Strip ":" prefix and ":$DATA" suffix to get a
1081 * "pure" stream name and only translate that.
1083 void *old_ptr = streams[i].name;
1084 char *stream_name = streams[i].name + 1;
1085 char *stream_type = strrchr_m(stream_name, ':');
1087 if (stream_type != NULL) {
1088 *stream_type = '\0';
1092 status = catia_string_replace_allocate(handle->conn, stream_name,
1093 &mapped_name, vfs_translate_to_windows);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 TALLOC_FREE(streams);
1099 if (stream_type != NULL) {
1100 streams[i].name = talloc_asprintf(streams, ":%s:%s",
1101 mapped_name, stream_type);
1103 streams[i].name = talloc_asprintf(streams, ":%s",
1106 TALLOC_FREE(mapped_name);
1107 TALLOC_FREE(old_ptr);
1108 if (streams[i].name == NULL) {
1109 TALLOC_FREE(streams);
1110 return NT_STATUS_NO_MEMORY;
1114 *_num_streams = num_streams;
1115 *_streams = streams;
1116 return NT_STATUS_OK;
1120 catia_get_nt_acl(struct vfs_handle_struct *handle,
1121 const struct smb_filename *smb_fname,
1122 uint32_t security_info,
1123 TALLOC_CTX *mem_ctx,
1124 struct security_descriptor **ppdesc)
1126 char *mapped_name = NULL;
1127 const char *path = smb_fname->base_name;
1128 struct smb_filename *mapped_smb_fname = NULL;
1131 status = catia_string_replace_allocate(handle->conn,
1132 path, &mapped_name, vfs_translate_to_unix);
1133 if (!NT_STATUS_IS_OK(status)) {
1134 errno = map_errno_from_nt_status(status);
1137 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1142 if (mapped_smb_fname == NULL) {
1143 TALLOC_FREE(mapped_name);
1144 return NT_STATUS_NO_MEMORY;
1147 status = SMB_VFS_NEXT_GET_NT_ACL(handle, mapped_smb_fname,
1148 security_info, mem_ctx, ppdesc);
1149 TALLOC_FREE(mapped_name);
1150 TALLOC_FREE(mapped_smb_fname);
1156 catia_sys_acl_get_file(vfs_handle_struct *handle,
1157 const struct smb_filename *smb_fname,
1158 SMB_ACL_TYPE_T type,
1159 TALLOC_CTX *mem_ctx)
1161 char *mapped_name = NULL;
1162 struct smb_filename *mapped_smb_fname = NULL;
1165 int saved_errno = 0;
1167 status = catia_string_replace_allocate(handle->conn,
1168 smb_fname->base_name,
1170 vfs_translate_to_unix);
1171 if (!NT_STATUS_IS_OK(status)) {
1172 errno = map_errno_from_nt_status(status);
1173 return (SMB_ACL_T)NULL;
1176 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1181 if (mapped_smb_fname == NULL) {
1182 TALLOC_FREE(mapped_name);
1184 return (SMB_ACL_T)NULL;
1187 ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, mapped_smb_fname,
1189 if (ret == (SMB_ACL_T)NULL) {
1190 saved_errno = errno;
1192 TALLOC_FREE(mapped_smb_fname);
1193 TALLOC_FREE(mapped_name);
1194 if (saved_errno != 0) {
1195 errno = saved_errno;
1201 catia_sys_acl_set_file(vfs_handle_struct *handle,
1202 const struct smb_filename *smb_fname,
1203 SMB_ACL_TYPE_T type,
1206 struct smb_filename *mapped_smb_fname = NULL;
1207 int saved_errno = 0;
1208 char *mapped_name = NULL;
1212 status = catia_string_replace_allocate(handle->conn,
1213 smb_fname->base_name,
1215 vfs_translate_to_unix);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 errno = map_errno_from_nt_status(status);
1221 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1226 if (mapped_smb_fname == NULL) {
1227 TALLOC_FREE(mapped_name);
1232 ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, mapped_smb_fname,
1235 saved_errno = errno;
1237 TALLOC_FREE(mapped_smb_fname);
1238 TALLOC_FREE(mapped_name);
1239 if (saved_errno != 0) {
1240 errno = saved_errno;
1246 catia_sys_acl_delete_def_file(vfs_handle_struct *handle,
1247 const struct smb_filename *smb_fname)
1249 struct smb_filename *mapped_smb_fname = NULL;
1250 int saved_errno = 0;
1251 char *mapped_name = NULL;
1255 status = catia_string_replace_allocate(handle->conn,
1256 smb_fname->base_name,
1258 vfs_translate_to_unix);
1259 if (!NT_STATUS_IS_OK(status)) {
1260 errno = map_errno_from_nt_status(status);
1264 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1269 if (mapped_smb_fname == NULL) {
1270 TALLOC_FREE(mapped_name);
1274 ret = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, mapped_smb_fname);
1276 saved_errno = errno;
1278 TALLOC_FREE(mapped_smb_fname);
1279 TALLOC_FREE(mapped_name);
1280 if (saved_errno != 0) {
1281 errno = saved_errno;
1287 catia_getxattr(vfs_handle_struct *handle,
1288 const struct smb_filename *smb_fname,
1293 struct smb_filename *mapped_smb_fname = NULL;
1294 char *mapped_name = NULL;
1295 char *mapped_ea_name = NULL;
1298 int saved_errno = 0;
1300 status = catia_string_replace_allocate(handle->conn,
1301 smb_fname->base_name,
1303 vfs_translate_to_unix);
1304 if (!NT_STATUS_IS_OK(status)) {
1305 errno = map_errno_from_nt_status(status);
1309 status = catia_string_replace_allocate(handle->conn,
1310 name, &mapped_ea_name, vfs_translate_to_unix);
1311 if (!NT_STATUS_IS_OK(status)) {
1312 TALLOC_FREE(mapped_name);
1313 errno = map_errno_from_nt_status(status);
1317 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1322 if (mapped_smb_fname == NULL) {
1323 TALLOC_FREE(mapped_name);
1324 TALLOC_FREE(mapped_ea_name);
1329 ret = SMB_VFS_NEXT_GETXATTR(handle, mapped_smb_fname,
1330 mapped_ea_name, value, size);
1332 saved_errno = errno;
1334 TALLOC_FREE(mapped_name);
1335 TALLOC_FREE(mapped_ea_name);
1336 TALLOC_FREE(mapped_smb_fname);
1337 if (saved_errno != 0) {
1338 errno = saved_errno;
1345 catia_listxattr(vfs_handle_struct *handle,
1346 const struct smb_filename *smb_fname,
1347 char *list, size_t size)
1349 struct smb_filename *mapped_smb_fname = NULL;
1350 char *mapped_name = NULL;
1353 int saved_errno = 0;
1355 status = catia_string_replace_allocate(handle->conn,
1356 smb_fname->base_name,
1358 vfs_translate_to_unix);
1359 if (!NT_STATUS_IS_OK(status)) {
1360 errno = map_errno_from_nt_status(status);
1364 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1369 if (mapped_smb_fname == NULL) {
1370 TALLOC_FREE(mapped_name);
1375 ret = SMB_VFS_NEXT_LISTXATTR(handle, mapped_smb_fname, list, size);
1377 saved_errno = errno;
1379 TALLOC_FREE(mapped_name);
1380 TALLOC_FREE(mapped_smb_fname);
1381 if (saved_errno != 0) {
1382 errno = saved_errno;
1389 catia_removexattr(vfs_handle_struct *handle,
1390 const struct smb_filename *smb_fname,
1393 struct smb_filename *mapped_smb_fname = NULL;
1394 char *mapped_name = NULL;
1395 char *mapped_ea_name = NULL;
1398 int saved_errno = 0;
1400 status = catia_string_replace_allocate(handle->conn,
1401 smb_fname->base_name,
1403 vfs_translate_to_unix);
1404 if (!NT_STATUS_IS_OK(status)) {
1405 errno = map_errno_from_nt_status(status);
1409 status = catia_string_replace_allocate(handle->conn,
1410 name, &mapped_ea_name, vfs_translate_to_unix);
1411 if (!NT_STATUS_IS_OK(status)) {
1412 TALLOC_FREE(mapped_name);
1413 errno = map_errno_from_nt_status(status);
1417 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1422 if (mapped_smb_fname == NULL) {
1423 TALLOC_FREE(mapped_name);
1424 TALLOC_FREE(mapped_ea_name);
1429 ret = SMB_VFS_NEXT_REMOVEXATTR(handle, mapped_smb_fname,
1432 saved_errno = errno;
1434 TALLOC_FREE(mapped_name);
1435 TALLOC_FREE(mapped_ea_name);
1436 TALLOC_FREE(mapped_smb_fname);
1437 if (saved_errno != 0) {
1438 errno = saved_errno;
1445 catia_setxattr(vfs_handle_struct *handle,
1446 const struct smb_filename *smb_fname,
1452 struct smb_filename *mapped_smb_fname = NULL;
1453 char *mapped_name = NULL;
1454 char *mapped_ea_name = NULL;
1457 int saved_errno = 0;
1459 status = catia_string_replace_allocate(handle->conn,
1460 smb_fname->base_name,
1462 vfs_translate_to_unix);
1463 if (!NT_STATUS_IS_OK(status)) {
1464 errno = map_errno_from_nt_status(status);
1468 status = catia_string_replace_allocate(handle->conn,
1469 name, &mapped_ea_name, vfs_translate_to_unix);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 TALLOC_FREE(mapped_name);
1472 errno = map_errno_from_nt_status(status);
1476 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1481 if (mapped_smb_fname == NULL) {
1482 TALLOC_FREE(mapped_name);
1483 TALLOC_FREE(mapped_ea_name);
1488 ret = SMB_VFS_NEXT_SETXATTR(handle, mapped_smb_fname, mapped_ea_name,
1489 value, size, flags);
1491 saved_errno = errno;
1493 TALLOC_FREE(mapped_name);
1494 TALLOC_FREE(mapped_ea_name);
1495 TALLOC_FREE(mapped_smb_fname);
1496 if (saved_errno != 0) {
1497 errno = saved_errno;
1503 static int catia_fstat(vfs_handle_struct *handle,
1505 SMB_STRUCT_STAT *sbuf)
1507 struct catia_cache *cc = NULL;
1510 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1515 ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1517 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1522 static ssize_t catia_pread(vfs_handle_struct *handle,
1523 files_struct *fsp, void *data,
1524 size_t n, off_t offset)
1526 struct catia_cache *cc = NULL;
1530 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1535 result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
1537 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1542 static ssize_t catia_pwrite(vfs_handle_struct *handle,
1543 files_struct *fsp, const void *data,
1544 size_t n, off_t offset)
1546 struct catia_cache *cc = NULL;
1550 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1555 result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
1557 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1562 static int catia_ftruncate(struct vfs_handle_struct *handle,
1563 struct files_struct *fsp,
1566 struct catia_cache *cc = NULL;
1569 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1574 ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
1576 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1581 static int catia_fallocate(struct vfs_handle_struct *handle,
1582 struct files_struct *fsp,
1587 struct catia_cache *cc = NULL;
1590 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1595 ret = SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
1597 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1602 static ssize_t catia_fgetxattr(struct vfs_handle_struct *handle,
1603 struct files_struct *fsp,
1608 char *mapped_xattr_name = NULL;
1612 status = catia_string_replace_allocate(handle->conn,
1613 name, &mapped_xattr_name,
1614 vfs_translate_to_unix);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 errno = map_errno_from_nt_status(status);
1620 result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, mapped_xattr_name,
1623 TALLOC_FREE(mapped_xattr_name);
1628 static ssize_t catia_flistxattr(struct vfs_handle_struct *handle,
1629 struct files_struct *fsp,
1633 struct catia_cache *cc = NULL;
1637 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1642 result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
1644 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1649 static int catia_fremovexattr(struct vfs_handle_struct *handle,
1650 struct files_struct *fsp,
1653 char *mapped_name = NULL;
1657 status = catia_string_replace_allocate(handle->conn,
1658 name, &mapped_name, vfs_translate_to_unix);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 errno = map_errno_from_nt_status(status);
1664 ret = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, mapped_name);
1666 TALLOC_FREE(mapped_name);
1671 static int catia_fsetxattr(struct vfs_handle_struct *handle,
1672 struct files_struct *fsp,
1678 char *mapped_xattr_name = NULL;
1682 status = catia_string_replace_allocate(
1683 handle->conn, name, &mapped_xattr_name, vfs_translate_to_unix);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 errno = map_errno_from_nt_status(status);
1689 ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, mapped_xattr_name,
1690 value, size, flags);
1692 TALLOC_FREE(mapped_xattr_name);
1697 static SMB_ACL_T catia_sys_acl_get_fd(vfs_handle_struct *handle,
1699 TALLOC_CTX *mem_ctx)
1701 struct catia_cache *cc = NULL;
1702 struct smb_acl_t *result = NULL;
1705 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1710 result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
1712 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1717 static int catia_sys_acl_blob_get_fd(vfs_handle_struct *handle,
1719 TALLOC_CTX *mem_ctx,
1720 char **blob_description,
1723 struct catia_cache *cc = NULL;
1726 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1731 ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx,
1732 blob_description, blob);
1734 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1739 static int catia_sys_acl_set_fd(vfs_handle_struct *handle,
1743 struct catia_cache *cc = NULL;
1746 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1751 ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
1753 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1758 static NTSTATUS catia_fget_nt_acl(vfs_handle_struct *handle,
1760 uint32_t security_info,
1761 TALLOC_CTX *mem_ctx,
1762 struct security_descriptor **ppdesc)
1764 struct catia_cache *cc = NULL;
1768 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1770 return map_nt_error_from_unix(errno);
1773 status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
1776 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1781 static NTSTATUS catia_fset_nt_acl(vfs_handle_struct *handle,
1783 uint32_t security_info_sent,
1784 const struct security_descriptor *psd)
1786 struct catia_cache *cc = NULL;
1790 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1792 return map_nt_error_from_unix(errno);
1795 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
1797 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1802 static NTSTATUS catia_fset_dos_attributes(struct vfs_handle_struct *handle,
1803 struct files_struct *fsp,
1806 struct catia_cache *cc = NULL;
1810 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1812 return map_nt_error_from_unix(errno);
1815 status = SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, dosmode);
1817 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1822 static NTSTATUS catia_fget_dos_attributes(struct vfs_handle_struct *handle,
1823 struct files_struct *fsp,
1826 struct catia_cache *cc = NULL;
1830 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1832 return map_nt_error_from_unix(errno);
1835 status = SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
1837 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1842 static int catia_fchown(vfs_handle_struct *handle,
1847 struct catia_cache *cc = NULL;
1850 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1855 ret = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
1857 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1862 static int catia_fchmod(vfs_handle_struct *handle,
1866 struct catia_cache *cc = NULL;
1869 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1874 ret = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1876 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1881 struct catia_pread_state {
1883 struct vfs_aio_state vfs_aio_state;
1884 struct files_struct *fsp;
1885 struct catia_cache *cc;
1888 static void catia_pread_done(struct tevent_req *subreq);
1890 static struct tevent_req *catia_pread_send(struct vfs_handle_struct *handle,
1891 TALLOC_CTX *mem_ctx,
1892 struct tevent_context *ev,
1893 struct files_struct *fsp,
1898 struct tevent_req *req = NULL, *subreq = NULL;
1899 struct catia_pread_state *state = NULL;
1902 req = tevent_req_create(mem_ctx, &state,
1903 struct catia_pread_state);
1909 ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
1911 tevent_req_error(req, errno);
1912 return tevent_req_post(req, ev);
1915 subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
1917 if (tevent_req_nomem(subreq, req)) {
1918 return tevent_req_post(req, ev);
1920 tevent_req_set_callback(subreq, catia_pread_done, req);
1925 static void catia_pread_done(struct tevent_req *subreq)
1927 struct tevent_req *req = tevent_req_callback_data(
1928 subreq, struct tevent_req);
1929 struct catia_pread_state *state = tevent_req_data(
1930 req, struct catia_pread_state);
1932 state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
1933 TALLOC_FREE(subreq);
1935 CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
1937 tevent_req_done(req);
1940 static ssize_t catia_pread_recv(struct tevent_req *req,
1941 struct vfs_aio_state *vfs_aio_state)
1943 struct catia_pread_state *state = tevent_req_data(
1944 req, struct catia_pread_state);
1946 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1950 *vfs_aio_state = state->vfs_aio_state;
1954 struct catia_pwrite_state {
1956 struct vfs_aio_state vfs_aio_state;
1957 struct files_struct *fsp;
1958 struct catia_cache *cc;
1961 static void catia_pwrite_done(struct tevent_req *subreq);
1963 static struct tevent_req *catia_pwrite_send(struct vfs_handle_struct *handle,
1964 TALLOC_CTX *mem_ctx,
1965 struct tevent_context *ev,
1966 struct files_struct *fsp,
1971 struct tevent_req *req = NULL, *subreq = NULL;
1972 struct catia_pwrite_state *state = NULL;
1975 req = tevent_req_create(mem_ctx, &state,
1976 struct catia_pwrite_state);
1982 ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
1984 tevent_req_error(req, errno);
1985 return tevent_req_post(req, ev);
1988 subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
1990 if (tevent_req_nomem(subreq, req)) {
1991 return tevent_req_post(req, ev);
1993 tevent_req_set_callback(subreq, catia_pwrite_done, req);
1998 static void catia_pwrite_done(struct tevent_req *subreq)
2000 struct tevent_req *req = tevent_req_callback_data(
2001 subreq, struct tevent_req);
2002 struct catia_pwrite_state *state = tevent_req_data(
2003 req, struct catia_pwrite_state);
2005 state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
2006 TALLOC_FREE(subreq);
2008 CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
2010 tevent_req_done(req);
2013 static ssize_t catia_pwrite_recv(struct tevent_req *req,
2014 struct vfs_aio_state *vfs_aio_state)
2016 struct catia_pwrite_state *state = tevent_req_data(
2017 req, struct catia_pwrite_state);
2019 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2023 *vfs_aio_state = state->vfs_aio_state;
2027 static off_t catia_lseek(vfs_handle_struct *handle,
2032 struct catia_cache *cc = NULL;
2036 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2041 result = SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence);
2043 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2048 struct catia_fsync_state {
2050 struct vfs_aio_state vfs_aio_state;
2051 struct files_struct *fsp;
2052 struct catia_cache *cc;
2055 static void catia_fsync_done(struct tevent_req *subreq);
2057 static struct tevent_req *catia_fsync_send(struct vfs_handle_struct *handle,
2058 TALLOC_CTX *mem_ctx,
2059 struct tevent_context *ev,
2060 struct files_struct *fsp)
2062 struct tevent_req *req = NULL, *subreq = NULL;
2063 struct catia_fsync_state *state = NULL;
2066 req = tevent_req_create(mem_ctx, &state,
2067 struct catia_fsync_state);
2073 ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
2075 tevent_req_error(req, errno);
2076 return tevent_req_post(req, ev);
2079 subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
2080 if (tevent_req_nomem(subreq, req)) {
2081 return tevent_req_post(req, ev);
2083 tevent_req_set_callback(subreq, catia_fsync_done, req);
2088 static void catia_fsync_done(struct tevent_req *subreq)
2090 struct tevent_req *req = tevent_req_callback_data(
2091 subreq, struct tevent_req);
2092 struct catia_fsync_state *state = tevent_req_data(
2093 req, struct catia_fsync_state);
2095 state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
2096 TALLOC_FREE(subreq);
2098 CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
2100 tevent_req_done(req);
2103 static int catia_fsync_recv(struct tevent_req *req,
2104 struct vfs_aio_state *vfs_aio_state)
2106 struct catia_fsync_state *state = tevent_req_data(
2107 req, struct catia_fsync_state);
2109 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2113 *vfs_aio_state = state->vfs_aio_state;
2117 static bool catia_lock(vfs_handle_struct *handle,
2124 struct catia_cache *cc = NULL;
2128 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2133 ok = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
2135 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2140 static int catia_kernel_flock(struct vfs_handle_struct *handle,
2141 struct files_struct *fsp,
2142 uint32_t share_mode,
2143 uint32_t access_mask)
2145 struct catia_cache *cc = NULL;
2148 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2153 ret = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode, access_mask);
2155 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2160 static int catia_linux_setlease(vfs_handle_struct *handle,
2164 struct catia_cache *cc = NULL;
2167 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2172 ret = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
2174 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2179 static bool catia_getlock(vfs_handle_struct *handle,
2186 struct catia_cache *cc = NULL;
2190 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2195 ok = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype, ppid);
2197 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2202 static bool catia_strict_lock_check(struct vfs_handle_struct *handle,
2203 struct files_struct *fsp,
2204 struct lock_struct *plock)
2206 struct catia_cache *cc = NULL;
2210 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2215 ok = SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle, fsp, plock);
2217 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2222 static NTSTATUS catia_fsctl(struct vfs_handle_struct *handle,
2223 struct files_struct *fsp,
2227 const uint8_t *_in_data,
2229 uint8_t **_out_data,
2230 uint32_t max_out_len,
2234 struct catia_cache *cc = NULL;
2237 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2239 return map_nt_error_from_unix(errno);
2242 result = SMB_VFS_NEXT_FSCTL(handle,
2253 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2258 static NTSTATUS catia_get_compression(vfs_handle_struct *handle,
2259 TALLOC_CTX *mem_ctx,
2260 struct files_struct *fsp,
2261 struct smb_filename *smb_fname,
2262 uint16_t *_compression_fmt)
2265 struct catia_cache *cc = NULL;
2267 struct smb_filename *mapped_smb_fname = NULL;
2268 char *mapped_name = NULL;
2271 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2273 return map_nt_error_from_unix(errno);
2275 mapped_smb_fname = fsp->fsp_name;
2277 result = catia_string_replace_allocate(handle->conn,
2278 smb_fname->base_name,
2280 vfs_translate_to_unix);
2281 if (!NT_STATUS_IS_OK(result)) {
2285 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
2290 if (mapped_smb_fname == NULL) {
2291 TALLOC_FREE(mapped_name);
2292 return NT_STATUS_NO_MEMORY;
2295 TALLOC_FREE(mapped_name);
2298 result = SMB_VFS_NEXT_GET_COMPRESSION(handle,
2305 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2307 TALLOC_FREE(mapped_smb_fname);
2313 static NTSTATUS catia_set_compression(vfs_handle_struct *handle,
2314 TALLOC_CTX *mem_ctx,
2315 struct files_struct *fsp,
2316 uint16_t compression_fmt)
2319 struct catia_cache *cc = NULL;
2322 ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2324 return map_nt_error_from_unix(errno);
2327 result = SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp,
2330 CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2335 static NTSTATUS catia_readdir_attr(struct vfs_handle_struct *handle,
2336 const struct smb_filename *smb_fname_in,
2337 TALLOC_CTX *mem_ctx,
2338 struct readdir_attr_data **pattr_data)
2340 struct smb_filename *smb_fname;
2344 status = catia_string_replace_allocate(handle->conn,
2345 smb_fname_in->base_name,
2347 vfs_translate_to_unix);
2348 if (!NT_STATUS_IS_OK(status)) {
2349 errno = map_errno_from_nt_status(status);
2353 smb_fname = synthetic_smb_fname(talloc_tos(), fname, NULL,
2354 &smb_fname_in->st, 0);
2356 status = SMB_VFS_NEXT_READDIR_ATTR(handle, smb_fname, mem_ctx, pattr_data);
2358 TALLOC_FREE(smb_fname);
2363 static NTSTATUS catia_get_dos_attributes(struct vfs_handle_struct *handle,
2364 struct smb_filename *smb_fname,
2367 char *mapped_name = NULL;
2368 const char *path = smb_fname->base_name;
2369 struct smb_filename *mapped_smb_fname = NULL;
2372 status = catia_string_replace_allocate(handle->conn,
2373 path, &mapped_name, vfs_translate_to_unix);
2374 if (!NT_STATUS_IS_OK(status)) {
2375 errno = map_errno_from_nt_status(status);
2378 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
2383 if (mapped_smb_fname == NULL) {
2384 TALLOC_FREE(mapped_name);
2385 return NT_STATUS_NO_MEMORY;
2388 status = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle,
2391 if (NT_STATUS_IS_OK(status)) {
2392 smb_fname->st = mapped_smb_fname->st;
2395 TALLOC_FREE(mapped_name);
2396 TALLOC_FREE(mapped_smb_fname);
2401 static NTSTATUS catia_set_dos_attributes(struct vfs_handle_struct *handle,
2402 const struct smb_filename *smb_fname,
2405 char *mapped_name = NULL;
2406 const char *path = smb_fname->base_name;
2407 struct smb_filename *mapped_smb_fname = NULL;
2410 status = catia_string_replace_allocate(handle->conn,
2411 path, &mapped_name, vfs_translate_to_unix);
2412 if (!NT_STATUS_IS_OK(status)) {
2413 errno = map_errno_from_nt_status(status);
2416 mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
2421 if (mapped_smb_fname == NULL) {
2422 TALLOC_FREE(mapped_name);
2423 return NT_STATUS_NO_MEMORY;
2426 status = SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
2429 TALLOC_FREE(mapped_name);
2430 TALLOC_FREE(mapped_smb_fname);
2435 static struct vfs_fn_pointers vfs_catia_fns = {
2436 .connect_fn = catia_connect,
2438 /* Directory operations */
2439 .mkdirat_fn = catia_mkdirat,
2440 .rmdir_fn = catia_rmdir,
2441 .opendir_fn = catia_opendir,
2442 .readdir_attr_fn = catia_readdir_attr,
2444 /* File operations */
2445 .open_fn = catia_open,
2446 .pread_fn = catia_pread,
2447 .pread_send_fn = catia_pread_send,
2448 .pread_recv_fn = catia_pread_recv,
2449 .pwrite_fn = catia_pwrite,
2450 .pwrite_send_fn = catia_pwrite_send,
2451 .pwrite_recv_fn = catia_pwrite_recv,
2452 .lseek_fn = catia_lseek,
2453 .renameat_fn = catia_renameat,
2454 .fsync_send_fn = catia_fsync_send,
2455 .fsync_recv_fn = catia_fsync_recv,
2456 .stat_fn = catia_stat,
2457 .fstat_fn = catia_fstat,
2458 .lstat_fn = catia_lstat,
2459 .unlink_fn = catia_unlink,
2460 .chmod_fn = catia_chmod,
2461 .fchmod_fn = catia_fchmod,
2462 .chown_fn = catia_chown,
2463 .fchown_fn = catia_fchown,
2464 .lchown_fn = catia_lchown,
2465 .chdir_fn = catia_chdir,
2466 .ntimes_fn = catia_ntimes,
2467 .ftruncate_fn = catia_ftruncate,
2468 .fallocate_fn = catia_fallocate,
2469 .lock_fn = catia_lock,
2470 .kernel_flock_fn = catia_kernel_flock,
2471 .linux_setlease_fn = catia_linux_setlease,
2472 .getlock_fn = catia_getlock,
2473 .realpath_fn = catia_realpath,
2474 .chflags_fn = catia_chflags,
2475 .streaminfo_fn = catia_streaminfo,
2476 .strict_lock_check_fn = catia_strict_lock_check,
2477 .translate_name_fn = catia_translate_name,
2478 .fsctl_fn = catia_fsctl,
2479 .get_dos_attributes_fn = catia_get_dos_attributes,
2480 .get_dos_attributes_send_fn = vfs_not_implemented_get_dos_attributes_send,
2481 .get_dos_attributes_recv_fn = vfs_not_implemented_get_dos_attributes_recv,
2482 .set_dos_attributes_fn = catia_set_dos_attributes,
2483 .fset_dos_attributes_fn = catia_fset_dos_attributes,
2484 .fget_dos_attributes_fn = catia_fget_dos_attributes,
2485 .get_compression_fn = catia_get_compression,
2486 .set_compression_fn = catia_set_compression,
2488 /* NT ACL operations. */
2489 .get_nt_acl_fn = catia_get_nt_acl,
2490 .fget_nt_acl_fn = catia_fget_nt_acl,
2491 .fset_nt_acl_fn = catia_fset_nt_acl,
2493 /* POSIX ACL operations. */
2494 .sys_acl_get_file_fn = catia_sys_acl_get_file,
2495 .sys_acl_get_fd_fn = catia_sys_acl_get_fd,
2496 .sys_acl_blob_get_fd_fn = catia_sys_acl_blob_get_fd,
2497 .sys_acl_set_file_fn = catia_sys_acl_set_file,
2498 .sys_acl_set_fd_fn = catia_sys_acl_set_fd,
2499 .sys_acl_delete_def_file_fn = catia_sys_acl_delete_def_file,
2501 /* EA operations. */
2502 .getxattr_fn = catia_getxattr,
2503 .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
2504 .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
2505 .listxattr_fn = catia_listxattr,
2506 .removexattr_fn = catia_removexattr,
2507 .setxattr_fn = catia_setxattr,
2508 .fgetxattr_fn = catia_fgetxattr,
2509 .flistxattr_fn = catia_flistxattr,
2510 .fremovexattr_fn = catia_fremovexattr,
2511 .fsetxattr_fn = catia_fsetxattr,
2515 NTSTATUS vfs_catia_init(TALLOC_CTX *ctx)
2519 ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
2521 if (!NT_STATUS_IS_OK(ret))
2524 vfs_catia_debug_level = debug_add_class("catia");
2525 if (vfs_catia_debug_level == -1) {
2526 vfs_catia_debug_level = DBGC_VFS;
2527 DEBUG(0, ("vfs_catia: Couldn't register custom debugging "
2530 DEBUG(10, ("vfs_catia: Debug class number of "
2531 "'catia': %d\n", vfs_catia_debug_level));