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/>.
26 #include "smbd/smbd.h"
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
,
38 char *capname
= capencode(talloc_tos(), smb_fname
->base_name
);
39 struct smb_filename
*cap_smb_fname
= NULL
;
45 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
51 if (cap_smb_fname
== NULL
) {
56 return SMB_VFS_NEXT_DISK_FREE(handle
, cap_smb_fname
,
60 static int cap_get_quota(vfs_handle_struct
*handle
,
61 const struct smb_filename
*smb_fname
,
62 enum SMB_QUOTA_TYPE qtype
,
66 char *cappath
= capencode(talloc_tos(), smb_fname
->base_name
);
67 struct smb_filename
*cap_smb_fname
= NULL
;
73 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
79 if (cap_smb_fname
== NULL
) {
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
;
94 DEBUG(3,("cap: cap_readdir\n"));
96 result
= SMB_VFS_NEXT_READDIR(handle
, dirfsp
, dirp
);
101 newname
= capdecode(talloc_tos(), result
->d_name
);
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
);
112 talloc_set_name_const(newdirent
, "struct dirent");
113 memcpy(newdirent
, result
, sizeof(struct dirent
));
114 memcpy(&newdirent
->d_name
, newname
, newnamelen
);
118 static int cap_mkdirat(vfs_handle_struct
*handle
,
119 struct files_struct
*dirfsp
,
120 const struct smb_filename
*smb_fname
,
123 char *cappath
= capencode(talloc_tos(), smb_fname
->base_name
);
124 struct smb_filename
*cap_smb_fname
= NULL
;
131 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
137 if (cap_smb_fname
== NULL
) {
138 TALLOC_FREE(cappath
);
143 return SMB_VFS_NEXT_MKDIRAT(handle
,
149 static int cap_openat(vfs_handle_struct
*handle
,
150 const struct files_struct
*dirfsp
,
151 const struct smb_filename
*smb_fname_in
,
153 const struct vfs_open_how
*how
)
155 char *cappath
= NULL
;
156 struct smb_filename
*smb_fname
= NULL
;
160 cappath
= capencode(talloc_tos(), smb_fname_in
->base_name
);
161 if (cappath
== NULL
) {
166 smb_fname
= cp_smb_filename(talloc_tos(), smb_fname_in
);
167 if (smb_fname
== NULL
) {
168 TALLOC_FREE(cappath
);
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
,
183 TALLOC_FREE(cappath
);
184 TALLOC_FREE(smb_fname
);
185 if (saved_errno
!= 0) {
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
)
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
;
207 full_fname_src
= full_path_from_dirfsp_atname(talloc_tos(),
210 if (full_fname_src
== NULL
) {
215 full_fname_dst
= full_path_from_dirfsp_atname(talloc_tos(),
218 if (full_fname_dst
== NULL
) {
223 capold
= capencode(talloc_tos(), full_fname_src
->base_name
);
224 capnew
= capencode(talloc_tos(), full_fname_dst
->base_name
);
225 if (!capold
|| !capnew
) {
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
) {
236 smb_fname_dst_tmp
= cp_smb_filename(talloc_tos(), full_fname_dst
);
237 if (smb_fname_dst_tmp
== NULL
) {
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
,
248 dstfsp
->conn
->cwd_fsp
,
258 TALLOC_FREE(full_fname_src
);
259 TALLOC_FREE(full_fname_dst
);
262 TALLOC_FREE(smb_fname_src_tmp
);
263 TALLOC_FREE(smb_fname_dst_tmp
);
272 static int cap_stat(vfs_handle_struct
*handle
, struct smb_filename
*smb_fname
)
275 char *tmp_base_name
= NULL
;
278 cappath
= capencode(talloc_tos(), smb_fname
->base_name
);
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
);
296 static int cap_lstat(vfs_handle_struct
*handle
, struct smb_filename
*smb_fname
)
299 char *tmp_base_name
= NULL
;
302 cappath
= capencode(talloc_tos(), smb_fname
->base_name
);
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
);
320 static int cap_unlinkat(vfs_handle_struct
*handle
,
321 struct files_struct
*dirfsp
,
322 const struct smb_filename
*smb_fname
,
325 struct smb_filename
*full_fname
= NULL
;
326 struct smb_filename
*smb_fname_tmp
= NULL
;
327 char *cappath
= NULL
;
330 full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
333 if (full_fname
== NULL
) {
337 cappath
= capencode(talloc_tos(), full_fname
->base_name
);
339 TALLOC_FREE(full_fname
);
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
) {
352 smb_fname_tmp
->base_name
= cappath
;
354 ret
= SMB_VFS_NEXT_UNLINKAT(handle
,
355 dirfsp
->conn
->cwd_fsp
,
359 TALLOC_FREE(smb_fname_tmp
);
363 static int cap_lchown(vfs_handle_struct
*handle
,
364 const struct smb_filename
*smb_fname
,
368 struct smb_filename
*cap_smb_fname
= NULL
;
369 char *cappath
= capencode(talloc_tos(), smb_fname
->base_name
);
378 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
384 if (cap_smb_fname
== NULL
) {
385 TALLOC_FREE(cappath
);
390 ret
= SMB_VFS_NEXT_LCHOWN(handle
, cap_smb_fname
, uid
, gid
);
392 TALLOC_FREE(cappath
);
393 TALLOC_FREE(cap_smb_fname
);
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
);
410 DEBUG(3,("cap: cap_chdir for %s\n", smb_fname
->base_name
));
412 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
418 if (cap_smb_fname
== NULL
) {
419 TALLOC_FREE(cappath
);
423 ret
= SMB_VFS_NEXT_CHDIR(handle
, cap_smb_fname
);
427 TALLOC_FREE(cappath
);
428 TALLOC_FREE(cap_smb_fname
);
429 if (saved_errno
!= 0) {
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
);
443 struct smb_filename
*new_link_target
= NULL
;
444 struct smb_filename
*new_cap_smb_fname
= NULL
;
448 if (capold
== NULL
) {
453 full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
456 if (full_fname
== NULL
) {
460 capnew
= capencode(talloc_tos(), full_fname
->base_name
);
462 TALLOC_FREE(full_fname
);
467 new_link_target
= synthetic_smb_fname(talloc_tos(),
472 new_smb_fname
->flags
);
473 if (new_link_target
== NULL
) {
474 TALLOC_FREE(full_fname
);
481 new_cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
486 new_smb_fname
->flags
);
487 if (new_cap_smb_fname
== NULL
) {
488 TALLOC_FREE(full_fname
);
491 TALLOC_FREE(new_link_target
);
495 ret
= SMB_VFS_NEXT_SYMLINKAT(handle
,
497 handle
->conn
->cwd_fsp
,
502 TALLOC_FREE(full_fname
);
505 TALLOC_FREE(new_link_target
);
506 TALLOC_FREE(new_cap_smb_fname
);
507 if (saved_errno
!= 0) {
513 static int cap_readlinkat(vfs_handle_struct
*handle
,
514 const struct files_struct
*dirfsp
,
515 const struct smb_filename
*smb_fname
,
519 struct smb_filename
*full_fname
= NULL
;
520 struct smb_filename
*cap_smb_fname
= NULL
;
521 char *cappath
= NULL
;
525 full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
528 if (full_fname
== NULL
) {
532 cappath
= capencode(talloc_tos(), full_fname
->base_name
);
533 if (cappath
== NULL
) {
534 TALLOC_FREE(full_fname
);
538 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
544 if (cap_smb_fname
== NULL
) {
545 TALLOC_FREE(full_fname
);
546 TALLOC_FREE(cappath
);
550 ret
= SMB_VFS_NEXT_READLINKAT(handle
,
551 handle
->conn
->cwd_fsp
,
558 TALLOC_FREE(full_fname
);
559 TALLOC_FREE(cappath
);
560 TALLOC_FREE(cap_smb_fname
);
561 if (saved_errno
!= 0) {
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
,
574 struct smb_filename
*old_full_fname
= NULL
;
575 struct smb_filename
*new_full_fname
= NULL
;
578 struct smb_filename
*old_cap_smb_fname
= NULL
;
579 struct smb_filename
*new_cap_smb_fname
= NULL
;
583 /* Process 'old' name. */
584 old_full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
587 if (old_full_fname
== NULL
) {
590 capold
= capencode(talloc_tos(), old_full_fname
->base_name
);
591 if (capold
== NULL
) {
594 TALLOC_FREE(old_full_fname
);
595 old_cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
600 old_smb_fname
->flags
);
601 if (old_cap_smb_fname
== NULL
) {
605 /* Process 'new' name. */
606 new_full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
609 if (new_full_fname
== NULL
) {
612 capnew
= capencode(talloc_tos(), new_full_fname
->base_name
);
613 if (capnew
== NULL
) {
616 TALLOC_FREE(new_full_fname
);
617 new_cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
622 new_smb_fname
->flags
);
623 if (new_cap_smb_fname
== NULL
) {
627 ret
= SMB_VFS_NEXT_LINKAT(handle
,
628 handle
->conn
->cwd_fsp
,
630 handle
->conn
->cwd_fsp
,
636 TALLOC_FREE(old_full_fname
);
637 TALLOC_FREE(old_full_fname
);
640 TALLOC_FREE(old_cap_smb_fname
);
641 TALLOC_FREE(new_cap_smb_fname
);
642 if (saved_errno
!= 0) {
649 TALLOC_FREE(old_full_fname
);
650 TALLOC_FREE(old_full_fname
);
653 TALLOC_FREE(old_cap_smb_fname
);
654 TALLOC_FREE(new_cap_smb_fname
);
659 static int cap_mknodat(vfs_handle_struct
*handle
,
660 files_struct
*dirfsp
,
661 const struct smb_filename
*smb_fname
,
665 struct smb_filename
*full_fname
= NULL
;
666 struct smb_filename
*cap_smb_fname
= NULL
;
667 char *cappath
= NULL
;
671 full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
674 if (full_fname
== NULL
) {
678 cappath
= capencode(talloc_tos(), full_fname
->base_name
);
680 TALLOC_FREE(full_fname
);
684 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
690 if (cap_smb_fname
== NULL
) {
691 TALLOC_FREE(full_fname
);
692 TALLOC_FREE(cappath
);
696 ret
= SMB_VFS_NEXT_MKNODAT(handle
,
697 handle
->conn
->cwd_fsp
,
704 TALLOC_FREE(full_fname
);
705 TALLOC_FREE(cappath
);
706 TALLOC_FREE(cap_smb_fname
);
707 if (saved_errno
!= 0) {
713 static struct smb_filename
*cap_realpath(vfs_handle_struct
*handle
,
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
);
727 cap_smb_fname
= synthetic_smb_fname(ctx
,
733 if (cap_smb_fname
== NULL
) {
734 TALLOC_FREE(cappath
);
738 return_fname
= SMB_VFS_NEXT_REALPATH(handle
, ctx
, cap_smb_fname
);
739 if (return_fname
== NULL
) {
742 TALLOC_FREE(cappath
);
743 TALLOC_FREE(cap_smb_fname
);
744 if (saved_errno
!= 0) {
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
);
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
);
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
);
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
;
793 if (cappath
== NULL
) {
794 return NT_STATUS_NO_MEMORY
;
796 cap_smb_fname
= synthetic_smb_fname(talloc_tos(),
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
,
811 TALLOC_FREE(cappath
);
812 TALLOC_FREE(cap_smb_fname
);
816 static NTSTATUS
cap_read_dfs_pathat(struct vfs_handle_struct
*handle
,
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
;
828 full_fname
= full_path_from_dirfsp_atname(talloc_tos(),
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(),
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
,
853 handle
->conn
->cwd_fsp
,
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
);
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
,
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
896 NTSTATUS
vfs_cap_init(TALLOC_CTX
*ctx
)
898 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "cap",
902 /* For CAP functions */
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
)
917 for (p1
= from
; *p1
; p1
++) {
918 if ((unsigned char)*p1
>= 0x80) {
926 to
= talloc_array(ctx
, char, len
);
931 for (out
= to
; *from
;) {
932 /* buffer husoku error */
933 if ((unsigned char)*from
>= 0x80) {
935 *out
++ = nybble_to_hex_lower(((*from
) >> 4));
936 *out
++ = nybble_to_hex_lower(*from
);
946 /*******************************************************************
948 ********************************************************************/
949 /* ":xx" -> a byte */
951 static char *capdecode(TALLOC_CTX
*ctx
, const char *from
)
958 for (p1
= from
; *p1
; len
++) {
967 to
= talloc_array(ctx
, char, len
);
972 for (out
= to
; *from
;) {
974 (void)hex_byte(&from
[1], (uint8_t *)(out
++));