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 connection_struct
*conn
= handle
->conn
;
127 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
128 struct smb_filename
*smb_fname_cpath
= NULL
;
129 struct vfs_statvfs_struct statbuf
;
132 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
134 if (smb_fname_cpath
== NULL
) {
138 ZERO_STRUCT(statbuf
);
139 ret
= SMB_VFS_STATVFS(conn
, smb_fname_cpath
, &statbuf
);
141 caps
= statbuf
.FsCapabilities
;
144 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
146 /* Work out what timestamp resolution we can
147 * use when setting a timestamp. */
149 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
151 TALLOC_FREE(smb_fname_cpath
);
155 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
156 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
157 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
158 /* If any of the normal UNIX directory timestamps
159 * have a non-zero tv_nsec component assume
160 * we might be able to set sub-second timestamps.
161 * See what filetime set primitives we have.
163 #if defined(HAVE_UTIMENSAT)
164 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
165 #elif defined(HAVE_UTIMES)
166 /* utimes allows msec timestamps to be set. */
167 *p_ts_res
= TIMESTAMP_SET_MSEC
;
168 #elif defined(HAVE_UTIME)
169 /* utime only allows sec timestamps to be set. */
170 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
173 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
175 "available on share %s, directory %s\n",
176 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
177 lp_servicename(talloc_tos(), conn
->params
->service
),
178 conn
->connectpath
));
180 TALLOC_FREE(smb_fname_cpath
);
184 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
185 struct dfs_GetDFSReferral
*r
)
187 struct junction_map
*junction
= NULL
;
189 bool self_referral
= false;
190 char *pathnamep
= NULL
;
191 char *local_dfs_path
= NULL
;
194 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
197 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
200 /* get the junction entry */
201 if (r
->in
.req
.servername
== NULL
) {
202 return NT_STATUS_NOT_FOUND
;
206 * Trim pathname sent by client so it begins with only one backslash.
207 * Two backslashes confuse some dfs clients
210 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
211 if (local_dfs_path
== NULL
) {
212 return NT_STATUS_NO_MEMORY
;
214 pathnamep
= local_dfs_path
;
215 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
216 IS_DIRECTORY_SEP(pathnamep
[1])) {
220 junction
= talloc_zero(r
, struct junction_map
);
221 if (junction
== NULL
) {
222 return NT_STATUS_NO_MEMORY
;
225 /* The following call can change cwd. */
226 status
= get_referred_path(r
, pathnamep
,
227 handle
->conn
->sconn
->remote_address
,
228 handle
->conn
->sconn
->local_address
,
229 !handle
->conn
->sconn
->using_smb2
,
230 junction
, &consumedcnt
, &self_referral
);
231 if (!NT_STATUS_IS_OK(status
)) {
232 struct smb_filename connectpath_fname
= {
233 .base_name
= handle
->conn
->connectpath
235 vfs_ChDir(handle
->conn
, &connectpath_fname
);
239 struct smb_filename connectpath_fname
= {
240 .base_name
= handle
->conn
->connectpath
242 vfs_ChDir(handle
->conn
, &connectpath_fname
);
245 if (!self_referral
) {
246 pathnamep
[consumedcnt
] = '\0';
249 dbgtext("Path %s to alternate path(s):",
251 for (i
=0; i
< junction
->referral_count
; i
++) {
253 junction
->referral_list
[i
].alternate_path
);
259 if (r
->in
.req
.max_referral_level
<= 2) {
260 max_referral_level
= 2;
262 if (r
->in
.req
.max_referral_level
>= 3) {
263 max_referral_level
= 3;
266 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
267 if (r
->out
.resp
== NULL
) {
268 return NT_STATUS_NO_MEMORY
;
271 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
272 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
274 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
276 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
279 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
280 struct dfs_referral_type
,
281 r
->out
.resp
->nb_referrals
);
282 if (r
->out
.resp
->referral_entries
== NULL
) {
283 return NT_STATUS_NO_MEMORY
;
286 switch (max_referral_level
) {
288 for(i
=0; i
< junction
->referral_count
; i
++) {
289 struct referral
*ref
= &junction
->referral_list
[i
];
290 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
291 struct dfs_referral_type
*t
=
292 &r
->out
.resp
->referral_entries
[i
];
293 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
296 v2
->size
= VERSION2_REFERRAL_SIZE
;
298 v2
->server_type
= DFS_SERVER_ROOT
;
300 v2
->server_type
= DFS_SERVER_NON_ROOT
;
303 v2
->proximity
= ref
->proximity
;
305 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
306 if (v2
->DFS_path
== NULL
) {
307 return NT_STATUS_NO_MEMORY
;
309 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
310 if (v2
->DFS_alt_path
== NULL
) {
311 return NT_STATUS_NO_MEMORY
;
313 v2
->netw_address
= talloc_strdup(mem_ctx
,
314 ref
->alternate_path
);
315 if (v2
->netw_address
== NULL
) {
316 return NT_STATUS_NO_MEMORY
;
322 for(i
=0; i
< junction
->referral_count
; i
++) {
323 struct referral
*ref
= &junction
->referral_list
[i
];
324 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
325 struct dfs_referral_type
*t
=
326 &r
->out
.resp
->referral_entries
[i
];
327 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
328 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
331 v3
->size
= VERSION3_REFERRAL_SIZE
;
333 v3
->server_type
= DFS_SERVER_ROOT
;
335 v3
->server_type
= DFS_SERVER_NON_ROOT
;
339 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
340 if (r1
->DFS_path
== NULL
) {
341 return NT_STATUS_NO_MEMORY
;
343 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
344 if (r1
->DFS_alt_path
== NULL
) {
345 return NT_STATUS_NO_MEMORY
;
347 r1
->netw_address
= talloc_strdup(mem_ctx
,
348 ref
->alternate_path
);
349 if (r1
->netw_address
== NULL
) {
350 return NT_STATUS_NO_MEMORY
;
355 DEBUG(0,("Invalid dfs referral version: %d\n",
356 max_referral_level
));
357 return NT_STATUS_INVALID_LEVEL
;
361 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
367 static NTSTATUS
vfswrap_snap_check_path(struct vfs_handle_struct
*handle
,
369 const char *service_path
,
372 return NT_STATUS_NOT_SUPPORTED
;
375 static NTSTATUS
vfswrap_snap_create(struct vfs_handle_struct
*handle
,
377 const char *base_volume
,
383 return NT_STATUS_NOT_SUPPORTED
;
386 static NTSTATUS
vfswrap_snap_delete(struct vfs_handle_struct
*handle
,
391 return NT_STATUS_NOT_SUPPORTED
;
394 /* Directory operations */
396 static DIR *vfswrap_opendir(vfs_handle_struct
*handle
,
397 const struct smb_filename
*smb_fname
,
403 START_PROFILE(syscall_opendir
);
404 result
= opendir(smb_fname
->base_name
);
405 END_PROFILE(syscall_opendir
);
409 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
416 START_PROFILE(syscall_fdopendir
);
417 result
= sys_fdopendir(fsp
->fh
->fd
);
418 END_PROFILE(syscall_fdopendir
);
423 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
425 SMB_STRUCT_STAT
*sbuf
)
427 struct dirent
*result
;
429 START_PROFILE(syscall_readdir
);
430 result
= readdir(dirp
);
431 END_PROFILE(syscall_readdir
);
433 /* Default Posix readdir() does not give us stat info.
434 * Set to invalid to indicate we didn't return this info. */
435 SET_STAT_INVALID(*sbuf
);
436 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
437 if (result
!= NULL
) {
438 /* See if we can efficiently return this. */
440 int flags
= AT_SYMLINK_NOFOLLOW
;
441 int ret
= fstatat(dirfd(dirp
),
446 * As this is an optimization,
447 * ignore it if we stat'ed a
448 * symlink. Make the caller
449 * do it again as we don't
450 * know if they wanted the link
451 * info, or its target info.
453 if ((ret
== 0) && (!S_ISLNK(st
.st_mode
))) {
454 init_stat_ex_from_stat(sbuf
,
456 lp_fake_directory_create_times(
457 SNUM(handle
->conn
)));
465 static NTSTATUS
vfswrap_readdir_attr(struct vfs_handle_struct
*handle
,
466 const struct smb_filename
*fname
,
468 struct readdir_attr_data
**attr_data
)
470 return NT_STATUS_NOT_SUPPORTED
;
473 static void vfswrap_seekdir(vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
475 START_PROFILE(syscall_seekdir
);
476 seekdir(dirp
, offset
);
477 END_PROFILE(syscall_seekdir
);
480 static long vfswrap_telldir(vfs_handle_struct
*handle
, DIR *dirp
)
483 START_PROFILE(syscall_telldir
);
484 result
= telldir(dirp
);
485 END_PROFILE(syscall_telldir
);
489 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
491 START_PROFILE(syscall_rewinddir
);
493 END_PROFILE(syscall_rewinddir
);
496 static int vfswrap_mkdir(vfs_handle_struct
*handle
,
497 const struct smb_filename
*smb_fname
,
501 bool has_dacl
= False
;
502 const char *path
= smb_fname
->base_name
;
505 START_PROFILE(syscall_mkdir
);
507 if (lp_inherit_acls(SNUM(handle
->conn
))
508 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
509 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
))) {
510 mode
= (0777 & lp_directory_mask(SNUM(handle
->conn
)));
515 result
= mkdir(path
, mode
);
517 if (result
== 0 && !has_dacl
) {
519 * We need to do this as the default behavior of POSIX ACLs
520 * is to set the mask to be the requested group permission
521 * bits, not the group permission bits to be the requested
522 * group permission bits. This is not what we want, as it will
523 * mess up any inherited ACL bits that were set. JRA.
525 int saved_errno
= errno
; /* We may get ENOSYS */
526 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, smb_fname
, mode
) == -1) &&
532 END_PROFILE(syscall_mkdir
);
536 static int vfswrap_rmdir(vfs_handle_struct
*handle
,
537 const struct smb_filename
*smb_fname
)
541 START_PROFILE(syscall_rmdir
);
542 result
= rmdir(smb_fname
->base_name
);
543 END_PROFILE(syscall_rmdir
);
547 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
551 START_PROFILE(syscall_closedir
);
552 result
= closedir(dirp
);
553 END_PROFILE(syscall_closedir
);
557 /* File operations */
559 static int vfswrap_open(vfs_handle_struct
*handle
,
560 struct smb_filename
*smb_fname
,
561 files_struct
*fsp
, int flags
, mode_t mode
)
565 START_PROFILE(syscall_open
);
567 if (smb_fname
->stream_name
) {
572 result
= open(smb_fname
->base_name
, flags
, mode
);
574 END_PROFILE(syscall_open
);
578 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
579 struct smb_request
*req
,
580 uint16_t root_dir_fid
,
581 struct smb_filename
*smb_fname
,
582 uint32_t access_mask
,
583 uint32_t share_access
,
584 uint32_t create_disposition
,
585 uint32_t create_options
,
586 uint32_t file_attributes
,
587 uint32_t oplock_request
,
588 struct smb2_lease
*lease
,
589 uint64_t allocation_size
,
590 uint32_t private_flags
,
591 struct security_descriptor
*sd
,
592 struct ea_list
*ea_list
,
593 files_struct
**result
,
595 const struct smb2_create_blobs
*in_context_blobs
,
596 struct smb2_create_blobs
*out_context_blobs
)
598 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
599 access_mask
, share_access
,
600 create_disposition
, create_options
,
601 file_attributes
, oplock_request
, lease
,
602 allocation_size
, private_flags
,
604 pinfo
, in_context_blobs
, out_context_blobs
);
607 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
611 START_PROFILE(syscall_close
);
612 result
= fd_close_posix(fsp
);
613 END_PROFILE(syscall_close
);
617 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
618 size_t n
, off_t offset
)
622 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
623 START_PROFILE_BYTES(syscall_pread
, n
);
624 result
= sys_pread(fsp
->fh
->fd
, data
, n
, offset
);
625 END_PROFILE_BYTES(syscall_pread
);
627 if (result
== -1 && errno
== ESPIPE
) {
628 /* Maintain the fiction that pipes can be seeked (sought?) on. */
629 result
= sys_read(fsp
->fh
->fd
, data
, n
);
633 #else /* HAVE_PREAD */
636 #endif /* HAVE_PREAD */
641 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
642 size_t n
, off_t offset
)
646 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
647 START_PROFILE_BYTES(syscall_pwrite
, n
);
648 result
= sys_pwrite(fsp
->fh
->fd
, data
, n
, offset
);
649 END_PROFILE_BYTES(syscall_pwrite
);
651 if (result
== -1 && errno
== ESPIPE
) {
652 /* Maintain the fiction that pipes can be sought on. */
653 result
= sys_write(fsp
->fh
->fd
, data
, n
);
656 #else /* HAVE_PWRITE */
659 #endif /* HAVE_PWRITE */
664 struct vfswrap_pread_state
{
671 struct vfs_aio_state vfs_aio_state
;
672 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
675 static void vfs_pread_do(void *private_data
);
676 static void vfs_pread_done(struct tevent_req
*subreq
);
677 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
);
679 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
681 struct tevent_context
*ev
,
682 struct files_struct
*fsp
,
684 size_t n
, off_t offset
)
686 struct tevent_req
*req
, *subreq
;
687 struct vfswrap_pread_state
*state
;
689 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
695 state
->fd
= fsp
->fh
->fd
;
698 state
->offset
= offset
;
700 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
701 state
->profile_bytes
, n
);
702 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
704 subreq
= pthreadpool_tevent_job_send(
705 state
, ev
, handle
->conn
->sconn
->pool
,
706 vfs_pread_do
, state
);
707 if (tevent_req_nomem(subreq
, req
)) {
708 return tevent_req_post(req
, ev
);
710 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
712 talloc_set_destructor(state
, vfs_pread_state_destructor
);
717 static void vfs_pread_do(void *private_data
)
719 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
720 private_data
, struct vfswrap_pread_state
);
721 struct timespec start_time
;
722 struct timespec end_time
;
724 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
726 PROFILE_TIMESTAMP(&start_time
);
729 state
->ret
= pread(state
->fd
, state
->buf
, state
->count
,
731 } while ((state
->ret
== -1) && (errno
== EINTR
));
733 if (state
->ret
== -1) {
734 state
->vfs_aio_state
.error
= errno
;
737 PROFILE_TIMESTAMP(&end_time
);
739 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
741 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
744 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
)
749 static void vfs_pread_done(struct tevent_req
*subreq
)
751 struct tevent_req
*req
= tevent_req_callback_data(
752 subreq
, struct tevent_req
);
753 struct vfswrap_pread_state
*state
= tevent_req_data(
754 req
, struct vfswrap_pread_state
);
757 ret
= pthreadpool_tevent_job_recv(subreq
);
759 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
760 talloc_set_destructor(state
, NULL
);
761 if (tevent_req_error(req
, ret
)) {
765 tevent_req_done(req
);
768 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
769 struct vfs_aio_state
*vfs_aio_state
)
771 struct vfswrap_pread_state
*state
= tevent_req_data(
772 req
, struct vfswrap_pread_state
);
774 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
778 *vfs_aio_state
= state
->vfs_aio_state
;
782 struct vfswrap_pwrite_state
{
789 struct vfs_aio_state vfs_aio_state
;
790 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
793 static void vfs_pwrite_do(void *private_data
);
794 static void vfs_pwrite_done(struct tevent_req
*subreq
);
795 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
);
797 static struct tevent_req
*vfswrap_pwrite_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_pwrite_state
*state
;
807 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pwrite_state
);
813 state
->fd
= fsp
->fh
->fd
;
816 state
->offset
= offset
;
818 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, 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_pwrite_do
, state
);
825 if (tevent_req_nomem(subreq
, req
)) {
826 return tevent_req_post(req
, ev
);
828 tevent_req_set_callback(subreq
, vfs_pwrite_done
, req
);
830 talloc_set_destructor(state
, vfs_pwrite_state_destructor
);
835 static void vfs_pwrite_do(void *private_data
)
837 struct vfswrap_pwrite_state
*state
= talloc_get_type_abort(
838 private_data
, struct vfswrap_pwrite_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
);
847 state
->ret
= pwrite(state
->fd
, state
->buf
, state
->count
,
849 } while ((state
->ret
== -1) && (errno
== EINTR
));
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_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
)
867 static void vfs_pwrite_done(struct tevent_req
*subreq
)
869 struct tevent_req
*req
= tevent_req_callback_data(
870 subreq
, struct tevent_req
);
871 struct vfswrap_pwrite_state
*state
= tevent_req_data(
872 req
, struct vfswrap_pwrite_state
);
875 ret
= pthreadpool_tevent_job_recv(subreq
);
877 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
878 talloc_set_destructor(state
, NULL
);
879 if (tevent_req_error(req
, ret
)) {
883 tevent_req_done(req
);
886 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
887 struct vfs_aio_state
*vfs_aio_state
)
889 struct vfswrap_pwrite_state
*state
= tevent_req_data(
890 req
, struct vfswrap_pwrite_state
);
892 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
896 *vfs_aio_state
= state
->vfs_aio_state
;
900 struct vfswrap_fsync_state
{
904 struct vfs_aio_state vfs_aio_state
;
905 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic
);
908 static void vfs_fsync_do(void *private_data
);
909 static void vfs_fsync_done(struct tevent_req
*subreq
);
910 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
);
912 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
914 struct tevent_context
*ev
,
915 struct files_struct
*fsp
)
917 struct tevent_req
*req
, *subreq
;
918 struct vfswrap_fsync_state
*state
;
920 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
926 state
->fd
= fsp
->fh
->fd
;
928 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync
, profile_p
,
929 state
->profile_basic
);
931 subreq
= pthreadpool_tevent_job_send(
932 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
933 if (tevent_req_nomem(subreq
, req
)) {
934 return tevent_req_post(req
, ev
);
936 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
938 talloc_set_destructor(state
, vfs_fsync_state_destructor
);
943 static void vfs_fsync_do(void *private_data
)
945 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
946 private_data
, struct vfswrap_fsync_state
);
947 struct timespec start_time
;
948 struct timespec end_time
;
950 PROFILE_TIMESTAMP(&start_time
);
953 state
->ret
= fsync(state
->fd
);
954 } while ((state
->ret
== -1) && (errno
== EINTR
));
956 if (state
->ret
== -1) {
957 state
->vfs_aio_state
.error
= errno
;
960 PROFILE_TIMESTAMP(&end_time
);
962 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
965 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
)
970 static void vfs_fsync_done(struct tevent_req
*subreq
)
972 struct tevent_req
*req
= tevent_req_callback_data(
973 subreq
, struct tevent_req
);
974 struct vfswrap_fsync_state
*state
= tevent_req_data(
975 req
, struct vfswrap_fsync_state
);
978 ret
= pthreadpool_tevent_job_recv(subreq
);
980 SMBPROFILE_BASIC_ASYNC_END(state
->profile_basic
);
981 talloc_set_destructor(state
, NULL
);
982 if (tevent_req_error(req
, ret
)) {
986 tevent_req_done(req
);
989 static int vfswrap_fsync_recv(struct tevent_req
*req
,
990 struct vfs_aio_state
*vfs_aio_state
)
992 struct vfswrap_fsync_state
*state
= tevent_req_data(
993 req
, struct vfswrap_fsync_state
);
995 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
999 *vfs_aio_state
= state
->vfs_aio_state
;
1003 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1007 START_PROFILE(syscall_lseek
);
1009 /* Cope with 'stat' file opens. */
1010 if (fsp
->fh
->fd
!= -1)
1011 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
1014 * We want to maintain the fiction that we can seek
1015 * on a fifo for file system purposes. This allows
1016 * people to set up UNIX fifo's that feed data to Windows
1017 * applications. JRA.
1020 if((result
== -1) && (errno
== ESPIPE
)) {
1025 END_PROFILE(syscall_lseek
);
1029 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1030 off_t offset
, size_t n
)
1034 START_PROFILE_BYTES(syscall_sendfile
, n
);
1035 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
1036 END_PROFILE_BYTES(syscall_sendfile
);
1040 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1042 files_struct
*tofsp
,
1048 START_PROFILE_BYTES(syscall_recvfile
, n
);
1049 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
1050 END_PROFILE_BYTES(syscall_recvfile
);
1054 static int vfswrap_rename(vfs_handle_struct
*handle
,
1055 const struct smb_filename
*smb_fname_src
,
1056 const struct smb_filename
*smb_fname_dst
)
1060 START_PROFILE(syscall_rename
);
1062 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
1067 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
1070 END_PROFILE(syscall_rename
);
1074 static int vfswrap_stat(vfs_handle_struct
*handle
,
1075 struct smb_filename
*smb_fname
)
1079 START_PROFILE(syscall_stat
);
1081 if (smb_fname
->stream_name
) {
1086 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1087 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1089 END_PROFILE(syscall_stat
);
1093 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1097 START_PROFILE(syscall_fstat
);
1098 result
= sys_fstat(fsp
->fh
->fd
,
1099 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1100 END_PROFILE(syscall_fstat
);
1104 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1105 struct smb_filename
*smb_fname
)
1109 START_PROFILE(syscall_lstat
);
1111 if (smb_fname
->stream_name
) {
1116 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1117 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1119 END_PROFILE(syscall_lstat
);
1123 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1125 enum vfs_translate_direction direction
,
1126 TALLOC_CTX
*mem_ctx
,
1129 return NT_STATUS_NONE_MAPPED
;
1133 * Implement the default fsctl operation.
1135 static bool vfswrap_logged_ioctl_message
= false;
1137 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1138 struct files_struct
*fsp
,
1141 uint16_t req_flags
, /* Needed for UNICODE ... */
1142 const uint8_t *_in_data
,
1144 uint8_t **_out_data
,
1145 uint32_t max_out_len
,
1148 const char *in_data
= (const char *)_in_data
;
1149 char **out_data
= (char **)_out_data
;
1153 case FSCTL_SET_SPARSE
:
1155 bool set_sparse
= true;
1157 if (in_len
>= 1 && in_data
[0] == 0) {
1161 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1163 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1164 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1165 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1166 nt_errstr(status
)));
1171 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1173 unsigned char objid
[16];
1174 char *return_data
= NULL
;
1176 /* This should return the object-id on this file.
1177 * I think I'll make this be the inode+dev. JRA.
1180 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1181 fsp_fnum_dbg(fsp
)));
1183 *out_len
= MIN(max_out_len
, 64);
1185 /* Hmmm, will this cause problems if less data asked for? */
1186 return_data
= talloc_array(ctx
, char, 64);
1187 if (return_data
== NULL
) {
1188 return NT_STATUS_NO_MEMORY
;
1191 /* For backwards compatibility only store the dev/inode. */
1192 push_file_id_16(return_data
, &fsp
->file_id
);
1193 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1194 push_file_id_16(return_data
+32, &fsp
->file_id
);
1195 memset(return_data
+48, 0, 16);
1196 *out_data
= return_data
;
1197 return NT_STATUS_OK
;
1200 case FSCTL_GET_REPARSE_POINT
:
1202 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1203 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1204 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1205 return NT_STATUS_NOT_A_REPARSE_POINT
;
1208 case FSCTL_SET_REPARSE_POINT
:
1210 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1211 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1212 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1213 return NT_STATUS_NOT_A_REPARSE_POINT
;
1216 case FSCTL_GET_SHADOW_COPY_DATA
:
1219 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1220 * and return their volume names. If max_data_count is 16, then it is just
1221 * asking for the number of volumes and length of the combined names.
1223 * pdata is the data allocated by our caller, but that uses
1224 * total_data_count (which is 0 in our case) rather than max_data_count.
1225 * Allocate the correct amount and return the pointer to let
1226 * it be deallocated when we return.
1228 struct shadow_copy_data
*shadow_data
= NULL
;
1229 bool labels
= False
;
1230 uint32_t labels_data_count
= 0;
1232 char *cur_pdata
= NULL
;
1234 if (max_out_len
< 16) {
1235 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1237 return NT_STATUS_INVALID_PARAMETER
;
1240 if (max_out_len
> 16) {
1244 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1245 if (shadow_data
== NULL
) {
1246 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1247 return NT_STATUS_NO_MEMORY
;
1251 * Call the VFS routine to actually do the work.
1253 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1256 /* broken module didn't set errno on error */
1257 status
= NT_STATUS_UNSUCCESSFUL
;
1259 status
= map_nt_error_from_unix(errno
);
1260 if (NT_STATUS_EQUAL(status
,
1261 NT_STATUS_NOT_SUPPORTED
)) {
1265 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1266 "connectpath %s, failed - %s.\n",
1267 fsp
->conn
->connectpath
,
1268 nt_errstr(status
)));
1269 TALLOC_FREE(shadow_data
);
1273 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1274 sizeof(SHADOW_COPY_LABEL
)) + 2;
1279 *out_len
= 12 + labels_data_count
;
1282 if (max_out_len
< *out_len
) {
1283 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1284 max_out_len
, *out_len
));
1285 TALLOC_FREE(shadow_data
);
1286 return NT_STATUS_BUFFER_TOO_SMALL
;
1289 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1290 if (cur_pdata
== NULL
) {
1291 TALLOC_FREE(shadow_data
);
1292 return NT_STATUS_NO_MEMORY
;
1295 *out_data
= cur_pdata
;
1297 /* num_volumes 4 bytes */
1298 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1301 /* num_labels 4 bytes */
1302 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1305 /* needed_data_count 4 bytes */
1306 SIVAL(cur_pdata
, 8, labels_data_count
);
1310 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1311 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1312 if (labels
&& shadow_data
->labels
) {
1313 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1315 status
= srvstr_push(cur_pdata
, req_flags
,
1316 cur_pdata
, shadow_data
->labels
[i
],
1317 2 * sizeof(SHADOW_COPY_LABEL
),
1318 STR_UNICODE
|STR_TERMINATE
, &len
);
1319 if (!NT_STATUS_IS_OK(status
)) {
1320 TALLOC_FREE(*out_data
);
1321 TALLOC_FREE(shadow_data
);
1324 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1325 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1329 TALLOC_FREE(shadow_data
);
1331 return NT_STATUS_OK
;
1334 case FSCTL_FIND_FILES_BY_SID
:
1336 /* pretend this succeeded -
1338 * we have to send back a list with all files owned by this SID
1340 * but I have to check that --metze
1346 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1347 fsp_fnum_dbg(fsp
)));
1350 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1351 return NT_STATUS_INVALID_PARAMETER
;
1354 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1356 /* unknown 4 bytes: this is not the length of the sid :-( */
1357 /*unknown = IVAL(pdata,0);*/
1359 if (!sid_parse(_in_data
+ 4, sid_len
, &sid
)) {
1360 return NT_STATUS_INVALID_PARAMETER
;
1362 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
1364 if (!sid_to_uid(&sid
, &uid
)) {
1365 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1366 sid_string_dbg(&sid
),
1367 (unsigned long)sid_len
));
1371 /* we can take a look at the find source :-)
1373 * find ./ -uid $uid -name '*' is what we need here
1376 * and send 4bytes len and then NULL terminated unicode strings
1379 * but I don't know how to deal with the paged results
1380 * (maybe we can hang the result anywhere in the fsp struct)
1382 * but I don't know how to deal with the paged results
1383 * (maybe we can hang the result anywhere in the fsp struct)
1385 * we don't send all files at once
1386 * and at the next we should *not* start from the beginning,
1387 * so we have to cache the result
1392 /* this works for now... */
1393 return NT_STATUS_OK
;
1396 case FSCTL_QUERY_ALLOCATED_RANGES
:
1398 /* FIXME: This is just a dummy reply, telling that all of the
1399 * file is allocated. MKS cp needs that.
1400 * Adding the real allocated ranges via FIEMAP on Linux
1401 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1402 * this FSCTL correct for sparse files.
1404 uint64_t offset
, length
;
1405 char *out_data_tmp
= NULL
;
1408 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1410 return NT_STATUS_INVALID_PARAMETER
;
1413 if (max_out_len
< 16) {
1414 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1416 return NT_STATUS_INVALID_PARAMETER
;
1419 offset
= BVAL(in_data
,0);
1420 length
= BVAL(in_data
,8);
1422 if (offset
+ length
< offset
) {
1423 /* No 64-bit integer wrap. */
1424 return NT_STATUS_INVALID_PARAMETER
;
1427 /* Shouldn't this be SMB_VFS_STAT ... ? */
1428 status
= vfs_stat_fsp(fsp
);
1429 if (!NT_STATUS_IS_OK(status
)) {
1434 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1435 if (out_data_tmp
== NULL
) {
1436 DEBUG(10, ("unable to allocate memory for response\n"));
1437 return NT_STATUS_NO_MEMORY
;
1440 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1441 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1443 memset(out_data_tmp
, 0, *out_len
);
1445 uint64_t end
= offset
+ length
;
1446 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1447 SBVAL(out_data_tmp
, 0, 0);
1448 SBVAL(out_data_tmp
, 8, end
);
1451 *out_data
= out_data_tmp
;
1453 return NT_STATUS_OK
;
1456 case FSCTL_IS_VOLUME_DIRTY
:
1458 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1459 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1461 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1462 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1464 return NT_STATUS_INVALID_PARAMETER
;
1469 * Only print once ... unfortunately there could be lots of
1470 * different FSCTLs that are called.
1472 if (!vfswrap_logged_ioctl_message
) {
1473 vfswrap_logged_ioctl_message
= true;
1474 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1475 __func__
, function
));
1479 return NT_STATUS_NOT_SUPPORTED
;
1482 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
1483 const struct smb_filename
*fname
,
1484 SMB_STRUCT_STAT
*sbuf
);
1486 static NTSTATUS
vfswrap_get_dos_attributes(struct vfs_handle_struct
*handle
,
1487 struct smb_filename
*smb_fname
,
1492 offline
= vfswrap_is_offline(handle
, smb_fname
, &smb_fname
->st
);
1494 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1497 return get_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1500 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1501 struct files_struct
*fsp
,
1506 offline
= vfswrap_is_offline(handle
, fsp
->fsp_name
, &fsp
->fsp_name
->st
);
1508 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1511 return get_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1514 static NTSTATUS
vfswrap_set_dos_attributes(struct vfs_handle_struct
*handle
,
1515 const struct smb_filename
*smb_fname
,
1518 return set_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1521 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1522 struct files_struct
*fsp
,
1525 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1528 static struct vfs_offload_ctx
*vfswrap_offload_ctx
;
1530 struct vfswrap_offload_read_state
{
1534 static struct tevent_req
*vfswrap_offload_read_send(
1535 TALLOC_CTX
*mem_ctx
,
1536 struct tevent_context
*ev
,
1537 struct vfs_handle_struct
*handle
,
1538 struct files_struct
*fsp
,
1544 struct tevent_req
*req
= NULL
;
1545 struct vfswrap_offload_read_state
*state
= NULL
;
1548 req
= tevent_req_create(mem_ctx
, &state
,
1549 struct vfswrap_offload_read_state
);
1554 status
= vfs_offload_token_ctx_init(fsp
->conn
->sconn
->client
,
1555 &vfswrap_offload_ctx
);
1556 if (tevent_req_nterror(req
, status
)) {
1557 return tevent_req_post(req
, ev
);
1560 if (fsctl
!= FSCTL_SRV_REQUEST_RESUME_KEY
) {
1561 tevent_req_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
1562 return tevent_req_post(req
, ev
);
1565 status
= vfs_offload_token_create_blob(state
, fsp
, fsctl
,
1567 if (tevent_req_nterror(req
, status
)) {
1568 return tevent_req_post(req
, ev
);
1571 status
= vfs_offload_token_db_store_fsp(vfswrap_offload_ctx
, fsp
,
1573 if (tevent_req_nterror(req
, status
)) {
1574 return tevent_req_post(req
, ev
);
1577 tevent_req_done(req
);
1578 return tevent_req_post(req
, ev
);
1581 static NTSTATUS
vfswrap_offload_read_recv(struct tevent_req
*req
,
1582 struct vfs_handle_struct
*handle
,
1583 TALLOC_CTX
*mem_ctx
,
1586 struct vfswrap_offload_read_state
*state
= tevent_req_data(
1587 req
, struct vfswrap_offload_read_state
);
1590 if (tevent_req_is_nterror(req
, &status
)) {
1591 tevent_req_received(req
);
1595 token
->length
= state
->token
.length
;
1596 token
->data
= talloc_move(mem_ctx
, &state
->token
.data
);
1598 tevent_req_received(req
);
1599 return NT_STATUS_OK
;
1602 struct vfswrap_offload_write_state
{
1603 struct tevent_context
*ev
;
1605 bool read_lck_locked
;
1606 bool write_lck_locked
;
1608 struct files_struct
*src_fsp
;
1610 struct files_struct
*dst_fsp
;
1614 size_t next_io_size
;
1617 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
);
1619 static struct tevent_req
*vfswrap_offload_write_send(
1620 struct vfs_handle_struct
*handle
,
1621 TALLOC_CTX
*mem_ctx
,
1622 struct tevent_context
*ev
,
1625 off_t transfer_offset
,
1626 struct files_struct
*dest_fsp
,
1630 struct tevent_req
*req
;
1631 struct vfswrap_offload_write_state
*state
= NULL
;
1632 size_t num
= MIN(to_copy
, COPYCHUNK_MAX_TOTAL_LEN
);
1633 files_struct
*src_fsp
= NULL
;
1636 req
= tevent_req_create(mem_ctx
, &state
,
1637 struct vfswrap_offload_write_state
);
1642 *state
= (struct vfswrap_offload_write_state
) {
1645 .src_off
= transfer_offset
,
1646 .dst_fsp
= dest_fsp
,
1647 .dst_off
= dest_off
,
1649 .remaining
= to_copy
,
1653 case FSCTL_SRV_COPYCHUNK
:
1654 case FSCTL_SRV_COPYCHUNK_WRITE
:
1657 case FSCTL_OFFLOAD_WRITE
:
1658 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
1659 return tevent_req_post(req
, ev
);
1661 case FSCTL_DUP_EXTENTS_TO_FILE
:
1662 DBG_DEBUG("COW clones not supported by vfs_default\n");
1663 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1664 return tevent_req_post(req
, ev
);
1667 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1668 return tevent_req_post(req
, ev
);
1672 * From here on we assume a copy-chunk fsctl
1676 tevent_req_done(req
);
1677 return tevent_req_post(req
, ev
);
1680 status
= vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx
,
1682 if (tevent_req_nterror(req
, status
)) {
1683 return tevent_req_post(req
, ev
);
1685 state
->src_fsp
= src_fsp
;
1687 DBG_DEBUG("server side copy chunk of length %" PRIu64
"\n", to_copy
);
1689 status
= vfs_offload_token_check_handles(fsctl
, src_fsp
, dest_fsp
);
1690 if (!NT_STATUS_IS_OK(status
)) {
1691 tevent_req_nterror(req
, status
);
1692 return tevent_req_post(req
, ev
);
1695 state
->buf
= talloc_array(state
, uint8_t, num
);
1696 if (tevent_req_nomem(state
->buf
, req
)) {
1697 return tevent_req_post(req
, ev
);
1700 status
= vfs_stat_fsp(src_fsp
);
1701 if (tevent_req_nterror(req
, status
)) {
1702 return tevent_req_post(req
, ev
);
1705 if (src_fsp
->fsp_name
->st
.st_ex_size
< state
->src_off
+ num
) {
1707 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1708 * If the SourceOffset or SourceOffset + Length extends beyond
1709 * the end of file, the server SHOULD<240> treat this as a
1710 * STATUS_END_OF_FILE error.
1712 * <240> Section 3.3.5.15.6: Windows servers will return
1713 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1715 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
1716 return tevent_req_post(req
, ev
);
1719 if (src_fsp
->op
== NULL
) {
1720 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1721 return tevent_req_post(req
, ev
);
1724 if (dest_fsp
->op
== NULL
) {
1725 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1726 return tevent_req_post(req
, ev
);
1729 status
= vfswrap_offload_write_loop(req
);
1730 if (!NT_STATUS_IS_OK(status
)) {
1731 tevent_req_nterror(req
, status
);
1732 return tevent_req_post(req
, ev
);
1738 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
);
1740 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
)
1742 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1743 req
, struct vfswrap_offload_write_state
);
1744 struct tevent_req
*subreq
= NULL
;
1745 struct lock_struct read_lck
;
1748 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
1750 init_strict_lock_struct(state
->src_fsp
,
1751 state
->src_fsp
->op
->global
->open_persistent_id
,
1753 state
->next_io_size
,
1757 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
1761 return NT_STATUS_FILE_LOCK_CONFLICT
;
1764 subreq
= SMB_VFS_PREAD_SEND(state
,
1765 state
->src_fsp
->conn
->sconn
->ev_ctx
,
1768 state
->next_io_size
,
1770 if (subreq
== NULL
) {
1771 return NT_STATUS_NO_MEMORY
;
1773 tevent_req_set_callback(subreq
, vfswrap_offload_write_read_done
, req
);
1775 return NT_STATUS_OK
;
1778 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
);
1780 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
)
1782 struct tevent_req
*req
= tevent_req_callback_data(
1783 subreq
, struct tevent_req
);
1784 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1785 req
, struct vfswrap_offload_write_state
);
1786 struct vfs_aio_state aio_state
;
1787 struct lock_struct write_lck
;
1791 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
1792 TALLOC_FREE(subreq
);
1794 DBG_ERR("read failed: %s\n", strerror(errno
));
1795 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1798 if (nread
!= state
->next_io_size
) {
1799 DBG_ERR("Short read, only %zd of %zu\n",
1800 nread
, state
->next_io_size
);
1801 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1805 state
->src_off
+= nread
;
1807 init_strict_lock_struct(state
->dst_fsp
,
1808 state
->dst_fsp
->op
->global
->open_persistent_id
,
1810 state
->next_io_size
,
1814 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
1818 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1822 subreq
= SMB_VFS_PWRITE_SEND(state
,
1826 state
->next_io_size
,
1828 if (subreq
== NULL
) {
1829 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1832 tevent_req_set_callback(subreq
, vfswrap_offload_write_write_done
, req
);
1835 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
)
1837 struct tevent_req
*req
= tevent_req_callback_data(
1838 subreq
, struct tevent_req
);
1839 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1840 req
, struct vfswrap_offload_write_state
);
1841 struct vfs_aio_state aio_state
;
1845 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
1846 TALLOC_FREE(subreq
);
1847 if (nwritten
== -1) {
1848 DBG_ERR("write failed: %s\n", strerror(errno
));
1849 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1852 if (nwritten
!= state
->next_io_size
) {
1853 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
1854 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1858 state
->dst_off
+= nwritten
;
1860 if (state
->remaining
< nwritten
) {
1861 /* Paranoia check */
1862 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1865 state
->remaining
-= nwritten
;
1866 if (state
->remaining
== 0) {
1867 tevent_req_done(req
);
1871 status
= vfswrap_offload_write_loop(req
);
1872 if (!NT_STATUS_IS_OK(status
)) {
1873 tevent_req_nterror(req
, status
);
1880 static NTSTATUS
vfswrap_offload_write_recv(struct vfs_handle_struct
*handle
,
1881 struct tevent_req
*req
,
1884 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1885 req
, struct vfswrap_offload_write_state
);
1888 if (tevent_req_is_nterror(req
, &status
)) {
1889 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
1891 tevent_req_received(req
);
1895 *copied
= state
->to_copy
;
1896 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
1897 tevent_req_received(req
);
1899 return NT_STATUS_OK
;
1902 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
1903 TALLOC_CTX
*mem_ctx
,
1904 struct files_struct
*fsp
,
1905 struct smb_filename
*smb_fname
,
1906 uint16_t *_compression_fmt
)
1908 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1911 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
1912 TALLOC_CTX
*mem_ctx
,
1913 struct files_struct
*fsp
,
1914 uint16_t compression_fmt
)
1916 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1919 /********************************************************************
1920 Given a stat buffer return the allocated size on disk, taking into
1921 account sparse files.
1922 ********************************************************************/
1923 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
1924 struct files_struct
*fsp
,
1925 const SMB_STRUCT_STAT
*sbuf
)
1929 START_PROFILE(syscall_get_alloc_size
);
1931 if(S_ISDIR(sbuf
->st_ex_mode
)) {
1936 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1937 /* The type of st_blocksize is blkcnt_t which *MUST* be
1938 signed (according to POSIX) and can be less than 64-bits.
1939 Ensure when we're converting to 64 bits wide we don't
1941 #if defined(SIZEOF_BLKCNT_T_8)
1942 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
1943 #elif defined(SIZEOF_BLKCNT_T_4)
1945 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
1946 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
1949 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1953 * Some file systems do not allocate a block for very
1954 * small files. But for non-empty file should report a
1958 uint64_t filesize
= get_file_size_stat(sbuf
);
1960 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
1964 result
= get_file_size_stat(sbuf
);
1967 if (fsp
&& fsp
->initial_allocation_size
)
1968 result
= MAX(result
,fsp
->initial_allocation_size
);
1970 result
= smb_roundup(handle
->conn
, result
);
1973 END_PROFILE(syscall_get_alloc_size
);
1977 static int vfswrap_unlink(vfs_handle_struct
*handle
,
1978 const struct smb_filename
*smb_fname
)
1982 START_PROFILE(syscall_unlink
);
1984 if (smb_fname
->stream_name
) {
1988 result
= unlink(smb_fname
->base_name
);
1991 END_PROFILE(syscall_unlink
);
1995 static int vfswrap_chmod(vfs_handle_struct
*handle
,
1996 const struct smb_filename
*smb_fname
,
2001 START_PROFILE(syscall_chmod
);
2004 * We need to do this due to the fact that the default POSIX ACL
2005 * chmod modifies the ACL *mask* for the group owner, not the
2006 * group owner bits directly. JRA.
2011 int saved_errno
= errno
; /* We might get ENOSYS */
2012 result
= SMB_VFS_CHMOD_ACL(handle
->conn
,
2016 END_PROFILE(syscall_chmod
);
2019 /* Error - return the old errno. */
2020 errno
= saved_errno
;
2023 result
= chmod(smb_fname
->base_name
, mode
);
2024 END_PROFILE(syscall_chmod
);
2028 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2032 START_PROFILE(syscall_fchmod
);
2035 * We need to do this due to the fact that the default POSIX ACL
2036 * chmod modifies the ACL *mask* for the group owner, not the
2037 * group owner bits directly. JRA.
2041 int saved_errno
= errno
; /* We might get ENOSYS */
2042 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
2043 END_PROFILE(syscall_fchmod
);
2046 /* Error - return the old errno. */
2047 errno
= saved_errno
;
2050 #if defined(HAVE_FCHMOD)
2051 result
= fchmod(fsp
->fh
->fd
, mode
);
2057 END_PROFILE(syscall_fchmod
);
2061 static int vfswrap_chown(vfs_handle_struct
*handle
,
2062 const struct smb_filename
*smb_fname
,
2068 START_PROFILE(syscall_chown
);
2069 result
= chown(smb_fname
->base_name
, uid
, gid
);
2070 END_PROFILE(syscall_chown
);
2074 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2079 START_PROFILE(syscall_fchown
);
2080 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
2081 END_PROFILE(syscall_fchown
);
2089 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2090 const struct smb_filename
*smb_fname
,
2096 START_PROFILE(syscall_lchown
);
2097 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2098 END_PROFILE(syscall_lchown
);
2102 static int vfswrap_chdir(vfs_handle_struct
*handle
,
2103 const struct smb_filename
*smb_fname
)
2107 START_PROFILE(syscall_chdir
);
2108 result
= chdir(smb_fname
->base_name
);
2109 END_PROFILE(syscall_chdir
);
2113 static struct smb_filename
*vfswrap_getwd(vfs_handle_struct
*handle
,
2117 struct smb_filename
*smb_fname
= NULL
;
2119 START_PROFILE(syscall_getwd
);
2120 result
= sys_getwd();
2121 END_PROFILE(syscall_getwd
);
2123 if (result
== NULL
) {
2126 smb_fname
= synthetic_smb_fname(ctx
,
2132 * sys_getwd() *always* returns malloced memory.
2133 * We must free here to avoid leaks:
2134 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2140 /*********************************************************************
2141 nsec timestamp resolution call. Convert down to whatever the underlying
2142 system will support.
2143 **********************************************************************/
2145 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
2146 const struct smb_filename
*smb_fname
,
2147 struct smb_file_time
*ft
)
2151 START_PROFILE(syscall_ntimes
);
2153 if (smb_fname
->stream_name
) {
2159 if (null_timespec(ft
->atime
)) {
2160 ft
->atime
= smb_fname
->st
.st_ex_atime
;
2163 if (null_timespec(ft
->mtime
)) {
2164 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
2167 if (!null_timespec(ft
->create_time
)) {
2168 set_create_timespec_ea(handle
->conn
,
2173 if ((timespec_compare(&ft
->atime
,
2174 &smb_fname
->st
.st_ex_atime
) == 0) &&
2175 (timespec_compare(&ft
->mtime
,
2176 &smb_fname
->st
.st_ex_mtime
) == 0)) {
2181 #if defined(HAVE_UTIMENSAT)
2183 struct timespec ts
[2];
2186 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
2188 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
2190 if (!((result
== -1) && (errno
== ENOSYS
))) {
2194 #if defined(HAVE_UTIMES)
2196 struct timeval tv
[2];
2197 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
2198 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
2199 result
= utimes(smb_fname
->base_name
, tv
);
2201 result
= utimes(smb_fname
->base_name
, NULL
);
2203 if (!((result
== -1) && (errno
== ENOSYS
))) {
2207 #if defined(HAVE_UTIME)
2209 struct utimbuf times
;
2210 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
2211 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
2212 result
= utime(smb_fname
->base_name
, ×
);
2214 result
= utime(smb_fname
->base_name
, NULL
);
2216 if (!((result
== -1) && (errno
== ENOSYS
))) {
2224 END_PROFILE(syscall_ntimes
);
2228 /*********************************************************************
2229 A version of ftruncate that will write the space on disk if strict
2231 **********************************************************************/
2233 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2235 off_t space_to_write
;
2236 uint64_t space_avail
;
2237 uint64_t bsize
,dfree
,dsize
;
2240 SMB_STRUCT_STAT
*pst
;
2242 status
= vfs_stat_fsp(fsp
);
2243 if (!NT_STATUS_IS_OK(status
)) {
2246 pst
= &fsp
->fsp_name
->st
;
2249 if (S_ISFIFO(pst
->st_ex_mode
))
2253 if (pst
->st_ex_size
== len
)
2256 /* Shrink - just ftruncate. */
2257 if (pst
->st_ex_size
> len
)
2258 return ftruncate(fsp
->fh
->fd
, len
);
2260 space_to_write
= len
- pst
->st_ex_size
;
2262 /* for allocation try fallocate first. This can fail on some
2263 platforms e.g. when the filesystem doesn't support it and no
2264 emulation is being done by the libc (like on AIX with JFS1). In that
2265 case we do our own emulation. fallocate implementations can
2266 return ENOTSUP or EINVAL in cases like that. */
2267 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2268 if (ret
== -1 && errno
== ENOSPC
) {
2274 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2275 "error %d. Falling back to slow manual allocation\n", errno
));
2277 /* available disk space is enough or not? */
2279 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2280 /* space_avail is 1k blocks */
2281 if (space_avail
== (uint64_t)-1 ||
2282 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2287 /* Write out the real space on disk. */
2288 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2296 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2299 SMB_STRUCT_STAT
*pst
;
2303 START_PROFILE(syscall_ftruncate
);
2305 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
2306 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2307 END_PROFILE(syscall_ftruncate
);
2311 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2312 ftruncate if the system supports it. Then I discovered that
2313 you can have some filesystems that support ftruncate
2314 expansion and some that don't! On Linux fat can't do
2315 ftruncate extend but ext2 can. */
2317 result
= ftruncate(fsp
->fh
->fd
, len
);
2319 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2320 extend a file with ftruncate. Provide alternate implementation
2323 /* Do an fstat to see if the file is longer than the requested
2324 size in which case the ftruncate above should have
2325 succeeded or shorter, in which case seek to len - 1 and
2326 write 1 byte of zero */
2327 status
= vfs_stat_fsp(fsp
);
2328 if (!NT_STATUS_IS_OK(status
)) {
2332 /* We need to update the files_struct after successful ftruncate */
2337 pst
= &fsp
->fsp_name
->st
;
2340 if (S_ISFIFO(pst
->st_ex_mode
)) {
2346 if (pst
->st_ex_size
== len
) {
2351 if (pst
->st_ex_size
> len
) {
2352 /* the ftruncate should have worked */
2356 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
2364 END_PROFILE(syscall_ftruncate
);
2368 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
2376 START_PROFILE(syscall_fallocate
);
2378 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
2380 * posix_fallocate returns 0 on success, errno on error
2381 * and doesn't set errno. Make it behave like fallocate()
2382 * which returns -1, and sets errno on failure.
2389 /* sys_fallocate handles filtering of unsupported mode flags */
2390 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
2392 END_PROFILE(syscall_fallocate
);
2396 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
2400 START_PROFILE(syscall_fcntl_lock
);
2402 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2404 "force process locks",
2406 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2409 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
2410 END_PROFILE(syscall_fcntl_lock
);
2414 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2415 uint32_t share_mode
, uint32_t access_mask
)
2417 START_PROFILE(syscall_kernel_flock
);
2418 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
2419 END_PROFILE(syscall_kernel_flock
);
2423 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2428 START_PROFILE(syscall_fcntl_getlock
);
2430 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2432 "force process locks",
2434 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2437 result
= fcntl_getlock(fsp
->fh
->fd
, op
, poffset
, pcount
, ptype
, ppid
);
2438 END_PROFILE(syscall_fcntl_getlock
);
2442 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2447 START_PROFILE(syscall_linux_setlease
);
2449 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2450 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2454 END_PROFILE(syscall_linux_setlease
);
2458 static int vfswrap_symlink(vfs_handle_struct
*handle
,
2459 const char *link_target
,
2460 const struct smb_filename
*new_smb_fname
)
2464 START_PROFILE(syscall_symlink
);
2465 result
= symlink(link_target
, new_smb_fname
->base_name
);
2466 END_PROFILE(syscall_symlink
);
2470 static int vfswrap_readlink(vfs_handle_struct
*handle
,
2471 const struct smb_filename
*smb_fname
,
2477 START_PROFILE(syscall_readlink
);
2478 result
= readlink(smb_fname
->base_name
, buf
, bufsiz
);
2479 END_PROFILE(syscall_readlink
);
2483 static int vfswrap_link(vfs_handle_struct
*handle
,
2484 const struct smb_filename
*old_smb_fname
,
2485 const struct smb_filename
*new_smb_fname
)
2489 START_PROFILE(syscall_link
);
2490 result
= link(old_smb_fname
->base_name
, new_smb_fname
->base_name
);
2491 END_PROFILE(syscall_link
);
2495 static int vfswrap_mknod(vfs_handle_struct
*handle
,
2496 const struct smb_filename
*smb_fname
,
2502 START_PROFILE(syscall_mknod
);
2503 result
= sys_mknod(smb_fname
->base_name
, mode
, dev
);
2504 END_PROFILE(syscall_mknod
);
2508 static struct smb_filename
*vfswrap_realpath(vfs_handle_struct
*handle
,
2510 const struct smb_filename
*smb_fname
)
2513 struct smb_filename
*result_fname
= NULL
;
2515 START_PROFILE(syscall_realpath
);
2516 result
= sys_realpath(smb_fname
->base_name
);
2517 END_PROFILE(syscall_realpath
);
2519 result_fname
= synthetic_smb_fname(ctx
, result
, NULL
, NULL
, 0);
2522 return result_fname
;
2525 static int vfswrap_chflags(vfs_handle_struct
*handle
,
2526 const struct smb_filename
*smb_fname
,
2530 return chflags(smb_fname
->base_name
, flags
);
2537 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2538 const SMB_STRUCT_STAT
*sbuf
)
2542 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2546 key
.devid
= sbuf
->st_ex_dev
;
2547 key
.inode
= sbuf
->st_ex_ino
;
2548 /* key.extid is unused by default. */
2553 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
2554 struct files_struct
*fsp
,
2555 const struct smb_filename
*smb_fname
,
2556 TALLOC_CTX
*mem_ctx
,
2557 unsigned int *pnum_streams
,
2558 struct stream_struct
**pstreams
)
2560 SMB_STRUCT_STAT sbuf
;
2561 struct stream_struct
*tmp_streams
= NULL
;
2564 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
2566 * No default streams on directories
2571 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
2572 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
2575 struct smb_filename smb_fname_cp
;
2577 ZERO_STRUCT(smb_fname_cp
);
2578 smb_fname_cp
.base_name
= discard_const_p(char,
2579 smb_fname
->base_name
);
2580 smb_fname_cp
.flags
= smb_fname
->flags
;
2582 if (smb_fname_cp
.flags
& SMB_FILENAME_POSIX_PATH
) {
2583 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname_cp
);
2585 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname_cp
);
2587 sbuf
= smb_fname_cp
.st
;
2591 return map_nt_error_from_unix(errno
);
2594 if (S_ISDIR(sbuf
.st_ex_mode
)) {
2598 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
2599 (*pnum_streams
) + 1);
2600 if (tmp_streams
== NULL
) {
2601 return NT_STATUS_NO_MEMORY
;
2603 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
2604 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
2605 return NT_STATUS_NO_MEMORY
;
2607 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
2608 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
2611 *pstreams
= tmp_streams
;
2613 return NT_STATUS_OK
;
2616 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
2619 TALLOC_CTX
*mem_ctx
,
2623 * Don't fall back to get_real_filename so callers can differentiate
2624 * between a full directory scan and an actual case-insensitive stat.
2630 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
2631 const struct smb_filename
*smb_fname
)
2633 return handle
->conn
->connectpath
;
2636 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
2637 struct byte_range_lock
*br_lck
,
2638 struct lock_struct
*plock
,
2641 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2643 /* Note: blr is not used in the default implementation. */
2644 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
2647 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
2648 struct messaging_context
*msg_ctx
,
2649 struct byte_range_lock
*br_lck
,
2650 const struct lock_struct
*plock
)
2652 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2654 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
2657 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
2658 struct byte_range_lock
*br_lck
,
2659 struct lock_struct
*plock
)
2661 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2663 /* Note: blr is not used in the default implementation. */
2664 return brl_lock_cancel_default(br_lck
, plock
);
2667 static bool vfswrap_strict_lock_check(struct vfs_handle_struct
*handle
,
2669 struct lock_struct
*plock
)
2671 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2672 plock
->lock_type
== WRITE_LOCK
);
2674 return strict_lock_check_default(fsp
, plock
);
2677 /* NT ACL operations. */
2679 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
2681 uint32_t security_info
,
2682 TALLOC_CTX
*mem_ctx
,
2683 struct security_descriptor
**ppdesc
)
2687 START_PROFILE(fget_nt_acl
);
2688 result
= posix_fget_nt_acl(fsp
, security_info
,
2690 END_PROFILE(fget_nt_acl
);
2694 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
2695 const struct smb_filename
*smb_fname
,
2696 uint32_t security_info
,
2697 TALLOC_CTX
*mem_ctx
,
2698 struct security_descriptor
**ppdesc
)
2702 START_PROFILE(get_nt_acl
);
2703 result
= posix_get_nt_acl(handle
->conn
,
2708 END_PROFILE(get_nt_acl
);
2712 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
2716 START_PROFILE(fset_nt_acl
);
2717 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
2718 END_PROFILE(fset_nt_acl
);
2722 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
2723 struct smb_filename
*file
,
2724 struct security_acl
*sacl
,
2725 uint32_t access_requested
,
2726 uint32_t access_denied
)
2728 return NT_STATUS_OK
; /* Nothing to do here ... */
2731 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
,
2732 const struct smb_filename
*smb_fname
,
2741 START_PROFILE(chmod_acl
);
2742 result
= chmod_acl(handle
->conn
, smb_fname
, mode
);
2743 END_PROFILE(chmod_acl
);
2748 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2756 START_PROFILE(fchmod_acl
);
2757 result
= fchmod_acl(fsp
, mode
);
2758 END_PROFILE(fchmod_acl
);
2763 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
2764 const struct smb_filename
*smb_fname
,
2765 SMB_ACL_TYPE_T type
,
2766 TALLOC_CTX
*mem_ctx
)
2768 return sys_acl_get_file(handle
, smb_fname
, type
, mem_ctx
);
2771 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
2773 TALLOC_CTX
*mem_ctx
)
2775 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
2778 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
,
2779 const struct smb_filename
*smb_fname
,
2780 SMB_ACL_TYPE_T acltype
,
2783 return sys_acl_set_file(handle
, smb_fname
, acltype
, theacl
);
2786 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2788 return sys_acl_set_fd(handle
, fsp
, theacl
);
2791 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
2792 const struct smb_filename
*smb_fname
)
2794 return sys_acl_delete_def_file(handle
, smb_fname
);
2797 /****************************************************************
2798 Extended attribute operations.
2799 *****************************************************************/
2801 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,
2802 const struct smb_filename
*smb_fname
,
2807 return getxattr(smb_fname
->base_name
, name
, value
, size
);
2810 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2812 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2815 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
,
2816 const struct smb_filename
*smb_fname
,
2820 return listxattr(smb_fname
->base_name
, list
, size
);
2823 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2825 return flistxattr(fsp
->fh
->fd
, list
, size
);
2828 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
,
2829 const struct smb_filename
*smb_fname
,
2832 return removexattr(smb_fname
->base_name
, name
);
2835 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2837 return fremovexattr(fsp
->fh
->fd
, name
);
2840 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
,
2841 const struct smb_filename
*smb_fname
,
2847 return setxattr(smb_fname
->base_name
, name
, value
, size
, flags
);
2850 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2852 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2855 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2860 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2861 const struct smb_filename
*fname
,
2862 SMB_STRUCT_STAT
*sbuf
)
2866 bool offline
= false;
2868 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2872 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2873 #if defined(ENOTSUP)
2879 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2880 if (!NT_STATUS_IS_OK(status
)) {
2881 errno
= map_errno_from_nt_status(status
);
2885 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2892 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
2893 struct files_struct
*fsp
,
2894 TALLOC_CTX
*mem_ctx
,
2897 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
2900 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
2901 struct files_struct
*fsp
,
2902 const DATA_BLOB old_cookie
,
2903 TALLOC_CTX
*mem_ctx
,
2904 DATA_BLOB
*new_cookie
)
2906 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
2910 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
2911 struct smb_request
*smb1req
,
2912 struct smbXsrv_open
*op
,
2913 const DATA_BLOB old_cookie
,
2914 TALLOC_CTX
*mem_ctx
,
2915 struct files_struct
**fsp
,
2916 DATA_BLOB
*new_cookie
)
2918 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
2919 old_cookie
, mem_ctx
,
2923 static struct vfs_fn_pointers vfs_default_fns
= {
2924 /* Disk operations */
2926 .connect_fn
= vfswrap_connect
,
2927 .disconnect_fn
= vfswrap_disconnect
,
2928 .disk_free_fn
= vfswrap_disk_free
,
2929 .get_quota_fn
= vfswrap_get_quota
,
2930 .set_quota_fn
= vfswrap_set_quota
,
2931 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
2932 .statvfs_fn
= vfswrap_statvfs
,
2933 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
2934 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
2935 .snap_check_path_fn
= vfswrap_snap_check_path
,
2936 .snap_create_fn
= vfswrap_snap_create
,
2937 .snap_delete_fn
= vfswrap_snap_delete
,
2939 /* Directory operations */
2941 .opendir_fn
= vfswrap_opendir
,
2942 .fdopendir_fn
= vfswrap_fdopendir
,
2943 .readdir_fn
= vfswrap_readdir
,
2944 .readdir_attr_fn
= vfswrap_readdir_attr
,
2945 .seekdir_fn
= vfswrap_seekdir
,
2946 .telldir_fn
= vfswrap_telldir
,
2947 .rewind_dir_fn
= vfswrap_rewinddir
,
2948 .mkdir_fn
= vfswrap_mkdir
,
2949 .rmdir_fn
= vfswrap_rmdir
,
2950 .closedir_fn
= vfswrap_closedir
,
2952 /* File operations */
2954 .open_fn
= vfswrap_open
,
2955 .create_file_fn
= vfswrap_create_file
,
2956 .close_fn
= vfswrap_close
,
2957 .pread_fn
= vfswrap_pread
,
2958 .pread_send_fn
= vfswrap_pread_send
,
2959 .pread_recv_fn
= vfswrap_pread_recv
,
2960 .pwrite_fn
= vfswrap_pwrite
,
2961 .pwrite_send_fn
= vfswrap_pwrite_send
,
2962 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
2963 .lseek_fn
= vfswrap_lseek
,
2964 .sendfile_fn
= vfswrap_sendfile
,
2965 .recvfile_fn
= vfswrap_recvfile
,
2966 .rename_fn
= vfswrap_rename
,
2967 .fsync_send_fn
= vfswrap_fsync_send
,
2968 .fsync_recv_fn
= vfswrap_fsync_recv
,
2969 .stat_fn
= vfswrap_stat
,
2970 .fstat_fn
= vfswrap_fstat
,
2971 .lstat_fn
= vfswrap_lstat
,
2972 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
2973 .unlink_fn
= vfswrap_unlink
,
2974 .chmod_fn
= vfswrap_chmod
,
2975 .fchmod_fn
= vfswrap_fchmod
,
2976 .chown_fn
= vfswrap_chown
,
2977 .fchown_fn
= vfswrap_fchown
,
2978 .lchown_fn
= vfswrap_lchown
,
2979 .chdir_fn
= vfswrap_chdir
,
2980 .getwd_fn
= vfswrap_getwd
,
2981 .ntimes_fn
= vfswrap_ntimes
,
2982 .ftruncate_fn
= vfswrap_ftruncate
,
2983 .fallocate_fn
= vfswrap_fallocate
,
2984 .lock_fn
= vfswrap_lock
,
2985 .kernel_flock_fn
= vfswrap_kernel_flock
,
2986 .linux_setlease_fn
= vfswrap_linux_setlease
,
2987 .getlock_fn
= vfswrap_getlock
,
2988 .symlink_fn
= vfswrap_symlink
,
2989 .readlink_fn
= vfswrap_readlink
,
2990 .link_fn
= vfswrap_link
,
2991 .mknod_fn
= vfswrap_mknod
,
2992 .realpath_fn
= vfswrap_realpath
,
2993 .chflags_fn
= vfswrap_chflags
,
2994 .file_id_create_fn
= vfswrap_file_id_create
,
2995 .streaminfo_fn
= vfswrap_streaminfo
,
2996 .get_real_filename_fn
= vfswrap_get_real_filename
,
2997 .connectpath_fn
= vfswrap_connectpath
,
2998 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
2999 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
3000 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
3001 .strict_lock_check_fn
= vfswrap_strict_lock_check
,
3002 .translate_name_fn
= vfswrap_translate_name
,
3003 .fsctl_fn
= vfswrap_fsctl
,
3004 .set_dos_attributes_fn
= vfswrap_set_dos_attributes
,
3005 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
3006 .get_dos_attributes_fn
= vfswrap_get_dos_attributes
,
3007 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
3008 .offload_read_send_fn
= vfswrap_offload_read_send
,
3009 .offload_read_recv_fn
= vfswrap_offload_read_recv
,
3010 .offload_write_send_fn
= vfswrap_offload_write_send
,
3011 .offload_write_recv_fn
= vfswrap_offload_write_recv
,
3012 .get_compression_fn
= vfswrap_get_compression
,
3013 .set_compression_fn
= vfswrap_set_compression
,
3015 /* NT ACL operations. */
3017 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
3018 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
3019 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
3020 .audit_file_fn
= vfswrap_audit_file
,
3022 /* POSIX ACL operations. */
3024 .chmod_acl_fn
= vfswrap_chmod_acl
,
3025 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
3027 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
3028 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
3029 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
3030 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
3031 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
3032 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
3033 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
3035 /* EA operations. */
3036 .getxattr_fn
= vfswrap_getxattr
,
3037 .fgetxattr_fn
= vfswrap_fgetxattr
,
3038 .listxattr_fn
= vfswrap_listxattr
,
3039 .flistxattr_fn
= vfswrap_flistxattr
,
3040 .removexattr_fn
= vfswrap_removexattr
,
3041 .fremovexattr_fn
= vfswrap_fremovexattr
,
3042 .setxattr_fn
= vfswrap_setxattr
,
3043 .fsetxattr_fn
= vfswrap_fsetxattr
,
3045 /* aio operations */
3046 .aio_force_fn
= vfswrap_aio_force
,
3048 /* durable handle operations */
3049 .durable_cookie_fn
= vfswrap_durable_cookie
,
3050 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
3051 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
3055 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
3057 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
3058 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);