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