vfs_catia: add debug class for that module
[Samba/bjacke.git] / source3 / modules / vfs_catia.c
blob3140df97f9a5ac67a312dbd519cd118ac956d1c0
1 /*
2 * Catia VFS module
4 * Implement a fixed mapping of forbidden NT characters in filenames that are
5 * used a lot by the CAD package Catia.
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...
11 * Copyright (C) Volker Lendecke, 2005
12 * Copyright (C) Aravind Srinivasan, 2009
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.
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.
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/>.
29 #include "includes.h"
30 #include "smbd/smbd.h"
32 static int vfs_catia_debug_level = DBGC_VFS;
34 #undef DBGC_CLASS
35 #define DBGC_CLASS vfs_catia_debug_level
37 #define GLOBAL_SNUM 0xFFFFFFF
38 #define MAP_SIZE 0xFF
39 #define MAP_NUM 0x101 /* max unicode charval / MAP_SIZE */
40 #define T_OFFSET(_v_) ((_v_ % MAP_SIZE))
41 #define T_START(_v_) (((_v_ / MAP_SIZE) * MAP_SIZE))
42 #define T_PICK(_v_) ((_v_ / MAP_SIZE))
44 struct char_mappings {
45 smb_ucs2_t entry[MAP_SIZE][2];
48 struct share_mapping_entry {
49 int snum;
50 struct share_mapping_entry *next;
51 struct char_mappings **mappings;
54 struct share_mapping_entry *srt_head = NULL;
56 static bool build_table(struct char_mappings **cmaps, int value)
58 int i;
59 int start = T_START(value);
61 (*cmaps) = talloc_zero(NULL, struct char_mappings);
63 if (!*cmaps)
64 return False;
66 for (i = 0; i < MAP_SIZE;i++) {
67 (*cmaps)->entry[i][vfs_translate_to_unix] = start + i;
68 (*cmaps)->entry[i][vfs_translate_to_windows] = start + i;
71 return True;
74 static void set_tables(struct char_mappings **cmaps,
75 long unix_map,
76 long windows_map)
78 int i;
80 /* set unix -> windows */
81 i = T_OFFSET(unix_map);
82 cmaps[T_PICK(unix_map)]->entry[i][vfs_translate_to_windows] = windows_map;
84 /* set windows -> unix */
85 i = T_OFFSET(windows_map);
86 cmaps[T_PICK(windows_map)]->entry[i][vfs_translate_to_unix] = unix_map;
89 static bool build_ranges(struct char_mappings **cmaps,
90 long unix_map,
91 long windows_map)
94 if (!cmaps[T_PICK(unix_map)]) {
95 if (!build_table(&cmaps[T_PICK(unix_map)], unix_map))
96 return False;
99 if (!cmaps[T_PICK(windows_map)]) {
100 if (!build_table(&cmaps[T_PICK(windows_map)], windows_map))
101 return False;
104 set_tables(cmaps, unix_map, windows_map);
106 return True;
109 static struct share_mapping_entry *get_srt(connection_struct *conn,
110 struct share_mapping_entry **global)
112 struct share_mapping_entry *share;
114 for (share = srt_head; share != NULL; share = share->next) {
115 if (share->snum == GLOBAL_SNUM)
116 (*global) = share;
118 if (share->snum == SNUM(conn))
119 return share;
122 return share;
125 static struct share_mapping_entry *add_srt(int snum, const char **mappings)
128 char *tmp;
129 fstring mapping;
130 int i;
131 long unix_map, windows_map;
132 struct share_mapping_entry *ret = NULL;
134 ret = (struct share_mapping_entry *)
135 TALLOC_ZERO(NULL, sizeof(struct share_mapping_entry) +
136 (mappings ? (MAP_NUM * sizeof(struct char_mappings *)) : 0));
138 if (!ret)
139 return ret;
141 ret->snum = snum;
143 if (mappings) {
144 ret->mappings = (struct char_mappings**) ((unsigned char*) ret +
145 sizeof(struct share_mapping_entry));
146 memset(ret->mappings, 0,
147 MAP_NUM * sizeof(struct char_mappings *));
148 } else {
149 ret->mappings = NULL;
150 return ret;
154 * catia mappings are of the form :
155 * UNIX char (in 0xnn hex) : WINDOWS char (in 0xnn hex)
157 * multiple mappings are comma seperated in smb.conf
159 for (i=0;mappings[i];i++) {
160 fstrcpy(mapping, mappings[i]);
161 unix_map = strtol(mapping, &tmp, 16);
162 if (unix_map == 0 && errno == EINVAL) {
163 DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
164 continue;
166 windows_map = strtol(++tmp, NULL, 16);
167 if (windows_map == 0 && errno == EINVAL) {
168 DEBUG(0, ("INVALID CATIA MAPPINGS - %s\n", mapping));
169 continue;
172 if (!build_ranges(ret->mappings, unix_map, windows_map)) {
173 DEBUG(0, ("TABLE ERROR - CATIA MAPPINGS - %s\n", mapping));
174 continue;
178 ret->next = srt_head;
179 srt_head = ret;
181 return ret;
184 static bool init_mappings(connection_struct *conn,
185 struct share_mapping_entry **selected_out)
187 const char **mappings = NULL;
188 struct share_mapping_entry *share_level = NULL;
189 struct share_mapping_entry *global = NULL;
191 /* check srt cache */
192 share_level = get_srt(conn, &global);
193 if (share_level) {
194 *selected_out = share_level;
195 return (share_level->mappings != NULL);
198 /* see if we have a global setting */
199 if (!global) {
200 /* global setting */
201 mappings = lp_parm_string_list(-1, "catia", "mappings", NULL);
202 global = add_srt(GLOBAL_SNUM, mappings);
205 /* no global setting - what about share level ? */
206 mappings = lp_parm_string_list(SNUM(conn), "catia", "mappings", NULL);
207 share_level = add_srt(SNUM(conn), mappings);
209 if (share_level->mappings) {
210 (*selected_out) = share_level;
211 return True;
212 } else if (global->mappings) {
213 share_level->mappings = global->mappings;
214 (*selected_out) = share_level;
215 return True;
218 return False;
221 static NTSTATUS catia_string_replace_allocate(connection_struct *conn,
222 const char *name_in,
223 char **mapped_name,
224 int direction)
226 static smb_ucs2_t *tmpbuf = NULL;
227 smb_ucs2_t *ptr;
228 struct share_mapping_entry *selected;
229 struct char_mappings *map = NULL;
230 size_t converted_size;
231 TALLOC_CTX *ctx = talloc_tos();
233 if (!init_mappings(conn, &selected)) {
234 /* No mappings found. Just use the old name */
235 *mapped_name = talloc_strdup(NULL, name_in);
236 if (!*mapped_name) {
237 errno = ENOMEM;
238 return NT_STATUS_NO_MEMORY;
240 return NT_STATUS_OK;
243 if ((push_ucs2_talloc(ctx, &tmpbuf, name_in,
244 &converted_size)) == false) {
245 return map_nt_error_from_unix(errno);
247 ptr = tmpbuf;
248 for(;*ptr;ptr++) {
249 if (*ptr == 0)
250 break;
251 map = selected->mappings[T_PICK((*ptr))];
253 /* nothing to do */
254 if (!map)
255 continue;
257 *ptr = map->entry[T_OFFSET((*ptr))][direction];
260 if ((pull_ucs2_talloc(ctx, mapped_name, tmpbuf,
261 &converted_size)) == false) {
262 TALLOC_FREE(tmpbuf);
263 return map_nt_error_from_unix(errno);
265 TALLOC_FREE(tmpbuf);
266 return NT_STATUS_OK;
269 static DIR *catia_opendir(vfs_handle_struct *handle,
270 const char *fname,
271 const char *mask,
272 uint32 attr)
274 char *name_mapped = NULL;
275 NTSTATUS status;
276 DIR *ret;
278 status = catia_string_replace_allocate(handle->conn, fname,
279 &name_mapped, vfs_translate_to_unix);
280 if (!NT_STATUS_IS_OK(status)) {
281 errno = map_errno_from_nt_status(status);
282 return NULL;
285 ret = SMB_VFS_NEXT_OPENDIR(handle, name_mapped, mask, attr);
286 TALLOC_FREE(name_mapped);
288 return ret;
292 * TRANSLATE_NAME call which converts the given name to
293 * "WINDOWS displayable" name
295 static NTSTATUS catia_translate_name(struct vfs_handle_struct *handle,
296 const char *orig_name,
297 enum vfs_translate_direction direction,
298 TALLOC_CTX *mem_ctx,
299 char **pmapped_name)
301 char *name = NULL;
302 char *mapped_name;
303 NTSTATUS ret;
306 * Copy the supplied name and free the memory for mapped_name,
307 * already allocated by the caller.
308 * We will be allocating new memory for mapped_name in
309 * catia_string_replace_allocate
311 name = talloc_strdup(talloc_tos(), orig_name);
312 if (!name) {
313 errno = ENOMEM;
314 return NT_STATUS_NO_MEMORY;
316 ret = catia_string_replace_allocate(handle->conn, name,
317 &mapped_name, direction);
319 TALLOC_FREE(name);
320 if (!NT_STATUS_IS_OK(ret)) {
321 return ret;
324 ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction,
325 mem_ctx, pmapped_name);
327 if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
328 *pmapped_name = talloc_move(mem_ctx, &mapped_name);
329 } else {
330 TALLOC_FREE(mapped_name);
333 return ret;
336 static int catia_open(vfs_handle_struct *handle,
337 struct smb_filename *smb_fname,
338 files_struct *fsp,
339 int flags,
340 mode_t mode)
342 char *name_mapped = NULL;
343 char *tmp_base_name;
344 int ret;
345 NTSTATUS status;
347 tmp_base_name = smb_fname->base_name;
348 status = catia_string_replace_allocate(handle->conn,
349 smb_fname->base_name,
350 &name_mapped, vfs_translate_to_unix);
351 if (!NT_STATUS_IS_OK(status)) {
352 errno = map_errno_from_nt_status(status);
353 return -1;
356 smb_fname->base_name = name_mapped;
357 ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
358 smb_fname->base_name = tmp_base_name;
359 TALLOC_FREE(name_mapped);
361 return ret;
364 static int catia_rename(vfs_handle_struct *handle,
365 const struct smb_filename *smb_fname_src,
366 const struct smb_filename *smb_fname_dst)
368 TALLOC_CTX *ctx = talloc_tos();
369 struct smb_filename *smb_fname_src_tmp = NULL;
370 struct smb_filename *smb_fname_dst_tmp = NULL;
371 char *src_name_mapped = NULL;
372 char *dst_name_mapped = NULL;
373 NTSTATUS status;
374 int ret = -1;
376 status = catia_string_replace_allocate(handle->conn,
377 smb_fname_src->base_name,
378 &src_name_mapped, vfs_translate_to_unix);
379 if (!NT_STATUS_IS_OK(status)) {
380 errno = map_errno_from_nt_status(status);
381 return -1;
384 status = catia_string_replace_allocate(handle->conn,
385 smb_fname_dst->base_name,
386 &dst_name_mapped, vfs_translate_to_unix);
387 if (!NT_STATUS_IS_OK(status)) {
388 errno = map_errno_from_nt_status(status);
389 return -1;
392 /* Setup temporary smb_filename structs. */
393 status = copy_smb_filename(ctx, smb_fname_src, &smb_fname_src_tmp);
395 if (!NT_STATUS_IS_OK(status)) {
396 errno = map_errno_from_nt_status(status);
397 goto out;
400 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
401 if (!NT_STATUS_IS_OK(status)) {
402 errno = map_errno_from_nt_status(status);
403 goto out;
406 smb_fname_src_tmp->base_name = src_name_mapped;
407 smb_fname_dst_tmp->base_name = dst_name_mapped;
408 DEBUG(10, ("converted old name: %s\n",
409 smb_fname_str_dbg(smb_fname_src_tmp)));
410 DEBUG(10, ("converted new name: %s\n",
411 smb_fname_str_dbg(smb_fname_dst_tmp)));
413 ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
414 smb_fname_dst_tmp);
415 out:
416 TALLOC_FREE(src_name_mapped);
417 TALLOC_FREE(dst_name_mapped);
418 TALLOC_FREE(smb_fname_src_tmp);
419 TALLOC_FREE(smb_fname_dst_tmp);
420 return ret;
423 static int catia_stat(vfs_handle_struct *handle,
424 struct smb_filename *smb_fname)
426 char *name = NULL;
427 char *tmp_base_name;
428 int ret;
429 NTSTATUS status;
431 status = catia_string_replace_allocate(handle->conn,
432 smb_fname->base_name,
433 &name, vfs_translate_to_unix);
434 if (!NT_STATUS_IS_OK(status)) {
435 errno = map_errno_from_nt_status(status);
436 return -1;
439 tmp_base_name = smb_fname->base_name;
440 smb_fname->base_name = name;
442 ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
443 smb_fname->base_name = tmp_base_name;
445 TALLOC_FREE(name);
446 return ret;
449 static int catia_lstat(vfs_handle_struct *handle,
450 struct smb_filename *smb_fname)
452 char *name = NULL;
453 char *tmp_base_name;
454 int ret;
455 NTSTATUS status;
457 status = catia_string_replace_allocate(handle->conn,
458 smb_fname->base_name,
459 &name, vfs_translate_to_unix);
460 if (!NT_STATUS_IS_OK(status)) {
461 errno = map_errno_from_nt_status(status);
462 return -1;
465 tmp_base_name = smb_fname->base_name;
466 smb_fname->base_name = name;
468 ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
469 smb_fname->base_name = tmp_base_name;
470 TALLOC_FREE(name);
472 return ret;
475 static int catia_unlink(vfs_handle_struct *handle,
476 const struct smb_filename *smb_fname)
478 struct smb_filename *smb_fname_tmp = NULL;
479 char *name = NULL;
480 NTSTATUS status;
481 int ret;
483 status = catia_string_replace_allocate(handle->conn,
484 smb_fname->base_name,
485 &name, vfs_translate_to_unix);
486 if (!NT_STATUS_IS_OK(status)) {
487 errno = map_errno_from_nt_status(status);
488 return -1;
491 /* Setup temporary smb_filename structs. */
492 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
493 if (!NT_STATUS_IS_OK(status)) {
494 errno = map_errno_from_nt_status(status);
495 return -1;
498 smb_fname_tmp->base_name = name;
499 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
500 TALLOC_FREE(smb_fname_tmp);
501 TALLOC_FREE(name);
503 return ret;
506 static int catia_chown(vfs_handle_struct *handle,
507 const char *path,
508 uid_t uid,
509 gid_t gid)
511 char *name = NULL;
512 NTSTATUS status;
513 int ret;
515 status = catia_string_replace_allocate(handle->conn, path,
516 &name, vfs_translate_to_unix);
517 if (!NT_STATUS_IS_OK(status)) {
518 errno = map_errno_from_nt_status(status);
519 return -1;
522 ret = SMB_VFS_NEXT_CHOWN(handle, name, uid, gid);
523 TALLOC_FREE(name);
525 return ret;
528 static int catia_lchown(vfs_handle_struct *handle,
529 const char *path,
530 uid_t uid,
531 gid_t gid)
533 char *name = NULL;
534 NTSTATUS status;
535 int ret;
537 status = catia_string_replace_allocate(handle->conn, path,
538 &name, vfs_translate_to_unix);
539 if (!NT_STATUS_IS_OK(status)) {
540 errno = map_errno_from_nt_status(status);
541 return -1;
544 ret = SMB_VFS_NEXT_LCHOWN(handle, name, uid, gid);
545 TALLOC_FREE(name);
547 return ret;
550 static int catia_rmdir(vfs_handle_struct *handle,
551 const char *path)
553 char *name = NULL;
554 NTSTATUS status;
555 int ret;
557 status = catia_string_replace_allocate(handle->conn, path,
558 &name, vfs_translate_to_unix);
559 if (!NT_STATUS_IS_OK(status)) {
560 errno = map_errno_from_nt_status(status);
561 return -1;
564 ret = SMB_VFS_NEXT_RMDIR(handle, name);
565 TALLOC_FREE(name);
567 return ret;
570 static int catia_mkdir(vfs_handle_struct *handle,
571 const char *path,
572 mode_t mode)
574 char *name = NULL;
575 NTSTATUS status;
576 int ret;
578 status = catia_string_replace_allocate(handle->conn, path,
579 &name, vfs_translate_to_unix);
580 if (!NT_STATUS_IS_OK(status)) {
581 errno = map_errno_from_nt_status(status);
582 return -1;
585 ret = SMB_VFS_NEXT_MKDIR(handle, name, mode);
586 TALLOC_FREE(name);
588 return ret;
591 static int catia_chdir(vfs_handle_struct *handle,
592 const char *path)
594 char *name = NULL;
595 NTSTATUS status;
596 int ret;
598 status = catia_string_replace_allocate(handle->conn, path,
599 &name, vfs_translate_to_unix);
600 if (!NT_STATUS_IS_OK(status)) {
601 errno = map_errno_from_nt_status(status);
602 return -1;
605 ret = SMB_VFS_NEXT_CHDIR(handle, name);
606 TALLOC_FREE(name);
608 return ret;
611 static int catia_ntimes(vfs_handle_struct *handle,
612 const struct smb_filename *smb_fname,
613 struct smb_file_time *ft)
615 struct smb_filename *smb_fname_tmp = NULL;
616 char *name = NULL;
617 NTSTATUS status;
618 int ret;
620 status = catia_string_replace_allocate(handle->conn,
621 smb_fname->base_name,
622 &name, vfs_translate_to_unix);
623 if (!NT_STATUS_IS_OK(status)) {
624 errno = map_errno_from_nt_status(status);
625 return -1;
628 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
629 if (!NT_STATUS_IS_OK(status)) {
630 errno = map_errno_from_nt_status(status);
631 return -1;
634 smb_fname_tmp->base_name = name;
635 ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
636 TALLOC_FREE(name);
637 TALLOC_FREE(smb_fname_tmp);
639 return ret;
642 static char *
643 catia_realpath(vfs_handle_struct *handle, const char *path)
645 char *mapped_name = NULL;
646 NTSTATUS status;
647 char *ret = NULL;
649 status = catia_string_replace_allocate(handle->conn, path,
650 &mapped_name, vfs_translate_to_unix);
651 if (!NT_STATUS_IS_OK(status)) {
652 errno = map_errno_from_nt_status(status);
653 return NULL;
656 ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name);
657 TALLOC_FREE(mapped_name);
659 return ret;
662 static int catia_chflags(struct vfs_handle_struct *handle,
663 const char *path, unsigned int flags)
665 char *mapped_name = NULL;
666 NTSTATUS status;
667 int ret;
669 status = catia_string_replace_allocate(handle->conn, path,
670 &mapped_name, vfs_translate_to_unix);
671 if (!NT_STATUS_IS_OK(status)) {
672 errno = map_errno_from_nt_status(status);
673 return -1;
676 ret = SMB_VFS_NEXT_CHFLAGS(handle, mapped_name, flags);
677 TALLOC_FREE(mapped_name);
679 return ret;
682 static NTSTATUS
683 catia_streaminfo(struct vfs_handle_struct *handle,
684 struct files_struct *fsp,
685 const char *path,
686 TALLOC_CTX *mem_ctx,
687 unsigned int *num_streams,
688 struct stream_struct **streams)
690 char *mapped_name = NULL;
691 NTSTATUS status;
693 status = catia_string_replace_allocate(handle->conn, path,
694 &mapped_name, vfs_translate_to_unix);
695 if (!NT_STATUS_IS_OK(status)) {
696 errno = map_errno_from_nt_status(status);
697 return status;
700 status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, mapped_name,
701 mem_ctx, num_streams,streams);
702 TALLOC_FREE(mapped_name);
704 return status;
707 static NTSTATUS
708 catia_get_nt_acl(struct vfs_handle_struct *handle,
709 const char *path,
710 uint32 security_info,
711 TALLOC_CTX *mem_ctx,
712 struct security_descriptor **ppdesc)
714 char *mapped_name = NULL;
715 NTSTATUS status;
717 status = catia_string_replace_allocate(handle->conn,
718 path, &mapped_name, vfs_translate_to_unix);
719 if (!NT_STATUS_IS_OK(status)) {
720 errno = map_errno_from_nt_status(status);
721 return status;
723 status = SMB_VFS_NEXT_GET_NT_ACL(handle, mapped_name,
724 security_info, mem_ctx, ppdesc);
725 TALLOC_FREE(mapped_name);
727 return status;
730 static int
731 catia_chmod_acl(vfs_handle_struct *handle,
732 const char *path,
733 mode_t mode)
735 char *mapped_name = NULL;
736 NTSTATUS status;
737 int ret;
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 -1;
746 ret = SMB_VFS_NEXT_CHMOD_ACL(handle, mapped_name, mode);
747 TALLOC_FREE(mapped_name);
748 return ret;
751 static SMB_ACL_T
752 catia_sys_acl_get_file(vfs_handle_struct *handle,
753 const char *path,
754 SMB_ACL_TYPE_T type,
755 TALLOC_CTX *mem_ctx)
757 char *mapped_name = NULL;
758 NTSTATUS status;
759 SMB_ACL_T ret;
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 NULL;
768 ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, mapped_name, type, mem_ctx);
769 TALLOC_FREE(mapped_name);
771 return ret;
774 static int
775 catia_sys_acl_set_file(vfs_handle_struct *handle,
776 const char *path,
777 SMB_ACL_TYPE_T type,
778 SMB_ACL_T theacl)
780 char *mapped_name = NULL;
781 NTSTATUS status;
782 int ret;
784 status = catia_string_replace_allocate(handle->conn,
785 path, &mapped_name, vfs_translate_to_unix);
786 if (!NT_STATUS_IS_OK(status)) {
787 errno = map_errno_from_nt_status(status);
788 return -1;
791 ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, mapped_name, type, theacl);
792 TALLOC_FREE(mapped_name);
794 return ret;
797 static int
798 catia_sys_acl_delete_def_file(vfs_handle_struct *handle,
799 const char *path)
801 char *mapped_name = NULL;
802 NTSTATUS status;
803 int ret;
805 status = catia_string_replace_allocate(handle->conn,
806 path, &mapped_name, vfs_translate_to_unix);
807 if (!NT_STATUS_IS_OK(status)) {
808 errno = map_errno_from_nt_status(status);
809 return -1;
812 ret = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, mapped_name);
813 TALLOC_FREE(mapped_name);
815 return ret;
818 static ssize_t
819 catia_getxattr(vfs_handle_struct *handle, const char *path,
820 const char *name, void *value, size_t size)
822 char *mapped_name = NULL;
823 NTSTATUS status;
824 ssize_t ret;
826 status = catia_string_replace_allocate(handle->conn,
827 name, &mapped_name, vfs_translate_to_unix);
828 if (!NT_STATUS_IS_OK(status)) {
829 errno = map_errno_from_nt_status(status);
830 return -1;
834 ret = SMB_VFS_NEXT_GETXATTR(handle, path, mapped_name, value, size);
835 TALLOC_FREE(mapped_name);
837 return ret;
840 static ssize_t
841 catia_listxattr(vfs_handle_struct *handle, const char *path,
842 char *list, size_t size)
844 char *mapped_name = NULL;
845 NTSTATUS status;
846 ssize_t ret;
848 status = catia_string_replace_allocate(handle->conn,
849 path, &mapped_name, vfs_translate_to_unix);
850 if (!NT_STATUS_IS_OK(status)) {
851 errno = map_errno_from_nt_status(status);
852 return -1;
856 ret = SMB_VFS_NEXT_LISTXATTR(handle, mapped_name, list, size);
857 TALLOC_FREE(mapped_name);
859 return ret;
862 static int
863 catia_removexattr(vfs_handle_struct *handle, const char *path,
864 const char *name)
866 char *mapped_name = NULL;
867 NTSTATUS status;
868 ssize_t ret;
870 status = catia_string_replace_allocate(handle->conn,
871 name, &mapped_name, vfs_translate_to_unix);
872 if (!NT_STATUS_IS_OK(status)) {
873 errno = map_errno_from_nt_status(status);
874 return -1;
878 ret = SMB_VFS_NEXT_REMOVEXATTR(handle, path, mapped_name);
879 TALLOC_FREE(mapped_name);
881 return ret;
884 static int
885 catia_setxattr(vfs_handle_struct *handle, const char *path,
886 const char *name, const void *value, size_t size,
887 int flags)
889 char *mapped_name = NULL;
890 NTSTATUS status;
891 ssize_t ret;
893 status = catia_string_replace_allocate(handle->conn,
894 name, &mapped_name, vfs_translate_to_unix);
895 if (!NT_STATUS_IS_OK(status)) {
896 errno = map_errno_from_nt_status(status);
897 return -1;
901 ret = SMB_VFS_NEXT_SETXATTR(handle, path, mapped_name, value, size, flags);
902 TALLOC_FREE(mapped_name);
904 return ret;
907 static struct vfs_fn_pointers vfs_catia_fns = {
908 .mkdir_fn = catia_mkdir,
909 .rmdir_fn = catia_rmdir,
910 .opendir_fn = catia_opendir,
911 .open_fn = catia_open,
912 .rename_fn = catia_rename,
913 .stat_fn = catia_stat,
914 .lstat_fn = catia_lstat,
915 .unlink_fn = catia_unlink,
916 .chown_fn = catia_chown,
917 .lchown_fn = catia_lchown,
918 .chdir_fn = catia_chdir,
919 .ntimes_fn = catia_ntimes,
920 .realpath_fn = catia_realpath,
921 .chflags_fn = catia_chflags,
922 .streaminfo_fn = catia_streaminfo,
923 .translate_name_fn = catia_translate_name,
924 .get_nt_acl_fn = catia_get_nt_acl,
925 .chmod_acl_fn = catia_chmod_acl,
926 .sys_acl_get_file_fn = catia_sys_acl_get_file,
927 .sys_acl_set_file_fn = catia_sys_acl_set_file,
928 .sys_acl_delete_def_file_fn = catia_sys_acl_delete_def_file,
929 .getxattr_fn = catia_getxattr,
930 .listxattr_fn = catia_listxattr,
931 .removexattr_fn = catia_removexattr,
932 .setxattr_fn = catia_setxattr,
935 NTSTATUS vfs_catia_init(void)
937 NTSTATUS ret;
939 ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia",
940 &vfs_catia_fns);
941 if (!NT_STATUS_IS_OK(ret))
942 return ret;
944 vfs_catia_debug_level = debug_add_class("catia");
945 if (vfs_catia_debug_level == -1) {
946 vfs_catia_debug_level = DBGC_VFS;
947 DEBUG(0, ("vfs_catia: Couldn't register custom debugging "
948 "class!\n"));
949 } else {
950 DEBUG(10, ("vfs_catia: Debug class number of "
951 "'catia': %d\n", vfs_catia_debug_level));
954 return ret;