vfs: SMB_VFS_GET_COMPRESSION() -> SMB_VFS_FGET_COMPRESSION()
[samba.git] / source3 / modules / vfs_catia.c
1 /*
2  * Catia VFS module
3  *
4  * Implement a fixed mapping of forbidden NT characters in filenames that are
5  * used a lot by the CAD package Catia.
6  *
7  * Catia V4 on AIX uses characters like "<*$ a *lot*, all forbidden under
8  * Windows...
9  *
10  * Copyright (C) Volker Lendecke, 2005
11  * Copyright (C) Aravind Srinivasan, 2009
12  * Copyright (C) Guenter Kukkukk, 2013
13  * Copyright (C) Ralph Boehme, 2017
14  *
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.
19  *
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.
24  *
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/>.
27  */
28
29
30 #include "includes.h"
31 #include "smbd/smbd.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "string_replace.h"
35
36 static int vfs_catia_debug_level = DBGC_VFS;
37
38 #undef DBGC_CLASS
39 #define DBGC_CLASS vfs_catia_debug_level
40
41 struct share_mapping_entry {
42         int snum;
43         struct share_mapping_entry *next;
44         struct char_mappings **mappings;
45 };
46
47 struct catia_cache {
48         bool is_fsp_ext;
49         const struct catia_cache * const *busy;
50         char *orig_fname;
51         char *fname;
52         char *orig_base_fname;
53         char *base_fname;
54 };
55
56 static struct share_mapping_entry *srt_head = NULL;
57
58 static struct share_mapping_entry *get_srt(connection_struct *conn,
59                                            struct share_mapping_entry **global)
60 {
61         struct share_mapping_entry *share;
62
63         for (share = srt_head; share != NULL; share = share->next) {
64                 if (share->snum == GLOBAL_SECTION_SNUM)
65                         (*global) = share;
66
67                 if (share->snum == SNUM(conn))
68                         return share;
69         }
70
71         return share;
72 }
73
74 static struct share_mapping_entry *add_srt(int snum, const char **mappings)
75 {
76         struct share_mapping_entry *sme = NULL;
77
78         sme = TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry));
79         if (sme == NULL)
80                 return sme;
81
82         sme->snum = snum;
83         sme->next = srt_head;
84         srt_head = sme;
85
86         if (mappings == NULL) {
87                 sme->mappings = NULL;
88                 return sme;
89         }
90
91         sme->mappings = string_replace_init_map(sme, mappings);
92
93         return sme;
94 }
95
96 static bool init_mappings(connection_struct *conn,
97                           struct share_mapping_entry **selected_out)
98 {
99         const char **mappings = NULL;
100         struct share_mapping_entry *share_level = NULL;
101         struct share_mapping_entry *global = NULL;
102
103         /* check srt cache */
104         share_level = get_srt(conn, &global);
105         if (share_level) {
106                 *selected_out = share_level;
107                 return (share_level->mappings != NULL);
108         }
109
110         /* see if we have a global setting */
111         if (!global) {
112                 /* global setting */
113                 mappings = lp_parm_string_list(-1, "catia", "mappings", NULL);
114                 global = add_srt(GLOBAL_SECTION_SNUM, mappings);
115         }
116
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);
120
121         if (share_level->mappings) {
122                 (*selected_out) = share_level;
123                 return True;
124         }
125         if (global->mappings) {
126                 share_level->mappings = global->mappings;
127                 (*selected_out) = share_level;
128                 return True;
129         }
130
131         return False;
132 }
133
134 static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
135                                               const char *name_in,
136                                               char **mapped_name,
137                                         enum vfs_translate_direction direction)
138 {
139         struct share_mapping_entry *selected;
140         NTSTATUS status;
141
142         if (!init_mappings(conn, &selected)) {
143                 /* No mappings found. Just use the old name */
144                 *mapped_name = talloc_strdup(talloc_tos(), name_in);
145                 if (!*mapped_name) {
146                         errno = ENOMEM;
147                         return NT_STATUS_NO_MEMORY;
148                 }
149                 return NT_STATUS_OK;
150         }
151
152         status = string_replace_allocate(conn,
153                                          name_in,
154                                          selected->mappings,
155                                          talloc_tos(),
156                                          mapped_name,
157                                          direction);
158         return status;
159 }
160
161 static int catia_connect(struct vfs_handle_struct *handle,
162                          const char *service,
163                          const char *user)
164 {
165         /*
166          * Unless we have an async implementation of get_dos_attributes turn
167          * this off.
168          */
169         lp_do_parameter(SNUM(handle->conn), "smbd:async dosmode", "false");
170
171         return SMB_VFS_NEXT_CONNECT(handle, service, user);
172 }
173
174 /*
175  * TRANSLATE_NAME call which converts the given name to
176  * "WINDOWS displayable" name
177  */
178 static NTSTATUS catia_translate_name(struct vfs_handle_struct *handle,
179                                      const char *orig_name,
180                                      enum vfs_translate_direction direction,
181                                      TALLOC_CTX *mem_ctx,
182                                      char **pmapped_name)
183 {
184         char *name = NULL;
185         char *mapped_name;
186         NTSTATUS status, ret;
187
188         /*
189          * Copy the supplied name and free the memory for mapped_name,
190          * already allocated by the caller.
191          * We will be allocating new memory for mapped_name in
192          * catia_string_replace_allocate
193          */
194         name = talloc_strdup(talloc_tos(), orig_name);
195         if (!name) {
196                 errno = ENOMEM;
197                 return NT_STATUS_NO_MEMORY;
198         }
199         status = catia_string_replace_allocate(handle->conn, name,
200                         &mapped_name, direction);
201
202         TALLOC_FREE(name);
203         if (!NT_STATUS_IS_OK(status)) {
204                 return status;
205         }
206
207         ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction,
208                                           mem_ctx, pmapped_name);
209
210         if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
211                 *pmapped_name = talloc_move(mem_ctx, &mapped_name);
212                 /* we need to return the former translation result here */
213                 ret = status;
214         } else {
215                 TALLOC_FREE(mapped_name);
216         }
217
218         return ret;
219 }
220
221 #define CATIA_DEBUG_CC(lvl, cc, fsp) \
222         catia_debug_cc((lvl), (cc), (fsp), __location__);
223
224 static void catia_debug_cc(int lvl,
225                            struct catia_cache *cc,
226                            files_struct *fsp,
227                            const char *location)
228 {
229         DEBUG(lvl, ("%s: cc [%p] cc->busy [%p] "
230                     "is_fsp_ext [%s] "
231                     "fsp [%p] fsp name [%s] "
232                     "orig_fname [%s] "
233                     "fname [%s] "
234                     "orig_base_fname [%s] "
235                     "base_fname [%s]\n",
236                     location,
237                     cc, cc->busy,
238                     cc->is_fsp_ext ? "yes" : "no",
239                     fsp, fsp_str_dbg(fsp),
240                     cc->orig_fname, cc->fname,
241                     cc->orig_base_fname, cc->base_fname));
242 }
243
244 static void catia_free_cc(struct catia_cache **_cc,
245                           vfs_handle_struct *handle,
246                           files_struct *fsp)
247 {
248         struct catia_cache *cc = *_cc;
249
250         if (cc->is_fsp_ext) {
251                 VFS_REMOVE_FSP_EXTENSION(handle, fsp);
252                 cc = NULL;
253         } else {
254                 TALLOC_FREE(cc);
255         }
256
257         *_cc = NULL;
258 }
259
260 static struct catia_cache *catia_validate_and_apply_cc(
261                                        vfs_handle_struct *handle,
262                                        files_struct *fsp,
263                                        const struct catia_cache * const *busy,
264                                        bool *make_tmp_cache)
265 {
266         struct catia_cache *cc = NULL;
267
268         *make_tmp_cache = false;
269
270         cc = (struct catia_cache *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
271         if (cc == NULL) {
272                 return NULL;
273         }
274
275         if (cc->busy != NULL) {
276                 if (cc->busy == busy) {
277                         /* This should never happen */
278                         CATIA_DEBUG_CC(0, cc, fsp);
279                         smb_panic(__location__);
280                 }
281
282                 /*
283                  * Recursion. Validate names, the names in the fsp's should be
284                  * the translated names we had set.
285                  */
286
287                 if ((cc->fname != fsp->fsp_name->base_name)
288                     ||
289                     ((fsp->base_fsp != NULL) &&
290                      (cc->base_fname != fsp->base_fsp->fsp_name->base_name)))
291                 {
292                         CATIA_DEBUG_CC(10, cc, fsp);
293
294                         /*
295                          * Names changed. Setting don't expose the cache on the
296                          * fsp and ask the caller to create a temporary cache.
297                          */
298                         *make_tmp_cache = true;
299                         return NULL;
300                 }
301
302                 /*
303                  * Ok, a validated cache while in a recursion, just let the
304                  * caller detect that cc->busy is != busy and there's
305                  * nothing else to do.
306                  */
307                 CATIA_DEBUG_CC(10, cc, fsp);
308                 return cc;
309         }
310
311         /* Not in a recursion */
312
313         if ((cc->orig_fname != fsp->fsp_name->base_name)
314             ||
315             ((fsp->base_fsp != NULL) &&
316              (cc->orig_base_fname != fsp->base_fsp->fsp_name->base_name)))
317         {
318                 /*
319                  * fsp names changed, this can happen in an rename op.
320                  * Trigger recreation as a full fledged fsp extension.
321                  */
322
323                 CATIA_DEBUG_CC(10, cc, fsp);
324                 catia_free_cc(&cc, handle, fsp);
325                 return NULL;
326         }
327
328
329         /*
330          * Ok, we found a valid cache entry, no recursion. Just set translated
331          * names from the cache and mark the cc as busy.
332          */
333         fsp->fsp_name->base_name = cc->fname;
334         if (fsp->base_fsp != NULL) {
335                 fsp->base_fsp->fsp_name->base_name = cc->base_fname;
336         }
337
338         cc->busy = busy;
339         CATIA_DEBUG_CC(10, cc, fsp);
340         return cc;
341 }
342
343 #define CATIA_FETCH_FSP_PRE_NEXT(mem_ctx, handle, fsp, _cc) \
344         catia_fetch_fsp_pre_next((mem_ctx), (handle), (fsp), (_cc), __func__);
345
346 static int catia_fetch_fsp_pre_next(TALLOC_CTX *mem_ctx,
347                                     vfs_handle_struct *handle,
348                                     files_struct *fsp,
349                                     struct catia_cache **_cc,
350                                     const char *function)
351 {
352         const struct catia_cache * const *busy =
353                 (const struct catia_cache * const *)_cc;
354         struct catia_cache *cc = NULL;
355         NTSTATUS status;
356         bool make_tmp_cache = false;
357
358         *_cc = NULL;
359
360         DBG_DEBUG("Called from [%s]\n", function);
361
362         cc = catia_validate_and_apply_cc(handle,
363                                          fsp,
364                                          busy,
365                                          &make_tmp_cache);
366         if (cc != NULL) {
367                 if (cc->busy != busy) {
368                         return 0;
369                 }
370                 *_cc = cc;
371                 return 0;
372         }
373
374         if (!make_tmp_cache) {
375                 cc = VFS_ADD_FSP_EXTENSION(
376                         handle, fsp, struct catia_cache, NULL);
377                 if (cc == NULL) {
378                         return -1;
379                 }
380                 *cc = (struct catia_cache) {
381                         .is_fsp_ext = true,
382                 };
383
384                 mem_ctx = VFS_MEMCTX_FSP_EXTENSION(handle, fsp);
385                 if (mem_ctx == NULL) {
386                         DBG_ERR("VFS_MEMCTX_FSP_EXTENSION failed\n");
387                         catia_free_cc(&cc, handle, fsp);
388                         return -1;
389                 }
390         } else {
391                 cc = talloc_zero(mem_ctx, struct catia_cache);
392                 if (cc == NULL) {
393                         return -1;
394                 }
395                 mem_ctx = cc;
396         }
397
398
399         status = catia_string_replace_allocate(handle->conn,
400                                                fsp->fsp_name->base_name,
401                                                &cc->fname,
402                                                vfs_translate_to_unix);
403         if (!NT_STATUS_IS_OK(status)) {
404                 catia_free_cc(&cc, handle, fsp);
405                 errno = map_errno_from_nt_status(status);
406                 return -1;
407         }
408         talloc_steal(mem_ctx, cc->fname);
409
410         if (fsp->base_fsp != NULL) {
411                 status = catia_string_replace_allocate(
412                         handle->conn,
413                         fsp->base_fsp->fsp_name->base_name,
414                         &cc->base_fname,
415                         vfs_translate_to_unix);
416                 if (!NT_STATUS_IS_OK(status)) {
417                         catia_free_cc(&cc, handle, fsp);
418                         errno = map_errno_from_nt_status(status);
419                         return -1;
420                 }
421                 talloc_steal(mem_ctx, cc->base_fname);
422         }
423
424         cc->orig_fname = fsp->fsp_name->base_name;
425         fsp->fsp_name->base_name = cc->fname;
426
427         if (fsp->base_fsp != NULL) {
428                 cc->orig_base_fname = fsp->base_fsp->fsp_name->base_name;
429                 fsp->base_fsp->fsp_name->base_name = cc->base_fname;
430         }
431
432         cc->busy = busy;
433         CATIA_DEBUG_CC(10, cc, fsp);
434
435         *_cc = cc;
436
437         return 0;
438 }
439
440 #define CATIA_FETCH_FSP_POST_NEXT(_cc, fsp) do { \
441         int catia_saved_errno = errno; \
442         catia_fetch_fsp_post_next((_cc), (fsp), __func__); \
443         errno = catia_saved_errno; \
444 } while(0)
445
446 static void catia_fetch_fsp_post_next(struct catia_cache **_cc,
447                                       files_struct *fsp,
448                                       const char *function)
449 {
450         const struct catia_cache * const *busy =
451                 (const struct catia_cache * const *)_cc;
452         struct catia_cache *cc = *_cc;
453
454         DBG_DEBUG("Called from [%s]\n", function);
455
456         if (cc == NULL) {
457                 /*
458                  * This can happen when recursing in the VFS on the fsp when the
459                  * pre_next func noticed the recursion and set out cc pointer to
460                  * NULL.
461                  */
462                 return;
463         }
464
465         if (cc->busy != busy) {
466                 CATIA_DEBUG_CC(0, cc, fsp);
467                 smb_panic(__location__);
468                 return;
469         }
470
471         cc->busy = NULL;
472         *_cc = NULL;
473
474         fsp->fsp_name->base_name = cc->orig_fname;
475         if (fsp->base_fsp != NULL) {
476                 fsp->base_fsp->fsp_name->base_name = cc->orig_base_fname;
477         }
478
479         CATIA_DEBUG_CC(10, cc, fsp);
480
481         if (!cc->is_fsp_ext) {
482                 TALLOC_FREE(cc);
483         }
484
485         return;
486 }
487
488 static int catia_openat(vfs_handle_struct *handle,
489                         const struct files_struct *dirfsp,
490                         const struct smb_filename *smb_fname_in,
491                         files_struct *fsp,
492                         int flags,
493                         mode_t mode)
494 {
495         struct smb_filename *smb_fname = NULL;
496         struct catia_cache *cc = NULL;
497         char *mapped_name = NULL;
498         NTSTATUS status;
499         int ret;
500         int saved_errno = 0;
501
502         status = catia_string_replace_allocate(handle->conn,
503                                                smb_fname_in->base_name,
504                                                &mapped_name,
505                                                vfs_translate_to_unix);
506         if (!NT_STATUS_IS_OK(status)) {
507                 return -1;
508         }
509
510         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
511         if (ret != 0) {
512                 TALLOC_FREE(mapped_name);
513                 return ret;
514         }
515
516         smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
517         if (smb_fname == NULL) {
518                 TALLOC_FREE(mapped_name);
519                 errno = ENOMEM;
520                 return -1;
521         }
522         smb_fname->base_name = mapped_name;
523
524         ret = SMB_VFS_NEXT_OPENAT(handle,
525                                   dirfsp,
526                                   smb_fname,
527                                   fsp,
528                                   flags,
529                                   mode);
530
531         if (ret == -1) {
532                 saved_errno = errno;
533         }
534         TALLOC_FREE(smb_fname);
535         TALLOC_FREE(mapped_name);
536         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
537         if (saved_errno != 0) {
538                 errno = saved_errno;
539         }
540         return ret;
541 }
542
543 static int catia_renameat(vfs_handle_struct *handle,
544                         files_struct *srcfsp,
545                         const struct smb_filename *smb_fname_src,
546                         files_struct *dstfsp,
547                         const struct smb_filename *smb_fname_dst)
548 {
549         TALLOC_CTX *ctx = talloc_tos();
550         struct smb_filename *smb_fname_src_tmp = NULL;
551         struct smb_filename *smb_fname_dst_tmp = NULL;
552         char *src_name_mapped = NULL;
553         char *dst_name_mapped = NULL;
554         NTSTATUS status;
555         int ret = -1;
556
557         status = catia_string_replace_allocate(handle->conn,
558                                 smb_fname_src->base_name,
559                                 &src_name_mapped, vfs_translate_to_unix);
560         if (!NT_STATUS_IS_OK(status)) {
561                 errno = map_errno_from_nt_status(status);
562                 return -1;
563         }
564
565         status = catia_string_replace_allocate(handle->conn,
566                                 smb_fname_dst->base_name,
567                                 &dst_name_mapped, vfs_translate_to_unix);
568         if (!NT_STATUS_IS_OK(status)) {
569                 errno = map_errno_from_nt_status(status);
570                 return -1;
571         }
572
573         /* Setup temporary smb_filename structs. */
574         smb_fname_src_tmp = cp_smb_filename(ctx, smb_fname_src);
575         if (smb_fname_src_tmp == NULL) {
576                 errno = ENOMEM;
577                 goto out;
578         }
579
580         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
581         if (smb_fname_dst_tmp == NULL) {
582                 errno = ENOMEM;
583                 goto out;
584         }
585
586         smb_fname_src_tmp->base_name = src_name_mapped;
587         smb_fname_dst_tmp->base_name = dst_name_mapped;
588         DEBUG(10, ("converted old name: %s\n",
589                                 smb_fname_str_dbg(smb_fname_src_tmp)));
590         DEBUG(10, ("converted new name: %s\n",
591                                 smb_fname_str_dbg(smb_fname_dst_tmp)));
592
593         ret = SMB_VFS_NEXT_RENAMEAT(handle,
594                         srcfsp,
595                         smb_fname_src_tmp,
596                         dstfsp,
597                         smb_fname_dst_tmp);
598
599 out:
600         TALLOC_FREE(src_name_mapped);
601         TALLOC_FREE(dst_name_mapped);
602         TALLOC_FREE(smb_fname_src_tmp);
603         TALLOC_FREE(smb_fname_dst_tmp);
604         return ret;
605 }
606
607
608 static int catia_stat(vfs_handle_struct *handle,
609                       struct smb_filename *smb_fname)
610 {
611         char *name = NULL;
612         char *tmp_base_name;
613         int ret;
614         NTSTATUS status;
615
616         status = catia_string_replace_allocate(handle->conn,
617                                 smb_fname->base_name,
618                                 &name, vfs_translate_to_unix);
619         if (!NT_STATUS_IS_OK(status)) {
620                 errno = map_errno_from_nt_status(status);
621                 return -1;
622         }
623
624         tmp_base_name = smb_fname->base_name;
625         smb_fname->base_name = name;
626
627         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
628         smb_fname->base_name = tmp_base_name;
629
630         TALLOC_FREE(name);
631         return ret;
632 }
633
634 static int catia_lstat(vfs_handle_struct *handle,
635                        struct smb_filename *smb_fname)
636 {
637         char *name = NULL;
638         char *tmp_base_name;
639         int ret;
640         NTSTATUS status;
641
642         status = catia_string_replace_allocate(handle->conn,
643                                 smb_fname->base_name,
644                                 &name, vfs_translate_to_unix);
645         if (!NT_STATUS_IS_OK(status)) {
646                 errno = map_errno_from_nt_status(status);
647                 return -1;
648         }
649
650         tmp_base_name = smb_fname->base_name;
651         smb_fname->base_name = name;
652
653         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
654         smb_fname->base_name = tmp_base_name;
655         TALLOC_FREE(name);
656
657         return ret;
658 }
659
660 static int catia_unlinkat(vfs_handle_struct *handle,
661                         struct files_struct *dirfsp,
662                         const struct smb_filename *smb_fname,
663                         int flags)
664 {
665         struct smb_filename *smb_fname_tmp = NULL;
666         char *name = NULL;
667         NTSTATUS status;
668         int ret;
669
670         status = catia_string_replace_allocate(handle->conn,
671                                         smb_fname->base_name,
672                                         &name, vfs_translate_to_unix);
673         if (!NT_STATUS_IS_OK(status)) {
674                 errno = map_errno_from_nt_status(status);
675                 return -1;
676         }
677
678         /* Setup temporary smb_filename structs. */
679         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
680         if (smb_fname_tmp == NULL) {
681                 errno = ENOMEM;
682                 return -1;
683         }
684
685         smb_fname_tmp->base_name = name;
686         ret = SMB_VFS_NEXT_UNLINKAT(handle,
687                         dirfsp,
688                         smb_fname_tmp,
689                         flags);
690         TALLOC_FREE(smb_fname_tmp);
691         TALLOC_FREE(name);
692
693         return ret;
694 }
695
696 static int catia_lchown(vfs_handle_struct *handle,
697                         const struct smb_filename *smb_fname,
698                         uid_t uid,
699                         gid_t gid)
700 {
701         char *name = NULL;
702         NTSTATUS status;
703         int ret;
704         int saved_errno;
705         struct smb_filename *catia_smb_fname = NULL;
706
707         status = catia_string_replace_allocate(handle->conn,
708                                         smb_fname->base_name,
709                                         &name,
710                                         vfs_translate_to_unix);
711         if (!NT_STATUS_IS_OK(status)) {
712                 errno = map_errno_from_nt_status(status);
713                 return -1;
714         }
715         catia_smb_fname = synthetic_smb_fname(talloc_tos(),
716                                         name,
717                                         NULL,
718                                         &smb_fname->st,
719                                         smb_fname->twrp,
720                                         smb_fname->flags);
721         if (catia_smb_fname == NULL) {
722                 TALLOC_FREE(name);
723                 errno = ENOMEM;
724                 return -1;
725         }
726
727         ret = SMB_VFS_NEXT_LCHOWN(handle, catia_smb_fname, uid, gid);
728         saved_errno = errno;
729         TALLOC_FREE(name);
730         TALLOC_FREE(catia_smb_fname);
731         errno = saved_errno;
732         return ret;
733 }
734
735 static int catia_chmod(vfs_handle_struct *handle,
736                         const struct smb_filename *smb_fname,
737                         mode_t mode)
738 {
739         char *name = NULL;
740         NTSTATUS status;
741         int ret;
742         int saved_errno;
743         struct smb_filename *catia_smb_fname = NULL;
744
745         status = catia_string_replace_allocate(handle->conn,
746                                         smb_fname->base_name,
747                                         &name,
748                                         vfs_translate_to_unix);
749         if (!NT_STATUS_IS_OK(status)) {
750                 errno = map_errno_from_nt_status(status);
751                 return -1;
752         }
753         catia_smb_fname = synthetic_smb_fname(talloc_tos(),
754                                         name,
755                                         NULL,
756                                         &smb_fname->st,
757                                         smb_fname->twrp,
758                                         smb_fname->flags);
759         if (catia_smb_fname == NULL) {
760                 TALLOC_FREE(name);
761                 errno = ENOMEM;
762                 return -1;
763         }
764
765         ret = SMB_VFS_NEXT_CHMOD(handle, catia_smb_fname, mode);
766         saved_errno = errno;
767         TALLOC_FREE(name);
768         TALLOC_FREE(catia_smb_fname);
769         errno = saved_errno;
770         return ret;
771 }
772
773 static int catia_mkdirat(vfs_handle_struct *handle,
774                         struct files_struct *dirfsp,
775                         const struct smb_filename *smb_fname,
776                         mode_t mode)
777 {
778         char *name = NULL;
779         NTSTATUS status;
780         int ret;
781         struct smb_filename *catia_smb_fname = NULL;
782
783         status = catia_string_replace_allocate(handle->conn,
784                                 smb_fname->base_name,
785                                 &name,
786                                 vfs_translate_to_unix);
787         if (!NT_STATUS_IS_OK(status)) {
788                 errno = map_errno_from_nt_status(status);
789                 return -1;
790         }
791         catia_smb_fname = synthetic_smb_fname(talloc_tos(),
792                                         name,
793                                         NULL,
794                                         &smb_fname->st,
795                                         smb_fname->twrp,
796                                         smb_fname->flags);
797         if (catia_smb_fname == NULL) {
798                 TALLOC_FREE(name);
799                 errno = ENOMEM;
800                 return -1;
801         }
802
803         ret = SMB_VFS_NEXT_MKDIRAT(handle,
804                         dirfsp,
805                         catia_smb_fname,
806                         mode);
807         TALLOC_FREE(name);
808         TALLOC_FREE(catia_smb_fname);
809
810         return ret;
811 }
812
813 static int catia_chdir(vfs_handle_struct *handle,
814                         const struct smb_filename *smb_fname)
815 {
816         char *name = NULL;
817         struct smb_filename *catia_smb_fname = NULL;
818         NTSTATUS status;
819         int ret;
820
821         status = catia_string_replace_allocate(handle->conn,
822                                         smb_fname->base_name,
823                                         &name,
824                                         vfs_translate_to_unix);
825         if (!NT_STATUS_IS_OK(status)) {
826                 errno = map_errno_from_nt_status(status);
827                 return -1;
828         }
829
830         catia_smb_fname = synthetic_smb_fname(talloc_tos(),
831                                         name,
832                                         NULL,
833                                         &smb_fname->st,
834                                         smb_fname->twrp,
835                                         smb_fname->flags);
836         if (catia_smb_fname == NULL) {
837                 TALLOC_FREE(name);
838                 errno = ENOMEM;
839                 return -1;
840         }
841         ret = SMB_VFS_NEXT_CHDIR(handle, catia_smb_fname);
842         TALLOC_FREE(name);
843         TALLOC_FREE(catia_smb_fname);
844
845         return ret;
846 }
847
848 static int catia_ntimes(vfs_handle_struct *handle,
849                         const struct smb_filename *smb_fname,
850                         struct smb_file_time *ft)
851 {
852         struct smb_filename *smb_fname_tmp = NULL;
853         char *name = NULL;
854         NTSTATUS status;
855         int ret;
856
857         status = catia_string_replace_allocate(handle->conn,
858                                 smb_fname->base_name,
859                                 &name, vfs_translate_to_unix);
860         if (!NT_STATUS_IS_OK(status)) {
861                 errno = map_errno_from_nt_status(status);
862                 return -1;
863         }
864
865         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
866         if (smb_fname_tmp == NULL) {
867                 errno = ENOMEM;
868                 return -1;
869         }
870
871         smb_fname_tmp->base_name = name;
872         ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
873         TALLOC_FREE(name);
874         TALLOC_FREE(smb_fname_tmp);
875
876         return ret;
877 }
878
879 static struct smb_filename *
880 catia_realpath(vfs_handle_struct *handle,
881                 TALLOC_CTX *ctx,
882                 const struct smb_filename *smb_fname)
883 {
884         char *mapped_name = NULL;
885         struct smb_filename *catia_smb_fname = NULL;
886         struct smb_filename *return_fname = NULL;
887         NTSTATUS status;
888
889         status = catia_string_replace_allocate(handle->conn,
890                                         smb_fname->base_name,
891                                         &mapped_name, vfs_translate_to_unix);
892         if (!NT_STATUS_IS_OK(status)) {
893                 errno = map_errno_from_nt_status(status);
894                 return NULL;
895         }
896
897         catia_smb_fname = synthetic_smb_fname(talloc_tos(),
898                                         mapped_name,
899                                         NULL,
900                                         &smb_fname->st,
901                                         smb_fname->twrp,
902                                         smb_fname->flags);
903         if (catia_smb_fname == NULL) {
904                 TALLOC_FREE(mapped_name);
905                 errno = ENOMEM;
906                 return NULL;
907         }
908         return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, catia_smb_fname);
909         TALLOC_FREE(mapped_name);
910         TALLOC_FREE(catia_smb_fname);
911         return return_fname;
912 }
913
914 static int catia_chflags(struct vfs_handle_struct *handle,
915                         const struct smb_filename *smb_fname,
916                         unsigned int flags)
917 {
918         char *name = NULL;
919         struct smb_filename *catia_smb_fname = NULL;
920         NTSTATUS status;
921         int ret;
922
923         status = catia_string_replace_allocate(handle->conn,
924                                 smb_fname->base_name,
925                                 &name,
926                                 vfs_translate_to_unix);
927         if (!NT_STATUS_IS_OK(status)) {
928                 errno = map_errno_from_nt_status(status);
929                 return -1;
930         }
931         catia_smb_fname = synthetic_smb_fname(talloc_tos(),
932                                         name,
933                                         NULL,
934                                         &smb_fname->st,
935                                         smb_fname->twrp,
936                                         smb_fname->flags);
937         if (catia_smb_fname == NULL) {
938                 TALLOC_FREE(name);
939                 errno = ENOMEM;
940                 return -1;
941         }
942
943         ret = SMB_VFS_NEXT_CHFLAGS(handle, catia_smb_fname, flags);
944         TALLOC_FREE(name);
945         TALLOC_FREE(catia_smb_fname);
946
947         return ret;
948 }
949
950 static NTSTATUS
951 catia_streaminfo(struct vfs_handle_struct *handle,
952                  struct files_struct *fsp,
953                  const struct smb_filename *smb_fname,
954                  TALLOC_CTX *mem_ctx,
955                  unsigned int *_num_streams,
956                  struct stream_struct **_streams)
957 {
958         char *mapped_name = NULL;
959         NTSTATUS status;
960         unsigned int i;
961         struct smb_filename *catia_smb_fname = NULL;
962         unsigned int num_streams = 0;
963         struct stream_struct *streams = NULL;
964
965         *_num_streams = 0;
966         *_streams = NULL;
967
968         status = catia_string_replace_allocate(handle->conn,
969                                 smb_fname->base_name,
970                                 &mapped_name,
971                                 vfs_translate_to_unix);
972         if (!NT_STATUS_IS_OK(status)) {
973                 errno = map_errno_from_nt_status(status);
974                 return status;
975         }
976
977         catia_smb_fname = synthetic_smb_fname(talloc_tos(),
978                                         mapped_name,
979                                         NULL,
980                                         &smb_fname->st,
981                                         smb_fname->twrp,
982                                         smb_fname->flags);
983         if (catia_smb_fname == NULL) {
984                 TALLOC_FREE(mapped_name);
985                 return NT_STATUS_NO_MEMORY;
986         }
987
988         status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, catia_smb_fname,
989                                          mem_ctx, &num_streams, &streams);
990         TALLOC_FREE(mapped_name);
991         TALLOC_FREE(catia_smb_fname);
992         if (!NT_STATUS_IS_OK(status)) {
993                 return status;
994         }
995
996         /*
997          * Translate stream names just like the base names
998          */
999         for (i = 0; i < num_streams; i++) {
1000                 /*
1001                  * Strip ":" prefix and ":$DATA" suffix to get a
1002                  * "pure" stream name and only translate that.
1003                  */
1004                 void *old_ptr = streams[i].name;
1005                 char *stream_name = streams[i].name + 1;
1006                 char *stream_type = strrchr_m(stream_name, ':');
1007
1008                 if (stream_type != NULL) {
1009                         *stream_type = '\0';
1010                         stream_type += 1;
1011                 }
1012
1013                 status = catia_string_replace_allocate(handle->conn, stream_name,
1014                                                        &mapped_name, vfs_translate_to_windows);
1015                 if (!NT_STATUS_IS_OK(status)) {
1016                         TALLOC_FREE(streams);
1017                         return status;
1018                 }
1019
1020                 if (stream_type != NULL) {
1021                         streams[i].name = talloc_asprintf(streams, ":%s:%s",
1022                                                           mapped_name, stream_type);
1023                 } else {
1024                         streams[i].name = talloc_asprintf(streams, ":%s",
1025                                                           mapped_name);
1026                 }
1027                 TALLOC_FREE(mapped_name);
1028                 TALLOC_FREE(old_ptr);
1029                 if (streams[i].name == NULL) {
1030                         TALLOC_FREE(streams);
1031                         return NT_STATUS_NO_MEMORY;
1032                 }
1033         }
1034
1035         *_num_streams = num_streams;
1036         *_streams = streams;
1037         return NT_STATUS_OK;
1038 }
1039
1040 static NTSTATUS catia_get_nt_acl_at(struct vfs_handle_struct *handle,
1041                                     struct files_struct *dirfsp,
1042                                     const struct smb_filename *smb_fname,
1043                                     uint32_t security_info,
1044                                     TALLOC_CTX *mem_ctx,
1045                                     struct security_descriptor **ppdesc)
1046 {
1047         char *mapped_name = NULL;
1048         const char *path = smb_fname->base_name;
1049         struct smb_filename *mapped_smb_fname = NULL;
1050         NTSTATUS status;
1051
1052         SMB_ASSERT(dirfsp == handle->conn->cwd_fsp);
1053
1054         status = catia_string_replace_allocate(handle->conn,
1055                                 path, &mapped_name, vfs_translate_to_unix);
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 errno = map_errno_from_nt_status(status);
1058                 return status;
1059         }
1060         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1061                                         mapped_name,
1062                                         NULL,
1063                                         &smb_fname->st,
1064                                         smb_fname->twrp,
1065                                         smb_fname->flags);
1066         if (mapped_smb_fname == NULL) {
1067                 TALLOC_FREE(mapped_name);
1068                 return NT_STATUS_NO_MEMORY;
1069         }
1070
1071         status = SMB_VFS_NEXT_GET_NT_ACL_AT(handle,
1072                                         dirfsp,
1073                                         mapped_smb_fname,
1074                                         security_info,
1075                                         mem_ctx,
1076                                         ppdesc);
1077         TALLOC_FREE(mapped_name);
1078         TALLOC_FREE(mapped_smb_fname);
1079
1080         return status;
1081 }
1082
1083 static SMB_ACL_T
1084 catia_sys_acl_get_file(vfs_handle_struct *handle,
1085                         const struct smb_filename *smb_fname,
1086                         SMB_ACL_TYPE_T type,
1087                         TALLOC_CTX *mem_ctx)
1088 {
1089         char *mapped_name = NULL;
1090         struct smb_filename *mapped_smb_fname = NULL;
1091         NTSTATUS status;
1092         SMB_ACL_T ret;
1093         int saved_errno = 0;
1094
1095         status = catia_string_replace_allocate(handle->conn,
1096                                 smb_fname->base_name,
1097                                 &mapped_name,
1098                                 vfs_translate_to_unix);
1099         if (!NT_STATUS_IS_OK(status)) {
1100                 errno = map_errno_from_nt_status(status);
1101                 return (SMB_ACL_T)NULL;
1102         }
1103
1104         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1105                                         mapped_name,
1106                                         NULL,
1107                                         &smb_fname->st,
1108                                         smb_fname->twrp,
1109                                         smb_fname->flags);
1110         if (mapped_smb_fname == NULL) {
1111                 TALLOC_FREE(mapped_name);
1112                 errno = ENOMEM;
1113                 return (SMB_ACL_T)NULL;
1114         }
1115
1116         ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, mapped_smb_fname,
1117                         type, mem_ctx);
1118         if (ret == (SMB_ACL_T)NULL) {
1119                 saved_errno = errno;
1120         }
1121         TALLOC_FREE(mapped_smb_fname);
1122         TALLOC_FREE(mapped_name);
1123         if (saved_errno != 0) {
1124                 errno = saved_errno;
1125         }
1126         return ret;
1127 }
1128
1129 static int
1130 catia_sys_acl_set_file(vfs_handle_struct *handle,
1131                         const struct smb_filename *smb_fname,
1132                         SMB_ACL_TYPE_T type,
1133                         SMB_ACL_T theacl)
1134 {
1135         struct smb_filename *mapped_smb_fname = NULL;
1136         int saved_errno = 0;
1137         char *mapped_name = NULL;
1138         NTSTATUS status;
1139         int ret;
1140
1141         status = catia_string_replace_allocate(handle->conn,
1142                                 smb_fname->base_name,
1143                                 &mapped_name,
1144                                 vfs_translate_to_unix);
1145         if (!NT_STATUS_IS_OK(status)) {
1146                 errno = map_errno_from_nt_status(status);
1147                 return -1;
1148         }
1149
1150         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1151                                         mapped_name,
1152                                         NULL,
1153                                         &smb_fname->st,
1154                                         smb_fname->twrp,
1155                                         smb_fname->flags);
1156         if (mapped_smb_fname == NULL) {
1157                 TALLOC_FREE(mapped_name);
1158                 errno = ENOMEM;
1159                 return -1;
1160         }
1161
1162         ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, mapped_smb_fname,
1163                         type, theacl);
1164         if (ret == -1) {
1165                 saved_errno = errno;
1166         }
1167         TALLOC_FREE(mapped_smb_fname);
1168         TALLOC_FREE(mapped_name);
1169         if (saved_errno != 0) {
1170                 errno = saved_errno;
1171         }
1172         return ret;
1173 }
1174
1175 static int
1176 catia_sys_acl_delete_def_file(vfs_handle_struct *handle,
1177                                 const struct smb_filename *smb_fname)
1178 {
1179         struct smb_filename *mapped_smb_fname = NULL;
1180         int saved_errno = 0;
1181         char *mapped_name = NULL;
1182         NTSTATUS status;
1183         int ret;
1184
1185         status = catia_string_replace_allocate(handle->conn,
1186                                 smb_fname->base_name,
1187                                 &mapped_name,
1188                                 vfs_translate_to_unix);
1189         if (!NT_STATUS_IS_OK(status)) {
1190                 errno = map_errno_from_nt_status(status);
1191                 return -1;
1192         }
1193
1194         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1195                                         mapped_name,
1196                                         NULL,
1197                                         &smb_fname->st,
1198                                         smb_fname->twrp,
1199                                         smb_fname->flags);
1200         if (mapped_smb_fname == NULL) {
1201                 TALLOC_FREE(mapped_name);
1202                 errno = ENOMEM;
1203                 return -1;
1204         }
1205         ret = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, mapped_smb_fname);
1206         if (ret == -1) {
1207                 saved_errno = errno;
1208         }
1209         TALLOC_FREE(mapped_smb_fname);
1210         TALLOC_FREE(mapped_name);
1211         if (saved_errno != 0) {
1212                 errno = saved_errno;
1213         }
1214         return ret;
1215 }
1216
1217 static ssize_t
1218 catia_getxattr(vfs_handle_struct *handle,
1219                         const struct smb_filename *smb_fname,
1220                         const char *name,
1221                         void *value,
1222                         size_t size)
1223 {
1224         struct smb_filename *mapped_smb_fname = NULL;
1225         char *mapped_name = NULL;
1226         char *mapped_ea_name = NULL;
1227         NTSTATUS status;
1228         ssize_t ret;
1229         int saved_errno = 0;
1230
1231         status = catia_string_replace_allocate(handle->conn,
1232                                 smb_fname->base_name,
1233                                 &mapped_name,
1234                                 vfs_translate_to_unix);
1235         if (!NT_STATUS_IS_OK(status)) {
1236                 errno = map_errno_from_nt_status(status);
1237                 return -1;
1238         }
1239
1240         status = catia_string_replace_allocate(handle->conn,
1241                                 name, &mapped_ea_name, vfs_translate_to_unix);
1242         if (!NT_STATUS_IS_OK(status)) {
1243                 TALLOC_FREE(mapped_name);
1244                 errno = map_errno_from_nt_status(status);
1245                 return -1;
1246         }
1247
1248         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1249                                         mapped_name,
1250                                         NULL,
1251                                         &smb_fname->st,
1252                                         smb_fname->twrp,
1253                                         smb_fname->flags);
1254         if (mapped_smb_fname == NULL) {
1255                 TALLOC_FREE(mapped_name);
1256                 TALLOC_FREE(mapped_ea_name);
1257                 errno = ENOMEM;
1258                 return -1;
1259         }
1260
1261         ret = SMB_VFS_NEXT_GETXATTR(handle, mapped_smb_fname,
1262                                 mapped_ea_name, value, size);
1263         if (ret == -1) {
1264                 saved_errno = errno;
1265         }
1266         TALLOC_FREE(mapped_name);
1267         TALLOC_FREE(mapped_ea_name);
1268         TALLOC_FREE(mapped_smb_fname);
1269         if (saved_errno != 0) {
1270                 errno = saved_errno;
1271         }
1272
1273         return ret;
1274 }
1275
1276 static ssize_t
1277 catia_listxattr(vfs_handle_struct *handle,
1278                 const struct smb_filename *smb_fname,
1279                 char *list, size_t size)
1280 {
1281         struct smb_filename *mapped_smb_fname = NULL;
1282         char *mapped_name = NULL;
1283         NTSTATUS status;
1284         ssize_t ret;
1285         int saved_errno = 0;
1286
1287         status = catia_string_replace_allocate(handle->conn,
1288                                 smb_fname->base_name,
1289                                 &mapped_name,
1290                                 vfs_translate_to_unix);
1291         if (!NT_STATUS_IS_OK(status)) {
1292                 errno = map_errno_from_nt_status(status);
1293                 return -1;
1294         }
1295
1296         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1297                                         mapped_name,
1298                                         NULL,
1299                                         &smb_fname->st,
1300                                         smb_fname->twrp,
1301                                         smb_fname->flags);
1302         if (mapped_smb_fname == NULL) {
1303                 TALLOC_FREE(mapped_name);
1304                 errno = ENOMEM;
1305                 return -1;
1306         }
1307
1308         ret = SMB_VFS_NEXT_LISTXATTR(handle, mapped_smb_fname, list, size);
1309         if (ret == -1) {
1310                 saved_errno = errno;
1311         }
1312         TALLOC_FREE(mapped_name);
1313         TALLOC_FREE(mapped_smb_fname);
1314         if (saved_errno != 0) {
1315                 errno = saved_errno;
1316         }
1317
1318         return ret;
1319 }
1320
1321 static int
1322 catia_removexattr(vfs_handle_struct *handle,
1323                         const struct smb_filename *smb_fname,
1324                         const char *name)
1325 {
1326         struct smb_filename *mapped_smb_fname = NULL;
1327         char *mapped_name = NULL;
1328         char *mapped_ea_name = NULL;
1329         NTSTATUS status;
1330         ssize_t ret;
1331         int saved_errno = 0;
1332
1333         status = catia_string_replace_allocate(handle->conn,
1334                                 smb_fname->base_name,
1335                                 &mapped_name,
1336                                 vfs_translate_to_unix);
1337         if (!NT_STATUS_IS_OK(status)) {
1338                 errno = map_errno_from_nt_status(status);
1339                 return -1;
1340         }
1341
1342         status = catia_string_replace_allocate(handle->conn,
1343                                 name, &mapped_ea_name, vfs_translate_to_unix);
1344         if (!NT_STATUS_IS_OK(status)) {
1345                 TALLOC_FREE(mapped_name);
1346                 errno = map_errno_from_nt_status(status);
1347                 return -1;
1348         }
1349
1350         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1351                                         mapped_name,
1352                                         NULL,
1353                                         &smb_fname->st,
1354                                         smb_fname->twrp,
1355                                         smb_fname->flags);
1356         if (mapped_smb_fname == NULL) {
1357                 TALLOC_FREE(mapped_name);
1358                 TALLOC_FREE(mapped_ea_name);
1359                 errno = ENOMEM;
1360                 return -1;
1361         }
1362
1363         ret = SMB_VFS_NEXT_REMOVEXATTR(handle, mapped_smb_fname,
1364                                 mapped_ea_name);
1365         if (ret == -1) {
1366                 saved_errno = errno;
1367         }
1368         TALLOC_FREE(mapped_name);
1369         TALLOC_FREE(mapped_ea_name);
1370         TALLOC_FREE(mapped_smb_fname);
1371         if (saved_errno != 0) {
1372                 errno = saved_errno;
1373         }
1374
1375         return ret;
1376 }
1377
1378 static int
1379 catia_setxattr(vfs_handle_struct *handle,
1380                         const struct smb_filename *smb_fname,
1381                         const char *name,
1382                         const void *value,
1383                         size_t size,
1384                         int flags)
1385 {
1386         struct smb_filename *mapped_smb_fname = NULL;
1387         char *mapped_name = NULL;
1388         char *mapped_ea_name = NULL;
1389         NTSTATUS status;
1390         ssize_t ret;
1391         int saved_errno = 0;
1392
1393         status = catia_string_replace_allocate(handle->conn,
1394                                 smb_fname->base_name,
1395                                 &mapped_name,
1396                                 vfs_translate_to_unix);
1397         if (!NT_STATUS_IS_OK(status)) {
1398                 errno = map_errno_from_nt_status(status);
1399                 return -1;
1400         }
1401
1402         status = catia_string_replace_allocate(handle->conn,
1403                                 name, &mapped_ea_name, vfs_translate_to_unix);
1404         if (!NT_STATUS_IS_OK(status)) {
1405                 TALLOC_FREE(mapped_name);
1406                 errno = map_errno_from_nt_status(status);
1407                 return -1;
1408         }
1409
1410         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
1411                                         mapped_name,
1412                                         NULL,
1413                                         &smb_fname->st,
1414                                         smb_fname->twrp,
1415                                         smb_fname->flags);
1416         if (mapped_smb_fname == NULL) {
1417                 TALLOC_FREE(mapped_name);
1418                 TALLOC_FREE(mapped_ea_name);
1419                 errno = ENOMEM;
1420                 return -1;
1421         }
1422
1423         ret = SMB_VFS_NEXT_SETXATTR(handle, mapped_smb_fname, mapped_ea_name,
1424                         value, size, flags);
1425         if (ret == -1) {
1426                 saved_errno = errno;
1427         }
1428         TALLOC_FREE(mapped_name);
1429         TALLOC_FREE(mapped_ea_name);
1430         TALLOC_FREE(mapped_smb_fname);
1431         if (saved_errno != 0) {
1432                 errno = saved_errno;
1433         }
1434
1435         return ret;
1436 }
1437
1438 static int catia_fstat(vfs_handle_struct *handle,
1439                        files_struct *fsp,
1440                        SMB_STRUCT_STAT *sbuf)
1441 {
1442         struct catia_cache *cc = NULL;
1443         int ret;
1444
1445         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1446         if (ret != 0) {
1447                 return ret;
1448         }
1449
1450         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1451
1452         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1453
1454         return ret;
1455 }
1456
1457 static ssize_t catia_pread(vfs_handle_struct *handle,
1458                            files_struct *fsp, void *data,
1459                            size_t n, off_t offset)
1460 {
1461         struct catia_cache *cc = NULL;
1462         ssize_t result;
1463         int ret;
1464
1465         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1466         if (ret != 0) {
1467                 return ret;
1468         }
1469
1470         result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
1471
1472         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1473
1474         return result;
1475 }
1476
1477 static ssize_t catia_pwrite(vfs_handle_struct *handle,
1478                             files_struct *fsp, const void *data,
1479                             size_t n, off_t offset)
1480 {
1481         struct catia_cache *cc = NULL;
1482         ssize_t result;
1483         int ret;
1484
1485         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1486         if (ret != 0) {
1487                 return ret;
1488         }
1489
1490         result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
1491
1492         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1493
1494         return result;
1495 }
1496
1497 static int catia_ftruncate(struct vfs_handle_struct *handle,
1498                            struct files_struct *fsp,
1499                            off_t offset)
1500 {
1501         struct catia_cache *cc = NULL;
1502         int ret;
1503
1504         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1505         if (ret != 0) {
1506                 return ret;
1507         }
1508
1509         ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
1510
1511         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1512
1513         return ret;
1514 }
1515
1516 static int catia_fallocate(struct vfs_handle_struct *handle,
1517                            struct files_struct *fsp,
1518                            uint32_t mode,
1519                            off_t offset,
1520                            off_t len)
1521 {
1522         struct catia_cache *cc = NULL;
1523         int ret;
1524
1525         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1526         if (ret != 0) {
1527                 return ret;
1528         }
1529
1530         ret = SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
1531
1532         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1533
1534         return ret;
1535 }
1536
1537 static ssize_t catia_fgetxattr(struct vfs_handle_struct *handle,
1538                                struct files_struct *fsp,
1539                                const char *name,
1540                                void *value,
1541                                size_t size)
1542 {
1543         char *mapped_xattr_name = NULL;
1544         NTSTATUS status;
1545         ssize_t result;
1546
1547         status = catia_string_replace_allocate(handle->conn,
1548                                                name, &mapped_xattr_name,
1549                                                vfs_translate_to_unix);
1550         if (!NT_STATUS_IS_OK(status)) {
1551                 errno = map_errno_from_nt_status(status);
1552                 return -1;
1553         }
1554
1555         result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, mapped_xattr_name,
1556                                         value, size);
1557
1558         TALLOC_FREE(mapped_xattr_name);
1559
1560         return result;
1561 }
1562
1563 static ssize_t catia_flistxattr(struct vfs_handle_struct *handle,
1564                                 struct files_struct *fsp,
1565                                 char *list,
1566                                 size_t size)
1567 {
1568         struct catia_cache *cc = NULL;
1569         ssize_t result;
1570         int ret;
1571
1572         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1573         if (ret != 0) {
1574                 return ret;
1575         }
1576
1577         result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
1578
1579         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1580
1581         return result;
1582 }
1583
1584 static int catia_fremovexattr(struct vfs_handle_struct *handle,
1585                               struct files_struct *fsp,
1586                               const char *name)
1587 {
1588         char *mapped_name = NULL;
1589         NTSTATUS status;
1590         int ret;
1591
1592         status = catia_string_replace_allocate(handle->conn,
1593                                 name, &mapped_name, vfs_translate_to_unix);
1594         if (!NT_STATUS_IS_OK(status)) {
1595                 errno = map_errno_from_nt_status(status);
1596                 return -1;
1597         }
1598
1599         ret = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, mapped_name);
1600
1601         TALLOC_FREE(mapped_name);
1602
1603         return ret;
1604 }
1605
1606 static int catia_fsetxattr(struct vfs_handle_struct *handle,
1607                            struct files_struct *fsp,
1608                            const char *name,
1609                            const void *value,
1610                            size_t size,
1611                            int flags)
1612 {
1613         char *mapped_xattr_name = NULL;
1614         NTSTATUS status;
1615         int ret;
1616
1617         status = catia_string_replace_allocate(
1618                 handle->conn, name, &mapped_xattr_name, vfs_translate_to_unix);
1619         if (!NT_STATUS_IS_OK(status)) {
1620                 errno = map_errno_from_nt_status(status);
1621                 return -1;
1622         }
1623
1624         ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, mapped_xattr_name,
1625                                      value, size, flags);
1626
1627         TALLOC_FREE(mapped_xattr_name);
1628
1629         return ret;
1630 }
1631
1632 static SMB_ACL_T catia_sys_acl_get_fd(vfs_handle_struct *handle,
1633                                       files_struct *fsp,
1634                                       TALLOC_CTX *mem_ctx)
1635 {
1636         struct catia_cache *cc = NULL;
1637         struct smb_acl_t *result = NULL;
1638         int ret;
1639
1640         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1641         if (ret != 0) {
1642                 return NULL;
1643         }
1644
1645         result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
1646
1647         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1648
1649         return result;
1650 }
1651
1652 static int catia_sys_acl_blob_get_fd(vfs_handle_struct *handle,
1653                                      files_struct *fsp,
1654                                      TALLOC_CTX *mem_ctx,
1655                                      char **blob_description,
1656                                      DATA_BLOB *blob)
1657 {
1658         struct catia_cache *cc = NULL;
1659         int ret;
1660
1661         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1662         if (ret != 0) {
1663                 return ret;
1664         }
1665
1666         ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx,
1667                                                blob_description, blob);
1668
1669         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1670
1671         return ret;
1672 }
1673
1674 static int catia_sys_acl_set_fd(vfs_handle_struct *handle,
1675                                 files_struct *fsp,
1676                                 SMB_ACL_T theacl)
1677 {
1678         struct catia_cache *cc = NULL;
1679         int ret;
1680
1681         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1682         if (ret != 0) {
1683                 return ret;
1684         }
1685
1686         ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
1687
1688         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1689
1690         return ret;
1691 }
1692
1693 static NTSTATUS catia_fget_nt_acl(vfs_handle_struct *handle,
1694                                   files_struct *fsp,
1695                                   uint32_t security_info,
1696                                   TALLOC_CTX *mem_ctx,
1697                                   struct security_descriptor **ppdesc)
1698 {
1699         struct catia_cache *cc = NULL;
1700         NTSTATUS status;
1701         int ret;
1702
1703         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1704         if (ret != 0) {
1705                 return map_nt_error_from_unix(errno);
1706         }
1707
1708         status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
1709                                           mem_ctx, ppdesc);
1710
1711         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1712
1713         return status;
1714 }
1715
1716 static NTSTATUS catia_fset_nt_acl(vfs_handle_struct *handle,
1717                                   files_struct *fsp,
1718                                   uint32_t security_info_sent,
1719                                   const struct security_descriptor *psd)
1720 {
1721         struct catia_cache *cc = NULL;
1722         NTSTATUS status;
1723         int ret;
1724
1725         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1726         if (ret != 0) {
1727                 return map_nt_error_from_unix(errno);
1728         }
1729
1730         status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
1731
1732         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1733
1734         return status;
1735 }
1736
1737 static NTSTATUS catia_fset_dos_attributes(struct vfs_handle_struct *handle,
1738                                           struct files_struct *fsp,
1739                                           uint32_t dosmode)
1740 {
1741         struct catia_cache *cc = NULL;
1742         NTSTATUS status;
1743         int ret;
1744
1745         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1746         if (ret != 0) {
1747                 return map_nt_error_from_unix(errno);
1748         }
1749
1750         status = SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES(handle, fsp, dosmode);
1751
1752         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1753
1754         return status;
1755 }
1756
1757 static NTSTATUS catia_fget_dos_attributes(struct vfs_handle_struct *handle,
1758                                           struct files_struct *fsp,
1759                                           uint32_t *dosmode)
1760 {
1761         struct catia_cache *cc = NULL;
1762         NTSTATUS status;
1763         int ret;
1764
1765         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1766         if (ret != 0) {
1767                 return map_nt_error_from_unix(errno);
1768         }
1769
1770         status = SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode);
1771
1772         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1773
1774         return status;
1775 }
1776
1777 static int catia_fchown(vfs_handle_struct *handle,
1778                         files_struct *fsp,
1779                         uid_t uid,
1780                         gid_t gid)
1781 {
1782         struct catia_cache *cc = NULL;
1783         int ret;
1784
1785         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1786         if (ret != 0) {
1787                 return ret;
1788         }
1789
1790         ret = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
1791
1792         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1793
1794         return ret;
1795 }
1796
1797 static int catia_fchmod(vfs_handle_struct *handle,
1798                         files_struct *fsp,
1799                         mode_t mode)
1800 {
1801         struct catia_cache *cc = NULL;
1802         int ret;
1803
1804         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1805         if (ret != 0) {
1806                 return ret;
1807         }
1808
1809         ret = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1810
1811         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1812
1813         return ret;
1814 }
1815
1816 struct catia_pread_state {
1817         ssize_t ret;
1818         struct vfs_aio_state vfs_aio_state;
1819         struct files_struct *fsp;
1820         struct catia_cache *cc;
1821 };
1822
1823 static void catia_pread_done(struct tevent_req *subreq);
1824
1825 static struct tevent_req *catia_pread_send(struct vfs_handle_struct *handle,
1826                                            TALLOC_CTX *mem_ctx,
1827                                            struct tevent_context *ev,
1828                                            struct files_struct *fsp,
1829                                            void *data,
1830                                            size_t n,
1831                                            off_t offset)
1832 {
1833         struct tevent_req *req = NULL, *subreq = NULL;
1834         struct catia_pread_state *state = NULL;
1835         int ret;
1836
1837         req = tevent_req_create(mem_ctx, &state,
1838                                 struct catia_pread_state);
1839         if (req == NULL) {
1840                 return NULL;
1841         }
1842         state->fsp = fsp;
1843
1844         ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
1845         if (ret != 0) {
1846                 tevent_req_error(req, errno);
1847                 return tevent_req_post(req, ev);
1848         }
1849
1850         subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
1851                                          n, offset);
1852         if (tevent_req_nomem(subreq, req)) {
1853                 return tevent_req_post(req, ev);
1854         }
1855         tevent_req_set_callback(subreq, catia_pread_done, req);
1856
1857         return req;
1858 }
1859
1860 static void catia_pread_done(struct tevent_req *subreq)
1861 {
1862         struct tevent_req *req = tevent_req_callback_data(
1863                 subreq, struct tevent_req);
1864         struct catia_pread_state *state = tevent_req_data(
1865                 req, struct catia_pread_state);
1866
1867         state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
1868         TALLOC_FREE(subreq);
1869
1870         CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
1871
1872         tevent_req_done(req);
1873 }
1874
1875 static ssize_t catia_pread_recv(struct tevent_req *req,
1876                                 struct vfs_aio_state *vfs_aio_state)
1877 {
1878         struct catia_pread_state *state = tevent_req_data(
1879                 req, struct catia_pread_state);
1880
1881         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1882                 return -1;
1883         }
1884
1885         *vfs_aio_state = state->vfs_aio_state;
1886         return state->ret;
1887 }
1888
1889 struct catia_pwrite_state {
1890         ssize_t ret;
1891         struct vfs_aio_state vfs_aio_state;
1892         struct files_struct *fsp;
1893         struct catia_cache *cc;
1894 };
1895
1896 static void catia_pwrite_done(struct tevent_req *subreq);
1897
1898 static struct tevent_req *catia_pwrite_send(struct vfs_handle_struct *handle,
1899                                             TALLOC_CTX *mem_ctx,
1900                                             struct tevent_context *ev,
1901                                             struct files_struct *fsp,
1902                                             const void *data,
1903                                             size_t n,
1904                                             off_t offset)
1905 {
1906         struct tevent_req *req = NULL, *subreq = NULL;
1907         struct catia_pwrite_state *state = NULL;
1908         int ret;
1909
1910         req = tevent_req_create(mem_ctx, &state,
1911                                 struct catia_pwrite_state);
1912         if (req == NULL) {
1913                 return NULL;
1914         }
1915         state->fsp = fsp;
1916
1917         ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
1918         if (ret != 0) {
1919                 tevent_req_error(req, errno);
1920                 return tevent_req_post(req, ev);
1921         }
1922
1923         subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
1924                                           n, offset);
1925         if (tevent_req_nomem(subreq, req)) {
1926                 return tevent_req_post(req, ev);
1927         }
1928         tevent_req_set_callback(subreq, catia_pwrite_done, req);
1929
1930         return req;
1931 }
1932
1933 static void catia_pwrite_done(struct tevent_req *subreq)
1934 {
1935         struct tevent_req *req = tevent_req_callback_data(
1936                 subreq, struct tevent_req);
1937         struct catia_pwrite_state *state = tevent_req_data(
1938                 req, struct catia_pwrite_state);
1939
1940         state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
1941         TALLOC_FREE(subreq);
1942
1943         CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
1944
1945         tevent_req_done(req);
1946 }
1947
1948 static ssize_t catia_pwrite_recv(struct tevent_req *req,
1949                                 struct vfs_aio_state *vfs_aio_state)
1950 {
1951         struct catia_pwrite_state *state = tevent_req_data(
1952                 req, struct catia_pwrite_state);
1953
1954         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1955                 return -1;
1956         }
1957
1958         *vfs_aio_state = state->vfs_aio_state;
1959         return state->ret;
1960 }
1961
1962 static off_t catia_lseek(vfs_handle_struct *handle,
1963                          files_struct *fsp,
1964                          off_t offset,
1965                          int whence)
1966 {
1967         struct catia_cache *cc = NULL;
1968         ssize_t result;
1969         int ret;
1970
1971         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
1972         if (ret != 0) {
1973                 return -1;
1974         }
1975
1976         result = SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence);
1977
1978         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
1979
1980         return result;
1981 }
1982
1983 struct catia_fsync_state {
1984         int ret;
1985         struct vfs_aio_state vfs_aio_state;
1986         struct files_struct *fsp;
1987         struct catia_cache *cc;
1988 };
1989
1990 static void catia_fsync_done(struct tevent_req *subreq);
1991
1992 static struct tevent_req *catia_fsync_send(struct vfs_handle_struct *handle,
1993                                            TALLOC_CTX *mem_ctx,
1994                                            struct tevent_context *ev,
1995                                            struct files_struct *fsp)
1996 {
1997         struct tevent_req *req = NULL, *subreq = NULL;
1998         struct catia_fsync_state *state = NULL;
1999         int ret;
2000
2001         req = tevent_req_create(mem_ctx, &state,
2002                                 struct catia_fsync_state);
2003         if (req == NULL) {
2004                 return NULL;
2005         }
2006         state->fsp = fsp;
2007
2008         ret = CATIA_FETCH_FSP_PRE_NEXT(state, handle, fsp, &state->cc);
2009         if (ret != 0) {
2010                 tevent_req_error(req, errno);
2011                 return tevent_req_post(req, ev);
2012         }
2013
2014         subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
2015         if (tevent_req_nomem(subreq, req)) {
2016                 return tevent_req_post(req, ev);
2017         }
2018         tevent_req_set_callback(subreq, catia_fsync_done, req);
2019
2020         return req;
2021 }
2022
2023 static void catia_fsync_done(struct tevent_req *subreq)
2024 {
2025         struct tevent_req *req = tevent_req_callback_data(
2026                 subreq, struct tevent_req);
2027         struct catia_fsync_state *state = tevent_req_data(
2028                 req, struct catia_fsync_state);
2029
2030         state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
2031         TALLOC_FREE(subreq);
2032
2033         CATIA_FETCH_FSP_POST_NEXT(&state->cc, state->fsp);
2034
2035         tevent_req_done(req);
2036 }
2037
2038 static int catia_fsync_recv(struct tevent_req *req,
2039                             struct vfs_aio_state *vfs_aio_state)
2040 {
2041         struct catia_fsync_state *state = tevent_req_data(
2042                 req, struct catia_fsync_state);
2043
2044         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2045                 return -1;
2046         }
2047
2048         *vfs_aio_state = state->vfs_aio_state;
2049         return state->ret;
2050 }
2051
2052 static bool catia_lock(vfs_handle_struct *handle,
2053                        files_struct *fsp,
2054                        int op,
2055                        off_t offset,
2056                        off_t count,
2057                        int type)
2058 {
2059         struct catia_cache *cc = NULL;
2060         bool ok;
2061         int ret;
2062
2063         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2064         if (ret != 0) {
2065                 return false;
2066         }
2067
2068         ok = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
2069
2070         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2071
2072         return ok;
2073 }
2074
2075 static int catia_kernel_flock(struct vfs_handle_struct *handle,
2076                               struct files_struct *fsp,
2077                               uint32_t share_access,
2078                               uint32_t access_mask)
2079 {
2080         struct catia_cache *cc = NULL;
2081         int ret;
2082
2083         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2084         if (ret != 0) {
2085                 return -1;
2086         }
2087
2088         ret = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_access, access_mask);
2089
2090         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2091
2092         return ret;
2093 }
2094
2095 static int catia_linux_setlease(vfs_handle_struct *handle,
2096                                 files_struct *fsp,
2097                                 int leasetype)
2098 {
2099         struct catia_cache *cc = NULL;
2100         int ret;
2101
2102         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2103         if (ret != 0) {
2104                 return -1;
2105         }
2106
2107         ret = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
2108
2109         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2110
2111         return ret;
2112 }
2113
2114 static bool catia_getlock(vfs_handle_struct *handle,
2115                           files_struct *fsp,
2116                           off_t *poffset,
2117                           off_t *pcount,
2118                           int *ptype,
2119                           pid_t *ppid)
2120 {
2121         struct catia_cache *cc = NULL;
2122         int ret;
2123         bool ok;
2124
2125         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2126         if (ret != 0) {
2127                 return false;
2128         }
2129
2130         ok = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype, ppid);
2131
2132         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2133
2134         return ok;
2135 }
2136
2137 static bool catia_strict_lock_check(struct vfs_handle_struct *handle,
2138                                     struct files_struct *fsp,
2139                                     struct lock_struct *plock)
2140 {
2141         struct catia_cache *cc = NULL;
2142         int ret;
2143         bool ok;
2144
2145         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2146         if (ret != 0) {
2147                 return false;
2148         }
2149
2150         ok = SMB_VFS_NEXT_STRICT_LOCK_CHECK(handle, fsp, plock);
2151
2152         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2153
2154         return ok;
2155 }
2156
2157 static NTSTATUS catia_fsctl(struct vfs_handle_struct *handle,
2158                             struct files_struct *fsp,
2159                             TALLOC_CTX *ctx,
2160                             uint32_t function,
2161                             uint16_t req_flags,
2162                             const uint8_t *_in_data,
2163                             uint32_t in_len,
2164                             uint8_t **_out_data,
2165                             uint32_t max_out_len,
2166                             uint32_t *out_len)
2167 {
2168         NTSTATUS result;
2169         struct catia_cache *cc = NULL;
2170         int ret;
2171
2172         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2173         if (ret != 0) {
2174                 return map_nt_error_from_unix(errno);
2175         }
2176
2177         result = SMB_VFS_NEXT_FSCTL(handle,
2178                                 fsp,
2179                                 ctx,
2180                                 function,
2181                                 req_flags,
2182                                 _in_data,
2183                                 in_len,
2184                                 _out_data,
2185                                 max_out_len,
2186                                 out_len);
2187
2188         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2189
2190         return result;
2191 }
2192
2193 static NTSTATUS catia_fget_compression(vfs_handle_struct *handle,
2194                                       TALLOC_CTX *mem_ctx,
2195                                       struct files_struct *fsp,
2196                                       uint16_t *_compression_fmt)
2197 {
2198         NTSTATUS result;
2199         struct catia_cache *cc = NULL;
2200         int ret;
2201
2202         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2203         if (ret != 0) {
2204                 return map_nt_error_from_unix(errno);
2205         }
2206
2207         result = SMB_VFS_NEXT_FGET_COMPRESSION(handle,
2208                                         mem_ctx,
2209                                         fsp,
2210                                         _compression_fmt);
2211
2212         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2213
2214         return result;
2215 }
2216
2217 static NTSTATUS catia_set_compression(vfs_handle_struct *handle,
2218                                       TALLOC_CTX *mem_ctx,
2219                                       struct files_struct *fsp,
2220                                       uint16_t compression_fmt)
2221 {
2222         NTSTATUS result;
2223         struct catia_cache *cc = NULL;
2224         int ret;
2225
2226         ret = CATIA_FETCH_FSP_PRE_NEXT(talloc_tos(), handle, fsp, &cc);
2227         if (ret != 0) {
2228                 return map_nt_error_from_unix(errno);
2229         }
2230
2231         result = SMB_VFS_NEXT_SET_COMPRESSION(handle, mem_ctx, fsp,
2232                                               compression_fmt);
2233
2234         CATIA_FETCH_FSP_POST_NEXT(&cc, fsp);
2235
2236         return result;
2237 }
2238
2239 static NTSTATUS catia_readdir_attr(struct vfs_handle_struct *handle,
2240                                    const struct smb_filename *smb_fname_in,
2241                                    TALLOC_CTX *mem_ctx,
2242                                    struct readdir_attr_data **pattr_data)
2243 {
2244         struct smb_filename *smb_fname;
2245         char *fname = NULL;
2246         NTSTATUS status;
2247
2248         status = catia_string_replace_allocate(handle->conn,
2249                                                smb_fname_in->base_name,
2250                                                &fname,
2251                                                vfs_translate_to_unix);
2252         if (!NT_STATUS_IS_OK(status)) {
2253                 errno = map_errno_from_nt_status(status);
2254                 return status;
2255         }
2256
2257         smb_fname = synthetic_smb_fname(talloc_tos(),
2258                                         fname,
2259                                         NULL,
2260                                         &smb_fname_in->st,
2261                                         smb_fname_in->twrp,
2262                                         0);
2263
2264         status = SMB_VFS_NEXT_READDIR_ATTR(handle, smb_fname, mem_ctx, pattr_data);
2265
2266         TALLOC_FREE(smb_fname);
2267         TALLOC_FREE(fname);
2268         return status;
2269 }
2270
2271 static NTSTATUS catia_set_dos_attributes(struct vfs_handle_struct *handle,
2272                                          const struct smb_filename *smb_fname,
2273                                          uint32_t dosmode)
2274 {
2275         char *mapped_name = NULL;
2276         const char *path = smb_fname->base_name;
2277         struct smb_filename *mapped_smb_fname = NULL;
2278         NTSTATUS status;
2279
2280         status = catia_string_replace_allocate(handle->conn,
2281                                 path, &mapped_name, vfs_translate_to_unix);
2282         if (!NT_STATUS_IS_OK(status)) {
2283                 errno = map_errno_from_nt_status(status);
2284                 return status;
2285         }
2286         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
2287                                         mapped_name,
2288                                         NULL,
2289                                         &smb_fname->st,
2290                                         smb_fname->twrp,
2291                                         smb_fname->flags);
2292         if (mapped_smb_fname == NULL) {
2293                 TALLOC_FREE(mapped_name);
2294                 return NT_STATUS_NO_MEMORY;
2295         }
2296
2297         status = SMB_VFS_NEXT_SET_DOS_ATTRIBUTES(handle,
2298                                                  mapped_smb_fname,
2299                                                  dosmode);
2300         TALLOC_FREE(mapped_name);
2301         TALLOC_FREE(mapped_smb_fname);
2302
2303         return status;
2304 }
2305
2306 static NTSTATUS catia_create_dfs_pathat(struct vfs_handle_struct *handle,
2307                         struct files_struct *dirfsp,
2308                         const struct smb_filename *smb_fname,
2309                         const struct referral *reflist,
2310                         size_t referral_count)
2311 {
2312         char *mapped_name = NULL;
2313         const char *path = smb_fname->base_name;
2314         struct smb_filename *mapped_smb_fname = NULL;
2315         NTSTATUS status;
2316
2317         status = catia_string_replace_allocate(handle->conn,
2318                                         path,
2319                                         &mapped_name,
2320                                         vfs_translate_to_unix);
2321         if (!NT_STATUS_IS_OK(status)) {
2322                 errno = map_errno_from_nt_status(status);
2323                 return status;
2324         }
2325         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
2326                                         mapped_name,
2327                                         NULL,
2328                                         &smb_fname->st,
2329                                         smb_fname->twrp,
2330                                         smb_fname->flags);
2331         if (mapped_smb_fname == NULL) {
2332                 TALLOC_FREE(mapped_name);
2333                 return NT_STATUS_NO_MEMORY;
2334         }
2335
2336         status = SMB_VFS_NEXT_CREATE_DFS_PATHAT(handle,
2337                                         dirfsp,
2338                                         mapped_smb_fname,
2339                                         reflist,
2340                                         referral_count);
2341         TALLOC_FREE(mapped_name);
2342         TALLOC_FREE(mapped_smb_fname);
2343         return status;
2344 }
2345
2346 static NTSTATUS catia_read_dfs_pathat(struct vfs_handle_struct *handle,
2347                         TALLOC_CTX *mem_ctx,
2348                         struct files_struct *dirfsp,
2349                         struct smb_filename *smb_fname,
2350                         struct referral **ppreflist,
2351                         size_t *preferral_count)
2352 {
2353         char *mapped_name = NULL;
2354         const char *path = smb_fname->base_name;
2355         struct smb_filename *mapped_smb_fname = NULL;
2356         NTSTATUS status;
2357
2358         status = catia_string_replace_allocate(handle->conn,
2359                                         path,
2360                                         &mapped_name,
2361                                         vfs_translate_to_unix);
2362         if (!NT_STATUS_IS_OK(status)) {
2363                 errno = map_errno_from_nt_status(status);
2364                 return status;
2365         }
2366         mapped_smb_fname = synthetic_smb_fname(talloc_tos(),
2367                                         mapped_name,
2368                                         NULL,
2369                                         &smb_fname->st,
2370                                         smb_fname->twrp,
2371                                         smb_fname->flags);
2372         if (mapped_smb_fname == NULL) {
2373                 TALLOC_FREE(mapped_name);
2374                 return NT_STATUS_NO_MEMORY;
2375         }
2376
2377         status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
2378                                         mem_ctx,
2379                                         dirfsp,
2380                                         mapped_smb_fname,
2381                                         ppreflist,
2382                                         preferral_count);
2383         if (NT_STATUS_IS_OK(status)) {
2384                 /* Return any stat(2) info. */
2385                 smb_fname->st = mapped_smb_fname->st;
2386         }
2387
2388         TALLOC_FREE(mapped_name);
2389         TALLOC_FREE(mapped_smb_fname);
2390         return status;
2391 }
2392
2393 static struct vfs_fn_pointers vfs_catia_fns = {
2394         .connect_fn = catia_connect,
2395
2396         /* Directory operations */
2397         .mkdirat_fn = catia_mkdirat,
2398         .readdir_attr_fn = catia_readdir_attr,
2399
2400         /* File operations */
2401         .openat_fn = catia_openat,
2402         .pread_fn = catia_pread,
2403         .pread_send_fn = catia_pread_send,
2404         .pread_recv_fn = catia_pread_recv,
2405         .pwrite_fn = catia_pwrite,
2406         .pwrite_send_fn = catia_pwrite_send,
2407         .pwrite_recv_fn = catia_pwrite_recv,
2408         .lseek_fn = catia_lseek,
2409         .renameat_fn = catia_renameat,
2410         .fsync_send_fn = catia_fsync_send,
2411         .fsync_recv_fn = catia_fsync_recv,
2412         .stat_fn = catia_stat,
2413         .fstat_fn = catia_fstat,
2414         .lstat_fn = catia_lstat,
2415         .unlinkat_fn = catia_unlinkat,
2416         .chmod_fn = catia_chmod,
2417         .fchmod_fn = catia_fchmod,
2418         .fchown_fn = catia_fchown,
2419         .lchown_fn = catia_lchown,
2420         .chdir_fn = catia_chdir,
2421         .ntimes_fn = catia_ntimes,
2422         .ftruncate_fn = catia_ftruncate,
2423         .fallocate_fn = catia_fallocate,
2424         .lock_fn = catia_lock,
2425         .kernel_flock_fn = catia_kernel_flock,
2426         .linux_setlease_fn = catia_linux_setlease,
2427         .getlock_fn = catia_getlock,
2428         .realpath_fn = catia_realpath,
2429         .chflags_fn = catia_chflags,
2430         .streaminfo_fn = catia_streaminfo,
2431         .strict_lock_check_fn = catia_strict_lock_check,
2432         .translate_name_fn = catia_translate_name,
2433         .fsctl_fn = catia_fsctl,
2434         .get_dos_attributes_send_fn = vfs_not_implemented_get_dos_attributes_send,
2435         .get_dos_attributes_recv_fn = vfs_not_implemented_get_dos_attributes_recv,
2436         .set_dos_attributes_fn = catia_set_dos_attributes,
2437         .fset_dos_attributes_fn = catia_fset_dos_attributes,
2438         .fget_dos_attributes_fn = catia_fget_dos_attributes,
2439         .fget_compression_fn = catia_fget_compression,
2440         .set_compression_fn = catia_set_compression,
2441         .create_dfs_pathat_fn = catia_create_dfs_pathat,
2442         .read_dfs_pathat_fn = catia_read_dfs_pathat,
2443
2444         /* NT ACL operations. */
2445         .get_nt_acl_at_fn = catia_get_nt_acl_at,
2446         .fget_nt_acl_fn = catia_fget_nt_acl,
2447         .fset_nt_acl_fn = catia_fset_nt_acl,
2448
2449         /* POSIX ACL operations. */
2450         .sys_acl_get_file_fn = catia_sys_acl_get_file,
2451         .sys_acl_get_fd_fn = catia_sys_acl_get_fd,
2452         .sys_acl_blob_get_fd_fn = catia_sys_acl_blob_get_fd,
2453         .sys_acl_set_file_fn = catia_sys_acl_set_file,
2454         .sys_acl_set_fd_fn = catia_sys_acl_set_fd,
2455         .sys_acl_delete_def_file_fn = catia_sys_acl_delete_def_file,
2456
2457         /* EA operations. */
2458         .getxattr_fn = catia_getxattr,
2459         .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
2460         .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
2461         .listxattr_fn = catia_listxattr,
2462         .removexattr_fn = catia_removexattr,
2463         .setxattr_fn = catia_setxattr,
2464         .fgetxattr_fn = catia_fgetxattr,
2465         .flistxattr_fn = catia_flistxattr,
2466         .fremovexattr_fn = catia_fremovexattr,
2467         .fsetxattr_fn = catia_fsetxattr,
2468 };
2469
2470 static_decl_vfs;
2471 NTSTATUS vfs_catia_init(TALLOC_CTX *ctx)
2472 {
2473         NTSTATUS ret;
2474
2475         ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
2476                                 &vfs_catia_fns);
2477         if (!NT_STATUS_IS_OK(ret))
2478                 return ret;
2479
2480         vfs_catia_debug_level = debug_add_class("catia");
2481         if (vfs_catia_debug_level == -1) {
2482                 vfs_catia_debug_level = DBGC_VFS;
2483                 DEBUG(0, ("vfs_catia: Couldn't register custom debugging "
2484                           "class!\n"));
2485         } else {
2486                 DEBUG(10, ("vfs_catia: Debug class number of "
2487                            "'catia': %d\n", vfs_catia_debug_level));
2488         }
2489
2490         return ret;
2491
2492 }