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