Convert all uint8/16/32 to _t in all modules.
[nivanova/samba-autobuild/.git] / source3 / modules / vfs_catia.c
1 /*
2  * Catia VFS module
3  *
4  * Implement a fixed mapping of forbidden NT characters in filenames that are
5  * used a lot by the CAD package Catia.
6  *
7  * Yes, this a BAD BAD UGLY INCOMPLETE hack, but it helps quite some people
8  * out there. Catia V4 on AIX uses characters like "<*$ a *lot*, all forbidden
9  * under Windows...
10  *
11  * Copyright (C) Volker Lendecke, 2005
12  * Copyright (C) Aravind Srinivasan, 2009
13  * Copyright (C) Guenter Kukkukk, 2013
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
33 static int vfs_catia_debug_level = DBGC_VFS;
34
35 #undef DBGC_CLASS
36 #define DBGC_CLASS vfs_catia_debug_level
37
38 #define GLOBAL_SNUM     0xFFFFFFF
39 #define MAP_SIZE        0xFF
40 #define MAP_NUM         0x101 /* max unicode charval / MAP_SIZE */
41 #define T_OFFSET(_v_)   ((_v_ % MAP_SIZE))
42 #define T_START(_v_)    (((_v_ / MAP_SIZE) * MAP_SIZE))
43 #define T_PICK(_v_)     ((_v_ / MAP_SIZE))
44
45 struct char_mappings {
46         smb_ucs2_t entry[MAP_SIZE][2];
47 };
48
49 struct share_mapping_entry {
50         int snum;
51         struct share_mapping_entry *next;
52         struct char_mappings **mappings;
53 };
54
55 struct share_mapping_entry *srt_head = NULL;
56
57 static bool build_table(struct char_mappings **cmaps, int value)
58 {
59         int i;
60         int start = T_START(value);
61
62         (*cmaps) = talloc_zero(NULL, struct char_mappings);
63
64         if (!*cmaps)
65                 return False;
66
67         for (i = 0; i < MAP_SIZE;i++) {
68                 (*cmaps)->entry[i][vfs_translate_to_unix] = start + i;
69                 (*cmaps)->entry[i][vfs_translate_to_windows] = start + i;
70         }
71
72         return True;
73 }
74
75 static void set_tables(struct char_mappings **cmaps,
76                        long unix_map,
77                        long windows_map)
78 {
79         int i;
80
81         /* set unix -> windows */
82         i = T_OFFSET(unix_map);
83         cmaps[T_PICK(unix_map)]->entry[i][vfs_translate_to_windows] = windows_map;
84
85         /* set windows -> unix */
86         i = T_OFFSET(windows_map);
87         cmaps[T_PICK(windows_map)]->entry[i][vfs_translate_to_unix] = unix_map;
88 }
89
90 static bool build_ranges(struct char_mappings **cmaps,
91                          long unix_map,
92                          long windows_map)
93 {
94
95         if (!cmaps[T_PICK(unix_map)]) {
96                 if (!build_table(&cmaps[T_PICK(unix_map)], unix_map))
97                         return False;
98         }
99
100         if (!cmaps[T_PICK(windows_map)]) {
101                 if (!build_table(&cmaps[T_PICK(windows_map)], windows_map))
102                         return False;
103         }
104
105         set_tables(cmaps, unix_map, windows_map);
106
107         return True;
108 }
109
110 static struct share_mapping_entry *get_srt(connection_struct *conn,
111                                            struct share_mapping_entry **global)
112 {
113         struct share_mapping_entry *share;
114
115         for (share = srt_head; share != NULL; share = share->next) {
116                 if (share->snum == GLOBAL_SNUM)
117                         (*global) = share;
118
119                 if (share->snum == SNUM(conn))
120                         return share;
121         }
122
123         return share;
124 }
125
126 static struct share_mapping_entry *add_srt(int snum, const char **mappings)
127 {
128
129         char *tmp;
130         fstring mapping;
131         int i;
132         long unix_map, windows_map;
133         struct share_mapping_entry *ret = NULL;
134
135         ret = (struct share_mapping_entry *)
136                 TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry) +
137                 (mappings ? (MAP_NUM * sizeof(struct char_mappings *)) : 0));
138
139         if (!ret)
140                 return ret;
141
142         ret->snum = snum;
143
144         if (mappings) {
145                 ret->mappings = (struct char_mappings**) ((unsigned char*) ret +
146                     sizeof(struct share_mapping_entry));
147                 memset(ret->mappings, 0,
148                     MAP_NUM * sizeof(struct char_mappings *));
149         } else {
150                 ret->mappings = NULL;
151                 return ret;
152         }
153
154         /*
155          * catia mappings are of the form :
156          * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
157          *
158          * multiple mappings are comma separated in smb.conf
159          */
160         for (i=0;mappings[i];i++) {
161                 fstrcpy(mapping, mappings[i]);
162                 unix_map = strtol(mapping, &tmp, 16);
163                 if (unix_map == 0 && errno == EINVAL) {
164                         DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
165                         continue;
166                 }
167                 windows_map = strtol(++tmp, NULL, 16);
168                 if (windows_map == 0 && errno == EINVAL) {
169                         DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
170                         continue;
171                 }
172
173                 if (!build_ranges(ret->mappings, unix_map, windows_map)) {
174                         DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping));
175                         continue;
176                 }
177         }
178
179         ret->next = srt_head;
180         srt_head = ret;
181
182         return ret;
183 }
184
185 static bool init_mappings(connection_struct *conn,
186                           struct share_mapping_entry **selected_out)
187 {
188         const char **mappings = NULL;
189         struct share_mapping_entry *share_level = NULL;
190         struct share_mapping_entry *global = NULL;
191
192         /* check srt cache */
193         share_level = get_srt(conn, &global);
194         if (share_level) {
195                 *selected_out = share_level;
196                 return (share_level->mappings != NULL);
197         }
198
199         /* see if we have a global setting */
200         if (!global) {
201                 /* global setting */
202                 mappings = lp_parm_string_list(-1, "catia", "mappings", NULL);
203                 global = add_srt(GLOBAL_SNUM, mappings);
204         }
205
206         /* no global setting - what about share level ? */
207         mappings = lp_parm_string_list(SNUM(conn), "catia", "mappings", NULL);
208         share_level = add_srt(SNUM(conn), mappings);
209
210         if (share_level->mappings) {
211                 (*selected_out) = share_level;
212                 return True;
213         }
214         if (global->mappings) {
215                 share_level->mappings = global->mappings;
216                 (*selected_out) = share_level;
217                 return True;
218         }
219
220         return False;
221 }
222
223 static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
224                                               const char *name_in,
225                                               char **mapped_name,
226                                         enum vfs_translate_direction direction)
227 {
228         static smb_ucs2_t *tmpbuf = NULL;
229         smb_ucs2_t *ptr;
230         struct share_mapping_entry *selected;
231         struct char_mappings *map = NULL;
232         size_t converted_size;
233         TALLOC_CTX *ctx = talloc_tos();
234
235         if (!init_mappings(conn, &selected)) {
236                 /* No mappings found. Just use the old name */
237                 *mapped_name = talloc_strdup(NULL, name_in);
238                 if (!*mapped_name) {
239                         errno = ENOMEM;
240                         return NT_STATUS_NO_MEMORY;
241                 }
242                 return NT_STATUS_OK;
243         }
244
245         if ((push_ucs2_talloc(ctx, &tmpbuf, name_in,
246                               &converted_size)) == false) {
247                 return map_nt_error_from_unix(errno);
248         }
249         ptr = tmpbuf;
250         for(;*ptr;ptr++) {
251                 if (*ptr == 0)
252                         break;
253                 map = selected->mappings[T_PICK((*ptr))];
254
255                 /* nothing to do */
256                 if (!map)
257                         continue;
258
259                 *ptr = map->entry[T_OFFSET((*ptr))][direction];
260         }
261
262         if ((pull_ucs2_talloc(ctx, mapped_name, tmpbuf,
263                               &converted_size)) == false) {
264                 TALLOC_FREE(tmpbuf);
265                 return map_nt_error_from_unix(errno);
266         }
267         TALLOC_FREE(tmpbuf);
268         return NT_STATUS_OK;
269 }
270
271 static DIR *catia_opendir(vfs_handle_struct *handle,
272                                      const char *fname,
273                                      const char *mask,
274                                      uint32_t attr)
275 {
276         char *name_mapped = NULL;
277         NTSTATUS status;
278         DIR *ret;
279
280         status = catia_string_replace_allocate(handle->conn, fname,
281                                         &name_mapped, vfs_translate_to_unix);
282         if (!NT_STATUS_IS_OK(status)) {
283                 errno = map_errno_from_nt_status(status);
284                 return NULL;
285         }
286
287         ret = SMB_VFS_NEXT_OPENDIR(handle, name_mapped, mask, attr);
288         TALLOC_FREE(name_mapped);
289
290         return ret;
291 }
292
293 /*
294  * TRANSLATE_NAME call which converts the given name to
295  * "WINDOWS displayable" name
296  */
297 static NTSTATUS catia_translate_name(struct vfs_handle_struct *handle,
298                                      const char *orig_name,
299                                      enum vfs_translate_direction direction,
300                                      TALLOC_CTX *mem_ctx,
301                                      char **pmapped_name)
302 {
303         char *name = NULL;
304         char *mapped_name;
305         NTSTATUS status, ret;
306
307         /*
308          * Copy the supplied name and free the memory for mapped_name,
309          * already allocated by the caller.
310          * We will be allocating new memory for mapped_name in
311          * catia_string_replace_allocate
312          */
313         name = talloc_strdup(talloc_tos(), orig_name);
314         if (!name) {
315                 errno = ENOMEM;
316                 return NT_STATUS_NO_MEMORY;
317         }
318         status = catia_string_replace_allocate(handle->conn, name,
319                         &mapped_name, direction);
320
321         TALLOC_FREE(name);
322         if (!NT_STATUS_IS_OK(status)) {
323                 return status;
324         }
325
326         ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction,
327                                           mem_ctx, pmapped_name);
328
329         if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
330                 *pmapped_name = talloc_move(mem_ctx, &mapped_name);
331                 /* we need to return the former translation result here */
332                 ret = status;
333         } else {
334                 TALLOC_FREE(mapped_name);
335         }
336
337         return ret;
338 }
339
340 static int catia_open(vfs_handle_struct *handle,
341                       struct smb_filename *smb_fname,
342                       files_struct *fsp,
343                       int flags,
344                       mode_t mode)
345 {
346         char *name_mapped = NULL;
347         char *tmp_base_name;
348         int ret;
349         NTSTATUS status;
350
351         tmp_base_name = smb_fname->base_name;
352         status = catia_string_replace_allocate(handle->conn,
353                                         smb_fname->base_name,
354                                         &name_mapped, vfs_translate_to_unix);
355         if (!NT_STATUS_IS_OK(status)) {
356                 errno = map_errno_from_nt_status(status);
357                 return -1;
358         }
359
360         smb_fname->base_name = name_mapped;
361         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
362         smb_fname->base_name = tmp_base_name;
363         TALLOC_FREE(name_mapped);
364
365         return ret;
366 }
367
368 static int catia_rename(vfs_handle_struct *handle,
369                         const struct smb_filename *smb_fname_src,
370                         const struct smb_filename *smb_fname_dst)
371 {
372         TALLOC_CTX *ctx = talloc_tos();
373         struct smb_filename *smb_fname_src_tmp = NULL;
374         struct smb_filename *smb_fname_dst_tmp = NULL;
375         char *src_name_mapped = NULL;
376         char *dst_name_mapped = NULL;
377         NTSTATUS status;
378         int ret = -1;
379
380         status = catia_string_replace_allocate(handle->conn,
381                                 smb_fname_src->base_name,
382                                 &src_name_mapped, vfs_translate_to_unix);
383         if (!NT_STATUS_IS_OK(status)) {
384                 errno = map_errno_from_nt_status(status);
385                 return -1;
386         }
387
388         status = catia_string_replace_allocate(handle->conn,
389                                 smb_fname_dst->base_name,
390                                 &dst_name_mapped, vfs_translate_to_unix);
391         if (!NT_STATUS_IS_OK(status)) {
392                 errno = map_errno_from_nt_status(status);
393                 return -1;
394         }
395
396         /* Setup temporary smb_filename structs. */
397         smb_fname_src_tmp = cp_smb_filename(ctx, smb_fname_src);
398         if (smb_fname_src_tmp == NULL) {
399                 errno = ENOMEM;
400                 goto out;
401         }
402
403         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
404         if (smb_fname_dst_tmp == NULL) {
405                 errno = ENOMEM;
406                 goto out;
407         }
408
409         smb_fname_src_tmp->base_name = src_name_mapped;
410         smb_fname_dst_tmp->base_name = dst_name_mapped; 
411         DEBUG(10, ("converted old name: %s\n",
412                                 smb_fname_str_dbg(smb_fname_src_tmp)));
413         DEBUG(10, ("converted new name: %s\n",
414                                 smb_fname_str_dbg(smb_fname_dst_tmp)));
415
416         ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
417                         smb_fname_dst_tmp);
418 out:
419         TALLOC_FREE(src_name_mapped);
420         TALLOC_FREE(dst_name_mapped);
421         TALLOC_FREE(smb_fname_src_tmp);
422         TALLOC_FREE(smb_fname_dst_tmp);
423         return ret;
424 }
425
426 static int catia_stat(vfs_handle_struct *handle,
427                       struct smb_filename *smb_fname)
428 {
429         char *name = NULL;
430         char *tmp_base_name;
431         int ret;
432         NTSTATUS status;
433
434         status = catia_string_replace_allocate(handle->conn,
435                                 smb_fname->base_name,
436                                 &name, vfs_translate_to_unix);
437         if (!NT_STATUS_IS_OK(status)) {
438                 errno = map_errno_from_nt_status(status);
439                 return -1;
440         }
441
442         tmp_base_name = smb_fname->base_name;
443         smb_fname->base_name = name;
444
445         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
446         smb_fname->base_name = tmp_base_name;
447
448         TALLOC_FREE(name);
449         return ret;
450 }
451
452 static int catia_lstat(vfs_handle_struct *handle,
453                        struct smb_filename *smb_fname)
454 {
455         char *name = NULL;
456         char *tmp_base_name;
457         int ret;
458         NTSTATUS status;
459
460         status = catia_string_replace_allocate(handle->conn,
461                                 smb_fname->base_name,
462                                 &name, vfs_translate_to_unix);
463         if (!NT_STATUS_IS_OK(status)) {
464                 errno = map_errno_from_nt_status(status);
465                 return -1;
466         }
467
468         tmp_base_name = smb_fname->base_name;
469         smb_fname->base_name = name;
470
471         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
472         smb_fname->base_name = tmp_base_name;
473         TALLOC_FREE(name);
474
475         return ret;
476 }
477
478 static int catia_unlink(vfs_handle_struct *handle,
479                         const struct smb_filename *smb_fname)
480 {
481         struct smb_filename *smb_fname_tmp = NULL;
482         char *name = NULL;
483         NTSTATUS status;
484         int ret;
485
486         status = catia_string_replace_allocate(handle->conn,
487                                         smb_fname->base_name,
488                                         &name, vfs_translate_to_unix);
489         if (!NT_STATUS_IS_OK(status)) {
490                 errno = map_errno_from_nt_status(status);
491                 return -1;
492         }
493
494         /* Setup temporary smb_filename structs. */
495         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
496         if (smb_fname_tmp == NULL) {
497                 errno = ENOMEM;
498                 return -1;
499         }
500
501         smb_fname_tmp->base_name = name;
502         ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
503         TALLOC_FREE(smb_fname_tmp);
504         TALLOC_FREE(name);
505
506         return ret;
507 }
508
509 static int catia_chown(vfs_handle_struct *handle,
510                        const char *path,
511                        uid_t uid,
512                        gid_t gid)
513 {
514         char *name = NULL;
515         NTSTATUS status;
516         int ret;
517
518         status = catia_string_replace_allocate(handle->conn, path,
519                                         &name, vfs_translate_to_unix);
520         if (!NT_STATUS_IS_OK(status)) {
521                 errno = map_errno_from_nt_status(status);
522                 return -1;
523         }
524
525         ret = SMB_VFS_NEXT_CHOWN(handle, name, uid, gid);
526         TALLOC_FREE(name);
527
528         return ret;
529 }
530
531 static int catia_lchown(vfs_handle_struct *handle,
532                         const char *path,
533                         uid_t uid,
534                         gid_t gid)
535 {
536         char *name = NULL;
537         NTSTATUS status;
538         int ret;
539
540         status = catia_string_replace_allocate(handle->conn, path,
541                                         &name, vfs_translate_to_unix);
542         if (!NT_STATUS_IS_OK(status)) {
543                 errno = map_errno_from_nt_status(status);
544                 return -1;
545         }
546
547         ret = SMB_VFS_NEXT_LCHOWN(handle, name, uid, gid);
548         TALLOC_FREE(name);
549
550         return ret;
551 }
552
553 static int catia_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
554 {
555         char *name = NULL;
556         NTSTATUS status;
557         int ret;
558
559         status = catia_string_replace_allocate(handle->conn, path,
560                                         &name, vfs_translate_to_unix);
561         if (!NT_STATUS_IS_OK(status)) {
562                 errno = map_errno_from_nt_status(status);
563                 return -1;
564         }
565
566         ret = SMB_VFS_NEXT_CHMOD(handle, name, mode);
567         TALLOC_FREE(name);
568
569         return ret;
570 }
571
572 static int catia_rmdir(vfs_handle_struct *handle,
573                        const char *path)
574 {
575         char *name = NULL;
576         NTSTATUS status;
577         int ret;
578
579         status = catia_string_replace_allocate(handle->conn, path,
580                                         &name, vfs_translate_to_unix);
581         if (!NT_STATUS_IS_OK(status)) {
582                 errno = map_errno_from_nt_status(status);
583                 return -1;
584         }
585
586         ret = SMB_VFS_NEXT_RMDIR(handle, name);
587         TALLOC_FREE(name);
588
589         return ret;
590 }
591
592 static int catia_mkdir(vfs_handle_struct *handle,
593                        const char *path,
594                        mode_t mode)
595 {
596         char *name = NULL;
597         NTSTATUS status;
598         int ret;
599
600         status = catia_string_replace_allocate(handle->conn, path,
601                                          &name, vfs_translate_to_unix);
602         if (!NT_STATUS_IS_OK(status)) {
603                 errno = map_errno_from_nt_status(status);
604                 return -1;
605         }
606
607         ret = SMB_VFS_NEXT_MKDIR(handle, name, mode);
608         TALLOC_FREE(name);
609
610         return ret;
611 }
612
613 static int catia_chdir(vfs_handle_struct *handle,
614                        const char *path)
615 {
616         char *name = NULL;
617         NTSTATUS status;
618         int ret;
619
620         status = catia_string_replace_allocate(handle->conn, path,
621                                         &name, vfs_translate_to_unix);
622         if (!NT_STATUS_IS_OK(status)) {
623                 errno = map_errno_from_nt_status(status);
624                 return -1;
625         }
626
627         ret = SMB_VFS_NEXT_CHDIR(handle, name);
628         TALLOC_FREE(name);
629
630         return ret;
631 }
632
633 static int catia_ntimes(vfs_handle_struct *handle,
634                         const struct smb_filename *smb_fname,
635                         struct smb_file_time *ft)
636 {
637         struct smb_filename *smb_fname_tmp = NULL;
638         char *name = NULL;
639         NTSTATUS status;
640         int ret;
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         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
651         if (smb_fname_tmp == NULL) {
652                 errno = ENOMEM;
653                 return -1;
654         }
655
656         smb_fname_tmp->base_name = name;
657         ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
658         TALLOC_FREE(name);
659         TALLOC_FREE(smb_fname_tmp);
660
661         return ret;
662 }
663
664 static char *
665 catia_realpath(vfs_handle_struct *handle, const char *path)
666 {
667         char *mapped_name = NULL;
668         NTSTATUS status;
669         char *ret = NULL;
670
671         status = catia_string_replace_allocate(handle->conn, path,
672                                         &mapped_name, vfs_translate_to_unix);
673         if (!NT_STATUS_IS_OK(status)) {
674                 errno = map_errno_from_nt_status(status);
675                 return NULL;
676         }
677
678         ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name);
679         TALLOC_FREE(mapped_name);
680
681         return ret;
682 }
683
684 static int catia_chflags(struct vfs_handle_struct *handle,
685                          const char *path, unsigned int flags)
686 {
687         char *mapped_name = NULL;
688         NTSTATUS status;
689         int ret;
690
691         status = catia_string_replace_allocate(handle->conn, path,
692                                         &mapped_name, vfs_translate_to_unix);
693         if (!NT_STATUS_IS_OK(status)) {
694                 errno = map_errno_from_nt_status(status);
695                 return -1;
696         }
697
698         ret = SMB_VFS_NEXT_CHFLAGS(handle, mapped_name, flags);
699         TALLOC_FREE(mapped_name);
700
701         return ret;
702 }
703
704 static NTSTATUS
705 catia_streaminfo(struct vfs_handle_struct *handle,
706                  struct files_struct *fsp,
707                  const char *path,
708                  TALLOC_CTX *mem_ctx,
709                  unsigned int *num_streams,
710                  struct stream_struct **streams)
711 {
712         char *mapped_name = NULL;
713         NTSTATUS status;
714
715         status = catia_string_replace_allocate(handle->conn, path,
716                                         &mapped_name, vfs_translate_to_unix);
717         if (!NT_STATUS_IS_OK(status)) {
718                 errno = map_errno_from_nt_status(status);
719                 return status;
720         }
721
722         status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, mapped_name,
723                                          mem_ctx, num_streams,streams);
724         TALLOC_FREE(mapped_name);
725
726         return status;
727 }
728
729 static NTSTATUS
730 catia_get_nt_acl(struct vfs_handle_struct *handle,
731                  const char *path,
732                  uint32_t security_info,
733                  TALLOC_CTX *mem_ctx,
734                  struct security_descriptor **ppdesc)
735 {
736         char *mapped_name = NULL;
737         NTSTATUS status;
738
739         status = catia_string_replace_allocate(handle->conn,
740                                 path, &mapped_name, vfs_translate_to_unix);
741         if (!NT_STATUS_IS_OK(status)) {
742                 errno = map_errno_from_nt_status(status);
743                 return status;
744         }
745         status = SMB_VFS_NEXT_GET_NT_ACL(handle, mapped_name,
746                                          security_info, mem_ctx, ppdesc);
747         TALLOC_FREE(mapped_name);
748
749         return status;
750 }
751
752 static int
753 catia_chmod_acl(vfs_handle_struct *handle,
754                 const char *path,
755                 mode_t mode)
756 {
757         char *mapped_name = NULL;
758         NTSTATUS status;
759         int ret;
760
761         status = catia_string_replace_allocate(handle->conn,
762                                 path, &mapped_name, vfs_translate_to_unix);
763         if (!NT_STATUS_IS_OK(status)) {
764                 errno = map_errno_from_nt_status(status);
765                 return -1;
766         }
767
768         ret = SMB_VFS_NEXT_CHMOD_ACL(handle, mapped_name, mode);
769         TALLOC_FREE(mapped_name);
770         return ret;
771 }
772
773 static SMB_ACL_T
774 catia_sys_acl_get_file(vfs_handle_struct *handle,
775                        const char *path,
776                        SMB_ACL_TYPE_T type,
777                        TALLOC_CTX *mem_ctx)
778 {
779         char *mapped_name = NULL;
780         NTSTATUS status;
781         SMB_ACL_T ret;
782
783         status = catia_string_replace_allocate(handle->conn,
784                                 path, &mapped_name, vfs_translate_to_unix);
785         if (!NT_STATUS_IS_OK(status)) {
786                 errno = map_errno_from_nt_status(status);
787                 return NULL;
788         }
789
790         ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, mapped_name, type, mem_ctx);
791         TALLOC_FREE(mapped_name);
792
793         return ret;
794 }
795
796 static int
797 catia_sys_acl_set_file(vfs_handle_struct *handle,
798                        const char *path,
799                        SMB_ACL_TYPE_T type,
800                        SMB_ACL_T theacl)
801 {
802         char *mapped_name = NULL;
803         NTSTATUS status;
804         int ret;
805
806         status = catia_string_replace_allocate(handle->conn,
807                                 path, &mapped_name, vfs_translate_to_unix);
808         if (!NT_STATUS_IS_OK(status)) {
809                 errno = map_errno_from_nt_status(status);
810                 return -1;
811         }
812
813         ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, mapped_name, type, theacl);
814         TALLOC_FREE(mapped_name);
815
816         return ret;
817 }
818
819 static int
820 catia_sys_acl_delete_def_file(vfs_handle_struct *handle,
821                               const char *path)
822 {
823         char *mapped_name = NULL;
824         NTSTATUS status;
825         int ret;
826
827         status = catia_string_replace_allocate(handle->conn,
828                                 path, &mapped_name, vfs_translate_to_unix);
829         if (!NT_STATUS_IS_OK(status)) {
830                 errno = map_errno_from_nt_status(status);
831                 return -1;
832         }
833
834         ret = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, mapped_name);
835         TALLOC_FREE(mapped_name);
836
837         return ret;
838 }
839
840 static ssize_t
841 catia_getxattr(vfs_handle_struct *handle, const char *path,
842                const char *name, void *value, size_t size)
843 {
844         char *mapped_name = NULL;
845         NTSTATUS status;
846         ssize_t ret;
847
848         status = catia_string_replace_allocate(handle->conn,
849                                 name, &mapped_name, vfs_translate_to_unix);
850         if (!NT_STATUS_IS_OK(status)) {
851                 errno = map_errno_from_nt_status(status);
852                 return -1;
853         }
854
855
856         ret = SMB_VFS_NEXT_GETXATTR(handle, path, mapped_name, value, size);
857         TALLOC_FREE(mapped_name);
858
859         return ret;
860 }
861
862 static ssize_t
863 catia_listxattr(vfs_handle_struct *handle, const char *path,
864                 char *list, size_t size)
865 {
866         char *mapped_name = NULL;
867         NTSTATUS status;
868         ssize_t ret;
869
870         status = catia_string_replace_allocate(handle->conn,
871                                 path, &mapped_name, vfs_translate_to_unix);
872         if (!NT_STATUS_IS_OK(status)) {
873                 errno = map_errno_from_nt_status(status);
874                 return -1;
875         }
876
877
878         ret = SMB_VFS_NEXT_LISTXATTR(handle, mapped_name, list, size);
879         TALLOC_FREE(mapped_name);
880
881         return ret;
882 }
883
884 static int
885 catia_removexattr(vfs_handle_struct *handle, const char *path,
886                   const char *name)
887 {
888         char *mapped_name = NULL;
889         NTSTATUS status;
890         ssize_t ret;
891
892         status = catia_string_replace_allocate(handle->conn,
893                                 name, &mapped_name, vfs_translate_to_unix);
894         if (!NT_STATUS_IS_OK(status)) {
895                 errno = map_errno_from_nt_status(status);
896                 return -1;
897         }
898
899
900         ret = SMB_VFS_NEXT_REMOVEXATTR(handle, path, mapped_name);
901         TALLOC_FREE(mapped_name);
902
903         return ret;
904 }
905
906 static int
907 catia_setxattr(vfs_handle_struct *handle, const char *path,
908                const char *name, const void *value, size_t size,
909                int flags)
910 {
911         char *mapped_name = NULL;
912         NTSTATUS status;
913         ssize_t ret;
914
915         status = catia_string_replace_allocate(handle->conn,
916                                 name, &mapped_name, vfs_translate_to_unix);
917         if (!NT_STATUS_IS_OK(status)) {
918                 errno = map_errno_from_nt_status(status);
919                 return -1;
920         }
921
922
923         ret = SMB_VFS_NEXT_SETXATTR(handle, path, mapped_name, value, size, flags);
924         TALLOC_FREE(mapped_name);
925
926         return ret;
927 }
928
929 static struct vfs_fn_pointers vfs_catia_fns = {
930         .mkdir_fn = catia_mkdir,
931         .rmdir_fn = catia_rmdir,
932         .opendir_fn = catia_opendir,
933         .open_fn = catia_open,
934         .rename_fn = catia_rename,
935         .stat_fn = catia_stat,
936         .lstat_fn = catia_lstat,
937         .unlink_fn = catia_unlink,
938         .chown_fn = catia_chown,
939         .lchown_fn = catia_lchown,
940         .chmod_fn = catia_chmod,
941         .chdir_fn = catia_chdir,
942         .ntimes_fn = catia_ntimes,
943         .realpath_fn = catia_realpath,
944         .chflags_fn = catia_chflags,
945         .streaminfo_fn = catia_streaminfo,
946         .translate_name_fn = catia_translate_name,
947         .get_nt_acl_fn = catia_get_nt_acl,
948         .chmod_acl_fn = catia_chmod_acl,
949         .sys_acl_get_file_fn = catia_sys_acl_get_file,
950         .sys_acl_set_file_fn = catia_sys_acl_set_file,
951         .sys_acl_delete_def_file_fn = catia_sys_acl_delete_def_file,
952         .getxattr_fn = catia_getxattr,
953         .listxattr_fn = catia_listxattr,
954         .removexattr_fn = catia_removexattr,
955         .setxattr_fn = catia_setxattr,
956 };
957
958 NTSTATUS vfs_catia_init(void)
959 {
960         NTSTATUS ret;
961
962         ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
963                                 &vfs_catia_fns);
964         if (!NT_STATUS_IS_OK(ret))
965                 return ret;
966
967         vfs_catia_debug_level = debug_add_class("catia");
968         if (vfs_catia_debug_level == -1) {
969                 vfs_catia_debug_level = DBGC_VFS;
970                 DEBUG(0, ("vfs_catia: Couldn't register custom debugging "
971                           "class!\n"));
972         } else {
973                 DEBUG(10, ("vfs_catia: Debug class number of "
974                            "'catia': %d\n", vfs_catia_debug_level));
975         }
976
977         return ret;
978
979 }