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/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/sys_rw.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
,
63 result
= sys_disk_free(handle
->conn
, path
, bsize
, dfree
, dsize
);
67 static int vfswrap_get_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
69 #ifdef HAVE_SYS_QUOTAS
72 START_PROFILE(syscall_get_quota
);
73 result
= sys_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
74 END_PROFILE(syscall_get_quota
);
82 static int vfswrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
84 #ifdef HAVE_SYS_QUOTAS
87 START_PROFILE(syscall_set_quota
);
88 result
= sys_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
89 END_PROFILE(syscall_set_quota
);
97 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
98 struct files_struct
*fsp
,
99 struct shadow_copy_data
*shadow_copy_data
,
103 return -1; /* Not implemented. */
106 static int vfswrap_statvfs(struct vfs_handle_struct
*handle
, const char *path
, vfs_statvfs_struct
*statbuf
)
108 return sys_statvfs(path
, statbuf
);
111 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct
*handle
,
112 enum timestamp_set_resolution
*p_ts_res
)
114 connection_struct
*conn
= handle
->conn
;
115 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
116 struct smb_filename
*smb_fname_cpath
= NULL
;
117 struct vfs_statvfs_struct statbuf
;
120 ZERO_STRUCT(statbuf
);
121 ret
= sys_statvfs(conn
->connectpath
, &statbuf
);
123 caps
= statbuf
.FsCapabilities
;
126 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
128 /* Work out what timestamp resolution we can
129 * use when setting a timestamp. */
131 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
133 if (smb_fname_cpath
== NULL
) {
137 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
139 TALLOC_FREE(smb_fname_cpath
);
143 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
144 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
145 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
146 /* If any of the normal UNIX directory timestamps
147 * have a non-zero tv_nsec component assume
148 * we might be able to set sub-second timestamps.
149 * See what filetime set primitives we have.
151 #if defined(HAVE_UTIMENSAT)
152 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
153 #elif defined(HAVE_UTIMES)
154 /* utimes allows msec timestamps to be set. */
155 *p_ts_res
= TIMESTAMP_SET_MSEC
;
156 #elif defined(HAVE_UTIME)
157 /* utime only allows sec timestamps to be set. */
158 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
161 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
163 "available on share %s, directory %s\n",
164 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
165 lp_servicename(talloc_tos(), conn
->params
->service
),
166 conn
->connectpath
));
168 TALLOC_FREE(smb_fname_cpath
);
172 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
173 struct dfs_GetDFSReferral
*r
)
175 struct junction_map
*junction
= NULL
;
177 bool self_referral
= false;
178 char *pathnamep
= NULL
;
179 char *local_dfs_path
= NULL
;
182 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
185 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
188 /* get the junction entry */
189 if (r
->in
.req
.servername
== NULL
) {
190 return NT_STATUS_NOT_FOUND
;
194 * Trim pathname sent by client so it begins with only one backslash.
195 * Two backslashes confuse some dfs clients
198 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
199 if (local_dfs_path
== NULL
) {
200 return NT_STATUS_NO_MEMORY
;
202 pathnamep
= local_dfs_path
;
203 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
204 IS_DIRECTORY_SEP(pathnamep
[1])) {
208 junction
= talloc_zero(r
, struct junction_map
);
209 if (junction
== NULL
) {
210 return NT_STATUS_NO_MEMORY
;
213 /* The following call can change cwd. */
214 status
= get_referred_path(r
, pathnamep
,
215 !handle
->conn
->sconn
->using_smb2
,
216 junction
, &consumedcnt
, &self_referral
);
217 if (!NT_STATUS_IS_OK(status
)) {
218 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
221 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
223 if (!self_referral
) {
224 pathnamep
[consumedcnt
] = '\0';
227 dbgtext("Path %s to alternate path(s):",
229 for (i
=0; i
< junction
->referral_count
; i
++) {
231 junction
->referral_list
[i
].alternate_path
);
237 if (r
->in
.req
.max_referral_level
<= 2) {
238 max_referral_level
= 2;
240 if (r
->in
.req
.max_referral_level
>= 3) {
241 max_referral_level
= 3;
244 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
245 if (r
->out
.resp
== NULL
) {
246 return NT_STATUS_NO_MEMORY
;
249 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
250 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
252 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
254 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
257 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
258 struct dfs_referral_type
,
259 r
->out
.resp
->nb_referrals
);
260 if (r
->out
.resp
->referral_entries
== NULL
) {
261 return NT_STATUS_NO_MEMORY
;
264 switch (max_referral_level
) {
266 for(i
=0; i
< junction
->referral_count
; i
++) {
267 struct referral
*ref
= &junction
->referral_list
[i
];
268 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
269 struct dfs_referral_type
*t
=
270 &r
->out
.resp
->referral_entries
[i
];
271 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
274 v2
->size
= VERSION2_REFERRAL_SIZE
;
276 v2
->server_type
= DFS_SERVER_ROOT
;
278 v2
->server_type
= DFS_SERVER_NON_ROOT
;
281 v2
->proximity
= ref
->proximity
;
283 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
284 if (v2
->DFS_path
== NULL
) {
285 return NT_STATUS_NO_MEMORY
;
287 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
288 if (v2
->DFS_alt_path
== NULL
) {
289 return NT_STATUS_NO_MEMORY
;
291 v2
->netw_address
= talloc_strdup(mem_ctx
,
292 ref
->alternate_path
);
293 if (v2
->netw_address
== NULL
) {
294 return NT_STATUS_NO_MEMORY
;
300 for(i
=0; i
< junction
->referral_count
; i
++) {
301 struct referral
*ref
= &junction
->referral_list
[i
];
302 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
303 struct dfs_referral_type
*t
=
304 &r
->out
.resp
->referral_entries
[i
];
305 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
306 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
309 v3
->size
= VERSION3_REFERRAL_SIZE
;
311 v3
->server_type
= DFS_SERVER_ROOT
;
313 v3
->server_type
= DFS_SERVER_NON_ROOT
;
317 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
318 if (r1
->DFS_path
== NULL
) {
319 return NT_STATUS_NO_MEMORY
;
321 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
322 if (r1
->DFS_alt_path
== NULL
) {
323 return NT_STATUS_NO_MEMORY
;
325 r1
->netw_address
= talloc_strdup(mem_ctx
,
326 ref
->alternate_path
);
327 if (r1
->netw_address
== NULL
) {
328 return NT_STATUS_NO_MEMORY
;
333 DEBUG(0,("Invalid dfs referral version: %d\n",
334 max_referral_level
));
335 return NT_STATUS_INVALID_LEVEL
;
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
345 static NTSTATUS
vfswrap_snap_check_path(struct vfs_handle_struct
*handle
,
347 const char *service_path
,
350 return NT_STATUS_NOT_SUPPORTED
;
353 static NTSTATUS
vfswrap_snap_create(struct vfs_handle_struct
*handle
,
355 const char *base_volume
,
361 return NT_STATUS_NOT_SUPPORTED
;
364 static NTSTATUS
vfswrap_snap_delete(struct vfs_handle_struct
*handle
,
369 return NT_STATUS_NOT_SUPPORTED
;
372 /* Directory operations */
374 static DIR *vfswrap_opendir(vfs_handle_struct
*handle
, const char *fname
, const char *mask
, uint32_t attr
)
378 START_PROFILE(syscall_opendir
);
379 result
= opendir(fname
);
380 END_PROFILE(syscall_opendir
);
384 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
391 START_PROFILE(syscall_fdopendir
);
392 result
= sys_fdopendir(fsp
->fh
->fd
);
393 END_PROFILE(syscall_fdopendir
);
398 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
400 SMB_STRUCT_STAT
*sbuf
)
402 struct dirent
*result
;
404 START_PROFILE(syscall_readdir
);
405 result
= readdir(dirp
);
406 END_PROFILE(syscall_readdir
);
408 /* Default Posix readdir() does not give us stat info.
409 * Set to invalid to indicate we didn't return this info. */
410 SET_STAT_INVALID(*sbuf
);
411 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
412 if (result
!= NULL
) {
413 /* See if we can efficiently return this. */
415 int flags
= (lp_posix_pathnames() ?
416 AT_SYMLINK_NOFOLLOW
: 0);
417 int ret
= fstatat(dirfd(dirp
),
422 init_stat_ex_from_stat(sbuf
,
424 lp_fake_directory_create_times(
425 SNUM(handle
->conn
)));
433 static NTSTATUS
vfswrap_readdir_attr(struct vfs_handle_struct
*handle
,
434 const struct smb_filename
*fname
,
436 struct readdir_attr_data
**attr_data
)
438 return NT_STATUS_NOT_SUPPORTED
;
441 static void vfswrap_seekdir(vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
443 START_PROFILE(syscall_seekdir
);
444 seekdir(dirp
, offset
);
445 END_PROFILE(syscall_seekdir
);
448 static long vfswrap_telldir(vfs_handle_struct
*handle
, DIR *dirp
)
451 START_PROFILE(syscall_telldir
);
452 result
= telldir(dirp
);
453 END_PROFILE(syscall_telldir
);
457 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
459 START_PROFILE(syscall_rewinddir
);
461 END_PROFILE(syscall_rewinddir
);
464 static int vfswrap_mkdir(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
467 bool has_dacl
= False
;
470 START_PROFILE(syscall_mkdir
);
472 if (lp_inherit_acls(SNUM(handle
->conn
))
473 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
474 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
)))
475 mode
= (0777 & lp_directory_mask(SNUM(handle
->conn
)));
479 result
= mkdir(path
, mode
);
481 if (result
== 0 && !has_dacl
) {
483 * We need to do this as the default behavior of POSIX ACLs
484 * is to set the mask to be the requested group permission
485 * bits, not the group permission bits to be the requested
486 * group permission bits. This is not what we want, as it will
487 * mess up any inherited ACL bits that were set. JRA.
489 int saved_errno
= errno
; /* We may get ENOSYS */
490 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, path
, mode
) == -1) && (errno
== ENOSYS
))
494 END_PROFILE(syscall_mkdir
);
498 static int vfswrap_rmdir(vfs_handle_struct
*handle
, const char *path
)
502 START_PROFILE(syscall_rmdir
);
503 result
= rmdir(path
);
504 END_PROFILE(syscall_rmdir
);
508 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
512 START_PROFILE(syscall_closedir
);
513 result
= closedir(dirp
);
514 END_PROFILE(syscall_closedir
);
518 static void vfswrap_init_search_op(vfs_handle_struct
*handle
,
521 /* Default behavior is a NOOP */
524 /* File operations */
526 static int vfswrap_open(vfs_handle_struct
*handle
,
527 struct smb_filename
*smb_fname
,
528 files_struct
*fsp
, int flags
, mode_t mode
)
532 START_PROFILE(syscall_open
);
534 if (smb_fname
->stream_name
) {
539 result
= open(smb_fname
->base_name
, flags
, mode
);
541 END_PROFILE(syscall_open
);
545 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
546 struct smb_request
*req
,
547 uint16_t root_dir_fid
,
548 struct smb_filename
*smb_fname
,
549 uint32_t access_mask
,
550 uint32_t share_access
,
551 uint32_t create_disposition
,
552 uint32_t create_options
,
553 uint32_t file_attributes
,
554 uint32_t oplock_request
,
555 struct smb2_lease
*lease
,
556 uint64_t allocation_size
,
557 uint32_t private_flags
,
558 struct security_descriptor
*sd
,
559 struct ea_list
*ea_list
,
560 files_struct
**result
,
562 const struct smb2_create_blobs
*in_context_blobs
,
563 struct smb2_create_blobs
*out_context_blobs
)
565 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
566 access_mask
, share_access
,
567 create_disposition
, create_options
,
568 file_attributes
, oplock_request
, lease
,
569 allocation_size
, private_flags
,
571 pinfo
, in_context_blobs
, out_context_blobs
);
574 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
578 START_PROFILE(syscall_close
);
579 result
= fd_close_posix(fsp
);
580 END_PROFILE(syscall_close
);
584 static ssize_t
vfswrap_read(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
588 START_PROFILE_BYTES(syscall_read
, n
);
589 result
= sys_read(fsp
->fh
->fd
, data
, n
);
590 END_PROFILE_BYTES(syscall_read
);
594 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
595 size_t n
, off_t offset
)
599 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
600 START_PROFILE_BYTES(syscall_pread
, n
);
601 result
= sys_pread(fsp
->fh
->fd
, data
, n
, offset
);
602 END_PROFILE_BYTES(syscall_pread
);
604 if (result
== -1 && errno
== ESPIPE
) {
605 /* Maintain the fiction that pipes can be seeked (sought?) on. */
606 result
= SMB_VFS_READ(fsp
, data
, n
);
610 #else /* HAVE_PREAD */
614 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
615 if (curr
== -1 && errno
== ESPIPE
) {
616 /* Maintain the fiction that pipes can be seeked (sought?) on. */
617 result
= SMB_VFS_READ(fsp
, data
, n
);
622 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
627 result
= SMB_VFS_READ(fsp
, data
, n
);
630 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
633 #endif /* HAVE_PREAD */
638 static ssize_t
vfswrap_write(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
642 START_PROFILE_BYTES(syscall_write
, n
);
643 result
= sys_write(fsp
->fh
->fd
, data
, n
);
644 END_PROFILE_BYTES(syscall_write
);
648 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
649 size_t n
, off_t offset
)
653 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
654 START_PROFILE_BYTES(syscall_pwrite
, n
);
655 result
= sys_pwrite(fsp
->fh
->fd
, data
, n
, offset
);
656 END_PROFILE_BYTES(syscall_pwrite
);
658 if (result
== -1 && errno
== ESPIPE
) {
659 /* Maintain the fiction that pipes can be sought on. */
660 result
= SMB_VFS_WRITE(fsp
, data
, n
);
663 #else /* HAVE_PWRITE */
667 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
672 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
676 result
= SMB_VFS_WRITE(fsp
, data
, n
);
679 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
682 #endif /* HAVE_PWRITE */
687 static void vfswrap_asys_finished(struct tevent_context
*ev
,
688 struct tevent_fd
*fde
,
689 uint16_t flags
, void *p
);
691 static bool vfswrap_init_asys_ctx(struct smbd_server_connection
*conn
)
696 if (conn
->asys_ctx
!= NULL
) {
699 ret
= asys_context_init(&conn
->asys_ctx
, aio_pending_size
);
701 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret
)));
705 fd
= asys_signalfd(conn
->asys_ctx
);
707 set_blocking(fd
, false);
709 conn
->asys_fde
= tevent_add_fd(conn
->ev_ctx
, conn
, fd
,
711 vfswrap_asys_finished
,
713 if (conn
->asys_fde
== NULL
) {
714 DEBUG(1, ("tevent_add_fd failed\n"));
715 asys_context_destroy(conn
->asys_ctx
);
716 conn
->asys_ctx
= NULL
;
722 struct vfswrap_asys_state
{
723 struct asys_context
*asys_ctx
;
724 struct tevent_req
*req
;
727 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic
);
728 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
731 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state
*s
)
733 asys_cancel(s
->asys_ctx
, s
->req
);
737 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
739 struct tevent_context
*ev
,
740 struct files_struct
*fsp
,
742 size_t n
, off_t offset
)
744 struct tevent_req
*req
;
745 struct vfswrap_asys_state
*state
;
748 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_asys_state
);
752 if (!vfswrap_init_asys_ctx(handle
->conn
->sconn
)) {
754 return tevent_req_post(req
, ev
);
756 state
->asys_ctx
= handle
->conn
->sconn
->asys_ctx
;
759 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
760 state
->profile_bytes
, n
);
761 ret
= asys_pread(state
->asys_ctx
, fsp
->fh
->fd
, data
, n
, offset
, req
);
763 tevent_req_error(req
, ret
);
764 return tevent_req_post(req
, ev
);
766 talloc_set_destructor(state
, vfswrap_asys_state_destructor
);
771 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
773 struct tevent_context
*ev
,
774 struct files_struct
*fsp
,
776 size_t n
, off_t offset
)
778 struct tevent_req
*req
;
779 struct vfswrap_asys_state
*state
;
782 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_asys_state
);
786 if (!vfswrap_init_asys_ctx(handle
->conn
->sconn
)) {
788 return tevent_req_post(req
, ev
);
790 state
->asys_ctx
= handle
->conn
->sconn
->asys_ctx
;
793 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
794 state
->profile_bytes
, n
);
795 ret
= asys_pwrite(state
->asys_ctx
, fsp
->fh
->fd
, data
, n
, offset
, req
);
797 tevent_req_error(req
, ret
);
798 return tevent_req_post(req
, ev
);
800 talloc_set_destructor(state
, vfswrap_asys_state_destructor
);
805 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
807 struct tevent_context
*ev
,
808 struct files_struct
*fsp
)
810 struct tevent_req
*req
;
811 struct vfswrap_asys_state
*state
;
814 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_asys_state
);
818 if (!vfswrap_init_asys_ctx(handle
->conn
->sconn
)) {
820 return tevent_req_post(req
, ev
);
822 state
->asys_ctx
= handle
->conn
->sconn
->asys_ctx
;
825 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync
, profile_p
,
826 state
->profile_basic
);
827 ret
= asys_fsync(state
->asys_ctx
, fsp
->fh
->fd
, req
);
829 tevent_req_error(req
, ret
);
830 return tevent_req_post(req
, ev
);
832 talloc_set_destructor(state
, vfswrap_asys_state_destructor
);
837 static void vfswrap_asys_finished(struct tevent_context
*ev
,
838 struct tevent_fd
*fde
,
839 uint16_t flags
, void *p
)
841 struct asys_context
*asys_ctx
= (struct asys_context
*)p
;
842 struct asys_result results
[outstanding_aio_calls
];
845 if ((flags
& TEVENT_FD_READ
) == 0) {
849 ret
= asys_results(asys_ctx
, results
, outstanding_aio_calls
);
851 DEBUG(1, ("asys_results returned %s\n", strerror(-ret
)));
855 for (i
=0; i
<ret
; i
++) {
856 struct asys_result
*result
= &results
[i
];
857 struct tevent_req
*req
;
858 struct vfswrap_asys_state
*state
;
860 if ((result
->ret
== -1) && (result
->err
== ECANCELED
)) {
864 req
= talloc_get_type_abort(result
->private_data
,
866 state
= tevent_req_data(req
, struct vfswrap_asys_state
);
868 talloc_set_destructor(state
, NULL
);
870 SMBPROFILE_BASIC_ASYNC_END(state
->profile_basic
);
871 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
872 state
->ret
= result
->ret
;
873 state
->err
= result
->err
;
874 tevent_req_defer_callback(req
, ev
);
875 tevent_req_done(req
);
879 static ssize_t
vfswrap_asys_ssize_t_recv(struct tevent_req
*req
, int *err
)
881 struct vfswrap_asys_state
*state
= tevent_req_data(
882 req
, struct vfswrap_asys_state
);
884 if (tevent_req_is_unix_error(req
, err
)) {
891 static int vfswrap_asys_int_recv(struct tevent_req
*req
, int *err
)
893 struct vfswrap_asys_state
*state
= tevent_req_data(
894 req
, struct vfswrap_asys_state
);
896 if (tevent_req_is_unix_error(req
, err
)) {
903 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
907 START_PROFILE(syscall_lseek
);
909 /* Cope with 'stat' file opens. */
910 if (fsp
->fh
->fd
!= -1)
911 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
914 * We want to maintain the fiction that we can seek
915 * on a fifo for file system purposes. This allows
916 * people to set up UNIX fifo's that feed data to Windows
920 if((result
== -1) && (errno
== ESPIPE
)) {
925 END_PROFILE(syscall_lseek
);
929 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
930 off_t offset
, size_t n
)
934 START_PROFILE_BYTES(syscall_sendfile
, n
);
935 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
936 END_PROFILE_BYTES(syscall_sendfile
);
940 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
948 START_PROFILE_BYTES(syscall_recvfile
, n
);
949 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
950 END_PROFILE_BYTES(syscall_recvfile
);
954 static int vfswrap_rename(vfs_handle_struct
*handle
,
955 const struct smb_filename
*smb_fname_src
,
956 const struct smb_filename
*smb_fname_dst
)
960 START_PROFILE(syscall_rename
);
962 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
967 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
970 END_PROFILE(syscall_rename
);
974 static int vfswrap_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
979 START_PROFILE(syscall_fsync
);
980 result
= fsync(fsp
->fh
->fd
);
981 END_PROFILE(syscall_fsync
);
988 static int vfswrap_stat(vfs_handle_struct
*handle
,
989 struct smb_filename
*smb_fname
)
993 START_PROFILE(syscall_stat
);
995 if (smb_fname
->stream_name
) {
1000 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1001 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1003 END_PROFILE(syscall_stat
);
1007 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1011 START_PROFILE(syscall_fstat
);
1012 result
= sys_fstat(fsp
->fh
->fd
,
1013 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1014 END_PROFILE(syscall_fstat
);
1018 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1019 struct smb_filename
*smb_fname
)
1023 START_PROFILE(syscall_lstat
);
1025 if (smb_fname
->stream_name
) {
1030 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1031 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1033 END_PROFILE(syscall_lstat
);
1037 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1039 enum vfs_translate_direction direction
,
1040 TALLOC_CTX
*mem_ctx
,
1043 return NT_STATUS_NONE_MAPPED
;
1047 * Implement the default fsctl operation.
1049 static bool vfswrap_logged_ioctl_message
= false;
1051 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1052 struct files_struct
*fsp
,
1055 uint16_t req_flags
, /* Needed for UNICODE ... */
1056 const uint8_t *_in_data
,
1058 uint8_t **_out_data
,
1059 uint32_t max_out_len
,
1062 const char *in_data
= (const char *)_in_data
;
1063 char **out_data
= (char **)_out_data
;
1067 case FSCTL_SET_SPARSE
:
1069 bool set_sparse
= true;
1071 if (in_len
>= 1 && in_data
[0] == 0) {
1075 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1077 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1078 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1079 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1080 nt_errstr(status
)));
1085 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1087 unsigned char objid
[16];
1088 char *return_data
= NULL
;
1090 /* This should return the object-id on this file.
1091 * I think I'll make this be the inode+dev. JRA.
1094 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1095 fsp_fnum_dbg(fsp
)));
1097 *out_len
= MIN(max_out_len
, 64);
1099 /* Hmmm, will this cause problems if less data asked for? */
1100 return_data
= talloc_array(ctx
, char, 64);
1101 if (return_data
== NULL
) {
1102 return NT_STATUS_NO_MEMORY
;
1105 /* For backwards compatibility only store the dev/inode. */
1106 push_file_id_16(return_data
, &fsp
->file_id
);
1107 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1108 push_file_id_16(return_data
+32, &fsp
->file_id
);
1109 memset(return_data
+48, 0, 16);
1110 *out_data
= return_data
;
1111 return NT_STATUS_OK
;
1114 case FSCTL_GET_REPARSE_POINT
:
1116 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1117 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1118 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1119 return NT_STATUS_NOT_A_REPARSE_POINT
;
1122 case FSCTL_SET_REPARSE_POINT
:
1124 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1125 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1126 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1127 return NT_STATUS_NOT_A_REPARSE_POINT
;
1130 case FSCTL_GET_SHADOW_COPY_DATA
:
1133 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1134 * and return their volume names. If max_data_count is 16, then it is just
1135 * asking for the number of volumes and length of the combined names.
1137 * pdata is the data allocated by our caller, but that uses
1138 * total_data_count (which is 0 in our case) rather than max_data_count.
1139 * Allocate the correct amount and return the pointer to let
1140 * it be deallocated when we return.
1142 struct shadow_copy_data
*shadow_data
= NULL
;
1143 bool labels
= False
;
1144 uint32_t labels_data_count
= 0;
1146 char *cur_pdata
= NULL
;
1148 if (max_out_len
< 16) {
1149 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1151 return NT_STATUS_INVALID_PARAMETER
;
1154 if (max_out_len
> 16) {
1158 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1159 if (shadow_data
== NULL
) {
1160 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1161 return NT_STATUS_NO_MEMORY
;
1165 * Call the VFS routine to actually do the work.
1167 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1170 /* broken module didn't set errno on error */
1171 status
= NT_STATUS_UNSUCCESSFUL
;
1173 status
= map_nt_error_from_unix(errno
);
1174 if (NT_STATUS_EQUAL(status
,
1175 NT_STATUS_NOT_SUPPORTED
)) {
1179 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1180 "connectpath %s, failed - %s.\n",
1181 fsp
->conn
->connectpath
,
1182 nt_errstr(status
)));
1183 TALLOC_FREE(shadow_data
);
1187 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1188 sizeof(SHADOW_COPY_LABEL
)) + 2;
1193 *out_len
= 12 + labels_data_count
;
1196 if (max_out_len
< *out_len
) {
1197 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1198 max_out_len
, *out_len
));
1199 TALLOC_FREE(shadow_data
);
1200 return NT_STATUS_BUFFER_TOO_SMALL
;
1203 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1204 if (cur_pdata
== NULL
) {
1205 TALLOC_FREE(shadow_data
);
1206 return NT_STATUS_NO_MEMORY
;
1209 *out_data
= cur_pdata
;
1211 /* num_volumes 4 bytes */
1212 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1215 /* num_labels 4 bytes */
1216 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1219 /* needed_data_count 4 bytes */
1220 SIVAL(cur_pdata
, 8, labels_data_count
);
1224 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1225 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1226 if (labels
&& shadow_data
->labels
) {
1227 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1229 status
= srvstr_push(cur_pdata
, req_flags
,
1230 cur_pdata
, shadow_data
->labels
[i
],
1231 2 * sizeof(SHADOW_COPY_LABEL
),
1232 STR_UNICODE
|STR_TERMINATE
, &len
);
1233 if (!NT_STATUS_IS_OK(status
)) {
1234 TALLOC_FREE(*out_data
);
1235 TALLOC_FREE(shadow_data
);
1238 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1239 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1243 TALLOC_FREE(shadow_data
);
1245 return NT_STATUS_OK
;
1248 case FSCTL_FIND_FILES_BY_SID
:
1250 /* pretend this succeeded -
1252 * we have to send back a list with all files owned by this SID
1254 * but I have to check that --metze
1260 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1261 fsp_fnum_dbg(fsp
)));
1264 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1265 return NT_STATUS_INVALID_PARAMETER
;
1268 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1270 /* unknown 4 bytes: this is not the length of the sid :-( */
1271 /*unknown = IVAL(pdata,0);*/
1273 if (!sid_parse(in_data
+ 4, sid_len
, &sid
)) {
1274 return NT_STATUS_INVALID_PARAMETER
;
1276 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
1278 if (!sid_to_uid(&sid
, &uid
)) {
1279 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1280 sid_string_dbg(&sid
),
1281 (unsigned long)sid_len
));
1285 /* we can take a look at the find source :-)
1287 * find ./ -uid $uid -name '*' is what we need here
1290 * and send 4bytes len and then NULL terminated unicode strings
1293 * but I don't know how to deal with the paged results
1294 * (maybe we can hang the result anywhere in the fsp struct)
1296 * but I don't know how to deal with the paged results
1297 * (maybe we can hang the result anywhere in the fsp struct)
1299 * we don't send all files at once
1300 * and at the next we should *not* start from the beginning,
1301 * so we have to cache the result
1306 /* this works for now... */
1307 return NT_STATUS_OK
;
1310 case FSCTL_QUERY_ALLOCATED_RANGES
:
1312 /* FIXME: This is just a dummy reply, telling that all of the
1313 * file is allocated. MKS cp needs that.
1314 * Adding the real allocated ranges via FIEMAP on Linux
1315 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1316 * this FSCTL correct for sparse files.
1318 uint64_t offset
, length
;
1319 char *out_data_tmp
= NULL
;
1322 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1324 return NT_STATUS_INVALID_PARAMETER
;
1327 if (max_out_len
< 16) {
1328 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1330 return NT_STATUS_INVALID_PARAMETER
;
1333 offset
= BVAL(in_data
,0);
1334 length
= BVAL(in_data
,8);
1336 if (offset
+ length
< offset
) {
1337 /* No 64-bit integer wrap. */
1338 return NT_STATUS_INVALID_PARAMETER
;
1341 /* Shouldn't this be SMB_VFS_STAT ... ? */
1342 status
= vfs_stat_fsp(fsp
);
1343 if (!NT_STATUS_IS_OK(status
)) {
1348 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1349 if (out_data_tmp
== NULL
) {
1350 DEBUG(10, ("unable to allocate memory for response\n"));
1351 return NT_STATUS_NO_MEMORY
;
1354 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1355 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1357 memset(out_data_tmp
, 0, *out_len
);
1359 uint64_t end
= offset
+ length
;
1360 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1361 SBVAL(out_data_tmp
, 0, 0);
1362 SBVAL(out_data_tmp
, 8, end
);
1365 *out_data
= out_data_tmp
;
1367 return NT_STATUS_OK
;
1370 case FSCTL_IS_VOLUME_DIRTY
:
1372 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1373 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1375 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1376 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1378 return NT_STATUS_INVALID_PARAMETER
;
1383 * Only print once ... unfortunately there could be lots of
1384 * different FSCTLs that are called.
1386 if (!vfswrap_logged_ioctl_message
) {
1387 vfswrap_logged_ioctl_message
= true;
1388 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1389 __func__
, function
));
1393 return NT_STATUS_NOT_SUPPORTED
;
1396 struct vfs_cc_state
{
1401 static struct tevent_req
*vfswrap_copy_chunk_send(struct vfs_handle_struct
*handle
,
1402 TALLOC_CTX
*mem_ctx
,
1403 struct tevent_context
*ev
,
1404 struct files_struct
*src_fsp
,
1406 struct files_struct
*dest_fsp
,
1410 struct tevent_req
*req
;
1411 struct vfs_cc_state
*vfs_cc_state
;
1414 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1415 (unsigned long)num
));
1417 req
= tevent_req_create(mem_ctx
, &vfs_cc_state
, struct vfs_cc_state
);
1422 vfs_cc_state
->buf
= talloc_array(vfs_cc_state
, uint8_t,
1423 MIN(num
, 8*1024*1024));
1424 if (tevent_req_nomem(vfs_cc_state
->buf
, req
)) {
1425 return tevent_req_post(req
, ev
);
1428 status
= vfs_stat_fsp(src_fsp
);
1429 if (tevent_req_nterror(req
, status
)) {
1430 return tevent_req_post(req
, ev
);
1433 if (src_fsp
->fsp_name
->st
.st_ex_size
< src_off
+ num
) {
1435 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1436 * If the SourceOffset or SourceOffset + Length extends beyond
1437 * the end of file, the server SHOULD<240> treat this as a
1438 * STATUS_END_OF_FILE error.
1440 * <240> Section 3.3.5.15.6: Windows servers will return
1441 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1443 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
1444 return tevent_req_post(req
, ev
);
1447 /* could use 2.6.33+ sendfile here to do this in kernel */
1448 while (vfs_cc_state
->copied
< num
) {
1450 struct lock_struct lck
;
1453 off_t this_num
= MIN(talloc_array_length(vfs_cc_state
->buf
),
1454 num
- vfs_cc_state
->copied
);
1456 if (src_fsp
->op
== NULL
) {
1457 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1458 return tevent_req_post(req
, ev
);
1460 init_strict_lock_struct(src_fsp
,
1461 src_fsp
->op
->global
->open_persistent_id
,
1467 if (!SMB_VFS_STRICT_LOCK(src_fsp
->conn
, src_fsp
, &lck
)) {
1468 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1469 return tevent_req_post(req
, ev
);
1472 ret
= SMB_VFS_PREAD(src_fsp
, vfs_cc_state
->buf
,
1475 saved_errno
= errno
;
1478 SMB_VFS_STRICT_UNLOCK(src_fsp
->conn
, src_fsp
, &lck
);
1481 errno
= saved_errno
;
1482 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
1483 return tevent_req_post(req
, ev
);
1485 if (ret
!= this_num
) {
1486 /* zero tolerance for short reads */
1487 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1488 return tevent_req_post(req
, ev
);
1493 if (dest_fsp
->op
== NULL
) {
1494 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1495 return tevent_req_post(req
, ev
);
1498 init_strict_lock_struct(dest_fsp
,
1499 dest_fsp
->op
->global
->open_persistent_id
,
1505 if (!SMB_VFS_STRICT_LOCK(dest_fsp
->conn
, dest_fsp
, &lck
)) {
1506 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1507 return tevent_req_post(req
, ev
);
1510 ret
= SMB_VFS_PWRITE(dest_fsp
, vfs_cc_state
->buf
,
1511 this_num
, dest_off
);
1513 saved_errno
= errno
;
1516 SMB_VFS_STRICT_UNLOCK(src_fsp
->conn
, src_fsp
, &lck
);
1519 errno
= saved_errno
;
1520 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
1521 return tevent_req_post(req
, ev
);
1523 if (ret
!= this_num
) {
1524 /* zero tolerance for short writes */
1525 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1526 return tevent_req_post(req
, ev
);
1530 vfs_cc_state
->copied
+= this_num
;
1533 tevent_req_done(req
);
1534 return tevent_req_post(req
, ev
);
1537 static NTSTATUS
vfswrap_copy_chunk_recv(struct vfs_handle_struct
*handle
,
1538 struct tevent_req
*req
,
1541 struct vfs_cc_state
*vfs_cc_state
= tevent_req_data(req
,
1542 struct vfs_cc_state
);
1545 if (tevent_req_is_nterror(req
, &status
)) {
1546 DEBUG(2, ("server side copy chunk failed: %s\n",
1547 nt_errstr(status
)));
1549 tevent_req_received(req
);
1553 *copied
= vfs_cc_state
->copied
;
1554 DEBUG(10, ("server side copy chunk copied %lu\n",
1555 (unsigned long)*copied
));
1556 tevent_req_received(req
);
1558 return NT_STATUS_OK
;
1561 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
1562 TALLOC_CTX
*mem_ctx
,
1563 struct files_struct
*fsp
,
1564 struct smb_filename
*smb_fname
,
1565 uint16_t *_compression_fmt
)
1567 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1570 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
1571 TALLOC_CTX
*mem_ctx
,
1572 struct files_struct
*fsp
,
1573 uint16_t compression_fmt
)
1575 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1578 /********************************************************************
1579 Given a stat buffer return the allocated size on disk, taking into
1580 account sparse files.
1581 ********************************************************************/
1582 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
1583 struct files_struct
*fsp
,
1584 const SMB_STRUCT_STAT
*sbuf
)
1588 START_PROFILE(syscall_get_alloc_size
);
1590 if(S_ISDIR(sbuf
->st_ex_mode
)) {
1595 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1596 /* The type of st_blocksize is blkcnt_t which *MUST* be
1597 signed (according to POSIX) and can be less than 64-bits.
1598 Ensure when we're converting to 64 bits wide we don't
1600 #if defined(SIZEOF_BLKCNT_T_8)
1601 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
1602 #elif defined(SIZEOF_BLKCNT_T_4)
1604 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
1605 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
1608 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1612 * Some file systems do not allocate a block for very
1613 * small files. But for non-empty file should report a
1617 uint64_t filesize
= get_file_size_stat(sbuf
);
1619 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
1623 result
= get_file_size_stat(sbuf
);
1626 if (fsp
&& fsp
->initial_allocation_size
)
1627 result
= MAX(result
,fsp
->initial_allocation_size
);
1629 result
= smb_roundup(handle
->conn
, result
);
1632 END_PROFILE(syscall_get_alloc_size
);
1636 static int vfswrap_unlink(vfs_handle_struct
*handle
,
1637 const struct smb_filename
*smb_fname
)
1641 START_PROFILE(syscall_unlink
);
1643 if (smb_fname
->stream_name
) {
1647 result
= unlink(smb_fname
->base_name
);
1650 END_PROFILE(syscall_unlink
);
1654 static int vfswrap_chmod(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
1658 START_PROFILE(syscall_chmod
);
1661 * We need to do this due to the fact that the default POSIX ACL
1662 * chmod modifies the ACL *mask* for the group owner, not the
1663 * group owner bits directly. JRA.
1668 int saved_errno
= errno
; /* We might get ENOSYS */
1669 if ((result
= SMB_VFS_CHMOD_ACL(handle
->conn
, path
, mode
)) == 0) {
1670 END_PROFILE(syscall_chmod
);
1673 /* Error - return the old errno. */
1674 errno
= saved_errno
;
1677 result
= chmod(path
, mode
);
1678 END_PROFILE(syscall_chmod
);
1682 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
1686 START_PROFILE(syscall_fchmod
);
1689 * We need to do this due to the fact that the default POSIX ACL
1690 * chmod modifies the ACL *mask* for the group owner, not the
1691 * group owner bits directly. JRA.
1695 int saved_errno
= errno
; /* We might get ENOSYS */
1696 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
1697 END_PROFILE(syscall_fchmod
);
1700 /* Error - return the old errno. */
1701 errno
= saved_errno
;
1704 #if defined(HAVE_FCHMOD)
1705 result
= fchmod(fsp
->fh
->fd
, mode
);
1711 END_PROFILE(syscall_fchmod
);
1715 static int vfswrap_chown(vfs_handle_struct
*handle
, const char *path
, uid_t uid
, gid_t gid
)
1719 START_PROFILE(syscall_chown
);
1720 result
= chown(path
, uid
, gid
);
1721 END_PROFILE(syscall_chown
);
1725 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
1730 START_PROFILE(syscall_fchown
);
1731 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
1732 END_PROFILE(syscall_fchown
);
1740 static int vfswrap_lchown(vfs_handle_struct
*handle
, const char *path
, uid_t uid
, gid_t gid
)
1744 START_PROFILE(syscall_lchown
);
1745 result
= lchown(path
, uid
, gid
);
1746 END_PROFILE(syscall_lchown
);
1750 static int vfswrap_chdir(vfs_handle_struct
*handle
, const char *path
)
1754 START_PROFILE(syscall_chdir
);
1755 result
= chdir(path
);
1756 END_PROFILE(syscall_chdir
);
1760 static char *vfswrap_getwd(vfs_handle_struct
*handle
)
1764 START_PROFILE(syscall_getwd
);
1765 result
= sys_getwd();
1766 END_PROFILE(syscall_getwd
);
1770 /*********************************************************************
1771 nsec timestamp resolution call. Convert down to whatever the underlying
1772 system will support.
1773 **********************************************************************/
1775 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
1776 const struct smb_filename
*smb_fname
,
1777 struct smb_file_time
*ft
)
1781 START_PROFILE(syscall_ntimes
);
1783 if (smb_fname
->stream_name
) {
1789 if (null_timespec(ft
->atime
)) {
1790 ft
->atime
= smb_fname
->st
.st_ex_atime
;
1793 if (null_timespec(ft
->mtime
)) {
1794 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
1797 if (!null_timespec(ft
->create_time
)) {
1798 set_create_timespec_ea(handle
->conn
,
1803 if ((timespec_compare(&ft
->atime
,
1804 &smb_fname
->st
.st_ex_atime
) == 0) &&
1805 (timespec_compare(&ft
->mtime
,
1806 &smb_fname
->st
.st_ex_mtime
) == 0)) {
1811 #if defined(HAVE_UTIMENSAT)
1813 struct timespec ts
[2];
1816 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
1818 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
1820 if (!((result
== -1) && (errno
== ENOSYS
))) {
1824 #if defined(HAVE_UTIMES)
1826 struct timeval tv
[2];
1827 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
1828 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
1829 result
= utimes(smb_fname
->base_name
, tv
);
1831 result
= utimes(smb_fname
->base_name
, NULL
);
1833 if (!((result
== -1) && (errno
== ENOSYS
))) {
1837 #if defined(HAVE_UTIME)
1839 struct utimbuf times
;
1840 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
1841 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
1842 result
= utime(smb_fname
->base_name
, ×
);
1844 result
= utime(smb_fname
->base_name
, NULL
);
1846 if (!((result
== -1) && (errno
== ENOSYS
))) {
1854 END_PROFILE(syscall_ntimes
);
1858 /*********************************************************************
1859 A version of ftruncate that will write the space on disk if strict
1861 **********************************************************************/
1863 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1865 off_t space_to_write
;
1866 uint64_t space_avail
;
1867 uint64_t bsize
,dfree
,dsize
;
1870 SMB_STRUCT_STAT
*pst
;
1872 status
= vfs_stat_fsp(fsp
);
1873 if (!NT_STATUS_IS_OK(status
)) {
1876 pst
= &fsp
->fsp_name
->st
;
1879 if (S_ISFIFO(pst
->st_ex_mode
))
1883 if (pst
->st_ex_size
== len
)
1886 /* Shrink - just ftruncate. */
1887 if (pst
->st_ex_size
> len
)
1888 return ftruncate(fsp
->fh
->fd
, len
);
1890 space_to_write
= len
- pst
->st_ex_size
;
1892 /* for allocation try fallocate first. This can fail on some
1893 platforms e.g. when the filesystem doesn't support it and no
1894 emulation is being done by the libc (like on AIX with JFS1). In that
1895 case we do our own emulation. fallocate implementations can
1896 return ENOTSUP or EINVAL in cases like that. */
1897 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
1898 if (ret
== -1 && errno
== ENOSPC
) {
1904 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1905 "error %d. Falling back to slow manual allocation\n", errno
));
1907 /* available disk space is enough or not? */
1908 space_avail
= get_dfree_info(fsp
->conn
,
1909 fsp
->fsp_name
->base_name
,
1910 &bsize
, &dfree
, &dsize
);
1911 /* space_avail is 1k blocks */
1912 if (space_avail
== (uint64_t)-1 ||
1913 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
1918 /* Write out the real space on disk. */
1919 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
1927 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1930 SMB_STRUCT_STAT
*pst
;
1934 START_PROFILE(syscall_ftruncate
);
1936 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
1937 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
1938 END_PROFILE(syscall_ftruncate
);
1942 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1943 ftruncate if the system supports it. Then I discovered that
1944 you can have some filesystems that support ftruncate
1945 expansion and some that don't! On Linux fat can't do
1946 ftruncate extend but ext2 can. */
1948 result
= ftruncate(fsp
->fh
->fd
, len
);
1950 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1951 extend a file with ftruncate. Provide alternate implementation
1954 /* Do an fstat to see if the file is longer than the requested
1955 size in which case the ftruncate above should have
1956 succeeded or shorter, in which case seek to len - 1 and
1957 write 1 byte of zero */
1958 status
= vfs_stat_fsp(fsp
);
1959 if (!NT_STATUS_IS_OK(status
)) {
1963 /* We need to update the files_struct after successful ftruncate */
1968 pst
= &fsp
->fsp_name
->st
;
1971 if (S_ISFIFO(pst
->st_ex_mode
)) {
1977 if (pst
->st_ex_size
== len
) {
1982 if (pst
->st_ex_size
> len
) {
1983 /* the ftruncate should have worked */
1987 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
1995 END_PROFILE(syscall_ftruncate
);
1999 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
2007 START_PROFILE(syscall_fallocate
);
2009 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
2011 * posix_fallocate returns 0 on success, errno on error
2012 * and doesn't set errno. Make it behave like fallocate()
2013 * which returns -1, and sets errno on failure.
2020 /* sys_fallocate handles filtering of unsupported mode flags */
2021 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
2023 END_PROFILE(syscall_fallocate
);
2027 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
2031 START_PROFILE(syscall_fcntl_lock
);
2032 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
2033 END_PROFILE(syscall_fcntl_lock
);
2037 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2038 uint32_t share_mode
, uint32_t access_mask
)
2040 START_PROFILE(syscall_kernel_flock
);
2041 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
2042 END_PROFILE(syscall_kernel_flock
);
2046 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2050 START_PROFILE(syscall_fcntl_getlock
);
2051 result
= fcntl_getlock(fsp
->fh
->fd
, poffset
, pcount
, ptype
, ppid
);
2052 END_PROFILE(syscall_fcntl_getlock
);
2056 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2061 START_PROFILE(syscall_linux_setlease
);
2063 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2064 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2068 END_PROFILE(syscall_linux_setlease
);
2072 static int vfswrap_symlink(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2076 START_PROFILE(syscall_symlink
);
2077 result
= symlink(oldpath
, newpath
);
2078 END_PROFILE(syscall_symlink
);
2082 static int vfswrap_readlink(vfs_handle_struct
*handle
, const char *path
, char *buf
, size_t bufsiz
)
2086 START_PROFILE(syscall_readlink
);
2087 result
= readlink(path
, buf
, bufsiz
);
2088 END_PROFILE(syscall_readlink
);
2092 static int vfswrap_link(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2096 START_PROFILE(syscall_link
);
2097 result
= link(oldpath
, newpath
);
2098 END_PROFILE(syscall_link
);
2102 static int vfswrap_mknod(vfs_handle_struct
*handle
, const char *pathname
, mode_t mode
, SMB_DEV_T dev
)
2106 START_PROFILE(syscall_mknod
);
2107 result
= sys_mknod(pathname
, mode
, dev
);
2108 END_PROFILE(syscall_mknod
);
2112 static char *vfswrap_realpath(vfs_handle_struct
*handle
, const char *path
)
2116 START_PROFILE(syscall_realpath
);
2117 #ifdef REALPATH_TAKES_NULL
2118 result
= realpath(path
, NULL
);
2120 result
= SMB_MALLOC_ARRAY(char, PATH_MAX
+1);
2122 char *resolved_path
= realpath(path
, result
);
2123 if (!resolved_path
) {
2126 /* SMB_ASSERT(result == resolved_path) ? */
2127 result
= resolved_path
;
2131 END_PROFILE(syscall_realpath
);
2135 static int vfswrap_chflags(vfs_handle_struct
*handle
, const char *path
,
2139 return chflags(path
, flags
);
2146 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2147 const SMB_STRUCT_STAT
*sbuf
)
2151 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2155 key
.devid
= sbuf
->st_ex_dev
;
2156 key
.inode
= sbuf
->st_ex_ino
;
2157 /* key.extid is unused by default. */
2162 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
2163 struct files_struct
*fsp
,
2165 TALLOC_CTX
*mem_ctx
,
2166 unsigned int *pnum_streams
,
2167 struct stream_struct
**pstreams
)
2169 SMB_STRUCT_STAT sbuf
;
2170 struct stream_struct
*tmp_streams
= NULL
;
2173 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
2175 * No default streams on directories
2180 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
2181 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
2184 struct smb_filename smb_fname
;
2186 ZERO_STRUCT(smb_fname
);
2187 smb_fname
.base_name
= discard_const_p(char, fname
);
2189 if (lp_posix_pathnames()) {
2190 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname
);
2192 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname
);
2194 sbuf
= smb_fname
.st
;
2198 return map_nt_error_from_unix(errno
);
2201 if (S_ISDIR(sbuf
.st_ex_mode
)) {
2205 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
2206 (*pnum_streams
) + 1);
2207 if (tmp_streams
== NULL
) {
2208 return NT_STATUS_NO_MEMORY
;
2210 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
2211 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
2212 return NT_STATUS_NO_MEMORY
;
2214 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
2215 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
2218 *pstreams
= tmp_streams
;
2220 return NT_STATUS_OK
;
2223 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
2226 TALLOC_CTX
*mem_ctx
,
2230 * Don't fall back to get_real_filename so callers can differentiate
2231 * between a full directory scan and an actual case-insensitive stat.
2237 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
2240 return handle
->conn
->connectpath
;
2243 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
2244 struct byte_range_lock
*br_lck
,
2245 struct lock_struct
*plock
,
2248 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2250 /* Note: blr is not used in the default implementation. */
2251 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
2254 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
2255 struct messaging_context
*msg_ctx
,
2256 struct byte_range_lock
*br_lck
,
2257 const struct lock_struct
*plock
)
2259 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2261 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
2264 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
2265 struct byte_range_lock
*br_lck
,
2266 struct lock_struct
*plock
)
2268 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2270 /* Note: blr is not used in the default implementation. */
2271 return brl_lock_cancel_default(br_lck
, plock
);
2274 static bool vfswrap_strict_lock(struct vfs_handle_struct
*handle
,
2276 struct lock_struct
*plock
)
2278 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2279 plock
->lock_type
== WRITE_LOCK
);
2281 return strict_lock_default(fsp
, plock
);
2284 static void vfswrap_strict_unlock(struct vfs_handle_struct
*handle
,
2286 struct lock_struct
*plock
)
2288 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2289 plock
->lock_type
== WRITE_LOCK
);
2291 strict_unlock_default(fsp
, plock
);
2294 /* NT ACL operations. */
2296 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
2298 uint32_t security_info
,
2299 TALLOC_CTX
*mem_ctx
,
2300 struct security_descriptor
**ppdesc
)
2304 START_PROFILE(fget_nt_acl
);
2305 result
= posix_fget_nt_acl(fsp
, security_info
,
2307 END_PROFILE(fget_nt_acl
);
2311 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
2313 uint32_t security_info
,
2314 TALLOC_CTX
*mem_ctx
,
2315 struct security_descriptor
**ppdesc
)
2319 START_PROFILE(get_nt_acl
);
2320 result
= posix_get_nt_acl(handle
->conn
, name
, security_info
,
2322 END_PROFILE(get_nt_acl
);
2326 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
2330 START_PROFILE(fset_nt_acl
);
2331 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
2332 END_PROFILE(fset_nt_acl
);
2336 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
2337 struct smb_filename
*file
,
2338 struct security_acl
*sacl
,
2339 uint32_t access_requested
,
2340 uint32_t access_denied
)
2342 return NT_STATUS_OK
; /* Nothing to do here ... */
2345 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
, const char *name
, mode_t mode
)
2353 START_PROFILE(chmod_acl
);
2354 result
= chmod_acl(handle
->conn
, name
, mode
);
2355 END_PROFILE(chmod_acl
);
2360 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2368 START_PROFILE(fchmod_acl
);
2369 result
= fchmod_acl(fsp
, mode
);
2370 END_PROFILE(fchmod_acl
);
2375 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
2377 SMB_ACL_TYPE_T type
,
2378 TALLOC_CTX
*mem_ctx
)
2380 return sys_acl_get_file(handle
, path_p
, type
, mem_ctx
);
2383 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
2385 TALLOC_CTX
*mem_ctx
)
2387 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
2390 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
, const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
2392 return sys_acl_set_file(handle
, name
, acltype
, theacl
);
2395 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2397 return sys_acl_set_fd(handle
, fsp
, theacl
);
2400 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
, const char *path
)
2402 return sys_acl_delete_def_file(handle
, path
);
2405 /****************************************************************
2406 Extended attribute operations.
2407 *****************************************************************/
2409 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,const char *path
, const char *name
, void *value
, size_t size
)
2411 return getxattr(path
, name
, value
, size
);
2414 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2416 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2419 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
, const char *path
, char *list
, size_t size
)
2421 return listxattr(path
, list
, size
);
2424 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2426 return flistxattr(fsp
->fh
->fd
, list
, size
);
2429 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
)
2431 return removexattr(path
, name
);
2434 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2436 return fremovexattr(fsp
->fh
->fd
, name
);
2439 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
2441 return setxattr(path
, name
, value
, size
, flags
);
2444 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2446 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2449 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2454 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2455 const struct smb_filename
*fname
,
2456 SMB_STRUCT_STAT
*sbuf
)
2460 bool offline
= false;
2462 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2466 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2467 #if defined(ENOTSUP)
2473 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2474 if (!NT_STATUS_IS_OK(status
)) {
2475 errno
= map_errno_from_nt_status(status
);
2479 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2486 static int vfswrap_set_offline(struct vfs_handle_struct
*handle
,
2487 const struct smb_filename
*fname
)
2489 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2490 #if defined(ENOTSUP)
2496 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
2497 struct files_struct
*fsp
,
2498 TALLOC_CTX
*mem_ctx
,
2501 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
2504 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
2505 struct files_struct
*fsp
,
2506 const DATA_BLOB old_cookie
,
2507 TALLOC_CTX
*mem_ctx
,
2508 DATA_BLOB
*new_cookie
)
2510 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
2514 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
2515 struct smb_request
*smb1req
,
2516 struct smbXsrv_open
*op
,
2517 const DATA_BLOB old_cookie
,
2518 TALLOC_CTX
*mem_ctx
,
2519 struct files_struct
**fsp
,
2520 DATA_BLOB
*new_cookie
)
2522 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
2523 old_cookie
, mem_ctx
,
2527 static struct vfs_fn_pointers vfs_default_fns
= {
2528 /* Disk operations */
2530 .connect_fn
= vfswrap_connect
,
2531 .disconnect_fn
= vfswrap_disconnect
,
2532 .disk_free_fn
= vfswrap_disk_free
,
2533 .get_quota_fn
= vfswrap_get_quota
,
2534 .set_quota_fn
= vfswrap_set_quota
,
2535 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
2536 .statvfs_fn
= vfswrap_statvfs
,
2537 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
2538 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
2539 .snap_check_path_fn
= vfswrap_snap_check_path
,
2540 .snap_create_fn
= vfswrap_snap_create
,
2541 .snap_delete_fn
= vfswrap_snap_delete
,
2543 /* Directory operations */
2545 .opendir_fn
= vfswrap_opendir
,
2546 .fdopendir_fn
= vfswrap_fdopendir
,
2547 .readdir_fn
= vfswrap_readdir
,
2548 .readdir_attr_fn
= vfswrap_readdir_attr
,
2549 .seekdir_fn
= vfswrap_seekdir
,
2550 .telldir_fn
= vfswrap_telldir
,
2551 .rewind_dir_fn
= vfswrap_rewinddir
,
2552 .mkdir_fn
= vfswrap_mkdir
,
2553 .rmdir_fn
= vfswrap_rmdir
,
2554 .closedir_fn
= vfswrap_closedir
,
2555 .init_search_op_fn
= vfswrap_init_search_op
,
2557 /* File operations */
2559 .open_fn
= vfswrap_open
,
2560 .create_file_fn
= vfswrap_create_file
,
2561 .close_fn
= vfswrap_close
,
2562 .read_fn
= vfswrap_read
,
2563 .pread_fn
= vfswrap_pread
,
2564 .pread_send_fn
= vfswrap_pread_send
,
2565 .pread_recv_fn
= vfswrap_asys_ssize_t_recv
,
2566 .write_fn
= vfswrap_write
,
2567 .pwrite_fn
= vfswrap_pwrite
,
2568 .pwrite_send_fn
= vfswrap_pwrite_send
,
2569 .pwrite_recv_fn
= vfswrap_asys_ssize_t_recv
,
2570 .lseek_fn
= vfswrap_lseek
,
2571 .sendfile_fn
= vfswrap_sendfile
,
2572 .recvfile_fn
= vfswrap_recvfile
,
2573 .rename_fn
= vfswrap_rename
,
2574 .fsync_fn
= vfswrap_fsync
,
2575 .fsync_send_fn
= vfswrap_fsync_send
,
2576 .fsync_recv_fn
= vfswrap_asys_int_recv
,
2577 .stat_fn
= vfswrap_stat
,
2578 .fstat_fn
= vfswrap_fstat
,
2579 .lstat_fn
= vfswrap_lstat
,
2580 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
2581 .unlink_fn
= vfswrap_unlink
,
2582 .chmod_fn
= vfswrap_chmod
,
2583 .fchmod_fn
= vfswrap_fchmod
,
2584 .chown_fn
= vfswrap_chown
,
2585 .fchown_fn
= vfswrap_fchown
,
2586 .lchown_fn
= vfswrap_lchown
,
2587 .chdir_fn
= vfswrap_chdir
,
2588 .getwd_fn
= vfswrap_getwd
,
2589 .ntimes_fn
= vfswrap_ntimes
,
2590 .ftruncate_fn
= vfswrap_ftruncate
,
2591 .fallocate_fn
= vfswrap_fallocate
,
2592 .lock_fn
= vfswrap_lock
,
2593 .kernel_flock_fn
= vfswrap_kernel_flock
,
2594 .linux_setlease_fn
= vfswrap_linux_setlease
,
2595 .getlock_fn
= vfswrap_getlock
,
2596 .symlink_fn
= vfswrap_symlink
,
2597 .readlink_fn
= vfswrap_readlink
,
2598 .link_fn
= vfswrap_link
,
2599 .mknod_fn
= vfswrap_mknod
,
2600 .realpath_fn
= vfswrap_realpath
,
2601 .chflags_fn
= vfswrap_chflags
,
2602 .file_id_create_fn
= vfswrap_file_id_create
,
2603 .streaminfo_fn
= vfswrap_streaminfo
,
2604 .get_real_filename_fn
= vfswrap_get_real_filename
,
2605 .connectpath_fn
= vfswrap_connectpath
,
2606 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
2607 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
2608 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
2609 .strict_lock_fn
= vfswrap_strict_lock
,
2610 .strict_unlock_fn
= vfswrap_strict_unlock
,
2611 .translate_name_fn
= vfswrap_translate_name
,
2612 .fsctl_fn
= vfswrap_fsctl
,
2613 .copy_chunk_send_fn
= vfswrap_copy_chunk_send
,
2614 .copy_chunk_recv_fn
= vfswrap_copy_chunk_recv
,
2615 .get_compression_fn
= vfswrap_get_compression
,
2616 .set_compression_fn
= vfswrap_set_compression
,
2618 /* NT ACL operations. */
2620 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
2621 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
2622 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
2623 .audit_file_fn
= vfswrap_audit_file
,
2625 /* POSIX ACL operations. */
2627 .chmod_acl_fn
= vfswrap_chmod_acl
,
2628 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
2630 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
2631 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
2632 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
2633 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
2634 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
2635 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
2636 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
2638 /* EA operations. */
2639 .getxattr_fn
= vfswrap_getxattr
,
2640 .fgetxattr_fn
= vfswrap_fgetxattr
,
2641 .listxattr_fn
= vfswrap_listxattr
,
2642 .flistxattr_fn
= vfswrap_flistxattr
,
2643 .removexattr_fn
= vfswrap_removexattr
,
2644 .fremovexattr_fn
= vfswrap_fremovexattr
,
2645 .setxattr_fn
= vfswrap_setxattr
,
2646 .fsetxattr_fn
= vfswrap_fsetxattr
,
2648 /* aio operations */
2649 .aio_force_fn
= vfswrap_aio_force
,
2651 /* offline operations */
2652 .is_offline_fn
= vfswrap_is_offline
,
2653 .set_offline_fn
= vfswrap_set_offline
,
2655 /* durable handle operations */
2656 .durable_cookie_fn
= vfswrap_durable_cookie
,
2657 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
2658 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
2661 NTSTATUS
vfs_default_init(void);
2662 NTSTATUS
vfs_default_init(void)
2664 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
2665 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);