vfs_ceph_new: Remove unused symbol for ceph_readdir
[Samba.git] / source3 / modules / vfs_cap.c
blob2d4ea76bb78af986742f97e2e3cf76816cd208b2
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,
196 const struct vfs_rename_how *how)
198 char *capold = NULL;
199 char *capnew = NULL;
200 struct smb_filename *smb_fname_src_tmp = NULL;
201 struct smb_filename *smb_fname_dst_tmp = NULL;
202 struct smb_filename *full_fname_src = NULL;
203 struct smb_filename *full_fname_dst = NULL;
204 int ret = -1;
205 int saved_errno = 0;
207 full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
208 srcfsp,
209 smb_fname_src);
210 if (full_fname_src == NULL) {
211 errno = ENOMEM;
212 goto out;
215 full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
216 dstfsp,
217 smb_fname_dst);
218 if (full_fname_dst == NULL) {
219 errno = ENOMEM;
220 goto out;
223 capold = capencode(talloc_tos(), full_fname_src->base_name);
224 capnew = capencode(talloc_tos(), full_fname_dst->base_name);
225 if (!capold || !capnew) {
226 errno = ENOMEM;
227 goto out;
230 /* Setup temporary smb_filename structs. */
231 smb_fname_src_tmp = cp_smb_filename(talloc_tos(), full_fname_src);
232 if (smb_fname_src_tmp == NULL) {
233 errno = ENOMEM;
234 goto out;
236 smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), full_fname_dst);
237 if (smb_fname_dst_tmp == NULL) {
238 errno = ENOMEM;
239 goto out;
242 smb_fname_src_tmp->base_name = capold;
243 smb_fname_dst_tmp->base_name = capnew;
245 ret = SMB_VFS_NEXT_RENAMEAT(handle,
246 srcfsp->conn->cwd_fsp,
247 smb_fname_src_tmp,
248 dstfsp->conn->cwd_fsp,
249 smb_fname_dst_tmp,
250 how);
252 out:
254 if (ret != 0) {
255 saved_errno = errno;
258 TALLOC_FREE(full_fname_src);
259 TALLOC_FREE(full_fname_dst);
260 TALLOC_FREE(capold);
261 TALLOC_FREE(capnew);
262 TALLOC_FREE(smb_fname_src_tmp);
263 TALLOC_FREE(smb_fname_dst_tmp);
265 if (ret != 0) {
266 errno = saved_errno;
269 return ret;
272 static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
274 char *cappath;
275 char *tmp_base_name = NULL;
276 int ret;
278 cappath = capencode(talloc_tos(), smb_fname->base_name);
280 if (!cappath) {
281 errno = ENOMEM;
282 return -1;
285 tmp_base_name = smb_fname->base_name;
286 smb_fname->base_name = cappath;
288 ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
290 smb_fname->base_name = tmp_base_name;
291 TALLOC_FREE(cappath);
293 return ret;
296 static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
298 char *cappath;
299 char *tmp_base_name = NULL;
300 int ret;
302 cappath = capencode(talloc_tos(), smb_fname->base_name);
304 if (!cappath) {
305 errno = ENOMEM;
306 return -1;
309 tmp_base_name = smb_fname->base_name;
310 smb_fname->base_name = cappath;
312 ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
314 smb_fname->base_name = tmp_base_name;
315 TALLOC_FREE(cappath);
317 return ret;
320 static int cap_unlinkat(vfs_handle_struct *handle,
321 struct files_struct *dirfsp,
322 const struct smb_filename *smb_fname,
323 int flags)
325 struct smb_filename *full_fname = NULL;
326 struct smb_filename *smb_fname_tmp = NULL;
327 char *cappath = NULL;
328 int ret;
330 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
331 dirfsp,
332 smb_fname);
333 if (full_fname == NULL) {
334 return -1;
337 cappath = capencode(talloc_tos(), full_fname->base_name);
338 if (!cappath) {
339 TALLOC_FREE(full_fname);
340 errno = ENOMEM;
341 return -1;
344 /* Setup temporary smb_filename structs. */
345 smb_fname_tmp = cp_smb_filename(talloc_tos(), full_fname);
346 TALLOC_FREE(full_fname);
347 if (smb_fname_tmp == NULL) {
348 errno = ENOMEM;
349 return -1;
352 smb_fname_tmp->base_name = cappath;
354 ret = SMB_VFS_NEXT_UNLINKAT(handle,
355 dirfsp->conn->cwd_fsp,
356 smb_fname_tmp,
357 flags);
359 TALLOC_FREE(smb_fname_tmp);
360 return ret;
363 static int cap_lchown(vfs_handle_struct *handle,
364 const struct smb_filename *smb_fname,
365 uid_t uid,
366 gid_t gid)
368 struct smb_filename *cap_smb_fname = NULL;
369 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
370 int ret;
371 int saved_errno;
373 if (!cappath) {
374 errno = ENOMEM;
375 return -1;
378 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
379 cappath,
380 NULL,
381 NULL,
382 smb_fname->twrp,
383 smb_fname->flags);
384 if (cap_smb_fname == NULL) {
385 TALLOC_FREE(cappath);
386 errno = ENOMEM;
387 return -1;
390 ret = SMB_VFS_NEXT_LCHOWN(handle, cap_smb_fname, uid, gid);
391 saved_errno = errno;
392 TALLOC_FREE(cappath);
393 TALLOC_FREE(cap_smb_fname);
394 errno = saved_errno;
395 return ret;
398 static int cap_chdir(vfs_handle_struct *handle,
399 const struct smb_filename *smb_fname)
401 struct smb_filename *cap_smb_fname = NULL;
402 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
403 int ret;
404 int saved_errno = 0;
406 if (!cappath) {
407 errno = ENOMEM;
408 return -1;
410 DEBUG(3,("cap: cap_chdir for %s\n", smb_fname->base_name));
412 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
413 cappath,
414 NULL,
415 NULL,
416 smb_fname->twrp,
417 smb_fname->flags);
418 if (cap_smb_fname == NULL) {
419 TALLOC_FREE(cappath);
420 errno = ENOMEM;
421 return -1;
423 ret = SMB_VFS_NEXT_CHDIR(handle, cap_smb_fname);
424 if (ret == -1) {
425 saved_errno = errno;
427 TALLOC_FREE(cappath);
428 TALLOC_FREE(cap_smb_fname);
429 if (saved_errno != 0) {
430 errno = saved_errno;
432 return ret;
435 static int cap_symlinkat(vfs_handle_struct *handle,
436 const struct smb_filename *link_contents,
437 struct files_struct *dirfsp,
438 const struct smb_filename *new_smb_fname)
440 struct smb_filename *full_fname = NULL;
441 char *capold = capencode(talloc_tos(), link_contents->base_name);
442 char *capnew = NULL;
443 struct smb_filename *new_link_target = NULL;
444 struct smb_filename *new_cap_smb_fname = NULL;
445 int saved_errno = 0;
446 int ret;
448 if (capold == NULL) {
449 errno = ENOMEM;
450 return -1;
453 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
454 dirfsp,
455 new_smb_fname);
456 if (full_fname == NULL) {
457 return -1;
460 capnew = capencode(talloc_tos(), full_fname->base_name);
461 if (!capnew) {
462 TALLOC_FREE(full_fname);
463 errno = ENOMEM;
464 return -1;
467 new_link_target = synthetic_smb_fname(talloc_tos(),
468 capold,
469 NULL,
470 NULL,
471 new_smb_fname->twrp,
472 new_smb_fname->flags);
473 if (new_link_target == NULL) {
474 TALLOC_FREE(full_fname);
475 TALLOC_FREE(capold);
476 TALLOC_FREE(capnew);
477 errno = ENOMEM;
478 return -1;
481 new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
482 capnew,
483 NULL,
484 NULL,
485 new_smb_fname->twrp,
486 new_smb_fname->flags);
487 if (new_cap_smb_fname == NULL) {
488 TALLOC_FREE(full_fname);
489 TALLOC_FREE(capold);
490 TALLOC_FREE(capnew);
491 TALLOC_FREE(new_link_target);
492 errno = ENOMEM;
493 return -1;
495 ret = SMB_VFS_NEXT_SYMLINKAT(handle,
496 new_link_target,
497 handle->conn->cwd_fsp,
498 new_cap_smb_fname);
499 if (ret == -1) {
500 saved_errno = errno;
502 TALLOC_FREE(full_fname);
503 TALLOC_FREE(capold);
504 TALLOC_FREE(capnew);
505 TALLOC_FREE(new_link_target);
506 TALLOC_FREE(new_cap_smb_fname);
507 if (saved_errno != 0) {
508 errno = saved_errno;
510 return ret;
513 static int cap_readlinkat(vfs_handle_struct *handle,
514 const struct files_struct *dirfsp,
515 const struct smb_filename *smb_fname,
516 char *buf,
517 size_t bufsiz)
519 struct smb_filename *full_fname = NULL;
520 struct smb_filename *cap_smb_fname = NULL;
521 char *cappath = NULL;
522 int saved_errno = 0;
523 int ret;
525 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
526 dirfsp,
527 smb_fname);
528 if (full_fname == NULL) {
529 return -1;
532 cappath = capencode(talloc_tos(), full_fname->base_name);
533 if (cappath == NULL) {
534 TALLOC_FREE(full_fname);
535 errno = ENOMEM;
536 return -1;
538 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
539 cappath,
540 NULL,
541 NULL,
542 smb_fname->twrp,
543 smb_fname->flags);
544 if (cap_smb_fname == NULL) {
545 TALLOC_FREE(full_fname);
546 TALLOC_FREE(cappath);
547 errno = ENOMEM;
548 return -1;
550 ret = SMB_VFS_NEXT_READLINKAT(handle,
551 handle->conn->cwd_fsp,
552 cap_smb_fname,
553 buf,
554 bufsiz);
555 if (ret == -1) {
556 saved_errno = errno;
558 TALLOC_FREE(full_fname);
559 TALLOC_FREE(cappath);
560 TALLOC_FREE(cap_smb_fname);
561 if (saved_errno != 0) {
562 errno = saved_errno;
564 return ret;
567 static int cap_linkat(vfs_handle_struct *handle,
568 files_struct *srcfsp,
569 const struct smb_filename *old_smb_fname,
570 files_struct *dstfsp,
571 const struct smb_filename *new_smb_fname,
572 int flags)
574 struct smb_filename *old_full_fname = NULL;
575 struct smb_filename *new_full_fname = NULL;
576 char *capold = NULL;
577 char *capnew = NULL;
578 struct smb_filename *old_cap_smb_fname = NULL;
579 struct smb_filename *new_cap_smb_fname = NULL;
580 int saved_errno = 0;
581 int ret;
583 /* Process 'old' name. */
584 old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
585 srcfsp,
586 old_smb_fname);
587 if (old_full_fname == NULL) {
588 goto nomem_out;
590 capold = capencode(talloc_tos(), old_full_fname->base_name);
591 if (capold == NULL) {
592 goto nomem_out;
594 TALLOC_FREE(old_full_fname);
595 old_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
596 capold,
597 NULL,
598 NULL,
599 old_smb_fname->twrp,
600 old_smb_fname->flags);
601 if (old_cap_smb_fname == NULL) {
602 goto nomem_out;
605 /* Process 'new' name. */
606 new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
607 dstfsp,
608 new_smb_fname);
609 if (new_full_fname == NULL) {
610 goto nomem_out;
612 capnew = capencode(talloc_tos(), new_full_fname->base_name);
613 if (capnew == NULL) {
614 goto nomem_out;
616 TALLOC_FREE(new_full_fname);
617 new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
618 capnew,
619 NULL,
620 NULL,
621 new_smb_fname->twrp,
622 new_smb_fname->flags);
623 if (new_cap_smb_fname == NULL) {
624 goto nomem_out;
627 ret = SMB_VFS_NEXT_LINKAT(handle,
628 handle->conn->cwd_fsp,
629 old_cap_smb_fname,
630 handle->conn->cwd_fsp,
631 new_cap_smb_fname,
632 flags);
633 if (ret == -1) {
634 saved_errno = errno;
636 TALLOC_FREE(old_full_fname);
637 TALLOC_FREE(old_full_fname);
638 TALLOC_FREE(capold);
639 TALLOC_FREE(capnew);
640 TALLOC_FREE(old_cap_smb_fname);
641 TALLOC_FREE(new_cap_smb_fname);
642 if (saved_errno != 0) {
643 errno = saved_errno;
645 return ret;
647 nomem_out:
649 TALLOC_FREE(old_full_fname);
650 TALLOC_FREE(old_full_fname);
651 TALLOC_FREE(capold);
652 TALLOC_FREE(capnew);
653 TALLOC_FREE(old_cap_smb_fname);
654 TALLOC_FREE(new_cap_smb_fname);
655 errno = ENOMEM;
656 return -1;
659 static int cap_mknodat(vfs_handle_struct *handle,
660 files_struct *dirfsp,
661 const struct smb_filename *smb_fname,
662 mode_t mode,
663 SMB_DEV_T dev)
665 struct smb_filename *full_fname = NULL;
666 struct smb_filename *cap_smb_fname = NULL;
667 char *cappath = NULL;
668 int ret;
669 int saved_errno = 0;
671 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
672 dirfsp,
673 smb_fname);
674 if (full_fname == NULL) {
675 return -1;
678 cappath = capencode(talloc_tos(), full_fname->base_name);
679 if (!cappath) {
680 TALLOC_FREE(full_fname);
681 errno = ENOMEM;
682 return -1;
684 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
685 cappath,
686 NULL,
687 NULL,
688 smb_fname->twrp,
689 smb_fname->flags);
690 if (cap_smb_fname == NULL) {
691 TALLOC_FREE(full_fname);
692 TALLOC_FREE(cappath);
693 errno = ENOMEM;
694 return -1;
696 ret = SMB_VFS_NEXT_MKNODAT(handle,
697 handle->conn->cwd_fsp,
698 cap_smb_fname,
699 mode,
700 dev);
701 if (ret == -1) {
702 saved_errno = errno;
704 TALLOC_FREE(full_fname);
705 TALLOC_FREE(cappath);
706 TALLOC_FREE(cap_smb_fname);
707 if (saved_errno != 0) {
708 errno = saved_errno;
710 return ret;
713 static struct smb_filename *cap_realpath(vfs_handle_struct *handle,
714 TALLOC_CTX *ctx,
715 const struct smb_filename *smb_fname)
717 /* monyo need capencode'ed and capdecode'ed? */
718 struct smb_filename *cap_smb_fname = NULL;
719 struct smb_filename *return_fname = NULL;
720 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
721 int saved_errno = 0;
723 if (!cappath) {
724 errno = ENOMEM;
725 return NULL;
727 cap_smb_fname = synthetic_smb_fname(ctx,
728 cappath,
729 NULL,
730 NULL,
731 smb_fname->twrp,
732 smb_fname->flags);
733 if (cap_smb_fname == NULL) {
734 TALLOC_FREE(cappath);
735 errno = ENOMEM;
736 return NULL;
738 return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname);
739 if (return_fname == NULL) {
740 saved_errno = errno;
742 TALLOC_FREE(cappath);
743 TALLOC_FREE(cap_smb_fname);
744 if (saved_errno != 0) {
745 errno = saved_errno;
747 return return_fname;
750 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
752 char *cappath = capencode(talloc_tos(), path);
754 if (!cappath) {
755 errno = ENOMEM;
756 return -1;
758 return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
761 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
763 char *cappath = capencode(talloc_tos(), path);
765 if (!cappath) {
766 errno = ENOMEM;
767 return -1;
769 return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
772 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
774 char *cappath = capencode(talloc_tos(), path);
776 if (!cappath) {
777 errno = ENOMEM;
778 return -1;
780 return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
783 static NTSTATUS cap_create_dfs_pathat(vfs_handle_struct *handle,
784 files_struct *dirfsp,
785 const struct smb_filename *smb_fname,
786 const struct referral *reflist,
787 size_t referral_count)
789 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
790 struct smb_filename *cap_smb_fname = NULL;
791 NTSTATUS status;
793 if (cappath == NULL) {
794 return NT_STATUS_NO_MEMORY;
796 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
797 cappath,
798 NULL,
799 NULL,
800 smb_fname->twrp,
801 smb_fname->flags);
802 if (cap_smb_fname == NULL) {
803 TALLOC_FREE(cappath);
804 return NT_STATUS_NO_MEMORY;
806 status = SMB_VFS_NEXT_CREATE_DFS_PATHAT(handle,
807 dirfsp,
808 cap_smb_fname,
809 reflist,
810 referral_count);
811 TALLOC_FREE(cappath);
812 TALLOC_FREE(cap_smb_fname);
813 return status;
816 static NTSTATUS cap_read_dfs_pathat(struct vfs_handle_struct *handle,
817 TALLOC_CTX *mem_ctx,
818 struct files_struct *dirfsp,
819 struct smb_filename *smb_fname,
820 struct referral **ppreflist,
821 size_t *preferral_count)
823 struct smb_filename *full_fname = NULL;
824 struct smb_filename *cap_smb_fname = NULL;
825 char *cappath = NULL;
826 NTSTATUS status;
828 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
829 dirfsp,
830 smb_fname);
831 if (full_fname == NULL) {
832 return NT_STATUS_NO_MEMORY;
834 cappath = capencode(talloc_tos(), full_fname->base_name);
835 if (cappath == NULL) {
836 TALLOC_FREE(full_fname);
837 return NT_STATUS_NO_MEMORY;
839 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
840 cappath,
841 NULL,
842 NULL,
843 smb_fname->twrp,
844 smb_fname->flags);
845 if (cap_smb_fname == NULL) {
846 TALLOC_FREE(full_fname);
847 TALLOC_FREE(cappath);
848 return NT_STATUS_NO_MEMORY;
851 status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
852 mem_ctx,
853 handle->conn->cwd_fsp,
854 cap_smb_fname,
855 ppreflist,
856 preferral_count);
858 if (NT_STATUS_IS_OK(status)) {
859 /* Return any stat(2) info. */
860 smb_fname->st = cap_smb_fname->st;
863 TALLOC_FREE(full_fname);
864 TALLOC_FREE(cappath);
865 TALLOC_FREE(cap_smb_fname);
866 return status;
869 static struct vfs_fn_pointers vfs_cap_fns = {
870 .disk_free_fn = cap_disk_free,
871 .get_quota_fn = cap_get_quota,
872 .readdir_fn = cap_readdir,
873 .mkdirat_fn = cap_mkdirat,
874 .openat_fn = cap_openat,
875 .renameat_fn = cap_renameat,
876 .stat_fn = cap_stat,
877 .lstat_fn = cap_lstat,
878 .unlinkat_fn = cap_unlinkat,
879 .lchown_fn = cap_lchown,
880 .chdir_fn = cap_chdir,
881 .symlinkat_fn = cap_symlinkat,
882 .readlinkat_fn = cap_readlinkat,
883 .linkat_fn = cap_linkat,
884 .mknodat_fn = cap_mknodat,
885 .realpath_fn = cap_realpath,
886 .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
887 .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
888 .fgetxattr_fn = cap_fgetxattr,
889 .fremovexattr_fn = cap_fremovexattr,
890 .fsetxattr_fn = cap_fsetxattr,
891 .create_dfs_pathat_fn = cap_create_dfs_pathat,
892 .read_dfs_pathat_fn = cap_read_dfs_pathat
895 static_decl_vfs;
896 NTSTATUS vfs_cap_init(TALLOC_CTX *ctx)
898 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap",
899 &vfs_cap_fns);
902 /* For CAP functions */
903 #define hex_tag ':'
904 #define is_hex(s) ((s)[0] == hex_tag)
906 /*******************************************************************
907 original code -> ":xx" - CAP format
908 ********************************************************************/
910 static char *capencode(TALLOC_CTX *ctx, const char *from)
912 char *out = NULL;
913 const char *p1;
914 char *to = NULL;
915 size_t len = 0;
917 for (p1 = from; *p1; p1++) {
918 if ((unsigned char)*p1 >= 0x80) {
919 len += 3;
920 } else {
921 len++;
924 len++;
926 to = talloc_array(ctx, char, len);
927 if (!to) {
928 return NULL;
931 for (out = to; *from;) {
932 /* buffer husoku error */
933 if ((unsigned char)*from >= 0x80) {
934 *out++ = hex_tag;
935 *out++ = nybble_to_hex_lower(((*from) >> 4));
936 *out++ = nybble_to_hex_lower(*from);
937 from++;
938 } else {
939 *out++ = *from++;
942 *out = '\0';
943 return to;
946 /*******************************************************************
947 CAP -> original code
948 ********************************************************************/
949 /* ":xx" -> a byte */
951 static char *capdecode(TALLOC_CTX *ctx, const char *from)
953 const char *p1;
954 char *out = NULL;
955 char *to = NULL;
956 size_t len = 0;
958 for (p1 = from; *p1; len++) {
959 if (is_hex(p1)) {
960 p1 += 3;
961 } else {
962 p1++;
965 len++;
967 to = talloc_array(ctx, char, len);
968 if (!to) {
969 return NULL;
972 for (out = to; *from;) {
973 if (is_hex(from)) {
974 (void)hex_byte(&from[1], (uint8_t *)(out++));
975 from += 3;
976 } else {
977 *out++ = *from++;
980 *out = '\0';
981 return to;