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