s3:vfs_modules: Fix Coverity ID 946: OVERRUN_STATIC
[ira/wip.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  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, see <http://www.gnu.org/licenses/>.
26  */
27
28
29 #include "includes.h"
30
31 #define TO_UNIX    0
32 #define TO_WINDOWS 1
33
34 #define GLOBAL_SNUM     0xFFFFFFF
35 #define MAP_SIZE        0xFF
36 #define MAP_NUM         0x101 /* max unicode charval / MAP_SIZE */
37 #define T_OFFSET(_v_)   ((_v_ % MAP_SIZE))
38 #define T_START(_v_)    (((_v_ / MAP_SIZE) * MAP_SIZE))
39 #define T_PICK(_v_)     ((_v_ / MAP_SIZE))
40
41 struct char_mappings {
42         smb_ucs2_t entry[MAP_SIZE][2];
43 };
44
45 struct share_mapping_entry {
46         int snum;
47         struct share_mapping_entry *next;
48         struct char_mappings **mappings;
49 };
50
51 struct share_mapping_entry *srt_head = NULL;
52
53 static bool build_table(struct char_mappings **cmaps, int value)
54 {
55         int i;
56         int start = T_START(value);
57
58         (*cmaps) = (struct char_mappings *)
59                         TALLOC_ZERO(NULL, sizeof(struct char_mappings));
60
61         if (!*cmaps)
62                 return False;
63
64         for (i = 0; i < MAP_SIZE;i++) {
65                 (*cmaps)->entry[i][TO_UNIX] = start + i;
66                 (*cmaps)->entry[i][TO_WINDOWS] = start + i;
67         }
68
69         return True;
70 }
71
72 static void set_tables(struct char_mappings **cmaps,
73                        long unix_map,
74                        long windows_map)
75 {
76         int i;
77
78         /* set unix -> windows */
79         i = T_OFFSET(unix_map);
80         cmaps[T_PICK(unix_map)]->entry[i][TO_WINDOWS] = windows_map;
81
82         /* set windows -> unix */
83         i = T_OFFSET(windows_map);
84         cmaps[T_PICK(windows_map)]->entry[i][TO_UNIX] = unix_map;
85 }
86
87 static bool build_ranges(struct char_mappings **cmaps,
88                          long unix_map,
89                          long windows_map)
90 {
91
92         if (!cmaps[T_PICK(unix_map)]) {
93                 if (!build_table(&cmaps[T_PICK(unix_map)], unix_map))
94                         return False;
95         }
96
97         if (!cmaps[T_PICK(windows_map)]) {
98                 if (!build_table(&cmaps[T_PICK(windows_map)], windows_map))
99                         return False;
100         }
101
102         set_tables(cmaps, unix_map, windows_map);
103
104         return True;
105 }
106
107 struct share_mapping_entry *get_srt(connection_struct *conn,
108                                     struct share_mapping_entry **global)
109 {
110         struct share_mapping_entry *share;
111
112         for (share = srt_head; share != NULL; share = share->next) {
113                 if (share->snum == GLOBAL_SNUM)
114                         (*global) = share;
115
116                 if (share->snum == SNUM(conn))
117                         return share;
118         }
119
120         return share;
121 }
122
123 struct share_mapping_entry *add_srt(int snum, const char **mappings)
124 {
125
126         char *tmp;
127         fstring mapping;
128         int i;
129         long unix_map, windows_map;
130         struct share_mapping_entry *ret = NULL;
131
132         ret = (struct share_mapping_entry *)
133                 TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry) +
134                 (mappings ? (MAP_NUM * sizeof(struct char_mappings *)) : 0));
135
136         if (!ret)
137                 return ret;
138
139         ret->snum = snum;
140
141         if (mappings) {
142                 ret->mappings = (struct char_mappings**) ((unsigned char*) ret +
143                     sizeof(struct share_mapping_entry));
144                 memset(ret->mappings, 0,
145                     MAP_NUM * sizeof(struct char_mappings *));
146         } else {
147                 ret->mappings = NULL;
148                 return ret;
149         }
150
151         /*
152          * catia mappings are of the form :
153          * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
154          *
155          * multiple mappings are comma seperated in smb.conf
156          */
157         for (i=0;mappings[i];i++) {
158                 fstrcpy(mapping, mappings[i]);
159                 unix_map = strtol(mapping, &tmp, 16);
160                 if (unix_map == 0 && errno == EINVAL) {
161                         DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
162                         continue;
163                 }
164                 windows_map = strtol(++tmp, NULL, 16);
165                 if (windows_map == 0 && errno == EINVAL) {
166                         DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
167                         continue;
168                 }
169
170                 if (!build_ranges(ret->mappings, unix_map, windows_map)) {
171                         DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping));
172                         continue;
173                 }
174         }
175
176         ret->next = srt_head;
177         srt_head = ret;
178
179         return ret;
180 }
181
182 static bool init_mappings(connection_struct *conn,
183                           struct share_mapping_entry **selected_out)
184 {
185         const char **mappings = NULL;
186         struct share_mapping_entry *share_level = NULL;
187         struct share_mapping_entry *global = NULL;
188
189         /* check srt cache */
190         share_level = get_srt(conn, &global);
191         if (share_level) {
192                 *selected_out = share_level;
193                 return (share_level->mappings != NULL);
194         }
195
196         /* see if we have a global setting */
197         if (!global) {
198                 /* global setting */
199                 mappings = lp_parm_string_list(-1, "catia", "mappings", NULL);
200                 global = add_srt(GLOBAL_SNUM, mappings);
201         }
202
203         /* no global setting - what about share level ? */
204         mappings = lp_parm_string_list(SNUM(conn), "catia", "mappings", NULL);
205         share_level = add_srt(SNUM(conn), mappings);
206
207         if (share_level->mappings) {
208                 (*selected_out) = share_level;
209                 return True;
210         } else if (global->mappings) {
211                 share_level->mappings = global->mappings;
212                 (*selected_out) = share_level;
213                 return True;
214         }
215
216         return False;
217 }
218
219 static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
220                                               const char *name_in,
221                                               char **mapped_name,
222                                               int direction)
223 {
224         static smb_ucs2_t *tmpbuf = NULL;
225         smb_ucs2_t *ptr;
226         struct share_mapping_entry *selected;
227         struct char_mappings *map = NULL;
228         size_t converted_size;
229         TALLOC_CTX *ctx = talloc_tos();
230
231         if (!init_mappings(conn, &selected))
232                 return NT_STATUS_OK;
233
234         if ((push_ucs2_talloc(ctx, &tmpbuf, name_in,
235                               &converted_size)) == -1) {
236                 return map_nt_error_from_unix(errno);
237         }
238         ptr = tmpbuf;
239         for(;*ptr;ptr++) {
240                 if (*ptr == 0)
241                         break;
242                 map = selected->mappings[T_PICK((*ptr))];
243
244                 /* nothing to do */
245                 if (!map)
246                         continue;
247
248                 *ptr = map->entry[T_OFFSET((*ptr))][direction];
249         }
250
251         if ((pull_ucs2_talloc(ctx, mapped_name, tmpbuf,
252                               &converted_size)) == -1) {
253                 TALLOC_FREE(tmpbuf);
254                 return map_nt_error_from_unix(errno);
255         }
256         TALLOC_FREE(tmpbuf);
257         return NT_STATUS_OK;
258 }
259
260 static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle,
261                                      const char *fname,
262                                      const char *mask,
263                                      uint32 attr)
264 {
265         char *name_mapped = NULL;
266         NTSTATUS status;
267         SMB_STRUCT_DIR *ret;
268
269         status = catia_string_replace_allocate(handle->conn, fname,
270                                         &name_mapped, TO_UNIX);
271         if (!NT_STATUS_IS_OK(status)) {
272                 errno = map_errno_from_nt_status(status);
273                 return NULL;
274         }
275
276         ret = SMB_VFS_NEXT_OPENDIR(handle, name_mapped, mask, attr);
277         TALLOC_FREE(name_mapped);
278
279         return ret;
280 }
281
282 /*
283  * TRANSLATE_NAME call which converts the given name to
284  * "WINDOWS displayable" name
285  */
286 static NTSTATUS catia_translate_name(vfs_handle_struct *handle,
287                                      char **mapped_name)
288 {
289         char *name = NULL;
290         NTSTATUS ret;
291
292         /*
293          * Copy the supplied name and free the memory for mapped_name,
294          * already allocated by the caller.
295          * We will be allocating new memory for mapped_name in
296          * catia_string_replace_allocate
297          */
298         name = talloc_strdup(talloc_tos(), *mapped_name);
299         if (!name) {
300                 errno = ENOMEM;
301                 return NT_STATUS_NO_MEMORY;
302         }
303         TALLOC_FREE(*mapped_name);
304         ret = catia_string_replace_allocate(handle->conn, name,
305                         mapped_name, TO_WINDOWS);
306
307         TALLOC_FREE(name);
308         if (!NT_STATUS_IS_OK(ret)) {
309                 return ret;
310         }
311
312         ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name);
313
314         return ret;
315 }
316
317 static int catia_open(vfs_handle_struct *handle,
318                       struct smb_filename *smb_fname,
319                       files_struct *fsp,
320                       int flags,
321                       mode_t mode)
322 {
323         char *name_mapped = NULL;
324         char *tmp_base_name;
325         int ret;
326         NTSTATUS status;
327
328         tmp_base_name = smb_fname->base_name;
329         status = catia_string_replace_allocate(handle->conn,
330                                         smb_fname->base_name,
331                                         &name_mapped, TO_UNIX);
332         if (!NT_STATUS_IS_OK(status)) {
333                 errno = map_errno_from_nt_status(status);
334                 return -1;
335         }
336
337         smb_fname->base_name = name_mapped;
338         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
339         smb_fname->base_name = tmp_base_name;
340         TALLOC_FREE(name_mapped);
341
342         return ret;
343 }
344
345 /* @internal - Isilon create file support */
346 static NTSTATUS catia_createfile(vfs_handle_struct *handle,
347                                  struct smb_request *req,
348                                  uint16_t root_dir_fid,
349                                  struct smb_filename *smb_fname,
350                                  uint32_t access_mask,
351                                  uint32_t share_access,
352                                  uint32_t create_disposition,
353                                  uint32_t create_options,
354                                  uint32_t file_attributes,
355                                  uint32_t oplock_request,
356                                  uint64_t allocation_size,
357                                  struct security_descriptor *sd,
358                                  struct ea_list *ea_list,
359                                  files_struct **result,
360                                  int *pinfo)
361 {
362         char *name_mapped = NULL;
363         char *tmp_base_name;
364         NTSTATUS ret;
365
366         ret = catia_string_replace_allocate(handle->conn, smb_fname->base_name,
367                                 &name_mapped, TO_UNIX);
368         if (!NT_STATUS_IS_OK(ret)) {
369                 errno = map_errno_from_nt_status(ret);
370                 return ret;
371         }
372
373         tmp_base_name = smb_fname->base_name;
374         DEBUG(5, ("catia_createfile converted %s->%s (orginally %s)\n",
375                                 tmp_base_name, name_mapped, tmp_base_name));
376         smb_fname->base_name = name_mapped;
377         ret = SMB_VFS_NEXT_CREATE_FILE(handle, req, root_dir_fid,
378                                 smb_fname, access_mask, share_access,
379                                 create_disposition, create_options,
380                                 file_attributes, oplock_request,
381                                 allocation_size, sd, ea_list,
382                                 result, pinfo);
383
384         smb_fname->base_name = tmp_base_name;
385         TALLOC_FREE(name_mapped);
386
387         return ret;
388 }
389
390 static int catia_rename(vfs_handle_struct *handle,
391                         const struct smb_filename *smb_fname_src,
392                         const struct smb_filename *smb_fname_dst)
393 {
394         TALLOC_CTX *ctx = talloc_tos();
395         struct smb_filename *smb_fname_src_tmp = NULL;
396         struct smb_filename *smb_fname_dst_tmp = NULL;
397         NTSTATUS status;
398         int ret = -1;
399
400         status = catia_string_replace_allocate(handle->conn,
401                                 smb_fname_src->base_name,
402                                 &(smb_fname_src_tmp->base_name), TO_UNIX);
403         if (!NT_STATUS_IS_OK(status)) {
404                 errno = map_errno_from_nt_status(status);
405                 return -1;
406         }
407
408         status = catia_string_replace_allocate(handle->conn,
409                                 smb_fname_dst->base_name,
410                                 &(smb_fname_dst_tmp->base_name), TO_UNIX);
411         if (!NT_STATUS_IS_OK(status)) {
412                 errno = map_errno_from_nt_status(status);
413                 return -1;
414         }
415
416         /* Setup temporary smb_filename structs. */
417         status = copy_smb_filename(ctx, smb_fname_src, &smb_fname_src_tmp);
418
419         if (!NT_STATUS_IS_OK(status)) {
420                 errno = map_errno_from_nt_status(status);
421                 goto out;
422         }
423
424         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
425         if (!NT_STATUS_IS_OK(status)) {
426                 errno = map_errno_from_nt_status(status);
427                 goto out;
428         }
429
430         DEBUG(10, ("converted old name: %s\n",
431                                 smb_fname_str_dbg(smb_fname_src_tmp)));
432         DEBUG(10, ("converted new name: %s\n",
433                                 smb_fname_str_dbg(smb_fname_dst_tmp)));
434
435         ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
436                         smb_fname_dst_tmp);
437 out:
438         TALLOC_FREE(smb_fname_src_tmp);
439         TALLOC_FREE(smb_fname_dst_tmp);
440         return ret;
441 }
442
443 static int catia_stat(vfs_handle_struct *handle,
444                       struct smb_filename *smb_fname)
445 {
446         char *name = NULL;
447         char *tmp_base_name;
448         int ret;
449         NTSTATUS status;
450
451         status = catia_string_replace_allocate(handle->conn,
452                                 smb_fname->base_name,
453                                 &name, TO_UNIX);
454         if (!NT_STATUS_IS_OK(status)) {
455                 errno = map_errno_from_nt_status(status);
456                 return -1;
457         }
458
459         tmp_base_name = smb_fname->base_name;
460         smb_fname->base_name = name;
461
462         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
463         smb_fname->base_name = tmp_base_name;
464
465         TALLOC_FREE(name);
466         return ret;
467 }
468
469 static int catia_lstat(vfs_handle_struct *handle,
470                        struct smb_filename *smb_fname)
471 {
472         char *name = NULL;
473         char *tmp_base_name;
474         int ret;
475         NTSTATUS status;
476
477         status = catia_string_replace_allocate(handle->conn,
478                                 smb_fname->base_name,
479                                 &name, TO_UNIX);
480         if (!NT_STATUS_IS_OK(status)) {
481                 errno = map_errno_from_nt_status(status);
482                 return -1;
483         }
484
485         tmp_base_name = smb_fname->base_name;
486         smb_fname->base_name = name;
487
488         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
489         smb_fname->base_name = tmp_base_name;
490         TALLOC_FREE(name);
491
492         return ret;
493 }
494
495 static int catia_unlink(vfs_handle_struct *handle,
496                         const struct smb_filename *smb_fname)
497 {
498         struct smb_filename *smb_fname_tmp = NULL;
499         char *name = NULL;
500         NTSTATUS status;
501         int ret;
502
503         status = catia_string_replace_allocate(handle->conn,
504                                         smb_fname->base_name,
505                                         &name, TO_UNIX);
506         if (!NT_STATUS_IS_OK(status)) {
507                 errno = map_errno_from_nt_status(status);
508                 return -1;
509         }
510
511         /* Setup temporary smb_filename structs. */
512         status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
513         if (!NT_STATUS_IS_OK(status)) {
514                 errno = map_errno_from_nt_status(status);
515                 return -1;
516         }
517
518         smb_fname_tmp->base_name = name;
519         ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
520         TALLOC_FREE(smb_fname_tmp);
521         TALLOC_FREE(name);
522
523         return ret;
524 }
525
526 static int catia_chown(vfs_handle_struct *handle,
527                        const char *path,
528                        uid_t uid,
529                        gid_t gid)
530 {
531         char *name = NULL;
532         NTSTATUS status;
533         int ret;
534
535         status = catia_string_replace_allocate(handle->conn, path,
536                                         &name, TO_UNIX);
537         if (!NT_STATUS_IS_OK(status)) {
538                 errno = map_errno_from_nt_status(status);
539                 return -1;
540         }
541
542         ret = SMB_VFS_NEXT_CHOWN(handle, name, uid, gid);
543         TALLOC_FREE(name);
544
545         return ret;
546 }
547
548 static int catia_lchown(vfs_handle_struct *handle,
549                         const char *path,
550                         uid_t uid,
551                         gid_t gid)
552 {
553         char *name = NULL;
554         NTSTATUS status;
555         int ret;
556
557         status = catia_string_replace_allocate(handle->conn, path,
558                                         &name, TO_UNIX);
559         if (!NT_STATUS_IS_OK(status)) {
560                 errno = map_errno_from_nt_status(status);
561                 return -1;
562         }
563
564         ret = SMB_VFS_NEXT_LCHOWN(handle, name, uid, gid);
565         TALLOC_FREE(name);
566
567         return ret;
568 }
569
570 static int catia_rmdir(vfs_handle_struct *handle,
571                        const char *path)
572 {
573         char *name = NULL;
574         NTSTATUS status;
575         int ret;
576
577         status = catia_string_replace_allocate(handle->conn, path,
578                                         &name, TO_UNIX);
579         if (!NT_STATUS_IS_OK(status)) {
580                 errno = map_errno_from_nt_status(status);
581                 return -1;
582         }
583
584         ret = SMB_VFS_NEXT_RMDIR(handle, name);
585         TALLOC_FREE(name);
586
587         return ret;
588 }
589
590 static int catia_mkdir(vfs_handle_struct *handle,
591                        const char *path,
592                        mode_t mode)
593 {
594         char *name = NULL;
595         NTSTATUS status;
596         int ret;
597
598         status = catia_string_replace_allocate(handle->conn, path,
599                                          &name, TO_UNIX);
600         if (!NT_STATUS_IS_OK(status)) {
601                 errno = map_errno_from_nt_status(status);
602                 return -1;
603         }
604
605         ret = SMB_VFS_NEXT_MKDIR(handle, name, mode);
606         TALLOC_FREE(name);
607
608         return ret;
609 }
610
611 static int catia_chdir(vfs_handle_struct *handle,
612                        const char *path)
613 {
614         char *name = NULL;
615         NTSTATUS status;
616         int ret;
617
618         status = catia_string_replace_allocate(handle->conn, path,
619                                         &name, TO_UNIX);
620         if (!NT_STATUS_IS_OK(status)) {
621                 errno = map_errno_from_nt_status(status);
622                 return -1;
623         }
624
625         ret = SMB_VFS_NEXT_CHDIR(handle, name);
626         TALLOC_FREE(name);
627
628         return ret;
629 }
630
631 static int catia_ntimes(vfs_handle_struct *handle,
632                         const struct smb_filename *smb_fname,
633                         struct smb_file_time *ft)
634 {
635         struct smb_filename *smb_fname_tmp = NULL;
636         char *name = NULL;
637         NTSTATUS status;
638         int ret;
639
640         status = catia_string_replace_allocate(handle->conn,
641                                 smb_fname->base_name,
642                                 &name, TO_UNIX);
643         if (!NT_STATUS_IS_OK(status)) {
644                 errno = map_errno_from_nt_status(status);
645                 return -1;
646         }
647
648         status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
649         if (!NT_STATUS_IS_OK(status)) {
650                 errno = map_errno_from_nt_status(status);
651                 return -1;
652         }
653
654         smb_fname_tmp->base_name = name;
655         ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
656         TALLOC_FREE(smb_fname_tmp);
657
658         return ret;
659 }
660
661 static char *
662 catia_realpath(vfs_handle_struct *handle, const char *path,
663                char *resolved_path)
664 {
665         char *mapped_name = NULL;
666         NTSTATUS status;
667         char *ret = NULL;
668
669         status = catia_string_replace_allocate(handle->conn, path,
670                                         &mapped_name, TO_UNIX);
671         if (!NT_STATUS_IS_OK(status)) {
672                 errno = map_errno_from_nt_status(status);
673                 return NULL;
674         }
675
676         ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name, resolved_path);
677         TALLOC_FREE(mapped_name);
678
679         return ret;
680 }
681
682 static int catia_chflags(struct vfs_handle_struct *handle,
683                          const char *path, unsigned int flags)
684 {
685         char *mapped_name = NULL;
686         NTSTATUS status;
687         int ret;
688
689         status = catia_string_replace_allocate(handle->conn, path,
690                                         &mapped_name, TO_UNIX);
691         if (!NT_STATUS_IS_OK(status)) {
692                 errno = map_errno_from_nt_status(status);
693                 return -1;
694         }
695
696         ret = SMB_VFS_NEXT_CHFLAGS(handle, mapped_name, flags);
697         TALLOC_FREE(mapped_name);
698
699         return ret;
700 }
701
702 static NTSTATUS
703 catia_streaminfo(struct vfs_handle_struct *handle,
704                  struct files_struct *fsp,
705                  const char *path,
706                  TALLOC_CTX *mem_ctx,
707                  unsigned int *num_streams,
708                  struct stream_struct **streams)
709 {
710         char *mapped_name = NULL;
711         NTSTATUS status;
712
713         status = catia_string_replace_allocate(handle->conn, path,
714                                         &mapped_name, TO_UNIX);
715         if (!NT_STATUS_IS_OK(status)) {
716                 errno = map_errno_from_nt_status(status);
717                 return status;
718         }
719
720         status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, mapped_name,
721                                          mem_ctx, num_streams,streams);
722         TALLOC_FREE(mapped_name);
723
724         return status;
725 }
726
727 static NTSTATUS
728 catia_get_nt_acl(struct vfs_handle_struct *handle,
729                  const char *path,
730                  uint32 security_info,
731                  struct security_descriptor **ppdesc)
732 {
733         char *mapped_name = NULL;
734         NTSTATUS status;
735
736         status = catia_string_replace_allocate(handle->conn,
737                                 path, &mapped_name, TO_UNIX);
738         if (!NT_STATUS_IS_OK(status)) {
739                 errno = map_errno_from_nt_status(status);
740                 return status;
741         }
742         status = SMB_VFS_NEXT_GET_NT_ACL(handle, mapped_name,
743                                          security_info, ppdesc);
744         TALLOC_FREE(mapped_name);
745
746         return status;
747 }
748
749 static int
750 catia_chmod_acl(vfs_handle_struct *handle,
751                 const char *path,
752                 mode_t mode)
753 {
754         char *mapped_name = NULL;
755         NTSTATUS status;
756         int ret;
757
758         status = catia_string_replace_allocate(handle->conn,
759                                 path, &mapped_name, TO_UNIX);
760         if (!NT_STATUS_IS_OK(status)) {
761                 errno = map_errno_from_nt_status(status);
762                 return -1;
763         }
764
765         ret = SMB_VFS_NEXT_CHMOD_ACL(handle, mapped_name, mode);
766         TALLOC_FREE(mapped_name);
767         return ret;
768 }
769
770 static SMB_ACL_T
771 catia_sys_acl_get_file(vfs_handle_struct *handle,
772                        const char *path,
773                        SMB_ACL_TYPE_T type)
774 {
775         char *mapped_name = NULL;
776         NTSTATUS status;
777         SMB_ACL_T ret;
778
779         status = catia_string_replace_allocate(handle->conn,
780                                 path, &mapped_name, TO_UNIX);
781         if (!NT_STATUS_IS_OK(status)) {
782                 errno = map_errno_from_nt_status(status);
783                 return NULL;
784         }
785
786         ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, mapped_name, type);
787         TALLOC_FREE(mapped_name);
788
789         return ret;
790 }
791
792 static int
793 catia_sys_acl_set_file(vfs_handle_struct *handle,
794                        const char *path,
795                        SMB_ACL_TYPE_T type,
796                        SMB_ACL_T theacl)
797 {
798         char *mapped_name = NULL;
799         NTSTATUS status;
800         int ret;
801
802         status = catia_string_replace_allocate(handle->conn,
803                                 path, &mapped_name, TO_UNIX);
804         if (!NT_STATUS_IS_OK(status)) {
805                 errno = map_errno_from_nt_status(status);
806                 return -1;
807         }
808
809         ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, mapped_name, type, theacl);
810         TALLOC_FREE(mapped_name);
811
812         return ret;
813 }
814
815 static int
816 catia_sys_acl_delete_def_file(vfs_handle_struct *handle,
817                               const char *path)
818 {
819         char *mapped_name = NULL;
820         NTSTATUS status;
821         int ret;
822
823         status = catia_string_replace_allocate(handle->conn,
824                                 path, &mapped_name, TO_UNIX);
825         if (!NT_STATUS_IS_OK(status)) {
826                 errno = map_errno_from_nt_status(status);
827                 return -1;
828         }
829
830         ret = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, mapped_name);
831         TALLOC_FREE(mapped_name);
832
833         return ret;
834 }
835
836 static ssize_t
837 catia_getxattr(vfs_handle_struct *handle, const char *path,
838                const char *name, void *value, size_t size)
839 {
840         char *mapped_name = NULL;
841         NTSTATUS status;
842         ssize_t ret;
843
844         status = catia_string_replace_allocate(handle->conn,
845                                 name, &mapped_name, TO_UNIX);
846         if (!NT_STATUS_IS_OK(status)) {
847                 errno = map_errno_from_nt_status(status);
848                 return -1;
849         }
850
851
852         ret = SMB_VFS_NEXT_GETXATTR(handle, path, mapped_name, value, size);
853         TALLOC_FREE(mapped_name);
854
855         return ret;
856 }
857
858 static ssize_t
859 catia_lgetxattr(vfs_handle_struct *handle, const char *path,
860                 const char *name, void *value, size_t size)
861 {
862         char *mapped_name = NULL;
863         NTSTATUS status;
864         ssize_t ret;
865
866         status = catia_string_replace_allocate(handle->conn,
867                                 name, &mapped_name, TO_UNIX);
868         if (!NT_STATUS_IS_OK(status)) {
869                 errno = map_errno_from_nt_status(status);
870                 return -1;
871         }
872
873
874         ret = SMB_VFS_NEXT_LGETXATTR(handle, path, mapped_name, value, size);
875         TALLOC_FREE(mapped_name);
876
877         return ret;
878 }
879
880 static ssize_t
881 catia_listxattr(vfs_handle_struct *handle, const char *path,
882                 char *list, size_t size)
883 {
884         char *mapped_name = NULL;
885         NTSTATUS status;
886         ssize_t ret;
887
888         status = catia_string_replace_allocate(handle->conn,
889                                 path, &mapped_name, TO_UNIX);
890         if (!NT_STATUS_IS_OK(status)) {
891                 errno = map_errno_from_nt_status(status);
892                 return -1;
893         }
894
895
896         ret = SMB_VFS_NEXT_LISTXATTR(handle, mapped_name, list, size);
897         TALLOC_FREE(mapped_name);
898
899         return ret;
900 }
901
902 static ssize_t
903 catia_llistxattr(vfs_handle_struct *handle, const char *path,
904                  char *list, size_t size)
905 {
906         char *mapped_name = NULL;
907         NTSTATUS status;
908         ssize_t ret;
909
910         status = catia_string_replace_allocate(handle->conn,
911                                 path, &mapped_name, TO_UNIX);
912         if (!NT_STATUS_IS_OK(status)) {
913                 errno = map_errno_from_nt_status(status);
914                 return -1;
915         }
916
917
918         ret = SMB_VFS_NEXT_LLISTXATTR(handle, mapped_name, list, size);
919         TALLOC_FREE(mapped_name);
920
921         return ret;
922 }
923
924 static int
925 catia_removexattr(vfs_handle_struct *handle, const char *path,
926                   const char *name)
927 {
928         char *mapped_name = NULL;
929         NTSTATUS status;
930         ssize_t ret;
931
932         status = catia_string_replace_allocate(handle->conn,
933                                 name, &mapped_name, TO_UNIX);
934         if (!NT_STATUS_IS_OK(status)) {
935                 errno = map_errno_from_nt_status(status);
936                 return -1;
937         }
938
939
940         ret = SMB_VFS_NEXT_REMOVEXATTR(handle, path, mapped_name);
941         TALLOC_FREE(mapped_name);
942
943         return ret;
944 }
945
946 static int
947 catia_lremovexattr(vfs_handle_struct *handle, const char *path,
948                    const char *name)
949 {
950         char *mapped_name = NULL;
951         NTSTATUS status;
952         ssize_t ret;
953
954         status = catia_string_replace_allocate(handle->conn,
955                                 name, &mapped_name, TO_UNIX);
956         if (!NT_STATUS_IS_OK(status)) {
957                 errno = map_errno_from_nt_status(status);
958                 return -1;
959         }
960
961
962         ret = SMB_VFS_NEXT_LREMOVEXATTR(handle, path, mapped_name);
963         TALLOC_FREE(mapped_name);
964
965         return ret;
966 }
967
968 static int
969 catia_setxattr(vfs_handle_struct *handle, const char *path,
970                const char *name, const void *value, size_t size,
971                int flags)
972 {
973         char *mapped_name = NULL;
974         NTSTATUS status;
975         ssize_t ret;
976
977         status = catia_string_replace_allocate(handle->conn,
978                                 name, &mapped_name, TO_UNIX);
979         if (!NT_STATUS_IS_OK(status)) {
980                 errno = map_errno_from_nt_status(status);
981                 return -1;
982         }
983
984
985         ret = SMB_VFS_NEXT_SETXATTR(handle, path, mapped_name, value, size, flags);
986         TALLOC_FREE(mapped_name);
987
988         return ret;
989 }
990
991 static int
992 catia_lsetxattr(vfs_handle_struct *handle, const char *path,
993                 const char *name, const void *value, size_t size,
994                 int flags)
995 {
996         char *mapped_name = NULL;
997         NTSTATUS status;
998         ssize_t ret;
999
1000         status = catia_string_replace_allocate(handle->conn,
1001                                 name, &mapped_name, TO_UNIX);
1002         if (!NT_STATUS_IS_OK(status)) {
1003                 errno = map_errno_from_nt_status(status);
1004                 return -1;
1005         }
1006
1007
1008         ret = SMB_VFS_NEXT_LSETXATTR(handle, path, mapped_name, value, size, flags);
1009         TALLOC_FREE(mapped_name);
1010
1011         return ret;
1012 }
1013
1014 static struct vfs_fn_pointers vfs_catia_fns = {
1015         .mkdir = catia_mkdir,
1016         .rmdir = catia_rmdir,
1017         .opendir = catia_opendir,
1018         .open = catia_open,
1019         .create_file = catia_createfile,
1020         .rename = catia_rename,
1021         .stat = catia_stat,
1022         .lstat = catia_lstat,
1023         .unlink = catia_unlink,
1024         .chown = catia_chown,
1025         .lchown = catia_lchown,
1026         .chdir = catia_chdir,
1027         .ntimes = catia_ntimes,
1028         .realpath = catia_realpath,
1029         .chflags = catia_chflags,
1030         .streaminfo = catia_streaminfo,
1031         .translate_name = catia_translate_name,
1032         .get_nt_acl = catia_get_nt_acl,
1033         .chmod_acl = catia_chmod_acl,
1034         .sys_acl_get_file = catia_sys_acl_get_file,
1035         .sys_acl_set_file = catia_sys_acl_set_file,
1036         .sys_acl_delete_def_file = catia_sys_acl_delete_def_file,
1037         .getxattr = catia_getxattr,
1038         .lgetxattr = catia_lgetxattr,
1039         .listxattr = catia_listxattr,
1040         .llistxattr = catia_llistxattr,
1041         .removexattr = catia_removexattr,
1042         .lremovexattr = catia_lremovexattr,
1043         .setxattr = catia_setxattr,
1044         .lsetxattr = catia_lsetxattr,
1045 };
1046
1047 NTSTATUS vfs_catia_init(void)
1048 {
1049         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
1050                                 &vfs_catia_fns);
1051 }