selftest: export/use CTDB related envvars in order to run the ctdb command
[Samba.git] / source3 / modules / vfs_cap.c
blob3553e118cc2cfcd6fce559e8bbe45ba71ff56885
1 /*
2 * CAP VFS module for Samba 3.x Version 0.3
4 * Copyright (C) Tim Potter, 1999-2000
5 * Copyright (C) Alexander Bokovoy, 2002-2003
6 * Copyright (C) Stefan (metze) Metzmacher, 2003
7 * Copyright (C) TAKAHASHI Motonobu (monyo), 2003
8 * Copyright (C) Jeremy Allison, 2007
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "smbd/smbd.h"
28 /* cap functions */
29 static char *capencode(TALLOC_CTX *ctx, const char *from);
30 static char *capdecode(TALLOC_CTX *ctx, const char *from);
32 static uint64_t cap_disk_free(vfs_handle_struct *handle,
33 const struct smb_filename *smb_fname,
34 uint64_t *bsize,
35 uint64_t *dfree,
36 uint64_t *dsize)
38 char *capname = capencode(talloc_tos(), smb_fname->base_name);
39 struct smb_filename *cap_smb_fname = NULL;
41 if (!capname) {
42 errno = ENOMEM;
43 return (uint64_t)-1;
45 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
46 capname,
47 NULL,
48 NULL,
49 smb_fname->twrp,
50 smb_fname->flags);
51 if (cap_smb_fname == NULL) {
52 TALLOC_FREE(capname);
53 errno = ENOMEM;
54 return (uint64_t)-1;
56 return SMB_VFS_NEXT_DISK_FREE(handle, cap_smb_fname,
57 bsize, dfree, dsize);
60 static int cap_get_quota(vfs_handle_struct *handle,
61 const struct smb_filename *smb_fname,
62 enum SMB_QUOTA_TYPE qtype,
63 unid_t id,
64 SMB_DISK_QUOTA *dq)
66 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
67 struct smb_filename *cap_smb_fname = NULL;
69 if (!cappath) {
70 errno = ENOMEM;
71 return -1;
73 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
74 cappath,
75 NULL,
76 NULL,
77 smb_fname->twrp,
78 smb_fname->flags);
79 if (cap_smb_fname == NULL) {
80 TALLOC_FREE(cappath);
81 errno = ENOMEM;
82 return -1;
84 return SMB_VFS_NEXT_GET_QUOTA(handle, cap_smb_fname, qtype, id, dq);
87 static struct dirent *
88 cap_readdir(vfs_handle_struct *handle, struct files_struct *dirfsp, DIR *dirp)
90 struct dirent *result;
91 struct dirent *newdirent;
92 char *newname;
93 size_t newnamelen;
94 DEBUG(3,("cap: cap_readdir\n"));
96 result = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp);
97 if (!result) {
98 return NULL;
101 newname = capdecode(talloc_tos(), result->d_name);
102 if (!newname) {
103 return NULL;
105 DEBUG(3,("cap: cap_readdir: %s\n", newname));
106 newnamelen = strlen(newname)+1;
107 newdirent = talloc_size(
108 talloc_tos(), sizeof(struct dirent) + newnamelen);
109 if (!newdirent) {
110 return NULL;
112 talloc_set_name_const(newdirent, "struct dirent");
113 memcpy(newdirent, result, sizeof(struct dirent));
114 memcpy(&newdirent->d_name, newname, newnamelen);
115 return newdirent;
118 static int cap_mkdirat(vfs_handle_struct *handle,
119 struct files_struct *dirfsp,
120 const struct smb_filename *smb_fname,
121 mode_t mode)
123 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
124 struct smb_filename *cap_smb_fname = NULL;
126 if (!cappath) {
127 errno = ENOMEM;
128 return -1;
131 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
132 cappath,
133 NULL,
134 NULL,
135 smb_fname->twrp,
136 smb_fname->flags);
137 if (cap_smb_fname == NULL) {
138 TALLOC_FREE(cappath);
139 errno = ENOMEM;
140 return -1;
143 return SMB_VFS_NEXT_MKDIRAT(handle,
144 dirfsp,
145 cap_smb_fname,
146 mode);
149 static int cap_openat(vfs_handle_struct *handle,
150 const struct files_struct *dirfsp,
151 const struct smb_filename *smb_fname_in,
152 files_struct *fsp,
153 const struct vfs_open_how *how)
155 char *cappath = NULL;
156 struct smb_filename *smb_fname = NULL;
157 int ret;
158 int saved_errno = 0;
160 cappath = capencode(talloc_tos(), smb_fname_in->base_name);
161 if (cappath == NULL) {
162 errno = ENOMEM;
163 return -1;
166 smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
167 if (smb_fname == NULL) {
168 TALLOC_FREE(cappath);
169 errno = ENOMEM;
170 return -1;
172 smb_fname->base_name = cappath;
174 DBG_DEBUG("cap_open for %s\n", smb_fname_str_dbg(smb_fname));
175 ret = SMB_VFS_NEXT_OPENAT(handle,
176 dirfsp,
177 smb_fname,
178 fsp,
179 how);
180 if (ret == -1) {
181 saved_errno = errno;
183 TALLOC_FREE(cappath);
184 TALLOC_FREE(smb_fname);
185 if (saved_errno != 0) {
186 errno = saved_errno;
188 return ret;
191 static int cap_renameat(vfs_handle_struct *handle,
192 files_struct *srcfsp,
193 const struct smb_filename *smb_fname_src,
194 files_struct *dstfsp,
195 const struct smb_filename *smb_fname_dst)
197 char *capold = NULL;
198 char *capnew = NULL;
199 struct smb_filename *smb_fname_src_tmp = NULL;
200 struct smb_filename *smb_fname_dst_tmp = NULL;
201 struct smb_filename *full_fname_src = NULL;
202 struct smb_filename *full_fname_dst = NULL;
203 int ret = -1;
204 int saved_errno = 0;
206 full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
207 srcfsp,
208 smb_fname_src);
209 if (full_fname_src == NULL) {
210 errno = ENOMEM;
211 goto out;
214 full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
215 dstfsp,
216 smb_fname_dst);
217 if (full_fname_dst == NULL) {
218 errno = ENOMEM;
219 goto out;
222 capold = capencode(talloc_tos(), full_fname_src->base_name);
223 capnew = capencode(talloc_tos(), full_fname_dst->base_name);
224 if (!capold || !capnew) {
225 errno = ENOMEM;
226 goto out;
229 /* Setup temporary smb_filename structs. */
230 smb_fname_src_tmp = cp_smb_filename(talloc_tos(), full_fname_src);
231 if (smb_fname_src_tmp == NULL) {
232 errno = ENOMEM;
233 goto out;
235 smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), full_fname_dst);
236 if (smb_fname_dst_tmp == NULL) {
237 errno = ENOMEM;
238 goto out;
241 smb_fname_src_tmp->base_name = capold;
242 smb_fname_dst_tmp->base_name = capnew;
244 ret = SMB_VFS_NEXT_RENAMEAT(handle,
245 srcfsp->conn->cwd_fsp,
246 smb_fname_src_tmp,
247 dstfsp->conn->cwd_fsp,
248 smb_fname_dst_tmp);
250 out:
252 if (ret != 0) {
253 saved_errno = errno;
256 TALLOC_FREE(full_fname_src);
257 TALLOC_FREE(full_fname_dst);
258 TALLOC_FREE(capold);
259 TALLOC_FREE(capnew);
260 TALLOC_FREE(smb_fname_src_tmp);
261 TALLOC_FREE(smb_fname_dst_tmp);
263 if (ret != 0) {
264 errno = saved_errno;
267 return ret;
270 static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
272 char *cappath;
273 char *tmp_base_name = NULL;
274 int ret;
276 cappath = capencode(talloc_tos(), smb_fname->base_name);
278 if (!cappath) {
279 errno = ENOMEM;
280 return -1;
283 tmp_base_name = smb_fname->base_name;
284 smb_fname->base_name = cappath;
286 ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
288 smb_fname->base_name = tmp_base_name;
289 TALLOC_FREE(cappath);
291 return ret;
294 static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
296 char *cappath;
297 char *tmp_base_name = NULL;
298 int ret;
300 cappath = capencode(talloc_tos(), smb_fname->base_name);
302 if (!cappath) {
303 errno = ENOMEM;
304 return -1;
307 tmp_base_name = smb_fname->base_name;
308 smb_fname->base_name = cappath;
310 ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
312 smb_fname->base_name = tmp_base_name;
313 TALLOC_FREE(cappath);
315 return ret;
318 static int cap_unlinkat(vfs_handle_struct *handle,
319 struct files_struct *dirfsp,
320 const struct smb_filename *smb_fname,
321 int flags)
323 struct smb_filename *full_fname = NULL;
324 struct smb_filename *smb_fname_tmp = NULL;
325 char *cappath = NULL;
326 int ret;
328 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
329 dirfsp,
330 smb_fname);
331 if (full_fname == NULL) {
332 return -1;
335 cappath = capencode(talloc_tos(), full_fname->base_name);
336 if (!cappath) {
337 TALLOC_FREE(full_fname);
338 errno = ENOMEM;
339 return -1;
342 /* Setup temporary smb_filename structs. */
343 smb_fname_tmp = cp_smb_filename(talloc_tos(), full_fname);
344 TALLOC_FREE(full_fname);
345 if (smb_fname_tmp == NULL) {
346 errno = ENOMEM;
347 return -1;
350 smb_fname_tmp->base_name = cappath;
352 ret = SMB_VFS_NEXT_UNLINKAT(handle,
353 dirfsp->conn->cwd_fsp,
354 smb_fname_tmp,
355 flags);
357 TALLOC_FREE(smb_fname_tmp);
358 return ret;
361 static int cap_lchown(vfs_handle_struct *handle,
362 const struct smb_filename *smb_fname,
363 uid_t uid,
364 gid_t gid)
366 struct smb_filename *cap_smb_fname = NULL;
367 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
368 int ret;
369 int saved_errno;
371 if (!cappath) {
372 errno = ENOMEM;
373 return -1;
376 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
377 cappath,
378 NULL,
379 NULL,
380 smb_fname->twrp,
381 smb_fname->flags);
382 if (cap_smb_fname == NULL) {
383 TALLOC_FREE(cappath);
384 errno = ENOMEM;
385 return -1;
388 ret = SMB_VFS_NEXT_LCHOWN(handle, cap_smb_fname, uid, gid);
389 saved_errno = errno;
390 TALLOC_FREE(cappath);
391 TALLOC_FREE(cap_smb_fname);
392 errno = saved_errno;
393 return ret;
396 static int cap_chdir(vfs_handle_struct *handle,
397 const struct smb_filename *smb_fname)
399 struct smb_filename *cap_smb_fname = NULL;
400 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
401 int ret;
402 int saved_errno = 0;
404 if (!cappath) {
405 errno = ENOMEM;
406 return -1;
408 DEBUG(3,("cap: cap_chdir for %s\n", smb_fname->base_name));
410 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
411 cappath,
412 NULL,
413 NULL,
414 smb_fname->twrp,
415 smb_fname->flags);
416 if (cap_smb_fname == NULL) {
417 TALLOC_FREE(cappath);
418 errno = ENOMEM;
419 return -1;
421 ret = SMB_VFS_NEXT_CHDIR(handle, cap_smb_fname);
422 if (ret == -1) {
423 saved_errno = errno;
425 TALLOC_FREE(cappath);
426 TALLOC_FREE(cap_smb_fname);
427 if (saved_errno != 0) {
428 errno = saved_errno;
430 return ret;
433 static int cap_symlinkat(vfs_handle_struct *handle,
434 const struct smb_filename *link_contents,
435 struct files_struct *dirfsp,
436 const struct smb_filename *new_smb_fname)
438 struct smb_filename *full_fname = NULL;
439 char *capold = capencode(talloc_tos(), link_contents->base_name);
440 char *capnew = NULL;
441 struct smb_filename *new_link_target = NULL;
442 struct smb_filename *new_cap_smb_fname = NULL;
443 int saved_errno = 0;
444 int ret;
446 if (capold == NULL) {
447 errno = ENOMEM;
448 return -1;
451 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
452 dirfsp,
453 new_smb_fname);
454 if (full_fname == NULL) {
455 return -1;
458 capnew = capencode(talloc_tos(), full_fname->base_name);
459 if (!capnew) {
460 TALLOC_FREE(full_fname);
461 errno = ENOMEM;
462 return -1;
465 new_link_target = synthetic_smb_fname(talloc_tos(),
466 capold,
467 NULL,
468 NULL,
469 new_smb_fname->twrp,
470 new_smb_fname->flags);
471 if (new_link_target == NULL) {
472 TALLOC_FREE(full_fname);
473 TALLOC_FREE(capold);
474 TALLOC_FREE(capnew);
475 errno = ENOMEM;
476 return -1;
479 new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
480 capnew,
481 NULL,
482 NULL,
483 new_smb_fname->twrp,
484 new_smb_fname->flags);
485 if (new_cap_smb_fname == NULL) {
486 TALLOC_FREE(full_fname);
487 TALLOC_FREE(capold);
488 TALLOC_FREE(capnew);
489 TALLOC_FREE(new_link_target);
490 errno = ENOMEM;
491 return -1;
493 ret = SMB_VFS_NEXT_SYMLINKAT(handle,
494 new_link_target,
495 handle->conn->cwd_fsp,
496 new_cap_smb_fname);
497 if (ret == -1) {
498 saved_errno = errno;
500 TALLOC_FREE(full_fname);
501 TALLOC_FREE(capold);
502 TALLOC_FREE(capnew);
503 TALLOC_FREE(new_link_target);
504 TALLOC_FREE(new_cap_smb_fname);
505 if (saved_errno != 0) {
506 errno = saved_errno;
508 return ret;
511 static int cap_readlinkat(vfs_handle_struct *handle,
512 const struct files_struct *dirfsp,
513 const struct smb_filename *smb_fname,
514 char *buf,
515 size_t bufsiz)
517 struct smb_filename *full_fname = NULL;
518 struct smb_filename *cap_smb_fname = NULL;
519 char *cappath = NULL;
520 int saved_errno = 0;
521 int ret;
523 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
524 dirfsp,
525 smb_fname);
526 if (full_fname == NULL) {
527 return -1;
530 cappath = capencode(talloc_tos(), full_fname->base_name);
531 if (cappath == NULL) {
532 TALLOC_FREE(full_fname);
533 errno = ENOMEM;
534 return -1;
536 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
537 cappath,
538 NULL,
539 NULL,
540 smb_fname->twrp,
541 smb_fname->flags);
542 if (cap_smb_fname == NULL) {
543 TALLOC_FREE(full_fname);
544 TALLOC_FREE(cappath);
545 errno = ENOMEM;
546 return -1;
548 ret = SMB_VFS_NEXT_READLINKAT(handle,
549 handle->conn->cwd_fsp,
550 cap_smb_fname,
551 buf,
552 bufsiz);
553 if (ret == -1) {
554 saved_errno = errno;
556 TALLOC_FREE(full_fname);
557 TALLOC_FREE(cappath);
558 TALLOC_FREE(cap_smb_fname);
559 if (saved_errno != 0) {
560 errno = saved_errno;
562 return ret;
565 static int cap_linkat(vfs_handle_struct *handle,
566 files_struct *srcfsp,
567 const struct smb_filename *old_smb_fname,
568 files_struct *dstfsp,
569 const struct smb_filename *new_smb_fname,
570 int flags)
572 struct smb_filename *old_full_fname = NULL;
573 struct smb_filename *new_full_fname = NULL;
574 char *capold = NULL;
575 char *capnew = NULL;
576 struct smb_filename *old_cap_smb_fname = NULL;
577 struct smb_filename *new_cap_smb_fname = NULL;
578 int saved_errno = 0;
579 int ret;
581 /* Process 'old' name. */
582 old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
583 srcfsp,
584 old_smb_fname);
585 if (old_full_fname == NULL) {
586 goto nomem_out;
588 capold = capencode(talloc_tos(), old_full_fname->base_name);
589 if (capold == NULL) {
590 goto nomem_out;
592 TALLOC_FREE(old_full_fname);
593 old_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
594 capold,
595 NULL,
596 NULL,
597 old_smb_fname->twrp,
598 old_smb_fname->flags);
599 if (old_cap_smb_fname == NULL) {
600 goto nomem_out;
603 /* Process 'new' name. */
604 new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
605 dstfsp,
606 new_smb_fname);
607 if (new_full_fname == NULL) {
608 goto nomem_out;
610 capnew = capencode(talloc_tos(), new_full_fname->base_name);
611 if (capnew == NULL) {
612 goto nomem_out;
614 TALLOC_FREE(new_full_fname);
615 new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
616 capnew,
617 NULL,
618 NULL,
619 new_smb_fname->twrp,
620 new_smb_fname->flags);
621 if (new_cap_smb_fname == NULL) {
622 goto nomem_out;
625 ret = SMB_VFS_NEXT_LINKAT(handle,
626 handle->conn->cwd_fsp,
627 old_cap_smb_fname,
628 handle->conn->cwd_fsp,
629 new_cap_smb_fname,
630 flags);
631 if (ret == -1) {
632 saved_errno = errno;
634 TALLOC_FREE(old_full_fname);
635 TALLOC_FREE(old_full_fname);
636 TALLOC_FREE(capold);
637 TALLOC_FREE(capnew);
638 TALLOC_FREE(old_cap_smb_fname);
639 TALLOC_FREE(new_cap_smb_fname);
640 if (saved_errno != 0) {
641 errno = saved_errno;
643 return ret;
645 nomem_out:
647 TALLOC_FREE(old_full_fname);
648 TALLOC_FREE(old_full_fname);
649 TALLOC_FREE(capold);
650 TALLOC_FREE(capnew);
651 TALLOC_FREE(old_cap_smb_fname);
652 TALLOC_FREE(new_cap_smb_fname);
653 errno = ENOMEM;
654 return -1;
657 static int cap_mknodat(vfs_handle_struct *handle,
658 files_struct *dirfsp,
659 const struct smb_filename *smb_fname,
660 mode_t mode,
661 SMB_DEV_T dev)
663 struct smb_filename *full_fname = NULL;
664 struct smb_filename *cap_smb_fname = NULL;
665 char *cappath = NULL;
666 int ret;
667 int saved_errno = 0;
669 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
670 dirfsp,
671 smb_fname);
672 if (full_fname == NULL) {
673 return -1;
676 cappath = capencode(talloc_tos(), full_fname->base_name);
677 if (!cappath) {
678 TALLOC_FREE(full_fname);
679 errno = ENOMEM;
680 return -1;
682 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
683 cappath,
684 NULL,
685 NULL,
686 smb_fname->twrp,
687 smb_fname->flags);
688 if (cap_smb_fname == NULL) {
689 TALLOC_FREE(full_fname);
690 TALLOC_FREE(cappath);
691 errno = ENOMEM;
692 return -1;
694 ret = SMB_VFS_NEXT_MKNODAT(handle,
695 handle->conn->cwd_fsp,
696 cap_smb_fname,
697 mode,
698 dev);
699 if (ret == -1) {
700 saved_errno = errno;
702 TALLOC_FREE(full_fname);
703 TALLOC_FREE(cappath);
704 TALLOC_FREE(cap_smb_fname);
705 if (saved_errno != 0) {
706 errno = saved_errno;
708 return ret;
711 static struct smb_filename *cap_realpath(vfs_handle_struct *handle,
712 TALLOC_CTX *ctx,
713 const struct smb_filename *smb_fname)
715 /* monyo need capencode'ed and capdecode'ed? */
716 struct smb_filename *cap_smb_fname = NULL;
717 struct smb_filename *return_fname = NULL;
718 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
719 int saved_errno = 0;
721 if (!cappath) {
722 errno = ENOMEM;
723 return NULL;
725 cap_smb_fname = synthetic_smb_fname(ctx,
726 cappath,
727 NULL,
728 NULL,
729 smb_fname->twrp,
730 smb_fname->flags);
731 if (cap_smb_fname == NULL) {
732 TALLOC_FREE(cappath);
733 errno = ENOMEM;
734 return NULL;
736 return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname);
737 if (return_fname == NULL) {
738 saved_errno = errno;
740 TALLOC_FREE(cappath);
741 TALLOC_FREE(cap_smb_fname);
742 if (saved_errno != 0) {
743 errno = saved_errno;
745 return return_fname;
748 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
750 char *cappath = capencode(talloc_tos(), path);
752 if (!cappath) {
753 errno = ENOMEM;
754 return -1;
756 return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
759 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
761 char *cappath = capencode(talloc_tos(), path);
763 if (!cappath) {
764 errno = ENOMEM;
765 return -1;
767 return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
770 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
772 char *cappath = capencode(talloc_tos(), path);
774 if (!cappath) {
775 errno = ENOMEM;
776 return -1;
778 return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
781 static NTSTATUS cap_create_dfs_pathat(vfs_handle_struct *handle,
782 files_struct *dirfsp,
783 const struct smb_filename *smb_fname,
784 const struct referral *reflist,
785 size_t referral_count)
787 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
788 struct smb_filename *cap_smb_fname = NULL;
789 NTSTATUS status;
791 if (cappath == NULL) {
792 return NT_STATUS_NO_MEMORY;
794 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
795 cappath,
796 NULL,
797 NULL,
798 smb_fname->twrp,
799 smb_fname->flags);
800 if (cap_smb_fname == NULL) {
801 TALLOC_FREE(cappath);
802 return NT_STATUS_NO_MEMORY;
804 status = SMB_VFS_NEXT_CREATE_DFS_PATHAT(handle,
805 dirfsp,
806 cap_smb_fname,
807 reflist,
808 referral_count);
809 TALLOC_FREE(cappath);
810 TALLOC_FREE(cap_smb_fname);
811 return status;
814 static NTSTATUS cap_read_dfs_pathat(struct vfs_handle_struct *handle,
815 TALLOC_CTX *mem_ctx,
816 struct files_struct *dirfsp,
817 struct smb_filename *smb_fname,
818 struct referral **ppreflist,
819 size_t *preferral_count)
821 struct smb_filename *full_fname = NULL;
822 struct smb_filename *cap_smb_fname = NULL;
823 char *cappath = NULL;
824 NTSTATUS status;
826 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
827 dirfsp,
828 smb_fname);
829 if (full_fname == NULL) {
830 return NT_STATUS_NO_MEMORY;
832 cappath = capencode(talloc_tos(), full_fname->base_name);
833 if (cappath == NULL) {
834 TALLOC_FREE(full_fname);
835 return NT_STATUS_NO_MEMORY;
837 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
838 cappath,
839 NULL,
840 NULL,
841 smb_fname->twrp,
842 smb_fname->flags);
843 if (cap_smb_fname == NULL) {
844 TALLOC_FREE(full_fname);
845 TALLOC_FREE(cappath);
846 return NT_STATUS_NO_MEMORY;
849 status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
850 mem_ctx,
851 handle->conn->cwd_fsp,
852 cap_smb_fname,
853 ppreflist,
854 preferral_count);
856 if (NT_STATUS_IS_OK(status)) {
857 /* Return any stat(2) info. */
858 smb_fname->st = cap_smb_fname->st;
861 TALLOC_FREE(full_fname);
862 TALLOC_FREE(cappath);
863 TALLOC_FREE(cap_smb_fname);
864 return status;
867 static struct vfs_fn_pointers vfs_cap_fns = {
868 .disk_free_fn = cap_disk_free,
869 .get_quota_fn = cap_get_quota,
870 .readdir_fn = cap_readdir,
871 .mkdirat_fn = cap_mkdirat,
872 .openat_fn = cap_openat,
873 .renameat_fn = cap_renameat,
874 .stat_fn = cap_stat,
875 .lstat_fn = cap_lstat,
876 .unlinkat_fn = cap_unlinkat,
877 .lchown_fn = cap_lchown,
878 .chdir_fn = cap_chdir,
879 .symlinkat_fn = cap_symlinkat,
880 .readlinkat_fn = cap_readlinkat,
881 .linkat_fn = cap_linkat,
882 .mknodat_fn = cap_mknodat,
883 .realpath_fn = cap_realpath,
884 .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
885 .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
886 .fgetxattr_fn = cap_fgetxattr,
887 .fremovexattr_fn = cap_fremovexattr,
888 .fsetxattr_fn = cap_fsetxattr,
889 .create_dfs_pathat_fn = cap_create_dfs_pathat,
890 .read_dfs_pathat_fn = cap_read_dfs_pathat
893 static_decl_vfs;
894 NTSTATUS vfs_cap_init(TALLOC_CTX *ctx)
896 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap",
897 &vfs_cap_fns);
900 /* For CAP functions */
901 #define hex_tag ':'
902 #define hex2bin(c) hex2bin_table[(unsigned char)(c)]
903 #define bin2hex(c) bin2hex_table[(unsigned char)(c)]
904 #define is_hex(s) ((s)[0] == hex_tag)
906 static unsigned char hex2bin_table[256] = {
907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
910 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
911 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
912 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
914 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
915 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
918 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
919 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
920 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
921 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
922 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
923 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
924 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 */
926 static unsigned char bin2hex_table[256] = "0123456789abcdef";
928 /*******************************************************************
929 original code -> ":xx" - CAP format
930 ********************************************************************/
932 static char *capencode(TALLOC_CTX *ctx, const char *from)
934 char *out = NULL;
935 const char *p1;
936 char *to = NULL;
937 size_t len = 0;
939 for (p1 = from; *p1; p1++) {
940 if ((unsigned char)*p1 >= 0x80) {
941 len += 3;
942 } else {
943 len++;
946 len++;
948 to = talloc_array(ctx, char, len);
949 if (!to) {
950 return NULL;
953 for (out = to; *from;) {
954 /* buffer husoku error */
955 if ((unsigned char)*from >= 0x80) {
956 *out++ = hex_tag;
957 *out++ = bin2hex (((*from)>>4)&0x0f);
958 *out++ = bin2hex ((*from)&0x0f);
959 from++;
960 } else {
961 *out++ = *from++;
964 *out = '\0';
965 return to;
968 /*******************************************************************
969 CAP -> original code
970 ********************************************************************/
971 /* ":xx" -> a byte */
973 static char *capdecode(TALLOC_CTX *ctx, const char *from)
975 const char *p1;
976 char *out = NULL;
977 char *to = NULL;
978 size_t len = 0;
980 for (p1 = from; *p1; len++) {
981 if (is_hex(p1)) {
982 p1 += 3;
983 } else {
984 p1++;
987 len++;
989 to = talloc_array(ctx, char, len);
990 if (!to) {
991 return NULL;
994 for (out = to; *from;) {
995 if (is_hex(from)) {
996 *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
997 from += 3;
998 } else {
999 *out++ = *from++;
1002 *out = '\0';
1003 return to;