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 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
{
746 struct vfs_aio_state vfs_aio_state
;
747 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
750 static void vfs_pread_do(void *private_data
);
751 static void vfs_pread_done(struct tevent_req
*subreq
);
752 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
);
754 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
756 struct tevent_context
*ev
,
757 struct files_struct
*fsp
,
759 size_t n
, off_t offset
)
761 struct tevent_req
*req
, *subreq
;
762 struct vfswrap_pread_state
*state
;
765 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
770 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
771 if (tevent_req_error(req
, ret
)) {
772 return tevent_req_post(req
, ev
);
776 state
->fd
= fsp
->fh
->fd
;
779 state
->offset
= offset
;
781 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
782 state
->profile_bytes
, n
);
783 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
785 subreq
= pthreadpool_tevent_job_send(
786 state
, ev
, handle
->conn
->sconn
->pool
,
787 vfs_pread_do
, state
);
788 if (tevent_req_nomem(subreq
, req
)) {
789 return tevent_req_post(req
, ev
);
791 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
793 talloc_set_destructor(state
, vfs_pread_state_destructor
);
798 static void vfs_pread_do(void *private_data
)
800 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
801 private_data
, struct vfswrap_pread_state
);
802 struct timespec start_time
;
803 struct timespec end_time
;
805 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
807 PROFILE_TIMESTAMP(&start_time
);
810 state
->ret
= pread(state
->fd
, state
->buf
, state
->count
,
812 } while ((state
->ret
== -1) && (errno
== EINTR
));
814 if (state
->ret
== -1) {
815 state
->vfs_aio_state
.error
= errno
;
818 PROFILE_TIMESTAMP(&end_time
);
820 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
822 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
825 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
)
830 static void vfs_pread_done(struct tevent_req
*subreq
)
832 struct tevent_req
*req
= tevent_req_callback_data(
833 subreq
, struct tevent_req
);
834 struct vfswrap_pread_state
*state
= tevent_req_data(
835 req
, struct vfswrap_pread_state
);
838 ret
= pthreadpool_tevent_job_recv(subreq
);
840 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
841 talloc_set_destructor(state
, NULL
);
842 if (tevent_req_error(req
, ret
)) {
846 tevent_req_done(req
);
849 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
850 struct vfs_aio_state
*vfs_aio_state
)
852 struct vfswrap_pread_state
*state
= tevent_req_data(
853 req
, struct vfswrap_pread_state
);
855 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
859 *vfs_aio_state
= state
->vfs_aio_state
;
863 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
));
938 if (state
->ret
== -1) {
939 state
->vfs_aio_state
.error
= errno
;
942 PROFILE_TIMESTAMP(&end_time
);
944 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
946 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
949 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
)
954 static void vfs_pwrite_done(struct tevent_req
*subreq
)
956 struct tevent_req
*req
= tevent_req_callback_data(
957 subreq
, struct tevent_req
);
958 struct vfswrap_pwrite_state
*state
= tevent_req_data(
959 req
, struct vfswrap_pwrite_state
);
962 ret
= pthreadpool_tevent_job_recv(subreq
);
964 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
965 talloc_set_destructor(state
, NULL
);
966 if (tevent_req_error(req
, ret
)) {
970 tevent_req_done(req
);
973 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
974 struct vfs_aio_state
*vfs_aio_state
)
976 struct vfswrap_pwrite_state
*state
= tevent_req_data(
977 req
, struct vfswrap_pwrite_state
);
979 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
983 *vfs_aio_state
= state
->vfs_aio_state
;
987 struct vfswrap_fsync_state
{
991 struct vfs_aio_state vfs_aio_state
;
992 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic
);
995 static void vfs_fsync_do(void *private_data
);
996 static void vfs_fsync_done(struct tevent_req
*subreq
);
997 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
);
999 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
1000 TALLOC_CTX
*mem_ctx
,
1001 struct tevent_context
*ev
,
1002 struct files_struct
*fsp
)
1004 struct tevent_req
*req
, *subreq
;
1005 struct vfswrap_fsync_state
*state
;
1008 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
1013 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
1014 if (tevent_req_error(req
, ret
)) {
1015 return tevent_req_post(req
, ev
);
1019 state
->fd
= fsp
->fh
->fd
;
1021 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync
, profile_p
,
1022 state
->profile_basic
);
1024 subreq
= pthreadpool_tevent_job_send(
1025 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
1026 if (tevent_req_nomem(subreq
, req
)) {
1027 return tevent_req_post(req
, ev
);
1029 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
1031 talloc_set_destructor(state
, vfs_fsync_state_destructor
);
1036 static void vfs_fsync_do(void *private_data
)
1038 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
1039 private_data
, struct vfswrap_fsync_state
);
1040 struct timespec start_time
;
1041 struct timespec end_time
;
1043 PROFILE_TIMESTAMP(&start_time
);
1046 state
->ret
= fsync(state
->fd
);
1047 } while ((state
->ret
== -1) && (errno
== EINTR
));
1049 if (state
->ret
== -1) {
1050 state
->vfs_aio_state
.error
= errno
;
1053 PROFILE_TIMESTAMP(&end_time
);
1055 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1058 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
)
1063 static void vfs_fsync_done(struct tevent_req
*subreq
)
1065 struct tevent_req
*req
= tevent_req_callback_data(
1066 subreq
, struct tevent_req
);
1067 struct vfswrap_fsync_state
*state
= tevent_req_data(
1068 req
, struct vfswrap_fsync_state
);
1071 ret
= pthreadpool_tevent_job_recv(subreq
);
1072 TALLOC_FREE(subreq
);
1073 SMBPROFILE_BASIC_ASYNC_END(state
->profile_basic
);
1074 talloc_set_destructor(state
, NULL
);
1075 if (tevent_req_error(req
, ret
)) {
1079 tevent_req_done(req
);
1082 static int vfswrap_fsync_recv(struct tevent_req
*req
,
1083 struct vfs_aio_state
*vfs_aio_state
)
1085 struct vfswrap_fsync_state
*state
= tevent_req_data(
1086 req
, struct vfswrap_fsync_state
);
1088 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1092 *vfs_aio_state
= state
->vfs_aio_state
;
1096 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1100 START_PROFILE(syscall_lseek
);
1102 /* Cope with 'stat' file opens. */
1103 if (fsp
->fh
->fd
!= -1)
1104 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
1107 * We want to maintain the fiction that we can seek
1108 * on a fifo for file system purposes. This allows
1109 * people to set up UNIX fifo's that feed data to Windows
1110 * applications. JRA.
1113 if((result
== -1) && (errno
== ESPIPE
)) {
1118 END_PROFILE(syscall_lseek
);
1122 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1123 off_t offset
, size_t n
)
1127 START_PROFILE_BYTES(syscall_sendfile
, n
);
1128 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
1129 END_PROFILE_BYTES(syscall_sendfile
);
1133 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1135 files_struct
*tofsp
,
1141 START_PROFILE_BYTES(syscall_recvfile
, n
);
1142 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
1143 END_PROFILE_BYTES(syscall_recvfile
);
1147 static int vfswrap_rename(vfs_handle_struct
*handle
,
1148 const struct smb_filename
*smb_fname_src
,
1149 const struct smb_filename
*smb_fname_dst
)
1153 START_PROFILE(syscall_rename
);
1155 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
1160 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
1163 END_PROFILE(syscall_rename
);
1167 static int vfswrap_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
1172 START_PROFILE(syscall_fsync
);
1173 result
= fsync(fsp
->fh
->fd
);
1174 END_PROFILE(syscall_fsync
);
1181 static int vfswrap_stat(vfs_handle_struct
*handle
,
1182 struct smb_filename
*smb_fname
)
1186 START_PROFILE(syscall_stat
);
1188 if (smb_fname
->stream_name
) {
1193 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1194 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1196 END_PROFILE(syscall_stat
);
1200 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1204 START_PROFILE(syscall_fstat
);
1205 result
= sys_fstat(fsp
->fh
->fd
,
1206 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1207 END_PROFILE(syscall_fstat
);
1211 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1212 struct smb_filename
*smb_fname
)
1216 START_PROFILE(syscall_lstat
);
1218 if (smb_fname
->stream_name
) {
1223 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1224 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1226 END_PROFILE(syscall_lstat
);
1230 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1232 enum vfs_translate_direction direction
,
1233 TALLOC_CTX
*mem_ctx
,
1236 return NT_STATUS_NONE_MAPPED
;
1240 * Implement the default fsctl operation.
1242 static bool vfswrap_logged_ioctl_message
= false;
1244 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1245 struct files_struct
*fsp
,
1248 uint16_t req_flags
, /* Needed for UNICODE ... */
1249 const uint8_t *_in_data
,
1251 uint8_t **_out_data
,
1252 uint32_t max_out_len
,
1255 const char *in_data
= (const char *)_in_data
;
1256 char **out_data
= (char **)_out_data
;
1260 case FSCTL_SET_SPARSE
:
1262 bool set_sparse
= true;
1264 if (in_len
>= 1 && in_data
[0] == 0) {
1268 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1270 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1271 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1272 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1273 nt_errstr(status
)));
1278 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1280 unsigned char objid
[16];
1281 char *return_data
= NULL
;
1283 /* This should return the object-id on this file.
1284 * I think I'll make this be the inode+dev. JRA.
1287 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1288 fsp_fnum_dbg(fsp
)));
1290 *out_len
= MIN(max_out_len
, 64);
1292 /* Hmmm, will this cause problems if less data asked for? */
1293 return_data
= talloc_array(ctx
, char, 64);
1294 if (return_data
== NULL
) {
1295 return NT_STATUS_NO_MEMORY
;
1298 /* For backwards compatibility only store the dev/inode. */
1299 push_file_id_16(return_data
, &fsp
->file_id
);
1300 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1301 push_file_id_16(return_data
+32, &fsp
->file_id
);
1302 memset(return_data
+48, 0, 16);
1303 *out_data
= return_data
;
1304 return NT_STATUS_OK
;
1307 case FSCTL_GET_REPARSE_POINT
:
1309 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1310 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1311 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1312 return NT_STATUS_NOT_A_REPARSE_POINT
;
1315 case FSCTL_SET_REPARSE_POINT
:
1317 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1318 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1319 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1320 return NT_STATUS_NOT_A_REPARSE_POINT
;
1323 case FSCTL_GET_SHADOW_COPY_DATA
:
1326 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1327 * and return their volume names. If max_data_count is 16, then it is just
1328 * asking for the number of volumes and length of the combined names.
1330 * pdata is the data allocated by our caller, but that uses
1331 * total_data_count (which is 0 in our case) rather than max_data_count.
1332 * Allocate the correct amount and return the pointer to let
1333 * it be deallocated when we return.
1335 struct shadow_copy_data
*shadow_data
= NULL
;
1336 bool labels
= False
;
1337 uint32_t labels_data_count
= 0;
1339 char *cur_pdata
= NULL
;
1341 if (max_out_len
< 16) {
1342 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1344 return NT_STATUS_INVALID_PARAMETER
;
1347 if (max_out_len
> 16) {
1351 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1352 if (shadow_data
== NULL
) {
1353 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1354 return NT_STATUS_NO_MEMORY
;
1358 * Call the VFS routine to actually do the work.
1360 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1363 /* broken module didn't set errno on error */
1364 status
= NT_STATUS_UNSUCCESSFUL
;
1366 status
= map_nt_error_from_unix(errno
);
1367 if (NT_STATUS_EQUAL(status
,
1368 NT_STATUS_NOT_SUPPORTED
)) {
1372 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1373 "connectpath %s, failed - %s.\n",
1374 fsp
->conn
->connectpath
,
1375 nt_errstr(status
)));
1376 TALLOC_FREE(shadow_data
);
1380 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1381 sizeof(SHADOW_COPY_LABEL
)) + 2;
1386 *out_len
= 12 + labels_data_count
;
1389 if (max_out_len
< *out_len
) {
1390 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1391 max_out_len
, *out_len
));
1392 TALLOC_FREE(shadow_data
);
1393 return NT_STATUS_BUFFER_TOO_SMALL
;
1396 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1397 if (cur_pdata
== NULL
) {
1398 TALLOC_FREE(shadow_data
);
1399 return NT_STATUS_NO_MEMORY
;
1402 *out_data
= cur_pdata
;
1404 /* num_volumes 4 bytes */
1405 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1408 /* num_labels 4 bytes */
1409 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1412 /* needed_data_count 4 bytes */
1413 SIVAL(cur_pdata
, 8, labels_data_count
);
1417 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1418 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1419 if (labels
&& shadow_data
->labels
) {
1420 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1422 status
= srvstr_push(cur_pdata
, req_flags
,
1423 cur_pdata
, shadow_data
->labels
[i
],
1424 2 * sizeof(SHADOW_COPY_LABEL
),
1425 STR_UNICODE
|STR_TERMINATE
, &len
);
1426 if (!NT_STATUS_IS_OK(status
)) {
1427 TALLOC_FREE(*out_data
);
1428 TALLOC_FREE(shadow_data
);
1431 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1432 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1436 TALLOC_FREE(shadow_data
);
1438 return NT_STATUS_OK
;
1441 case FSCTL_FIND_FILES_BY_SID
:
1443 /* pretend this succeeded -
1445 * we have to send back a list with all files owned by this SID
1447 * but I have to check that --metze
1453 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1454 fsp_fnum_dbg(fsp
)));
1457 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1458 return NT_STATUS_INVALID_PARAMETER
;
1461 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1463 /* unknown 4 bytes: this is not the length of the sid :-( */
1464 /*unknown = IVAL(pdata,0);*/
1466 if (!sid_parse(_in_data
+ 4, sid_len
, &sid
)) {
1467 return NT_STATUS_INVALID_PARAMETER
;
1469 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
1471 if (!sid_to_uid(&sid
, &uid
)) {
1472 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1473 sid_string_dbg(&sid
),
1474 (unsigned long)sid_len
));
1478 /* we can take a look at the find source :-)
1480 * find ./ -uid $uid -name '*' is what we need here
1483 * and send 4bytes len and then NULL terminated unicode strings
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 * but I don't know how to deal with the paged results
1490 * (maybe we can hang the result anywhere in the fsp struct)
1492 * we don't send all files at once
1493 * and at the next we should *not* start from the beginning,
1494 * so we have to cache the result
1499 /* this works for now... */
1500 return NT_STATUS_OK
;
1503 case FSCTL_QUERY_ALLOCATED_RANGES
:
1505 /* FIXME: This is just a dummy reply, telling that all of the
1506 * file is allocated. MKS cp needs that.
1507 * Adding the real allocated ranges via FIEMAP on Linux
1508 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1509 * this FSCTL correct for sparse files.
1511 uint64_t offset
, length
;
1512 char *out_data_tmp
= NULL
;
1515 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1517 return NT_STATUS_INVALID_PARAMETER
;
1520 if (max_out_len
< 16) {
1521 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1523 return NT_STATUS_INVALID_PARAMETER
;
1526 offset
= BVAL(in_data
,0);
1527 length
= BVAL(in_data
,8);
1529 if (offset
+ length
< offset
) {
1530 /* No 64-bit integer wrap. */
1531 return NT_STATUS_INVALID_PARAMETER
;
1534 /* Shouldn't this be SMB_VFS_STAT ... ? */
1535 status
= vfs_stat_fsp(fsp
);
1536 if (!NT_STATUS_IS_OK(status
)) {
1541 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1542 if (out_data_tmp
== NULL
) {
1543 DEBUG(10, ("unable to allocate memory for response\n"));
1544 return NT_STATUS_NO_MEMORY
;
1547 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1548 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1550 memset(out_data_tmp
, 0, *out_len
);
1552 uint64_t end
= offset
+ length
;
1553 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1554 SBVAL(out_data_tmp
, 0, 0);
1555 SBVAL(out_data_tmp
, 8, end
);
1558 *out_data
= out_data_tmp
;
1560 return NT_STATUS_OK
;
1563 case FSCTL_IS_VOLUME_DIRTY
:
1565 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1566 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1568 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1569 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1571 return NT_STATUS_INVALID_PARAMETER
;
1576 * Only print once ... unfortunately there could be lots of
1577 * different FSCTLs that are called.
1579 if (!vfswrap_logged_ioctl_message
) {
1580 vfswrap_logged_ioctl_message
= true;
1581 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1582 __func__
, function
));
1586 return NT_STATUS_NOT_SUPPORTED
;
1589 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
1590 const struct smb_filename
*fname
,
1591 SMB_STRUCT_STAT
*sbuf
);
1593 static NTSTATUS
vfswrap_get_dos_attributes(struct vfs_handle_struct
*handle
,
1594 struct smb_filename
*smb_fname
,
1599 offline
= vfswrap_is_offline(handle
, smb_fname
, &smb_fname
->st
);
1601 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1604 return get_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1607 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1608 struct files_struct
*fsp
,
1613 offline
= vfswrap_is_offline(handle
, fsp
->fsp_name
, &fsp
->fsp_name
->st
);
1615 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1618 return get_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1621 static NTSTATUS
vfswrap_set_dos_attributes(struct vfs_handle_struct
*handle
,
1622 const struct smb_filename
*smb_fname
,
1625 return set_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1628 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1629 struct files_struct
*fsp
,
1632 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1635 static struct vfs_offload_ctx
*vfswrap_offload_ctx
;
1637 struct vfswrap_offload_read_state
{
1641 static struct tevent_req
*vfswrap_offload_read_send(
1642 TALLOC_CTX
*mem_ctx
,
1643 struct tevent_context
*ev
,
1644 struct vfs_handle_struct
*handle
,
1645 struct files_struct
*fsp
,
1651 struct tevent_req
*req
= NULL
;
1652 struct vfswrap_offload_read_state
*state
= NULL
;
1655 req
= tevent_req_create(mem_ctx
, &state
,
1656 struct vfswrap_offload_read_state
);
1661 status
= vfs_offload_token_ctx_init(fsp
->conn
->sconn
->client
,
1662 &vfswrap_offload_ctx
);
1663 if (tevent_req_nterror(req
, status
)) {
1664 return tevent_req_post(req
, ev
);
1667 if (fsctl
!= FSCTL_SRV_REQUEST_RESUME_KEY
) {
1668 tevent_req_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
1669 return tevent_req_post(req
, ev
);
1672 status
= vfs_offload_token_create_blob(state
, fsp
, fsctl
,
1674 if (tevent_req_nterror(req
, status
)) {
1675 return tevent_req_post(req
, ev
);
1678 status
= vfs_offload_token_db_store_fsp(vfswrap_offload_ctx
, fsp
,
1680 if (tevent_req_nterror(req
, status
)) {
1681 return tevent_req_post(req
, ev
);
1684 tevent_req_done(req
);
1685 return tevent_req_post(req
, ev
);
1688 static NTSTATUS
vfswrap_offload_read_recv(struct tevent_req
*req
,
1689 struct vfs_handle_struct
*handle
,
1690 TALLOC_CTX
*mem_ctx
,
1693 struct vfswrap_offload_read_state
*state
= tevent_req_data(
1694 req
, struct vfswrap_offload_read_state
);
1697 if (tevent_req_is_nterror(req
, &status
)) {
1698 tevent_req_received(req
);
1702 token
->length
= state
->token
.length
;
1703 token
->data
= talloc_move(mem_ctx
, &state
->token
.data
);
1705 tevent_req_received(req
);
1706 return NT_STATUS_OK
;
1709 struct vfswrap_offload_write_state
{
1710 struct tevent_context
*ev
;
1712 bool read_lck_locked
;
1713 bool write_lck_locked
;
1715 struct files_struct
*src_fsp
;
1717 struct files_struct
*dst_fsp
;
1721 size_t next_io_size
;
1724 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
);
1726 static struct tevent_req
*vfswrap_offload_write_send(
1727 struct vfs_handle_struct
*handle
,
1728 TALLOC_CTX
*mem_ctx
,
1729 struct tevent_context
*ev
,
1732 off_t transfer_offset
,
1733 struct files_struct
*dest_fsp
,
1737 struct tevent_req
*req
;
1738 struct vfswrap_offload_write_state
*state
= NULL
;
1739 size_t num
= MIN(to_copy
, COPYCHUNK_MAX_TOTAL_LEN
);
1740 files_struct
*src_fsp
= NULL
;
1743 req
= tevent_req_create(mem_ctx
, &state
,
1744 struct vfswrap_offload_write_state
);
1749 *state
= (struct vfswrap_offload_write_state
) {
1752 .src_off
= transfer_offset
,
1753 .dst_fsp
= dest_fsp
,
1754 .dst_off
= dest_off
,
1756 .remaining
= to_copy
,
1760 case FSCTL_SRV_COPYCHUNK
:
1761 case FSCTL_SRV_COPYCHUNK_WRITE
:
1764 case FSCTL_OFFLOAD_WRITE
:
1765 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
1766 return tevent_req_post(req
, ev
);
1768 case FSCTL_DUP_EXTENTS_TO_FILE
:
1769 DBG_DEBUG("COW clones not supported by vfs_default\n");
1770 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1771 return tevent_req_post(req
, ev
);
1774 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1775 return tevent_req_post(req
, ev
);
1779 * From here on we assume a copy-chunk fsctl
1783 tevent_req_done(req
);
1784 return tevent_req_post(req
, ev
);
1787 status
= vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx
,
1789 if (tevent_req_nterror(req
, status
)) {
1790 return tevent_req_post(req
, ev
);
1792 state
->src_fsp
= src_fsp
;
1794 DBG_DEBUG("server side copy chunk of length %" PRIu64
"\n", to_copy
);
1796 status
= vfs_offload_token_check_handles(fsctl
, src_fsp
, dest_fsp
);
1797 if (!NT_STATUS_IS_OK(status
)) {
1798 tevent_req_nterror(req
, status
);
1799 return tevent_req_post(req
, ev
);
1802 state
->buf
= talloc_array(state
, uint8_t, num
);
1803 if (tevent_req_nomem(state
->buf
, req
)) {
1804 return tevent_req_post(req
, ev
);
1807 status
= vfs_stat_fsp(src_fsp
);
1808 if (tevent_req_nterror(req
, status
)) {
1809 return tevent_req_post(req
, ev
);
1812 if (src_fsp
->fsp_name
->st
.st_ex_size
< state
->src_off
+ num
) {
1814 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1815 * If the SourceOffset or SourceOffset + Length extends beyond
1816 * the end of file, the server SHOULD<240> treat this as a
1817 * STATUS_END_OF_FILE error.
1819 * <240> Section 3.3.5.15.6: Windows servers will return
1820 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1822 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
1823 return tevent_req_post(req
, ev
);
1826 if (src_fsp
->op
== NULL
) {
1827 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1828 return tevent_req_post(req
, ev
);
1831 if (dest_fsp
->op
== NULL
) {
1832 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1833 return tevent_req_post(req
, ev
);
1836 status
= vfswrap_offload_write_loop(req
);
1837 if (!NT_STATUS_IS_OK(status
)) {
1838 tevent_req_nterror(req
, status
);
1839 return tevent_req_post(req
, ev
);
1845 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
);
1847 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
)
1849 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1850 req
, struct vfswrap_offload_write_state
);
1851 struct tevent_req
*subreq
= NULL
;
1852 struct lock_struct read_lck
;
1855 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
1857 init_strict_lock_struct(state
->src_fsp
,
1858 state
->src_fsp
->op
->global
->open_persistent_id
,
1860 state
->next_io_size
,
1864 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
1868 return NT_STATUS_FILE_LOCK_CONFLICT
;
1871 subreq
= SMB_VFS_PREAD_SEND(state
,
1872 state
->src_fsp
->conn
->sconn
->ev_ctx
,
1875 state
->next_io_size
,
1877 if (subreq
== NULL
) {
1878 return NT_STATUS_NO_MEMORY
;
1880 tevent_req_set_callback(subreq
, vfswrap_offload_write_read_done
, req
);
1882 return NT_STATUS_OK
;
1885 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
);
1887 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
)
1889 struct tevent_req
*req
= tevent_req_callback_data(
1890 subreq
, struct tevent_req
);
1891 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1892 req
, struct vfswrap_offload_write_state
);
1893 struct vfs_aio_state aio_state
;
1894 struct lock_struct write_lck
;
1898 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
1899 TALLOC_FREE(subreq
);
1901 DBG_ERR("read failed: %s\n", strerror(errno
));
1902 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1905 if (nread
!= state
->next_io_size
) {
1906 DBG_ERR("Short read, only %zd of %zu\n",
1907 nread
, state
->next_io_size
);
1908 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1912 state
->src_off
+= nread
;
1914 init_strict_lock_struct(state
->dst_fsp
,
1915 state
->dst_fsp
->op
->global
->open_persistent_id
,
1917 state
->next_io_size
,
1921 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
1925 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1929 subreq
= SMB_VFS_PWRITE_SEND(state
,
1933 state
->next_io_size
,
1935 if (subreq
== NULL
) {
1936 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1939 tevent_req_set_callback(subreq
, vfswrap_offload_write_write_done
, req
);
1942 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
)
1944 struct tevent_req
*req
= tevent_req_callback_data(
1945 subreq
, struct tevent_req
);
1946 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1947 req
, struct vfswrap_offload_write_state
);
1948 struct vfs_aio_state aio_state
;
1952 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
1953 TALLOC_FREE(subreq
);
1954 if (nwritten
== -1) {
1955 DBG_ERR("write failed: %s\n", strerror(errno
));
1956 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1959 if (nwritten
!= state
->next_io_size
) {
1960 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
1961 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1965 state
->dst_off
+= nwritten
;
1967 if (state
->remaining
< nwritten
) {
1968 /* Paranoia check */
1969 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1972 state
->remaining
-= nwritten
;
1973 if (state
->remaining
== 0) {
1974 tevent_req_done(req
);
1978 status
= vfswrap_offload_write_loop(req
);
1979 if (!NT_STATUS_IS_OK(status
)) {
1980 tevent_req_nterror(req
, status
);
1987 static NTSTATUS
vfswrap_offload_write_recv(struct vfs_handle_struct
*handle
,
1988 struct tevent_req
*req
,
1991 struct vfswrap_offload_write_state
*state
= tevent_req_data(
1992 req
, struct vfswrap_offload_write_state
);
1995 if (tevent_req_is_nterror(req
, &status
)) {
1996 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
1998 tevent_req_received(req
);
2002 *copied
= state
->to_copy
;
2003 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
2004 tevent_req_received(req
);
2006 return NT_STATUS_OK
;
2009 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
2010 TALLOC_CTX
*mem_ctx
,
2011 struct files_struct
*fsp
,
2012 struct smb_filename
*smb_fname
,
2013 uint16_t *_compression_fmt
)
2015 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2018 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
2019 TALLOC_CTX
*mem_ctx
,
2020 struct files_struct
*fsp
,
2021 uint16_t compression_fmt
)
2023 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2026 /********************************************************************
2027 Given a stat buffer return the allocated size on disk, taking into
2028 account sparse files.
2029 ********************************************************************/
2030 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
2031 struct files_struct
*fsp
,
2032 const SMB_STRUCT_STAT
*sbuf
)
2036 START_PROFILE(syscall_get_alloc_size
);
2038 if(S_ISDIR(sbuf
->st_ex_mode
)) {
2043 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2044 /* The type of st_blocksize is blkcnt_t which *MUST* be
2045 signed (according to POSIX) and can be less than 64-bits.
2046 Ensure when we're converting to 64 bits wide we don't
2048 #if defined(SIZEOF_BLKCNT_T_8)
2049 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
2050 #elif defined(SIZEOF_BLKCNT_T_4)
2052 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
2053 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
2056 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2060 * Some file systems do not allocate a block for very
2061 * small files. But for non-empty file should report a
2065 uint64_t filesize
= get_file_size_stat(sbuf
);
2067 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
2071 result
= get_file_size_stat(sbuf
);
2074 if (fsp
&& fsp
->initial_allocation_size
)
2075 result
= MAX(result
,fsp
->initial_allocation_size
);
2077 result
= smb_roundup(handle
->conn
, result
);
2080 END_PROFILE(syscall_get_alloc_size
);
2084 static int vfswrap_unlink(vfs_handle_struct
*handle
,
2085 const struct smb_filename
*smb_fname
)
2089 START_PROFILE(syscall_unlink
);
2091 if (smb_fname
->stream_name
) {
2095 result
= unlink(smb_fname
->base_name
);
2098 END_PROFILE(syscall_unlink
);
2102 static int vfswrap_chmod(vfs_handle_struct
*handle
,
2103 const struct smb_filename
*smb_fname
,
2108 START_PROFILE(syscall_chmod
);
2111 * We need to do this due to the fact that the default POSIX ACL
2112 * chmod modifies the ACL *mask* for the group owner, not the
2113 * group owner bits directly. JRA.
2118 int saved_errno
= errno
; /* We might get ENOSYS */
2119 result
= SMB_VFS_CHMOD_ACL(handle
->conn
,
2123 END_PROFILE(syscall_chmod
);
2126 /* Error - return the old errno. */
2127 errno
= saved_errno
;
2130 result
= chmod(smb_fname
->base_name
, mode
);
2131 END_PROFILE(syscall_chmod
);
2135 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2139 START_PROFILE(syscall_fchmod
);
2142 * We need to do this due to the fact that the default POSIX ACL
2143 * chmod modifies the ACL *mask* for the group owner, not the
2144 * group owner bits directly. JRA.
2148 int saved_errno
= errno
; /* We might get ENOSYS */
2149 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
2150 END_PROFILE(syscall_fchmod
);
2153 /* Error - return the old errno. */
2154 errno
= saved_errno
;
2157 #if defined(HAVE_FCHMOD)
2158 result
= fchmod(fsp
->fh
->fd
, mode
);
2164 END_PROFILE(syscall_fchmod
);
2168 static int vfswrap_chown(vfs_handle_struct
*handle
,
2169 const struct smb_filename
*smb_fname
,
2175 START_PROFILE(syscall_chown
);
2176 result
= chown(smb_fname
->base_name
, uid
, gid
);
2177 END_PROFILE(syscall_chown
);
2181 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2186 START_PROFILE(syscall_fchown
);
2187 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
2188 END_PROFILE(syscall_fchown
);
2196 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2197 const struct smb_filename
*smb_fname
,
2203 START_PROFILE(syscall_lchown
);
2204 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2205 END_PROFILE(syscall_lchown
);
2209 static int vfswrap_chdir(vfs_handle_struct
*handle
,
2210 const struct smb_filename
*smb_fname
)
2214 START_PROFILE(syscall_chdir
);
2215 result
= chdir(smb_fname
->base_name
);
2216 END_PROFILE(syscall_chdir
);
2220 static struct smb_filename
*vfswrap_getwd(vfs_handle_struct
*handle
,
2224 struct smb_filename
*smb_fname
= NULL
;
2226 START_PROFILE(syscall_getwd
);
2227 result
= sys_getwd();
2228 END_PROFILE(syscall_getwd
);
2230 if (result
== NULL
) {
2233 smb_fname
= synthetic_smb_fname(ctx
,
2239 * sys_getwd() *always* returns malloced memory.
2240 * We must free here to avoid leaks:
2241 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2247 /*********************************************************************
2248 nsec timestamp resolution call. Convert down to whatever the underlying
2249 system will support.
2250 **********************************************************************/
2252 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
2253 const struct smb_filename
*smb_fname
,
2254 struct smb_file_time
*ft
)
2258 START_PROFILE(syscall_ntimes
);
2260 if (smb_fname
->stream_name
) {
2266 if (null_timespec(ft
->atime
)) {
2267 ft
->atime
= smb_fname
->st
.st_ex_atime
;
2270 if (null_timespec(ft
->mtime
)) {
2271 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
2274 if (!null_timespec(ft
->create_time
)) {
2275 set_create_timespec_ea(handle
->conn
,
2280 if ((timespec_compare(&ft
->atime
,
2281 &smb_fname
->st
.st_ex_atime
) == 0) &&
2282 (timespec_compare(&ft
->mtime
,
2283 &smb_fname
->st
.st_ex_mtime
) == 0)) {
2288 #if defined(HAVE_UTIMENSAT)
2290 struct timespec ts
[2];
2293 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
2295 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
2297 if (!((result
== -1) && (errno
== ENOSYS
))) {
2301 #if defined(HAVE_UTIMES)
2303 struct timeval tv
[2];
2304 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
2305 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
2306 result
= utimes(smb_fname
->base_name
, tv
);
2308 result
= utimes(smb_fname
->base_name
, NULL
);
2310 if (!((result
== -1) && (errno
== ENOSYS
))) {
2314 #if defined(HAVE_UTIME)
2316 struct utimbuf times
;
2317 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
2318 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
2319 result
= utime(smb_fname
->base_name
, ×
);
2321 result
= utime(smb_fname
->base_name
, NULL
);
2323 if (!((result
== -1) && (errno
== ENOSYS
))) {
2331 END_PROFILE(syscall_ntimes
);
2335 /*********************************************************************
2336 A version of ftruncate that will write the space on disk if strict
2338 **********************************************************************/
2340 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2342 off_t space_to_write
;
2343 uint64_t space_avail
;
2344 uint64_t bsize
,dfree
,dsize
;
2347 SMB_STRUCT_STAT
*pst
;
2349 status
= vfs_stat_fsp(fsp
);
2350 if (!NT_STATUS_IS_OK(status
)) {
2353 pst
= &fsp
->fsp_name
->st
;
2356 if (S_ISFIFO(pst
->st_ex_mode
))
2360 if (pst
->st_ex_size
== len
)
2363 /* Shrink - just ftruncate. */
2364 if (pst
->st_ex_size
> len
)
2365 return ftruncate(fsp
->fh
->fd
, len
);
2367 space_to_write
= len
- pst
->st_ex_size
;
2369 /* for allocation try fallocate first. This can fail on some
2370 platforms e.g. when the filesystem doesn't support it and no
2371 emulation is being done by the libc (like on AIX with JFS1). In that
2372 case we do our own emulation. fallocate implementations can
2373 return ENOTSUP or EINVAL in cases like that. */
2374 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2375 if (ret
== -1 && errno
== ENOSPC
) {
2381 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2382 "error %d. Falling back to slow manual allocation\n", errno
));
2384 /* available disk space is enough or not? */
2386 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2387 /* space_avail is 1k blocks */
2388 if (space_avail
== (uint64_t)-1 ||
2389 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2394 /* Write out the real space on disk. */
2395 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2403 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2406 SMB_STRUCT_STAT
*pst
;
2410 START_PROFILE(syscall_ftruncate
);
2412 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
2413 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2414 END_PROFILE(syscall_ftruncate
);
2418 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2419 ftruncate if the system supports it. Then I discovered that
2420 you can have some filesystems that support ftruncate
2421 expansion and some that don't! On Linux fat can't do
2422 ftruncate extend but ext2 can. */
2424 result
= ftruncate(fsp
->fh
->fd
, len
);
2426 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2427 extend a file with ftruncate. Provide alternate implementation
2430 /* Do an fstat to see if the file is longer than the requested
2431 size in which case the ftruncate above should have
2432 succeeded or shorter, in which case seek to len - 1 and
2433 write 1 byte of zero */
2434 status
= vfs_stat_fsp(fsp
);
2435 if (!NT_STATUS_IS_OK(status
)) {
2439 /* We need to update the files_struct after successful ftruncate */
2444 pst
= &fsp
->fsp_name
->st
;
2447 if (S_ISFIFO(pst
->st_ex_mode
)) {
2453 if (pst
->st_ex_size
== len
) {
2458 if (pst
->st_ex_size
> len
) {
2459 /* the ftruncate should have worked */
2463 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
2471 END_PROFILE(syscall_ftruncate
);
2475 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
2483 START_PROFILE(syscall_fallocate
);
2485 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
2487 * posix_fallocate returns 0 on success, errno on error
2488 * and doesn't set errno. Make it behave like fallocate()
2489 * which returns -1, and sets errno on failure.
2496 /* sys_fallocate handles filtering of unsupported mode flags */
2497 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
2499 END_PROFILE(syscall_fallocate
);
2503 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
2507 START_PROFILE(syscall_fcntl_lock
);
2509 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2511 "force process locks",
2513 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2516 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
2517 END_PROFILE(syscall_fcntl_lock
);
2521 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2522 uint32_t share_mode
, uint32_t access_mask
)
2524 START_PROFILE(syscall_kernel_flock
);
2525 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
2526 END_PROFILE(syscall_kernel_flock
);
2530 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2535 START_PROFILE(syscall_fcntl_getlock
);
2537 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2539 "force process locks",
2541 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2544 result
= fcntl_getlock(fsp
->fh
->fd
, op
, poffset
, pcount
, ptype
, ppid
);
2545 END_PROFILE(syscall_fcntl_getlock
);
2549 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2554 START_PROFILE(syscall_linux_setlease
);
2556 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2557 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2561 END_PROFILE(syscall_linux_setlease
);
2565 static int vfswrap_symlink(vfs_handle_struct
*handle
,
2566 const char *link_target
,
2567 const struct smb_filename
*new_smb_fname
)
2571 START_PROFILE(syscall_symlink
);
2572 result
= symlink(link_target
, new_smb_fname
->base_name
);
2573 END_PROFILE(syscall_symlink
);
2577 static int vfswrap_readlink(vfs_handle_struct
*handle
,
2578 const struct smb_filename
*smb_fname
,
2584 START_PROFILE(syscall_readlink
);
2585 result
= readlink(smb_fname
->base_name
, buf
, bufsiz
);
2586 END_PROFILE(syscall_readlink
);
2590 static int vfswrap_link(vfs_handle_struct
*handle
,
2591 const struct smb_filename
*old_smb_fname
,
2592 const struct smb_filename
*new_smb_fname
)
2596 START_PROFILE(syscall_link
);
2597 result
= link(old_smb_fname
->base_name
, new_smb_fname
->base_name
);
2598 END_PROFILE(syscall_link
);
2602 static int vfswrap_mknod(vfs_handle_struct
*handle
,
2603 const struct smb_filename
*smb_fname
,
2609 START_PROFILE(syscall_mknod
);
2610 result
= sys_mknod(smb_fname
->base_name
, mode
, dev
);
2611 END_PROFILE(syscall_mknod
);
2615 static struct smb_filename
*vfswrap_realpath(vfs_handle_struct
*handle
,
2617 const struct smb_filename
*smb_fname
)
2620 struct smb_filename
*result_fname
= NULL
;
2622 START_PROFILE(syscall_realpath
);
2623 result
= sys_realpath(smb_fname
->base_name
);
2624 END_PROFILE(syscall_realpath
);
2626 result_fname
= synthetic_smb_fname(ctx
, result
, NULL
, NULL
, 0);
2629 return result_fname
;
2632 static int vfswrap_chflags(vfs_handle_struct
*handle
,
2633 const struct smb_filename
*smb_fname
,
2637 return chflags(smb_fname
->base_name
, flags
);
2644 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2645 const SMB_STRUCT_STAT
*sbuf
)
2649 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2653 key
.devid
= sbuf
->st_ex_dev
;
2654 key
.inode
= sbuf
->st_ex_ino
;
2655 /* key.extid is unused by default. */
2660 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
2661 struct files_struct
*fsp
,
2662 const struct smb_filename
*smb_fname
,
2663 TALLOC_CTX
*mem_ctx
,
2664 unsigned int *pnum_streams
,
2665 struct stream_struct
**pstreams
)
2667 SMB_STRUCT_STAT sbuf
;
2668 struct stream_struct
*tmp_streams
= NULL
;
2671 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
2673 * No default streams on directories
2678 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
2679 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
2682 struct smb_filename smb_fname_cp
;
2684 ZERO_STRUCT(smb_fname_cp
);
2685 smb_fname_cp
.base_name
= discard_const_p(char,
2686 smb_fname
->base_name
);
2687 smb_fname_cp
.flags
= smb_fname
->flags
;
2689 if (smb_fname_cp
.flags
& SMB_FILENAME_POSIX_PATH
) {
2690 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname_cp
);
2692 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname_cp
);
2694 sbuf
= smb_fname_cp
.st
;
2698 return map_nt_error_from_unix(errno
);
2701 if (S_ISDIR(sbuf
.st_ex_mode
)) {
2705 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
2706 (*pnum_streams
) + 1);
2707 if (tmp_streams
== NULL
) {
2708 return NT_STATUS_NO_MEMORY
;
2710 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
2711 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
2712 return NT_STATUS_NO_MEMORY
;
2714 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
2715 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
2718 *pstreams
= tmp_streams
;
2720 return NT_STATUS_OK
;
2723 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
2726 TALLOC_CTX
*mem_ctx
,
2730 * Don't fall back to get_real_filename so callers can differentiate
2731 * between a full directory scan and an actual case-insensitive stat.
2737 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
2738 const struct smb_filename
*smb_fname
)
2740 return handle
->conn
->connectpath
;
2743 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
2744 struct byte_range_lock
*br_lck
,
2745 struct lock_struct
*plock
,
2748 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2750 /* Note: blr is not used in the default implementation. */
2751 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
2754 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
2755 struct messaging_context
*msg_ctx
,
2756 struct byte_range_lock
*br_lck
,
2757 const struct lock_struct
*plock
)
2759 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2761 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
2764 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
2765 struct byte_range_lock
*br_lck
,
2766 struct lock_struct
*plock
)
2768 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2770 /* Note: blr is not used in the default implementation. */
2771 return brl_lock_cancel_default(br_lck
, plock
);
2774 static bool vfswrap_strict_lock_check(struct vfs_handle_struct
*handle
,
2776 struct lock_struct
*plock
)
2778 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2779 plock
->lock_type
== WRITE_LOCK
);
2781 return strict_lock_check_default(fsp
, plock
);
2784 /* NT ACL operations. */
2786 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
2788 uint32_t security_info
,
2789 TALLOC_CTX
*mem_ctx
,
2790 struct security_descriptor
**ppdesc
)
2794 START_PROFILE(fget_nt_acl
);
2795 result
= posix_fget_nt_acl(fsp
, security_info
,
2797 END_PROFILE(fget_nt_acl
);
2801 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
2802 const struct smb_filename
*smb_fname
,
2803 uint32_t security_info
,
2804 TALLOC_CTX
*mem_ctx
,
2805 struct security_descriptor
**ppdesc
)
2809 START_PROFILE(get_nt_acl
);
2810 result
= posix_get_nt_acl(handle
->conn
,
2815 END_PROFILE(get_nt_acl
);
2819 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
2823 START_PROFILE(fset_nt_acl
);
2824 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
2825 END_PROFILE(fset_nt_acl
);
2829 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
2830 struct smb_filename
*file
,
2831 struct security_acl
*sacl
,
2832 uint32_t access_requested
,
2833 uint32_t access_denied
)
2835 return NT_STATUS_OK
; /* Nothing to do here ... */
2838 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
,
2839 const struct smb_filename
*smb_fname
,
2848 START_PROFILE(chmod_acl
);
2849 result
= chmod_acl(handle
->conn
, smb_fname
, mode
);
2850 END_PROFILE(chmod_acl
);
2855 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2863 START_PROFILE(fchmod_acl
);
2864 result
= fchmod_acl(fsp
, mode
);
2865 END_PROFILE(fchmod_acl
);
2870 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
2871 const struct smb_filename
*smb_fname
,
2872 SMB_ACL_TYPE_T type
,
2873 TALLOC_CTX
*mem_ctx
)
2875 return sys_acl_get_file(handle
, smb_fname
, type
, mem_ctx
);
2878 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
2880 TALLOC_CTX
*mem_ctx
)
2882 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
2885 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
,
2886 const struct smb_filename
*smb_fname
,
2887 SMB_ACL_TYPE_T acltype
,
2890 return sys_acl_set_file(handle
, smb_fname
, acltype
, theacl
);
2893 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2895 return sys_acl_set_fd(handle
, fsp
, theacl
);
2898 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
2899 const struct smb_filename
*smb_fname
)
2901 return sys_acl_delete_def_file(handle
, smb_fname
);
2904 /****************************************************************
2905 Extended attribute operations.
2906 *****************************************************************/
2908 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,
2909 const struct smb_filename
*smb_fname
,
2914 return getxattr(smb_fname
->base_name
, name
, value
, size
);
2917 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2919 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2922 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
,
2923 const struct smb_filename
*smb_fname
,
2927 return listxattr(smb_fname
->base_name
, list
, size
);
2930 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2932 return flistxattr(fsp
->fh
->fd
, list
, size
);
2935 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
,
2936 const struct smb_filename
*smb_fname
,
2939 return removexattr(smb_fname
->base_name
, name
);
2942 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2944 return fremovexattr(fsp
->fh
->fd
, name
);
2947 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
,
2948 const struct smb_filename
*smb_fname
,
2954 return setxattr(smb_fname
->base_name
, name
, value
, size
, flags
);
2957 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2959 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2962 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2967 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2968 const struct smb_filename
*fname
,
2969 SMB_STRUCT_STAT
*sbuf
)
2973 bool offline
= false;
2975 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2979 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2980 #if defined(ENOTSUP)
2986 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2987 if (!NT_STATUS_IS_OK(status
)) {
2988 errno
= map_errno_from_nt_status(status
);
2992 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2999 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
3000 struct files_struct
*fsp
,
3001 TALLOC_CTX
*mem_ctx
,
3004 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
3007 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
3008 struct files_struct
*fsp
,
3009 const DATA_BLOB old_cookie
,
3010 TALLOC_CTX
*mem_ctx
,
3011 DATA_BLOB
*new_cookie
)
3013 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
3017 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
3018 struct smb_request
*smb1req
,
3019 struct smbXsrv_open
*op
,
3020 const DATA_BLOB old_cookie
,
3021 TALLOC_CTX
*mem_ctx
,
3022 struct files_struct
**fsp
,
3023 DATA_BLOB
*new_cookie
)
3025 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
3026 old_cookie
, mem_ctx
,
3030 static struct vfs_fn_pointers vfs_default_fns
= {
3031 /* Disk operations */
3033 .connect_fn
= vfswrap_connect
,
3034 .disconnect_fn
= vfswrap_disconnect
,
3035 .disk_free_fn
= vfswrap_disk_free
,
3036 .get_quota_fn
= vfswrap_get_quota
,
3037 .set_quota_fn
= vfswrap_set_quota
,
3038 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
3039 .statvfs_fn
= vfswrap_statvfs
,
3040 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
3041 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
3042 .snap_check_path_fn
= vfswrap_snap_check_path
,
3043 .snap_create_fn
= vfswrap_snap_create
,
3044 .snap_delete_fn
= vfswrap_snap_delete
,
3046 /* Directory operations */
3048 .opendir_fn
= vfswrap_opendir
,
3049 .fdopendir_fn
= vfswrap_fdopendir
,
3050 .readdir_fn
= vfswrap_readdir
,
3051 .readdir_attr_fn
= vfswrap_readdir_attr
,
3052 .seekdir_fn
= vfswrap_seekdir
,
3053 .telldir_fn
= vfswrap_telldir
,
3054 .rewind_dir_fn
= vfswrap_rewinddir
,
3055 .mkdir_fn
= vfswrap_mkdir
,
3056 .rmdir_fn
= vfswrap_rmdir
,
3057 .closedir_fn
= vfswrap_closedir
,
3058 .init_search_op_fn
= vfswrap_init_search_op
,
3060 /* File operations */
3062 .open_fn
= vfswrap_open
,
3063 .create_file_fn
= vfswrap_create_file
,
3064 .close_fn
= vfswrap_close
,
3065 .read_fn
= vfswrap_read
,
3066 .pread_fn
= vfswrap_pread
,
3067 .pread_send_fn
= vfswrap_pread_send
,
3068 .pread_recv_fn
= vfswrap_pread_recv
,
3069 .write_fn
= vfswrap_write
,
3070 .pwrite_fn
= vfswrap_pwrite
,
3071 .pwrite_send_fn
= vfswrap_pwrite_send
,
3072 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
3073 .lseek_fn
= vfswrap_lseek
,
3074 .sendfile_fn
= vfswrap_sendfile
,
3075 .recvfile_fn
= vfswrap_recvfile
,
3076 .rename_fn
= vfswrap_rename
,
3077 .fsync_fn
= vfswrap_fsync
,
3078 .fsync_send_fn
= vfswrap_fsync_send
,
3079 .fsync_recv_fn
= vfswrap_fsync_recv
,
3080 .stat_fn
= vfswrap_stat
,
3081 .fstat_fn
= vfswrap_fstat
,
3082 .lstat_fn
= vfswrap_lstat
,
3083 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
3084 .unlink_fn
= vfswrap_unlink
,
3085 .chmod_fn
= vfswrap_chmod
,
3086 .fchmod_fn
= vfswrap_fchmod
,
3087 .chown_fn
= vfswrap_chown
,
3088 .fchown_fn
= vfswrap_fchown
,
3089 .lchown_fn
= vfswrap_lchown
,
3090 .chdir_fn
= vfswrap_chdir
,
3091 .getwd_fn
= vfswrap_getwd
,
3092 .ntimes_fn
= vfswrap_ntimes
,
3093 .ftruncate_fn
= vfswrap_ftruncate
,
3094 .fallocate_fn
= vfswrap_fallocate
,
3095 .lock_fn
= vfswrap_lock
,
3096 .kernel_flock_fn
= vfswrap_kernel_flock
,
3097 .linux_setlease_fn
= vfswrap_linux_setlease
,
3098 .getlock_fn
= vfswrap_getlock
,
3099 .symlink_fn
= vfswrap_symlink
,
3100 .readlink_fn
= vfswrap_readlink
,
3101 .link_fn
= vfswrap_link
,
3102 .mknod_fn
= vfswrap_mknod
,
3103 .realpath_fn
= vfswrap_realpath
,
3104 .chflags_fn
= vfswrap_chflags
,
3105 .file_id_create_fn
= vfswrap_file_id_create
,
3106 .streaminfo_fn
= vfswrap_streaminfo
,
3107 .get_real_filename_fn
= vfswrap_get_real_filename
,
3108 .connectpath_fn
= vfswrap_connectpath
,
3109 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
3110 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
3111 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
3112 .strict_lock_check_fn
= vfswrap_strict_lock_check
,
3113 .translate_name_fn
= vfswrap_translate_name
,
3114 .fsctl_fn
= vfswrap_fsctl
,
3115 .set_dos_attributes_fn
= vfswrap_set_dos_attributes
,
3116 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
3117 .get_dos_attributes_fn
= vfswrap_get_dos_attributes
,
3118 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
3119 .offload_read_send_fn
= vfswrap_offload_read_send
,
3120 .offload_read_recv_fn
= vfswrap_offload_read_recv
,
3121 .offload_write_send_fn
= vfswrap_offload_write_send
,
3122 .offload_write_recv_fn
= vfswrap_offload_write_recv
,
3123 .get_compression_fn
= vfswrap_get_compression
,
3124 .set_compression_fn
= vfswrap_set_compression
,
3126 /* NT ACL operations. */
3128 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
3129 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
3130 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
3131 .audit_file_fn
= vfswrap_audit_file
,
3133 /* POSIX ACL operations. */
3135 .chmod_acl_fn
= vfswrap_chmod_acl
,
3136 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
3138 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
3139 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
3140 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
3141 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
3142 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
3143 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
3144 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
3146 /* EA operations. */
3147 .getxattr_fn
= vfswrap_getxattr
,
3148 .fgetxattr_fn
= vfswrap_fgetxattr
,
3149 .listxattr_fn
= vfswrap_listxattr
,
3150 .flistxattr_fn
= vfswrap_flistxattr
,
3151 .removexattr_fn
= vfswrap_removexattr
,
3152 .fremovexattr_fn
= vfswrap_fremovexattr
,
3153 .setxattr_fn
= vfswrap_setxattr
,
3154 .fsetxattr_fn
= vfswrap_fsetxattr
,
3156 /* aio operations */
3157 .aio_force_fn
= vfswrap_aio_force
,
3159 /* durable handle operations */
3160 .durable_cookie_fn
= vfswrap_durable_cookie
,
3161 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
3162 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
3165 NTSTATUS
vfs_default_init(TALLOC_CTX
*);
3166 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
3168 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
3169 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);