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"
39 #define DBGC_CLASS DBGC_VFS
41 /* Check for NULL pointer parameters in vfswrap_* functions */
43 /* We don't want to have NULL function pointers lying around. Someone
44 is sure to try and execute them. These stubs are used to prevent
47 static int vfswrap_connect(vfs_handle_struct
*handle
, const char *service
, const char *user
)
49 return 0; /* Return >= 0 for success */
52 static void vfswrap_disconnect(vfs_handle_struct
*handle
)
58 static uint64_t vfswrap_disk_free(vfs_handle_struct
*handle
, const char *path
,
59 uint64_t *bsize
, uint64_t *dfree
,
62 if (sys_fsusage(path
, dfree
, dsize
) != 0) {
70 static int vfswrap_get_quota(struct vfs_handle_struct
*handle
, const char *path
,
71 enum SMB_QUOTA_TYPE qtype
, unid_t id
,
74 #ifdef HAVE_SYS_QUOTAS
77 START_PROFILE(syscall_get_quota
);
78 result
= sys_get_quota(path
, qtype
, id
, qt
);
79 END_PROFILE(syscall_get_quota
);
87 static int vfswrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
89 #ifdef HAVE_SYS_QUOTAS
92 START_PROFILE(syscall_set_quota
);
93 result
= sys_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
94 END_PROFILE(syscall_set_quota
);
102 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
103 struct files_struct
*fsp
,
104 struct shadow_copy_data
*shadow_copy_data
,
108 return -1; /* Not implemented. */
111 static int vfswrap_statvfs(struct vfs_handle_struct
*handle
, const char *path
, vfs_statvfs_struct
*statbuf
)
113 return sys_statvfs(path
, statbuf
);
116 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct
*handle
,
117 enum timestamp_set_resolution
*p_ts_res
)
119 connection_struct
*conn
= handle
->conn
;
120 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
121 struct smb_filename
*smb_fname_cpath
= NULL
;
122 struct vfs_statvfs_struct statbuf
;
125 ZERO_STRUCT(statbuf
);
126 ret
= sys_statvfs(conn
->connectpath
, &statbuf
);
128 caps
= statbuf
.FsCapabilities
;
131 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
133 /* Work out what timestamp resolution we can
134 * use when setting a timestamp. */
136 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
138 if (smb_fname_cpath
== NULL
) {
142 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
144 TALLOC_FREE(smb_fname_cpath
);
148 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
149 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
150 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
151 /* If any of the normal UNIX directory timestamps
152 * have a non-zero tv_nsec component assume
153 * we might be able to set sub-second timestamps.
154 * See what filetime set primitives we have.
156 #if defined(HAVE_UTIMENSAT)
157 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
158 #elif defined(HAVE_UTIMES)
159 /* utimes allows msec timestamps to be set. */
160 *p_ts_res
= TIMESTAMP_SET_MSEC
;
161 #elif defined(HAVE_UTIME)
162 /* utime only allows sec timestamps to be set. */
163 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
166 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
168 "available on share %s, directory %s\n",
169 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
170 lp_servicename(talloc_tos(), conn
->params
->service
),
171 conn
->connectpath
));
173 TALLOC_FREE(smb_fname_cpath
);
177 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
178 struct dfs_GetDFSReferral
*r
)
180 struct junction_map
*junction
= NULL
;
182 bool self_referral
= false;
183 char *pathnamep
= NULL
;
184 char *local_dfs_path
= NULL
;
187 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
190 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
193 /* get the junction entry */
194 if (r
->in
.req
.servername
== NULL
) {
195 return NT_STATUS_NOT_FOUND
;
199 * Trim pathname sent by client so it begins with only one backslash.
200 * Two backslashes confuse some dfs clients
203 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
204 if (local_dfs_path
== NULL
) {
205 return NT_STATUS_NO_MEMORY
;
207 pathnamep
= local_dfs_path
;
208 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
209 IS_DIRECTORY_SEP(pathnamep
[1])) {
213 junction
= talloc_zero(r
, struct junction_map
);
214 if (junction
== NULL
) {
215 return NT_STATUS_NO_MEMORY
;
218 /* The following call can change cwd. */
219 status
= get_referred_path(r
, pathnamep
,
220 handle
->conn
->sconn
->remote_address
,
221 handle
->conn
->sconn
->local_address
,
222 !handle
->conn
->sconn
->using_smb2
,
223 junction
, &consumedcnt
, &self_referral
);
224 if (!NT_STATUS_IS_OK(status
)) {
225 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
228 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
230 if (!self_referral
) {
231 pathnamep
[consumedcnt
] = '\0';
234 dbgtext("Path %s to alternate path(s):",
236 for (i
=0; i
< junction
->referral_count
; i
++) {
238 junction
->referral_list
[i
].alternate_path
);
244 if (r
->in
.req
.max_referral_level
<= 2) {
245 max_referral_level
= 2;
247 if (r
->in
.req
.max_referral_level
>= 3) {
248 max_referral_level
= 3;
251 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
252 if (r
->out
.resp
== NULL
) {
253 return NT_STATUS_NO_MEMORY
;
256 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
257 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
259 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
261 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
264 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
265 struct dfs_referral_type
,
266 r
->out
.resp
->nb_referrals
);
267 if (r
->out
.resp
->referral_entries
== NULL
) {
268 return NT_STATUS_NO_MEMORY
;
271 switch (max_referral_level
) {
273 for(i
=0; i
< junction
->referral_count
; i
++) {
274 struct referral
*ref
= &junction
->referral_list
[i
];
275 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
276 struct dfs_referral_type
*t
=
277 &r
->out
.resp
->referral_entries
[i
];
278 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
281 v2
->size
= VERSION2_REFERRAL_SIZE
;
283 v2
->server_type
= DFS_SERVER_ROOT
;
285 v2
->server_type
= DFS_SERVER_NON_ROOT
;
288 v2
->proximity
= ref
->proximity
;
290 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
291 if (v2
->DFS_path
== NULL
) {
292 return NT_STATUS_NO_MEMORY
;
294 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
295 if (v2
->DFS_alt_path
== NULL
) {
296 return NT_STATUS_NO_MEMORY
;
298 v2
->netw_address
= talloc_strdup(mem_ctx
,
299 ref
->alternate_path
);
300 if (v2
->netw_address
== NULL
) {
301 return NT_STATUS_NO_MEMORY
;
307 for(i
=0; i
< junction
->referral_count
; i
++) {
308 struct referral
*ref
= &junction
->referral_list
[i
];
309 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
310 struct dfs_referral_type
*t
=
311 &r
->out
.resp
->referral_entries
[i
];
312 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
313 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
316 v3
->size
= VERSION3_REFERRAL_SIZE
;
318 v3
->server_type
= DFS_SERVER_ROOT
;
320 v3
->server_type
= DFS_SERVER_NON_ROOT
;
324 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
325 if (r1
->DFS_path
== NULL
) {
326 return NT_STATUS_NO_MEMORY
;
328 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
329 if (r1
->DFS_alt_path
== NULL
) {
330 return NT_STATUS_NO_MEMORY
;
332 r1
->netw_address
= talloc_strdup(mem_ctx
,
333 ref
->alternate_path
);
334 if (r1
->netw_address
== NULL
) {
335 return NT_STATUS_NO_MEMORY
;
340 DEBUG(0,("Invalid dfs referral version: %d\n",
341 max_referral_level
));
342 return NT_STATUS_INVALID_LEVEL
;
346 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
352 static NTSTATUS
vfswrap_snap_check_path(struct vfs_handle_struct
*handle
,
354 const char *service_path
,
357 return NT_STATUS_NOT_SUPPORTED
;
360 static NTSTATUS
vfswrap_snap_create(struct vfs_handle_struct
*handle
,
362 const char *base_volume
,
368 return NT_STATUS_NOT_SUPPORTED
;
371 static NTSTATUS
vfswrap_snap_delete(struct vfs_handle_struct
*handle
,
376 return NT_STATUS_NOT_SUPPORTED
;
379 /* Directory operations */
381 static DIR *vfswrap_opendir(vfs_handle_struct
*handle
,
382 const struct smb_filename
*smb_fname
,
388 START_PROFILE(syscall_opendir
);
389 result
= opendir(smb_fname
->base_name
);
390 END_PROFILE(syscall_opendir
);
394 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
401 START_PROFILE(syscall_fdopendir
);
402 result
= sys_fdopendir(fsp
->fh
->fd
);
403 END_PROFILE(syscall_fdopendir
);
408 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
410 SMB_STRUCT_STAT
*sbuf
)
412 struct dirent
*result
;
414 START_PROFILE(syscall_readdir
);
415 result
= readdir(dirp
);
416 END_PROFILE(syscall_readdir
);
418 /* Default Posix readdir() does not give us stat info.
419 * Set to invalid to indicate we didn't return this info. */
420 SET_STAT_INVALID(*sbuf
);
421 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
422 if (result
!= NULL
) {
423 /* See if we can efficiently return this. */
425 int flags
= AT_SYMLINK_NOFOLLOW
;
426 int ret
= fstatat(dirfd(dirp
),
431 * As this is an optimization,
432 * ignore it if we stat'ed a
433 * symlink. Make the caller
434 * do it again as we don't
435 * know if they wanted the link
436 * info, or its target info.
438 if ((ret
== 0) && (!S_ISLNK(st
.st_mode
))) {
439 init_stat_ex_from_stat(sbuf
,
441 lp_fake_directory_create_times(
442 SNUM(handle
->conn
)));
450 static NTSTATUS
vfswrap_readdir_attr(struct vfs_handle_struct
*handle
,
451 const struct smb_filename
*fname
,
453 struct readdir_attr_data
**attr_data
)
455 return NT_STATUS_NOT_SUPPORTED
;
458 static void vfswrap_seekdir(vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
460 START_PROFILE(syscall_seekdir
);
461 seekdir(dirp
, offset
);
462 END_PROFILE(syscall_seekdir
);
465 static long vfswrap_telldir(vfs_handle_struct
*handle
, DIR *dirp
)
468 START_PROFILE(syscall_telldir
);
469 result
= telldir(dirp
);
470 END_PROFILE(syscall_telldir
);
474 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
476 START_PROFILE(syscall_rewinddir
);
478 END_PROFILE(syscall_rewinddir
);
481 static int vfswrap_mkdir(vfs_handle_struct
*handle
,
482 const struct smb_filename
*smb_fname
,
486 bool has_dacl
= False
;
487 const char *path
= smb_fname
->base_name
;
490 START_PROFILE(syscall_mkdir
);
492 if (lp_inherit_acls(SNUM(handle
->conn
))
493 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
494 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
))) {
495 mode
= (0777 & lp_directory_mask(SNUM(handle
->conn
)));
500 result
= mkdir(path
, mode
);
502 if (result
== 0 && !has_dacl
) {
504 * We need to do this as the default behavior of POSIX ACLs
505 * is to set the mask to be the requested group permission
506 * bits, not the group permission bits to be the requested
507 * group permission bits. This is not what we want, as it will
508 * mess up any inherited ACL bits that were set. JRA.
510 int saved_errno
= errno
; /* We may get ENOSYS */
511 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, smb_fname
, mode
) == -1) &&
517 END_PROFILE(syscall_mkdir
);
521 static int vfswrap_rmdir(vfs_handle_struct
*handle
,
522 const struct smb_filename
*smb_fname
)
526 START_PROFILE(syscall_rmdir
);
527 result
= rmdir(smb_fname
->base_name
);
528 END_PROFILE(syscall_rmdir
);
532 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
536 START_PROFILE(syscall_closedir
);
537 result
= closedir(dirp
);
538 END_PROFILE(syscall_closedir
);
542 static void vfswrap_init_search_op(vfs_handle_struct
*handle
,
545 /* Default behavior is a NOOP */
548 /* File operations */
550 static int vfswrap_open(vfs_handle_struct
*handle
,
551 struct smb_filename
*smb_fname
,
552 files_struct
*fsp
, int flags
, mode_t mode
)
556 START_PROFILE(syscall_open
);
558 if (smb_fname
->stream_name
) {
563 result
= open(smb_fname
->base_name
, flags
, mode
);
565 END_PROFILE(syscall_open
);
569 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
570 struct smb_request
*req
,
571 uint16_t root_dir_fid
,
572 struct smb_filename
*smb_fname
,
573 uint32_t access_mask
,
574 uint32_t share_access
,
575 uint32_t create_disposition
,
576 uint32_t create_options
,
577 uint32_t file_attributes
,
578 uint32_t oplock_request
,
579 struct smb2_lease
*lease
,
580 uint64_t allocation_size
,
581 uint32_t private_flags
,
582 struct security_descriptor
*sd
,
583 struct ea_list
*ea_list
,
584 files_struct
**result
,
586 const struct smb2_create_blobs
*in_context_blobs
,
587 struct smb2_create_blobs
*out_context_blobs
)
589 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
590 access_mask
, share_access
,
591 create_disposition
, create_options
,
592 file_attributes
, oplock_request
, lease
,
593 allocation_size
, private_flags
,
595 pinfo
, in_context_blobs
, out_context_blobs
);
598 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
602 START_PROFILE(syscall_close
);
603 result
= fd_close_posix(fsp
);
604 END_PROFILE(syscall_close
);
608 static ssize_t
vfswrap_read(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
612 START_PROFILE_BYTES(syscall_read
, n
);
613 result
= sys_read(fsp
->fh
->fd
, data
, n
);
614 END_PROFILE_BYTES(syscall_read
);
618 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
619 size_t n
, off_t offset
)
623 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
624 START_PROFILE_BYTES(syscall_pread
, n
);
625 result
= sys_pread(fsp
->fh
->fd
, data
, n
, offset
);
626 END_PROFILE_BYTES(syscall_pread
);
628 if (result
== -1 && errno
== ESPIPE
) {
629 /* Maintain the fiction that pipes can be seeked (sought?) on. */
630 result
= SMB_VFS_READ(fsp
, data
, n
);
634 #else /* HAVE_PREAD */
638 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
639 if (curr
== -1 && errno
== ESPIPE
) {
640 /* Maintain the fiction that pipes can be seeked (sought?) on. */
641 result
= SMB_VFS_READ(fsp
, data
, n
);
646 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
651 result
= SMB_VFS_READ(fsp
, data
, n
);
654 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
657 #endif /* HAVE_PREAD */
662 static ssize_t
vfswrap_write(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
666 START_PROFILE_BYTES(syscall_write
, n
);
667 result
= sys_write(fsp
->fh
->fd
, data
, n
);
668 END_PROFILE_BYTES(syscall_write
);
672 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
673 size_t n
, off_t offset
)
677 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
678 START_PROFILE_BYTES(syscall_pwrite
, n
);
679 result
= sys_pwrite(fsp
->fh
->fd
, data
, n
, offset
);
680 END_PROFILE_BYTES(syscall_pwrite
);
682 if (result
== -1 && errno
== ESPIPE
) {
683 /* Maintain the fiction that pipes can be sought on. */
684 result
= SMB_VFS_WRITE(fsp
, data
, n
);
687 #else /* HAVE_PWRITE */
691 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
696 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
700 result
= SMB_VFS_WRITE(fsp
, data
, n
);
703 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
706 #endif /* HAVE_PWRITE */
711 static int vfswrap_init_pool(struct smbd_server_connection
*conn
)
715 if (conn
->pool
!= NULL
) {
719 ret
= pthreadpool_tevent_init(conn
, lp_aio_max_threads(),
724 struct vfswrap_pread_state
{
732 struct vfs_aio_state vfs_aio_state
;
733 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
736 static void vfs_pread_do(void *private_data
);
737 static void vfs_pread_done(struct tevent_req
*subreq
);
739 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
741 struct tevent_context
*ev
,
742 struct files_struct
*fsp
,
744 size_t n
, off_t offset
)
746 struct tevent_req
*req
, *subreq
;
747 struct vfswrap_pread_state
*state
;
750 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
755 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
756 if (tevent_req_error(req
, ret
)) {
757 return tevent_req_post(req
, ev
);
761 state
->fd
= fsp
->fh
->fd
;
764 state
->offset
= offset
;
766 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
767 state
->profile_bytes
, n
);
768 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
770 subreq
= pthreadpool_tevent_job_send(
771 state
, ev
, handle
->conn
->sconn
->pool
,
772 vfs_pread_do
, state
);
773 if (tevent_req_nomem(subreq
, req
)) {
774 return tevent_req_post(req
, ev
);
776 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
781 static void vfs_pread_do(void *private_data
)
783 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
784 private_data
, struct vfswrap_pread_state
);
785 struct timespec start_time
;
786 struct timespec end_time
;
788 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
790 PROFILE_TIMESTAMP(&start_time
);
793 state
->ret
= pread(state
->fd
, state
->buf
, state
->count
,
795 } while ((state
->ret
== -1) && (errno
== EINTR
));
799 PROFILE_TIMESTAMP(&end_time
);
801 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
803 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
806 static void vfs_pread_done(struct tevent_req
*subreq
)
808 struct tevent_req
*req
= tevent_req_callback_data(
809 subreq
, struct tevent_req
);
811 struct vfswrap_pread_state
*state
= tevent_req_data(
812 req
, struct vfswrap_pread_state
);
816 ret
= pthreadpool_tevent_job_recv(subreq
);
818 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
819 if (tevent_req_error(req
, ret
)) {
823 tevent_req_done(req
);
826 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
827 struct vfs_aio_state
*vfs_aio_state
)
829 struct vfswrap_pread_state
*state
= tevent_req_data(
830 req
, struct vfswrap_pread_state
);
832 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
836 *vfs_aio_state
= state
->vfs_aio_state
;
840 struct vfswrap_pwrite_state
{
848 struct vfs_aio_state vfs_aio_state
;
849 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
852 static void vfs_pwrite_do(void *private_data
);
853 static void vfs_pwrite_done(struct tevent_req
*subreq
);
855 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
857 struct tevent_context
*ev
,
858 struct files_struct
*fsp
,
860 size_t n
, off_t offset
)
862 struct tevent_req
*req
, *subreq
;
863 struct vfswrap_pwrite_state
*state
;
866 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pwrite_state
);
871 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
872 if (tevent_req_error(req
, ret
)) {
873 return tevent_req_post(req
, ev
);
877 state
->fd
= fsp
->fh
->fd
;
880 state
->offset
= offset
;
882 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
883 state
->profile_bytes
, n
);
884 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
886 subreq
= pthreadpool_tevent_job_send(
887 state
, ev
, handle
->conn
->sconn
->pool
,
888 vfs_pwrite_do
, state
);
889 if (tevent_req_nomem(subreq
, req
)) {
890 return tevent_req_post(req
, ev
);
892 tevent_req_set_callback(subreq
, vfs_pwrite_done
, req
);
897 static void vfs_pwrite_do(void *private_data
)
899 struct vfswrap_pwrite_state
*state
= talloc_get_type_abort(
900 private_data
, struct vfswrap_pwrite_state
);
901 struct timespec start_time
;
902 struct timespec end_time
;
904 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
906 PROFILE_TIMESTAMP(&start_time
);
909 state
->ret
= pwrite(state
->fd
, state
->buf
, state
->count
,
911 } while ((state
->ret
== -1) && (errno
== EINTR
));
915 PROFILE_TIMESTAMP(&end_time
);
917 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
919 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
922 static void vfs_pwrite_done(struct tevent_req
*subreq
)
924 struct tevent_req
*req
= tevent_req_callback_data(
925 subreq
, struct tevent_req
);
927 struct vfswrap_pwrite_state
*state
= tevent_req_data(
928 req
, struct vfswrap_pwrite_state
);
932 ret
= pthreadpool_tevent_job_recv(subreq
);
934 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
935 if (tevent_req_error(req
, ret
)) {
939 tevent_req_done(req
);
942 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
943 struct vfs_aio_state
*vfs_aio_state
)
945 struct vfswrap_pwrite_state
*state
= tevent_req_data(
946 req
, struct vfswrap_pwrite_state
);
948 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
952 *vfs_aio_state
= state
->vfs_aio_state
;
956 struct vfswrap_fsync_state
{
961 struct vfs_aio_state vfs_aio_state
;
962 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic
);
965 static void vfs_fsync_do(void *private_data
);
966 static void vfs_fsync_done(struct tevent_req
*subreq
);
968 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
970 struct tevent_context
*ev
,
971 struct files_struct
*fsp
)
973 struct tevent_req
*req
, *subreq
;
974 struct vfswrap_fsync_state
*state
;
977 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
982 ret
= vfswrap_init_pool(handle
->conn
->sconn
);
983 if (tevent_req_error(req
, ret
)) {
984 return tevent_req_post(req
, ev
);
988 state
->fd
= fsp
->fh
->fd
;
990 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync
, profile_p
,
991 state
->profile_basic
);
993 subreq
= pthreadpool_tevent_job_send(
994 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
995 if (tevent_req_nomem(subreq
, req
)) {
996 return tevent_req_post(req
, ev
);
998 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
1003 static void vfs_fsync_do(void *private_data
)
1005 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
1006 private_data
, struct vfswrap_fsync_state
);
1007 struct timespec start_time
;
1008 struct timespec end_time
;
1010 PROFILE_TIMESTAMP(&start_time
);
1013 state
->ret
= fsync(state
->fd
);
1014 } while ((state
->ret
== -1) && (errno
== EINTR
));
1018 PROFILE_TIMESTAMP(&end_time
);
1020 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1023 static void vfs_fsync_done(struct tevent_req
*subreq
)
1025 struct tevent_req
*req
= tevent_req_callback_data(
1026 subreq
, struct tevent_req
);
1028 struct vfswrap_fsync_state
*state
= tevent_req_data(
1029 req
, struct vfswrap_fsync_state
);
1033 ret
= pthreadpool_tevent_job_recv(subreq
);
1034 TALLOC_FREE(subreq
);
1035 SMBPROFILE_BASIC_ASYNC_END(state
->profile_basic
);
1036 if (tevent_req_error(req
, ret
)) {
1040 tevent_req_done(req
);
1043 static int vfswrap_fsync_recv(struct tevent_req
*req
,
1044 struct vfs_aio_state
*vfs_aio_state
)
1046 struct vfswrap_fsync_state
*state
= tevent_req_data(
1047 req
, struct vfswrap_fsync_state
);
1049 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1053 *vfs_aio_state
= state
->vfs_aio_state
;
1057 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1061 START_PROFILE(syscall_lseek
);
1063 /* Cope with 'stat' file opens. */
1064 if (fsp
->fh
->fd
!= -1)
1065 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
1068 * We want to maintain the fiction that we can seek
1069 * on a fifo for file system purposes. This allows
1070 * people to set up UNIX fifo's that feed data to Windows
1071 * applications. JRA.
1074 if((result
== -1) && (errno
== ESPIPE
)) {
1079 END_PROFILE(syscall_lseek
);
1083 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1084 off_t offset
, size_t n
)
1088 START_PROFILE_BYTES(syscall_sendfile
, n
);
1089 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
1090 END_PROFILE_BYTES(syscall_sendfile
);
1094 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1096 files_struct
*tofsp
,
1102 START_PROFILE_BYTES(syscall_recvfile
, n
);
1103 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
1104 END_PROFILE_BYTES(syscall_recvfile
);
1108 static int vfswrap_rename(vfs_handle_struct
*handle
,
1109 const struct smb_filename
*smb_fname_src
,
1110 const struct smb_filename
*smb_fname_dst
)
1114 START_PROFILE(syscall_rename
);
1116 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
1121 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
1124 END_PROFILE(syscall_rename
);
1128 static int vfswrap_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
1133 START_PROFILE(syscall_fsync
);
1134 result
= fsync(fsp
->fh
->fd
);
1135 END_PROFILE(syscall_fsync
);
1142 static int vfswrap_stat(vfs_handle_struct
*handle
,
1143 struct smb_filename
*smb_fname
)
1147 START_PROFILE(syscall_stat
);
1149 if (smb_fname
->stream_name
) {
1154 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1155 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1157 END_PROFILE(syscall_stat
);
1161 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1165 START_PROFILE(syscall_fstat
);
1166 result
= sys_fstat(fsp
->fh
->fd
,
1167 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1168 END_PROFILE(syscall_fstat
);
1172 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1173 struct smb_filename
*smb_fname
)
1177 START_PROFILE(syscall_lstat
);
1179 if (smb_fname
->stream_name
) {
1184 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1185 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1187 END_PROFILE(syscall_lstat
);
1191 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1193 enum vfs_translate_direction direction
,
1194 TALLOC_CTX
*mem_ctx
,
1197 return NT_STATUS_NONE_MAPPED
;
1201 * Implement the default fsctl operation.
1203 static bool vfswrap_logged_ioctl_message
= false;
1205 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1206 struct files_struct
*fsp
,
1209 uint16_t req_flags
, /* Needed for UNICODE ... */
1210 const uint8_t *_in_data
,
1212 uint8_t **_out_data
,
1213 uint32_t max_out_len
,
1216 const char *in_data
= (const char *)_in_data
;
1217 char **out_data
= (char **)_out_data
;
1221 case FSCTL_SET_SPARSE
:
1223 bool set_sparse
= true;
1225 if (in_len
>= 1 && in_data
[0] == 0) {
1229 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1231 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1232 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1233 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1234 nt_errstr(status
)));
1239 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1241 unsigned char objid
[16];
1242 char *return_data
= NULL
;
1244 /* This should return the object-id on this file.
1245 * I think I'll make this be the inode+dev. JRA.
1248 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1249 fsp_fnum_dbg(fsp
)));
1251 *out_len
= MIN(max_out_len
, 64);
1253 /* Hmmm, will this cause problems if less data asked for? */
1254 return_data
= talloc_array(ctx
, char, 64);
1255 if (return_data
== NULL
) {
1256 return NT_STATUS_NO_MEMORY
;
1259 /* For backwards compatibility only store the dev/inode. */
1260 push_file_id_16(return_data
, &fsp
->file_id
);
1261 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1262 push_file_id_16(return_data
+32, &fsp
->file_id
);
1263 memset(return_data
+48, 0, 16);
1264 *out_data
= return_data
;
1265 return NT_STATUS_OK
;
1268 case FSCTL_GET_REPARSE_POINT
:
1270 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1271 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1272 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1273 return NT_STATUS_NOT_A_REPARSE_POINT
;
1276 case FSCTL_SET_REPARSE_POINT
:
1278 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1279 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1280 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1281 return NT_STATUS_NOT_A_REPARSE_POINT
;
1284 case FSCTL_GET_SHADOW_COPY_DATA
:
1287 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1288 * and return their volume names. If max_data_count is 16, then it is just
1289 * asking for the number of volumes and length of the combined names.
1291 * pdata is the data allocated by our caller, but that uses
1292 * total_data_count (which is 0 in our case) rather than max_data_count.
1293 * Allocate the correct amount and return the pointer to let
1294 * it be deallocated when we return.
1296 struct shadow_copy_data
*shadow_data
= NULL
;
1297 bool labels
= False
;
1298 uint32_t labels_data_count
= 0;
1300 char *cur_pdata
= NULL
;
1302 if (max_out_len
< 16) {
1303 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1305 return NT_STATUS_INVALID_PARAMETER
;
1308 if (max_out_len
> 16) {
1312 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1313 if (shadow_data
== NULL
) {
1314 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1315 return NT_STATUS_NO_MEMORY
;
1319 * Call the VFS routine to actually do the work.
1321 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1324 /* broken module didn't set errno on error */
1325 status
= NT_STATUS_UNSUCCESSFUL
;
1327 status
= map_nt_error_from_unix(errno
);
1328 if (NT_STATUS_EQUAL(status
,
1329 NT_STATUS_NOT_SUPPORTED
)) {
1333 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1334 "connectpath %s, failed - %s.\n",
1335 fsp
->conn
->connectpath
,
1336 nt_errstr(status
)));
1337 TALLOC_FREE(shadow_data
);
1341 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1342 sizeof(SHADOW_COPY_LABEL
)) + 2;
1347 *out_len
= 12 + labels_data_count
;
1350 if (max_out_len
< *out_len
) {
1351 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1352 max_out_len
, *out_len
));
1353 TALLOC_FREE(shadow_data
);
1354 return NT_STATUS_BUFFER_TOO_SMALL
;
1357 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1358 if (cur_pdata
== NULL
) {
1359 TALLOC_FREE(shadow_data
);
1360 return NT_STATUS_NO_MEMORY
;
1363 *out_data
= cur_pdata
;
1365 /* num_volumes 4 bytes */
1366 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1369 /* num_labels 4 bytes */
1370 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1373 /* needed_data_count 4 bytes */
1374 SIVAL(cur_pdata
, 8, labels_data_count
);
1378 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1379 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1380 if (labels
&& shadow_data
->labels
) {
1381 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1383 status
= srvstr_push(cur_pdata
, req_flags
,
1384 cur_pdata
, shadow_data
->labels
[i
],
1385 2 * sizeof(SHADOW_COPY_LABEL
),
1386 STR_UNICODE
|STR_TERMINATE
, &len
);
1387 if (!NT_STATUS_IS_OK(status
)) {
1388 TALLOC_FREE(*out_data
);
1389 TALLOC_FREE(shadow_data
);
1392 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1393 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1397 TALLOC_FREE(shadow_data
);
1399 return NT_STATUS_OK
;
1402 case FSCTL_FIND_FILES_BY_SID
:
1404 /* pretend this succeeded -
1406 * we have to send back a list with all files owned by this SID
1408 * but I have to check that --metze
1414 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1415 fsp_fnum_dbg(fsp
)));
1418 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1419 return NT_STATUS_INVALID_PARAMETER
;
1422 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1424 /* unknown 4 bytes: this is not the length of the sid :-( */
1425 /*unknown = IVAL(pdata,0);*/
1427 if (!sid_parse(_in_data
+ 4, sid_len
, &sid
)) {
1428 return NT_STATUS_INVALID_PARAMETER
;
1430 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
1432 if (!sid_to_uid(&sid
, &uid
)) {
1433 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1434 sid_string_dbg(&sid
),
1435 (unsigned long)sid_len
));
1439 /* we can take a look at the find source :-)
1441 * find ./ -uid $uid -name '*' is what we need here
1444 * and send 4bytes len and then NULL terminated unicode strings
1447 * but I don't know how to deal with the paged results
1448 * (maybe we can hang the result anywhere in the fsp struct)
1450 * but I don't know how to deal with the paged results
1451 * (maybe we can hang the result anywhere in the fsp struct)
1453 * we don't send all files at once
1454 * and at the next we should *not* start from the beginning,
1455 * so we have to cache the result
1460 /* this works for now... */
1461 return NT_STATUS_OK
;
1464 case FSCTL_QUERY_ALLOCATED_RANGES
:
1466 /* FIXME: This is just a dummy reply, telling that all of the
1467 * file is allocated. MKS cp needs that.
1468 * Adding the real allocated ranges via FIEMAP on Linux
1469 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1470 * this FSCTL correct for sparse files.
1472 uint64_t offset
, length
;
1473 char *out_data_tmp
= NULL
;
1476 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1478 return NT_STATUS_INVALID_PARAMETER
;
1481 if (max_out_len
< 16) {
1482 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1484 return NT_STATUS_INVALID_PARAMETER
;
1487 offset
= BVAL(in_data
,0);
1488 length
= BVAL(in_data
,8);
1490 if (offset
+ length
< offset
) {
1491 /* No 64-bit integer wrap. */
1492 return NT_STATUS_INVALID_PARAMETER
;
1495 /* Shouldn't this be SMB_VFS_STAT ... ? */
1496 status
= vfs_stat_fsp(fsp
);
1497 if (!NT_STATUS_IS_OK(status
)) {
1502 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1503 if (out_data_tmp
== NULL
) {
1504 DEBUG(10, ("unable to allocate memory for response\n"));
1505 return NT_STATUS_NO_MEMORY
;
1508 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1509 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1511 memset(out_data_tmp
, 0, *out_len
);
1513 uint64_t end
= offset
+ length
;
1514 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1515 SBVAL(out_data_tmp
, 0, 0);
1516 SBVAL(out_data_tmp
, 8, end
);
1519 *out_data
= out_data_tmp
;
1521 return NT_STATUS_OK
;
1524 case FSCTL_IS_VOLUME_DIRTY
:
1526 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1527 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1529 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1530 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1532 return NT_STATUS_INVALID_PARAMETER
;
1537 * Only print once ... unfortunately there could be lots of
1538 * different FSCTLs that are called.
1540 if (!vfswrap_logged_ioctl_message
) {
1541 vfswrap_logged_ioctl_message
= true;
1542 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1543 __func__
, function
));
1547 return NT_STATUS_NOT_SUPPORTED
;
1550 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
1551 const struct smb_filename
*fname
,
1552 SMB_STRUCT_STAT
*sbuf
);
1554 static NTSTATUS
vfswrap_get_dos_attributes(struct vfs_handle_struct
*handle
,
1555 struct smb_filename
*smb_fname
,
1560 offline
= vfswrap_is_offline(handle
, smb_fname
, &smb_fname
->st
);
1562 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1565 return get_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1568 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1569 struct files_struct
*fsp
,
1574 offline
= vfswrap_is_offline(handle
, fsp
->fsp_name
, &fsp
->fsp_name
->st
);
1576 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1579 return get_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1582 static NTSTATUS
vfswrap_set_dos_attributes(struct vfs_handle_struct
*handle
,
1583 const struct smb_filename
*smb_fname
,
1586 return set_ea_dos_attribute(handle
->conn
, smb_fname
, dosmode
);
1589 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1590 struct files_struct
*fsp
,
1593 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
1596 struct vfs_cc_state
{
1597 struct tevent_context
*ev
;
1599 bool read_lck_locked
;
1600 struct lock_struct read_lck
;
1601 bool write_lck_locked
;
1602 struct lock_struct write_lck
;
1603 struct files_struct
*src_fsp
;
1605 struct files_struct
*dst_fsp
;
1609 size_t next_io_size
;
1613 static NTSTATUS
copy_chunk_loop(struct tevent_req
*req
);
1615 static struct tevent_req
*vfswrap_copy_chunk_send(struct vfs_handle_struct
*handle
,
1616 TALLOC_CTX
*mem_ctx
,
1617 struct tevent_context
*ev
,
1618 struct files_struct
*src_fsp
,
1620 struct files_struct
*dest_fsp
,
1625 struct tevent_req
*req
;
1626 struct vfs_cc_state
*state
= NULL
;
1627 size_t num
= MIN(to_copy
, COPYCHUNK_MAX_TOTAL_LEN
);
1630 DBG_DEBUG("server side copy chunk of length %" PRIu64
"\n", to_copy
);
1632 req
= tevent_req_create(mem_ctx
, &state
, struct vfs_cc_state
);
1637 if (flags
& ~VFS_COPY_CHUNK_FL_MASK_ALL
) {
1638 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1639 return tevent_req_post(req
, ev
);
1642 if (flags
& VFS_COPY_CHUNK_FL_MUST_CLONE
) {
1643 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1644 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1645 return tevent_req_post(req
, ev
);
1648 *state
= (struct vfs_cc_state
) {
1652 .dst_fsp
= dest_fsp
,
1653 .dst_off
= dest_off
,
1655 .remaining
= to_copy
,
1658 state
->buf
= talloc_array(state
, uint8_t, num
);
1659 if (tevent_req_nomem(state
->buf
, req
)) {
1660 return tevent_req_post(req
, ev
);
1663 status
= vfs_stat_fsp(src_fsp
);
1664 if (tevent_req_nterror(req
, status
)) {
1665 return tevent_req_post(req
, ev
);
1668 if (src_fsp
->fsp_name
->st
.st_ex_size
< src_off
+ num
) {
1670 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1671 * If the SourceOffset or SourceOffset + Length extends beyond
1672 * the end of file, the server SHOULD<240> treat this as a
1673 * STATUS_END_OF_FILE error.
1675 * <240> Section 3.3.5.15.6: Windows servers will return
1676 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1678 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
1679 return tevent_req_post(req
, ev
);
1682 if (src_fsp
->op
== NULL
) {
1683 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1684 return tevent_req_post(req
, ev
);
1687 if (dest_fsp
->op
== NULL
) {
1688 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1689 return tevent_req_post(req
, ev
);
1692 status
= copy_chunk_loop(req
);
1693 if (!NT_STATUS_IS_OK(status
)) {
1694 tevent_req_nterror(req
, status
);
1695 return tevent_req_post(req
, ev
);
1701 static void vfswrap_copy_chunk_read_done(struct tevent_req
*subreq
);
1703 static NTSTATUS
copy_chunk_loop(struct tevent_req
*req
)
1705 struct vfs_cc_state
*state
= tevent_req_data(req
, struct vfs_cc_state
);
1706 struct tevent_req
*subreq
= NULL
;
1709 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
1711 if (!(state
->flags
& VFS_COPY_CHUNK_FL_IGNORE_LOCKS
)) {
1712 init_strict_lock_struct(state
->src_fsp
,
1713 state
->src_fsp
->op
->global
->open_persistent_id
,
1715 state
->next_io_size
,
1719 ok
= SMB_VFS_STRICT_LOCK(state
->src_fsp
->conn
,
1723 return NT_STATUS_FILE_LOCK_CONFLICT
;
1727 subreq
= SMB_VFS_PREAD_SEND(state
,
1728 state
->src_fsp
->conn
->sconn
->ev_ctx
,
1731 state
->next_io_size
,
1733 if (subreq
== NULL
) {
1734 return NT_STATUS_NO_MEMORY
;
1736 tevent_req_set_callback(subreq
, vfswrap_copy_chunk_read_done
, req
);
1738 return NT_STATUS_OK
;
1741 static void vfswrap_copy_chunk_write_done(struct tevent_req
*subreq
);
1743 static void vfswrap_copy_chunk_read_done(struct tevent_req
*subreq
)
1745 struct tevent_req
*req
= tevent_req_callback_data(
1746 subreq
, struct tevent_req
);
1747 struct vfs_cc_state
*state
= tevent_req_data(req
, struct vfs_cc_state
);
1748 struct vfs_aio_state aio_state
;
1752 if (!(state
->flags
& VFS_COPY_CHUNK_FL_IGNORE_LOCKS
)) {
1753 SMB_VFS_STRICT_UNLOCK(state
->src_fsp
->conn
,
1756 ZERO_STRUCT(state
->read_lck
);
1759 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
1760 TALLOC_FREE(subreq
);
1762 DBG_ERR("read failed: %s\n", strerror(errno
));
1763 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1766 if (nread
!= state
->next_io_size
) {
1767 DBG_ERR("Short read, only %zd of %zu\n",
1768 nread
, state
->next_io_size
);
1769 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1773 state
->src_off
+= nread
;
1775 if (!(state
->flags
& VFS_COPY_CHUNK_FL_IGNORE_LOCKS
)) {
1776 init_strict_lock_struct(state
->dst_fsp
,
1777 state
->dst_fsp
->op
->global
->open_persistent_id
,
1779 state
->next_io_size
,
1783 ok
= SMB_VFS_STRICT_LOCK(state
->dst_fsp
->conn
,
1787 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1792 subreq
= SMB_VFS_PWRITE_SEND(state
,
1796 state
->next_io_size
,
1798 if (subreq
== NULL
) {
1799 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1802 tevent_req_set_callback(subreq
, vfswrap_copy_chunk_write_done
, req
);
1805 static void vfswrap_copy_chunk_write_done(struct tevent_req
*subreq
)
1807 struct tevent_req
*req
= tevent_req_callback_data(
1808 subreq
, struct tevent_req
);
1809 struct vfs_cc_state
*state
= tevent_req_data(req
, struct vfs_cc_state
);
1810 struct vfs_aio_state aio_state
;
1814 if (!(state
->flags
& VFS_COPY_CHUNK_FL_IGNORE_LOCKS
)) {
1815 SMB_VFS_STRICT_UNLOCK(state
->dst_fsp
->conn
,
1818 ZERO_STRUCT(state
->write_lck
);
1821 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
1822 TALLOC_FREE(subreq
);
1823 if (nwritten
== -1) {
1824 DBG_ERR("write failed: %s\n", strerror(errno
));
1825 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
1828 if (nwritten
!= state
->next_io_size
) {
1829 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
1830 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1834 state
->dst_off
+= nwritten
;
1836 if (state
->remaining
< nwritten
) {
1837 /* Paranoia check */
1838 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1841 state
->remaining
-= nwritten
;
1842 if (state
->remaining
== 0) {
1843 tevent_req_done(req
);
1847 status
= copy_chunk_loop(req
);
1848 if (!NT_STATUS_IS_OK(status
)) {
1849 tevent_req_nterror(req
, status
);
1856 static NTSTATUS
vfswrap_copy_chunk_recv(struct vfs_handle_struct
*handle
,
1857 struct tevent_req
*req
,
1860 struct vfs_cc_state
*state
= tevent_req_data(req
, struct vfs_cc_state
);
1863 if (tevent_req_is_nterror(req
, &status
)) {
1864 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
1866 tevent_req_received(req
);
1870 *copied
= state
->to_copy
;
1871 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
1872 tevent_req_received(req
);
1874 return NT_STATUS_OK
;
1877 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
1878 TALLOC_CTX
*mem_ctx
,
1879 struct files_struct
*fsp
,
1880 struct smb_filename
*smb_fname
,
1881 uint16_t *_compression_fmt
)
1883 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1886 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
1887 TALLOC_CTX
*mem_ctx
,
1888 struct files_struct
*fsp
,
1889 uint16_t compression_fmt
)
1891 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1894 /********************************************************************
1895 Given a stat buffer return the allocated size on disk, taking into
1896 account sparse files.
1897 ********************************************************************/
1898 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
1899 struct files_struct
*fsp
,
1900 const SMB_STRUCT_STAT
*sbuf
)
1904 START_PROFILE(syscall_get_alloc_size
);
1906 if(S_ISDIR(sbuf
->st_ex_mode
)) {
1911 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1912 /* The type of st_blocksize is blkcnt_t which *MUST* be
1913 signed (according to POSIX) and can be less than 64-bits.
1914 Ensure when we're converting to 64 bits wide we don't
1916 #if defined(SIZEOF_BLKCNT_T_8)
1917 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
1918 #elif defined(SIZEOF_BLKCNT_T_4)
1920 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
1921 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
1924 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1928 * Some file systems do not allocate a block for very
1929 * small files. But for non-empty file should report a
1933 uint64_t filesize
= get_file_size_stat(sbuf
);
1935 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
1939 result
= get_file_size_stat(sbuf
);
1942 if (fsp
&& fsp
->initial_allocation_size
)
1943 result
= MAX(result
,fsp
->initial_allocation_size
);
1945 result
= smb_roundup(handle
->conn
, result
);
1948 END_PROFILE(syscall_get_alloc_size
);
1952 static int vfswrap_unlink(vfs_handle_struct
*handle
,
1953 const struct smb_filename
*smb_fname
)
1957 START_PROFILE(syscall_unlink
);
1959 if (smb_fname
->stream_name
) {
1963 result
= unlink(smb_fname
->base_name
);
1966 END_PROFILE(syscall_unlink
);
1970 static int vfswrap_chmod(vfs_handle_struct
*handle
,
1971 const struct smb_filename
*smb_fname
,
1976 START_PROFILE(syscall_chmod
);
1979 * We need to do this due to the fact that the default POSIX ACL
1980 * chmod modifies the ACL *mask* for the group owner, not the
1981 * group owner bits directly. JRA.
1986 int saved_errno
= errno
; /* We might get ENOSYS */
1987 result
= SMB_VFS_CHMOD_ACL(handle
->conn
,
1991 END_PROFILE(syscall_chmod
);
1994 /* Error - return the old errno. */
1995 errno
= saved_errno
;
1998 result
= chmod(smb_fname
->base_name
, mode
);
1999 END_PROFILE(syscall_chmod
);
2003 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2007 START_PROFILE(syscall_fchmod
);
2010 * We need to do this due to the fact that the default POSIX ACL
2011 * chmod modifies the ACL *mask* for the group owner, not the
2012 * group owner bits directly. JRA.
2016 int saved_errno
= errno
; /* We might get ENOSYS */
2017 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
2018 END_PROFILE(syscall_fchmod
);
2021 /* Error - return the old errno. */
2022 errno
= saved_errno
;
2025 #if defined(HAVE_FCHMOD)
2026 result
= fchmod(fsp
->fh
->fd
, mode
);
2032 END_PROFILE(syscall_fchmod
);
2036 static int vfswrap_chown(vfs_handle_struct
*handle
,
2037 const struct smb_filename
*smb_fname
,
2043 START_PROFILE(syscall_chown
);
2044 result
= chown(smb_fname
->base_name
, uid
, gid
);
2045 END_PROFILE(syscall_chown
);
2049 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2054 START_PROFILE(syscall_fchown
);
2055 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
2056 END_PROFILE(syscall_fchown
);
2064 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2065 const struct smb_filename
*smb_fname
,
2071 START_PROFILE(syscall_lchown
);
2072 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2073 END_PROFILE(syscall_lchown
);
2077 static int vfswrap_chdir(vfs_handle_struct
*handle
, const char *path
)
2081 START_PROFILE(syscall_chdir
);
2082 result
= chdir(path
);
2083 END_PROFILE(syscall_chdir
);
2087 static char *vfswrap_getwd(vfs_handle_struct
*handle
)
2091 START_PROFILE(syscall_getwd
);
2092 result
= sys_getwd();
2093 END_PROFILE(syscall_getwd
);
2097 /*********************************************************************
2098 nsec timestamp resolution call. Convert down to whatever the underlying
2099 system will support.
2100 **********************************************************************/
2102 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
2103 const struct smb_filename
*smb_fname
,
2104 struct smb_file_time
*ft
)
2108 START_PROFILE(syscall_ntimes
);
2110 if (smb_fname
->stream_name
) {
2116 if (null_timespec(ft
->atime
)) {
2117 ft
->atime
= smb_fname
->st
.st_ex_atime
;
2120 if (null_timespec(ft
->mtime
)) {
2121 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
2124 if (!null_timespec(ft
->create_time
)) {
2125 set_create_timespec_ea(handle
->conn
,
2130 if ((timespec_compare(&ft
->atime
,
2131 &smb_fname
->st
.st_ex_atime
) == 0) &&
2132 (timespec_compare(&ft
->mtime
,
2133 &smb_fname
->st
.st_ex_mtime
) == 0)) {
2138 #if defined(HAVE_UTIMENSAT)
2140 struct timespec ts
[2];
2143 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
2145 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
2147 if (!((result
== -1) && (errno
== ENOSYS
))) {
2151 #if defined(HAVE_UTIMES)
2153 struct timeval tv
[2];
2154 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
2155 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
2156 result
= utimes(smb_fname
->base_name
, tv
);
2158 result
= utimes(smb_fname
->base_name
, NULL
);
2160 if (!((result
== -1) && (errno
== ENOSYS
))) {
2164 #if defined(HAVE_UTIME)
2166 struct utimbuf times
;
2167 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
2168 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
2169 result
= utime(smb_fname
->base_name
, ×
);
2171 result
= utime(smb_fname
->base_name
, NULL
);
2173 if (!((result
== -1) && (errno
== ENOSYS
))) {
2181 END_PROFILE(syscall_ntimes
);
2185 /*********************************************************************
2186 A version of ftruncate that will write the space on disk if strict
2188 **********************************************************************/
2190 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2192 off_t space_to_write
;
2193 uint64_t space_avail
;
2194 uint64_t bsize
,dfree
,dsize
;
2197 SMB_STRUCT_STAT
*pst
;
2199 status
= vfs_stat_fsp(fsp
);
2200 if (!NT_STATUS_IS_OK(status
)) {
2203 pst
= &fsp
->fsp_name
->st
;
2206 if (S_ISFIFO(pst
->st_ex_mode
))
2210 if (pst
->st_ex_size
== len
)
2213 /* Shrink - just ftruncate. */
2214 if (pst
->st_ex_size
> len
)
2215 return ftruncate(fsp
->fh
->fd
, len
);
2217 space_to_write
= len
- pst
->st_ex_size
;
2219 /* for allocation try fallocate first. This can fail on some
2220 platforms e.g. when the filesystem doesn't support it and no
2221 emulation is being done by the libc (like on AIX with JFS1). In that
2222 case we do our own emulation. fallocate implementations can
2223 return ENOTSUP or EINVAL in cases like that. */
2224 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2225 if (ret
== -1 && errno
== ENOSPC
) {
2231 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2232 "error %d. Falling back to slow manual allocation\n", errno
));
2234 /* available disk space is enough or not? */
2236 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2237 /* space_avail is 1k blocks */
2238 if (space_avail
== (uint64_t)-1 ||
2239 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2244 /* Write out the real space on disk. */
2245 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2253 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2256 SMB_STRUCT_STAT
*pst
;
2260 START_PROFILE(syscall_ftruncate
);
2262 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
2263 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2264 END_PROFILE(syscall_ftruncate
);
2268 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2269 ftruncate if the system supports it. Then I discovered that
2270 you can have some filesystems that support ftruncate
2271 expansion and some that don't! On Linux fat can't do
2272 ftruncate extend but ext2 can. */
2274 result
= ftruncate(fsp
->fh
->fd
, len
);
2276 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2277 extend a file with ftruncate. Provide alternate implementation
2280 /* Do an fstat to see if the file is longer than the requested
2281 size in which case the ftruncate above should have
2282 succeeded or shorter, in which case seek to len - 1 and
2283 write 1 byte of zero */
2284 status
= vfs_stat_fsp(fsp
);
2285 if (!NT_STATUS_IS_OK(status
)) {
2289 /* We need to update the files_struct after successful ftruncate */
2294 pst
= &fsp
->fsp_name
->st
;
2297 if (S_ISFIFO(pst
->st_ex_mode
)) {
2303 if (pst
->st_ex_size
== len
) {
2308 if (pst
->st_ex_size
> len
) {
2309 /* the ftruncate should have worked */
2313 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
2321 END_PROFILE(syscall_ftruncate
);
2325 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
2333 START_PROFILE(syscall_fallocate
);
2335 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
2337 * posix_fallocate returns 0 on success, errno on error
2338 * and doesn't set errno. Make it behave like fallocate()
2339 * which returns -1, and sets errno on failure.
2346 /* sys_fallocate handles filtering of unsupported mode flags */
2347 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
2349 END_PROFILE(syscall_fallocate
);
2353 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
2357 START_PROFILE(syscall_fcntl_lock
);
2359 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2361 "force process locks",
2363 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2366 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
2367 END_PROFILE(syscall_fcntl_lock
);
2371 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2372 uint32_t share_mode
, uint32_t access_mask
)
2374 START_PROFILE(syscall_kernel_flock
);
2375 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
2376 END_PROFILE(syscall_kernel_flock
);
2380 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2385 START_PROFILE(syscall_fcntl_getlock
);
2387 if (fsp
->use_ofd_locks
|| !lp_parm_bool(SNUM(fsp
->conn
),
2389 "force process locks",
2391 op
= map_process_lock_to_ofd_lock(op
, &fsp
->use_ofd_locks
);
2394 result
= fcntl_getlock(fsp
->fh
->fd
, op
, poffset
, pcount
, ptype
, ppid
);
2395 END_PROFILE(syscall_fcntl_getlock
);
2399 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2404 START_PROFILE(syscall_linux_setlease
);
2406 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2407 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2411 END_PROFILE(syscall_linux_setlease
);
2415 static int vfswrap_symlink(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2419 START_PROFILE(syscall_symlink
);
2420 result
= symlink(oldpath
, newpath
);
2421 END_PROFILE(syscall_symlink
);
2425 static int vfswrap_readlink(vfs_handle_struct
*handle
, const char *path
, char *buf
, size_t bufsiz
)
2429 START_PROFILE(syscall_readlink
);
2430 result
= readlink(path
, buf
, bufsiz
);
2431 END_PROFILE(syscall_readlink
);
2435 static int vfswrap_link(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2439 START_PROFILE(syscall_link
);
2440 result
= link(oldpath
, newpath
);
2441 END_PROFILE(syscall_link
);
2445 static int vfswrap_mknod(vfs_handle_struct
*handle
,
2446 const struct smb_filename
*smb_fname
,
2452 START_PROFILE(syscall_mknod
);
2453 result
= sys_mknod(smb_fname
->base_name
, mode
, dev
);
2454 END_PROFILE(syscall_mknod
);
2458 static char *vfswrap_realpath(vfs_handle_struct
*handle
, const char *path
)
2462 START_PROFILE(syscall_realpath
);
2463 result
= sys_realpath(path
);
2464 END_PROFILE(syscall_realpath
);
2468 static int vfswrap_chflags(vfs_handle_struct
*handle
, const char *path
,
2472 return chflags(path
, flags
);
2479 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2480 const SMB_STRUCT_STAT
*sbuf
)
2484 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2488 key
.devid
= sbuf
->st_ex_dev
;
2489 key
.inode
= sbuf
->st_ex_ino
;
2490 /* key.extid is unused by default. */
2495 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
2496 struct files_struct
*fsp
,
2497 const struct smb_filename
*smb_fname
,
2498 TALLOC_CTX
*mem_ctx
,
2499 unsigned int *pnum_streams
,
2500 struct stream_struct
**pstreams
)
2502 SMB_STRUCT_STAT sbuf
;
2503 struct stream_struct
*tmp_streams
= NULL
;
2506 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
2508 * No default streams on directories
2513 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
2514 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
2517 struct smb_filename smb_fname_cp
;
2519 ZERO_STRUCT(smb_fname_cp
);
2520 smb_fname_cp
.base_name
= discard_const_p(char,
2521 smb_fname
->base_name
);
2522 smb_fname_cp
.flags
= smb_fname
->flags
;
2524 if (smb_fname_cp
.flags
& SMB_FILENAME_POSIX_PATH
) {
2525 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname_cp
);
2527 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname_cp
);
2529 sbuf
= smb_fname_cp
.st
;
2533 return map_nt_error_from_unix(errno
);
2536 if (S_ISDIR(sbuf
.st_ex_mode
)) {
2540 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
2541 (*pnum_streams
) + 1);
2542 if (tmp_streams
== NULL
) {
2543 return NT_STATUS_NO_MEMORY
;
2545 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
2546 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
2547 return NT_STATUS_NO_MEMORY
;
2549 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
2550 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
2553 *pstreams
= tmp_streams
;
2555 return NT_STATUS_OK
;
2558 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
2561 TALLOC_CTX
*mem_ctx
,
2565 * Don't fall back to get_real_filename so callers can differentiate
2566 * between a full directory scan and an actual case-insensitive stat.
2572 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
2575 return handle
->conn
->connectpath
;
2578 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
2579 struct byte_range_lock
*br_lck
,
2580 struct lock_struct
*plock
,
2583 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2585 /* Note: blr is not used in the default implementation. */
2586 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
2589 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
2590 struct messaging_context
*msg_ctx
,
2591 struct byte_range_lock
*br_lck
,
2592 const struct lock_struct
*plock
)
2594 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2596 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
2599 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
2600 struct byte_range_lock
*br_lck
,
2601 struct lock_struct
*plock
)
2603 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2605 /* Note: blr is not used in the default implementation. */
2606 return brl_lock_cancel_default(br_lck
, plock
);
2609 static bool vfswrap_strict_lock(struct vfs_handle_struct
*handle
,
2611 struct lock_struct
*plock
)
2613 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2614 plock
->lock_type
== WRITE_LOCK
);
2616 return strict_lock_default(fsp
, plock
);
2619 static void vfswrap_strict_unlock(struct vfs_handle_struct
*handle
,
2621 struct lock_struct
*plock
)
2623 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2624 plock
->lock_type
== WRITE_LOCK
);
2626 strict_unlock_default(fsp
, plock
);
2629 /* NT ACL operations. */
2631 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
2633 uint32_t security_info
,
2634 TALLOC_CTX
*mem_ctx
,
2635 struct security_descriptor
**ppdesc
)
2639 START_PROFILE(fget_nt_acl
);
2640 result
= posix_fget_nt_acl(fsp
, security_info
,
2642 END_PROFILE(fget_nt_acl
);
2646 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
2647 const struct smb_filename
*smb_fname
,
2648 uint32_t security_info
,
2649 TALLOC_CTX
*mem_ctx
,
2650 struct security_descriptor
**ppdesc
)
2654 START_PROFILE(get_nt_acl
);
2655 result
= posix_get_nt_acl(handle
->conn
,
2660 END_PROFILE(get_nt_acl
);
2664 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
2668 START_PROFILE(fset_nt_acl
);
2669 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
2670 END_PROFILE(fset_nt_acl
);
2674 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
2675 struct smb_filename
*file
,
2676 struct security_acl
*sacl
,
2677 uint32_t access_requested
,
2678 uint32_t access_denied
)
2680 return NT_STATUS_OK
; /* Nothing to do here ... */
2683 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
,
2684 const struct smb_filename
*smb_fname
,
2693 START_PROFILE(chmod_acl
);
2694 result
= chmod_acl(handle
->conn
, smb_fname
, mode
);
2695 END_PROFILE(chmod_acl
);
2700 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2708 START_PROFILE(fchmod_acl
);
2709 result
= fchmod_acl(fsp
, mode
);
2710 END_PROFILE(fchmod_acl
);
2715 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
2716 const struct smb_filename
*smb_fname
,
2717 SMB_ACL_TYPE_T type
,
2718 TALLOC_CTX
*mem_ctx
)
2720 return sys_acl_get_file(handle
, smb_fname
, type
, mem_ctx
);
2723 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
2725 TALLOC_CTX
*mem_ctx
)
2727 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
2730 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
,
2731 const struct smb_filename
*smb_fname
,
2732 SMB_ACL_TYPE_T acltype
,
2735 return sys_acl_set_file(handle
, smb_fname
, acltype
, theacl
);
2738 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2740 return sys_acl_set_fd(handle
, fsp
, theacl
);
2743 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
,
2744 const struct smb_filename
*smb_fname
)
2746 return sys_acl_delete_def_file(handle
, smb_fname
);
2749 /****************************************************************
2750 Extended attribute operations.
2751 *****************************************************************/
2753 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,
2754 const struct smb_filename
*smb_fname
,
2759 return getxattr(smb_fname
->base_name
, name
, value
, size
);
2762 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2764 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2767 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
,
2768 const struct smb_filename
*smb_fname
,
2772 return listxattr(smb_fname
->base_name
, list
, size
);
2775 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2777 return flistxattr(fsp
->fh
->fd
, list
, size
);
2780 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
,
2781 const struct smb_filename
*smb_fname
,
2784 return removexattr(smb_fname
->base_name
, name
);
2787 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2789 return fremovexattr(fsp
->fh
->fd
, name
);
2792 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
,
2793 const struct smb_filename
*smb_fname
,
2799 return setxattr(smb_fname
->base_name
, name
, value
, size
, flags
);
2802 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2804 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2807 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2812 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2813 const struct smb_filename
*fname
,
2814 SMB_STRUCT_STAT
*sbuf
)
2818 bool offline
= false;
2820 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2824 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2825 #if defined(ENOTSUP)
2831 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2832 if (!NT_STATUS_IS_OK(status
)) {
2833 errno
= map_errno_from_nt_status(status
);
2837 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2844 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
2845 struct files_struct
*fsp
,
2846 TALLOC_CTX
*mem_ctx
,
2849 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
2852 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
2853 struct files_struct
*fsp
,
2854 const DATA_BLOB old_cookie
,
2855 TALLOC_CTX
*mem_ctx
,
2856 DATA_BLOB
*new_cookie
)
2858 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
2862 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
2863 struct smb_request
*smb1req
,
2864 struct smbXsrv_open
*op
,
2865 const DATA_BLOB old_cookie
,
2866 TALLOC_CTX
*mem_ctx
,
2867 struct files_struct
**fsp
,
2868 DATA_BLOB
*new_cookie
)
2870 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
2871 old_cookie
, mem_ctx
,
2875 static struct vfs_fn_pointers vfs_default_fns
= {
2876 /* Disk operations */
2878 .connect_fn
= vfswrap_connect
,
2879 .disconnect_fn
= vfswrap_disconnect
,
2880 .disk_free_fn
= vfswrap_disk_free
,
2881 .get_quota_fn
= vfswrap_get_quota
,
2882 .set_quota_fn
= vfswrap_set_quota
,
2883 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
2884 .statvfs_fn
= vfswrap_statvfs
,
2885 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
2886 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
2887 .snap_check_path_fn
= vfswrap_snap_check_path
,
2888 .snap_create_fn
= vfswrap_snap_create
,
2889 .snap_delete_fn
= vfswrap_snap_delete
,
2891 /* Directory operations */
2893 .opendir_fn
= vfswrap_opendir
,
2894 .fdopendir_fn
= vfswrap_fdopendir
,
2895 .readdir_fn
= vfswrap_readdir
,
2896 .readdir_attr_fn
= vfswrap_readdir_attr
,
2897 .seekdir_fn
= vfswrap_seekdir
,
2898 .telldir_fn
= vfswrap_telldir
,
2899 .rewind_dir_fn
= vfswrap_rewinddir
,
2900 .mkdir_fn
= vfswrap_mkdir
,
2901 .rmdir_fn
= vfswrap_rmdir
,
2902 .closedir_fn
= vfswrap_closedir
,
2903 .init_search_op_fn
= vfswrap_init_search_op
,
2905 /* File operations */
2907 .open_fn
= vfswrap_open
,
2908 .create_file_fn
= vfswrap_create_file
,
2909 .close_fn
= vfswrap_close
,
2910 .read_fn
= vfswrap_read
,
2911 .pread_fn
= vfswrap_pread
,
2912 .pread_send_fn
= vfswrap_pread_send
,
2913 .pread_recv_fn
= vfswrap_pread_recv
,
2914 .write_fn
= vfswrap_write
,
2915 .pwrite_fn
= vfswrap_pwrite
,
2916 .pwrite_send_fn
= vfswrap_pwrite_send
,
2917 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
2918 .lseek_fn
= vfswrap_lseek
,
2919 .sendfile_fn
= vfswrap_sendfile
,
2920 .recvfile_fn
= vfswrap_recvfile
,
2921 .rename_fn
= vfswrap_rename
,
2922 .fsync_fn
= vfswrap_fsync
,
2923 .fsync_send_fn
= vfswrap_fsync_send
,
2924 .fsync_recv_fn
= vfswrap_fsync_recv
,
2925 .stat_fn
= vfswrap_stat
,
2926 .fstat_fn
= vfswrap_fstat
,
2927 .lstat_fn
= vfswrap_lstat
,
2928 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
2929 .unlink_fn
= vfswrap_unlink
,
2930 .chmod_fn
= vfswrap_chmod
,
2931 .fchmod_fn
= vfswrap_fchmod
,
2932 .chown_fn
= vfswrap_chown
,
2933 .fchown_fn
= vfswrap_fchown
,
2934 .lchown_fn
= vfswrap_lchown
,
2935 .chdir_fn
= vfswrap_chdir
,
2936 .getwd_fn
= vfswrap_getwd
,
2937 .ntimes_fn
= vfswrap_ntimes
,
2938 .ftruncate_fn
= vfswrap_ftruncate
,
2939 .fallocate_fn
= vfswrap_fallocate
,
2940 .lock_fn
= vfswrap_lock
,
2941 .kernel_flock_fn
= vfswrap_kernel_flock
,
2942 .linux_setlease_fn
= vfswrap_linux_setlease
,
2943 .getlock_fn
= vfswrap_getlock
,
2944 .symlink_fn
= vfswrap_symlink
,
2945 .readlink_fn
= vfswrap_readlink
,
2946 .link_fn
= vfswrap_link
,
2947 .mknod_fn
= vfswrap_mknod
,
2948 .realpath_fn
= vfswrap_realpath
,
2949 .chflags_fn
= vfswrap_chflags
,
2950 .file_id_create_fn
= vfswrap_file_id_create
,
2951 .streaminfo_fn
= vfswrap_streaminfo
,
2952 .get_real_filename_fn
= vfswrap_get_real_filename
,
2953 .connectpath_fn
= vfswrap_connectpath
,
2954 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
2955 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
2956 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
2957 .strict_lock_fn
= vfswrap_strict_lock
,
2958 .strict_unlock_fn
= vfswrap_strict_unlock
,
2959 .translate_name_fn
= vfswrap_translate_name
,
2960 .fsctl_fn
= vfswrap_fsctl
,
2961 .set_dos_attributes_fn
= vfswrap_set_dos_attributes
,
2962 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
2963 .get_dos_attributes_fn
= vfswrap_get_dos_attributes
,
2964 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
2965 .copy_chunk_send_fn
= vfswrap_copy_chunk_send
,
2966 .copy_chunk_recv_fn
= vfswrap_copy_chunk_recv
,
2967 .get_compression_fn
= vfswrap_get_compression
,
2968 .set_compression_fn
= vfswrap_set_compression
,
2970 /* NT ACL operations. */
2972 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
2973 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
2974 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
2975 .audit_file_fn
= vfswrap_audit_file
,
2977 /* POSIX ACL operations. */
2979 .chmod_acl_fn
= vfswrap_chmod_acl
,
2980 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
2982 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
2983 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
2984 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
2985 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
2986 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
2987 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
2988 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
2990 /* EA operations. */
2991 .getxattr_fn
= vfswrap_getxattr
,
2992 .fgetxattr_fn
= vfswrap_fgetxattr
,
2993 .listxattr_fn
= vfswrap_listxattr
,
2994 .flistxattr_fn
= vfswrap_flistxattr
,
2995 .removexattr_fn
= vfswrap_removexattr
,
2996 .fremovexattr_fn
= vfswrap_fremovexattr
,
2997 .setxattr_fn
= vfswrap_setxattr
,
2998 .fsetxattr_fn
= vfswrap_fsetxattr
,
3000 /* aio operations */
3001 .aio_force_fn
= vfswrap_aio_force
,
3003 /* durable handle operations */
3004 .durable_cookie_fn
= vfswrap_durable_cookie
,
3005 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
3006 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
3009 NTSTATUS
vfs_default_init(TALLOC_CTX
*);
3010 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
3012 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
3013 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);