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"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct
*handle
, const char *service
, const char *user
)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct
*handle
)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct
*handle
, const char *path
,
58 uint64_t *bsize
, uint64_t *dfree
,
61 if (sys_fsusage(path
, dfree
, dsize
) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct
*handle
, const char *path
,
70 enum SMB_QUOTA_TYPE qtype
, unid_t id
,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota
);
77 result
= sys_get_quota(path
, qtype
, id
, qt
);
78 END_PROFILE(syscall_get_quota
);
86 static int vfswrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota
);
92 result
= sys_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
93 END_PROFILE(syscall_set_quota
);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
102 struct files_struct
*fsp
,
103 struct shadow_copy_data
*shadow_copy_data
,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct
*handle
, const char *path
, vfs_statvfs_struct
*statbuf
)
112 return sys_statvfs(path
, statbuf
);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct
*handle
,
116 enum timestamp_set_resolution
*p_ts_res
)
118 connection_struct
*conn
= handle
->conn
;
119 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
120 struct smb_filename
*smb_fname_cpath
= NULL
;
121 struct vfs_statvfs_struct statbuf
;
124 ZERO_STRUCT(statbuf
);
125 ret
= sys_statvfs(conn
->connectpath
, &statbuf
);
127 caps
= statbuf
.FsCapabilities
;
130 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
137 if (smb_fname_cpath
== NULL
) {
141 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
143 TALLOC_FREE(smb_fname_cpath
);
147 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
148 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
149 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res
= TIMESTAMP_SET_MSEC
;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn
->params
->service
),
170 conn
->connectpath
));
172 TALLOC_FREE(smb_fname_cpath
);
176 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
177 struct dfs_GetDFSReferral
*r
)
179 struct junction_map
*junction
= NULL
;
181 bool self_referral
= false;
182 char *pathnamep
= NULL
;
183 char *local_dfs_path
= NULL
;
186 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
192 /* get the junction entry */
193 if (r
->in
.req
.servername
== NULL
) {
194 return NT_STATUS_NOT_FOUND
;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
203 if (local_dfs_path
== NULL
) {
204 return NT_STATUS_NO_MEMORY
;
206 pathnamep
= local_dfs_path
;
207 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
208 IS_DIRECTORY_SEP(pathnamep
[1])) {
212 junction
= talloc_zero(r
, struct junction_map
);
213 if (junction
== NULL
) {
214 return NT_STATUS_NO_MEMORY
;
217 /* The following call can change cwd. */
218 status
= get_referred_path(r
, pathnamep
,
219 handle
->conn
->sconn
->remote_address
,
220 handle
->conn
->sconn
->local_address
,
221 !handle
->conn
->sconn
->using_smb2
,
222 junction
, &consumedcnt
, &self_referral
);
223 if (!NT_STATUS_IS_OK(status
)) {
224 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
227 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
229 if (!self_referral
) {
230 pathnamep
[consumedcnt
] = '\0';
233 dbgtext("Path %s to alternate path(s):",
235 for (i
=0; i
< junction
->referral_count
; i
++) {
237 junction
->referral_list
[i
].alternate_path
);
243 if (r
->in
.req
.max_referral_level
<= 2) {
244 max_referral_level
= 2;
246 if (r
->in
.req
.max_referral_level
>= 3) {
247 max_referral_level
= 3;
250 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
251 if (r
->out
.resp
== NULL
) {
252 return NT_STATUS_NO_MEMORY
;
255 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
256 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
258 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
260 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
263 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
264 struct dfs_referral_type
,
265 r
->out
.resp
->nb_referrals
);
266 if (r
->out
.resp
->referral_entries
== NULL
) {
267 return NT_STATUS_NO_MEMORY
;
270 switch (max_referral_level
) {
272 for(i
=0; i
< junction
->referral_count
; i
++) {
273 struct referral
*ref
= &junction
->referral_list
[i
];
274 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
275 struct dfs_referral_type
*t
=
276 &r
->out
.resp
->referral_entries
[i
];
277 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
280 v2
->size
= VERSION2_REFERRAL_SIZE
;
282 v2
->server_type
= DFS_SERVER_ROOT
;
284 v2
->server_type
= DFS_SERVER_NON_ROOT
;
287 v2
->proximity
= ref
->proximity
;
289 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
290 if (v2
->DFS_path
== NULL
) {
291 return NT_STATUS_NO_MEMORY
;
293 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
294 if (v2
->DFS_alt_path
== NULL
) {
295 return NT_STATUS_NO_MEMORY
;
297 v2
->netw_address
= talloc_strdup(mem_ctx
,
298 ref
->alternate_path
);
299 if (v2
->netw_address
== NULL
) {
300 return NT_STATUS_NO_MEMORY
;
306 for(i
=0; i
< junction
->referral_count
; i
++) {
307 struct referral
*ref
= &junction
->referral_list
[i
];
308 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
309 struct dfs_referral_type
*t
=
310 &r
->out
.resp
->referral_entries
[i
];
311 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
312 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
315 v3
->size
= VERSION3_REFERRAL_SIZE
;
317 v3
->server_type
= DFS_SERVER_ROOT
;
319 v3
->server_type
= DFS_SERVER_NON_ROOT
;
323 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
324 if (r1
->DFS_path
== NULL
) {
325 return NT_STATUS_NO_MEMORY
;
327 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
328 if (r1
->DFS_alt_path
== NULL
) {
329 return NT_STATUS_NO_MEMORY
;
331 r1
->netw_address
= talloc_strdup(mem_ctx
,
332 ref
->alternate_path
);
333 if (r1
->netw_address
== NULL
) {
334 return NT_STATUS_NO_MEMORY
;
339 DEBUG(0,("Invalid dfs referral version: %d\n",
340 max_referral_level
));
341 return NT_STATUS_INVALID_LEVEL
;
345 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
351 static NTSTATUS
vfswrap_snap_check_path(struct vfs_handle_struct
*handle
,
353 const char *service_path
,
356 return NT_STATUS_NOT_SUPPORTED
;
359 static NTSTATUS
vfswrap_snap_create(struct vfs_handle_struct
*handle
,
361 const char *base_volume
,
367 return NT_STATUS_NOT_SUPPORTED
;
370 static NTSTATUS
vfswrap_snap_delete(struct vfs_handle_struct
*handle
,
375 return NT_STATUS_NOT_SUPPORTED
;
378 /* Directory operations */
380 static DIR *vfswrap_opendir(vfs_handle_struct
*handle
,
381 const struct smb_filename
*smb_fname
,
387 START_PROFILE(syscall_opendir
);
388 result
= opendir(smb_fname
->base_name
);
389 END_PROFILE(syscall_opendir
);
393 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
400 START_PROFILE(syscall_fdopendir
);
401 result
= sys_fdopendir(fsp
->fh
->fd
);
402 END_PROFILE(syscall_fdopendir
);
407 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
409 SMB_STRUCT_STAT
*sbuf
)
411 struct dirent
*result
;
413 START_PROFILE(syscall_readdir
);
414 result
= readdir(dirp
);
415 END_PROFILE(syscall_readdir
);
417 /* Default Posix readdir() does not give us stat info.
418 * Set to invalid to indicate we didn't return this info. */
419 SET_STAT_INVALID(*sbuf
);
420 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
421 if (result
!= NULL
) {
422 /* See if we can efficiently return this. */
424 int flags
= AT_SYMLINK_NOFOLLOW
;
425 int ret
= fstatat(dirfd(dirp
),
430 * As this is an optimization,
431 * ignore it if we stat'ed a
432 * symlink. Make the caller
433 * do it again as we don't
434 * know if they wanted the link
435 * info, or its target info.
437 if ((ret
== 0) && (!S_ISLNK(st
.st_mode
))) {
438 init_stat_ex_from_stat(sbuf
,
440 lp_fake_directory_create_times(
441 SNUM(handle
->conn
)));
449 static NTSTATUS
vfswrap_readdir_attr(struct vfs_handle_struct
*handle
,
450 const struct smb_filename
*fname
,
452 struct readdir_attr_data
**attr_data
)
454 return NT_STATUS_NOT_SUPPORTED
;
457 static void vfswrap_seekdir(vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
459 START_PROFILE(syscall_seekdir
);
460 seekdir(dirp
, offset
);
461 END_PROFILE(syscall_seekdir
);
464 static long vfswrap_telldir(vfs_handle_struct
*handle
, DIR *dirp
)
467 START_PROFILE(syscall_telldir
);
468 result
= telldir(dirp
);
469 END_PROFILE(syscall_telldir
);
473 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
475 START_PROFILE(syscall_rewinddir
);
477 END_PROFILE(syscall_rewinddir
);
480 static int vfswrap_mkdir(vfs_handle_struct
*handle
,
481 const struct smb_filename
*smb_fname
,
485 bool has_dacl
= False
;
486 const char *path
= smb_fname
->base_name
;
489 START_PROFILE(syscall_mkdir
);
491 if (lp_inherit_acls(SNUM(handle
->conn
))
492 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
493 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
))) {
494 mode
= (0777 & lp_directory_mask(SNUM(handle
->conn
)));
499 result
= mkdir(path
, mode
);
501 if (result
== 0 && !has_dacl
) {
503 * We need to do this as the default behavior of POSIX ACLs
504 * is to set the mask to be the requested group permission
505 * bits, not the group permission bits to be the requested
506 * group permission bits. This is not what we want, as it will
507 * mess up any inherited ACL bits that were set. JRA.
509 int saved_errno
= errno
; /* We may get ENOSYS */
510 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, smb_fname
, mode
) == -1) &&
516 END_PROFILE(syscall_mkdir
);
520 static int vfswrap_rmdir(vfs_handle_struct
*handle
,
521 const struct smb_filename
*smb_fname
)
525 START_PROFILE(syscall_rmdir
);
526 result
= rmdir(smb_fname
->base_name
);
527 END_PROFILE(syscall_rmdir
);
531 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
535 START_PROFILE(syscall_closedir
);
536 result
= closedir(dirp
);
537 END_PROFILE(syscall_closedir
);
541 static void vfswrap_init_search_op(vfs_handle_struct
*handle
,
544 /* Default behavior is a NOOP */
547 /* File operations */
549 static int vfswrap_open(vfs_handle_struct
*handle
,
550 struct smb_filename
*smb_fname
,
551 files_struct
*fsp
, int flags
, mode_t mode
)
555 START_PROFILE(syscall_open
);
557 if (smb_fname
->stream_name
) {
562 result
= open(smb_fname
->base_name
, flags
, mode
);
564 END_PROFILE(syscall_open
);
568 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
569 struct smb_request
*req
,
570 uint16_t root_dir_fid
,
571 struct smb_filename
*smb_fname
,
572 uint32_t access_mask
,
573 uint32_t share_access
,
574 uint32_t create_disposition
,
575 uint32_t create_options
,
576 uint32_t file_attributes
,
577 uint32_t oplock_request
,
578 struct smb2_lease
*lease
,
579 uint64_t allocation_size
,
580 uint32_t private_flags
,
581 struct security_descriptor
*sd
,
582 struct ea_list
*ea_list
,
583 files_struct
**result
,
585 const struct smb2_create_blobs
*in_context_blobs
,
586 struct smb2_create_blobs
*out_context_blobs
)
588 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
589 access_mask
, share_access
,
590 create_disposition
, create_options
,
591 file_attributes
, oplock_request
, lease
,
592 allocation_size
, private_flags
,
594 pinfo
, in_context_blobs
, out_context_blobs
);
597 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
601 START_PROFILE(syscall_close
);
602 result
= fd_close_posix(fsp
);
603 END_PROFILE(syscall_close
);
607 static ssize_t
vfswrap_read(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
611 START_PROFILE_BYTES(syscall_read
, n
);
612 result
= sys_read(fsp
->fh
->fd
, data
, n
);
613 END_PROFILE_BYTES(syscall_read
);
617 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
618 size_t n
, off_t offset
)
622 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
623 START_PROFILE_BYTES(syscall_pread
, n
);
624 result
= sys_pread(fsp
->fh
->fd
, data
, n
, offset
);
625 END_PROFILE_BYTES(syscall_pread
);
627 if (result
== -1 && errno
== ESPIPE
) {
628 /* Maintain the fiction that pipes can be seeked (sought?) on. */
629 result
= SMB_VFS_READ(fsp
, data
, n
);
633 #else /* HAVE_PREAD */
637 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
638 if (curr
== -1 && errno
== ESPIPE
) {
639 /* Maintain the fiction that pipes can be seeked (sought?) on. */
640 result
= SMB_VFS_READ(fsp
, data
, n
);
645 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
650 result
= SMB_VFS_READ(fsp
, data
, n
);
653 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
656 #endif /* HAVE_PREAD */
661 static ssize_t
vfswrap_write(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
665 START_PROFILE_BYTES(syscall_write
, n
);
666 result
= sys_write(fsp
->fh
->fd
, data
, n
);
667 END_PROFILE_BYTES(syscall_write
);
671 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
672 size_t n
, off_t offset
)
676 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
677 START_PROFILE_BYTES(syscall_pwrite
, n
);
678 result
= sys_pwrite(fsp
->fh
->fd
, data
, n
, offset
);
679 END_PROFILE_BYTES(syscall_pwrite
);
681 if (result
== -1 && errno
== ESPIPE
) {
682 /* Maintain the fiction that pipes can be sought on. */
683 result
= SMB_VFS_WRITE(fsp
, data
, n
);
686 #else /* HAVE_PWRITE */
690 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
695 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
699 result
= SMB_VFS_WRITE(fsp
, data
, n
);
702 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
705 #endif /* HAVE_PWRITE */
710 static int vfswrap_init_pool(struct smbd_server_connection
*conn
)
714 if (conn
->pool
!= NULL
) {
718 ret
= pthreadpool_tevent_init(conn
, lp_aio_max_threads(),
723 struct vfswrap_pread_state
{
730 struct vfs_aio_state vfs_aio_state
;
731 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
734 static void vfs_pread_do(void *private_data
);
735 static void vfs_pread_done(struct tevent_req
*subreq
);
736 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
);
738 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
740 struct tevent_context
*ev
,
741 struct files_struct
*fsp
,
743 size_t n
, off_t offset
)
745 struct tevent_req
*req
, *subreq
;
746 struct vfswrap_pread_state
*state
;
749 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
754 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
755 if (tevent_req_error(req
, ret
)) {
756 return tevent_req_post(req
, ev
);
760 state
->fd
= fsp
->fh
->fd
;
763 state
->offset
= offset
;
765 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
766 state
->profile_bytes
, n
);
767 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
769 subreq
= pthreadpool_tevent_job_send(
770 state
, ev
, handle
->conn
->sconn
->pool
,
771 vfs_pread_do
, state
);
772 if (tevent_req_nomem(subreq
, req
)) {
773 return tevent_req_post(req
, ev
);
775 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
777 talloc_set_destructor(state
, vfs_pread_state_destructor
);
782 static void vfs_pread_do(void *private_data
)
784 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
785 private_data
, struct vfswrap_pread_state
);
786 struct timespec start_time
;
787 struct timespec end_time
;
789 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
791 PROFILE_TIMESTAMP(&start_time
);
794 state
->ret
= pread(state
->fd
, state
->buf
, state
->count
,
796 } while ((state
->ret
== -1) && (errno
== EINTR
));
798 if (state
->ret
== -1) {
799 state
->vfs_aio_state
.error
= errno
;
802 PROFILE_TIMESTAMP(&end_time
);
804 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
806 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
809 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
)
814 static void vfs_pread_done(struct tevent_req
*subreq
)
816 struct tevent_req
*req
= tevent_req_callback_data(
817 subreq
, struct tevent_req
);
818 struct vfswrap_pread_state
*state
= tevent_req_data(
819 req
, struct vfswrap_pread_state
);
822 ret
= pthreadpool_tevent_job_recv(subreq
);
824 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
825 talloc_set_destructor(state
, NULL
);
826 if (tevent_req_error(req
, ret
)) {
830 tevent_req_done(req
);
833 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
834 struct vfs_aio_state
*vfs_aio_state
)
836 struct vfswrap_pread_state
*state
= tevent_req_data(
837 req
, struct vfswrap_pread_state
);
839 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
843 *vfs_aio_state
= state
->vfs_aio_state
;
847 struct vfswrap_pwrite_state
{
854 struct vfs_aio_state vfs_aio_state
;
855 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
858 static void vfs_pwrite_do(void *private_data
);
859 static void vfs_pwrite_done(struct tevent_req
*subreq
);
860 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
);
862 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
864 struct tevent_context
*ev
,
865 struct files_struct
*fsp
,
867 size_t n
, off_t offset
)
869 struct tevent_req
*req
, *subreq
;
870 struct vfswrap_pwrite_state
*state
;
873 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pwrite_state
);
878 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
879 if (tevent_req_error(req
, ret
)) {
880 return tevent_req_post(req
, ev
);
884 state
->fd
= fsp
->fh
->fd
;
887 state
->offset
= offset
;
889 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
890 state
->profile_bytes
, n
);
891 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
893 subreq
= pthreadpool_tevent_job_send(
894 state
, ev
, handle
->conn
->sconn
->pool
,
895 vfs_pwrite_do
, state
);
896 if (tevent_req_nomem(subreq
, req
)) {
897 return tevent_req_post(req
, ev
);
899 tevent_req_set_callback(subreq
, vfs_pwrite_done
, req
);
901 talloc_set_destructor(state
, vfs_pwrite_state_destructor
);
906 static void vfs_pwrite_do(void *private_data
)
908 struct vfswrap_pwrite_state
*state
= talloc_get_type_abort(
909 private_data
, struct vfswrap_pwrite_state
);
910 struct timespec start_time
;
911 struct timespec end_time
;
913 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
915 PROFILE_TIMESTAMP(&start_time
);
918 state
->ret
= pwrite(state
->fd
, state
->buf
, state
->count
,
920 } while ((state
->ret
== -1) && (errno
== EINTR
));
922 if (state
->ret
== -1) {
923 state
->vfs_aio_state
.error
= errno
;
926 PROFILE_TIMESTAMP(&end_time
);
928 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
930 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
933 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
)
938 static void vfs_pwrite_done(struct tevent_req
*subreq
)
940 struct tevent_req
*req
= tevent_req_callback_data(
941 subreq
, struct tevent_req
);
942 struct vfswrap_pwrite_state
*state
= tevent_req_data(
943 req
, struct vfswrap_pwrite_state
);
946 ret
= pthreadpool_tevent_job_recv(subreq
);
948 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
949 talloc_set_destructor(state
, NULL
);
950 if (tevent_req_error(req
, ret
)) {
954 tevent_req_done(req
);
957 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
958 struct vfs_aio_state
*vfs_aio_state
)
960 struct vfswrap_pwrite_state
*state
= tevent_req_data(
961 req
, struct vfswrap_pwrite_state
);
963 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
967 *vfs_aio_state
= state
->vfs_aio_state
;
971 struct vfswrap_fsync_state
{
975 struct vfs_aio_state vfs_aio_state
;
976 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic
);
979 static void vfs_fsync_do(void *private_data
);
980 static void vfs_fsync_done(struct tevent_req
*subreq
);
981 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
);
983 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
985 struct tevent_context
*ev
,
986 struct files_struct
*fsp
)
988 struct tevent_req
*req
, *subreq
;
989 struct vfswrap_fsync_state
*state
;
992 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
997 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
998 if (tevent_req_error(req
, ret
)) {
999 return tevent_req_post(req
, ev
);
1003 state
->fd
= fsp
->fh
->fd
;
1005 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync
, profile_p
,
1006 state
->profile_basic
);
1008 subreq
= pthreadpool_tevent_job_send(
1009 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
1010 if (tevent_req_nomem(subreq
, req
)) {
1011 return tevent_req_post(req
, ev
);
1013 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
1015 talloc_set_destructor(state
, vfs_fsync_state_destructor
);
1020 static void vfs_fsync_do(void *private_data
)
1022 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
1023 private_data
, struct vfswrap_fsync_state
);
1024 struct timespec start_time
;
1025 struct timespec end_time
;
1027 PROFILE_TIMESTAMP(&start_time
);
1030 state
->ret
= fsync(state
->fd
);
1031 } while ((state
->ret
== -1) && (errno
== EINTR
));
1033 if (state
->ret
== -1) {
1034 state
->vfs_aio_state
.error
= errno
;
1037 PROFILE_TIMESTAMP(&end_time
);
1039 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1042 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
)
1047 static void vfs_fsync_done(struct tevent_req
*subreq
)
1049 struct tevent_req
*req
= tevent_req_callback_data(
1050 subreq
, struct tevent_req
);
1051 struct vfswrap_fsync_state
*state
= tevent_req_data(
1052 req
, struct vfswrap_fsync_state
);
1055 ret
= pthreadpool_tevent_job_recv(subreq
);
1056 TALLOC_FREE(subreq
);
1057 SMBPROFILE_BASIC_ASYNC_END(state
->profile_basic
);
1058 talloc_set_destructor(state
, NULL
);
1059 if (tevent_req_error(req
, ret
)) {
1063 tevent_req_done(req
);
1066 static int vfswrap_fsync_recv(struct tevent_req
*req
,
1067 struct vfs_aio_state
*vfs_aio_state
)
1069 struct vfswrap_fsync_state
*state
= tevent_req_data(
1070 req
, struct vfswrap_fsync_state
);
1072 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1076 *vfs_aio_state
= state
->vfs_aio_state
;
1080 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1084 START_PROFILE(syscall_lseek
);
1086 /* Cope with 'stat' file opens. */
1087 if (fsp
->fh
->fd
!= -1)
1088 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
1091 * We want to maintain the fiction that we can seek
1092 * on a fifo for file system purposes. This allows
1093 * people to set up UNIX fifo's that feed data to Windows
1094 * applications. JRA.
1097 if((result
== -1) && (errno
== ESPIPE
)) {
1102 END_PROFILE(syscall_lseek
);
1106 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1107 off_t offset
, size_t n
)
1111 START_PROFILE_BYTES(syscall_sendfile
, n
);
1112 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
1113 END_PROFILE_BYTES(syscall_sendfile
);
1117 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1119 files_struct
*tofsp
,
1125 START_PROFILE_BYTES(syscall_recvfile
, n
);
1126 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
1127 END_PROFILE_BYTES(syscall_recvfile
);
1131 static int vfswrap_rename(vfs_handle_struct
*handle
,
1132 const struct smb_filename
*smb_fname_src
,
1133 const struct smb_filename
*smb_fname_dst
)
1137 START_PROFILE(syscall_rename
);
1139 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
1144 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
1147 END_PROFILE(syscall_rename
);
1151 static int vfswrap_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
1156 START_PROFILE(syscall_fsync
);
1157 result
= fsync(fsp
->fh
->fd
);
1158 END_PROFILE(syscall_fsync
);
1165 static int vfswrap_stat(vfs_handle_struct
*handle
,
1166 struct smb_filename
*smb_fname
)
1170 START_PROFILE(syscall_stat
);
1172 if (smb_fname
->stream_name
) {
1177 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1178 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1180 END_PROFILE(syscall_stat
);
1184 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1188 START_PROFILE(syscall_fstat
);
1189 result
= sys_fstat(fsp
->fh
->fd
,
1190 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1191 END_PROFILE(syscall_fstat
);
1195 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1196 struct smb_filename
*smb_fname
)
1200 START_PROFILE(syscall_lstat
);
1202 if (smb_fname
->stream_name
) {
1207 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1208 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1210 END_PROFILE(syscall_lstat
);
1214 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1216 enum vfs_translate_direction direction
,
1217 TALLOC_CTX
*mem_ctx
,
1220 return NT_STATUS_NONE_MAPPED
;
1224 * Implement the default fsctl operation.
1226 static bool vfswrap_logged_ioctl_message
= false;
1228 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1229 struct files_struct
*fsp
,
1232 uint16_t req_flags
, /* Needed for UNICODE ... */
1233 const uint8_t *_in_data
,
1235 uint8_t **_out_data
,
1236 uint32_t max_out_len
,
1239 const char *in_data
= (const char *)_in_data
;
1240 char **out_data
= (char **)_out_data
;
1244 case FSCTL_SET_SPARSE
:
1246 bool set_sparse
= true;
1248 if (in_len
>= 1 && in_data
[0] == 0) {
1252 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1254 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1255 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1256 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1257 nt_errstr(status
)));
1262 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1264 unsigned char objid
[16];
1265 char *return_data
= NULL
;
1267 /* This should return the object-id on this file.
1268 * I think I'll make this be the inode+dev. JRA.
1271 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1272 fsp_fnum_dbg(fsp
)));
1274 *out_len
= MIN(max_out_len
, 64);
1276 /* Hmmm, will this cause problems if less data asked for? */
1277 return_data
= talloc_array(ctx
, char, 64);
1278 if (return_data
== NULL
) {
1279 return NT_STATUS_NO_MEMORY
;
1282 /* For backwards compatibility only store the dev/inode. */
1283 push_file_id_16(return_data
, &fsp
->file_id
);
1284 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1285 push_file_id_16(return_data
+32, &fsp
->file_id
);
1286 memset(return_data
+48, 0, 16);
1287 *out_data
= return_data
;
1288 return NT_STATUS_OK
;
1291 case FSCTL_GET_REPARSE_POINT
:
1293 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1294 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1295 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1296 return NT_STATUS_NOT_A_REPARSE_POINT
;
1299 case FSCTL_SET_REPARSE_POINT
:
1301 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1302 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1303 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1304 return NT_STATUS_NOT_A_REPARSE_POINT
;
1307 case FSCTL_GET_SHADOW_COPY_DATA
:
1310 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1311 * and return their volume names. If max_data_count is 16, then it is just
1312 * asking for the number of volumes and length of the combined names.
1314 * pdata is the data allocated by our caller, but that uses
1315 * total_data_count (which is 0 in our case) rather than max_data_count.
1316 * Allocate the correct amount and return the pointer to let
1317 * it be deallocated when we return.
1319 struct shadow_copy_data
*shadow_data
= NULL
;
1320 bool labels
= False
;
1321 uint32_t labels_data_count
= 0;
1323 char *cur_pdata
= NULL
;
1325 if (max_out_len
< 16) {
1326 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1328 return NT_STATUS_INVALID_PARAMETER
;
1331 if (max_out_len
> 16) {
1335 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1336 if (shadow_data
== NULL
) {
1337 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1338 return NT_STATUS_NO_MEMORY
;
1342 * Call the VFS routine to actually do the work.
1344 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1347 /* broken module didn't set errno on error */
1348 status
= NT_STATUS_UNSUCCESSFUL
;
1350 status
= map_nt_error_from_unix(errno
);
1351 if (NT_STATUS_EQUAL(status
,
1352 NT_STATUS_NOT_SUPPORTED
)) {
1356 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1357 "connectpath %s, failed - %s.\n",
1358 fsp
->conn
->connectpath
,
1359 nt_errstr(status
)));
1360 TALLOC_FREE(shadow_data
);
1364 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1365 sizeof(SHADOW_COPY_LABEL
)) + 2;
1370 *out_len
= 12 + labels_data_count
;
1373 if (max_out_len
< *out_len
) {
1374 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1375 max_out_len
, *out_len
));
1376 TALLOC_FREE(shadow_data
);
1377 return NT_STATUS_BUFFER_TOO_SMALL
;
1380 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1381 if (cur_pdata
== NULL
) {
1382 TALLOC_FREE(shadow_data
);
1383 return NT_STATUS_NO_MEMORY
;
1386 *out_data
= cur_pdata
;
1388 /* num_volumes 4 bytes */
1389 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1392 /* num_labels 4 bytes */
1393 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1396 /* needed_data_count 4 bytes */
1397 SIVAL(cur_pdata
, 8, labels_data_count
);
1401 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1402 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1403 if (labels
&& shadow_data
->labels
) {
1404 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1406 status
= srvstr_push(cur_pdata
, req_flags
,
1407 cur_pdata
, shadow_data
->labels
[i
],
1408 2 * sizeof(SHADOW_COPY_LABEL
),
1409 STR_UNICODE
|STR_TERMINATE
, &len
);
1410 if (!NT_STATUS_IS_OK(status
)) {
1411 TALLOC_FREE(*out_data
);
1412 TALLOC_FREE(shadow_data
);
1415 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1416 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1420 TALLOC_FREE(shadow_data
);
1422 return NT_STATUS_OK
;
1425 case FSCTL_FIND_FILES_BY_SID
:
1427 /* pretend this succeeded -
1429 * we have to send back a list with all files owned by this SID
1431 * but I have to check that --metze
1437 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1438 fsp_fnum_dbg(fsp
)));
1441 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1442 return NT_STATUS_INVALID_PARAMETER
;
1445 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1447 /* unknown 4 bytes: this is not the length of the sid :-( */
1448 /*unknown = IVAL(pdata,0);*/
1450 if (!sid_parse(_in_data
+ 4, sid_len
, &sid
)) {
1451 return NT_STATUS_INVALID_PARAMETER
;
1453 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
1455 if (!sid_to_uid(&sid
, &uid
)) {
1456 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1457 sid_string_dbg(&sid
),
1458 (unsigned long)sid_len
));
1462 /* we can take a look at the find source :-)
1464 * find ./ -uid $uid -name '*' is what we need here
1467 * and send 4bytes len and then NULL terminated unicode strings
1470 * but I don't know how to deal with the paged results
1471 * (maybe we can hang the result anywhere in the fsp struct)
1473 * but I don't know how to deal with the paged results
1474 * (maybe we can hang the result anywhere in the fsp struct)
1476 * we don't send all files at once
1477 * and at the next we should *not* start from the beginning,
1478 * so we have to cache the result
1483 /* this works for now... */
1484 return NT_STATUS_OK
;
1487 case FSCTL_QUERY_ALLOCATED_RANGES
:
1489 /* FIXME: This is just a dummy reply, telling that all of the
1490 * file is allocated. MKS cp needs that.
1491 * Adding the real allocated ranges via FIEMAP on Linux
1492 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1493 * this FSCTL correct for sparse files.
1495 uint64_t offset
, length
;
1496 char *out_data_tmp
= NULL
;
1499 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1501 return NT_STATUS_INVALID_PARAMETER
;
1504 if (max_out_len
< 16) {
1505 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1507 return NT_STATUS_INVALID_PARAMETER
;
1510 offset
= BVAL(in_data
,0);
1511 length
= BVAL(in_data
,8);
1513 if (offset
+ length
< offset
) {
1514 /* No 64-bit integer wrap. */
1515 return NT_STATUS_INVALID_PARAMETER
;
1518 /* Shouldn't this be SMB_VFS_STAT ... ? */
1519 status
= vfs_stat_fsp(fsp
);
1520 if (!NT_STATUS_IS_OK(status
)) {
1525 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1526 if (out_data_tmp
== NULL
) {
1527 DEBUG(10, ("unable to allocate memory for response\n"));
1528 return NT_STATUS_NO_MEMORY
;
1531 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1532 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1534 memset(out_data_tmp
, 0, *out_len
);
1536 uint64_t end
= offset
+ length
;
1537 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1538 SBVAL(out_data_tmp
, 0, 0);
1539 SBVAL(out_data_tmp
, 8, end
);
1542 *out_data
= out_data_tmp
;
1544 return NT_STATUS_OK
;
1547 case FSCTL_IS_VOLUME_DIRTY
:
1549 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1550 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1552 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1553 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1555 return NT_STATUS_INVALID_PARAMETER
;
1560 * Only print once ... unfortunately there could be lots of
1561 * different FSCTLs that are called.
1563 if (!vfswrap_logged_ioctl_message
) {
1564 vfswrap_logged_ioctl_message
= true;
1565 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1566 __func__
, function
));
1570 return NT_STATUS_NOT_SUPPORTED
;
1573 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
1574 const struct smb_filename
*fname
,
1575 SMB_STRUCT_STAT
*sbuf
);
1577 static NTSTATUS
vfswrap_get_dos_attributes(struct vfs_handle_struct
*handle
,
1578 struct smb_filename
*smb_fname
,
1583 offline
= vfswrap_is_offline(handle
, smb_fname
, &smb_fname
->st
);
1585 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1588 return get_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1591 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1592 struct files_struct
*fsp
,
1597 offline
= vfswrap_is_offline(handle
, fsp
->fsp_name
, &fsp
->fsp_name
->st
);
1599 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1602 return get_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1605 static NTSTATUS
vfswrap_set_dos_attributes(struct vfs_handle_struct
*handle
,
1606 const struct smb_filename
*smb_fname
,
1609 return set_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1612 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1613 struct files_struct
*fsp
,
1616 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1619 struct vfs_cc_state
{
1624 static struct tevent_req
*vfswrap_copy_chunk_send(struct vfs_handle_struct
*handle
,
1625 TALLOC_CTX
*mem_ctx
,
1626 struct tevent_context
*ev
,
1627 struct files_struct
*src_fsp
,
1629 struct files_struct
*dest_fsp
,
1633 struct tevent_req
*req
;
1634 struct vfs_cc_state
*vfs_cc_state
;
1637 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1638 (unsigned long)num
));
1640 req
= tevent_req_create(mem_ctx
, &vfs_cc_state
, struct vfs_cc_state
);
1645 vfs_cc_state
->buf
= talloc_array(vfs_cc_state
, uint8_t,
1646 MIN(num
, 8*1024*1024));
1647 if (tevent_req_nomem(vfs_cc_state
->buf
, req
)) {
1648 return tevent_req_post(req
, ev
);
1651 status
= vfs_stat_fsp(src_fsp
);
1652 if (tevent_req_nterror(req
, status
)) {
1653 return tevent_req_post(req
, ev
);
1656 if (src_fsp
->fsp_name
->st
.st_ex_size
< src_off
+ num
) {
1658 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1659 * If the SourceOffset or SourceOffset + Length extends beyond
1660 * the end of file, the server SHOULD<240> treat this as a
1661 * STATUS_END_OF_FILE error.
1663 * <240> Section 3.3.5.15.6: Windows servers will return
1664 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1666 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
1667 return tevent_req_post(req
, ev
);
1670 /* could use 2.6.33+ sendfile here to do this in kernel */
1671 while (vfs_cc_state
->copied
< num
) {
1673 struct lock_struct lck
;
1676 off_t this_num
= MIN(talloc_array_length(vfs_cc_state
->buf
),
1677 num
- vfs_cc_state
->copied
);
1679 if (src_fsp
->op
== NULL
) {
1680 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1681 return tevent_req_post(req
, ev
);
1683 init_strict_lock_struct(src_fsp
,
1684 src_fsp
->op
->global
->open_persistent_id
,
1690 if (!SMB_VFS_STRICT_LOCK(src_fsp
->conn
, src_fsp
, &lck
)) {
1691 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1692 return tevent_req_post(req
, ev
);
1695 ret
= SMB_VFS_PREAD(src_fsp
, vfs_cc_state
->buf
,
1698 saved_errno
= errno
;
1701 SMB_VFS_STRICT_UNLOCK(dest_fsp
->conn
, dest_fsp
, &lck
);
1704 errno
= saved_errno
;
1705 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
1706 return tevent_req_post(req
, ev
);
1708 if (ret
!= this_num
) {
1709 /* zero tolerance for short reads */
1710 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1711 return tevent_req_post(req
, ev
);
1716 if (dest_fsp
->op
== NULL
) {
1717 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1718 return tevent_req_post(req
, ev
);
1721 init_strict_lock_struct(dest_fsp
,
1722 dest_fsp
->op
->global
->open_persistent_id
,
1728 if (!SMB_VFS_STRICT_LOCK(dest_fsp
->conn
, dest_fsp
, &lck
)) {
1729 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1730 return tevent_req_post(req
, ev
);
1733 ret
= SMB_VFS_PWRITE(dest_fsp
, vfs_cc_state
->buf
,
1734 this_num
, dest_off
);
1736 saved_errno
= errno
;
1739 SMB_VFS_STRICT_UNLOCK(src_fsp
->conn
, src_fsp
, &lck
);
1742 errno
= saved_errno
;
1743 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
1744 return tevent_req_post(req
, ev
);
1746 if (ret
!= this_num
) {
1747 /* zero tolerance for short writes */
1748 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1749 return tevent_req_post(req
, ev
);
1753 vfs_cc_state
->copied
+= this_num
;
1756 tevent_req_done(req
);
1757 return tevent_req_post(req
, ev
);
1760 static NTSTATUS
vfswrap_copy_chunk_recv(struct vfs_handle_struct
*handle
,
1761 struct tevent_req
*req
,
1764 struct vfs_cc_state
*vfs_cc_state
= tevent_req_data(req
,
1765 struct vfs_cc_state
);
1768 if (tevent_req_is_nterror(req
, &status
)) {
1769 DEBUG(2, ("server side copy chunk failed: %s\n",
1770 nt_errstr(status
)));
1772 tevent_req_received(req
);
1776 *copied
= vfs_cc_state
->copied
;
1777 DEBUG(10, ("server side copy chunk copied %lu\n",
1778 (unsigned long)*copied
));
1779 tevent_req_received(req
);
1781 return NT_STATUS_OK
;
1784 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
1785 TALLOC_CTX
*mem_ctx
,
1786 struct files_struct
*fsp
,
1787 struct smb_filename
*smb_fname
,
1788 uint16_t *_compression_fmt
)
1790 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1793 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
1794 TALLOC_CTX
*mem_ctx
,
1795 struct files_struct
*fsp
,
1796 uint16_t compression_fmt
)
1798 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1801 /********************************************************************
1802 Given a stat buffer return the allocated size on disk, taking into
1803 account sparse files.
1804 ********************************************************************/
1805 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
1806 struct files_struct
*fsp
,
1807 const SMB_STRUCT_STAT
*sbuf
)
1811 START_PROFILE(syscall_get_alloc_size
);
1813 if(S_ISDIR(sbuf
->st_ex_mode
)) {
1818 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1819 /* The type of st_blocksize is blkcnt_t which *MUST* be
1820 signed (according to POSIX) and can be less than 64-bits.
1821 Ensure when we're converting to 64 bits wide we don't
1823 #if defined(SIZEOF_BLKCNT_T_8)
1824 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
1825 #elif defined(SIZEOF_BLKCNT_T_4)
1827 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
1828 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
1831 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1835 * Some file systems do not allocate a block for very
1836 * small files. But for non-empty file should report a
1840 uint64_t filesize
= get_file_size_stat(sbuf
);
1842 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
1846 result
= get_file_size_stat(sbuf
);
1849 if (fsp
&& fsp
->initial_allocation_size
)
1850 result
= MAX(result
,fsp
->initial_allocation_size
);
1852 result
= smb_roundup(handle
->conn
, result
);
1855 END_PROFILE(syscall_get_alloc_size
);
1859 static int vfswrap_unlink(vfs_handle_struct
*handle
,
1860 const struct smb_filename
*smb_fname
)
1864 START_PROFILE(syscall_unlink
);
1866 if (smb_fname
->stream_name
) {
1870 result
= unlink(smb_fname
->base_name
);
1873 END_PROFILE(syscall_unlink
);
1877 static int vfswrap_chmod(vfs_handle_struct
*handle
,
1878 const struct smb_filename
*smb_fname
,
1883 START_PROFILE(syscall_chmod
);
1886 * We need to do this due to the fact that the default POSIX ACL
1887 * chmod modifies the ACL *mask* for the group owner, not the
1888 * group owner bits directly. JRA.
1893 int saved_errno
= errno
; /* We might get ENOSYS */
1894 result
= SMB_VFS_CHMOD_ACL(handle
->conn
,
1898 END_PROFILE(syscall_chmod
);
1901 /* Error - return the old errno. */
1902 errno
= saved_errno
;
1905 result
= chmod(smb_fname
->base_name
, mode
);
1906 END_PROFILE(syscall_chmod
);
1910 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
1914 START_PROFILE(syscall_fchmod
);
1917 * We need to do this due to the fact that the default POSIX ACL
1918 * chmod modifies the ACL *mask* for the group owner, not the
1919 * group owner bits directly. JRA.
1923 int saved_errno
= errno
; /* We might get ENOSYS */
1924 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
1925 END_PROFILE(syscall_fchmod
);
1928 /* Error - return the old errno. */
1929 errno
= saved_errno
;
1932 #if defined(HAVE_FCHMOD)
1933 result
= fchmod(fsp
->fh
->fd
, mode
);
1939 END_PROFILE(syscall_fchmod
);
1943 static int vfswrap_chown(vfs_handle_struct
*handle
,
1944 const struct smb_filename
*smb_fname
,
1950 START_PROFILE(syscall_chown
);
1951 result
= chown(smb_fname
->base_name
, uid
, gid
);
1952 END_PROFILE(syscall_chown
);
1956 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
1961 START_PROFILE(syscall_fchown
);
1962 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
1963 END_PROFILE(syscall_fchown
);
1971 static int vfswrap_lchown(vfs_handle_struct
*handle
,
1972 const struct smb_filename
*smb_fname
,
1978 START_PROFILE(syscall_lchown
);
1979 result
= lchown(smb_fname
->base_name
, uid
, gid
);
1980 END_PROFILE(syscall_lchown
);
1984 static int vfswrap_chdir(vfs_handle_struct
*handle
, const char *path
)
1988 START_PROFILE(syscall_chdir
);
1989 result
= chdir(path
);
1990 END_PROFILE(syscall_chdir
);
1994 static char *vfswrap_getwd(vfs_handle_struct
*handle
)
1998 START_PROFILE(syscall_getwd
);
1999 result
= sys_getwd();
2000 END_PROFILE(syscall_getwd
);
2004 /*********************************************************************
2005 nsec timestamp resolution call. Convert down to whatever the underlying
2006 system will support.
2007 **********************************************************************/
2009 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
2010 const struct smb_filename
*smb_fname
,
2011 struct smb_file_time
*ft
)
2015 START_PROFILE(syscall_ntimes
);
2017 if (smb_fname
->stream_name
) {
2023 if (null_timespec(ft
->atime
)) {
2024 ft
->atime
= smb_fname
->st
.st_ex_atime
;
2027 if (null_timespec(ft
->mtime
)) {
2028 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
2031 if (!null_timespec(ft
->create_time
)) {
2032 set_create_timespec_ea(handle
->conn
,
2037 if ((timespec_compare(&ft
->atime
,
2038 &smb_fname
->st
.st_ex_atime
) == 0) &&
2039 (timespec_compare(&ft
->mtime
,
2040 &smb_fname
->st
.st_ex_mtime
) == 0)) {
2045 #if defined(HAVE_UTIMENSAT)
2047 struct timespec ts
[2];
2050 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
2052 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
2054 if (!((result
== -1) && (errno
== ENOSYS
))) {
2058 #if defined(HAVE_UTIMES)
2060 struct timeval tv
[2];
2061 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
2062 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
2063 result
= utimes(smb_fname
->base_name
, tv
);
2065 result
= utimes(smb_fname
->base_name
, NULL
);
2067 if (!((result
== -1) && (errno
== ENOSYS
))) {
2071 #if defined(HAVE_UTIME)
2073 struct utimbuf times
;
2074 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
2075 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
2076 result
= utime(smb_fname
->base_name
, ×
);
2078 result
= utime(smb_fname
->base_name
, NULL
);
2080 if (!((result
== -1) && (errno
== ENOSYS
))) {
2088 END_PROFILE(syscall_ntimes
);
2092 /*********************************************************************
2093 A version of ftruncate that will write the space on disk if strict
2095 **********************************************************************/
2097 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2099 off_t space_to_write
;
2100 uint64_t space_avail
;
2101 uint64_t bsize
,dfree
,dsize
;
2104 SMB_STRUCT_STAT
*pst
;
2106 status
= vfs_stat_fsp(fsp
);
2107 if (!NT_STATUS_IS_OK(status
)) {
2110 pst
= &fsp
->fsp_name
->st
;
2113 if (S_ISFIFO(pst
->st_ex_mode
))
2117 if (pst
->st_ex_size
== len
)
2120 /* Shrink - just ftruncate. */
2121 if (pst
->st_ex_size
> len
)
2122 return ftruncate(fsp
->fh
->fd
, len
);
2124 space_to_write
= len
- pst
->st_ex_size
;
2126 /* for allocation try fallocate first. This can fail on some
2127 platforms e.g. when the filesystem doesn't support it and no
2128 emulation is being done by the libc (like on AIX with JFS1). In that
2129 case we do our own emulation. fallocate implementations can
2130 return ENOTSUP or EINVAL in cases like that. */
2131 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2132 if (ret
== -1 && errno
== ENOSPC
) {
2138 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2139 "error %d. Falling back to slow manual allocation\n", errno
));
2141 /* available disk space is enough or not? */
2143 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2144 /* space_avail is 1k blocks */
2145 if (space_avail
== (uint64_t)-1 ||
2146 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2151 /* Write out the real space on disk. */
2152 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2160 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2163 SMB_STRUCT_STAT
*pst
;
2167 START_PROFILE(syscall_ftruncate
);
2169 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
2170 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2171 END_PROFILE(syscall_ftruncate
);
2175 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2176 ftruncate if the system supports it. Then I discovered that
2177 you can have some filesystems that support ftruncate
2178 expansion and some that don't! On Linux fat can't do
2179 ftruncate extend but ext2 can. */
2181 result
= ftruncate(fsp
->fh
->fd
, len
);
2183 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2184 extend a file with ftruncate. Provide alternate implementation
2187 /* Do an fstat to see if the file is longer than the requested
2188 size in which case the ftruncate above should have
2189 succeeded or shorter, in which case seek to len - 1 and
2190 write 1 byte of zero */
2191 status
= vfs_stat_fsp(fsp
);
2192 if (!NT_STATUS_IS_OK(status
)) {
2196 /* We need to update the files_struct after successful ftruncate */
2201 pst
= &fsp
->fsp_name
->st
;
2204 if (S_ISFIFO(pst
->st_ex_mode
)) {
2210 if (pst
->st_ex_size
== len
) {
2215 if (pst
->st_ex_size
> len
) {
2216 /* the ftruncate should have worked */
2220 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
2228 END_PROFILE(syscall_ftruncate
);
2232 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
2240 START_PROFILE(syscall_fallocate
);
2242 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
2244 * posix_fallocate returns 0 on success, errno on error
2245 * and doesn't set errno. Make it behave like fallocate()
2246 * which returns -1, and sets errno on failure.
2253 /* sys_fallocate handles filtering of unsupported mode flags */
2254 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
2256 END_PROFILE(syscall_fallocate
);
2260 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
2264 START_PROFILE(syscall_fcntl_lock
);
2266 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2268 "force process locks",
2270 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2273 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
2274 END_PROFILE(syscall_fcntl_lock
);
2278 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2279 uint32_t share_mode
, uint32_t access_mask
)
2281 START_PROFILE(syscall_kernel_flock
);
2282 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
2283 END_PROFILE(syscall_kernel_flock
);
2287 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2292 START_PROFILE(syscall_fcntl_getlock
);
2294 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2296 "force process locks",
2298 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2301 result
= fcntl_getlock(fsp
->fh
->fd
, op
, poffset
, pcount
, ptype
, ppid
);
2302 END_PROFILE(syscall_fcntl_getlock
);
2306 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2311 START_PROFILE(syscall_linux_setlease
);
2313 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2314 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2318 END_PROFILE(syscall_linux_setlease
);
2322 static int vfswrap_symlink(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2326 START_PROFILE(syscall_symlink
);
2327 result
= symlink(oldpath
, newpath
);
2328 END_PROFILE(syscall_symlink
);
2332 static int vfswrap_readlink(vfs_handle_struct
*handle
, const char *path
, char *buf
, size_t bufsiz
)
2336 START_PROFILE(syscall_readlink
);
2337 result
= readlink(path
, buf
, bufsiz
);
2338 END_PROFILE(syscall_readlink
);
2342 static int vfswrap_link(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2346 START_PROFILE(syscall_link
);
2347 result
= link(oldpath
, newpath
);
2348 END_PROFILE(syscall_link
);
2352 static int vfswrap_mknod(vfs_handle_struct
*handle
, const char *pathname
, mode_t mode
, SMB_DEV_T dev
)
2356 START_PROFILE(syscall_mknod
);
2357 result
= sys_mknod(pathname
, mode
, dev
);
2358 END_PROFILE(syscall_mknod
);
2362 static char *vfswrap_realpath(vfs_handle_struct
*handle
, const char *path
)
2366 START_PROFILE(syscall_realpath
);
2367 result
= sys_realpath(path
);
2368 END_PROFILE(syscall_realpath
);
2372 static int vfswrap_chflags(vfs_handle_struct
*handle
, const char *path
,
2376 return chflags(path
, flags
);
2383 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2384 const SMB_STRUCT_STAT
*sbuf
)
2388 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2392 key
.devid
= sbuf
->st_ex_dev
;
2393 key
.inode
= sbuf
->st_ex_ino
;
2394 /* key.extid is unused by default. */
2399 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
2400 struct files_struct
*fsp
,
2401 const struct smb_filename
*smb_fname
,
2402 TALLOC_CTX
*mem_ctx
,
2403 unsigned int *pnum_streams
,
2404 struct stream_struct
**pstreams
)
2406 SMB_STRUCT_STAT sbuf
;
2407 struct stream_struct
*tmp_streams
= NULL
;
2410 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
2412 * No default streams on directories
2417 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
2418 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
2421 struct smb_filename smb_fname_cp
;
2423 ZERO_STRUCT(smb_fname_cp
);
2424 smb_fname_cp
.base_name
= discard_const_p(char,
2425 smb_fname
->base_name
);
2426 smb_fname_cp
.flags
= smb_fname
->flags
;
2428 if (smb_fname_cp
.flags
& SMB_FILENAME_POSIX_PATH
) {
2429 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname_cp
);
2431 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname_cp
);
2433 sbuf
= smb_fname_cp
.st
;
2437 return map_nt_error_from_unix(errno
);
2440 if (S_ISDIR(sbuf
.st_ex_mode
)) {
2444 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
2445 (*pnum_streams
) + 1);
2446 if (tmp_streams
== NULL
) {
2447 return NT_STATUS_NO_MEMORY
;
2449 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
2450 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
2451 return NT_STATUS_NO_MEMORY
;
2453 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
2454 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
2457 *pstreams
= tmp_streams
;
2459 return NT_STATUS_OK
;
2462 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
2465 TALLOC_CTX
*mem_ctx
,
2469 * Don't fall back to get_real_filename so callers can differentiate
2470 * between a full directory scan and an actual case-insensitive stat.
2476 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
2479 return handle
->conn
->connectpath
;
2482 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
2483 struct byte_range_lock
*br_lck
,
2484 struct lock_struct
*plock
,
2487 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2489 /* Note: blr is not used in the default implementation. */
2490 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
2493 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
2494 struct messaging_context
*msg_ctx
,
2495 struct byte_range_lock
*br_lck
,
2496 const struct lock_struct
*plock
)
2498 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2500 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
2503 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
2504 struct byte_range_lock
*br_lck
,
2505 struct lock_struct
*plock
)
2507 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2509 /* Note: blr is not used in the default implementation. */
2510 return brl_lock_cancel_default(br_lck
, plock
);
2513 static bool vfswrap_strict_lock(struct vfs_handle_struct
*handle
,
2515 struct lock_struct
*plock
)
2517 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2518 plock
->lock_type
== WRITE_LOCK
);
2520 return strict_lock_default(fsp
, plock
);
2523 static void vfswrap_strict_unlock(struct vfs_handle_struct
*handle
,
2525 struct lock_struct
*plock
)
2527 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2528 plock
->lock_type
== WRITE_LOCK
);
2530 strict_unlock_default(fsp
, plock
);
2533 /* NT ACL operations. */
2535 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
2537 uint32_t security_info
,
2538 TALLOC_CTX
*mem_ctx
,
2539 struct security_descriptor
**ppdesc
)
2543 START_PROFILE(fget_nt_acl
);
2544 result
= posix_fget_nt_acl(fsp
, security_info
,
2546 END_PROFILE(fget_nt_acl
);
2550 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
2551 const struct smb_filename
*smb_fname
,
2552 uint32_t security_info
,
2553 TALLOC_CTX
*mem_ctx
,
2554 struct security_descriptor
**ppdesc
)
2558 START_PROFILE(get_nt_acl
);
2559 result
= posix_get_nt_acl(handle
->conn
,
2564 END_PROFILE(get_nt_acl
);
2568 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
2572 START_PROFILE(fset_nt_acl
);
2573 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
2574 END_PROFILE(fset_nt_acl
);
2578 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
2579 struct smb_filename
*file
,
2580 struct security_acl
*sacl
,
2581 uint32_t access_requested
,
2582 uint32_t access_denied
)
2584 return NT_STATUS_OK
; /* Nothing to do here ... */
2587 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
,
2588 const struct smb_filename
*smb_fname
,
2597 START_PROFILE(chmod_acl
);
2598 result
= chmod_acl(handle
->conn
, smb_fname
->base_name
, mode
);
2599 END_PROFILE(chmod_acl
);
2604 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2612 START_PROFILE(fchmod_acl
);
2613 result
= fchmod_acl(fsp
, mode
);
2614 END_PROFILE(fchmod_acl
);
2619 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
2621 SMB_ACL_TYPE_T type
,
2622 TALLOC_CTX
*mem_ctx
)
2624 return sys_acl_get_file(handle
, path_p
, type
, mem_ctx
);
2627 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
2629 TALLOC_CTX
*mem_ctx
)
2631 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
2634 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
, const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
2636 return sys_acl_set_file(handle
, name
, acltype
, theacl
);
2639 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2641 return sys_acl_set_fd(handle
, fsp
, theacl
);
2644 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
, const char *path
)
2646 return sys_acl_delete_def_file(handle
, path
);
2649 /****************************************************************
2650 Extended attribute operations.
2651 *****************************************************************/
2653 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,const char *path
, const char *name
, void *value
, size_t size
)
2655 return getxattr(path
, name
, value
, size
);
2658 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2660 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2663 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
, const char *path
, char *list
, size_t size
)
2665 return listxattr(path
, list
, size
);
2668 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2670 return flistxattr(fsp
->fh
->fd
, list
, size
);
2673 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
)
2675 return removexattr(path
, name
);
2678 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2680 return fremovexattr(fsp
->fh
->fd
, name
);
2683 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
2685 return setxattr(path
, name
, value
, size
, flags
);
2688 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2690 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2693 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2698 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2699 const struct smb_filename
*fname
,
2700 SMB_STRUCT_STAT
*sbuf
)
2704 bool offline
= false;
2706 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2710 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2711 #if defined(ENOTSUP)
2717 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2718 if (!NT_STATUS_IS_OK(status
)) {
2719 errno
= map_errno_from_nt_status(status
);
2723 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2730 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
2731 struct files_struct
*fsp
,
2732 TALLOC_CTX
*mem_ctx
,
2735 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
2738 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
2739 struct files_struct
*fsp
,
2740 const DATA_BLOB old_cookie
,
2741 TALLOC_CTX
*mem_ctx
,
2742 DATA_BLOB
*new_cookie
)
2744 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
2748 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
2749 struct smb_request
*smb1req
,
2750 struct smbXsrv_open
*op
,
2751 const DATA_BLOB old_cookie
,
2752 TALLOC_CTX
*mem_ctx
,
2753 struct files_struct
**fsp
,
2754 DATA_BLOB
*new_cookie
)
2756 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
2757 old_cookie
, mem_ctx
,
2761 static struct vfs_fn_pointers vfs_default_fns
= {
2762 /* Disk operations */
2764 .connect_fn
= vfswrap_connect
,
2765 .disconnect_fn
= vfswrap_disconnect
,
2766 .disk_free_fn
= vfswrap_disk_free
,
2767 .get_quota_fn
= vfswrap_get_quota
,
2768 .set_quota_fn
= vfswrap_set_quota
,
2769 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
2770 .statvfs_fn
= vfswrap_statvfs
,
2771 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
2772 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
2773 .snap_check_path_fn
= vfswrap_snap_check_path
,
2774 .snap_create_fn
= vfswrap_snap_create
,
2775 .snap_delete_fn
= vfswrap_snap_delete
,
2777 /* Directory operations */
2779 .opendir_fn
= vfswrap_opendir
,
2780 .fdopendir_fn
= vfswrap_fdopendir
,
2781 .readdir_fn
= vfswrap_readdir
,
2782 .readdir_attr_fn
= vfswrap_readdir_attr
,
2783 .seekdir_fn
= vfswrap_seekdir
,
2784 .telldir_fn
= vfswrap_telldir
,
2785 .rewind_dir_fn
= vfswrap_rewinddir
,
2786 .mkdir_fn
= vfswrap_mkdir
,
2787 .rmdir_fn
= vfswrap_rmdir
,
2788 .closedir_fn
= vfswrap_closedir
,
2789 .init_search_op_fn
= vfswrap_init_search_op
,
2791 /* File operations */
2793 .open_fn
= vfswrap_open
,
2794 .create_file_fn
= vfswrap_create_file
,
2795 .close_fn
= vfswrap_close
,
2796 .read_fn
= vfswrap_read
,
2797 .pread_fn
= vfswrap_pread
,
2798 .pread_send_fn
= vfswrap_pread_send
,
2799 .pread_recv_fn
= vfswrap_pread_recv
,
2800 .write_fn
= vfswrap_write
,
2801 .pwrite_fn
= vfswrap_pwrite
,
2802 .pwrite_send_fn
= vfswrap_pwrite_send
,
2803 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
2804 .lseek_fn
= vfswrap_lseek
,
2805 .sendfile_fn
= vfswrap_sendfile
,
2806 .recvfile_fn
= vfswrap_recvfile
,
2807 .rename_fn
= vfswrap_rename
,
2808 .fsync_fn
= vfswrap_fsync
,
2809 .fsync_send_fn
= vfswrap_fsync_send
,
2810 .fsync_recv_fn
= vfswrap_fsync_recv
,
2811 .stat_fn
= vfswrap_stat
,
2812 .fstat_fn
= vfswrap_fstat
,
2813 .lstat_fn
= vfswrap_lstat
,
2814 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
2815 .unlink_fn
= vfswrap_unlink
,
2816 .chmod_fn
= vfswrap_chmod
,
2817 .fchmod_fn
= vfswrap_fchmod
,
2818 .chown_fn
= vfswrap_chown
,
2819 .fchown_fn
= vfswrap_fchown
,
2820 .lchown_fn
= vfswrap_lchown
,
2821 .chdir_fn
= vfswrap_chdir
,
2822 .getwd_fn
= vfswrap_getwd
,
2823 .ntimes_fn
= vfswrap_ntimes
,
2824 .ftruncate_fn
= vfswrap_ftruncate
,
2825 .fallocate_fn
= vfswrap_fallocate
,
2826 .lock_fn
= vfswrap_lock
,
2827 .kernel_flock_fn
= vfswrap_kernel_flock
,
2828 .linux_setlease_fn
= vfswrap_linux_setlease
,
2829 .getlock_fn
= vfswrap_getlock
,
2830 .symlink_fn
= vfswrap_symlink
,
2831 .readlink_fn
= vfswrap_readlink
,
2832 .link_fn
= vfswrap_link
,
2833 .mknod_fn
= vfswrap_mknod
,
2834 .realpath_fn
= vfswrap_realpath
,
2835 .chflags_fn
= vfswrap_chflags
,
2836 .file_id_create_fn
= vfswrap_file_id_create
,
2837 .streaminfo_fn
= vfswrap_streaminfo
,
2838 .get_real_filename_fn
= vfswrap_get_real_filename
,
2839 .connectpath_fn
= vfswrap_connectpath
,
2840 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
2841 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
2842 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
2843 .strict_lock_fn
= vfswrap_strict_lock
,
2844 .strict_unlock_fn
= vfswrap_strict_unlock
,
2845 .translate_name_fn
= vfswrap_translate_name
,
2846 .fsctl_fn
= vfswrap_fsctl
,
2847 .set_dos_attributes_fn
= vfswrap_set_dos_attributes
,
2848 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
2849 .get_dos_attributes_fn
= vfswrap_get_dos_attributes
,
2850 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
2851 .copy_chunk_send_fn
= vfswrap_copy_chunk_send
,
2852 .copy_chunk_recv_fn
= vfswrap_copy_chunk_recv
,
2853 .get_compression_fn
= vfswrap_get_compression
,
2854 .set_compression_fn
= vfswrap_set_compression
,
2856 /* NT ACL operations. */
2858 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
2859 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
2860 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
2861 .audit_file_fn
= vfswrap_audit_file
,
2863 /* POSIX ACL operations. */
2865 .chmod_acl_fn
= vfswrap_chmod_acl
,
2866 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
2868 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
2869 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
2870 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
2871 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
2872 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
2873 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
2874 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
2876 /* EA operations. */
2877 .getxattr_fn
= vfswrap_getxattr
,
2878 .fgetxattr_fn
= vfswrap_fgetxattr
,
2879 .listxattr_fn
= vfswrap_listxattr
,
2880 .flistxattr_fn
= vfswrap_flistxattr
,
2881 .removexattr_fn
= vfswrap_removexattr
,
2882 .fremovexattr_fn
= vfswrap_fremovexattr
,
2883 .setxattr_fn
= vfswrap_setxattr
,
2884 .fsetxattr_fn
= vfswrap_fsetxattr
,
2886 /* aio operations */
2887 .aio_force_fn
= vfswrap_aio_force
,
2889 /* durable handle operations */
2890 .durable_cookie_fn
= vfswrap_durable_cookie
,
2891 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
2892 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
2895 NTSTATUS
vfs_default_init(void);
2896 NTSTATUS
vfs_default_init(void)
2898 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
2899 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);