smbd: reject FILE_ATTRIBUTE_TEMPORARY on directories
[Samba.git] / source3 / modules / vfs_cap.c
blobac2c1b0410d85dffdeabe8c3fbf5a929a492b98b
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 const struct vfs_open_how *how)
157 char *cappath = NULL;
158 struct smb_filename *smb_fname = NULL;
159 int ret;
160 int saved_errno = 0;
162 cappath = capencode(talloc_tos(), smb_fname_in->base_name);
163 if (cappath == NULL) {
164 errno = ENOMEM;
165 return -1;
168 smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
169 if (smb_fname == NULL) {
170 TALLOC_FREE(cappath);
171 errno = ENOMEM;
172 return -1;
174 smb_fname->base_name = cappath;
176 DBG_DEBUG("cap_open for %s\n", smb_fname_str_dbg(smb_fname));
177 ret = SMB_VFS_NEXT_OPENAT(handle,
178 dirfsp,
179 smb_fname,
180 fsp,
181 how);
182 if (ret == -1) {
183 saved_errno = errno;
185 TALLOC_FREE(cappath);
186 TALLOC_FREE(smb_fname);
187 if (saved_errno != 0) {
188 errno = saved_errno;
190 return ret;
193 static int cap_renameat(vfs_handle_struct *handle,
194 files_struct *srcfsp,
195 const struct smb_filename *smb_fname_src,
196 files_struct *dstfsp,
197 const struct smb_filename *smb_fname_dst)
199 char *capold = NULL;
200 char *capnew = NULL;
201 struct smb_filename *smb_fname_src_tmp = NULL;
202 struct smb_filename *smb_fname_dst_tmp = NULL;
203 struct smb_filename *full_fname_src = NULL;
204 struct smb_filename *full_fname_dst = NULL;
205 int ret = -1;
206 int saved_errno = 0;
208 full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
209 srcfsp,
210 smb_fname_src);
211 if (full_fname_src == NULL) {
212 errno = ENOMEM;
213 goto out;
216 full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
217 dstfsp,
218 smb_fname_dst);
219 if (full_fname_dst == NULL) {
220 errno = ENOMEM;
221 goto out;
224 capold = capencode(talloc_tos(), full_fname_src->base_name);
225 capnew = capencode(talloc_tos(), full_fname_dst->base_name);
226 if (!capold || !capnew) {
227 errno = ENOMEM;
228 goto out;
231 /* Setup temporary smb_filename structs. */
232 smb_fname_src_tmp = cp_smb_filename(talloc_tos(), full_fname_src);
233 if (smb_fname_src_tmp == NULL) {
234 errno = ENOMEM;
235 goto out;
237 smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), full_fname_dst);
238 if (smb_fname_dst_tmp == NULL) {
239 errno = ENOMEM;
240 goto out;
243 smb_fname_src_tmp->base_name = capold;
244 smb_fname_dst_tmp->base_name = capnew;
246 ret = SMB_VFS_NEXT_RENAMEAT(handle,
247 srcfsp->conn->cwd_fsp,
248 smb_fname_src_tmp,
249 dstfsp->conn->cwd_fsp,
250 smb_fname_dst_tmp);
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 hex2bin(c) hex2bin_table[(unsigned char)(c)]
905 #define bin2hex(c) bin2hex_table[(unsigned char)(c)]
906 #define is_hex(s) ((s)[0] == hex_tag)
908 static unsigned char hex2bin_table[256] = {
909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
912 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
913 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
914 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
915 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
916 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
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, /* 0x70 */
919 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
920 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
921 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
922 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
923 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
924 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
925 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
926 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 */
928 static unsigned char bin2hex_table[256] = "0123456789abcdef";
930 /*******************************************************************
931 original code -> ":xx" - CAP format
932 ********************************************************************/
934 static char *capencode(TALLOC_CTX *ctx, const char *from)
936 char *out = NULL;
937 const char *p1;
938 char *to = NULL;
939 size_t len = 0;
941 for (p1 = from; *p1; p1++) {
942 if ((unsigned char)*p1 >= 0x80) {
943 len += 3;
944 } else {
945 len++;
948 len++;
950 to = talloc_array(ctx, char, len);
951 if (!to) {
952 return NULL;
955 for (out = to; *from;) {
956 /* buffer husoku error */
957 if ((unsigned char)*from >= 0x80) {
958 *out++ = hex_tag;
959 *out++ = bin2hex (((*from)>>4)&0x0f);
960 *out++ = bin2hex ((*from)&0x0f);
961 from++;
962 } else {
963 *out++ = *from++;
966 *out = '\0';
967 return to;
970 /*******************************************************************
971 CAP -> original code
972 ********************************************************************/
973 /* ":xx" -> a byte */
975 static char *capdecode(TALLOC_CTX *ctx, const char *from)
977 const char *p1;
978 char *out = NULL;
979 char *to = NULL;
980 size_t len = 0;
982 for (p1 = from; *p1; len++) {
983 if (is_hex(p1)) {
984 p1 += 3;
985 } else {
986 p1++;
989 len++;
991 to = talloc_array(ctx, char, len);
992 if (!to) {
993 return NULL;
996 for (out = to; *from;) {
997 if (is_hex(from)) {
998 *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
999 from += 3;
1000 } else {
1001 *out++ = *from++;
1004 *out = '\0';
1005 return to;