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 ZERO_STRUCT(statbuf
);
133 ret
= sys_statvfs(conn
->connectpath
, &statbuf
);
135 caps
= statbuf
.FsCapabilities
;
138 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
140 /* Work out what timestamp resolution we can
141 * use when setting a timestamp. */
143 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
145 if (smb_fname_cpath
== NULL
) {
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 static void vfswrap_init_search_op(vfs_handle_struct
*handle
,
560 /* Default behavior is a NOOP */
563 /* File operations */
565 static int vfswrap_open(vfs_handle_struct
*handle
,
566 struct smb_filename
*smb_fname
,
567 files_struct
*fsp
, int flags
, mode_t mode
)
571 START_PROFILE(syscall_open
);
573 if (smb_fname
->stream_name
) {
578 result
= open(smb_fname
->base_name
, flags
, mode
);
580 END_PROFILE(syscall_open
);
584 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
585 struct smb_request
*req
,
586 uint16_t root_dir_fid
,
587 struct smb_filename
*smb_fname
,
588 uint32_t access_mask
,
589 uint32_t share_access
,
590 uint32_t create_disposition
,
591 uint32_t create_options
,
592 uint32_t file_attributes
,
593 uint32_t oplock_request
,
594 struct smb2_lease
*lease
,
595 uint64_t allocation_size
,
596 uint32_t private_flags
,
597 struct security_descriptor
*sd
,
598 struct ea_list
*ea_list
,
599 files_struct
**result
,
601 const struct smb2_create_blobs
*in_context_blobs
,
602 struct smb2_create_blobs
*out_context_blobs
)
604 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
605 access_mask
, share_access
,
606 create_disposition
, create_options
,
607 file_attributes
, oplock_request
, lease
,
608 allocation_size
, private_flags
,
610 pinfo
, in_context_blobs
, out_context_blobs
);
613 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
617 START_PROFILE(syscall_close
);
618 result
= fd_close_posix(fsp
);
619 END_PROFILE(syscall_close
);
623 static ssize_t
vfswrap_read(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
627 START_PROFILE_BYTES(syscall_read
, n
);
628 result
= sys_read(fsp
->fh
->fd
, data
, n
);
629 END_PROFILE_BYTES(syscall_read
);
633 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
634 size_t n
, off_t offset
)
638 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
639 START_PROFILE_BYTES(syscall_pread
, n
);
640 result
= sys_pread(fsp
->fh
->fd
, data
, n
, offset
);
641 END_PROFILE_BYTES(syscall_pread
);
643 if (result
== -1 && errno
== ESPIPE
) {
644 /* Maintain the fiction that pipes can be seeked (sought?) on. */
645 result
= SMB_VFS_READ(fsp
, data
, n
);
649 #else /* HAVE_PREAD */
653 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
654 if (curr
== -1 && errno
== ESPIPE
) {
655 /* Maintain the fiction that pipes can be seeked (sought?) on. */
656 result
= SMB_VFS_READ(fsp
, data
, n
);
661 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
666 result
= SMB_VFS_READ(fsp
, data
, n
);
669 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
672 #endif /* HAVE_PREAD */
677 static ssize_t
vfswrap_write(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
681 START_PROFILE_BYTES(syscall_write
, n
);
682 result
= sys_write(fsp
->fh
->fd
, data
, n
);
683 END_PROFILE_BYTES(syscall_write
);
687 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
688 size_t n
, off_t offset
)
692 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
693 START_PROFILE_BYTES(syscall_pwrite
, n
);
694 result
= sys_pwrite(fsp
->fh
->fd
, data
, n
, offset
);
695 END_PROFILE_BYTES(syscall_pwrite
);
697 if (result
== -1 && errno
== ESPIPE
) {
698 /* Maintain the fiction that pipes can be sought on. */
699 result
= SMB_VFS_WRITE(fsp
, data
, n
);
702 #else /* HAVE_PWRITE */
706 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
711 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
715 result
= SMB_VFS_WRITE(fsp
, data
, n
);
718 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
721 #endif /* HAVE_PWRITE */
726 static int vfswrap_init_pool(struct smbd_server_connection
*conn
)
730 if (conn
->pool
!= NULL
) {
734 ret
= pthreadpool_tevent_init(conn
, lp_aio_max_threads(),
739 struct vfswrap_pread_state
{
747 struct vfs_aio_state vfs_aio_state
;
748 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
751 static void vfs_pread_do(void *private_data
);
752 static void vfs_pread_done(struct tevent_req
*subreq
);
753 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
);
755 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
757 struct tevent_context
*ev
,
758 struct files_struct
*fsp
,
760 size_t n
, off_t offset
)
762 struct tevent_req
*req
, *subreq
;
763 struct vfswrap_pread_state
*state
;
766 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
771 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
772 if (tevent_req_error(req
, ret
)) {
773 return tevent_req_post(req
, ev
);
777 state
->fd
= fsp
->fh
->fd
;
780 state
->offset
= offset
;
782 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
783 state
->profile_bytes
, n
);
784 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
786 subreq
= pthreadpool_tevent_job_send(
787 state
, ev
, handle
->conn
->sconn
->pool
,
788 vfs_pread_do
, state
);
789 if (tevent_req_nomem(subreq
, req
)) {
790 return tevent_req_post(req
, ev
);
792 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
794 talloc_set_destructor(state
, vfs_pread_state_destructor
);
799 static void vfs_pread_do(void *private_data
)
801 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
802 private_data
, struct vfswrap_pread_state
);
803 struct timespec start_time
;
804 struct timespec end_time
;
806 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
808 PROFILE_TIMESTAMP(&start_time
);
811 state
->ret
= pread(state
->fd
, state
->buf
, state
->count
,
813 } while ((state
->ret
== -1) && (errno
== EINTR
));
817 PROFILE_TIMESTAMP(&end_time
);
819 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
821 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
824 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
)
829 static void vfs_pread_done(struct tevent_req
*subreq
)
831 struct tevent_req
*req
= tevent_req_callback_data(
832 subreq
, struct tevent_req
);
833 struct vfswrap_pread_state
*state
= tevent_req_data(
834 req
, struct vfswrap_pread_state
);
837 ret
= pthreadpool_tevent_job_recv(subreq
);
839 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
840 talloc_set_destructor(state
, NULL
);
841 if (tevent_req_error(req
, ret
)) {
845 tevent_req_done(req
);
848 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
849 struct vfs_aio_state
*vfs_aio_state
)
851 struct vfswrap_pread_state
*state
= tevent_req_data(
852 req
, struct vfswrap_pread_state
);
854 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
858 *vfs_aio_state
= state
->vfs_aio_state
;
862 struct vfswrap_pwrite_state
{
870 struct vfs_aio_state vfs_aio_state
;
871 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
874 static void vfs_pwrite_do(void *private_data
);
875 static void vfs_pwrite_done(struct tevent_req
*subreq
);
876 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
);
878 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
880 struct tevent_context
*ev
,
881 struct files_struct
*fsp
,
883 size_t n
, off_t offset
)
885 struct tevent_req
*req
, *subreq
;
886 struct vfswrap_pwrite_state
*state
;
889 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pwrite_state
);
894 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
895 if (tevent_req_error(req
, ret
)) {
896 return tevent_req_post(req
, ev
);
900 state
->fd
= fsp
->fh
->fd
;
903 state
->offset
= offset
;
905 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
906 state
->profile_bytes
, n
);
907 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
909 subreq
= pthreadpool_tevent_job_send(
910 state
, ev
, handle
->conn
->sconn
->pool
,
911 vfs_pwrite_do
, state
);
912 if (tevent_req_nomem(subreq
, req
)) {
913 return tevent_req_post(req
, ev
);
915 tevent_req_set_callback(subreq
, vfs_pwrite_done
, req
);
917 talloc_set_destructor(state
, vfs_pwrite_state_destructor
);
922 static void vfs_pwrite_do(void *private_data
)
924 struct vfswrap_pwrite_state
*state
= talloc_get_type_abort(
925 private_data
, struct vfswrap_pwrite_state
);
926 struct timespec start_time
;
927 struct timespec end_time
;
929 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
931 PROFILE_TIMESTAMP(&start_time
);
934 state
->ret
= pwrite(state
->fd
, state
->buf
, state
->count
,
936 } while ((state
->ret
== -1) && (errno
== EINTR
));
940 PROFILE_TIMESTAMP(&end_time
);
942 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
944 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
947 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
)
952 static void vfs_pwrite_done(struct tevent_req
*subreq
)
954 struct tevent_req
*req
= tevent_req_callback_data(
955 subreq
, struct tevent_req
);
956 struct vfswrap_pwrite_state
*state
= tevent_req_data(
957 req
, struct vfswrap_pwrite_state
);
960 ret
= pthreadpool_tevent_job_recv(subreq
);
962 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
963 talloc_set_destructor(state
, NULL
);
964 if (tevent_req_error(req
, ret
)) {
968 tevent_req_done(req
);
971 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
972 struct vfs_aio_state
*vfs_aio_state
)
974 struct vfswrap_pwrite_state
*state
= tevent_req_data(
975 req
, struct vfswrap_pwrite_state
);
977 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
981 *vfs_aio_state
= state
->vfs_aio_state
;
985 struct vfswrap_fsync_state
{
990 struct vfs_aio_state vfs_aio_state
;
991 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic
);
994 static void vfs_fsync_do(void *private_data
);
995 static void vfs_fsync_done(struct tevent_req
*subreq
);
996 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
);
998 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
1000 struct tevent_context
*ev
,
1001 struct files_struct
*fsp
)
1003 struct tevent_req
*req
, *subreq
;
1004 struct vfswrap_fsync_state
*state
;
1007 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
1012 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
1013 if (tevent_req_error(req
, ret
)) {
1014 return tevent_req_post(req
, ev
);
1018 state
->fd
= fsp
->fh
->fd
;
1020 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync
, profile_p
,
1021 state
->profile_basic
);
1023 subreq
= pthreadpool_tevent_job_send(
1024 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
1025 if (tevent_req_nomem(subreq
, req
)) {
1026 return tevent_req_post(req
, ev
);
1028 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
1030 talloc_set_destructor(state
, vfs_fsync_state_destructor
);
1035 static void vfs_fsync_do(void *private_data
)
1037 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
1038 private_data
, struct vfswrap_fsync_state
);
1039 struct timespec start_time
;
1040 struct timespec end_time
;
1042 PROFILE_TIMESTAMP(&start_time
);
1045 state
->ret
= fsync(state
->fd
);
1046 } while ((state
->ret
== -1) && (errno
== EINTR
));
1050 PROFILE_TIMESTAMP(&end_time
);
1052 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1055 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
)
1060 static void vfs_fsync_done(struct tevent_req
*subreq
)
1062 struct tevent_req
*req
= tevent_req_callback_data(
1063 subreq
, struct tevent_req
);
1064 struct vfswrap_fsync_state
*state
= tevent_req_data(
1065 req
, struct vfswrap_fsync_state
);
1068 ret
= pthreadpool_tevent_job_recv(subreq
);
1069 TALLOC_FREE(subreq
);
1070 SMBPROFILE_BASIC_ASYNC_END(state
->profile_basic
);
1071 talloc_set_destructor(state
, NULL
);
1072 if (tevent_req_error(req
, ret
)) {
1076 tevent_req_done(req
);
1079 static int vfswrap_fsync_recv(struct tevent_req
*req
,
1080 struct vfs_aio_state
*vfs_aio_state
)
1082 struct vfswrap_fsync_state
*state
= tevent_req_data(
1083 req
, struct vfswrap_fsync_state
);
1085 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1089 *vfs_aio_state
= state
->vfs_aio_state
;
1093 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1097 START_PROFILE(syscall_lseek
);
1099 /* Cope with 'stat' file opens. */
1100 if (fsp
->fh
->fd
!= -1)
1101 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
1104 * We want to maintain the fiction that we can seek
1105 * on a fifo for file system purposes. This allows
1106 * people to set up UNIX fifo's that feed data to Windows
1107 * applications. JRA.
1110 if((result
== -1) && (errno
== ESPIPE
)) {
1115 END_PROFILE(syscall_lseek
);
1119 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1120 off_t offset
, size_t n
)
1124 START_PROFILE_BYTES(syscall_sendfile
, n
);
1125 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
1126 END_PROFILE_BYTES(syscall_sendfile
);
1130 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1132 files_struct
*tofsp
,
1138 START_PROFILE_BYTES(syscall_recvfile
, n
);
1139 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
1140 END_PROFILE_BYTES(syscall_recvfile
);
1144 static int vfswrap_rename(vfs_handle_struct
*handle
,
1145 const struct smb_filename
*smb_fname_src
,
1146 const struct smb_filename
*smb_fname_dst
)
1150 START_PROFILE(syscall_rename
);
1152 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
1157 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
1160 END_PROFILE(syscall_rename
);
1164 static int vfswrap_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
1169 START_PROFILE(syscall_fsync
);
1170 result
= fsync(fsp
->fh
->fd
);
1171 END_PROFILE(syscall_fsync
);
1178 static int vfswrap_stat(vfs_handle_struct
*handle
,
1179 struct smb_filename
*smb_fname
)
1183 START_PROFILE(syscall_stat
);
1185 if (smb_fname
->stream_name
) {
1190 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1191 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1193 END_PROFILE(syscall_stat
);
1197 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1201 START_PROFILE(syscall_fstat
);
1202 result
= sys_fstat(fsp
->fh
->fd
,
1203 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1204 END_PROFILE(syscall_fstat
);
1208 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1209 struct smb_filename
*smb_fname
)
1213 START_PROFILE(syscall_lstat
);
1215 if (smb_fname
->stream_name
) {
1220 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1221 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1223 END_PROFILE(syscall_lstat
);
1227 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1229 enum vfs_translate_direction direction
,
1230 TALLOC_CTX
*mem_ctx
,
1233 return NT_STATUS_NONE_MAPPED
;
1237 * Implement the default fsctl operation.
1239 static bool vfswrap_logged_ioctl_message
= false;
1241 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1242 struct files_struct
*fsp
,
1245 uint16_t req_flags
, /* Needed for UNICODE ... */
1246 const uint8_t *_in_data
,
1248 uint8_t **_out_data
,
1249 uint32_t max_out_len
,
1252 const char *in_data
= (const char *)_in_data
;
1253 char **out_data
= (char **)_out_data
;
1257 case FSCTL_SET_SPARSE
:
1259 bool set_sparse
= true;
1261 if (in_len
>= 1 && in_data
[0] == 0) {
1265 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1267 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1268 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1269 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1270 nt_errstr(status
)));
1275 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1277 unsigned char objid
[16];
1278 char *return_data
= NULL
;
1280 /* This should return the object-id on this file.
1281 * I think I'll make this be the inode+dev. JRA.
1284 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1285 fsp_fnum_dbg(fsp
)));
1287 *out_len
= MIN(max_out_len
, 64);
1289 /* Hmmm, will this cause problems if less data asked for? */
1290 return_data
= talloc_array(ctx
, char, 64);
1291 if (return_data
== NULL
) {
1292 return NT_STATUS_NO_MEMORY
;
1295 /* For backwards compatibility only store the dev/inode. */
1296 push_file_id_16(return_data
, &fsp
->file_id
);
1297 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1298 push_file_id_16(return_data
+32, &fsp
->file_id
);
1299 memset(return_data
+48, 0, 16);
1300 *out_data
= return_data
;
1301 return NT_STATUS_OK
;
1304 case FSCTL_GET_REPARSE_POINT
:
1306 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1307 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1308 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1309 return NT_STATUS_NOT_A_REPARSE_POINT
;
1312 case FSCTL_SET_REPARSE_POINT
:
1314 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1315 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1316 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1317 return NT_STATUS_NOT_A_REPARSE_POINT
;
1320 case FSCTL_GET_SHADOW_COPY_DATA
:
1323 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1324 * and return their volume names. If max_data_count is 16, then it is just
1325 * asking for the number of volumes and length of the combined names.
1327 * pdata is the data allocated by our caller, but that uses
1328 * total_data_count (which is 0 in our case) rather than max_data_count.
1329 * Allocate the correct amount and return the pointer to let
1330 * it be deallocated when we return.
1332 struct shadow_copy_data
*shadow_data
= NULL
;
1333 bool labels
= False
;
1334 uint32_t labels_data_count
= 0;
1336 char *cur_pdata
= NULL
;
1338 if (max_out_len
< 16) {
1339 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1341 return NT_STATUS_INVALID_PARAMETER
;
1344 if (max_out_len
> 16) {
1348 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1349 if (shadow_data
== NULL
) {
1350 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1351 return NT_STATUS_NO_MEMORY
;
1355 * Call the VFS routine to actually do the work.
1357 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1360 /* broken module didn't set errno on error */
1361 status
= NT_STATUS_UNSUCCESSFUL
;
1363 status
= map_nt_error_from_unix(errno
);
1364 if (NT_STATUS_EQUAL(status
,
1365 NT_STATUS_NOT_SUPPORTED
)) {
1369 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1370 "connectpath %s, failed - %s.\n",
1371 fsp
->conn
->connectpath
,
1372 nt_errstr(status
)));
1373 TALLOC_FREE(shadow_data
);
1377 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1378 sizeof(SHADOW_COPY_LABEL
)) + 2;
1383 *out_len
= 12 + labels_data_count
;
1386 if (max_out_len
< *out_len
) {
1387 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1388 max_out_len
, *out_len
));
1389 TALLOC_FREE(shadow_data
);
1390 return NT_STATUS_BUFFER_TOO_SMALL
;
1393 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1394 if (cur_pdata
== NULL
) {
1395 TALLOC_FREE(shadow_data
);
1396 return NT_STATUS_NO_MEMORY
;
1399 *out_data
= cur_pdata
;
1401 /* num_volumes 4 bytes */
1402 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1405 /* num_labels 4 bytes */
1406 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1409 /* needed_data_count 4 bytes */
1410 SIVAL(cur_pdata
, 8, labels_data_count
);
1414 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1415 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1416 if (labels
&& shadow_data
->labels
) {
1417 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1419 status
= srvstr_push(cur_pdata
, req_flags
,
1420 cur_pdata
, shadow_data
->labels
[i
],
1421 2 * sizeof(SHADOW_COPY_LABEL
),
1422 STR_UNICODE
|STR_TERMINATE
, &len
);
1423 if (!NT_STATUS_IS_OK(status
)) {
1424 TALLOC_FREE(*out_data
);
1425 TALLOC_FREE(shadow_data
);
1428 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1429 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1433 TALLOC_FREE(shadow_data
);
1435 return NT_STATUS_OK
;
1438 case FSCTL_FIND_FILES_BY_SID
:
1440 /* pretend this succeeded -
1442 * we have to send back a list with all files owned by this SID
1444 * but I have to check that --metze
1450 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1451 fsp_fnum_dbg(fsp
)));
1454 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1455 return NT_STATUS_INVALID_PARAMETER
;
1458 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1460 /* unknown 4 bytes: this is not the length of the sid :-( */
1461 /*unknown = IVAL(pdata,0);*/
1463 if (!sid_parse(_in_data
+ 4, sid_len
, &sid
)) {
1464 return NT_STATUS_INVALID_PARAMETER
;
1466 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
1468 if (!sid_to_uid(&sid
, &uid
)) {
1469 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1470 sid_string_dbg(&sid
),
1471 (unsigned long)sid_len
));
1475 /* we can take a look at the find source :-)
1477 * find ./ -uid $uid -name '*' is what we need here
1480 * and send 4bytes len and then NULL terminated unicode strings
1483 * but I don't know how to deal with the paged results
1484 * (maybe we can hang the result anywhere in the fsp struct)
1486 * but I don't know how to deal with the paged results
1487 * (maybe we can hang the result anywhere in the fsp struct)
1489 * we don't send all files at once
1490 * and at the next we should *not* start from the beginning,
1491 * so we have to cache the result
1496 /* this works for now... */
1497 return NT_STATUS_OK
;
1500 case FSCTL_QUERY_ALLOCATED_RANGES
:
1502 /* FIXME: This is just a dummy reply, telling that all of the
1503 * file is allocated. MKS cp needs that.
1504 * Adding the real allocated ranges via FIEMAP on Linux
1505 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1506 * this FSCTL correct for sparse files.
1508 uint64_t offset
, length
;
1509 char *out_data_tmp
= NULL
;
1512 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1514 return NT_STATUS_INVALID_PARAMETER
;
1517 if (max_out_len
< 16) {
1518 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1520 return NT_STATUS_INVALID_PARAMETER
;
1523 offset
= BVAL(in_data
,0);
1524 length
= BVAL(in_data
,8);
1526 if (offset
+ length
< offset
) {
1527 /* No 64-bit integer wrap. */
1528 return NT_STATUS_INVALID_PARAMETER
;
1531 /* Shouldn't this be SMB_VFS_STAT ... ? */
1532 status
= vfs_stat_fsp(fsp
);
1533 if (!NT_STATUS_IS_OK(status
)) {
1538 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1539 if (out_data_tmp
== NULL
) {
1540 DEBUG(10, ("unable to allocate memory for response\n"));
1541 return NT_STATUS_NO_MEMORY
;
1544 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1545 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1547 memset(out_data_tmp
, 0, *out_len
);
1549 uint64_t end
= offset
+ length
;
1550 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1551 SBVAL(out_data_tmp
, 0, 0);
1552 SBVAL(out_data_tmp
, 8, end
);
1555 *out_data
= out_data_tmp
;
1557 return NT_STATUS_OK
;
1560 case FSCTL_IS_VOLUME_DIRTY
:
1562 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1563 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1565 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1566 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1568 return NT_STATUS_INVALID_PARAMETER
;
1573 * Only print once ... unfortunately there could be lots of
1574 * different FSCTLs that are called.
1576 if (!vfswrap_logged_ioctl_message
) {
1577 vfswrap_logged_ioctl_message
= true;
1578 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1579 __func__
, function
));
1583 return NT_STATUS_NOT_SUPPORTED
;
1586 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
1587 const struct smb_filename
*fname
,
1588 SMB_STRUCT_STAT
*sbuf
);
1590 static NTSTATUS
vfswrap_get_dos_attributes(struct vfs_handle_struct
*handle
,
1591 struct smb_filename
*smb_fname
,
1596 offline
= vfswrap_is_offline(handle
, smb_fname
, &smb_fname
->st
);
1598 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1601 return get_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1604 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1605 struct files_struct
*fsp
,
1610 offline
= vfswrap_is_offline(handle
, fsp
->fsp_name
, &fsp
->fsp_name
->st
);
1612 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1615 return get_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1618 static NTSTATUS
vfswrap_set_dos_attributes(struct vfs_handle_struct
*handle
,
1619 const struct smb_filename
*smb_fname
,
1622 return set_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1625 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1626 struct files_struct
*fsp
,
1629 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1632 static struct vfs_offload_ctx
*vfswrap_offload_ctx
;
1634 struct vfswrap_offload_read_state
{
1638 static struct tevent_req
*vfswrap_offload_read_send(
1639 TALLOC_CTX
*mem_ctx
,
1640 struct tevent_context
*ev
,
1641 struct vfs_handle_struct
*handle
,
1642 struct files_struct
*fsp
,
1648 struct tevent_req
*req
= NULL
;
1649 struct vfswrap_offload_read_state
*state
= NULL
;
1652 req
= tevent_req_create(mem_ctx
, &state
,
1653 struct vfswrap_offload_read_state
);
1658 status
= vfs_offload_token_ctx_init(fsp
->conn
->sconn
->client
,
1659 &vfswrap_offload_ctx
);
1660 if (tevent_req_nterror(req
, status
)) {
1661 return tevent_req_post(req
, ev
);
1664 if (fsctl
!= FSCTL_SRV_REQUEST_RESUME_KEY
) {
1665 tevent_req_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
1666 return tevent_req_post(req
, ev
);
1669 status
= vfs_offload_token_create_blob(state
, fsp
, fsctl
,
1671 if (tevent_req_nterror(req
, status
)) {
1672 return tevent_req_post(req
, ev
);
1675 status
= vfs_offload_token_db_store_fsp(vfswrap_offload_ctx
, fsp
,
1677 if (tevent_req_nterror(req
, status
)) {
1678 return tevent_req_post(req
, ev
);
1681 tevent_req_done(req
);
1682 return tevent_req_post(req
, ev
);
1685 static NTSTATUS
vfswrap_offload_read_recv(struct tevent_req
*req
,
1686 struct vfs_handle_struct
*handle
,
1687 TALLOC_CTX
*mem_ctx
,
1690 struct vfswrap_offload_read_state
*state
= tevent_req_data(
1691 req
, struct vfswrap_offload_read_state
);
1694 if (tevent_req_is_nterror(req
, &status
)) {
1695 tevent_req_received(req
);
1699 token
->length
= state
->token
.length
;
1700 token
->data
= talloc_move(mem_ctx
, &state
->token
.data
);
1702 tevent_req_received(req
);
1703 return NT_STATUS_OK
;
1706 struct vfswrap_offload_write_state
{
1707 struct tevent_context
*ev
;
1709 bool read_lck_locked
;
1710 bool write_lck_locked
;
1712 struct files_struct
*src_fsp
;
1714 struct files_struct
*dst_fsp
;
1718 size_t next_io_size
;
1721 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
);
1723 static struct tevent_req
*vfswrap_offload_write_send(
1724 struct vfs_handle_struct
*handle
,
1725 TALLOC_CTX
*mem_ctx
,
1726 struct tevent_context
*ev
,
1729 off_t transfer_offset
,
1730 struct files_struct
*dest_fsp
,
1734 struct tevent_req
*req
;
1735 struct vfswrap_offload_write_state
*state
= NULL
;
1736 size_t num
= MIN(to_copy
, COPYCHUNK_MAX_TOTAL_LEN
);
1737 files_struct
*src_fsp
= NULL
;
1740 req
= tevent_req_create(mem_ctx
, &state
,
1741 struct vfswrap_offload_write_state
);
1746 *state
= (struct vfswrap_offload_write_state
) {
1749 .src_off
= transfer_offset
,
1750 .dst_fsp
= dest_fsp
,
1751 .dst_off
= dest_off
,
1753 .remaining
= to_copy
,
1757 case FSCTL_SRV_COPYCHUNK
:
1758 case FSCTL_SRV_COPYCHUNK_WRITE
:
1761 case FSCTL_OFFLOAD_WRITE
:
1762 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
1763 return tevent_req_post(req
, ev
);
1765 case FSCTL_DUP_EXTENTS_TO_FILE
:
1766 DBG_DEBUG("COW clones not supported by vfs_default\n");
1767 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1768 return tevent_req_post(req
, ev
);
1771 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1772 return tevent_req_post(req
, ev
);
1776 * From here on we assume a copy-chunk fsctl
1780 tevent_req_done(req
);
1781 return tevent_req_post(req
, ev
);
1784 status
= vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx
,
1786 if (tevent_req_nterror(req
, status
)) {
1787 return tevent_req_post(req
, ev
);
1789 state
->src_fsp
= src_fsp
;
1791 DBG_DEBUG("server side copy chunk of length %" PRIu64
"\n", to_copy
);
1793 status
= vfs_offload_token_check_handles(fsctl
, src_fsp
, dest_fsp
);
1794 if (!NT_STATUS_IS_OK(status
)) {
1795 tevent_req_nterror(req
, status
);
1796 return tevent_req_post(req
, ev
);
1799 state
->buf
= talloc_array(state
, uint8_t, num
);
1800 if (tevent_req_nomem(state
->buf
, req
)) {
1801 return tevent_req_post(req
, ev
);
1804 status
= vfs_stat_fsp(src_fsp
);
1805 if (tevent_req_nterror(req
, status
)) {
1806 return tevent_req_post(req
, ev
);
1809 if (src_fsp
->fsp_name
->st
.st_ex_size
< state
->src_off
+ num
) {
1811 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1812 * If the SourceOffset or SourceOffset + Length extends beyond
1813 * the end of file, the server SHOULD<240> treat this as a
1814 * STATUS_END_OF_FILE error.
1816 * <240> Section 3.3.5.15.6: Windows servers will return
1817 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1819 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
1820 return tevent_req_post(req
, ev
);
1823 if (src_fsp
->op
== NULL
) {
1824 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1825 return tevent_req_post(req
, ev
);
1828 if (dest_fsp
->op
== NULL
) {
1829 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1830 return tevent_req_post(req
, ev
);
1833 status
= vfswrap_offload_write_loop(req
);
1834 if (!NT_STATUS_IS_OK(status
)) {
1835 tevent_req_nterror(req
, status
);
1836 return tevent_req_post(req
, ev
);
1842 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
);
1844 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
)
1846 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1847 req
, struct vfswrap_offload_write_state
);
1848 struct tevent_req
*subreq
= NULL
;
1849 struct lock_struct read_lck
;
1852 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
1854 init_strict_lock_struct(state
->src_fsp
,
1855 state
->src_fsp
->op
->global
->open_persistent_id
,
1857 state
->next_io_size
,
1861 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
1865 return NT_STATUS_FILE_LOCK_CONFLICT
;
1868 subreq
= SMB_VFS_PREAD_SEND(state
,
1869 state
->src_fsp
->conn
->sconn
->ev_ctx
,
1872 state
->next_io_size
,
1874 if (subreq
== NULL
) {
1875 return NT_STATUS_NO_MEMORY
;
1877 tevent_req_set_callback(subreq
, vfswrap_offload_write_read_done
, req
);
1879 return NT_STATUS_OK
;
1882 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
);
1884 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
)
1886 struct tevent_req
*req
= tevent_req_callback_data(
1887 subreq
, struct tevent_req
);
1888 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1889 req
, struct vfswrap_offload_write_state
);
1890 struct vfs_aio_state aio_state
;
1891 struct lock_struct write_lck
;
1895 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
1896 TALLOC_FREE(subreq
);
1898 DBG_ERR("read failed: %s\n", strerror(errno
));
1899 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1902 if (nread
!= state
->next_io_size
) {
1903 DBG_ERR("Short read, only %zd of %zu\n",
1904 nread
, state
->next_io_size
);
1905 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1909 state
->src_off
+= nread
;
1911 init_strict_lock_struct(state
->dst_fsp
,
1912 state
->dst_fsp
->op
->global
->open_persistent_id
,
1914 state
->next_io_size
,
1918 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
1922 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1926 subreq
= SMB_VFS_PWRITE_SEND(state
,
1930 state
->next_io_size
,
1932 if (subreq
== NULL
) {
1933 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1936 tevent_req_set_callback(subreq
, vfswrap_offload_write_write_done
, req
);
1939 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
)
1941 struct tevent_req
*req
= tevent_req_callback_data(
1942 subreq
, struct tevent_req
);
1943 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1944 req
, struct vfswrap_offload_write_state
);
1945 struct vfs_aio_state aio_state
;
1949 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
1950 TALLOC_FREE(subreq
);
1951 if (nwritten
== -1) {
1952 DBG_ERR("write failed: %s\n", strerror(errno
));
1953 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1956 if (nwritten
!= state
->next_io_size
) {
1957 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
1958 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1962 state
->dst_off
+= nwritten
;
1964 if (state
->remaining
< nwritten
) {
1965 /* Paranoia check */
1966 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1969 state
->remaining
-= nwritten
;
1970 if (state
->remaining
== 0) {
1971 tevent_req_done(req
);
1975 status
= vfswrap_offload_write_loop(req
);
1976 if (!NT_STATUS_IS_OK(status
)) {
1977 tevent_req_nterror(req
, status
);
1984 static NTSTATUS
vfswrap_offload_write_recv(struct vfs_handle_struct
*handle
,
1985 struct tevent_req
*req
,
1988 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1989 req
, struct vfswrap_offload_write_state
);
1992 if (tevent_req_is_nterror(req
, &status
)) {
1993 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
1995 tevent_req_received(req
);
1999 *copied
= state
->to_copy
;
2000 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
2001 tevent_req_received(req
);
2003 return NT_STATUS_OK
;
2006 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
2007 TALLOC_CTX
*mem_ctx
,
2008 struct files_struct
*fsp
,
2009 struct smb_filename
*smb_fname
,
2010 uint16_t *_compression_fmt
)
2012 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2015 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
2016 TALLOC_CTX
*mem_ctx
,
2017 struct files_struct
*fsp
,
2018 uint16_t compression_fmt
)
2020 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2023 /********************************************************************
2024 Given a stat buffer return the allocated size on disk, taking into
2025 account sparse files.
2026 ********************************************************************/
2027 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
2028 struct files_struct
*fsp
,
2029 const SMB_STRUCT_STAT
*sbuf
)
2033 START_PROFILE(syscall_get_alloc_size
);
2035 if(S_ISDIR(sbuf
->st_ex_mode
)) {
2040 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2041 /* The type of st_blocksize is blkcnt_t which *MUST* be
2042 signed (according to POSIX) and can be less than 64-bits.
2043 Ensure when we're converting to 64 bits wide we don't
2045 #if defined(SIZEOF_BLKCNT_T_8)
2046 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
2047 #elif defined(SIZEOF_BLKCNT_T_4)
2049 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
2050 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
2053 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2057 * Some file systems do not allocate a block for very
2058 * small files. But for non-empty file should report a
2062 uint64_t filesize
= get_file_size_stat(sbuf
);
2064 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
2068 result
= get_file_size_stat(sbuf
);
2071 if (fsp
&& fsp
->initial_allocation_size
)
2072 result
= MAX(result
,fsp
->initial_allocation_size
);
2074 result
= smb_roundup(handle
->conn
, result
);
2077 END_PROFILE(syscall_get_alloc_size
);
2081 static int vfswrap_unlink(vfs_handle_struct
*handle
,
2082 const struct smb_filename
*smb_fname
)
2086 START_PROFILE(syscall_unlink
);
2088 if (smb_fname
->stream_name
) {
2092 result
= unlink(smb_fname
->base_name
);
2095 END_PROFILE(syscall_unlink
);
2099 static int vfswrap_chmod(vfs_handle_struct
*handle
,
2100 const struct smb_filename
*smb_fname
,
2105 START_PROFILE(syscall_chmod
);
2108 * We need to do this due to the fact that the default POSIX ACL
2109 * chmod modifies the ACL *mask* for the group owner, not the
2110 * group owner bits directly. JRA.
2115 int saved_errno
= errno
; /* We might get ENOSYS */
2116 result
= SMB_VFS_CHMOD_ACL(handle
->conn
,
2120 END_PROFILE(syscall_chmod
);
2123 /* Error - return the old errno. */
2124 errno
= saved_errno
;
2127 result
= chmod(smb_fname
->base_name
, mode
);
2128 END_PROFILE(syscall_chmod
);
2132 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2136 START_PROFILE(syscall_fchmod
);
2139 * We need to do this due to the fact that the default POSIX ACL
2140 * chmod modifies the ACL *mask* for the group owner, not the
2141 * group owner bits directly. JRA.
2145 int saved_errno
= errno
; /* We might get ENOSYS */
2146 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
2147 END_PROFILE(syscall_fchmod
);
2150 /* Error - return the old errno. */
2151 errno
= saved_errno
;
2154 #if defined(HAVE_FCHMOD)
2155 result
= fchmod(fsp
->fh
->fd
, mode
);
2161 END_PROFILE(syscall_fchmod
);
2165 static int vfswrap_chown(vfs_handle_struct
*handle
,
2166 const struct smb_filename
*smb_fname
,
2172 START_PROFILE(syscall_chown
);
2173 result
= chown(smb_fname
->base_name
, uid
, gid
);
2174 END_PROFILE(syscall_chown
);
2178 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2183 START_PROFILE(syscall_fchown
);
2184 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
2185 END_PROFILE(syscall_fchown
);
2193 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2194 const struct smb_filename
*smb_fname
,
2200 START_PROFILE(syscall_lchown
);
2201 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2202 END_PROFILE(syscall_lchown
);
2206 static int vfswrap_chdir(vfs_handle_struct
*handle
,
2207 const struct smb_filename
*smb_fname
)
2211 START_PROFILE(syscall_chdir
);
2212 result
= chdir(smb_fname
->base_name
);
2213 END_PROFILE(syscall_chdir
);
2217 static struct smb_filename
*vfswrap_getwd(vfs_handle_struct
*handle
,
2221 struct smb_filename
*smb_fname
= NULL
;
2223 START_PROFILE(syscall_getwd
);
2224 result
= sys_getwd();
2225 END_PROFILE(syscall_getwd
);
2226 smb_fname
= synthetic_smb_fname(ctx
,
2231 if (smb_fname
== NULL
) {
2237 /*********************************************************************
2238 nsec timestamp resolution call. Convert down to whatever the underlying
2239 system will support.
2240 **********************************************************************/
2242 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
2243 const struct smb_filename
*smb_fname
,
2244 struct smb_file_time
*ft
)
2248 START_PROFILE(syscall_ntimes
);
2250 if (smb_fname
->stream_name
) {
2256 if (null_timespec(ft
->atime
)) {
2257 ft
->atime
= smb_fname
->st
.st_ex_atime
;
2260 if (null_timespec(ft
->mtime
)) {
2261 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
2264 if (!null_timespec(ft
->create_time
)) {
2265 set_create_timespec_ea(handle
->conn
,
2270 if ((timespec_compare(&ft
->atime
,
2271 &smb_fname
->st
.st_ex_atime
) == 0) &&
2272 (timespec_compare(&ft
->mtime
,
2273 &smb_fname
->st
.st_ex_mtime
) == 0)) {
2278 #if defined(HAVE_UTIMENSAT)
2280 struct timespec ts
[2];
2283 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
2285 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
2287 if (!((result
== -1) && (errno
== ENOSYS
))) {
2291 #if defined(HAVE_UTIMES)
2293 struct timeval tv
[2];
2294 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
2295 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
2296 result
= utimes(smb_fname
->base_name
, tv
);
2298 result
= utimes(smb_fname
->base_name
, NULL
);
2300 if (!((result
== -1) && (errno
== ENOSYS
))) {
2304 #if defined(HAVE_UTIME)
2306 struct utimbuf times
;
2307 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
2308 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
2309 result
= utime(smb_fname
->base_name
, ×
);
2311 result
= utime(smb_fname
->base_name
, NULL
);
2313 if (!((result
== -1) && (errno
== ENOSYS
))) {
2321 END_PROFILE(syscall_ntimes
);
2325 /*********************************************************************
2326 A version of ftruncate that will write the space on disk if strict
2328 **********************************************************************/
2330 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2332 off_t space_to_write
;
2333 uint64_t space_avail
;
2334 uint64_t bsize
,dfree
,dsize
;
2337 SMB_STRUCT_STAT
*pst
;
2339 status
= vfs_stat_fsp(fsp
);
2340 if (!NT_STATUS_IS_OK(status
)) {
2343 pst
= &fsp
->fsp_name
->st
;
2346 if (S_ISFIFO(pst
->st_ex_mode
))
2350 if (pst
->st_ex_size
== len
)
2353 /* Shrink - just ftruncate. */
2354 if (pst
->st_ex_size
> len
)
2355 return ftruncate(fsp
->fh
->fd
, len
);
2357 space_to_write
= len
- pst
->st_ex_size
;
2359 /* for allocation try fallocate first. This can fail on some
2360 platforms e.g. when the filesystem doesn't support it and no
2361 emulation is being done by the libc (like on AIX with JFS1). In that
2362 case we do our own emulation. fallocate implementations can
2363 return ENOTSUP or EINVAL in cases like that. */
2364 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2365 if (ret
== -1 && errno
== ENOSPC
) {
2371 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2372 "error %d. Falling back to slow manual allocation\n", errno
));
2374 /* available disk space is enough or not? */
2376 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2377 /* space_avail is 1k blocks */
2378 if (space_avail
== (uint64_t)-1 ||
2379 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2384 /* Write out the real space on disk. */
2385 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2393 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2396 SMB_STRUCT_STAT
*pst
;
2400 START_PROFILE(syscall_ftruncate
);
2402 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
2403 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2404 END_PROFILE(syscall_ftruncate
);
2408 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2409 ftruncate if the system supports it. Then I discovered that
2410 you can have some filesystems that support ftruncate
2411 expansion and some that don't! On Linux fat can't do
2412 ftruncate extend but ext2 can. */
2414 result
= ftruncate(fsp
->fh
->fd
, len
);
2416 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2417 extend a file with ftruncate. Provide alternate implementation
2420 /* Do an fstat to see if the file is longer than the requested
2421 size in which case the ftruncate above should have
2422 succeeded or shorter, in which case seek to len - 1 and
2423 write 1 byte of zero */
2424 status
= vfs_stat_fsp(fsp
);
2425 if (!NT_STATUS_IS_OK(status
)) {
2429 /* We need to update the files_struct after successful ftruncate */
2434 pst
= &fsp
->fsp_name
->st
;
2437 if (S_ISFIFO(pst
->st_ex_mode
)) {
2443 if (pst
->st_ex_size
== len
) {
2448 if (pst
->st_ex_size
> len
) {
2449 /* the ftruncate should have worked */
2453 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
2461 END_PROFILE(syscall_ftruncate
);
2465 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
2473 START_PROFILE(syscall_fallocate
);
2475 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
2477 * posix_fallocate returns 0 on success, errno on error
2478 * and doesn't set errno. Make it behave like fallocate()
2479 * which returns -1, and sets errno on failure.
2486 /* sys_fallocate handles filtering of unsupported mode flags */
2487 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
2489 END_PROFILE(syscall_fallocate
);
2493 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
2497 START_PROFILE(syscall_fcntl_lock
);
2499 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2501 "force process locks",
2503 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2506 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
2507 END_PROFILE(syscall_fcntl_lock
);
2511 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2512 uint32_t share_mode
, uint32_t access_mask
)
2514 START_PROFILE(syscall_kernel_flock
);
2515 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
2516 END_PROFILE(syscall_kernel_flock
);
2520 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2525 START_PROFILE(syscall_fcntl_getlock
);
2527 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2529 "force process locks",
2531 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2534 result
= fcntl_getlock(fsp
->fh
->fd
, op
, poffset
, pcount
, ptype
, ppid
);
2535 END_PROFILE(syscall_fcntl_getlock
);
2539 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2544 START_PROFILE(syscall_linux_setlease
);
2546 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2547 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2551 END_PROFILE(syscall_linux_setlease
);
2555 static int vfswrap_symlink(vfs_handle_struct
*handle
,
2556 const char *link_target
,
2557 const struct smb_filename
*new_smb_fname
)
2561 START_PROFILE(syscall_symlink
);
2562 result
= symlink(link_target
, new_smb_fname
->base_name
);
2563 END_PROFILE(syscall_symlink
);
2567 static int vfswrap_readlink(vfs_handle_struct
*handle
,
2568 const struct smb_filename
*smb_fname
,
2574 START_PROFILE(syscall_readlink
);
2575 result
= readlink(smb_fname
->base_name
, buf
, bufsiz
);
2576 END_PROFILE(syscall_readlink
);
2580 static int vfswrap_link(vfs_handle_struct
*handle
,
2581 const struct smb_filename
*old_smb_fname
,
2582 const struct smb_filename
*new_smb_fname
)
2586 START_PROFILE(syscall_link
);
2587 result
= link(old_smb_fname
->base_name
, new_smb_fname
->base_name
);
2588 END_PROFILE(syscall_link
);
2592 static int vfswrap_mknod(vfs_handle_struct
*handle
,
2593 const struct smb_filename
*smb_fname
,
2599 START_PROFILE(syscall_mknod
);
2600 result
= sys_mknod(smb_fname
->base_name
, mode
, dev
);
2601 END_PROFILE(syscall_mknod
);
2605 static struct smb_filename
*vfswrap_realpath(vfs_handle_struct
*handle
,
2607 const struct smb_filename
*smb_fname
)
2610 struct smb_filename
*result_fname
= NULL
;
2612 START_PROFILE(syscall_realpath
);
2613 result
= sys_realpath(smb_fname
->base_name
);
2614 END_PROFILE(syscall_realpath
);
2616 result_fname
= synthetic_smb_fname(ctx
, result
, NULL
, NULL
, 0);
2619 return result_fname
;
2622 static int vfswrap_chflags(vfs_handle_struct
*handle
,
2623 const struct smb_filename
*smb_fname
,
2627 return chflags(smb_fname
->base_name
, flags
);
2634 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2635 const SMB_STRUCT_STAT
*sbuf
)
2639 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2643 key
.devid
= sbuf
->st_ex_dev
;
2644 key
.inode
= sbuf
->st_ex_ino
;
2645 /* key.extid is unused by default. */
2650 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
2651 struct files_struct
*fsp
,
2652 const struct smb_filename
*smb_fname
,
2653 TALLOC_CTX
*mem_ctx
,
2654 unsigned int *pnum_streams
,
2655 struct stream_struct
**pstreams
)
2657 SMB_STRUCT_STAT sbuf
;
2658 struct stream_struct
*tmp_streams
= NULL
;
2661 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
2663 * No default streams on directories
2668 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
2669 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
2672 struct smb_filename smb_fname_cp
;
2674 ZERO_STRUCT(smb_fname_cp
);
2675 smb_fname_cp
.base_name
= discard_const_p(char,
2676 smb_fname
->base_name
);
2677 smb_fname_cp
.flags
= smb_fname
->flags
;
2679 if (smb_fname_cp
.flags
& SMB_FILENAME_POSIX_PATH
) {
2680 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname_cp
);
2682 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname_cp
);
2684 sbuf
= smb_fname_cp
.st
;
2688 return map_nt_error_from_unix(errno
);
2691 if (S_ISDIR(sbuf
.st_ex_mode
)) {
2695 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
2696 (*pnum_streams
) + 1);
2697 if (tmp_streams
== NULL
) {
2698 return NT_STATUS_NO_MEMORY
;
2700 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
2701 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
2702 return NT_STATUS_NO_MEMORY
;
2704 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
2705 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
2708 *pstreams
= tmp_streams
;
2710 return NT_STATUS_OK
;
2713 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
2716 TALLOC_CTX
*mem_ctx
,
2720 * Don't fall back to get_real_filename so callers can differentiate
2721 * between a full directory scan and an actual case-insensitive stat.
2727 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
2728 const struct smb_filename
*smb_fname
)
2730 return handle
->conn
->connectpath
;
2733 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
2734 struct byte_range_lock
*br_lck
,
2735 struct lock_struct
*plock
,
2738 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2740 /* Note: blr is not used in the default implementation. */
2741 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
2744 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
2745 struct messaging_context
*msg_ctx
,
2746 struct byte_range_lock
*br_lck
,
2747 const struct lock_struct
*plock
)
2749 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2751 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
2754 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
2755 struct byte_range_lock
*br_lck
,
2756 struct lock_struct
*plock
)
2758 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2760 /* Note: blr is not used in the default implementation. */
2761 return brl_lock_cancel_default(br_lck
, plock
);
2764 static bool vfswrap_strict_lock_check(struct vfs_handle_struct
*handle
,
2766 struct lock_struct
*plock
)
2768 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2769 plock
->lock_type
== WRITE_LOCK
);
2771 return strict_lock_check_default(fsp
, plock
);
2774 /* NT ACL operations. */
2776 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
2778 uint32_t security_info
,
2779 TALLOC_CTX
*mem_ctx
,
2780 struct security_descriptor
**ppdesc
)
2784 START_PROFILE(fget_nt_acl
);
2785 result
= posix_fget_nt_acl(fsp
, security_info
,
2787 END_PROFILE(fget_nt_acl
);
2791 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
2792 const struct smb_filename
*smb_fname
,
2793 uint32_t security_info
,
2794 TALLOC_CTX
*mem_ctx
,
2795 struct security_descriptor
**ppdesc
)
2799 START_PROFILE(get_nt_acl
);
2800 result
= posix_get_nt_acl(handle
->conn
,
2805 END_PROFILE(get_nt_acl
);
2809 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
2813 START_PROFILE(fset_nt_acl
);
2814 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
2815 END_PROFILE(fset_nt_acl
);
2819 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
2820 struct smb_filename
*file
,
2821 struct security_acl
*sacl
,
2822 uint32_t access_requested
,
2823 uint32_t access_denied
)
2825 return NT_STATUS_OK
; /* Nothing to do here ... */
2828 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
,
2829 const struct smb_filename
*smb_fname
,
2838 START_PROFILE(chmod_acl
);
2839 result
= chmod_acl(handle
->conn
, smb_fname
, mode
);
2840 END_PROFILE(chmod_acl
);
2845 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2853 START_PROFILE(fchmod_acl
);
2854 result
= fchmod_acl(fsp
, mode
);
2855 END_PROFILE(fchmod_acl
);
2860 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
2861 const struct smb_filename
*smb_fname
,
2862 SMB_ACL_TYPE_T type
,
2863 TALLOC_CTX
*mem_ctx
)
2865 return sys_acl_get_file(handle
, smb_fname
, type
, mem_ctx
);
2868 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
2870 TALLOC_CTX
*mem_ctx
)
2872 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
2875 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
,
2876 const struct smb_filename
*smb_fname
,
2877 SMB_ACL_TYPE_T acltype
,
2880 return sys_acl_set_file(handle
, smb_fname
, acltype
, theacl
);
2883 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2885 return sys_acl_set_fd(handle
, fsp
, theacl
);
2888 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
2889 const struct smb_filename
*smb_fname
)
2891 return sys_acl_delete_def_file(handle
, smb_fname
);
2894 /****************************************************************
2895 Extended attribute operations.
2896 *****************************************************************/
2898 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,
2899 const struct smb_filename
*smb_fname
,
2904 return getxattr(smb_fname
->base_name
, name
, value
, size
);
2907 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2909 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2912 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
,
2913 const struct smb_filename
*smb_fname
,
2917 return listxattr(smb_fname
->base_name
, list
, size
);
2920 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2922 return flistxattr(fsp
->fh
->fd
, list
, size
);
2925 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
,
2926 const struct smb_filename
*smb_fname
,
2929 return removexattr(smb_fname
->base_name
, name
);
2932 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2934 return fremovexattr(fsp
->fh
->fd
, name
);
2937 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
,
2938 const struct smb_filename
*smb_fname
,
2944 return setxattr(smb_fname
->base_name
, name
, value
, size
, flags
);
2947 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2949 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2952 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2957 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2958 const struct smb_filename
*fname
,
2959 SMB_STRUCT_STAT
*sbuf
)
2963 bool offline
= false;
2965 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2969 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2970 #if defined(ENOTSUP)
2976 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2977 if (!NT_STATUS_IS_OK(status
)) {
2978 errno
= map_errno_from_nt_status(status
);
2982 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2989 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
2990 struct files_struct
*fsp
,
2991 TALLOC_CTX
*mem_ctx
,
2994 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
2997 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
2998 struct files_struct
*fsp
,
2999 const DATA_BLOB old_cookie
,
3000 TALLOC_CTX
*mem_ctx
,
3001 DATA_BLOB
*new_cookie
)
3003 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
3007 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
3008 struct smb_request
*smb1req
,
3009 struct smbXsrv_open
*op
,
3010 const DATA_BLOB old_cookie
,
3011 TALLOC_CTX
*mem_ctx
,
3012 struct files_struct
**fsp
,
3013 DATA_BLOB
*new_cookie
)
3015 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
3016 old_cookie
, mem_ctx
,
3020 static struct vfs_fn_pointers vfs_default_fns
= {
3021 /* Disk operations */
3023 .connect_fn
= vfswrap_connect
,
3024 .disconnect_fn
= vfswrap_disconnect
,
3025 .disk_free_fn
= vfswrap_disk_free
,
3026 .get_quota_fn
= vfswrap_get_quota
,
3027 .set_quota_fn
= vfswrap_set_quota
,
3028 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
3029 .statvfs_fn
= vfswrap_statvfs
,
3030 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
3031 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
3032 .snap_check_path_fn
= vfswrap_snap_check_path
,
3033 .snap_create_fn
= vfswrap_snap_create
,
3034 .snap_delete_fn
= vfswrap_snap_delete
,
3036 /* Directory operations */
3038 .opendir_fn
= vfswrap_opendir
,
3039 .fdopendir_fn
= vfswrap_fdopendir
,
3040 .readdir_fn
= vfswrap_readdir
,
3041 .readdir_attr_fn
= vfswrap_readdir_attr
,
3042 .seekdir_fn
= vfswrap_seekdir
,
3043 .telldir_fn
= vfswrap_telldir
,
3044 .rewind_dir_fn
= vfswrap_rewinddir
,
3045 .mkdir_fn
= vfswrap_mkdir
,
3046 .rmdir_fn
= vfswrap_rmdir
,
3047 .closedir_fn
= vfswrap_closedir
,
3048 .init_search_op_fn
= vfswrap_init_search_op
,
3050 /* File operations */
3052 .open_fn
= vfswrap_open
,
3053 .create_file_fn
= vfswrap_create_file
,
3054 .close_fn
= vfswrap_close
,
3055 .read_fn
= vfswrap_read
,
3056 .pread_fn
= vfswrap_pread
,
3057 .pread_send_fn
= vfswrap_pread_send
,
3058 .pread_recv_fn
= vfswrap_pread_recv
,
3059 .write_fn
= vfswrap_write
,
3060 .pwrite_fn
= vfswrap_pwrite
,
3061 .pwrite_send_fn
= vfswrap_pwrite_send
,
3062 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
3063 .lseek_fn
= vfswrap_lseek
,
3064 .sendfile_fn
= vfswrap_sendfile
,
3065 .recvfile_fn
= vfswrap_recvfile
,
3066 .rename_fn
= vfswrap_rename
,
3067 .fsync_fn
= vfswrap_fsync
,
3068 .fsync_send_fn
= vfswrap_fsync_send
,
3069 .fsync_recv_fn
= vfswrap_fsync_recv
,
3070 .stat_fn
= vfswrap_stat
,
3071 .fstat_fn
= vfswrap_fstat
,
3072 .lstat_fn
= vfswrap_lstat
,
3073 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
3074 .unlink_fn
= vfswrap_unlink
,
3075 .chmod_fn
= vfswrap_chmod
,
3076 .fchmod_fn
= vfswrap_fchmod
,
3077 .chown_fn
= vfswrap_chown
,
3078 .fchown_fn
= vfswrap_fchown
,
3079 .lchown_fn
= vfswrap_lchown
,
3080 .chdir_fn
= vfswrap_chdir
,
3081 .getwd_fn
= vfswrap_getwd
,
3082 .ntimes_fn
= vfswrap_ntimes
,
3083 .ftruncate_fn
= vfswrap_ftruncate
,
3084 .fallocate_fn
= vfswrap_fallocate
,
3085 .lock_fn
= vfswrap_lock
,
3086 .kernel_flock_fn
= vfswrap_kernel_flock
,
3087 .linux_setlease_fn
= vfswrap_linux_setlease
,
3088 .getlock_fn
= vfswrap_getlock
,
3089 .symlink_fn
= vfswrap_symlink
,
3090 .readlink_fn
= vfswrap_readlink
,
3091 .link_fn
= vfswrap_link
,
3092 .mknod_fn
= vfswrap_mknod
,
3093 .realpath_fn
= vfswrap_realpath
,
3094 .chflags_fn
= vfswrap_chflags
,
3095 .file_id_create_fn
= vfswrap_file_id_create
,
3096 .streaminfo_fn
= vfswrap_streaminfo
,
3097 .get_real_filename_fn
= vfswrap_get_real_filename
,
3098 .connectpath_fn
= vfswrap_connectpath
,
3099 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
3100 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
3101 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
3102 .strict_lock_check_fn
= vfswrap_strict_lock_check
,
3103 .translate_name_fn
= vfswrap_translate_name
,
3104 .fsctl_fn
= vfswrap_fsctl
,
3105 .set_dos_attributes_fn
= vfswrap_set_dos_attributes
,
3106 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
3107 .get_dos_attributes_fn
= vfswrap_get_dos_attributes
,
3108 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
3109 .offload_read_send_fn
= vfswrap_offload_read_send
,
3110 .offload_read_recv_fn
= vfswrap_offload_read_recv
,
3111 .offload_write_send_fn
= vfswrap_offload_write_send
,
3112 .offload_write_recv_fn
= vfswrap_offload_write_recv
,
3113 .get_compression_fn
= vfswrap_get_compression
,
3114 .set_compression_fn
= vfswrap_set_compression
,
3116 /* NT ACL operations. */
3118 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
3119 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
3120 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
3121 .audit_file_fn
= vfswrap_audit_file
,
3123 /* POSIX ACL operations. */
3125 .chmod_acl_fn
= vfswrap_chmod_acl
,
3126 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
3128 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
3129 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
3130 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
3131 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
3132 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
3133 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
3134 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
3136 /* EA operations. */
3137 .getxattr_fn
= vfswrap_getxattr
,
3138 .fgetxattr_fn
= vfswrap_fgetxattr
,
3139 .listxattr_fn
= vfswrap_listxattr
,
3140 .flistxattr_fn
= vfswrap_flistxattr
,
3141 .removexattr_fn
= vfswrap_removexattr
,
3142 .fremovexattr_fn
= vfswrap_fremovexattr
,
3143 .setxattr_fn
= vfswrap_setxattr
,
3144 .fsetxattr_fn
= vfswrap_fsetxattr
,
3146 /* aio operations */
3147 .aio_force_fn
= vfswrap_aio_force
,
3149 /* durable handle operations */
3150 .durable_cookie_fn
= vfswrap_durable_cookie
,
3151 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
3152 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
3155 NTSTATUS
vfs_default_init(TALLOC_CTX
*);
3156 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
3158 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
3159 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);