ctdb-recoverd: Update the local node map before pushing out flags
[samba.git] / source3 / modules / vfs_cap.c
blob4a47b26c7b9a842620fed618292b9b8cd53547a7
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 *cap_readdir(vfs_handle_struct *handle,
88 struct files_struct *dirfsp,
89 DIR *dirp,
90 SMB_STRUCT_STAT *sbuf)
92 struct dirent *result;
93 struct dirent *newdirent;
94 char *newname;
95 size_t newnamelen;
96 DEBUG(3,("cap: cap_readdir\n"));
98 result = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, NULL);
99 if (!result) {
100 return NULL;
103 newname = capdecode(talloc_tos(), result->d_name);
104 if (!newname) {
105 return NULL;
107 DEBUG(3,("cap: cap_readdir: %s\n", newname));
108 newnamelen = strlen(newname)+1;
109 newdirent = talloc_size(
110 talloc_tos(), sizeof(struct dirent) + newnamelen);
111 if (!newdirent) {
112 return NULL;
114 talloc_set_name_const(newdirent, "struct dirent");
115 memcpy(newdirent, result, sizeof(struct dirent));
116 memcpy(&newdirent->d_name, newname, newnamelen);
117 return newdirent;
120 static int cap_mkdirat(vfs_handle_struct *handle,
121 struct files_struct *dirfsp,
122 const struct smb_filename *smb_fname,
123 mode_t mode)
125 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
126 struct smb_filename *cap_smb_fname = NULL;
128 if (!cappath) {
129 errno = ENOMEM;
130 return -1;
133 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
134 cappath,
135 NULL,
136 NULL,
137 smb_fname->twrp,
138 smb_fname->flags);
139 if (cap_smb_fname == NULL) {
140 TALLOC_FREE(cappath);
141 errno = ENOMEM;
142 return -1;
145 return SMB_VFS_NEXT_MKDIRAT(handle,
146 dirfsp,
147 cap_smb_fname,
148 mode);
151 static int cap_openat(vfs_handle_struct *handle,
152 const struct files_struct *dirfsp,
153 const struct smb_filename *smb_fname_in,
154 files_struct *fsp,
155 int flags,
156 mode_t mode)
158 char *cappath = NULL;
159 struct smb_filename *smb_fname = NULL;
160 int ret;
161 int saved_errno = 0;
163 cappath = capencode(talloc_tos(), smb_fname_in->base_name);
164 if (cappath == NULL) {
165 errno = ENOMEM;
166 return -1;
169 smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
170 if (smb_fname == NULL) {
171 TALLOC_FREE(cappath);
172 errno = ENOMEM;
173 return -1;
175 smb_fname->base_name = cappath;
177 DBG_DEBUG("cap_open for %s\n", smb_fname_str_dbg(smb_fname));
178 ret = SMB_VFS_NEXT_OPENAT(handle,
179 dirfsp,
180 smb_fname,
181 fsp,
182 flags,
183 mode);
185 if (ret == -1) {
186 saved_errno = errno;
188 TALLOC_FREE(cappath);
189 TALLOC_FREE(smb_fname);
190 if (saved_errno != 0) {
191 errno = saved_errno;
193 return ret;
196 static int cap_renameat(vfs_handle_struct *handle,
197 files_struct *srcfsp,
198 const struct smb_filename *smb_fname_src,
199 files_struct *dstfsp,
200 const struct smb_filename *smb_fname_dst)
202 char *capold = NULL;
203 char *capnew = NULL;
204 struct smb_filename *smb_fname_src_tmp = NULL;
205 struct smb_filename *smb_fname_dst_tmp = NULL;
206 struct smb_filename *full_fname_src = NULL;
207 struct smb_filename *full_fname_dst = NULL;
208 int ret = -1;
209 int saved_errno = 0;
211 full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
212 srcfsp,
213 smb_fname_src);
214 if (full_fname_src == NULL) {
215 errno = ENOMEM;
216 goto out;
219 full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
220 dstfsp,
221 smb_fname_dst);
222 if (full_fname_dst == NULL) {
223 errno = ENOMEM;
224 goto out;
227 capold = capencode(talloc_tos(), full_fname_src->base_name);
228 capnew = capencode(talloc_tos(), full_fname_dst->base_name);
229 if (!capold || !capnew) {
230 errno = ENOMEM;
231 goto out;
234 /* Setup temporary smb_filename structs. */
235 smb_fname_src_tmp = cp_smb_filename(talloc_tos(), full_fname_src);
236 if (smb_fname_src_tmp == NULL) {
237 errno = ENOMEM;
238 goto out;
240 smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), full_fname_dst);
241 if (smb_fname_dst_tmp == NULL) {
242 errno = ENOMEM;
243 goto out;
246 smb_fname_src_tmp->base_name = capold;
247 smb_fname_dst_tmp->base_name = capnew;
249 ret = SMB_VFS_NEXT_RENAMEAT(handle,
250 srcfsp->conn->cwd_fsp,
251 smb_fname_src_tmp,
252 dstfsp->conn->cwd_fsp,
253 smb_fname_dst_tmp);
255 out:
257 if (ret != 0) {
258 saved_errno = errno;
261 TALLOC_FREE(full_fname_src);
262 TALLOC_FREE(full_fname_dst);
263 TALLOC_FREE(capold);
264 TALLOC_FREE(capnew);
265 TALLOC_FREE(smb_fname_src_tmp);
266 TALLOC_FREE(smb_fname_dst_tmp);
268 if (ret != 0) {
269 errno = saved_errno;
272 return ret;
275 static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
277 char *cappath;
278 char *tmp_base_name = NULL;
279 int ret;
281 cappath = capencode(talloc_tos(), smb_fname->base_name);
283 if (!cappath) {
284 errno = ENOMEM;
285 return -1;
288 tmp_base_name = smb_fname->base_name;
289 smb_fname->base_name = cappath;
291 ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
293 smb_fname->base_name = tmp_base_name;
294 TALLOC_FREE(cappath);
296 return ret;
299 static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
301 char *cappath;
302 char *tmp_base_name = NULL;
303 int ret;
305 cappath = capencode(talloc_tos(), smb_fname->base_name);
307 if (!cappath) {
308 errno = ENOMEM;
309 return -1;
312 tmp_base_name = smb_fname->base_name;
313 smb_fname->base_name = cappath;
315 ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
317 smb_fname->base_name = tmp_base_name;
318 TALLOC_FREE(cappath);
320 return ret;
323 static int cap_unlinkat(vfs_handle_struct *handle,
324 struct files_struct *dirfsp,
325 const struct smb_filename *smb_fname,
326 int flags)
328 struct smb_filename *full_fname = NULL;
329 struct smb_filename *smb_fname_tmp = NULL;
330 char *cappath = NULL;
331 int ret;
333 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
334 dirfsp,
335 smb_fname);
336 if (full_fname == NULL) {
337 return -1;
340 cappath = capencode(talloc_tos(), full_fname->base_name);
341 if (!cappath) {
342 TALLOC_FREE(full_fname);
343 errno = ENOMEM;
344 return -1;
347 /* Setup temporary smb_filename structs. */
348 smb_fname_tmp = cp_smb_filename(talloc_tos(), full_fname);
349 TALLOC_FREE(full_fname);
350 if (smb_fname_tmp == NULL) {
351 errno = ENOMEM;
352 return -1;
355 smb_fname_tmp->base_name = cappath;
357 ret = SMB_VFS_NEXT_UNLINKAT(handle,
358 dirfsp->conn->cwd_fsp,
359 smb_fname_tmp,
360 flags);
362 TALLOC_FREE(smb_fname_tmp);
363 return ret;
366 static int cap_lchown(vfs_handle_struct *handle,
367 const struct smb_filename *smb_fname,
368 uid_t uid,
369 gid_t gid)
371 struct smb_filename *cap_smb_fname = NULL;
372 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
373 int ret;
374 int saved_errno;
376 if (!cappath) {
377 errno = ENOMEM;
378 return -1;
381 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
382 cappath,
383 NULL,
384 NULL,
385 smb_fname->twrp,
386 smb_fname->flags);
387 if (cap_smb_fname == NULL) {
388 TALLOC_FREE(cappath);
389 errno = ENOMEM;
390 return -1;
393 ret = SMB_VFS_NEXT_LCHOWN(handle, cap_smb_fname, uid, gid);
394 saved_errno = errno;
395 TALLOC_FREE(cappath);
396 TALLOC_FREE(cap_smb_fname);
397 errno = saved_errno;
398 return ret;
401 static int cap_chdir(vfs_handle_struct *handle,
402 const struct smb_filename *smb_fname)
404 struct smb_filename *cap_smb_fname = NULL;
405 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
406 int ret;
407 int saved_errno = 0;
409 if (!cappath) {
410 errno = ENOMEM;
411 return -1;
413 DEBUG(3,("cap: cap_chdir for %s\n", smb_fname->base_name));
415 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
416 cappath,
417 NULL,
418 NULL,
419 smb_fname->twrp,
420 smb_fname->flags);
421 if (cap_smb_fname == NULL) {
422 TALLOC_FREE(cappath);
423 errno = ENOMEM;
424 return -1;
426 ret = SMB_VFS_NEXT_CHDIR(handle, cap_smb_fname);
427 if (ret == -1) {
428 saved_errno = errno;
430 TALLOC_FREE(cappath);
431 TALLOC_FREE(cap_smb_fname);
432 if (saved_errno != 0) {
433 errno = saved_errno;
435 return ret;
438 static int cap_symlinkat(vfs_handle_struct *handle,
439 const struct smb_filename *link_contents,
440 struct files_struct *dirfsp,
441 const struct smb_filename *new_smb_fname)
443 struct smb_filename *full_fname = NULL;
444 char *capold = capencode(talloc_tos(), link_contents->base_name);
445 char *capnew = NULL;
446 struct smb_filename *new_link_target = NULL;
447 struct smb_filename *new_cap_smb_fname = NULL;
448 int saved_errno = 0;
449 int ret;
451 if (!capold || !capnew) {
452 errno = ENOMEM;
453 return -1;
456 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
457 dirfsp,
458 new_smb_fname);
459 if (full_fname == NULL) {
460 return -1;
463 capnew = capencode(talloc_tos(), full_fname->base_name);
464 if (!capnew) {
465 TALLOC_FREE(full_fname);
466 errno = ENOMEM;
467 return -1;
470 new_link_target = synthetic_smb_fname(talloc_tos(),
471 capold,
472 NULL,
473 NULL,
474 new_smb_fname->twrp,
475 new_smb_fname->flags);
476 if (new_link_target == NULL) {
477 TALLOC_FREE(full_fname);
478 TALLOC_FREE(capold);
479 TALLOC_FREE(capnew);
480 errno = ENOMEM;
481 return -1;
484 new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
485 capnew,
486 NULL,
487 NULL,
488 new_smb_fname->twrp,
489 new_smb_fname->flags);
490 if (new_cap_smb_fname == NULL) {
491 TALLOC_FREE(full_fname);
492 TALLOC_FREE(capold);
493 TALLOC_FREE(capnew);
494 TALLOC_FREE(new_link_target);
495 errno = ENOMEM;
496 return -1;
498 ret = SMB_VFS_NEXT_SYMLINKAT(handle,
499 new_link_target,
500 handle->conn->cwd_fsp,
501 new_cap_smb_fname);
502 if (ret == -1) {
503 saved_errno = errno;
505 TALLOC_FREE(full_fname);
506 TALLOC_FREE(capold);
507 TALLOC_FREE(capnew);
508 TALLOC_FREE(new_link_target);
509 TALLOC_FREE(new_cap_smb_fname);
510 if (saved_errno != 0) {
511 errno = saved_errno;
513 return ret;
516 static int cap_readlinkat(vfs_handle_struct *handle,
517 const struct files_struct *dirfsp,
518 const struct smb_filename *smb_fname,
519 char *buf,
520 size_t bufsiz)
522 struct smb_filename *full_fname = NULL;
523 struct smb_filename *cap_smb_fname = NULL;
524 char *cappath = NULL;
525 int saved_errno = 0;
526 int ret;
528 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
529 dirfsp,
530 smb_fname);
531 if (full_fname == NULL) {
532 return -1;
535 cappath = capencode(talloc_tos(), full_fname->base_name);
536 if (cappath == NULL) {
537 TALLOC_FREE(full_fname);
538 errno = ENOMEM;
539 return -1;
541 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
542 cappath,
543 NULL,
544 NULL,
545 smb_fname->twrp,
546 smb_fname->flags);
547 if (cap_smb_fname == NULL) {
548 TALLOC_FREE(full_fname);
549 TALLOC_FREE(cappath);
550 errno = ENOMEM;
551 return -1;
553 ret = SMB_VFS_NEXT_READLINKAT(handle,
554 handle->conn->cwd_fsp,
555 cap_smb_fname,
556 buf,
557 bufsiz);
558 if (ret == -1) {
559 saved_errno = errno;
561 TALLOC_FREE(full_fname);
562 TALLOC_FREE(cappath);
563 TALLOC_FREE(cap_smb_fname);
564 if (saved_errno != 0) {
565 errno = saved_errno;
567 return ret;
570 static int cap_linkat(vfs_handle_struct *handle,
571 files_struct *srcfsp,
572 const struct smb_filename *old_smb_fname,
573 files_struct *dstfsp,
574 const struct smb_filename *new_smb_fname,
575 int flags)
577 struct smb_filename *old_full_fname = NULL;
578 struct smb_filename *new_full_fname = NULL;
579 char *capold = NULL;
580 char *capnew = NULL;
581 struct smb_filename *old_cap_smb_fname = NULL;
582 struct smb_filename *new_cap_smb_fname = NULL;
583 int saved_errno = 0;
584 int ret;
586 /* Process 'old' name. */
587 old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
588 srcfsp,
589 old_smb_fname);
590 if (old_full_fname == NULL) {
591 goto nomem_out;
593 capold = capencode(talloc_tos(), old_full_fname->base_name);
594 if (capold == NULL) {
595 goto nomem_out;
597 TALLOC_FREE(old_full_fname);
598 old_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
599 capold,
600 NULL,
601 NULL,
602 old_smb_fname->twrp,
603 old_smb_fname->flags);
604 if (old_cap_smb_fname == NULL) {
605 goto nomem_out;
608 /* Process 'new' name. */
609 new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
610 dstfsp,
611 new_smb_fname);
612 if (new_full_fname == NULL) {
613 goto nomem_out;
615 capnew = capencode(talloc_tos(), new_full_fname->base_name);
616 if (capnew == NULL) {
617 goto nomem_out;
619 TALLOC_FREE(new_full_fname);
620 new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
621 capnew,
622 NULL,
623 NULL,
624 new_smb_fname->twrp,
625 new_smb_fname->flags);
626 if (new_cap_smb_fname == NULL) {
627 goto nomem_out;
630 ret = SMB_VFS_NEXT_LINKAT(handle,
631 handle->conn->cwd_fsp,
632 old_cap_smb_fname,
633 handle->conn->cwd_fsp,
634 new_cap_smb_fname,
635 flags);
636 if (ret == -1) {
637 saved_errno = errno;
639 TALLOC_FREE(old_full_fname);
640 TALLOC_FREE(old_full_fname);
641 TALLOC_FREE(capold);
642 TALLOC_FREE(capnew);
643 TALLOC_FREE(old_cap_smb_fname);
644 TALLOC_FREE(new_cap_smb_fname);
645 if (saved_errno != 0) {
646 errno = saved_errno;
648 return ret;
650 nomem_out:
652 TALLOC_FREE(old_full_fname);
653 TALLOC_FREE(old_full_fname);
654 TALLOC_FREE(capold);
655 TALLOC_FREE(capnew);
656 TALLOC_FREE(old_cap_smb_fname);
657 TALLOC_FREE(new_cap_smb_fname);
658 errno = ENOMEM;
659 return -1;
662 static int cap_mknodat(vfs_handle_struct *handle,
663 files_struct *dirfsp,
664 const struct smb_filename *smb_fname,
665 mode_t mode,
666 SMB_DEV_T dev)
668 struct smb_filename *full_fname = NULL;
669 struct smb_filename *cap_smb_fname = NULL;
670 char *cappath = NULL;
671 int ret;
672 int saved_errno = 0;
674 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
675 dirfsp,
676 smb_fname);
677 if (full_fname == NULL) {
678 return -1;
681 cappath = capencode(talloc_tos(), full_fname->base_name);
682 if (!cappath) {
683 TALLOC_FREE(full_fname);
684 errno = ENOMEM;
685 return -1;
687 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
688 cappath,
689 NULL,
690 NULL,
691 smb_fname->twrp,
692 smb_fname->flags);
693 if (cap_smb_fname == NULL) {
694 TALLOC_FREE(full_fname);
695 TALLOC_FREE(cappath);
696 errno = ENOMEM;
697 return -1;
699 ret = SMB_VFS_NEXT_MKNODAT(handle,
700 handle->conn->cwd_fsp,
701 cap_smb_fname,
702 mode,
703 dev);
704 if (ret == -1) {
705 saved_errno = errno;
707 TALLOC_FREE(full_fname);
708 TALLOC_FREE(cappath);
709 TALLOC_FREE(cap_smb_fname);
710 if (saved_errno != 0) {
711 errno = saved_errno;
713 return ret;
716 static struct smb_filename *cap_realpath(vfs_handle_struct *handle,
717 TALLOC_CTX *ctx,
718 const struct smb_filename *smb_fname)
720 /* monyo need capencode'ed and capdecode'ed? */
721 struct smb_filename *cap_smb_fname = NULL;
722 struct smb_filename *return_fname = NULL;
723 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
724 int saved_errno = 0;
726 if (!cappath) {
727 errno = ENOMEM;
728 return NULL;
730 cap_smb_fname = synthetic_smb_fname(ctx,
731 cappath,
732 NULL,
733 NULL,
734 smb_fname->twrp,
735 smb_fname->flags);
736 if (cap_smb_fname == NULL) {
737 TALLOC_FREE(cappath);
738 errno = ENOMEM;
739 return NULL;
741 return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname);
742 if (return_fname == NULL) {
743 saved_errno = errno;
745 TALLOC_FREE(cappath);
746 TALLOC_FREE(cap_smb_fname);
747 if (saved_errno != 0) {
748 errno = saved_errno;
750 return return_fname;
753 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
755 char *cappath = capencode(talloc_tos(), path);
757 if (!cappath) {
758 errno = ENOMEM;
759 return -1;
761 return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
764 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
766 char *cappath = capencode(talloc_tos(), path);
768 if (!cappath) {
769 errno = ENOMEM;
770 return -1;
772 return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
775 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
777 char *cappath = capencode(talloc_tos(), path);
779 if (!cappath) {
780 errno = ENOMEM;
781 return -1;
783 return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
786 static NTSTATUS cap_create_dfs_pathat(vfs_handle_struct *handle,
787 files_struct *dirfsp,
788 const struct smb_filename *smb_fname,
789 const struct referral *reflist,
790 size_t referral_count)
792 char *cappath = capencode(talloc_tos(), smb_fname->base_name);
793 struct smb_filename *cap_smb_fname = NULL;
794 NTSTATUS status;
796 if (cappath == NULL) {
797 return NT_STATUS_NO_MEMORY;
799 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
800 cappath,
801 NULL,
802 NULL,
803 smb_fname->twrp,
804 smb_fname->flags);
805 if (cap_smb_fname == NULL) {
806 TALLOC_FREE(cappath);
807 return NT_STATUS_NO_MEMORY;
809 status = SMB_VFS_NEXT_CREATE_DFS_PATHAT(handle,
810 dirfsp,
811 cap_smb_fname,
812 reflist,
813 referral_count);
814 TALLOC_FREE(cappath);
815 TALLOC_FREE(cap_smb_fname);
816 return status;
819 static NTSTATUS cap_read_dfs_pathat(struct vfs_handle_struct *handle,
820 TALLOC_CTX *mem_ctx,
821 struct files_struct *dirfsp,
822 struct smb_filename *smb_fname,
823 struct referral **ppreflist,
824 size_t *preferral_count)
826 struct smb_filename *full_fname = NULL;
827 struct smb_filename *cap_smb_fname = NULL;
828 char *cappath = NULL;
829 NTSTATUS status;
831 full_fname = full_path_from_dirfsp_atname(talloc_tos(),
832 dirfsp,
833 smb_fname);
834 if (full_fname == NULL) {
835 return NT_STATUS_NO_MEMORY;
837 cappath = capencode(talloc_tos(), full_fname->base_name);
838 if (cappath == NULL) {
839 TALLOC_FREE(full_fname);
840 return NT_STATUS_NO_MEMORY;
842 cap_smb_fname = synthetic_smb_fname(talloc_tos(),
843 cappath,
844 NULL,
845 NULL,
846 smb_fname->twrp,
847 smb_fname->flags);
848 if (cap_smb_fname == NULL) {
849 TALLOC_FREE(full_fname);
850 TALLOC_FREE(cappath);
851 return NT_STATUS_NO_MEMORY;
854 status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
855 mem_ctx,
856 handle->conn->cwd_fsp,
857 cap_smb_fname,
858 ppreflist,
859 preferral_count);
861 if (NT_STATUS_IS_OK(status)) {
862 /* Return any stat(2) info. */
863 smb_fname->st = cap_smb_fname->st;
866 TALLOC_FREE(full_fname);
867 TALLOC_FREE(cappath);
868 TALLOC_FREE(cap_smb_fname);
869 return status;
872 static struct vfs_fn_pointers vfs_cap_fns = {
873 .disk_free_fn = cap_disk_free,
874 .get_quota_fn = cap_get_quota,
875 .readdir_fn = cap_readdir,
876 .mkdirat_fn = cap_mkdirat,
877 .openat_fn = cap_openat,
878 .renameat_fn = cap_renameat,
879 .stat_fn = cap_stat,
880 .lstat_fn = cap_lstat,
881 .unlinkat_fn = cap_unlinkat,
882 .lchown_fn = cap_lchown,
883 .chdir_fn = cap_chdir,
884 .symlinkat_fn = cap_symlinkat,
885 .readlinkat_fn = cap_readlinkat,
886 .linkat_fn = cap_linkat,
887 .mknodat_fn = cap_mknodat,
888 .realpath_fn = cap_realpath,
889 .getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
890 .getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
891 .fgetxattr_fn = cap_fgetxattr,
892 .fremovexattr_fn = cap_fremovexattr,
893 .fsetxattr_fn = cap_fsetxattr,
894 .create_dfs_pathat_fn = cap_create_dfs_pathat,
895 .read_dfs_pathat_fn = cap_read_dfs_pathat
898 static_decl_vfs;
899 NTSTATUS vfs_cap_init(TALLOC_CTX *ctx)
901 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap",
902 &vfs_cap_fns);
905 /* For CAP functions */
906 #define hex_tag ':'
907 #define hex2bin(c) hex2bin_table[(unsigned char)(c)]
908 #define bin2hex(c) bin2hex_table[(unsigned char)(c)]
909 #define is_hex(s) ((s)[0] == hex_tag)
911 static unsigned char hex2bin_table[256] = {
912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
915 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
916 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
917 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
918 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
919 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
920 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
921 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
922 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
923 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
924 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
925 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
926 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
927 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
928 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 */
931 static unsigned char bin2hex_table[256] = "0123456789abcdef";
933 /*******************************************************************
934 original code -> ":xx" - CAP format
935 ********************************************************************/
937 static char *capencode(TALLOC_CTX *ctx, const char *from)
939 char *out = NULL;
940 const char *p1;
941 char *to = NULL;
942 size_t len = 0;
944 for (p1 = from; *p1; p1++) {
945 if ((unsigned char)*p1 >= 0x80) {
946 len += 3;
947 } else {
948 len++;
951 len++;
953 to = talloc_array(ctx, char, len);
954 if (!to) {
955 return NULL;
958 for (out = to; *from;) {
959 /* buffer husoku error */
960 if ((unsigned char)*from >= 0x80) {
961 *out++ = hex_tag;
962 *out++ = bin2hex (((*from)>>4)&0x0f);
963 *out++ = bin2hex ((*from)&0x0f);
964 from++;
965 } else {
966 *out++ = *from++;
969 *out = '\0';
970 return to;
973 /*******************************************************************
974 CAP -> original code
975 ********************************************************************/
976 /* ":xx" -> a byte */
978 static char *capdecode(TALLOC_CTX *ctx, const char *from)
980 const char *p1;
981 char *out = NULL;
982 char *to = NULL;
983 size_t len = 0;
985 for (p1 = from; *p1; len++) {
986 if (is_hex(p1)) {
987 p1 += 3;
988 } else {
989 p1++;
992 len++;
994 to = talloc_array(ctx, char, len);
995 if (!to) {
996 return NULL;
999 for (out = to; *from;) {
1000 if (is_hex(from)) {
1001 *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
1002 from += 3;
1003 } else {
1004 *out++ = *from++;
1007 *out = '\0';
1008 return to;