2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
40 #define DBGC_CLASS DBGC_VFS
42 /* Check for NULL pointer parameters in vfswrap_* functions */
44 /* We don't want to have NULL function pointers lying around. Someone
45 is sure to try and execute them. These stubs are used to prevent
48 static int vfswrap_connect(vfs_handle_struct
*handle
, const char *service
, const char *user
)
50 return 0; /* Return >= 0 for success */
53 static void vfswrap_disconnect(vfs_handle_struct
*handle
)
59 static uint64_t vfswrap_disk_free(vfs_handle_struct
*handle
,
60 const struct smb_filename
*smb_fname
,
65 if (sys_fsusage(smb_fname
->base_name
, dfree
, dsize
) != 0) {
73 static int vfswrap_get_quota(struct vfs_handle_struct
*handle
,
74 const struct smb_filename
*smb_fname
,
75 enum SMB_QUOTA_TYPE qtype
,
79 #ifdef HAVE_SYS_QUOTAS
82 START_PROFILE(syscall_get_quota
);
83 result
= sys_get_quota(smb_fname
->base_name
, qtype
, id
, qt
);
84 END_PROFILE(syscall_get_quota
);
92 static int vfswrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
94 #ifdef HAVE_SYS_QUOTAS
97 START_PROFILE(syscall_set_quota
);
98 result
= sys_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
99 END_PROFILE(syscall_set_quota
);
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
108 struct files_struct
*fsp
,
109 struct shadow_copy_data
*shadow_copy_data
,
113 return -1; /* Not implemented. */
116 static int vfswrap_statvfs(struct vfs_handle_struct
*handle
,
117 const struct smb_filename
*smb_fname
,
118 vfs_statvfs_struct
*statbuf
)
120 return sys_statvfs(smb_fname
->base_name
, statbuf
);
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct
*handle
,
124 enum timestamp_set_resolution
*p_ts_res
)
126 const struct loadparm_substitution
*lp_sub
=
127 loadparm_s3_global_substitution();
128 connection_struct
*conn
= handle
->conn
;
129 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
130 struct smb_filename
*smb_fname_cpath
= NULL
;
131 struct vfs_statvfs_struct statbuf
;
134 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
136 if (smb_fname_cpath
== NULL
) {
140 ZERO_STRUCT(statbuf
);
141 ret
= SMB_VFS_STATVFS(conn
, smb_fname_cpath
, &statbuf
);
143 caps
= statbuf
.FsCapabilities
;
146 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
148 /* Work out what timestamp resolution we can
149 * use when setting a timestamp. */
151 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
153 TALLOC_FREE(smb_fname_cpath
);
157 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
158 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
159 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
160 /* If any of the normal UNIX directory timestamps
161 * have a non-zero tv_nsec component assume
162 * we might be able to set sub-second timestamps.
163 * See what filetime set primitives we have.
165 #if defined(HAVE_UTIMENSAT)
166 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
167 #elif defined(HAVE_UTIMES)
168 /* utimes allows msec timestamps to be set. */
169 *p_ts_res
= TIMESTAMP_SET_MSEC
;
170 #elif defined(HAVE_UTIME)
171 /* utime only allows sec timestamps to be set. */
172 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
175 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
177 "available on share %s, directory %s\n",
178 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
179 lp_servicename(talloc_tos(), lp_sub
, conn
->params
->service
),
180 conn
->connectpath
));
182 TALLOC_FREE(smb_fname_cpath
);
186 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
187 struct dfs_GetDFSReferral
*r
)
189 struct junction_map
*junction
= NULL
;
191 bool self_referral
= false;
192 char *pathnamep
= NULL
;
193 char *local_dfs_path
= NULL
;
196 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
199 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
202 /* get the junction entry */
203 if (r
->in
.req
.servername
== NULL
) {
204 return NT_STATUS_NOT_FOUND
;
208 * Trim pathname sent by client so it begins with only one backslash.
209 * Two backslashes confuse some dfs clients
212 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
213 if (local_dfs_path
== NULL
) {
214 return NT_STATUS_NO_MEMORY
;
216 pathnamep
= local_dfs_path
;
217 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
218 IS_DIRECTORY_SEP(pathnamep
[1])) {
222 junction
= talloc_zero(r
, struct junction_map
);
223 if (junction
== NULL
) {
224 return NT_STATUS_NO_MEMORY
;
227 /* The following call can change cwd. */
228 status
= get_referred_path(r
,
229 handle
->conn
->session_info
,
231 handle
->conn
->sconn
->remote_address
,
232 handle
->conn
->sconn
->local_address
,
233 !handle
->conn
->sconn
->using_smb2
,
234 junction
, &consumedcnt
, &self_referral
);
235 if (!NT_STATUS_IS_OK(status
)) {
236 struct smb_filename connectpath_fname
= {
237 .base_name
= handle
->conn
->connectpath
239 vfs_ChDir(handle
->conn
, &connectpath_fname
);
243 struct smb_filename connectpath_fname
= {
244 .base_name
= handle
->conn
->connectpath
246 vfs_ChDir(handle
->conn
, &connectpath_fname
);
249 if (!self_referral
) {
250 pathnamep
[consumedcnt
] = '\0';
253 dbgtext("Path %s to alternate path(s):",
255 for (i
=0; i
< junction
->referral_count
; i
++) {
257 junction
->referral_list
[i
].alternate_path
);
263 if (r
->in
.req
.max_referral_level
<= 2) {
264 max_referral_level
= 2;
266 if (r
->in
.req
.max_referral_level
>= 3) {
267 max_referral_level
= 3;
270 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
271 if (r
->out
.resp
== NULL
) {
272 return NT_STATUS_NO_MEMORY
;
275 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
276 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
278 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
280 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
283 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
284 struct dfs_referral_type
,
285 r
->out
.resp
->nb_referrals
);
286 if (r
->out
.resp
->referral_entries
== NULL
) {
287 return NT_STATUS_NO_MEMORY
;
290 switch (max_referral_level
) {
292 for(i
=0; i
< junction
->referral_count
; i
++) {
293 struct referral
*ref
= &junction
->referral_list
[i
];
294 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
295 struct dfs_referral_type
*t
=
296 &r
->out
.resp
->referral_entries
[i
];
297 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
300 v2
->size
= VERSION2_REFERRAL_SIZE
;
302 v2
->server_type
= DFS_SERVER_ROOT
;
304 v2
->server_type
= DFS_SERVER_NON_ROOT
;
307 v2
->proximity
= ref
->proximity
;
309 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
310 if (v2
->DFS_path
== NULL
) {
311 return NT_STATUS_NO_MEMORY
;
313 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
314 if (v2
->DFS_alt_path
== NULL
) {
315 return NT_STATUS_NO_MEMORY
;
317 v2
->netw_address
= talloc_strdup(mem_ctx
,
318 ref
->alternate_path
);
319 if (v2
->netw_address
== NULL
) {
320 return NT_STATUS_NO_MEMORY
;
326 for(i
=0; i
< junction
->referral_count
; i
++) {
327 struct referral
*ref
= &junction
->referral_list
[i
];
328 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
329 struct dfs_referral_type
*t
=
330 &r
->out
.resp
->referral_entries
[i
];
331 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
332 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
335 v3
->size
= VERSION3_REFERRAL_SIZE
;
337 v3
->server_type
= DFS_SERVER_ROOT
;
339 v3
->server_type
= DFS_SERVER_NON_ROOT
;
343 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
344 if (r1
->DFS_path
== NULL
) {
345 return NT_STATUS_NO_MEMORY
;
347 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
348 if (r1
->DFS_alt_path
== NULL
) {
349 return NT_STATUS_NO_MEMORY
;
351 r1
->netw_address
= talloc_strdup(mem_ctx
,
352 ref
->alternate_path
);
353 if (r1
->netw_address
== NULL
) {
354 return NT_STATUS_NO_MEMORY
;
359 DEBUG(0,("Invalid dfs referral version: %d\n",
360 max_referral_level
));
361 return NT_STATUS_INVALID_LEVEL
;
365 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
371 static NTSTATUS
vfswrap_create_dfs_pathat(struct vfs_handle_struct
*handle
,
372 struct files_struct
*dirfsp
,
373 const struct smb_filename
*smb_fname
,
374 const struct referral
*reflist
,
375 size_t referral_count
)
377 TALLOC_CTX
*frame
= talloc_stackframe();
378 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
380 char *msdfs_link
= NULL
;
382 SMB_ASSERT(dirfsp
== dirfsp
->conn
->cwd_fsp
);
384 /* Form the msdfs_link contents */
385 msdfs_link
= msdfs_link_string(frame
,
388 if (msdfs_link
== NULL
) {
392 ret
= symlinkat(msdfs_link
,
394 smb_fname
->base_name
);
396 status
= NT_STATUS_OK
;
398 status
= map_nt_error_from_unix(errno
);
408 * Read and return the contents of a DFS redirect given a
409 * pathname. A caller can pass in NULL for ppreflist and
410 * preferral_count but still determine if this was a
411 * DFS redirect point by getting NT_STATUS_OK back
412 * without incurring the overhead of reading and parsing
413 * the referral contents.
416 static NTSTATUS
vfswrap_read_dfs_pathat(struct vfs_handle_struct
*handle
,
418 struct files_struct
*dirfsp
,
419 const struct smb_filename
*smb_fname
,
420 struct referral
**ppreflist
,
421 size_t *preferral_count
)
423 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
425 char *link_target
= NULL
;
428 #if defined(HAVE_BROKEN_READLINK)
429 char link_target_buf
[PATH_MAX
];
431 char link_target_buf
[7];
434 SMB_ASSERT(dirfsp
== dirfsp
->conn
->cwd_fsp
);
436 if (ppreflist
== NULL
&& preferral_count
== NULL
) {
438 * We're only checking if this is a DFS
439 * redirect. We don't need to return data.
441 bufsize
= sizeof(link_target_buf
);
442 link_target
= link_target_buf
;
445 link_target
= talloc_array(mem_ctx
, char, bufsize
);
451 referral_len
= readlinkat(dirfsp
->fh
->fd
,
452 smb_fname
->base_name
,
455 if (referral_len
== -1) {
456 if (errno
== EINVAL
) {
458 * If the path isn't a link, readlinkat
459 * returns EINVAL. Allow the caller to
462 DBG_INFO("%s is not a link.\n", smb_fname
->base_name
);
463 status
= NT_STATUS_OBJECT_TYPE_MISMATCH
;
465 status
= map_nt_error_from_unix(errno
);
466 DBG_ERR("Error reading "
467 "msdfs link %s: %s\n",
468 smb_fname
->base_name
,
473 link_target
[referral_len
] = '\0';
475 DBG_INFO("%s -> %s\n",
476 smb_fname
->base_name
,
479 if (!strnequal(link_target
, "msdfs:", 6)) {
480 status
= NT_STATUS_OBJECT_TYPE_MISMATCH
;
484 if (ppreflist
== NULL
&& preferral_count
== NULL
) {
485 /* Early return for checking if this is a DFS link. */
489 ok
= parse_msdfs_symlink(mem_ctx
,
490 lp_msdfs_shuffle_referrals(SNUM(handle
->conn
)),
496 status
= NT_STATUS_OK
;
498 status
= NT_STATUS_NO_MEMORY
;
503 if (link_target
!= link_target_buf
) {
504 TALLOC_FREE(link_target
);
509 static NTSTATUS
vfswrap_snap_check_path(struct vfs_handle_struct
*handle
,
511 const char *service_path
,
514 return NT_STATUS_NOT_SUPPORTED
;
517 static NTSTATUS
vfswrap_snap_create(struct vfs_handle_struct
*handle
,
519 const char *base_volume
,
525 return NT_STATUS_NOT_SUPPORTED
;
528 static NTSTATUS
vfswrap_snap_delete(struct vfs_handle_struct
*handle
,
533 return NT_STATUS_NOT_SUPPORTED
;
536 /* Directory operations */
538 static DIR *vfswrap_opendir(vfs_handle_struct
*handle
,
539 const struct smb_filename
*smb_fname
,
545 START_PROFILE(syscall_opendir
);
546 result
= opendir(smb_fname
->base_name
);
547 END_PROFILE(syscall_opendir
);
551 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
558 START_PROFILE(syscall_fdopendir
);
559 result
= sys_fdopendir(fsp
->fh
->fd
);
560 END_PROFILE(syscall_fdopendir
);
565 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
567 SMB_STRUCT_STAT
*sbuf
)
569 struct dirent
*result
;
571 START_PROFILE(syscall_readdir
);
572 result
= readdir(dirp
);
573 END_PROFILE(syscall_readdir
);
575 /* Default Posix readdir() does not give us stat info.
576 * Set to invalid to indicate we didn't return this info. */
577 SET_STAT_INVALID(*sbuf
);
578 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
579 if (result
!= NULL
) {
580 /* See if we can efficiently return this. */
582 int flags
= AT_SYMLINK_NOFOLLOW
;
583 int ret
= fstatat(dirfd(dirp
),
588 * As this is an optimization,
589 * ignore it if we stat'ed a
590 * symlink. Make the caller
591 * do it again as we don't
592 * know if they wanted the link
593 * info, or its target info.
595 if ((ret
== 0) && (!S_ISLNK(st
.st_mode
))) {
596 init_stat_ex_from_stat(sbuf
,
598 lp_fake_directory_create_times(
599 SNUM(handle
->conn
)));
607 static NTSTATUS
vfswrap_readdir_attr(struct vfs_handle_struct
*handle
,
608 const struct smb_filename
*fname
,
610 struct readdir_attr_data
**attr_data
)
612 return NT_STATUS_NOT_SUPPORTED
;
615 static void vfswrap_seekdir(vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
617 START_PROFILE(syscall_seekdir
);
618 seekdir(dirp
, offset
);
619 END_PROFILE(syscall_seekdir
);
622 static long vfswrap_telldir(vfs_handle_struct
*handle
, DIR *dirp
)
625 START_PROFILE(syscall_telldir
);
626 result
= telldir(dirp
);
627 END_PROFILE(syscall_telldir
);
631 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
633 START_PROFILE(syscall_rewinddir
);
635 END_PROFILE(syscall_rewinddir
);
638 static int vfswrap_mkdirat(vfs_handle_struct
*handle
,
639 struct files_struct
*dirfsp
,
640 const struct smb_filename
*smb_fname
,
644 const char *path
= smb_fname
->base_name
;
647 START_PROFILE(syscall_mkdirat
);
649 SMB_ASSERT(dirfsp
== dirfsp
->conn
->cwd_fsp
);
651 if (lp_inherit_acls(SNUM(handle
->conn
))
652 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
653 && directory_has_default_acl(handle
->conn
, parent
)) {
654 mode
= (0777 & lp_directory_mask(SNUM(handle
->conn
)));
659 result
= mkdirat(dirfsp
->fh
->fd
, path
, mode
);
661 END_PROFILE(syscall_mkdirat
);
665 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
669 START_PROFILE(syscall_closedir
);
670 result
= closedir(dirp
);
671 END_PROFILE(syscall_closedir
);
675 /* File operations */
677 static int vfswrap_open(vfs_handle_struct
*handle
,
678 struct smb_filename
*smb_fname
,
679 files_struct
*fsp
, int flags
, mode_t mode
)
683 START_PROFILE(syscall_open
);
685 if (is_named_stream(smb_fname
)) {
690 result
= open(smb_fname
->base_name
, flags
, mode
);
692 END_PROFILE(syscall_open
);
696 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
697 struct smb_request
*req
,
698 uint16_t root_dir_fid
,
699 struct smb_filename
*smb_fname
,
700 uint32_t access_mask
,
701 uint32_t share_access
,
702 uint32_t create_disposition
,
703 uint32_t create_options
,
704 uint32_t file_attributes
,
705 uint32_t oplock_request
,
706 const struct smb2_lease
*lease
,
707 uint64_t allocation_size
,
708 uint32_t private_flags
,
709 struct security_descriptor
*sd
,
710 struct ea_list
*ea_list
,
711 files_struct
**result
,
713 const struct smb2_create_blobs
*in_context_blobs
,
714 struct smb2_create_blobs
*out_context_blobs
)
716 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
717 access_mask
, share_access
,
718 create_disposition
, create_options
,
719 file_attributes
, oplock_request
, lease
,
720 allocation_size
, private_flags
,
722 pinfo
, in_context_blobs
, out_context_blobs
);
725 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
729 START_PROFILE(syscall_close
);
730 result
= fd_close_posix(fsp
);
731 END_PROFILE(syscall_close
);
735 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
736 size_t n
, off_t offset
)
740 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
741 START_PROFILE_BYTES(syscall_pread
, n
);
742 result
= sys_pread_full(fsp
->fh
->fd
, data
, n
, offset
);
743 END_PROFILE_BYTES(syscall_pread
);
745 if (result
== -1 && errno
== ESPIPE
) {
746 /* Maintain the fiction that pipes can be seeked (sought?) on. */
747 result
= sys_read(fsp
->fh
->fd
, data
, n
);
751 #else /* HAVE_PREAD */
754 #endif /* HAVE_PREAD */
759 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
760 size_t n
, off_t offset
)
764 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
765 START_PROFILE_BYTES(syscall_pwrite
, n
);
766 result
= sys_pwrite_full(fsp
->fh
->fd
, data
, n
, offset
);
767 END_PROFILE_BYTES(syscall_pwrite
);
769 if (result
== -1 && errno
== ESPIPE
) {
770 /* Maintain the fiction that pipes can be sought on. */
771 result
= sys_write(fsp
->fh
->fd
, data
, n
);
774 #else /* HAVE_PWRITE */
777 #endif /* HAVE_PWRITE */
782 struct vfswrap_pread_state
{
789 struct vfs_aio_state vfs_aio_state
;
790 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
793 static void vfs_pread_do(void *private_data
);
794 static void vfs_pread_done(struct tevent_req
*subreq
);
795 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
);
797 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
799 struct tevent_context
*ev
,
800 struct files_struct
*fsp
,
802 size_t n
, off_t offset
)
804 struct tevent_req
*req
, *subreq
;
805 struct vfswrap_pread_state
*state
;
807 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
813 state
->fd
= fsp
->fh
->fd
;
816 state
->offset
= offset
;
818 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
819 state
->profile_bytes
, n
);
820 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
822 subreq
= pthreadpool_tevent_job_send(
823 state
, ev
, handle
->conn
->sconn
->pool
,
824 vfs_pread_do
, state
);
825 if (tevent_req_nomem(subreq
, req
)) {
826 return tevent_req_post(req
, ev
);
828 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
830 talloc_set_destructor(state
, vfs_pread_state_destructor
);
835 static void vfs_pread_do(void *private_data
)
837 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
838 private_data
, struct vfswrap_pread_state
);
839 struct timespec start_time
;
840 struct timespec end_time
;
842 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
844 PROFILE_TIMESTAMP(&start_time
);
846 state
->ret
= sys_pread_full(state
->fd
,
851 if (state
->ret
== -1) {
852 state
->vfs_aio_state
.error
= errno
;
855 PROFILE_TIMESTAMP(&end_time
);
857 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
859 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
862 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
)
867 static void vfs_pread_done(struct tevent_req
*subreq
)
869 struct tevent_req
*req
= tevent_req_callback_data(
870 subreq
, struct tevent_req
);
871 struct vfswrap_pread_state
*state
= tevent_req_data(
872 req
, struct vfswrap_pread_state
);
875 ret
= pthreadpool_tevent_job_recv(subreq
);
877 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
878 talloc_set_destructor(state
, NULL
);
881 tevent_req_error(req
, ret
);
885 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
886 * means the lower level pthreadpool failed to create a new
887 * thread. Fallback to sync processing in that case to allow
888 * some progress for the client.
893 tevent_req_done(req
);
896 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
897 struct vfs_aio_state
*vfs_aio_state
)
899 struct vfswrap_pread_state
*state
= tevent_req_data(
900 req
, struct vfswrap_pread_state
);
902 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
906 *vfs_aio_state
= state
->vfs_aio_state
;
910 struct vfswrap_pwrite_state
{
917 struct vfs_aio_state vfs_aio_state
;
918 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
921 static void vfs_pwrite_do(void *private_data
);
922 static void vfs_pwrite_done(struct tevent_req
*subreq
);
923 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
);
925 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
927 struct tevent_context
*ev
,
928 struct files_struct
*fsp
,
930 size_t n
, off_t offset
)
932 struct tevent_req
*req
, *subreq
;
933 struct vfswrap_pwrite_state
*state
;
935 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pwrite_state
);
941 state
->fd
= fsp
->fh
->fd
;
944 state
->offset
= offset
;
946 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
947 state
->profile_bytes
, n
);
948 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
950 subreq
= pthreadpool_tevent_job_send(
951 state
, ev
, handle
->conn
->sconn
->pool
,
952 vfs_pwrite_do
, state
);
953 if (tevent_req_nomem(subreq
, req
)) {
954 return tevent_req_post(req
, ev
);
956 tevent_req_set_callback(subreq
, vfs_pwrite_done
, req
);
958 talloc_set_destructor(state
, vfs_pwrite_state_destructor
);
963 static void vfs_pwrite_do(void *private_data
)
965 struct vfswrap_pwrite_state
*state
= talloc_get_type_abort(
966 private_data
, struct vfswrap_pwrite_state
);
967 struct timespec start_time
;
968 struct timespec end_time
;
970 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
972 PROFILE_TIMESTAMP(&start_time
);
974 state
->ret
= sys_pwrite_full(state
->fd
,
979 if (state
->ret
== -1) {
980 state
->vfs_aio_state
.error
= errno
;
983 PROFILE_TIMESTAMP(&end_time
);
985 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
987 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
990 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
)
995 static void vfs_pwrite_done(struct tevent_req
*subreq
)
997 struct tevent_req
*req
= tevent_req_callback_data(
998 subreq
, struct tevent_req
);
999 struct vfswrap_pwrite_state
*state
= tevent_req_data(
1000 req
, struct vfswrap_pwrite_state
);
1003 ret
= pthreadpool_tevent_job_recv(subreq
);
1004 TALLOC_FREE(subreq
);
1005 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
1006 talloc_set_destructor(state
, NULL
);
1008 if (ret
!= EAGAIN
) {
1009 tevent_req_error(req
, ret
);
1013 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1014 * means the lower level pthreadpool failed to create a new
1015 * thread. Fallback to sync processing in that case to allow
1016 * some progress for the client.
1018 vfs_pwrite_do(state
);
1021 tevent_req_done(req
);
1024 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
1025 struct vfs_aio_state
*vfs_aio_state
)
1027 struct vfswrap_pwrite_state
*state
= tevent_req_data(
1028 req
, struct vfswrap_pwrite_state
);
1030 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1034 *vfs_aio_state
= state
->vfs_aio_state
;
1038 struct vfswrap_fsync_state
{
1042 struct vfs_aio_state vfs_aio_state
;
1043 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
1046 static void vfs_fsync_do(void *private_data
);
1047 static void vfs_fsync_done(struct tevent_req
*subreq
);
1048 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
);
1050 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
1051 TALLOC_CTX
*mem_ctx
,
1052 struct tevent_context
*ev
,
1053 struct files_struct
*fsp
)
1055 struct tevent_req
*req
, *subreq
;
1056 struct vfswrap_fsync_state
*state
;
1058 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
1064 state
->fd
= fsp
->fh
->fd
;
1066 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync
, profile_p
,
1067 state
->profile_bytes
, 0);
1068 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1070 subreq
= pthreadpool_tevent_job_send(
1071 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
1072 if (tevent_req_nomem(subreq
, req
)) {
1073 return tevent_req_post(req
, ev
);
1075 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
1077 talloc_set_destructor(state
, vfs_fsync_state_destructor
);
1082 static void vfs_fsync_do(void *private_data
)
1084 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
1085 private_data
, struct vfswrap_fsync_state
);
1086 struct timespec start_time
;
1087 struct timespec end_time
;
1089 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
1091 PROFILE_TIMESTAMP(&start_time
);
1094 state
->ret
= fsync(state
->fd
);
1095 } while ((state
->ret
== -1) && (errno
== EINTR
));
1097 if (state
->ret
== -1) {
1098 state
->vfs_aio_state
.error
= errno
;
1101 PROFILE_TIMESTAMP(&end_time
);
1103 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1105 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1108 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
)
1113 static void vfs_fsync_done(struct tevent_req
*subreq
)
1115 struct tevent_req
*req
= tevent_req_callback_data(
1116 subreq
, struct tevent_req
);
1117 struct vfswrap_fsync_state
*state
= tevent_req_data(
1118 req
, struct vfswrap_fsync_state
);
1121 ret
= pthreadpool_tevent_job_recv(subreq
);
1122 TALLOC_FREE(subreq
);
1123 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
1124 talloc_set_destructor(state
, NULL
);
1126 if (ret
!= EAGAIN
) {
1127 tevent_req_error(req
, ret
);
1131 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1132 * means the lower level pthreadpool failed to create a new
1133 * thread. Fallback to sync processing in that case to allow
1134 * some progress for the client.
1136 vfs_fsync_do(state
);
1139 tevent_req_done(req
);
1142 static int vfswrap_fsync_recv(struct tevent_req
*req
,
1143 struct vfs_aio_state
*vfs_aio_state
)
1145 struct vfswrap_fsync_state
*state
= tevent_req_data(
1146 req
, struct vfswrap_fsync_state
);
1148 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1152 *vfs_aio_state
= state
->vfs_aio_state
;
1156 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1160 START_PROFILE(syscall_lseek
);
1162 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
1164 * We want to maintain the fiction that we can seek
1165 * on a fifo for file system purposes. This allows
1166 * people to set up UNIX fifo's that feed data to Windows
1167 * applications. JRA.
1170 if((result
== -1) && (errno
== ESPIPE
)) {
1175 END_PROFILE(syscall_lseek
);
1179 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1180 off_t offset
, size_t n
)
1184 START_PROFILE_BYTES(syscall_sendfile
, n
);
1185 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
1186 END_PROFILE_BYTES(syscall_sendfile
);
1190 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1192 files_struct
*tofsp
,
1198 START_PROFILE_BYTES(syscall_recvfile
, n
);
1199 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
1200 END_PROFILE_BYTES(syscall_recvfile
);
1204 static int vfswrap_renameat(vfs_handle_struct
*handle
,
1205 files_struct
*srcfsp
,
1206 const struct smb_filename
*smb_fname_src
,
1207 files_struct
*dstfsp
,
1208 const struct smb_filename
*smb_fname_dst
)
1212 START_PROFILE(syscall_renameat
);
1214 if (is_named_stream(smb_fname_src
) || is_named_stream(smb_fname_dst
)) {
1219 result
= renameat(srcfsp
->fh
->fd
,
1220 smb_fname_src
->base_name
,
1222 smb_fname_dst
->base_name
);
1225 END_PROFILE(syscall_renameat
);
1229 static int vfswrap_stat(vfs_handle_struct
*handle
,
1230 struct smb_filename
*smb_fname
)
1234 START_PROFILE(syscall_stat
);
1236 if (is_named_stream(smb_fname
)) {
1241 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1242 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1244 END_PROFILE(syscall_stat
);
1248 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1252 START_PROFILE(syscall_fstat
);
1253 result
= sys_fstat(fsp
->fh
->fd
,
1254 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1255 END_PROFILE(syscall_fstat
);
1259 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1260 struct smb_filename
*smb_fname
)
1264 START_PROFILE(syscall_lstat
);
1266 if (is_named_stream(smb_fname
)) {
1271 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1272 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1274 END_PROFILE(syscall_lstat
);
1278 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1280 enum vfs_translate_direction direction
,
1281 TALLOC_CTX
*mem_ctx
,
1284 return NT_STATUS_NONE_MAPPED
;
1288 * Implement the default fsctl operation.
1290 static bool vfswrap_logged_ioctl_message
= false;
1292 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1293 struct files_struct
*fsp
,
1296 uint16_t req_flags
, /* Needed for UNICODE ... */
1297 const uint8_t *_in_data
,
1299 uint8_t **_out_data
,
1300 uint32_t max_out_len
,
1303 const char *in_data
= (const char *)_in_data
;
1304 char **out_data
= (char **)_out_data
;
1308 case FSCTL_SET_SPARSE
:
1310 bool set_sparse
= true;
1312 if (in_len
>= 1 && in_data
[0] == 0) {
1316 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1318 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1319 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1320 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1321 nt_errstr(status
)));
1326 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1328 unsigned char objid
[16];
1329 char *return_data
= NULL
;
1331 /* This should return the object-id on this file.
1332 * I think I'll make this be the inode+dev. JRA.
1335 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1336 fsp_fnum_dbg(fsp
)));
1338 *out_len
= MIN(max_out_len
, 64);
1340 /* Hmmm, will this cause problems if less data asked for? */
1341 return_data
= talloc_array(ctx
, char, 64);
1342 if (return_data
== NULL
) {
1343 return NT_STATUS_NO_MEMORY
;
1346 /* For backwards compatibility only store the dev/inode. */
1347 push_file_id_16(return_data
, &fsp
->file_id
);
1348 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1349 push_file_id_16(return_data
+32, &fsp
->file_id
);
1350 memset(return_data
+48, 0, 16);
1351 *out_data
= return_data
;
1352 return NT_STATUS_OK
;
1355 case FSCTL_GET_REPARSE_POINT
:
1357 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1358 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1359 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1360 return NT_STATUS_NOT_A_REPARSE_POINT
;
1363 case FSCTL_SET_REPARSE_POINT
:
1365 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1366 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1367 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1368 return NT_STATUS_NOT_A_REPARSE_POINT
;
1371 case FSCTL_GET_SHADOW_COPY_DATA
:
1374 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1375 * and return their volume names. If max_data_count is 16, then it is just
1376 * asking for the number of volumes and length of the combined names.
1378 * pdata is the data allocated by our caller, but that uses
1379 * total_data_count (which is 0 in our case) rather than max_data_count.
1380 * Allocate the correct amount and return the pointer to let
1381 * it be deallocated when we return.
1383 struct shadow_copy_data
*shadow_data
= NULL
;
1384 bool labels
= False
;
1385 uint32_t labels_data_count
= 0;
1387 char *cur_pdata
= NULL
;
1389 if (max_out_len
< 16) {
1390 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1392 return NT_STATUS_INVALID_PARAMETER
;
1395 if (max_out_len
> 16) {
1399 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1400 if (shadow_data
== NULL
) {
1401 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1402 return NT_STATUS_NO_MEMORY
;
1406 * Call the VFS routine to actually do the work.
1408 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1411 /* broken module didn't set errno on error */
1412 status
= NT_STATUS_UNSUCCESSFUL
;
1414 status
= map_nt_error_from_unix(errno
);
1415 if (NT_STATUS_EQUAL(status
,
1416 NT_STATUS_NOT_SUPPORTED
)) {
1420 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1421 "connectpath %s, failed - %s.\n",
1422 fsp
->conn
->connectpath
,
1423 nt_errstr(status
)));
1424 TALLOC_FREE(shadow_data
);
1428 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1429 sizeof(SHADOW_COPY_LABEL
)) + 2;
1434 *out_len
= 12 + labels_data_count
;
1437 if (max_out_len
< *out_len
) {
1438 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1439 max_out_len
, *out_len
));
1440 TALLOC_FREE(shadow_data
);
1441 return NT_STATUS_BUFFER_TOO_SMALL
;
1444 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1445 if (cur_pdata
== NULL
) {
1446 TALLOC_FREE(shadow_data
);
1447 return NT_STATUS_NO_MEMORY
;
1450 *out_data
= cur_pdata
;
1452 /* num_volumes 4 bytes */
1453 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1456 /* num_labels 4 bytes */
1457 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1460 /* needed_data_count 4 bytes */
1461 SIVAL(cur_pdata
, 8, labels_data_count
);
1465 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1466 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1467 if (labels
&& shadow_data
->labels
) {
1468 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1470 status
= srvstr_push(cur_pdata
, req_flags
,
1471 cur_pdata
, shadow_data
->labels
[i
],
1472 2 * sizeof(SHADOW_COPY_LABEL
),
1473 STR_UNICODE
|STR_TERMINATE
, &len
);
1474 if (!NT_STATUS_IS_OK(status
)) {
1475 TALLOC_FREE(*out_data
);
1476 TALLOC_FREE(shadow_data
);
1479 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1480 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1484 TALLOC_FREE(shadow_data
);
1486 return NT_STATUS_OK
;
1489 case FSCTL_FIND_FILES_BY_SID
:
1491 /* pretend this succeeded -
1493 * we have to send back a list with all files owned by this SID
1495 * but I have to check that --metze
1499 struct dom_sid_buf buf
;
1503 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1504 fsp_fnum_dbg(fsp
)));
1507 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1508 return NT_STATUS_INVALID_PARAMETER
;
1511 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1513 /* unknown 4 bytes: this is not the length of the sid :-( */
1514 /*unknown = IVAL(pdata,0);*/
1516 ret
= sid_parse(_in_data
+ 4, sid_len
, &sid
);
1518 return NT_STATUS_INVALID_PARAMETER
;
1520 DEBUGADD(10, ("for SID: %s\n",
1521 dom_sid_str_buf(&sid
, &buf
)));
1523 if (!sid_to_uid(&sid
, &uid
)) {
1524 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1525 dom_sid_str_buf(&sid
, &buf
),
1526 (unsigned long)sid_len
));
1530 /* we can take a look at the find source :-)
1532 * find ./ -uid $uid -name '*' is what we need here
1535 * and send 4bytes len and then NULL terminated unicode strings
1538 * but I don't know how to deal with the paged results
1539 * (maybe we can hang the result anywhere in the fsp struct)
1541 * but I don't know how to deal with the paged results
1542 * (maybe we can hang the result anywhere in the fsp struct)
1544 * we don't send all files at once
1545 * and at the next we should *not* start from the beginning,
1546 * so we have to cache the result
1551 /* this works for now... */
1552 return NT_STATUS_OK
;
1555 case FSCTL_QUERY_ALLOCATED_RANGES
:
1557 /* FIXME: This is just a dummy reply, telling that all of the
1558 * file is allocated. MKS cp needs that.
1559 * Adding the real allocated ranges via FIEMAP on Linux
1560 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1561 * this FSCTL correct for sparse files.
1563 uint64_t offset
, length
;
1564 char *out_data_tmp
= NULL
;
1567 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1569 return NT_STATUS_INVALID_PARAMETER
;
1572 if (max_out_len
< 16) {
1573 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1575 return NT_STATUS_INVALID_PARAMETER
;
1578 offset
= BVAL(in_data
,0);
1579 length
= BVAL(in_data
,8);
1581 if (offset
+ length
< offset
) {
1582 /* No 64-bit integer wrap. */
1583 return NT_STATUS_INVALID_PARAMETER
;
1586 /* Shouldn't this be SMB_VFS_STAT ... ? */
1587 status
= vfs_stat_fsp(fsp
);
1588 if (!NT_STATUS_IS_OK(status
)) {
1593 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1594 if (out_data_tmp
== NULL
) {
1595 DEBUG(10, ("unable to allocate memory for response\n"));
1596 return NT_STATUS_NO_MEMORY
;
1599 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1600 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1602 memset(out_data_tmp
, 0, *out_len
);
1604 uint64_t end
= offset
+ length
;
1605 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1606 SBVAL(out_data_tmp
, 0, 0);
1607 SBVAL(out_data_tmp
, 8, end
);
1610 *out_data
= out_data_tmp
;
1612 return NT_STATUS_OK
;
1615 case FSCTL_IS_VOLUME_DIRTY
:
1617 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1618 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1620 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1621 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1623 return NT_STATUS_INVALID_PARAMETER
;
1628 * Only print once ... unfortunately there could be lots of
1629 * different FSCTLs that are called.
1631 if (!vfswrap_logged_ioctl_message
) {
1632 vfswrap_logged_ioctl_message
= true;
1633 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1634 __func__
, function
));
1638 return NT_STATUS_NOT_SUPPORTED
;
1641 static bool vfswrap_is_offline(struct connection_struct
*conn
,
1642 const struct smb_filename
*fname
);
1644 static NTSTATUS
vfswrap_get_dos_attributes(struct vfs_handle_struct
*handle
,
1645 struct smb_filename
*smb_fname
,
1650 offline
= vfswrap_is_offline(handle
->conn
, smb_fname
);
1652 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1655 return get_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1658 struct vfswrap_get_dos_attributes_state
{
1659 struct vfs_aio_state aio_state
;
1660 connection_struct
*conn
;
1661 TALLOC_CTX
*mem_ctx
;
1662 struct tevent_context
*ev
;
1663 files_struct
*dir_fsp
;
1664 struct smb_filename
*smb_fname
;
1669 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req
*subreq
);
1671 static struct tevent_req
*vfswrap_get_dos_attributes_send(
1672 TALLOC_CTX
*mem_ctx
,
1673 struct tevent_context
*ev
,
1674 struct vfs_handle_struct
*handle
,
1675 files_struct
*dir_fsp
,
1676 struct smb_filename
*smb_fname
)
1678 struct tevent_req
*req
= NULL
;
1679 struct tevent_req
*subreq
= NULL
;
1680 struct vfswrap_get_dos_attributes_state
*state
= NULL
;
1682 req
= tevent_req_create(mem_ctx
, &state
,
1683 struct vfswrap_get_dos_attributes_state
);
1688 *state
= (struct vfswrap_get_dos_attributes_state
) {
1689 .conn
= dir_fsp
->conn
,
1693 .smb_fname
= smb_fname
,
1696 subreq
= SMB_VFS_GETXATTRAT_SEND(state
,
1700 SAMBA_XATTR_DOS_ATTRIB
,
1702 if (tevent_req_nomem(subreq
, req
)) {
1703 return tevent_req_post(req
, ev
);
1705 tevent_req_set_callback(subreq
,
1706 vfswrap_get_dos_attributes_getxattr_done
,
1712 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req
*subreq
)
1714 struct tevent_req
*req
=
1715 tevent_req_callback_data(subreq
,
1717 struct vfswrap_get_dos_attributes_state
*state
=
1718 tevent_req_data(req
,
1719 struct vfswrap_get_dos_attributes_state
);
1721 DATA_BLOB blob
= {0};
1723 char *tofree
= NULL
;
1724 char pathbuf
[PATH_MAX
+1];
1726 struct smb_filename smb_fname
;
1730 xattr_size
= SMB_VFS_GETXATTRAT_RECV(subreq
,
1734 TALLOC_FREE(subreq
);
1735 if (xattr_size
== -1) {
1736 status
= map_nt_error_from_unix(state
->aio_state
.error
);
1738 if (state
->as_root
) {
1739 tevent_req_nterror(req
, status
);
1742 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1743 tevent_req_nterror(req
, status
);
1747 state
->as_root
= true;
1750 subreq
= SMB_VFS_GETXATTRAT_SEND(state
,
1754 SAMBA_XATTR_DOS_ATTRIB
,
1757 if (tevent_req_nomem(subreq
, req
)) {
1760 tevent_req_set_callback(subreq
,
1761 vfswrap_get_dos_attributes_getxattr_done
,
1766 blob
.length
= xattr_size
;
1768 status
= parse_dos_attribute_blob(state
->smb_fname
,
1771 if (!NT_STATUS_IS_OK(status
)) {
1772 tevent_req_nterror(req
, status
);
1776 pathlen
= full_path_tos(state
->dir_fsp
->fsp_name
->base_name
,
1777 state
->smb_fname
->base_name
,
1782 if (pathlen
== -1) {
1783 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1787 smb_fname
= (struct smb_filename
) {
1789 .st
= state
->smb_fname
->st
,
1790 .flags
= state
->smb_fname
->flags
,
1793 offline
= vfswrap_is_offline(state
->conn
, &smb_fname
);
1795 state
->dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1797 TALLOC_FREE(tofree
);
1799 tevent_req_done(req
);
1803 static NTSTATUS
vfswrap_get_dos_attributes_recv(struct tevent_req
*req
,
1804 struct vfs_aio_state
*aio_state
,
1807 struct vfswrap_get_dos_attributes_state
*state
=
1808 tevent_req_data(req
,
1809 struct vfswrap_get_dos_attributes_state
);
1812 if (tevent_req_is_nterror(req
, &status
)) {
1813 tevent_req_received(req
);
1817 *aio_state
= state
->aio_state
;
1818 *dosmode
= state
->dosmode
;
1819 tevent_req_received(req
);
1820 return NT_STATUS_OK
;
1823 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1824 struct files_struct
*fsp
,
1829 offline
= vfswrap_is_offline(handle
->conn
, fsp
->fsp_name
);
1831 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1834 return get_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1837 static NTSTATUS
vfswrap_set_dos_attributes(struct vfs_handle_struct
*handle
,
1838 const struct smb_filename
*smb_fname
,
1841 return set_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1844 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1845 struct files_struct
*fsp
,
1848 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1851 static struct vfs_offload_ctx
*vfswrap_offload_ctx
;
1853 struct vfswrap_offload_read_state
{
1857 static struct tevent_req
*vfswrap_offload_read_send(
1858 TALLOC_CTX
*mem_ctx
,
1859 struct tevent_context
*ev
,
1860 struct vfs_handle_struct
*handle
,
1861 struct files_struct
*fsp
,
1867 struct tevent_req
*req
= NULL
;
1868 struct vfswrap_offload_read_state
*state
= NULL
;
1871 req
= tevent_req_create(mem_ctx
, &state
,
1872 struct vfswrap_offload_read_state
);
1877 status
= vfs_offload_token_ctx_init(fsp
->conn
->sconn
->client
,
1878 &vfswrap_offload_ctx
);
1879 if (tevent_req_nterror(req
, status
)) {
1880 return tevent_req_post(req
, ev
);
1883 if (fsctl
!= FSCTL_SRV_REQUEST_RESUME_KEY
) {
1884 tevent_req_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
1885 return tevent_req_post(req
, ev
);
1888 status
= vfs_offload_token_create_blob(state
, fsp
, fsctl
,
1890 if (tevent_req_nterror(req
, status
)) {
1891 return tevent_req_post(req
, ev
);
1894 status
= vfs_offload_token_db_store_fsp(vfswrap_offload_ctx
, fsp
,
1896 if (tevent_req_nterror(req
, status
)) {
1897 return tevent_req_post(req
, ev
);
1900 tevent_req_done(req
);
1901 return tevent_req_post(req
, ev
);
1904 static NTSTATUS
vfswrap_offload_read_recv(struct tevent_req
*req
,
1905 struct vfs_handle_struct
*handle
,
1906 TALLOC_CTX
*mem_ctx
,
1909 struct vfswrap_offload_read_state
*state
= tevent_req_data(
1910 req
, struct vfswrap_offload_read_state
);
1913 if (tevent_req_is_nterror(req
, &status
)) {
1914 tevent_req_received(req
);
1918 token
->length
= state
->token
.length
;
1919 token
->data
= talloc_move(mem_ctx
, &state
->token
.data
);
1921 tevent_req_received(req
);
1922 return NT_STATUS_OK
;
1925 struct vfswrap_offload_write_state
{
1927 bool read_lck_locked
;
1928 bool write_lck_locked
;
1930 struct tevent_context
*src_ev
;
1931 struct files_struct
*src_fsp
;
1933 struct tevent_context
*dst_ev
;
1934 struct files_struct
*dst_fsp
;
1938 size_t next_io_size
;
1941 static void vfswrap_offload_write_cleanup(struct tevent_req
*req
,
1942 enum tevent_req_state req_state
)
1944 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1945 req
, struct vfswrap_offload_write_state
);
1948 if (state
->dst_fsp
== NULL
) {
1952 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
1954 state
->dst_fsp
= NULL
;
1957 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
);
1959 static struct tevent_req
*vfswrap_offload_write_send(
1960 struct vfs_handle_struct
*handle
,
1961 TALLOC_CTX
*mem_ctx
,
1962 struct tevent_context
*ev
,
1965 off_t transfer_offset
,
1966 struct files_struct
*dest_fsp
,
1970 struct tevent_req
*req
;
1971 struct vfswrap_offload_write_state
*state
= NULL
;
1972 /* off_t is signed! */
1973 off_t max_offset
= INT64_MAX
- to_copy
;
1974 size_t num
= MIN(to_copy
, COPYCHUNK_MAX_TOTAL_LEN
);
1975 files_struct
*src_fsp
= NULL
;
1979 req
= tevent_req_create(mem_ctx
, &state
,
1980 struct vfswrap_offload_write_state
);
1985 *state
= (struct vfswrap_offload_write_state
) {
1987 .src_off
= transfer_offset
,
1989 .dst_fsp
= dest_fsp
,
1990 .dst_off
= dest_off
,
1992 .remaining
= to_copy
,
1995 tevent_req_set_cleanup_fn(req
, vfswrap_offload_write_cleanup
);
1998 case FSCTL_SRV_COPYCHUNK
:
1999 case FSCTL_SRV_COPYCHUNK_WRITE
:
2002 case FSCTL_OFFLOAD_WRITE
:
2003 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2004 return tevent_req_post(req
, ev
);
2006 case FSCTL_DUP_EXTENTS_TO_FILE
:
2007 DBG_DEBUG("COW clones not supported by vfs_default\n");
2008 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2009 return tevent_req_post(req
, ev
);
2012 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2013 return tevent_req_post(req
, ev
);
2017 * From here on we assume a copy-chunk fsctl
2021 tevent_req_done(req
);
2022 return tevent_req_post(req
, ev
);
2025 if (state
->src_off
> max_offset
) {
2027 * Protect integer checks below.
2029 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2030 return tevent_req_post(req
, ev
);
2032 if (state
->src_off
< 0) {
2034 * Protect integer checks below.
2036 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2037 return tevent_req_post(req
, ev
);
2039 if (state
->dst_off
> max_offset
) {
2041 * Protect integer checks below.
2043 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2044 return tevent_req_post(req
, ev
);
2046 if (state
->dst_off
< 0) {
2048 * Protect integer checks below.
2050 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2051 return tevent_req_post(req
, ev
);
2054 status
= vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx
,
2056 if (tevent_req_nterror(req
, status
)) {
2057 return tevent_req_post(req
, ev
);
2060 DBG_DEBUG("server side copy chunk of length %" PRIu64
"\n", to_copy
);
2062 status
= vfs_offload_token_check_handles(fsctl
, src_fsp
, dest_fsp
);
2063 if (!NT_STATUS_IS_OK(status
)) {
2064 tevent_req_nterror(req
, status
);
2065 return tevent_req_post(req
, ev
);
2068 ok
= change_to_user_and_service_by_fsp(src_fsp
);
2070 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2071 return tevent_req_post(req
, ev
);
2074 state
->src_ev
= src_fsp
->conn
->sconn
->ev_ctx
;
2075 state
->src_fsp
= src_fsp
;
2077 status
= vfs_stat_fsp(src_fsp
);
2078 if (tevent_req_nterror(req
, status
)) {
2079 return tevent_req_post(req
, ev
);
2082 if (src_fsp
->fsp_name
->st
.st_ex_size
< state
->src_off
+ to_copy
) {
2084 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2085 * If the SourceOffset or SourceOffset + Length extends beyond
2086 * the end of file, the server SHOULD<240> treat this as a
2087 * STATUS_END_OF_FILE error.
2089 * <240> Section 3.3.5.15.6: Windows servers will return
2090 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2092 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
2093 return tevent_req_post(req
, ev
);
2096 state
->buf
= talloc_array(state
, uint8_t, num
);
2097 if (tevent_req_nomem(state
->buf
, req
)) {
2098 return tevent_req_post(req
, ev
);
2101 status
= vfswrap_offload_write_loop(req
);
2102 if (!NT_STATUS_IS_OK(status
)) {
2103 tevent_req_nterror(req
, status
);
2104 return tevent_req_post(req
, ev
);
2110 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
);
2112 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
)
2114 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2115 req
, struct vfswrap_offload_write_state
);
2116 struct tevent_req
*subreq
= NULL
;
2117 struct lock_struct read_lck
;
2121 * This is called under the context of state->src_fsp.
2124 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
2126 init_strict_lock_struct(state
->src_fsp
,
2127 state
->src_fsp
->op
->global
->open_persistent_id
,
2129 state
->next_io_size
,
2133 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
2137 return NT_STATUS_FILE_LOCK_CONFLICT
;
2140 subreq
= SMB_VFS_PREAD_SEND(state
,
2144 state
->next_io_size
,
2146 if (subreq
== NULL
) {
2147 return NT_STATUS_NO_MEMORY
;
2149 tevent_req_set_callback(subreq
, vfswrap_offload_write_read_done
, req
);
2151 return NT_STATUS_OK
;
2154 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
);
2156 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
)
2158 struct tevent_req
*req
= tevent_req_callback_data(
2159 subreq
, struct tevent_req
);
2160 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2161 req
, struct vfswrap_offload_write_state
);
2162 struct vfs_aio_state aio_state
;
2163 struct lock_struct write_lck
;
2167 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
2168 TALLOC_FREE(subreq
);
2170 DBG_ERR("read failed: %s\n", strerror(aio_state
.error
));
2171 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2174 if (nread
!= state
->next_io_size
) {
2175 DBG_ERR("Short read, only %zd of %zu\n",
2176 nread
, state
->next_io_size
);
2177 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2181 state
->src_off
+= nread
;
2183 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2185 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2189 init_strict_lock_struct(state
->dst_fsp
,
2190 state
->dst_fsp
->op
->global
->open_persistent_id
,
2192 state
->next_io_size
,
2196 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
2200 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
2204 subreq
= SMB_VFS_PWRITE_SEND(state
,
2208 state
->next_io_size
,
2210 if (subreq
== NULL
) {
2211 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2214 tevent_req_set_callback(subreq
, vfswrap_offload_write_write_done
, req
);
2217 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
)
2219 struct tevent_req
*req
= tevent_req_callback_data(
2220 subreq
, struct tevent_req
);
2221 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2222 req
, struct vfswrap_offload_write_state
);
2223 struct vfs_aio_state aio_state
;
2228 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
2229 TALLOC_FREE(subreq
);
2230 if (nwritten
== -1) {
2231 DBG_ERR("write failed: %s\n", strerror(aio_state
.error
));
2232 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2235 if (nwritten
!= state
->next_io_size
) {
2236 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
2237 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2241 state
->dst_off
+= nwritten
;
2243 if (state
->remaining
< nwritten
) {
2244 /* Paranoia check */
2245 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2248 state
->remaining
-= nwritten
;
2249 if (state
->remaining
== 0) {
2250 tevent_req_done(req
);
2254 ok
= change_to_user_and_service_by_fsp(state
->src_fsp
);
2256 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2260 status
= vfswrap_offload_write_loop(req
);
2261 if (!NT_STATUS_IS_OK(status
)) {
2262 tevent_req_nterror(req
, status
);
2269 static NTSTATUS
vfswrap_offload_write_recv(struct vfs_handle_struct
*handle
,
2270 struct tevent_req
*req
,
2273 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2274 req
, struct vfswrap_offload_write_state
);
2277 if (tevent_req_is_nterror(req
, &status
)) {
2278 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
2280 tevent_req_received(req
);
2284 *copied
= state
->to_copy
;
2285 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
2286 tevent_req_received(req
);
2288 return NT_STATUS_OK
;
2291 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
2292 TALLOC_CTX
*mem_ctx
,
2293 struct files_struct
*fsp
,
2294 struct smb_filename
*smb_fname
,
2295 uint16_t *_compression_fmt
)
2297 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2300 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
2301 TALLOC_CTX
*mem_ctx
,
2302 struct files_struct
*fsp
,
2303 uint16_t compression_fmt
)
2305 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2308 /********************************************************************
2309 Given a stat buffer return the allocated size on disk, taking into
2310 account sparse files.
2311 ********************************************************************/
2312 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
2313 struct files_struct
*fsp
,
2314 const SMB_STRUCT_STAT
*sbuf
)
2318 START_PROFILE(syscall_get_alloc_size
);
2320 if(S_ISDIR(sbuf
->st_ex_mode
)) {
2325 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2326 /* The type of st_blocksize is blkcnt_t which *MUST* be
2327 signed (according to POSIX) and can be less than 64-bits.
2328 Ensure when we're converting to 64 bits wide we don't
2330 #if defined(SIZEOF_BLKCNT_T_8)
2331 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
2332 #elif defined(SIZEOF_BLKCNT_T_4)
2334 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
2335 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
2338 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2342 * Some file systems do not allocate a block for very
2343 * small files. But for non-empty file should report a
2347 uint64_t filesize
= get_file_size_stat(sbuf
);
2349 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
2353 result
= get_file_size_stat(sbuf
);
2356 if (fsp
&& fsp
->initial_allocation_size
)
2357 result
= MAX(result
,fsp
->initial_allocation_size
);
2359 result
= smb_roundup(handle
->conn
, result
);
2362 END_PROFILE(syscall_get_alloc_size
);
2366 static int vfswrap_unlinkat(vfs_handle_struct
*handle
,
2367 struct files_struct
*dirfsp
,
2368 const struct smb_filename
*smb_fname
,
2373 START_PROFILE(syscall_unlinkat
);
2375 SMB_ASSERT(dirfsp
== dirfsp
->conn
->cwd_fsp
);
2377 if (is_named_stream(smb_fname
)) {
2381 result
= unlinkat(dirfsp
->fh
->fd
,
2382 smb_fname
->base_name
,
2386 END_PROFILE(syscall_unlinkat
);
2390 static int vfswrap_chmod(vfs_handle_struct
*handle
,
2391 const struct smb_filename
*smb_fname
,
2396 START_PROFILE(syscall_chmod
);
2397 result
= chmod(smb_fname
->base_name
, mode
);
2398 END_PROFILE(syscall_chmod
);
2402 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2406 START_PROFILE(syscall_fchmod
);
2407 #if defined(HAVE_FCHMOD)
2408 result
= fchmod(fsp
->fh
->fd
, mode
);
2414 END_PROFILE(syscall_fchmod
);
2418 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2423 START_PROFILE(syscall_fchown
);
2424 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
2425 END_PROFILE(syscall_fchown
);
2433 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2434 const struct smb_filename
*smb_fname
,
2440 START_PROFILE(syscall_lchown
);
2441 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2442 END_PROFILE(syscall_lchown
);
2446 static int vfswrap_chdir(vfs_handle_struct
*handle
,
2447 const struct smb_filename
*smb_fname
)
2451 START_PROFILE(syscall_chdir
);
2452 result
= chdir(smb_fname
->base_name
);
2453 END_PROFILE(syscall_chdir
);
2457 static struct smb_filename
*vfswrap_getwd(vfs_handle_struct
*handle
,
2461 struct smb_filename
*smb_fname
= NULL
;
2463 START_PROFILE(syscall_getwd
);
2464 result
= sys_getwd();
2465 END_PROFILE(syscall_getwd
);
2467 if (result
== NULL
) {
2470 smb_fname
= synthetic_smb_fname(ctx
,
2476 * sys_getwd() *always* returns malloced memory.
2477 * We must free here to avoid leaks:
2478 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2484 /*********************************************************************
2485 nsec timestamp resolution call. Convert down to whatever the underlying
2486 system will support.
2487 **********************************************************************/
2489 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
2490 const struct smb_filename
*smb_fname
,
2491 struct smb_file_time
*ft
)
2495 START_PROFILE(syscall_ntimes
);
2497 if (is_named_stream(smb_fname
)) {
2503 if (is_omit_timespec(&ft
->atime
)) {
2504 ft
->atime
= smb_fname
->st
.st_ex_atime
;
2507 if (is_omit_timespec(&ft
->mtime
)) {
2508 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
2511 if (!is_omit_timespec(&ft
->create_time
)) {
2512 set_create_timespec_ea(handle
->conn
,
2517 if ((timespec_compare(&ft
->atime
,
2518 &smb_fname
->st
.st_ex_atime
) == 0) &&
2519 (timespec_compare(&ft
->mtime
,
2520 &smb_fname
->st
.st_ex_mtime
) == 0)) {
2525 #if defined(HAVE_UTIMENSAT)
2527 struct timespec ts
[2];
2530 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
2532 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
2534 if (!((result
== -1) && (errno
== ENOSYS
))) {
2538 #if defined(HAVE_UTIMES)
2540 struct timeval tv
[2];
2541 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
2542 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
2543 result
= utimes(smb_fname
->base_name
, tv
);
2545 result
= utimes(smb_fname
->base_name
, NULL
);
2547 if (!((result
== -1) && (errno
== ENOSYS
))) {
2551 #if defined(HAVE_UTIME)
2553 struct utimbuf times
;
2554 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
2555 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
2556 result
= utime(smb_fname
->base_name
, ×
);
2558 result
= utime(smb_fname
->base_name
, NULL
);
2560 if (!((result
== -1) && (errno
== ENOSYS
))) {
2568 END_PROFILE(syscall_ntimes
);
2572 /*********************************************************************
2573 A version of ftruncate that will write the space on disk if strict
2575 **********************************************************************/
2577 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2579 off_t space_to_write
;
2580 uint64_t space_avail
;
2581 uint64_t bsize
,dfree
,dsize
;
2584 SMB_STRUCT_STAT
*pst
;
2587 ok
= vfs_valid_pwrite_range(len
, 0);
2593 status
= vfs_stat_fsp(fsp
);
2594 if (!NT_STATUS_IS_OK(status
)) {
2597 pst
= &fsp
->fsp_name
->st
;
2600 if (S_ISFIFO(pst
->st_ex_mode
))
2604 if (pst
->st_ex_size
== len
)
2607 /* Shrink - just ftruncate. */
2608 if (pst
->st_ex_size
> len
)
2609 return ftruncate(fsp
->fh
->fd
, len
);
2611 space_to_write
= len
- pst
->st_ex_size
;
2613 /* for allocation try fallocate first. This can fail on some
2614 platforms e.g. when the filesystem doesn't support it and no
2615 emulation is being done by the libc (like on AIX with JFS1). In that
2616 case we do our own emulation. fallocate implementations can
2617 return ENOTSUP or EINVAL in cases like that. */
2618 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2619 if (ret
== -1 && errno
== ENOSPC
) {
2625 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2626 "error %d. Falling back to slow manual allocation\n", errno
));
2628 /* available disk space is enough or not? */
2630 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2631 /* space_avail is 1k blocks */
2632 if (space_avail
== (uint64_t)-1 ||
2633 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2638 /* Write out the real space on disk. */
2639 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2647 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2650 SMB_STRUCT_STAT
*pst
;
2654 START_PROFILE(syscall_ftruncate
);
2656 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
2657 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2658 END_PROFILE(syscall_ftruncate
);
2662 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2663 ftruncate if the system supports it. Then I discovered that
2664 you can have some filesystems that support ftruncate
2665 expansion and some that don't! On Linux fat can't do
2666 ftruncate extend but ext2 can. */
2668 result
= ftruncate(fsp
->fh
->fd
, len
);
2670 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2671 extend a file with ftruncate. Provide alternate implementation
2674 /* Do an fstat to see if the file is longer than the requested
2675 size in which case the ftruncate above should have
2676 succeeded or shorter, in which case seek to len - 1 and
2677 write 1 byte of zero */
2678 status
= vfs_stat_fsp(fsp
);
2679 if (!NT_STATUS_IS_OK(status
)) {
2683 /* We need to update the files_struct after successful ftruncate */
2688 pst
= &fsp
->fsp_name
->st
;
2691 if (S_ISFIFO(pst
->st_ex_mode
)) {
2697 if (pst
->st_ex_size
== len
) {
2702 if (pst
->st_ex_size
> len
) {
2703 /* the ftruncate should have worked */
2707 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
2715 END_PROFILE(syscall_ftruncate
);
2719 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
2727 START_PROFILE(syscall_fallocate
);
2729 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
2731 * posix_fallocate returns 0 on success, errno on error
2732 * and doesn't set errno. Make it behave like fallocate()
2733 * which returns -1, and sets errno on failure.
2740 /* sys_fallocate handles filtering of unsupported mode flags */
2741 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
2743 END_PROFILE(syscall_fallocate
);
2747 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
2751 START_PROFILE(syscall_fcntl_lock
);
2753 if (fsp
->use_ofd_locks
) {
2754 op
= map_process_lock_to_ofd_lock(op
);
2757 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
2758 END_PROFILE(syscall_fcntl_lock
);
2762 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2763 uint32_t share_access
, uint32_t access_mask
)
2765 START_PROFILE(syscall_kernel_flock
);
2766 kernel_flock(fsp
->fh
->fd
, share_access
, access_mask
);
2767 END_PROFILE(syscall_kernel_flock
);
2771 static int vfswrap_fcntl(vfs_handle_struct
*handle
, files_struct
*fsp
, int cmd
,
2775 va_list dup_cmd_arg
;
2779 START_PROFILE(syscall_fcntl
);
2781 va_copy(dup_cmd_arg
, cmd_arg
);
2787 #if defined(HAVE_OFD_LOCKS)
2792 #if defined(HAVE_F_OWNER_EX)
2796 #if defined(HAVE_RW_HINTS)
2799 case F_GET_FILE_RW_HINT
:
2800 case F_SET_FILE_RW_HINT
:
2802 argp
= va_arg(dup_cmd_arg
, void *);
2803 result
= sys_fcntl_ptr(fsp
->fh
->fd
, cmd
, argp
);
2806 val
= va_arg(dup_cmd_arg
, int);
2807 result
= sys_fcntl_int(fsp
->fh
->fd
, cmd
, val
);
2810 va_end(dup_cmd_arg
);
2812 END_PROFILE(syscall_fcntl
);
2816 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2821 START_PROFILE(syscall_fcntl_getlock
);
2823 if (fsp
->use_ofd_locks
) {
2824 op
= map_process_lock_to_ofd_lock(op
);
2827 result
= fcntl_getlock(fsp
->fh
->fd
, op
, poffset
, pcount
, ptype
, ppid
);
2828 END_PROFILE(syscall_fcntl_getlock
);
2832 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2837 START_PROFILE(syscall_linux_setlease
);
2839 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2840 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2844 END_PROFILE(syscall_linux_setlease
);
2848 static int vfswrap_symlinkat(vfs_handle_struct
*handle
,
2849 const char *link_target
,
2850 struct files_struct
*dirfsp
,
2851 const struct smb_filename
*new_smb_fname
)
2855 START_PROFILE(syscall_symlinkat
);
2857 SMB_ASSERT(dirfsp
== dirfsp
->conn
->cwd_fsp
);
2859 result
= symlinkat(link_target
,
2861 new_smb_fname
->base_name
);
2862 END_PROFILE(syscall_symlinkat
);
2866 static int vfswrap_readlinkat(vfs_handle_struct
*handle
,
2867 files_struct
*dirfsp
,
2868 const struct smb_filename
*smb_fname
,
2874 START_PROFILE(syscall_readlinkat
);
2876 SMB_ASSERT(dirfsp
== dirfsp
->conn
->cwd_fsp
);
2878 result
= readlinkat(dirfsp
->fh
->fd
,
2879 smb_fname
->base_name
,
2883 END_PROFILE(syscall_readlinkat
);
2887 static int vfswrap_linkat(vfs_handle_struct
*handle
,
2888 files_struct
*srcfsp
,
2889 const struct smb_filename
*old_smb_fname
,
2890 files_struct
*dstfsp
,
2891 const struct smb_filename
*new_smb_fname
,
2896 START_PROFILE(syscall_linkat
);
2898 SMB_ASSERT(srcfsp
== srcfsp
->conn
->cwd_fsp
);
2899 SMB_ASSERT(dstfsp
== dstfsp
->conn
->cwd_fsp
);
2901 result
= linkat(srcfsp
->fh
->fd
,
2902 old_smb_fname
->base_name
,
2904 new_smb_fname
->base_name
,
2907 END_PROFILE(syscall_linkat
);
2911 static int vfswrap_mknodat(vfs_handle_struct
*handle
,
2912 files_struct
*dirfsp
,
2913 const struct smb_filename
*smb_fname
,
2919 START_PROFILE(syscall_mknodat
);
2921 SMB_ASSERT(dirfsp
== dirfsp
->conn
->cwd_fsp
);
2923 result
= sys_mknodat(dirfsp
->fh
->fd
,
2924 smb_fname
->base_name
,
2928 END_PROFILE(syscall_mknodat
);
2932 static struct smb_filename
*vfswrap_realpath(vfs_handle_struct
*handle
,
2934 const struct smb_filename
*smb_fname
)
2937 struct smb_filename
*result_fname
= NULL
;
2939 START_PROFILE(syscall_realpath
);
2940 result
= sys_realpath(smb_fname
->base_name
);
2941 END_PROFILE(syscall_realpath
);
2943 result_fname
= synthetic_smb_fname(ctx
, result
, NULL
, NULL
, 0);
2946 return result_fname
;
2949 static int vfswrap_chflags(vfs_handle_struct
*handle
,
2950 const struct smb_filename
*smb_fname
,
2954 return chflags(smb_fname
->base_name
, flags
);
2961 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2962 const SMB_STRUCT_STAT
*sbuf
)
2966 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2970 key
.devid
= sbuf
->st_ex_dev
;
2971 key
.inode
= sbuf
->st_ex_ino
;
2972 /* key.extid is unused by default. */
2977 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct
*handle
,
2978 const SMB_STRUCT_STAT
*psbuf
)
2982 if (!(psbuf
->st_ex_iflags
& ST_EX_IFLAG_CALCULATED_FILE_ID
)) {
2983 return psbuf
->st_ex_file_id
;
2986 if (handle
->conn
->base_share_dev
== psbuf
->st_ex_dev
) {
2987 return (uint64_t)psbuf
->st_ex_ino
;
2991 file_id
= ((psbuf
->st_ex_ino
) & UINT32_MAX
);
2994 file_id
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32;
2999 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
3000 struct files_struct
*fsp
,
3001 const struct smb_filename
*smb_fname
,
3002 TALLOC_CTX
*mem_ctx
,
3003 unsigned int *pnum_streams
,
3004 struct stream_struct
**pstreams
)
3006 SMB_STRUCT_STAT sbuf
;
3007 struct stream_struct
*tmp_streams
= NULL
;
3010 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
3012 * No default streams on directories
3017 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
3018 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
3021 struct smb_filename smb_fname_cp
;
3023 ZERO_STRUCT(smb_fname_cp
);
3024 smb_fname_cp
.base_name
= discard_const_p(char,
3025 smb_fname
->base_name
);
3026 smb_fname_cp
.flags
= smb_fname
->flags
;
3028 if (smb_fname_cp
.flags
& SMB_FILENAME_POSIX_PATH
) {
3029 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname_cp
);
3031 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname_cp
);
3033 sbuf
= smb_fname_cp
.st
;
3037 return map_nt_error_from_unix(errno
);
3040 if (S_ISDIR(sbuf
.st_ex_mode
)) {
3044 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
3045 (*pnum_streams
) + 1);
3046 if (tmp_streams
== NULL
) {
3047 return NT_STATUS_NO_MEMORY
;
3049 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
3050 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
3051 return NT_STATUS_NO_MEMORY
;
3053 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
3054 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
3057 *pstreams
= tmp_streams
;
3059 return NT_STATUS_OK
;
3062 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
3065 TALLOC_CTX
*mem_ctx
,
3069 * Don't fall back to get_real_filename so callers can differentiate
3070 * between a full directory scan and an actual case-insensitive stat.
3076 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
3077 const struct smb_filename
*smb_fname
)
3079 return handle
->conn
->connectpath
;
3082 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
3083 struct byte_range_lock
*br_lck
,
3084 struct lock_struct
*plock
)
3086 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3088 /* Note: blr is not used in the default implementation. */
3089 return brl_lock_windows_default(br_lck
, plock
);
3092 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
3093 struct byte_range_lock
*br_lck
,
3094 const struct lock_struct
*plock
)
3096 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3098 return brl_unlock_windows_default(br_lck
, plock
);
3101 static bool vfswrap_strict_lock_check(struct vfs_handle_struct
*handle
,
3103 struct lock_struct
*plock
)
3105 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
3106 plock
->lock_type
== WRITE_LOCK
);
3108 return strict_lock_check_default(fsp
, plock
);
3111 /* NT ACL operations. */
3113 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
3115 uint32_t security_info
,
3116 TALLOC_CTX
*mem_ctx
,
3117 struct security_descriptor
**ppdesc
)
3121 START_PROFILE(fget_nt_acl
);
3122 result
= posix_fget_nt_acl(fsp
, security_info
,
3124 END_PROFILE(fget_nt_acl
);
3128 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
3129 const struct smb_filename
*smb_fname
,
3130 uint32_t security_info
,
3131 TALLOC_CTX
*mem_ctx
,
3132 struct security_descriptor
**ppdesc
)
3136 START_PROFILE(get_nt_acl
);
3137 result
= posix_get_nt_acl(handle
->conn
,
3142 END_PROFILE(get_nt_acl
);
3146 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
3150 START_PROFILE(fset_nt_acl
);
3151 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
3152 END_PROFILE(fset_nt_acl
);
3156 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
3157 struct smb_filename
*file
,
3158 struct security_acl
*sacl
,
3159 uint32_t access_requested
,
3160 uint32_t access_denied
)
3162 return NT_STATUS_OK
; /* Nothing to do here ... */
3165 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
3166 const struct smb_filename
*smb_fname
,
3167 SMB_ACL_TYPE_T type
,
3168 TALLOC_CTX
*mem_ctx
)
3170 return sys_acl_get_file(handle
, smb_fname
, type
, mem_ctx
);
3173 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
3175 TALLOC_CTX
*mem_ctx
)
3177 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
3180 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
,
3181 const struct smb_filename
*smb_fname
,
3182 SMB_ACL_TYPE_T acltype
,
3185 return sys_acl_set_file(handle
, smb_fname
, acltype
, theacl
);
3188 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
3190 return sys_acl_set_fd(handle
, fsp
, theacl
);
3193 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
3194 const struct smb_filename
*smb_fname
)
3196 return sys_acl_delete_def_file(handle
, smb_fname
);
3199 /****************************************************************
3200 Extended attribute operations.
3201 *****************************************************************/
3203 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,
3204 const struct smb_filename
*smb_fname
,
3209 return getxattr(smb_fname
->base_name
, name
, value
, size
);
3212 struct vfswrap_getxattrat_state
{
3213 struct tevent_context
*ev
;
3214 files_struct
*dir_fsp
;
3215 const struct smb_filename
*smb_fname
;
3216 struct tevent_req
*req
;
3219 * The following variables are talloced off "state" which is protected
3220 * by a destructor and thus are guaranteed to be safe to be used in the
3221 * job function in the worker thread.
3224 const char *xattr_name
;
3225 uint8_t *xattr_value
;
3226 struct security_unix_token
*token
;
3229 struct vfs_aio_state vfs_aio_state
;
3230 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
3233 static int vfswrap_getxattrat_state_destructor(
3234 struct vfswrap_getxattrat_state
*state
)
3239 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
);
3240 static void vfswrap_getxattrat_do_async(void *private_data
);
3241 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
);
3243 static struct tevent_req
*vfswrap_getxattrat_send(
3244 TALLOC_CTX
*mem_ctx
,
3245 struct tevent_context
*ev
,
3246 struct vfs_handle_struct
*handle
,
3247 files_struct
*dir_fsp
,
3248 const struct smb_filename
*smb_fname
,
3249 const char *xattr_name
,
3252 struct tevent_req
*req
= NULL
;
3253 struct tevent_req
*subreq
= NULL
;
3254 struct vfswrap_getxattrat_state
*state
= NULL
;
3255 size_t max_threads
= 0;
3256 bool have_per_thread_cwd
= false;
3257 bool have_per_thread_creds
= false;
3258 bool do_async
= false;
3260 req
= tevent_req_create(mem_ctx
, &state
,
3261 struct vfswrap_getxattrat_state
);
3265 *state
= (struct vfswrap_getxattrat_state
) {
3268 .smb_fname
= smb_fname
,
3272 max_threads
= pthreadpool_tevent_max_threads(dir_fsp
->conn
->sconn
->pool
);
3273 if (max_threads
>= 1) {
3275 * We need a non sync threadpool!
3277 have_per_thread_cwd
= per_thread_cwd_supported();
3279 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3280 have_per_thread_creds
= true;
3282 if (have_per_thread_cwd
&& have_per_thread_creds
) {
3286 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat
, profile_p
,
3287 state
->profile_bytes
, 0);
3289 if (dir_fsp
->fh
->fd
== -1) {
3290 DBG_ERR("Need a valid directory fd\n");
3291 tevent_req_error(req
, EINVAL
);
3292 return tevent_req_post(req
, ev
);
3295 if (alloc_hint
> 0) {
3296 state
->xattr_value
= talloc_zero_array(state
,
3299 if (tevent_req_nomem(state
->xattr_value
, req
)) {
3300 return tevent_req_post(req
, ev
);
3305 vfswrap_getxattrat_do_sync(req
);
3306 return tevent_req_post(req
, ev
);
3310 * Now allocate all parameters from a memory context that won't go away
3311 * no matter what. These paremeters will get used in threads and we
3312 * can't reliably cancel threads, so all buffers passed to the threads
3313 * must not be freed before all referencing threads terminate.
3316 state
->name
= talloc_strdup(state
, smb_fname
->base_name
);
3317 if (tevent_req_nomem(state
->name
, req
)) {
3318 return tevent_req_post(req
, ev
);
3321 state
->xattr_name
= talloc_strdup(state
, xattr_name
);
3322 if (tevent_req_nomem(state
->xattr_name
, req
)) {
3323 return tevent_req_post(req
, ev
);
3327 * This is a hot codepath so at first glance one might think we should
3328 * somehow optimize away the token allocation and do a
3329 * talloc_reference() or similar black magic instead. But due to the
3330 * talloc_stackframe pool per SMB2 request this should be a simple copy
3331 * without a malloc in most cases.
3333 if (geteuid() == sec_initial_uid()) {
3334 state
->token
= root_unix_token(state
);
3336 state
->token
= copy_unix_token(
3338 dir_fsp
->conn
->session_info
->unix_token
);
3340 if (tevent_req_nomem(state
->token
, req
)) {
3341 return tevent_req_post(req
, ev
);
3344 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3346 subreq
= pthreadpool_tevent_job_send(
3349 dir_fsp
->conn
->sconn
->pool
,
3350 vfswrap_getxattrat_do_async
,
3352 if (tevent_req_nomem(subreq
, req
)) {
3353 return tevent_req_post(req
, ev
);
3355 tevent_req_set_callback(subreq
, vfswrap_getxattrat_done
, req
);
3357 talloc_set_destructor(state
, vfswrap_getxattrat_state_destructor
);
3362 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
)
3364 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3365 req
, struct vfswrap_getxattrat_state
);
3367 char *tofree
= NULL
;
3368 char pathbuf
[PATH_MAX
+1];
3372 pathlen
= full_path_tos(state
->dir_fsp
->fsp_name
->base_name
,
3373 state
->smb_fname
->base_name
,
3378 if (pathlen
== -1) {
3379 tevent_req_error(req
, ENOMEM
);
3383 state
->xattr_size
= getxattr(path
,
3386 talloc_array_length(state
->xattr_value
));
3388 TALLOC_FREE(tofree
);
3389 if (state
->xattr_size
== -1) {
3390 tevent_req_error(req
, err
);
3394 tevent_req_done(req
);
3398 static void vfswrap_getxattrat_do_async(void *private_data
)
3400 struct vfswrap_getxattrat_state
*state
= talloc_get_type_abort(
3401 private_data
, struct vfswrap_getxattrat_state
);
3402 struct timespec start_time
;
3403 struct timespec end_time
;
3406 PROFILE_TIMESTAMP(&start_time
);
3407 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
3410 * Here we simulate a getxattrat()
3411 * call using fchdir();getxattr()
3414 per_thread_cwd_activate();
3416 /* Become the correct credential on this thread. */
3417 ret
= set_thread_credentials(state
->token
->uid
,
3419 (size_t)state
->token
->ngroups
,
3420 state
->token
->groups
);
3422 state
->xattr_size
= -1;
3423 state
->vfs_aio_state
.error
= errno
;
3427 ret
= fchdir(state
->dir_fsp
->fh
->fd
);
3429 state
->xattr_size
= -1;
3430 state
->vfs_aio_state
.error
= errno
;
3434 state
->xattr_size
= getxattr(state
->name
,
3437 talloc_array_length(state
->xattr_value
));
3438 if (state
->xattr_size
== -1) {
3439 state
->vfs_aio_state
.error
= errno
;
3443 PROFILE_TIMESTAMP(&end_time
);
3444 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
3445 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3448 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
)
3450 struct tevent_req
*req
= tevent_req_callback_data(
3451 subreq
, struct tevent_req
);
3452 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3453 req
, struct vfswrap_getxattrat_state
);
3458 * Make sure we run as the user again
3460 ok
= change_to_user_and_service_by_fsp(state
->dir_fsp
);
3463 ret
= pthreadpool_tevent_job_recv(subreq
);
3464 TALLOC_FREE(subreq
);
3465 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
3466 talloc_set_destructor(state
, NULL
);
3468 if (ret
!= EAGAIN
) {
3469 tevent_req_error(req
, ret
);
3473 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3474 * means the lower level pthreadpool failed to create a new
3475 * thread. Fallback to sync processing in that case to allow
3476 * some progress for the client.
3478 vfswrap_getxattrat_do_sync(req
);
3482 if (state
->xattr_size
== -1) {
3483 tevent_req_error(req
, state
->vfs_aio_state
.error
);
3487 if (state
->xattr_value
== NULL
) {
3489 * The caller only wanted the size.
3491 tevent_req_done(req
);
3496 * shrink the buffer to the returned size.
3497 * (can't fail). It means NULL if size is 0.
3499 state
->xattr_value
= talloc_realloc(state
,
3504 tevent_req_done(req
);
3507 static ssize_t
vfswrap_getxattrat_recv(struct tevent_req
*req
,
3508 struct vfs_aio_state
*aio_state
,
3509 TALLOC_CTX
*mem_ctx
,
3510 uint8_t **xattr_value
)
3512 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3513 req
, struct vfswrap_getxattrat_state
);
3516 if (tevent_req_is_unix_error(req
, &aio_state
->error
)) {
3517 tevent_req_received(req
);
3521 *aio_state
= state
->vfs_aio_state
;
3522 xattr_size
= state
->xattr_size
;
3523 if (xattr_value
!= NULL
) {
3524 *xattr_value
= talloc_move(mem_ctx
, &state
->xattr_value
);
3527 tevent_req_received(req
);
3531 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
3533 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
3536 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
,
3537 const struct smb_filename
*smb_fname
,
3541 return listxattr(smb_fname
->base_name
, list
, size
);
3544 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
3546 return flistxattr(fsp
->fh
->fd
, list
, size
);
3549 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
,
3550 const struct smb_filename
*smb_fname
,
3553 return removexattr(smb_fname
->base_name
, name
);
3556 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
3558 return fremovexattr(fsp
->fh
->fd
, name
);
3561 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
,
3562 const struct smb_filename
*smb_fname
,
3568 return setxattr(smb_fname
->base_name
, name
, value
, size
, flags
);
3571 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
3573 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
3576 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
3581 static bool vfswrap_is_offline(struct connection_struct
*conn
,
3582 const struct smb_filename
*fname
)
3586 bool offline
= false;
3588 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
3592 if (!lp_dmapi_support(SNUM(conn
)) || !dmapi_have_session()) {
3593 #if defined(ENOTSUP)
3599 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
3600 if (!NT_STATUS_IS_OK(status
)) {
3601 errno
= map_errno_from_nt_status(status
);
3605 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
3612 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
3613 struct files_struct
*fsp
,
3614 TALLOC_CTX
*mem_ctx
,
3617 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
3620 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
3621 struct files_struct
*fsp
,
3622 const DATA_BLOB old_cookie
,
3623 TALLOC_CTX
*mem_ctx
,
3624 DATA_BLOB
*new_cookie
)
3626 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
3630 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
3631 struct smb_request
*smb1req
,
3632 struct smbXsrv_open
*op
,
3633 const DATA_BLOB old_cookie
,
3634 TALLOC_CTX
*mem_ctx
,
3635 struct files_struct
**fsp
,
3636 DATA_BLOB
*new_cookie
)
3638 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
3639 old_cookie
, mem_ctx
,
3643 static struct vfs_fn_pointers vfs_default_fns
= {
3644 /* Disk operations */
3646 .connect_fn
= vfswrap_connect
,
3647 .disconnect_fn
= vfswrap_disconnect
,
3648 .disk_free_fn
= vfswrap_disk_free
,
3649 .get_quota_fn
= vfswrap_get_quota
,
3650 .set_quota_fn
= vfswrap_set_quota
,
3651 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
3652 .statvfs_fn
= vfswrap_statvfs
,
3653 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
3654 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
3655 .create_dfs_pathat_fn
= vfswrap_create_dfs_pathat
,
3656 .read_dfs_pathat_fn
= vfswrap_read_dfs_pathat
,
3657 .snap_check_path_fn
= vfswrap_snap_check_path
,
3658 .snap_create_fn
= vfswrap_snap_create
,
3659 .snap_delete_fn
= vfswrap_snap_delete
,
3661 /* Directory operations */
3663 .opendir_fn
= vfswrap_opendir
,
3664 .fdopendir_fn
= vfswrap_fdopendir
,
3665 .readdir_fn
= vfswrap_readdir
,
3666 .readdir_attr_fn
= vfswrap_readdir_attr
,
3667 .seekdir_fn
= vfswrap_seekdir
,
3668 .telldir_fn
= vfswrap_telldir
,
3669 .rewind_dir_fn
= vfswrap_rewinddir
,
3670 .mkdirat_fn
= vfswrap_mkdirat
,
3671 .closedir_fn
= vfswrap_closedir
,
3673 /* File operations */
3675 .open_fn
= vfswrap_open
,
3676 .create_file_fn
= vfswrap_create_file
,
3677 .close_fn
= vfswrap_close
,
3678 .pread_fn
= vfswrap_pread
,
3679 .pread_send_fn
= vfswrap_pread_send
,
3680 .pread_recv_fn
= vfswrap_pread_recv
,
3681 .pwrite_fn
= vfswrap_pwrite
,
3682 .pwrite_send_fn
= vfswrap_pwrite_send
,
3683 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
3684 .lseek_fn
= vfswrap_lseek
,
3685 .sendfile_fn
= vfswrap_sendfile
,
3686 .recvfile_fn
= vfswrap_recvfile
,
3687 .renameat_fn
= vfswrap_renameat
,
3688 .fsync_send_fn
= vfswrap_fsync_send
,
3689 .fsync_recv_fn
= vfswrap_fsync_recv
,
3690 .stat_fn
= vfswrap_stat
,
3691 .fstat_fn
= vfswrap_fstat
,
3692 .lstat_fn
= vfswrap_lstat
,
3693 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
3694 .unlinkat_fn
= vfswrap_unlinkat
,
3695 .chmod_fn
= vfswrap_chmod
,
3696 .fchmod_fn
= vfswrap_fchmod
,
3697 .fchown_fn
= vfswrap_fchown
,
3698 .lchown_fn
= vfswrap_lchown
,
3699 .chdir_fn
= vfswrap_chdir
,
3700 .getwd_fn
= vfswrap_getwd
,
3701 .ntimes_fn
= vfswrap_ntimes
,
3702 .ftruncate_fn
= vfswrap_ftruncate
,
3703 .fallocate_fn
= vfswrap_fallocate
,
3704 .lock_fn
= vfswrap_lock
,
3705 .kernel_flock_fn
= vfswrap_kernel_flock
,
3706 .fcntl_fn
= vfswrap_fcntl
,
3707 .linux_setlease_fn
= vfswrap_linux_setlease
,
3708 .getlock_fn
= vfswrap_getlock
,
3709 .symlinkat_fn
= vfswrap_symlinkat
,
3710 .readlinkat_fn
= vfswrap_readlinkat
,
3711 .linkat_fn
= vfswrap_linkat
,
3712 .mknodat_fn
= vfswrap_mknodat
,
3713 .realpath_fn
= vfswrap_realpath
,
3714 .chflags_fn
= vfswrap_chflags
,
3715 .file_id_create_fn
= vfswrap_file_id_create
,
3716 .fs_file_id_fn
= vfswrap_fs_file_id
,
3717 .streaminfo_fn
= vfswrap_streaminfo
,
3718 .get_real_filename_fn
= vfswrap_get_real_filename
,
3719 .connectpath_fn
= vfswrap_connectpath
,
3720 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
3721 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
3722 .strict_lock_check_fn
= vfswrap_strict_lock_check
,
3723 .translate_name_fn
= vfswrap_translate_name
,
3724 .fsctl_fn
= vfswrap_fsctl
,
3725 .set_dos_attributes_fn
= vfswrap_set_dos_attributes
,
3726 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
3727 .get_dos_attributes_fn
= vfswrap_get_dos_attributes
,
3728 .get_dos_attributes_send_fn
= vfswrap_get_dos_attributes_send
,
3729 .get_dos_attributes_recv_fn
= vfswrap_get_dos_attributes_recv
,
3730 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
3731 .offload_read_send_fn
= vfswrap_offload_read_send
,
3732 .offload_read_recv_fn
= vfswrap_offload_read_recv
,
3733 .offload_write_send_fn
= vfswrap_offload_write_send
,
3734 .offload_write_recv_fn
= vfswrap_offload_write_recv
,
3735 .get_compression_fn
= vfswrap_get_compression
,
3736 .set_compression_fn
= vfswrap_set_compression
,
3738 /* NT ACL operations. */
3740 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
3741 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
3742 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
3743 .audit_file_fn
= vfswrap_audit_file
,
3745 /* POSIX ACL operations. */
3747 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
3748 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
3749 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
3750 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
3751 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
3752 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
3753 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
3755 /* EA operations. */
3756 .getxattr_fn
= vfswrap_getxattr
,
3757 .getxattrat_send_fn
= vfswrap_getxattrat_send
,
3758 .getxattrat_recv_fn
= vfswrap_getxattrat_recv
,
3759 .fgetxattr_fn
= vfswrap_fgetxattr
,
3760 .listxattr_fn
= vfswrap_listxattr
,
3761 .flistxattr_fn
= vfswrap_flistxattr
,
3762 .removexattr_fn
= vfswrap_removexattr
,
3763 .fremovexattr_fn
= vfswrap_fremovexattr
,
3764 .setxattr_fn
= vfswrap_setxattr
,
3765 .fsetxattr_fn
= vfswrap_fsetxattr
,
3767 /* aio operations */
3768 .aio_force_fn
= vfswrap_aio_force
,
3770 /* durable handle operations */
3771 .durable_cookie_fn
= vfswrap_durable_cookie
,
3772 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
3773 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
3777 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
3780 * Here we need to implement every call!
3782 * As this is the end of the vfs module chain.
3784 smb_vfs_assert_all_fns(&vfs_default_fns
, DEFAULT_VFS_MODULE_NAME
);
3785 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
3786 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);