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
, bool small_query
, uint64_t *bsize
,
58 uint64_t *dfree
, uint64_t *dsize
)
62 result
= sys_disk_free(handle
->conn
, path
, small_query
, bsize
, dfree
, dsize
);
66 static int vfswrap_get_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
68 #ifdef HAVE_SYS_QUOTAS
71 START_PROFILE(syscall_get_quota
);
72 result
= sys_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
73 END_PROFILE(syscall_get_quota
);
81 static int vfswrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
83 #ifdef HAVE_SYS_QUOTAS
86 START_PROFILE(syscall_set_quota
);
87 result
= sys_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
88 END_PROFILE(syscall_set_quota
);
96 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
97 struct files_struct
*fsp
,
98 struct shadow_copy_data
*shadow_copy_data
,
102 return -1; /* Not implemented. */
105 static int vfswrap_statvfs(struct vfs_handle_struct
*handle
, const char *path
, vfs_statvfs_struct
*statbuf
)
107 return sys_statvfs(path
, statbuf
);
110 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct
*handle
,
111 enum timestamp_set_resolution
*p_ts_res
)
113 connection_struct
*conn
= handle
->conn
;
114 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
115 struct smb_filename
*smb_fname_cpath
= NULL
;
116 struct vfs_statvfs_struct statbuf
;
119 ZERO_STRUCT(statbuf
);
120 ret
= sys_statvfs(conn
->connectpath
, &statbuf
);
122 caps
= statbuf
.FsCapabilities
;
125 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
127 /* Work out what timestamp resolution we can
128 * use when setting a timestamp. */
130 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(), conn
->connectpath
,
132 if (smb_fname_cpath
== NULL
) {
136 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
138 TALLOC_FREE(smb_fname_cpath
);
142 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
143 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
144 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
145 /* If any of the normal UNIX directory timestamps
146 * have a non-zero tv_nsec component assume
147 * we might be able to set sub-second timestamps.
148 * See what filetime set primitives we have.
150 #if defined(HAVE_UTIMENSAT)
151 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
152 #elif defined(HAVE_UTIMES)
153 /* utimes allows msec timestamps to be set. */
154 *p_ts_res
= TIMESTAMP_SET_MSEC
;
155 #elif defined(HAVE_UTIME)
156 /* utime only allows sec timestamps to be set. */
157 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
160 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
162 "available on share %s, directory %s\n",
163 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
164 lp_servicename(talloc_tos(), conn
->params
->service
),
165 conn
->connectpath
));
167 TALLOC_FREE(smb_fname_cpath
);
171 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
172 struct dfs_GetDFSReferral
*r
)
174 struct junction_map
*junction
= NULL
;
176 bool self_referral
= false;
177 char *pathnamep
= NULL
;
178 char *local_dfs_path
= NULL
;
181 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
184 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
187 /* get the junction entry */
188 if (r
->in
.req
.servername
== NULL
) {
189 return NT_STATUS_NOT_FOUND
;
193 * Trim pathname sent by client so it begins with only one backslash.
194 * Two backslashes confuse some dfs clients
197 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
198 if (local_dfs_path
== NULL
) {
199 return NT_STATUS_NO_MEMORY
;
201 pathnamep
= local_dfs_path
;
202 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
203 IS_DIRECTORY_SEP(pathnamep
[1])) {
207 junction
= talloc_zero(r
, struct junction_map
);
208 if (junction
== NULL
) {
209 return NT_STATUS_NO_MEMORY
;
212 /* The following call can change cwd. */
213 status
= get_referred_path(r
, pathnamep
,
214 !handle
->conn
->sconn
->using_smb2
,
215 junction
, &consumedcnt
, &self_referral
);
216 if (!NT_STATUS_IS_OK(status
)) {
217 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
220 vfs_ChDir(handle
->conn
, handle
->conn
->connectpath
);
222 if (!self_referral
) {
223 pathnamep
[consumedcnt
] = '\0';
226 dbgtext("Path %s to alternate path(s):",
228 for (i
=0; i
< junction
->referral_count
; i
++) {
230 junction
->referral_list
[i
].alternate_path
);
236 if (r
->in
.req
.max_referral_level
<= 2) {
237 max_referral_level
= 2;
239 if (r
->in
.req
.max_referral_level
>= 3) {
240 max_referral_level
= 3;
243 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
244 if (r
->out
.resp
== NULL
) {
245 return NT_STATUS_NO_MEMORY
;
248 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
249 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
251 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
253 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
256 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
257 struct dfs_referral_type
,
258 r
->out
.resp
->nb_referrals
);
259 if (r
->out
.resp
->referral_entries
== NULL
) {
260 return NT_STATUS_NO_MEMORY
;
263 switch (max_referral_level
) {
265 for(i
=0; i
< junction
->referral_count
; i
++) {
266 struct referral
*ref
= &junction
->referral_list
[i
];
267 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
268 struct dfs_referral_type
*t
=
269 &r
->out
.resp
->referral_entries
[i
];
270 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
273 v2
->size
= VERSION2_REFERRAL_SIZE
;
275 v2
->server_type
= DFS_SERVER_ROOT
;
277 v2
->server_type
= DFS_SERVER_NON_ROOT
;
280 v2
->proximity
= ref
->proximity
;
282 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
283 if (v2
->DFS_path
== NULL
) {
284 return NT_STATUS_NO_MEMORY
;
286 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
287 if (v2
->DFS_alt_path
== NULL
) {
288 return NT_STATUS_NO_MEMORY
;
290 v2
->netw_address
= talloc_strdup(mem_ctx
,
291 ref
->alternate_path
);
292 if (v2
->netw_address
== NULL
) {
293 return NT_STATUS_NO_MEMORY
;
299 for(i
=0; i
< junction
->referral_count
; i
++) {
300 struct referral
*ref
= &junction
->referral_list
[i
];
301 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
302 struct dfs_referral_type
*t
=
303 &r
->out
.resp
->referral_entries
[i
];
304 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
305 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
308 v3
->size
= VERSION3_REFERRAL_SIZE
;
310 v3
->server_type
= DFS_SERVER_ROOT
;
312 v3
->server_type
= DFS_SERVER_NON_ROOT
;
316 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
317 if (r1
->DFS_path
== NULL
) {
318 return NT_STATUS_NO_MEMORY
;
320 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
321 if (r1
->DFS_alt_path
== NULL
) {
322 return NT_STATUS_NO_MEMORY
;
324 r1
->netw_address
= talloc_strdup(mem_ctx
,
325 ref
->alternate_path
);
326 if (r1
->netw_address
== NULL
) {
327 return NT_STATUS_NO_MEMORY
;
332 DEBUG(0,("Invalid dfs referral version: %d\n",
333 max_referral_level
));
334 return NT_STATUS_INVALID_LEVEL
;
338 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
344 /* Directory operations */
346 static DIR *vfswrap_opendir(vfs_handle_struct
*handle
, const char *fname
, const char *mask
, uint32 attr
)
350 START_PROFILE(syscall_opendir
);
351 result
= opendir(fname
);
352 END_PROFILE(syscall_opendir
);
356 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
363 START_PROFILE(syscall_fdopendir
);
364 result
= sys_fdopendir(fsp
->fh
->fd
);
365 END_PROFILE(syscall_fdopendir
);
370 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
372 SMB_STRUCT_STAT
*sbuf
)
374 struct dirent
*result
;
376 START_PROFILE(syscall_readdir
);
377 result
= readdir(dirp
);
378 END_PROFILE(syscall_readdir
);
380 /* Default Posix readdir() does not give us stat info.
381 * Set to invalid to indicate we didn't return this info. */
382 SET_STAT_INVALID(*sbuf
);
383 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
384 if (result
!= NULL
) {
385 /* See if we can efficiently return this. */
387 int flags
= (lp_posix_pathnames() ?
388 AT_SYMLINK_NOFOLLOW
: 0);
389 int ret
= fstatat(dirfd(dirp
),
394 init_stat_ex_from_stat(sbuf
,
396 lp_fake_directory_create_times(
397 SNUM(handle
->conn
)));
405 static NTSTATUS
vfswrap_readdir_attr(struct vfs_handle_struct
*handle
,
406 const struct smb_filename
*fname
,
408 struct readdir_attr_data
**attr_data
)
410 return NT_STATUS_NOT_SUPPORTED
;
413 static void vfswrap_seekdir(vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
415 START_PROFILE(syscall_seekdir
);
416 seekdir(dirp
, offset
);
417 END_PROFILE(syscall_seekdir
);
420 static long vfswrap_telldir(vfs_handle_struct
*handle
, DIR *dirp
)
423 START_PROFILE(syscall_telldir
);
424 result
= telldir(dirp
);
425 END_PROFILE(syscall_telldir
);
429 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
431 START_PROFILE(syscall_rewinddir
);
433 END_PROFILE(syscall_rewinddir
);
436 static int vfswrap_mkdir(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
439 bool has_dacl
= False
;
442 START_PROFILE(syscall_mkdir
);
444 if (lp_inherit_acls(SNUM(handle
->conn
))
445 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
446 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
)))
447 mode
= (0777 & lp_directory_mask(SNUM(handle
->conn
)));
451 result
= mkdir(path
, mode
);
453 if (result
== 0 && !has_dacl
) {
455 * We need to do this as the default behavior of POSIX ACLs
456 * is to set the mask to be the requested group permission
457 * bits, not the group permission bits to be the requested
458 * group permission bits. This is not what we want, as it will
459 * mess up any inherited ACL bits that were set. JRA.
461 int saved_errno
= errno
; /* We may get ENOSYS */
462 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, path
, mode
) == -1) && (errno
== ENOSYS
))
466 END_PROFILE(syscall_mkdir
);
470 static int vfswrap_rmdir(vfs_handle_struct
*handle
, const char *path
)
474 START_PROFILE(syscall_rmdir
);
475 result
= rmdir(path
);
476 END_PROFILE(syscall_rmdir
);
480 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
484 START_PROFILE(syscall_closedir
);
485 result
= closedir(dirp
);
486 END_PROFILE(syscall_closedir
);
490 static void vfswrap_init_search_op(vfs_handle_struct
*handle
,
493 /* Default behavior is a NOOP */
496 /* File operations */
498 static int vfswrap_open(vfs_handle_struct
*handle
,
499 struct smb_filename
*smb_fname
,
500 files_struct
*fsp
, int flags
, mode_t mode
)
504 START_PROFILE(syscall_open
);
506 if (smb_fname
->stream_name
) {
511 result
= open(smb_fname
->base_name
, flags
, mode
);
513 END_PROFILE(syscall_open
);
517 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
518 struct smb_request
*req
,
519 uint16_t root_dir_fid
,
520 struct smb_filename
*smb_fname
,
521 uint32_t access_mask
,
522 uint32_t share_access
,
523 uint32_t create_disposition
,
524 uint32_t create_options
,
525 uint32_t file_attributes
,
526 uint32_t oplock_request
,
527 struct smb2_lease
*lease
,
528 uint64_t allocation_size
,
529 uint32_t private_flags
,
530 struct security_descriptor
*sd
,
531 struct ea_list
*ea_list
,
532 files_struct
**result
,
534 const struct smb2_create_blobs
*in_context_blobs
,
535 struct smb2_create_blobs
*out_context_blobs
)
537 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
538 access_mask
, share_access
,
539 create_disposition
, create_options
,
540 file_attributes
, oplock_request
, lease
,
541 allocation_size
, private_flags
,
543 pinfo
, in_context_blobs
, out_context_blobs
);
546 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
550 START_PROFILE(syscall_close
);
551 result
= fd_close_posix(fsp
);
552 END_PROFILE(syscall_close
);
556 static ssize_t
vfswrap_read(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
560 START_PROFILE_BYTES(syscall_read
, n
);
561 result
= sys_read(fsp
->fh
->fd
, data
, n
);
562 END_PROFILE_BYTES(syscall_read
);
566 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
567 size_t n
, off_t offset
)
571 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
572 START_PROFILE_BYTES(syscall_pread
, n
);
573 result
= sys_pread(fsp
->fh
->fd
, data
, n
, offset
);
574 END_PROFILE_BYTES(syscall_pread
);
576 if (result
== -1 && errno
== ESPIPE
) {
577 /* Maintain the fiction that pipes can be seeked (sought?) on. */
578 result
= SMB_VFS_READ(fsp
, data
, n
);
582 #else /* HAVE_PREAD */
586 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
587 if (curr
== -1 && errno
== ESPIPE
) {
588 /* Maintain the fiction that pipes can be seeked (sought?) on. */
589 result
= SMB_VFS_READ(fsp
, data
, n
);
594 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
599 result
= SMB_VFS_READ(fsp
, data
, n
);
602 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
605 #endif /* HAVE_PREAD */
610 static ssize_t
vfswrap_write(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
614 START_PROFILE_BYTES(syscall_write
, n
);
615 result
= sys_write(fsp
->fh
->fd
, data
, n
);
616 END_PROFILE_BYTES(syscall_write
);
620 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
621 size_t n
, off_t offset
)
625 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
626 START_PROFILE_BYTES(syscall_pwrite
, n
);
627 result
= sys_pwrite(fsp
->fh
->fd
, data
, n
, offset
);
628 END_PROFILE_BYTES(syscall_pwrite
);
630 if (result
== -1 && errno
== ESPIPE
) {
631 /* Maintain the fiction that pipes can be sought on. */
632 result
= SMB_VFS_WRITE(fsp
, data
, n
);
635 #else /* HAVE_PWRITE */
639 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
644 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
648 result
= SMB_VFS_WRITE(fsp
, data
, n
);
651 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
654 #endif /* HAVE_PWRITE */
659 static void vfswrap_asys_finished(struct tevent_context
*ev
,
660 struct tevent_fd
*fde
,
661 uint16_t flags
, void *p
);
663 static bool vfswrap_init_asys_ctx(struct smbd_server_connection
*conn
)
668 if (conn
->asys_ctx
!= NULL
) {
671 ret
= asys_context_init(&conn
->asys_ctx
, aio_pending_size
);
673 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret
)));
677 fd
= asys_signalfd(conn
->asys_ctx
);
679 set_blocking(fd
, false);
681 conn
->asys_fde
= tevent_add_fd(conn
->ev_ctx
, conn
, fd
,
683 vfswrap_asys_finished
,
685 if (conn
->asys_fde
== NULL
) {
686 DEBUG(1, ("tevent_add_fd failed\n"));
687 asys_context_destroy(conn
->asys_ctx
);
688 conn
->asys_ctx
= NULL
;
694 struct vfswrap_asys_state
{
695 struct asys_context
*asys_ctx
;
696 struct tevent_req
*req
;
699 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic
);
700 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
703 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state
*s
)
705 asys_cancel(s
->asys_ctx
, s
->req
);
709 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
711 struct tevent_context
*ev
,
712 struct files_struct
*fsp
,
714 size_t n
, off_t offset
)
716 struct tevent_req
*req
;
717 struct vfswrap_asys_state
*state
;
720 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_asys_state
);
724 if (!vfswrap_init_asys_ctx(handle
->conn
->sconn
)) {
726 return tevent_req_post(req
, ev
);
728 state
->asys_ctx
= handle
->conn
->sconn
->asys_ctx
;
731 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
732 state
->profile_bytes
, n
);
733 ret
= asys_pread(state
->asys_ctx
, fsp
->fh
->fd
, data
, n
, offset
, req
);
735 tevent_req_error(req
, ret
);
736 return tevent_req_post(req
, ev
);
738 talloc_set_destructor(state
, vfswrap_asys_state_destructor
);
743 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
745 struct tevent_context
*ev
,
746 struct files_struct
*fsp
,
748 size_t n
, off_t offset
)
750 struct tevent_req
*req
;
751 struct vfswrap_asys_state
*state
;
754 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_asys_state
);
758 if (!vfswrap_init_asys_ctx(handle
->conn
->sconn
)) {
760 return tevent_req_post(req
, ev
);
762 state
->asys_ctx
= handle
->conn
->sconn
->asys_ctx
;
765 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
766 state
->profile_bytes
, n
);
767 ret
= asys_pwrite(state
->asys_ctx
, fsp
->fh
->fd
, data
, n
, offset
, req
);
769 tevent_req_error(req
, ret
);
770 return tevent_req_post(req
, ev
);
772 talloc_set_destructor(state
, vfswrap_asys_state_destructor
);
777 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
779 struct tevent_context
*ev
,
780 struct files_struct
*fsp
)
782 struct tevent_req
*req
;
783 struct vfswrap_asys_state
*state
;
786 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_asys_state
);
790 if (!vfswrap_init_asys_ctx(handle
->conn
->sconn
)) {
792 return tevent_req_post(req
, ev
);
794 state
->asys_ctx
= handle
->conn
->sconn
->asys_ctx
;
797 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync
, profile_p
,
798 state
->profile_basic
);
799 ret
= asys_fsync(state
->asys_ctx
, fsp
->fh
->fd
, req
);
801 tevent_req_error(req
, ret
);
802 return tevent_req_post(req
, ev
);
804 talloc_set_destructor(state
, vfswrap_asys_state_destructor
);
809 static void vfswrap_asys_finished(struct tevent_context
*ev
,
810 struct tevent_fd
*fde
,
811 uint16_t flags
, void *p
)
813 struct asys_context
*asys_ctx
= (struct asys_context
*)p
;
814 struct asys_result results
[outstanding_aio_calls
];
817 if ((flags
& TEVENT_FD_READ
) == 0) {
821 ret
= asys_results(asys_ctx
, results
, outstanding_aio_calls
);
823 DEBUG(1, ("asys_results returned %s\n", strerror(-ret
)));
827 for (i
=0; i
<ret
; i
++) {
828 struct asys_result
*result
= &results
[i
];
829 struct tevent_req
*req
;
830 struct vfswrap_asys_state
*state
;
832 if ((result
->ret
== -1) && (result
->err
== ECANCELED
)) {
836 req
= talloc_get_type_abort(result
->private_data
,
838 state
= tevent_req_data(req
, struct vfswrap_asys_state
);
840 talloc_set_destructor(state
, NULL
);
842 SMBPROFILE_BASIC_ASYNC_END(state
->profile_basic
);
843 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
844 state
->ret
= result
->ret
;
845 state
->err
= result
->err
;
846 tevent_req_defer_callback(req
, ev
);
847 tevent_req_done(req
);
851 static ssize_t
vfswrap_asys_ssize_t_recv(struct tevent_req
*req
, int *err
)
853 struct vfswrap_asys_state
*state
= tevent_req_data(
854 req
, struct vfswrap_asys_state
);
856 if (tevent_req_is_unix_error(req
, err
)) {
863 static int vfswrap_asys_int_recv(struct tevent_req
*req
, int *err
)
865 struct vfswrap_asys_state
*state
= tevent_req_data(
866 req
, struct vfswrap_asys_state
);
868 if (tevent_req_is_unix_error(req
, err
)) {
875 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
879 START_PROFILE(syscall_lseek
);
881 /* Cope with 'stat' file opens. */
882 if (fsp
->fh
->fd
!= -1)
883 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
886 * We want to maintain the fiction that we can seek
887 * on a fifo for file system purposes. This allows
888 * people to set up UNIX fifo's that feed data to Windows
892 if((result
== -1) && (errno
== ESPIPE
)) {
897 END_PROFILE(syscall_lseek
);
901 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
902 off_t offset
, size_t n
)
906 START_PROFILE_BYTES(syscall_sendfile
, n
);
907 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
908 END_PROFILE_BYTES(syscall_sendfile
);
912 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
920 START_PROFILE_BYTES(syscall_recvfile
, n
);
921 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
922 END_PROFILE_BYTES(syscall_recvfile
);
926 static int vfswrap_rename(vfs_handle_struct
*handle
,
927 const struct smb_filename
*smb_fname_src
,
928 const struct smb_filename
*smb_fname_dst
)
932 START_PROFILE(syscall_rename
);
934 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
939 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
942 END_PROFILE(syscall_rename
);
946 static int vfswrap_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
951 START_PROFILE(syscall_fsync
);
952 result
= fsync(fsp
->fh
->fd
);
953 END_PROFILE(syscall_fsync
);
960 static int vfswrap_stat(vfs_handle_struct
*handle
,
961 struct smb_filename
*smb_fname
)
965 START_PROFILE(syscall_stat
);
967 if (smb_fname
->stream_name
) {
972 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
973 lp_fake_directory_create_times(SNUM(handle
->conn
)));
975 END_PROFILE(syscall_stat
);
979 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
983 START_PROFILE(syscall_fstat
);
984 result
= sys_fstat(fsp
->fh
->fd
,
985 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
986 END_PROFILE(syscall_fstat
);
990 static int vfswrap_lstat(vfs_handle_struct
*handle
,
991 struct smb_filename
*smb_fname
)
995 START_PROFILE(syscall_lstat
);
997 if (smb_fname
->stream_name
) {
1002 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1003 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1005 END_PROFILE(syscall_lstat
);
1009 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1011 enum vfs_translate_direction direction
,
1012 TALLOC_CTX
*mem_ctx
,
1015 return NT_STATUS_NONE_MAPPED
;
1019 * Implement the default fsctl operation.
1021 static bool vfswrap_logged_ioctl_message
= false;
1023 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1024 struct files_struct
*fsp
,
1027 uint16_t req_flags
, /* Needed for UNICODE ... */
1028 const uint8_t *_in_data
,
1030 uint8_t **_out_data
,
1031 uint32_t max_out_len
,
1034 const char *in_data
= (const char *)_in_data
;
1035 char **out_data
= (char **)_out_data
;
1039 case FSCTL_SET_SPARSE
:
1041 bool set_sparse
= true;
1043 if (in_len
>= 1 && in_data
[0] == 0) {
1047 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1049 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1050 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1051 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1052 nt_errstr(status
)));
1057 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1059 unsigned char objid
[16];
1060 char *return_data
= NULL
;
1062 /* This should return the object-id on this file.
1063 * I think I'll make this be the inode+dev. JRA.
1066 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1067 fsp_fnum_dbg(fsp
)));
1069 *out_len
= MIN(max_out_len
, 64);
1071 /* Hmmm, will this cause problems if less data asked for? */
1072 return_data
= talloc_array(ctx
, char, 64);
1073 if (return_data
== NULL
) {
1074 return NT_STATUS_NO_MEMORY
;
1077 /* For backwards compatibility only store the dev/inode. */
1078 push_file_id_16(return_data
, &fsp
->file_id
);
1079 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1080 push_file_id_16(return_data
+32, &fsp
->file_id
);
1081 memset(return_data
+48, 0, 16);
1082 *out_data
= return_data
;
1083 return NT_STATUS_OK
;
1086 case FSCTL_GET_REPARSE_POINT
:
1088 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1089 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1090 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1091 return NT_STATUS_NOT_A_REPARSE_POINT
;
1094 case FSCTL_SET_REPARSE_POINT
:
1096 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1097 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1098 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
1099 return NT_STATUS_NOT_A_REPARSE_POINT
;
1102 case FSCTL_GET_SHADOW_COPY_DATA
:
1105 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1106 * and return their volume names. If max_data_count is 16, then it is just
1107 * asking for the number of volumes and length of the combined names.
1109 * pdata is the data allocated by our caller, but that uses
1110 * total_data_count (which is 0 in our case) rather than max_data_count.
1111 * Allocate the correct amount and return the pointer to let
1112 * it be deallocated when we return.
1114 struct shadow_copy_data
*shadow_data
= NULL
;
1115 bool labels
= False
;
1116 uint32 labels_data_count
= 0;
1118 char *cur_pdata
= NULL
;
1120 if (max_out_len
< 16) {
1121 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1123 return NT_STATUS_INVALID_PARAMETER
;
1126 if (max_out_len
> 16) {
1130 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1131 if (shadow_data
== NULL
) {
1132 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1133 return NT_STATUS_NO_MEMORY
;
1137 * Call the VFS routine to actually do the work.
1139 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1142 /* broken module didn't set errno on error */
1143 status
= NT_STATUS_UNSUCCESSFUL
;
1145 status
= map_nt_error_from_unix(errno
);
1146 if (NT_STATUS_EQUAL(status
,
1147 NT_STATUS_NOT_SUPPORTED
)) {
1151 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1152 "connectpath %s, failed - %s.\n",
1153 fsp
->conn
->connectpath
,
1154 nt_errstr(status
)));
1155 TALLOC_FREE(shadow_data
);
1159 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1160 sizeof(SHADOW_COPY_LABEL
)) + 2;
1165 *out_len
= 12 + labels_data_count
;
1168 if (max_out_len
< *out_len
) {
1169 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1170 max_out_len
, *out_len
));
1171 TALLOC_FREE(shadow_data
);
1172 return NT_STATUS_BUFFER_TOO_SMALL
;
1175 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1176 if (cur_pdata
== NULL
) {
1177 TALLOC_FREE(shadow_data
);
1178 return NT_STATUS_NO_MEMORY
;
1181 *out_data
= cur_pdata
;
1183 /* num_volumes 4 bytes */
1184 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1187 /* num_labels 4 bytes */
1188 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1191 /* needed_data_count 4 bytes */
1192 SIVAL(cur_pdata
, 8, labels_data_count
);
1196 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1197 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
1198 if (labels
&& shadow_data
->labels
) {
1199 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1201 status
= srvstr_push(cur_pdata
, req_flags
,
1202 cur_pdata
, shadow_data
->labels
[i
],
1203 2 * sizeof(SHADOW_COPY_LABEL
),
1204 STR_UNICODE
|STR_TERMINATE
, &len
);
1205 if (!NT_STATUS_IS_OK(status
)) {
1206 TALLOC_FREE(*out_data
);
1207 TALLOC_FREE(shadow_data
);
1210 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1211 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1215 TALLOC_FREE(shadow_data
);
1217 return NT_STATUS_OK
;
1220 case FSCTL_FIND_FILES_BY_SID
:
1222 /* pretend this succeeded -
1224 * we have to send back a list with all files owned by this SID
1226 * but I have to check that --metze
1232 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1233 fsp_fnum_dbg(fsp
)));
1236 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1237 return NT_STATUS_INVALID_PARAMETER
;
1240 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1242 /* unknown 4 bytes: this is not the length of the sid :-( */
1243 /*unknown = IVAL(pdata,0);*/
1245 if (!sid_parse(in_data
+ 4, sid_len
, &sid
)) {
1246 return NT_STATUS_INVALID_PARAMETER
;
1248 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
1250 if (!sid_to_uid(&sid
, &uid
)) {
1251 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1252 sid_string_dbg(&sid
),
1253 (unsigned long)sid_len
));
1257 /* we can take a look at the find source :-)
1259 * find ./ -uid $uid -name '*' is what we need here
1262 * and send 4bytes len and then NULL terminated unicode strings
1265 * but I don't know how to deal with the paged results
1266 * (maybe we can hang the result anywhere in the fsp struct)
1268 * but I don't know how to deal with the paged results
1269 * (maybe we can hang the result anywhere in the fsp struct)
1271 * we don't send all files at once
1272 * and at the next we should *not* start from the beginning,
1273 * so we have to cache the result
1278 /* this works for now... */
1279 return NT_STATUS_OK
;
1282 case FSCTL_QUERY_ALLOCATED_RANGES
:
1284 /* FIXME: This is just a dummy reply, telling that all of the
1285 * file is allocated. MKS cp needs that.
1286 * Adding the real allocated ranges via FIEMAP on Linux
1287 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1288 * this FSCTL correct for sparse files.
1290 uint64_t offset
, length
;
1291 char *out_data_tmp
= NULL
;
1294 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1296 return NT_STATUS_INVALID_PARAMETER
;
1299 if (max_out_len
< 16) {
1300 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1302 return NT_STATUS_INVALID_PARAMETER
;
1305 offset
= BVAL(in_data
,0);
1306 length
= BVAL(in_data
,8);
1308 if (offset
+ length
< offset
) {
1309 /* No 64-bit integer wrap. */
1310 return NT_STATUS_INVALID_PARAMETER
;
1313 /* Shouldn't this be SMB_VFS_STAT ... ? */
1314 status
= vfs_stat_fsp(fsp
);
1315 if (!NT_STATUS_IS_OK(status
)) {
1320 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1321 if (out_data_tmp
== NULL
) {
1322 DEBUG(10, ("unable to allocate memory for response\n"));
1323 return NT_STATUS_NO_MEMORY
;
1326 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1327 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1329 memset(out_data_tmp
, 0, *out_len
);
1331 uint64_t end
= offset
+ length
;
1332 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1333 SBVAL(out_data_tmp
, 0, 0);
1334 SBVAL(out_data_tmp
, 8, end
);
1337 *out_data
= out_data_tmp
;
1339 return NT_STATUS_OK
;
1342 case FSCTL_IS_VOLUME_DIRTY
:
1344 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1345 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
)));
1347 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1348 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1350 return NT_STATUS_INVALID_PARAMETER
;
1355 * Only print once ... unfortunately there could be lots of
1356 * different FSCTLs that are called.
1358 if (!vfswrap_logged_ioctl_message
) {
1359 vfswrap_logged_ioctl_message
= true;
1360 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1361 __func__
, function
));
1365 return NT_STATUS_NOT_SUPPORTED
;
1368 struct vfs_cc_state
{
1373 static struct tevent_req
*vfswrap_copy_chunk_send(struct vfs_handle_struct
*handle
,
1374 TALLOC_CTX
*mem_ctx
,
1375 struct tevent_context
*ev
,
1376 struct files_struct
*src_fsp
,
1378 struct files_struct
*dest_fsp
,
1382 struct tevent_req
*req
;
1383 struct vfs_cc_state
*vfs_cc_state
;
1386 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1387 (unsigned long)num
));
1389 req
= tevent_req_create(mem_ctx
, &vfs_cc_state
, struct vfs_cc_state
);
1394 status
= vfs_stat_fsp(src_fsp
);
1395 if (tevent_req_nterror(req
, status
)) {
1396 return tevent_req_post(req
, ev
);
1399 if (src_fsp
->fsp_name
->st
.st_ex_size
< src_off
+ num
) {
1401 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1402 * If the SourceOffset or SourceOffset + Length extends beyond
1403 * the end of file, the server SHOULD<240> treat this as a
1404 * STATUS_END_OF_FILE error.
1406 * <240> Section 3.3.5.15.6: Windows servers will return
1407 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1409 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
1410 return tevent_req_post(req
, ev
);
1413 /* could use 2.6.33+ sendfile here to do this in kernel */
1414 while (vfs_cc_state
->copied
< num
) {
1416 struct lock_struct lck
;
1419 off_t this_num
= MIN(sizeof(vfs_cc_state
->buf
),
1420 num
- vfs_cc_state
->copied
);
1422 if (src_fsp
->op
== NULL
) {
1423 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1424 return tevent_req_post(req
, ev
);
1426 init_strict_lock_struct(src_fsp
,
1427 src_fsp
->op
->global
->open_persistent_id
,
1433 if (!SMB_VFS_STRICT_LOCK(src_fsp
->conn
, src_fsp
, &lck
)) {
1434 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1435 return tevent_req_post(req
, ev
);
1438 ret
= SMB_VFS_PREAD(src_fsp
, vfs_cc_state
->buf
,
1441 saved_errno
= errno
;
1444 SMB_VFS_STRICT_UNLOCK(src_fsp
->conn
, src_fsp
, &lck
);
1447 errno
= saved_errno
;
1448 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
1449 return tevent_req_post(req
, ev
);
1451 if (ret
!= this_num
) {
1452 /* zero tolerance for short reads */
1453 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1454 return tevent_req_post(req
, ev
);
1459 if (dest_fsp
->op
== NULL
) {
1460 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1461 return tevent_req_post(req
, ev
);
1464 init_strict_lock_struct(dest_fsp
,
1465 dest_fsp
->op
->global
->open_persistent_id
,
1471 if (!SMB_VFS_STRICT_LOCK(dest_fsp
->conn
, dest_fsp
, &lck
)) {
1472 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
1473 return tevent_req_post(req
, ev
);
1476 ret
= SMB_VFS_PWRITE(dest_fsp
, vfs_cc_state
->buf
,
1477 this_num
, dest_off
);
1479 saved_errno
= errno
;
1482 SMB_VFS_STRICT_UNLOCK(src_fsp
->conn
, src_fsp
, &lck
);
1485 errno
= saved_errno
;
1486 tevent_req_nterror(req
, map_nt_error_from_unix(errno
));
1487 return tevent_req_post(req
, ev
);
1489 if (ret
!= this_num
) {
1490 /* zero tolerance for short writes */
1491 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
1492 return tevent_req_post(req
, ev
);
1496 vfs_cc_state
->copied
+= this_num
;
1499 tevent_req_done(req
);
1500 return tevent_req_post(req
, ev
);
1503 static NTSTATUS
vfswrap_copy_chunk_recv(struct vfs_handle_struct
*handle
,
1504 struct tevent_req
*req
,
1507 struct vfs_cc_state
*vfs_cc_state
= tevent_req_data(req
,
1508 struct vfs_cc_state
);
1511 if (tevent_req_is_nterror(req
, &status
)) {
1512 DEBUG(2, ("server side copy chunk failed: %s\n",
1513 nt_errstr(status
)));
1515 tevent_req_received(req
);
1519 *copied
= vfs_cc_state
->copied
;
1520 DEBUG(10, ("server side copy chunk copied %lu\n",
1521 (unsigned long)*copied
));
1522 tevent_req_received(req
);
1524 return NT_STATUS_OK
;
1527 static NTSTATUS
vfswrap_get_compression(struct vfs_handle_struct
*handle
,
1528 TALLOC_CTX
*mem_ctx
,
1529 struct files_struct
*fsp
,
1530 struct smb_filename
*smb_fname
,
1531 uint16_t *_compression_fmt
)
1533 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1536 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
1537 TALLOC_CTX
*mem_ctx
,
1538 struct files_struct
*fsp
,
1539 uint16_t compression_fmt
)
1541 return NT_STATUS_INVALID_DEVICE_REQUEST
;
1544 /********************************************************************
1545 Given a stat buffer return the allocated size on disk, taking into
1546 account sparse files.
1547 ********************************************************************/
1548 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
1549 struct files_struct
*fsp
,
1550 const SMB_STRUCT_STAT
*sbuf
)
1554 START_PROFILE(syscall_get_alloc_size
);
1556 if(S_ISDIR(sbuf
->st_ex_mode
)) {
1561 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1562 /* The type of st_blocksize is blkcnt_t which *MUST* be
1563 signed (according to POSIX) and can be less than 64-bits.
1564 Ensure when we're converting to 64 bits wide we don't
1566 #if defined(SIZEOF_BLKCNT_T_8)
1567 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
1568 #elif defined(SIZEOF_BLKCNT_T_4)
1570 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
1571 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
1574 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1578 * Some file systems do not allocate a block for very
1579 * small files. But for non-empty file should report a
1583 uint64_t filesize
= get_file_size_stat(sbuf
);
1585 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
1589 result
= get_file_size_stat(sbuf
);
1592 if (fsp
&& fsp
->initial_allocation_size
)
1593 result
= MAX(result
,fsp
->initial_allocation_size
);
1595 result
= smb_roundup(handle
->conn
, result
);
1598 END_PROFILE(syscall_get_alloc_size
);
1602 static int vfswrap_unlink(vfs_handle_struct
*handle
,
1603 const struct smb_filename
*smb_fname
)
1607 START_PROFILE(syscall_unlink
);
1609 if (smb_fname
->stream_name
) {
1613 result
= unlink(smb_fname
->base_name
);
1616 END_PROFILE(syscall_unlink
);
1620 static int vfswrap_chmod(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
1624 START_PROFILE(syscall_chmod
);
1627 * We need to do this due to the fact that the default POSIX ACL
1628 * chmod modifies the ACL *mask* for the group owner, not the
1629 * group owner bits directly. JRA.
1634 int saved_errno
= errno
; /* We might get ENOSYS */
1635 if ((result
= SMB_VFS_CHMOD_ACL(handle
->conn
, path
, mode
)) == 0) {
1636 END_PROFILE(syscall_chmod
);
1639 /* Error - return the old errno. */
1640 errno
= saved_errno
;
1643 result
= chmod(path
, mode
);
1644 END_PROFILE(syscall_chmod
);
1648 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
1652 START_PROFILE(syscall_fchmod
);
1655 * We need to do this due to the fact that the default POSIX ACL
1656 * chmod modifies the ACL *mask* for the group owner, not the
1657 * group owner bits directly. JRA.
1661 int saved_errno
= errno
; /* We might get ENOSYS */
1662 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
1663 END_PROFILE(syscall_fchmod
);
1666 /* Error - return the old errno. */
1667 errno
= saved_errno
;
1670 #if defined(HAVE_FCHMOD)
1671 result
= fchmod(fsp
->fh
->fd
, mode
);
1677 END_PROFILE(syscall_fchmod
);
1681 static int vfswrap_chown(vfs_handle_struct
*handle
, const char *path
, uid_t uid
, gid_t gid
)
1685 START_PROFILE(syscall_chown
);
1686 result
= chown(path
, uid
, gid
);
1687 END_PROFILE(syscall_chown
);
1691 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
1696 START_PROFILE(syscall_fchown
);
1697 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
1698 END_PROFILE(syscall_fchown
);
1706 static int vfswrap_lchown(vfs_handle_struct
*handle
, const char *path
, uid_t uid
, gid_t gid
)
1710 START_PROFILE(syscall_lchown
);
1711 result
= lchown(path
, uid
, gid
);
1712 END_PROFILE(syscall_lchown
);
1716 static int vfswrap_chdir(vfs_handle_struct
*handle
, const char *path
)
1720 START_PROFILE(syscall_chdir
);
1721 result
= chdir(path
);
1722 END_PROFILE(syscall_chdir
);
1726 static char *vfswrap_getwd(vfs_handle_struct
*handle
)
1730 START_PROFILE(syscall_getwd
);
1731 result
= sys_getwd();
1732 END_PROFILE(syscall_getwd
);
1736 /*********************************************************************
1737 nsec timestamp resolution call. Convert down to whatever the underlying
1738 system will support.
1739 **********************************************************************/
1741 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
1742 const struct smb_filename
*smb_fname
,
1743 struct smb_file_time
*ft
)
1747 START_PROFILE(syscall_ntimes
);
1749 if (smb_fname
->stream_name
) {
1755 if (null_timespec(ft
->atime
)) {
1756 ft
->atime
= smb_fname
->st
.st_ex_atime
;
1759 if (null_timespec(ft
->mtime
)) {
1760 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
1763 if (!null_timespec(ft
->create_time
)) {
1764 set_create_timespec_ea(handle
->conn
,
1769 if ((timespec_compare(&ft
->atime
,
1770 &smb_fname
->st
.st_ex_atime
) == 0) &&
1771 (timespec_compare(&ft
->mtime
,
1772 &smb_fname
->st
.st_ex_mtime
) == 0)) {
1777 #if defined(HAVE_UTIMENSAT)
1779 struct timespec ts
[2];
1782 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
1784 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
1786 if (!((result
== -1) && (errno
== ENOSYS
))) {
1790 #if defined(HAVE_UTIMES)
1792 struct timeval tv
[2];
1793 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
1794 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
1795 result
= utimes(smb_fname
->base_name
, tv
);
1797 result
= utimes(smb_fname
->base_name
, NULL
);
1799 if (!((result
== -1) && (errno
== ENOSYS
))) {
1803 #if defined(HAVE_UTIME)
1805 struct utimbuf times
;
1806 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
1807 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
1808 result
= utime(smb_fname
->base_name
, ×
);
1810 result
= utime(smb_fname
->base_name
, NULL
);
1812 if (!((result
== -1) && (errno
== ENOSYS
))) {
1820 END_PROFILE(syscall_ntimes
);
1824 /*********************************************************************
1825 A version of ftruncate that will write the space on disk if strict
1827 **********************************************************************/
1829 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1831 off_t space_to_write
;
1832 uint64_t space_avail
;
1833 uint64_t bsize
,dfree
,dsize
;
1836 SMB_STRUCT_STAT
*pst
;
1838 status
= vfs_stat_fsp(fsp
);
1839 if (!NT_STATUS_IS_OK(status
)) {
1842 pst
= &fsp
->fsp_name
->st
;
1845 if (S_ISFIFO(pst
->st_ex_mode
))
1849 if (pst
->st_ex_size
== len
)
1852 /* Shrink - just ftruncate. */
1853 if (pst
->st_ex_size
> len
)
1854 return ftruncate(fsp
->fh
->fd
, len
);
1856 space_to_write
= len
- pst
->st_ex_size
;
1858 /* for allocation try fallocate first. This can fail on some
1859 platforms e.g. when the filesystem doesn't support it and no
1860 emulation is being done by the libc (like on AIX with JFS1). In that
1861 case we do our own emulation. fallocate implementations can
1862 return ENOTSUP or EINVAL in cases like that. */
1863 ret
= SMB_VFS_FALLOCATE(fsp
, VFS_FALLOCATE_EXTEND_SIZE
,
1864 pst
->st_ex_size
, space_to_write
);
1865 if (ret
== -1 && errno
== ENOSPC
) {
1871 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1872 "error %d. Falling back to slow manual allocation\n", errno
));
1874 /* available disk space is enough or not? */
1875 space_avail
= get_dfree_info(fsp
->conn
,
1876 fsp
->fsp_name
->base_name
, false,
1877 &bsize
,&dfree
,&dsize
);
1878 /* space_avail is 1k blocks */
1879 if (space_avail
== (uint64_t)-1 ||
1880 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
1885 /* Write out the real space on disk. */
1886 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
1894 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1897 SMB_STRUCT_STAT
*pst
;
1901 START_PROFILE(syscall_ftruncate
);
1903 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
1904 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
1905 END_PROFILE(syscall_ftruncate
);
1909 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1910 ftruncate if the system supports it. Then I discovered that
1911 you can have some filesystems that support ftruncate
1912 expansion and some that don't! On Linux fat can't do
1913 ftruncate extend but ext2 can. */
1915 result
= ftruncate(fsp
->fh
->fd
, len
);
1919 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1920 extend a file with ftruncate. Provide alternate implementation
1923 /* Do an fstat to see if the file is longer than the requested
1924 size in which case the ftruncate above should have
1925 succeeded or shorter, in which case seek to len - 1 and
1926 write 1 byte of zero */
1927 status
= vfs_stat_fsp(fsp
);
1928 if (!NT_STATUS_IS_OK(status
)) {
1931 pst
= &fsp
->fsp_name
->st
;
1934 if (S_ISFIFO(pst
->st_ex_mode
)) {
1940 if (pst
->st_ex_size
== len
) {
1945 if (pst
->st_ex_size
> len
) {
1946 /* the ftruncate should have worked */
1950 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
1958 END_PROFILE(syscall_ftruncate
);
1962 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
1964 enum vfs_fallocate_mode mode
,
1970 START_PROFILE(syscall_fallocate
);
1971 if (mode
== VFS_FALLOCATE_EXTEND_SIZE
) {
1972 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
1974 * posix_fallocate returns 0 on success, errno on error
1975 * and doesn't set errno. Make it behave like fallocate()
1976 * which returns -1, and sets errno on failure.
1982 } else if (mode
== VFS_FALLOCATE_KEEP_SIZE
) {
1983 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
1988 END_PROFILE(syscall_fallocate
);
1992 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
1996 START_PROFILE(syscall_fcntl_lock
);
1997 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
1998 END_PROFILE(syscall_fcntl_lock
);
2002 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
2003 uint32 share_mode
, uint32 access_mask
)
2005 START_PROFILE(syscall_kernel_flock
);
2006 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
2007 END_PROFILE(syscall_kernel_flock
);
2011 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
2015 START_PROFILE(syscall_fcntl_getlock
);
2016 result
= fcntl_getlock(fsp
->fh
->fd
, poffset
, pcount
, ptype
, ppid
);
2017 END_PROFILE(syscall_fcntl_getlock
);
2021 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
2026 START_PROFILE(syscall_linux_setlease
);
2028 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2029 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
2033 END_PROFILE(syscall_linux_setlease
);
2037 static int vfswrap_symlink(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2041 START_PROFILE(syscall_symlink
);
2042 result
= symlink(oldpath
, newpath
);
2043 END_PROFILE(syscall_symlink
);
2047 static int vfswrap_readlink(vfs_handle_struct
*handle
, const char *path
, char *buf
, size_t bufsiz
)
2051 START_PROFILE(syscall_readlink
);
2052 result
= readlink(path
, buf
, bufsiz
);
2053 END_PROFILE(syscall_readlink
);
2057 static int vfswrap_link(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
2061 START_PROFILE(syscall_link
);
2062 result
= link(oldpath
, newpath
);
2063 END_PROFILE(syscall_link
);
2067 static int vfswrap_mknod(vfs_handle_struct
*handle
, const char *pathname
, mode_t mode
, SMB_DEV_T dev
)
2071 START_PROFILE(syscall_mknod
);
2072 result
= sys_mknod(pathname
, mode
, dev
);
2073 END_PROFILE(syscall_mknod
);
2077 static char *vfswrap_realpath(vfs_handle_struct
*handle
, const char *path
)
2081 START_PROFILE(syscall_realpath
);
2082 #ifdef REALPATH_TAKES_NULL
2083 result
= realpath(path
, NULL
);
2085 result
= SMB_MALLOC_ARRAY(char, PATH_MAX
+1);
2087 char *resolved_path
= realpath(path
, result
);
2088 if (!resolved_path
) {
2091 /* SMB_ASSERT(result == resolved_path) ? */
2092 result
= resolved_path
;
2096 END_PROFILE(syscall_realpath
);
2100 static NTSTATUS
vfswrap_notify_watch(vfs_handle_struct
*vfs_handle
,
2101 struct sys_notify_context
*ctx
,
2104 uint32_t *subdir_filter
,
2105 void (*callback
)(struct sys_notify_context
*ctx
,
2107 struct notify_event
*ev
),
2108 void *private_data
, void *handle
)
2111 * So far inotify is the only supported default notify mechanism. If
2112 * another platform like the the BSD's or a proprietary Unix comes
2113 * along and wants another default, we can play the same trick we
2114 * played with Posix ACLs.
2116 * Until that is the case, hard-code inotify here.
2119 if (lp_kernel_change_notify(vfs_handle
->conn
->params
)) {
2121 if (!lp_parm_bool(-1, "notify", "inotify", True
)) {
2122 return NT_STATUS_INVALID_SYSTEM_SERVICE
;
2125 * "ctx->private_data" is not obvious as a talloc context
2126 * here. Without modifying the VFS we don't have a mem_ctx
2127 * available here, and ctx->private_data was used by
2128 * inotify_watch before it got a real talloc parent.
2130 ret
= inotify_watch(ctx
->private_data
, ctx
,
2131 path
, filter
, subdir_filter
,
2132 callback
, private_data
, handle
);
2134 return map_nt_error_from_unix(ret
);
2136 return NT_STATUS_OK
;
2140 * Do nothing, leave everything to notify_internal.c
2142 return NT_STATUS_OK
;
2145 static int vfswrap_chflags(vfs_handle_struct
*handle
, const char *path
,
2149 return chflags(path
, flags
);
2156 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
2157 const SMB_STRUCT_STAT
*sbuf
)
2161 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2165 key
.devid
= sbuf
->st_ex_dev
;
2166 key
.inode
= sbuf
->st_ex_ino
;
2167 /* key.extid is unused by default. */
2172 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
2173 struct files_struct
*fsp
,
2175 TALLOC_CTX
*mem_ctx
,
2176 unsigned int *pnum_streams
,
2177 struct stream_struct
**pstreams
)
2179 SMB_STRUCT_STAT sbuf
;
2180 struct stream_struct
*tmp_streams
= NULL
;
2183 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
2185 * No default streams on directories
2190 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
2191 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
2194 struct smb_filename smb_fname
;
2196 ZERO_STRUCT(smb_fname
);
2197 smb_fname
.base_name
= discard_const_p(char, fname
);
2199 if (lp_posix_pathnames()) {
2200 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname
);
2202 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname
);
2204 sbuf
= smb_fname
.st
;
2208 return map_nt_error_from_unix(errno
);
2211 if (S_ISDIR(sbuf
.st_ex_mode
)) {
2215 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
2216 (*pnum_streams
) + 1);
2217 if (tmp_streams
== NULL
) {
2218 return NT_STATUS_NO_MEMORY
;
2220 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
2221 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
2222 return NT_STATUS_NO_MEMORY
;
2224 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
2225 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
2228 *pstreams
= tmp_streams
;
2230 return NT_STATUS_OK
;
2233 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
2236 TALLOC_CTX
*mem_ctx
,
2240 * Don't fall back to get_real_filename so callers can differentiate
2241 * between a full directory scan and an actual case-insensitive stat.
2247 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
2250 return handle
->conn
->connectpath
;
2253 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
2254 struct byte_range_lock
*br_lck
,
2255 struct lock_struct
*plock
,
2258 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2260 /* Note: blr is not used in the default implementation. */
2261 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
2264 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
2265 struct messaging_context
*msg_ctx
,
2266 struct byte_range_lock
*br_lck
,
2267 const struct lock_struct
*plock
)
2269 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2271 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
2274 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
2275 struct byte_range_lock
*br_lck
,
2276 struct lock_struct
*plock
)
2278 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
2280 /* Note: blr is not used in the default implementation. */
2281 return brl_lock_cancel_default(br_lck
, plock
);
2284 static bool vfswrap_strict_lock(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 return strict_lock_default(fsp
, plock
);
2294 static void vfswrap_strict_unlock(struct vfs_handle_struct
*handle
,
2296 struct lock_struct
*plock
)
2298 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
2299 plock
->lock_type
== WRITE_LOCK
);
2301 strict_unlock_default(fsp
, plock
);
2304 /* NT ACL operations. */
2306 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
2308 uint32 security_info
,
2309 TALLOC_CTX
*mem_ctx
,
2310 struct security_descriptor
**ppdesc
)
2314 START_PROFILE(fget_nt_acl
);
2315 result
= posix_fget_nt_acl(fsp
, security_info
,
2317 END_PROFILE(fget_nt_acl
);
2321 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
2323 uint32 security_info
,
2324 TALLOC_CTX
*mem_ctx
,
2325 struct security_descriptor
**ppdesc
)
2329 START_PROFILE(get_nt_acl
);
2330 result
= posix_get_nt_acl(handle
->conn
, name
, security_info
,
2332 END_PROFILE(get_nt_acl
);
2336 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32 security_info_sent
, const struct security_descriptor
*psd
)
2340 START_PROFILE(fset_nt_acl
);
2341 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
2342 END_PROFILE(fset_nt_acl
);
2346 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
2347 struct smb_filename
*file
,
2348 struct security_acl
*sacl
,
2349 uint32_t access_requested
,
2350 uint32_t access_denied
)
2352 return NT_STATUS_OK
; /* Nothing to do here ... */
2355 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
, const char *name
, mode_t mode
)
2363 START_PROFILE(chmod_acl
);
2364 result
= chmod_acl(handle
->conn
, name
, mode
);
2365 END_PROFILE(chmod_acl
);
2370 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2378 START_PROFILE(fchmod_acl
);
2379 result
= fchmod_acl(fsp
, mode
);
2380 END_PROFILE(fchmod_acl
);
2385 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
,
2387 SMB_ACL_TYPE_T type
,
2388 TALLOC_CTX
*mem_ctx
)
2390 return sys_acl_get_file(handle
, path_p
, type
, mem_ctx
);
2393 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
2395 TALLOC_CTX
*mem_ctx
)
2397 return sys_acl_get_fd(handle
, fsp
, mem_ctx
);
2400 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
, const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
2402 return sys_acl_set_file(handle
, name
, acltype
, theacl
);
2405 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2407 return sys_acl_set_fd(handle
, fsp
, theacl
);
2410 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
, const char *path
)
2412 return sys_acl_delete_def_file(handle
, path
);
2415 /****************************************************************
2416 Extended attribute operations.
2417 *****************************************************************/
2419 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,const char *path
, const char *name
, void *value
, size_t size
)
2421 return getxattr(path
, name
, value
, size
);
2424 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2426 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2429 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
, const char *path
, char *list
, size_t size
)
2431 return listxattr(path
, list
, size
);
2434 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2436 return flistxattr(fsp
->fh
->fd
, list
, size
);
2439 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
)
2441 return removexattr(path
, name
);
2444 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2446 return fremovexattr(fsp
->fh
->fd
, name
);
2449 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
2451 return setxattr(path
, name
, value
, size
, flags
);
2454 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2456 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2459 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2464 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2465 const struct smb_filename
*fname
,
2466 SMB_STRUCT_STAT
*sbuf
)
2470 bool offline
= false;
2472 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2476 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2477 #if defined(ENOTSUP)
2483 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2484 if (!NT_STATUS_IS_OK(status
)) {
2485 errno
= map_errno_from_nt_status(status
);
2489 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2496 static int vfswrap_set_offline(struct vfs_handle_struct
*handle
,
2497 const struct smb_filename
*fname
)
2499 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2500 #if defined(ENOTSUP)
2506 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
2507 struct files_struct
*fsp
,
2508 TALLOC_CTX
*mem_ctx
,
2511 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
2514 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
2515 struct files_struct
*fsp
,
2516 const DATA_BLOB old_cookie
,
2517 TALLOC_CTX
*mem_ctx
,
2518 DATA_BLOB
*new_cookie
)
2520 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
2524 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
2525 struct smb_request
*smb1req
,
2526 struct smbXsrv_open
*op
,
2527 const DATA_BLOB old_cookie
,
2528 TALLOC_CTX
*mem_ctx
,
2529 struct files_struct
**fsp
,
2530 DATA_BLOB
*new_cookie
)
2532 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
2533 old_cookie
, mem_ctx
,
2537 static struct vfs_fn_pointers vfs_default_fns
= {
2538 /* Disk operations */
2540 .connect_fn
= vfswrap_connect
,
2541 .disconnect_fn
= vfswrap_disconnect
,
2542 .disk_free_fn
= vfswrap_disk_free
,
2543 .get_quota_fn
= vfswrap_get_quota
,
2544 .set_quota_fn
= vfswrap_set_quota
,
2545 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
2546 .statvfs_fn
= vfswrap_statvfs
,
2547 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
2548 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
2550 /* Directory operations */
2552 .opendir_fn
= vfswrap_opendir
,
2553 .fdopendir_fn
= vfswrap_fdopendir
,
2554 .readdir_fn
= vfswrap_readdir
,
2555 .readdir_attr_fn
= vfswrap_readdir_attr
,
2556 .seekdir_fn
= vfswrap_seekdir
,
2557 .telldir_fn
= vfswrap_telldir
,
2558 .rewind_dir_fn
= vfswrap_rewinddir
,
2559 .mkdir_fn
= vfswrap_mkdir
,
2560 .rmdir_fn
= vfswrap_rmdir
,
2561 .closedir_fn
= vfswrap_closedir
,
2562 .init_search_op_fn
= vfswrap_init_search_op
,
2564 /* File operations */
2566 .open_fn
= vfswrap_open
,
2567 .create_file_fn
= vfswrap_create_file
,
2568 .close_fn
= vfswrap_close
,
2569 .read_fn
= vfswrap_read
,
2570 .pread_fn
= vfswrap_pread
,
2571 .pread_send_fn
= vfswrap_pread_send
,
2572 .pread_recv_fn
= vfswrap_asys_ssize_t_recv
,
2573 .write_fn
= vfswrap_write
,
2574 .pwrite_fn
= vfswrap_pwrite
,
2575 .pwrite_send_fn
= vfswrap_pwrite_send
,
2576 .pwrite_recv_fn
= vfswrap_asys_ssize_t_recv
,
2577 .lseek_fn
= vfswrap_lseek
,
2578 .sendfile_fn
= vfswrap_sendfile
,
2579 .recvfile_fn
= vfswrap_recvfile
,
2580 .rename_fn
= vfswrap_rename
,
2581 .fsync_fn
= vfswrap_fsync
,
2582 .fsync_send_fn
= vfswrap_fsync_send
,
2583 .fsync_recv_fn
= vfswrap_asys_int_recv
,
2584 .stat_fn
= vfswrap_stat
,
2585 .fstat_fn
= vfswrap_fstat
,
2586 .lstat_fn
= vfswrap_lstat
,
2587 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
2588 .unlink_fn
= vfswrap_unlink
,
2589 .chmod_fn
= vfswrap_chmod
,
2590 .fchmod_fn
= vfswrap_fchmod
,
2591 .chown_fn
= vfswrap_chown
,
2592 .fchown_fn
= vfswrap_fchown
,
2593 .lchown_fn
= vfswrap_lchown
,
2594 .chdir_fn
= vfswrap_chdir
,
2595 .getwd_fn
= vfswrap_getwd
,
2596 .ntimes_fn
= vfswrap_ntimes
,
2597 .ftruncate_fn
= vfswrap_ftruncate
,
2598 .fallocate_fn
= vfswrap_fallocate
,
2599 .lock_fn
= vfswrap_lock
,
2600 .kernel_flock_fn
= vfswrap_kernel_flock
,
2601 .linux_setlease_fn
= vfswrap_linux_setlease
,
2602 .getlock_fn
= vfswrap_getlock
,
2603 .symlink_fn
= vfswrap_symlink
,
2604 .readlink_fn
= vfswrap_readlink
,
2605 .link_fn
= vfswrap_link
,
2606 .mknod_fn
= vfswrap_mknod
,
2607 .realpath_fn
= vfswrap_realpath
,
2608 .notify_watch_fn
= vfswrap_notify_watch
,
2609 .chflags_fn
= vfswrap_chflags
,
2610 .file_id_create_fn
= vfswrap_file_id_create
,
2611 .streaminfo_fn
= vfswrap_streaminfo
,
2612 .get_real_filename_fn
= vfswrap_get_real_filename
,
2613 .connectpath_fn
= vfswrap_connectpath
,
2614 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
2615 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
2616 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
2617 .strict_lock_fn
= vfswrap_strict_lock
,
2618 .strict_unlock_fn
= vfswrap_strict_unlock
,
2619 .translate_name_fn
= vfswrap_translate_name
,
2620 .fsctl_fn
= vfswrap_fsctl
,
2621 .copy_chunk_send_fn
= vfswrap_copy_chunk_send
,
2622 .copy_chunk_recv_fn
= vfswrap_copy_chunk_recv
,
2623 .get_compression_fn
= vfswrap_get_compression
,
2624 .set_compression_fn
= vfswrap_set_compression
,
2626 /* NT ACL operations. */
2628 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
2629 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
2630 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
2631 .audit_file_fn
= vfswrap_audit_file
,
2633 /* POSIX ACL operations. */
2635 .chmod_acl_fn
= vfswrap_chmod_acl
,
2636 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
2638 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
2639 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
2640 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
2641 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
2642 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
2643 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
2644 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
2646 /* EA operations. */
2647 .getxattr_fn
= vfswrap_getxattr
,
2648 .fgetxattr_fn
= vfswrap_fgetxattr
,
2649 .listxattr_fn
= vfswrap_listxattr
,
2650 .flistxattr_fn
= vfswrap_flistxattr
,
2651 .removexattr_fn
= vfswrap_removexattr
,
2652 .fremovexattr_fn
= vfswrap_fremovexattr
,
2653 .setxattr_fn
= vfswrap_setxattr
,
2654 .fsetxattr_fn
= vfswrap_fsetxattr
,
2656 /* aio operations */
2657 .aio_force_fn
= vfswrap_aio_force
,
2659 /* offline operations */
2660 .is_offline_fn
= vfswrap_is_offline
,
2661 .set_offline_fn
= vfswrap_set_offline
,
2663 /* durable handle operations */
2664 .durable_cookie_fn
= vfswrap_durable_cookie
,
2665 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
2666 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
2669 NTSTATUS
vfs_default_init(void);
2670 NTSTATUS
vfs_default_init(void)
2672 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
2673 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);