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"
34 #define DBGC_CLASS DBGC_VFS
36 /* Check for NULL pointer parameters in vfswrap_* functions */
38 /* We don't want to have NULL function pointers lying around. Someone
39 is sure to try and execute them. These stubs are used to prevent
42 static int vfswrap_connect(vfs_handle_struct
*handle
, const char *service
, const char *user
)
44 return 0; /* Return >= 0 for success */
47 static void vfswrap_disconnect(vfs_handle_struct
*handle
)
53 static uint64_t vfswrap_disk_free(vfs_handle_struct
*handle
, const char *path
, bool small_query
, uint64_t *bsize
,
54 uint64_t *dfree
, uint64_t *dsize
)
58 result
= sys_disk_free(handle
->conn
, path
, small_query
, bsize
, dfree
, dsize
);
62 static int vfswrap_get_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
64 #ifdef HAVE_SYS_QUOTAS
67 START_PROFILE(syscall_get_quota
);
68 result
= sys_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
69 END_PROFILE(syscall_get_quota
);
77 static int vfswrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
79 #ifdef HAVE_SYS_QUOTAS
82 START_PROFILE(syscall_set_quota
);
83 result
= sys_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
84 END_PROFILE(syscall_set_quota
);
92 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
93 struct files_struct
*fsp
,
94 struct shadow_copy_data
*shadow_copy_data
,
98 return -1; /* Not implemented. */
101 static int vfswrap_statvfs(struct vfs_handle_struct
*handle
, const char *path
, vfs_statvfs_struct
*statbuf
)
103 return sys_statvfs(path
, statbuf
);
106 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct
*handle
,
107 enum timestamp_set_resolution
*p_ts_res
)
109 connection_struct
*conn
= handle
->conn
;
110 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
111 struct smb_filename
*smb_fname_cpath
= NULL
;
112 struct vfs_statvfs_struct statbuf
;
116 ZERO_STRUCT(statbuf
);
117 ret
= sys_statvfs(conn
->connectpath
, &statbuf
);
119 caps
= statbuf
.FsCapabilities
;
122 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
124 /* Work out what timestamp resolution we can
125 * use when setting a timestamp. */
127 status
= create_synthetic_smb_fname(talloc_tos(),
132 if (!NT_STATUS_IS_OK(status
)) {
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(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("setup_dfs_referral: Path %s to "
227 "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,("setup_dfs_referral: Invalid dfs referral "
335 max_referral_level
));
336 return NT_STATUS_INVALID_LEVEL
;
340 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
346 /* Directory operations */
348 static DIR *vfswrap_opendir(vfs_handle_struct
*handle
, const char *fname
, const char *mask
, uint32 attr
)
352 START_PROFILE(syscall_opendir
);
353 result
= opendir(fname
);
354 END_PROFILE(syscall_opendir
);
358 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
365 START_PROFILE(syscall_fdopendir
);
366 result
= sys_fdopendir(fsp
->fh
->fd
);
367 END_PROFILE(syscall_fdopendir
);
372 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
374 SMB_STRUCT_STAT
*sbuf
)
376 struct dirent
*result
;
378 START_PROFILE(syscall_readdir
);
379 result
= readdir(dirp
);
380 /* Default Posix readdir() does not give us stat info.
381 * Set to invalid to indicate we didn't return this info. */
383 SET_STAT_INVALID(*sbuf
);
384 END_PROFILE(syscall_readdir
);
388 static void vfswrap_seekdir(vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
390 START_PROFILE(syscall_seekdir
);
391 seekdir(dirp
, offset
);
392 END_PROFILE(syscall_seekdir
);
395 static long vfswrap_telldir(vfs_handle_struct
*handle
, DIR *dirp
)
398 START_PROFILE(syscall_telldir
);
399 result
= telldir(dirp
);
400 END_PROFILE(syscall_telldir
);
404 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
406 START_PROFILE(syscall_rewinddir
);
408 END_PROFILE(syscall_rewinddir
);
411 static int vfswrap_mkdir(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
414 bool has_dacl
= False
;
417 START_PROFILE(syscall_mkdir
);
419 if (lp_inherit_acls(SNUM(handle
->conn
))
420 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
421 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
)))
422 mode
= (0777 & lp_dir_mask(SNUM(handle
->conn
)));
426 result
= mkdir(path
, mode
);
428 if (result
== 0 && !has_dacl
) {
430 * We need to do this as the default behavior of POSIX ACLs
431 * is to set the mask to be the requested group permission
432 * bits, not the group permission bits to be the requested
433 * group permission bits. This is not what we want, as it will
434 * mess up any inherited ACL bits that were set. JRA.
436 int saved_errno
= errno
; /* We may get ENOSYS */
437 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, path
, mode
) == -1) && (errno
== ENOSYS
))
441 END_PROFILE(syscall_mkdir
);
445 static int vfswrap_rmdir(vfs_handle_struct
*handle
, const char *path
)
449 START_PROFILE(syscall_rmdir
);
450 result
= rmdir(path
);
451 END_PROFILE(syscall_rmdir
);
455 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
459 START_PROFILE(syscall_closedir
);
460 result
= closedir(dirp
);
461 END_PROFILE(syscall_closedir
);
465 static void vfswrap_init_search_op(vfs_handle_struct
*handle
,
468 /* Default behavior is a NOOP */
471 /* File operations */
473 static int vfswrap_open(vfs_handle_struct
*handle
,
474 struct smb_filename
*smb_fname
,
475 files_struct
*fsp
, int flags
, mode_t mode
)
479 START_PROFILE(syscall_open
);
481 if (smb_fname
->stream_name
) {
486 result
= open(smb_fname
->base_name
, flags
, mode
);
488 END_PROFILE(syscall_open
);
492 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
493 struct smb_request
*req
,
494 uint16_t root_dir_fid
,
495 struct smb_filename
*smb_fname
,
496 uint32_t access_mask
,
497 uint32_t share_access
,
498 uint32_t create_disposition
,
499 uint32_t create_options
,
500 uint32_t file_attributes
,
501 uint32_t oplock_request
,
502 uint64_t allocation_size
,
503 uint32_t private_flags
,
504 struct security_descriptor
*sd
,
505 struct ea_list
*ea_list
,
506 files_struct
**result
,
509 return create_file_default(handle
->conn
, req
, root_dir_fid
, smb_fname
,
510 access_mask
, share_access
,
511 create_disposition
, create_options
,
512 file_attributes
, oplock_request
,
513 allocation_size
, private_flags
,
518 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
522 START_PROFILE(syscall_close
);
523 result
= fd_close_posix(fsp
);
524 END_PROFILE(syscall_close
);
528 static ssize_t
vfswrap_read(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
532 START_PROFILE_BYTES(syscall_read
, n
);
533 result
= sys_read(fsp
->fh
->fd
, data
, n
);
534 END_PROFILE(syscall_read
);
538 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
539 size_t n
, off_t offset
)
543 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
544 START_PROFILE_BYTES(syscall_pread
, n
);
545 result
= sys_pread(fsp
->fh
->fd
, data
, n
, offset
);
546 END_PROFILE(syscall_pread
);
548 if (result
== -1 && errno
== ESPIPE
) {
549 /* Maintain the fiction that pipes can be seeked (sought?) on. */
550 result
= SMB_VFS_READ(fsp
, data
, n
);
554 #else /* HAVE_PREAD */
558 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
559 if (curr
== -1 && errno
== ESPIPE
) {
560 /* Maintain the fiction that pipes can be seeked (sought?) on. */
561 result
= SMB_VFS_READ(fsp
, data
, n
);
566 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
571 result
= SMB_VFS_READ(fsp
, data
, n
);
574 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
577 #endif /* HAVE_PREAD */
582 static ssize_t
vfswrap_write(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
586 START_PROFILE_BYTES(syscall_write
, n
);
587 result
= sys_write(fsp
->fh
->fd
, data
, n
);
588 END_PROFILE(syscall_write
);
592 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
593 size_t n
, off_t offset
)
597 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
598 START_PROFILE_BYTES(syscall_pwrite
, n
);
599 result
= sys_pwrite(fsp
->fh
->fd
, data
, n
, offset
);
600 END_PROFILE(syscall_pwrite
);
602 if (result
== -1 && errno
== ESPIPE
) {
603 /* Maintain the fiction that pipes can be sought on. */
604 result
= SMB_VFS_WRITE(fsp
, data
, n
);
607 #else /* HAVE_PWRITE */
611 curr
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
616 if (SMB_VFS_LSEEK(fsp
, offset
, SEEK_SET
) == -1) {
620 result
= SMB_VFS_WRITE(fsp
, data
, n
);
623 SMB_VFS_LSEEK(fsp
, curr
, SEEK_SET
);
626 #endif /* HAVE_PWRITE */
631 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
635 START_PROFILE(syscall_lseek
);
637 /* Cope with 'stat' file opens. */
638 if (fsp
->fh
->fd
!= -1)
639 result
= lseek(fsp
->fh
->fd
, offset
, whence
);
642 * We want to maintain the fiction that we can seek
643 * on a fifo for file system purposes. This allows
644 * people to set up UNIX fifo's that feed data to Windows
648 if((result
== -1) && (errno
== ESPIPE
)) {
653 END_PROFILE(syscall_lseek
);
657 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
658 off_t offset
, size_t n
)
662 START_PROFILE_BYTES(syscall_sendfile
, n
);
663 result
= sys_sendfile(tofd
, fromfsp
->fh
->fd
, hdr
, offset
, n
);
664 END_PROFILE(syscall_sendfile
);
668 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
676 START_PROFILE_BYTES(syscall_recvfile
, n
);
677 result
= sys_recvfile(fromfd
, tofsp
->fh
->fd
, offset
, n
);
678 END_PROFILE(syscall_recvfile
);
682 static int vfswrap_rename(vfs_handle_struct
*handle
,
683 const struct smb_filename
*smb_fname_src
,
684 const struct smb_filename
*smb_fname_dst
)
688 START_PROFILE(syscall_rename
);
690 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
695 result
= rename(smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
698 END_PROFILE(syscall_rename
);
702 static int vfswrap_fsync(vfs_handle_struct
*handle
, files_struct
*fsp
)
707 START_PROFILE(syscall_fsync
);
708 result
= fsync(fsp
->fh
->fd
);
709 END_PROFILE(syscall_fsync
);
716 static int vfswrap_stat(vfs_handle_struct
*handle
,
717 struct smb_filename
*smb_fname
)
721 START_PROFILE(syscall_stat
);
723 if (smb_fname
->stream_name
) {
728 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
729 lp_fake_dir_create_times(SNUM(handle
->conn
)));
731 END_PROFILE(syscall_stat
);
735 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
739 START_PROFILE(syscall_fstat
);
740 result
= sys_fstat(fsp
->fh
->fd
,
741 sbuf
, lp_fake_dir_create_times(SNUM(handle
->conn
)));
742 END_PROFILE(syscall_fstat
);
746 static int vfswrap_lstat(vfs_handle_struct
*handle
,
747 struct smb_filename
*smb_fname
)
751 START_PROFILE(syscall_lstat
);
753 if (smb_fname
->stream_name
) {
758 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
759 lp_fake_dir_create_times(SNUM(handle
->conn
)));
761 END_PROFILE(syscall_lstat
);
765 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
767 enum vfs_translate_direction direction
,
771 return NT_STATUS_NONE_MAPPED
;
775 * Implement the default fsctl operation.
777 static bool vfswrap_logged_ioctl_message
= false;
779 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
780 struct files_struct
*fsp
,
783 uint16_t req_flags
, /* Needed for UNICODE ... */
784 const uint8_t *_in_data
,
787 uint32_t max_out_len
,
790 const char *in_data
= (const char *)_in_data
;
791 char **out_data
= (char **)_out_data
;
794 case FSCTL_SET_SPARSE
:
796 bool set_sparse
= true;
799 if (in_len
>= 1 && in_data
[0] == 0) {
803 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
805 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
806 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
807 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
813 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
815 unsigned char objid
[16];
816 char *return_data
= NULL
;
818 /* This should return the object-id on this file.
819 * I think I'll make this be the inode+dev. JRA.
822 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
825 *out_len
= (max_out_len
>= 64) ? 64 : max_out_len
;
826 /* Hmmm, will this cause problems if less data asked for? */
827 return_data
= talloc_array(ctx
, char, 64);
828 if (return_data
== NULL
) {
829 return NT_STATUS_NO_MEMORY
;
832 /* For backwards compatibility only store the dev/inode. */
833 push_file_id_16(return_data
, &fsp
->file_id
);
834 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
835 push_file_id_16(return_data
+32, &fsp
->file_id
);
836 *out_data
= return_data
;
840 case FSCTL_GET_REPARSE_POINT
:
842 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
843 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
844 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
845 return NT_STATUS_NOT_A_REPARSE_POINT
;
848 case FSCTL_SET_REPARSE_POINT
:
850 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
851 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
852 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp
)));
853 return NT_STATUS_NOT_A_REPARSE_POINT
;
856 case FSCTL_GET_SHADOW_COPY_DATA
:
859 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
860 * and return their volume names. If max_data_count is 16, then it is just
861 * asking for the number of volumes and length of the combined names.
863 * pdata is the data allocated by our caller, but that uses
864 * total_data_count (which is 0 in our case) rather than max_data_count.
865 * Allocate the correct amount and return the pointer to let
866 * it be deallocated when we return.
868 struct shadow_copy_data
*shadow_data
= NULL
;
870 uint32 labels_data_count
= 0;
872 char *cur_pdata
= NULL
;
874 if (max_out_len
< 16) {
875 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
877 return NT_STATUS_INVALID_PARAMETER
;
880 if (max_out_len
> 16) {
884 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
885 if (shadow_data
== NULL
) {
886 DEBUG(0,("TALLOC_ZERO() failed!\n"));
887 return NT_STATUS_NO_MEMORY
;
891 * Call the VFS routine to actually do the work.
893 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
894 TALLOC_FREE(shadow_data
);
895 if (errno
== ENOSYS
) {
896 DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n",
897 fsp
->conn
->connectpath
));
898 return NT_STATUS_NOT_SUPPORTED
;
900 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n",
901 fsp
->conn
->connectpath
));
902 return NT_STATUS_UNSUCCESSFUL
;
906 labels_data_count
= (shadow_data
->num_volumes
* 2 *
907 sizeof(SHADOW_COPY_LABEL
)) + 2;
912 *out_len
= 12 + labels_data_count
+ 4;
915 if (max_out_len
< *out_len
) {
916 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
917 max_out_len
, *out_len
));
918 TALLOC_FREE(shadow_data
);
919 return NT_STATUS_BUFFER_TOO_SMALL
;
922 cur_pdata
= talloc_array(ctx
, char, *out_len
);
923 if (cur_pdata
== NULL
) {
924 TALLOC_FREE(shadow_data
);
925 return NT_STATUS_NO_MEMORY
;
928 *out_data
= cur_pdata
;
930 /* num_volumes 4 bytes */
931 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
934 /* num_labels 4 bytes */
935 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
938 /* needed_data_count 4 bytes */
939 SIVAL(cur_pdata
, 8, labels_data_count
+ 4);
943 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
944 shadow_data
->num_volumes
, fsp_str_dbg(fsp
)));
945 if (labels
&& shadow_data
->labels
) {
946 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
947 srvstr_push(cur_pdata
, req_flags
,
948 cur_pdata
, shadow_data
->labels
[i
],
949 2 * sizeof(SHADOW_COPY_LABEL
),
950 STR_UNICODE
|STR_TERMINATE
);
951 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
952 DEBUGADD(10,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
956 TALLOC_FREE(shadow_data
);
961 case FSCTL_FIND_FILES_BY_SID
:
963 /* pretend this succeeded -
965 * we have to send back a list with all files owned by this SID
967 * but I have to check that --metze
973 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
977 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
978 return NT_STATUS_INVALID_PARAMETER
;
981 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
983 /* unknown 4 bytes: this is not the length of the sid :-( */
984 /*unknown = IVAL(pdata,0);*/
986 if (!sid_parse(in_data
+ 4, sid_len
, &sid
)) {
987 return NT_STATUS_INVALID_PARAMETER
;
989 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid
)));
991 if (!sid_to_uid(&sid
, &uid
)) {
992 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
993 sid_string_dbg(&sid
),
994 (unsigned long)sid_len
));
998 /* we can take a look at the find source :-)
1000 * find ./ -uid $uid -name '*' is what we need here
1003 * and send 4bytes len and then NULL terminated unicode strings
1006 * but I don't know how to deal with the paged results
1007 * (maybe we can hang the result anywhere in the fsp struct)
1009 * but I don't know how to deal with the paged results
1010 * (maybe we can hang the result anywhere in the fsp struct)
1012 * we don't send all files at once
1013 * and at the next we should *not* start from the beginning,
1014 * so we have to cache the result
1019 /* this works for now... */
1020 return NT_STATUS_OK
;
1023 case FSCTL_QUERY_ALLOCATED_RANGES
:
1025 /* FIXME: This is just a dummy reply, telling that all of the
1026 * file is allocated. MKS cp needs that.
1027 * Adding the real allocated ranges via FIEMAP on Linux
1028 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1029 * this FSCTL correct for sparse files.
1032 uint64_t offset
, length
;
1033 char *out_data_tmp
= NULL
;
1036 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1038 return NT_STATUS_INVALID_PARAMETER
;
1041 if (max_out_len
< 16) {
1042 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1044 return NT_STATUS_INVALID_PARAMETER
;
1047 offset
= BVAL(in_data
,0);
1048 length
= BVAL(in_data
,8);
1050 if (offset
+ length
< offset
) {
1051 /* No 64-bit integer wrap. */
1052 return NT_STATUS_INVALID_PARAMETER
;
1055 /* Shouldn't this be SMB_VFS_STAT ... ? */
1056 status
= vfs_stat_fsp(fsp
);
1057 if (!NT_STATUS_IS_OK(status
)) {
1062 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1063 if (out_data_tmp
== NULL
) {
1064 DEBUG(10, ("unable to allocate memory for response\n"));
1065 return NT_STATUS_NO_MEMORY
;
1068 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1069 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1071 memset(out_data_tmp
, 0, *out_len
);
1073 uint64_t end
= offset
+ length
;
1074 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1075 SBVAL(out_data_tmp
, 0, 0);
1076 SBVAL(out_data_tmp
, 8, end
);
1079 *out_data
= out_data_tmp
;
1081 return NT_STATUS_OK
;
1084 case FSCTL_IS_VOLUME_DIRTY
:
1086 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1087 "(but not implemented)\n", fsp_fnum_dbg(fsp
)));
1089 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1090 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1092 return NT_STATUS_INVALID_PARAMETER
;
1097 * Only print once ... unfortunately there could be lots of
1098 * different FSCTLs that are called.
1100 if (!vfswrap_logged_ioctl_message
) {
1101 vfswrap_logged_ioctl_message
= true;
1102 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1103 __func__
, function
));
1107 return NT_STATUS_NOT_SUPPORTED
;
1110 /********************************************************************
1111 Given a stat buffer return the allocated size on disk, taking into
1112 account sparse files.
1113 ********************************************************************/
1114 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
1115 struct files_struct
*fsp
,
1116 const SMB_STRUCT_STAT
*sbuf
)
1120 START_PROFILE(syscall_get_alloc_size
);
1122 if(S_ISDIR(sbuf
->st_ex_mode
)) {
1127 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1128 /* The type of st_blocksize is blkcnt_t which *MUST* be
1129 signed (according to POSIX) and can be less than 64-bits.
1130 Ensure when we're converting to 64 bits wide we don't
1132 #if defined(SIZEOF_BLKCNT_T_8)
1133 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
1134 #elif defined(SIZEOF_BLKCNT_T_4)
1136 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
1137 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
1140 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1143 result
= get_file_size_stat(sbuf
);
1146 if (fsp
&& fsp
->initial_allocation_size
)
1147 result
= MAX(result
,fsp
->initial_allocation_size
);
1149 result
= smb_roundup(handle
->conn
, result
);
1152 END_PROFILE(syscall_get_alloc_size
);
1156 static int vfswrap_unlink(vfs_handle_struct
*handle
,
1157 const struct smb_filename
*smb_fname
)
1161 START_PROFILE(syscall_unlink
);
1163 if (smb_fname
->stream_name
) {
1167 result
= unlink(smb_fname
->base_name
);
1170 END_PROFILE(syscall_unlink
);
1174 static int vfswrap_chmod(vfs_handle_struct
*handle
, const char *path
, mode_t mode
)
1178 START_PROFILE(syscall_chmod
);
1181 * We need to do this due to the fact that the default POSIX ACL
1182 * chmod modifies the ACL *mask* for the group owner, not the
1183 * group owner bits directly. JRA.
1188 int saved_errno
= errno
; /* We might get ENOSYS */
1189 if ((result
= SMB_VFS_CHMOD_ACL(handle
->conn
, path
, mode
)) == 0) {
1190 END_PROFILE(syscall_chmod
);
1193 /* Error - return the old errno. */
1194 errno
= saved_errno
;
1197 result
= chmod(path
, mode
);
1198 END_PROFILE(syscall_chmod
);
1202 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
1206 START_PROFILE(syscall_fchmod
);
1209 * We need to do this due to the fact that the default POSIX ACL
1210 * chmod modifies the ACL *mask* for the group owner, not the
1211 * group owner bits directly. JRA.
1215 int saved_errno
= errno
; /* We might get ENOSYS */
1216 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
1217 END_PROFILE(syscall_fchmod
);
1220 /* Error - return the old errno. */
1221 errno
= saved_errno
;
1224 #if defined(HAVE_FCHMOD)
1225 result
= fchmod(fsp
->fh
->fd
, mode
);
1231 END_PROFILE(syscall_fchmod
);
1235 static int vfswrap_chown(vfs_handle_struct
*handle
, const char *path
, uid_t uid
, gid_t gid
)
1239 START_PROFILE(syscall_chown
);
1240 result
= chown(path
, uid
, gid
);
1241 END_PROFILE(syscall_chown
);
1245 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
1250 START_PROFILE(syscall_fchown
);
1251 result
= fchown(fsp
->fh
->fd
, uid
, gid
);
1252 END_PROFILE(syscall_fchown
);
1260 static int vfswrap_lchown(vfs_handle_struct
*handle
, const char *path
, uid_t uid
, gid_t gid
)
1264 START_PROFILE(syscall_lchown
);
1265 result
= lchown(path
, uid
, gid
);
1266 END_PROFILE(syscall_lchown
);
1270 static int vfswrap_chdir(vfs_handle_struct
*handle
, const char *path
)
1274 START_PROFILE(syscall_chdir
);
1275 result
= chdir(path
);
1276 END_PROFILE(syscall_chdir
);
1280 static char *vfswrap_getwd(vfs_handle_struct
*handle
)
1284 START_PROFILE(syscall_getwd
);
1285 result
= sys_getwd();
1286 END_PROFILE(syscall_getwd
);
1290 /*********************************************************************
1291 nsec timestamp resolution call. Convert down to whatever the underlying
1292 system will support.
1293 **********************************************************************/
1295 static int vfswrap_ntimes(vfs_handle_struct
*handle
,
1296 const struct smb_filename
*smb_fname
,
1297 struct smb_file_time
*ft
)
1301 START_PROFILE(syscall_ntimes
);
1303 if (smb_fname
->stream_name
) {
1309 if (null_timespec(ft
->atime
)) {
1310 ft
->atime
= smb_fname
->st
.st_ex_atime
;
1313 if (null_timespec(ft
->mtime
)) {
1314 ft
->mtime
= smb_fname
->st
.st_ex_mtime
;
1317 if (!null_timespec(ft
->create_time
)) {
1318 set_create_timespec_ea(handle
->conn
,
1323 if ((timespec_compare(&ft
->atime
,
1324 &smb_fname
->st
.st_ex_atime
) == 0) &&
1325 (timespec_compare(&ft
->mtime
,
1326 &smb_fname
->st
.st_ex_mtime
) == 0)) {
1331 #if defined(HAVE_UTIMENSAT)
1333 struct timespec ts
[2];
1336 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, ts
, 0);
1338 result
= utimensat(AT_FDCWD
, smb_fname
->base_name
, NULL
, 0);
1340 if (!((result
== -1) && (errno
== ENOSYS
))) {
1344 #if defined(HAVE_UTIMES)
1346 struct timeval tv
[2];
1347 tv
[0] = convert_timespec_to_timeval(ft
->atime
);
1348 tv
[1] = convert_timespec_to_timeval(ft
->mtime
);
1349 result
= utimes(smb_fname
->base_name
, tv
);
1351 result
= utimes(smb_fname
->base_name
, NULL
);
1353 if (!((result
== -1) && (errno
== ENOSYS
))) {
1357 #if defined(HAVE_UTIME)
1359 struct utimbuf times
;
1360 times
.actime
= convert_timespec_to_time_t(ft
->atime
);
1361 times
.modtime
= convert_timespec_to_time_t(ft
->mtime
);
1362 result
= utime(smb_fname
->base_name
, ×
);
1364 result
= utime(smb_fname
->base_name
, NULL
);
1366 if (!((result
== -1) && (errno
== ENOSYS
))) {
1374 END_PROFILE(syscall_ntimes
);
1378 /*********************************************************************
1379 A version of ftruncate that will write the space on disk if strict
1381 **********************************************************************/
1383 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1385 off_t space_to_write
;
1386 uint64_t space_avail
;
1387 uint64_t bsize
,dfree
,dsize
;
1390 SMB_STRUCT_STAT
*pst
;
1392 status
= vfs_stat_fsp(fsp
);
1393 if (!NT_STATUS_IS_OK(status
)) {
1396 pst
= &fsp
->fsp_name
->st
;
1399 if (S_ISFIFO(pst
->st_ex_mode
))
1403 if (pst
->st_ex_size
== len
)
1406 /* Shrink - just ftruncate. */
1407 if (pst
->st_ex_size
> len
)
1408 return ftruncate(fsp
->fh
->fd
, len
);
1410 space_to_write
= len
- pst
->st_ex_size
;
1412 /* for allocation try fallocate first. This can fail on some
1413 platforms e.g. when the filesystem doesn't support it and no
1414 emulation is being done by the libc (like on AIX with JFS1). In that
1415 case we do our own emulation. fallocate implementations can
1416 return ENOTSUP or EINVAL in cases like that. */
1417 ret
= SMB_VFS_FALLOCATE(fsp
, VFS_FALLOCATE_EXTEND_SIZE
,
1418 pst
->st_ex_size
, space_to_write
);
1419 if (ret
== ENOSPC
) {
1426 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1427 "error %d. Falling back to slow manual allocation\n", ret
));
1429 /* available disk space is enough or not? */
1430 space_avail
= get_dfree_info(fsp
->conn
,
1431 fsp
->fsp_name
->base_name
, false,
1432 &bsize
,&dfree
,&dsize
);
1433 /* space_avail is 1k blocks */
1434 if (space_avail
== (uint64_t)-1 ||
1435 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
1440 /* Write out the real space on disk. */
1441 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
1450 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1453 SMB_STRUCT_STAT
*pst
;
1457 START_PROFILE(syscall_ftruncate
);
1459 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->is_sparse
) {
1460 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
1461 END_PROFILE(syscall_ftruncate
);
1465 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1466 ftruncate if the system supports it. Then I discovered that
1467 you can have some filesystems that support ftruncate
1468 expansion and some that don't! On Linux fat can't do
1469 ftruncate extend but ext2 can. */
1471 result
= ftruncate(fsp
->fh
->fd
, len
);
1475 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1476 extend a file with ftruncate. Provide alternate implementation
1479 /* Do an fstat to see if the file is longer than the requested
1480 size in which case the ftruncate above should have
1481 succeeded or shorter, in which case seek to len - 1 and
1482 write 1 byte of zero */
1483 status
= vfs_stat_fsp(fsp
);
1484 if (!NT_STATUS_IS_OK(status
)) {
1487 pst
= &fsp
->fsp_name
->st
;
1490 if (S_ISFIFO(pst
->st_ex_mode
)) {
1496 if (pst
->st_ex_size
== len
) {
1501 if (pst
->st_ex_size
> len
) {
1502 /* the ftruncate should have worked */
1506 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
1514 END_PROFILE(syscall_ftruncate
);
1518 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
1520 enum vfs_fallocate_mode mode
,
1526 START_PROFILE(syscall_fallocate
);
1527 if (mode
== VFS_FALLOCATE_EXTEND_SIZE
) {
1528 result
= sys_posix_fallocate(fsp
->fh
->fd
, offset
, len
);
1529 } else if (mode
== VFS_FALLOCATE_KEEP_SIZE
) {
1530 result
= sys_fallocate(fsp
->fh
->fd
, mode
, offset
, len
);
1535 END_PROFILE(syscall_fallocate
);
1539 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
1543 START_PROFILE(syscall_fcntl_lock
);
1544 result
= fcntl_lock(fsp
->fh
->fd
, op
, offset
, count
, type
);
1545 END_PROFILE(syscall_fcntl_lock
);
1549 static int vfswrap_kernel_flock(vfs_handle_struct
*handle
, files_struct
*fsp
,
1550 uint32 share_mode
, uint32 access_mask
)
1552 START_PROFILE(syscall_kernel_flock
);
1553 kernel_flock(fsp
->fh
->fd
, share_mode
, access_mask
);
1554 END_PROFILE(syscall_kernel_flock
);
1558 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
1562 START_PROFILE(syscall_fcntl_getlock
);
1563 result
= fcntl_getlock(fsp
->fh
->fd
, poffset
, pcount
, ptype
, ppid
);
1564 END_PROFILE(syscall_fcntl_getlock
);
1568 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
1573 START_PROFILE(syscall_linux_setlease
);
1575 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1576 /* first set the signal handler */
1577 if(linux_set_lease_sighandler(fsp
->fh
->fd
) == -1) {
1581 result
= linux_setlease(fsp
->fh
->fd
, leasetype
);
1585 END_PROFILE(syscall_linux_setlease
);
1589 static int vfswrap_symlink(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
1593 START_PROFILE(syscall_symlink
);
1594 result
= symlink(oldpath
, newpath
);
1595 END_PROFILE(syscall_symlink
);
1599 static int vfswrap_readlink(vfs_handle_struct
*handle
, const char *path
, char *buf
, size_t bufsiz
)
1603 START_PROFILE(syscall_readlink
);
1604 result
= readlink(path
, buf
, bufsiz
);
1605 END_PROFILE(syscall_readlink
);
1609 static int vfswrap_link(vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
1613 START_PROFILE(syscall_link
);
1614 result
= link(oldpath
, newpath
);
1615 END_PROFILE(syscall_link
);
1619 static int vfswrap_mknod(vfs_handle_struct
*handle
, const char *pathname
, mode_t mode
, SMB_DEV_T dev
)
1623 START_PROFILE(syscall_mknod
);
1624 result
= sys_mknod(pathname
, mode
, dev
);
1625 END_PROFILE(syscall_mknod
);
1629 static char *vfswrap_realpath(vfs_handle_struct
*handle
, const char *path
)
1633 START_PROFILE(syscall_realpath
);
1634 #ifdef REALPATH_TAKES_NULL
1635 result
= realpath(path
, NULL
);
1637 result
= SMB_MALLOC_ARRAY(char, PATH_MAX
+1);
1639 char *resolved_path
= realpath(path
, result
);
1640 if (!resolved_path
) {
1643 /* SMB_ASSERT(result == resolved_path) ? */
1644 result
= resolved_path
;
1648 END_PROFILE(syscall_realpath
);
1652 static NTSTATUS
vfswrap_notify_watch(vfs_handle_struct
*vfs_handle
,
1653 struct sys_notify_context
*ctx
,
1656 uint32_t *subdir_filter
,
1657 void (*callback
)(struct sys_notify_context
*ctx
,
1659 struct notify_event
*ev
),
1660 void *private_data
, void *handle
)
1663 * So far inotify is the only supported default notify mechanism. If
1664 * another platform like the the BSD's or a proprietary Unix comes
1665 * along and wants another default, we can play the same trick we
1666 * played with Posix ACLs.
1668 * Until that is the case, hard-code inotify here.
1671 if (lp_kernel_change_notify(vfs_handle
->conn
->params
)) {
1672 return inotify_watch(ctx
, path
, filter
, subdir_filter
,
1673 callback
, private_data
, handle
);
1677 * Do nothing, leave everything to notify_internal.c
1679 return NT_STATUS_OK
;
1682 static int vfswrap_chflags(vfs_handle_struct
*handle
, const char *path
,
1686 return chflags(path
, flags
);
1693 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
1694 const SMB_STRUCT_STAT
*sbuf
)
1698 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
1702 key
.devid
= sbuf
->st_ex_dev
;
1703 key
.inode
= sbuf
->st_ex_ino
;
1704 /* key.extid is unused by default. */
1709 static NTSTATUS
vfswrap_streaminfo(vfs_handle_struct
*handle
,
1710 struct files_struct
*fsp
,
1712 TALLOC_CTX
*mem_ctx
,
1713 unsigned int *pnum_streams
,
1714 struct stream_struct
**pstreams
)
1716 SMB_STRUCT_STAT sbuf
;
1717 struct stream_struct
*tmp_streams
= NULL
;
1720 if ((fsp
!= NULL
) && (fsp
->is_directory
)) {
1722 * No default streams on directories
1727 if ((fsp
!= NULL
) && (fsp
->fh
->fd
!= -1)) {
1728 ret
= SMB_VFS_FSTAT(fsp
, &sbuf
);
1731 struct smb_filename smb_fname
;
1733 ZERO_STRUCT(smb_fname
);
1734 smb_fname
.base_name
= discard_const_p(char, fname
);
1736 if (lp_posix_pathnames()) {
1737 ret
= SMB_VFS_LSTAT(handle
->conn
, &smb_fname
);
1739 ret
= SMB_VFS_STAT(handle
->conn
, &smb_fname
);
1741 sbuf
= smb_fname
.st
;
1745 return map_nt_error_from_unix(errno
);
1748 if (S_ISDIR(sbuf
.st_ex_mode
)) {
1752 tmp_streams
= talloc_realloc(mem_ctx
, *pstreams
, struct stream_struct
,
1753 (*pnum_streams
) + 1);
1754 if (tmp_streams
== NULL
) {
1755 return NT_STATUS_NO_MEMORY
;
1757 tmp_streams
[*pnum_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
1758 if (tmp_streams
[*pnum_streams
].name
== NULL
) {
1759 return NT_STATUS_NO_MEMORY
;
1761 tmp_streams
[*pnum_streams
].size
= sbuf
.st_ex_size
;
1762 tmp_streams
[*pnum_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(handle
->conn
, fsp
, &sbuf
);
1765 *pstreams
= tmp_streams
;
1767 return NT_STATUS_OK
;
1770 static int vfswrap_get_real_filename(struct vfs_handle_struct
*handle
,
1773 TALLOC_CTX
*mem_ctx
,
1777 * Don't fall back to get_real_filename so callers can differentiate
1778 * between a full directory scan and an actual case-insensitive stat.
1784 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
1787 return handle
->conn
->connectpath
;
1790 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
1791 struct byte_range_lock
*br_lck
,
1792 struct lock_struct
*plock
,
1794 struct blocking_lock_record
*blr
)
1796 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
1798 /* Note: blr is not used in the default implementation. */
1799 return brl_lock_windows_default(br_lck
, plock
, blocking_lock
);
1802 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
1803 struct messaging_context
*msg_ctx
,
1804 struct byte_range_lock
*br_lck
,
1805 const struct lock_struct
*plock
)
1807 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
1809 return brl_unlock_windows_default(msg_ctx
, br_lck
, plock
);
1812 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct
*handle
,
1813 struct byte_range_lock
*br_lck
,
1814 struct lock_struct
*plock
,
1815 struct blocking_lock_record
*blr
)
1817 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
1819 /* Note: blr is not used in the default implementation. */
1820 return brl_lock_cancel_default(br_lck
, plock
);
1823 static bool vfswrap_strict_lock(struct vfs_handle_struct
*handle
,
1825 struct lock_struct
*plock
)
1827 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
1828 plock
->lock_type
== WRITE_LOCK
);
1830 return strict_lock_default(fsp
, plock
);
1833 static void vfswrap_strict_unlock(struct vfs_handle_struct
*handle
,
1835 struct lock_struct
*plock
)
1837 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
1838 plock
->lock_type
== WRITE_LOCK
);
1840 strict_unlock_default(fsp
, plock
);
1843 /* NT ACL operations. */
1845 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
1847 uint32 security_info
,
1848 struct security_descriptor
**ppdesc
)
1852 START_PROFILE(fget_nt_acl
);
1853 result
= posix_fget_nt_acl(fsp
, security_info
, ppdesc
);
1854 END_PROFILE(fget_nt_acl
);
1858 static NTSTATUS
vfswrap_get_nt_acl(vfs_handle_struct
*handle
,
1860 uint32 security_info
,
1861 struct security_descriptor
**ppdesc
)
1865 START_PROFILE(get_nt_acl
);
1866 result
= posix_get_nt_acl(handle
->conn
, name
, security_info
, ppdesc
);
1867 END_PROFILE(get_nt_acl
);
1871 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32 security_info_sent
, const struct security_descriptor
*psd
)
1875 START_PROFILE(fset_nt_acl
);
1876 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
1877 END_PROFILE(fset_nt_acl
);
1881 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
1882 struct smb_filename
*file
,
1883 struct security_acl
*sacl
,
1884 uint32_t access_requested
,
1885 uint32_t access_denied
)
1887 return NT_STATUS_OK
; /* Nothing to do here ... */
1890 static int vfswrap_chmod_acl(vfs_handle_struct
*handle
, const char *name
, mode_t mode
)
1898 START_PROFILE(chmod_acl
);
1899 result
= chmod_acl(handle
->conn
, name
, mode
);
1900 END_PROFILE(chmod_acl
);
1905 static int vfswrap_fchmod_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
1913 START_PROFILE(fchmod_acl
);
1914 result
= fchmod_acl(fsp
, mode
);
1915 END_PROFILE(fchmod_acl
);
1920 static int vfswrap_sys_acl_get_entry(vfs_handle_struct
*handle
, SMB_ACL_T theacl
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
1922 return sys_acl_get_entry(theacl
, entry_id
, entry_p
);
1925 static int vfswrap_sys_acl_get_tag_type(vfs_handle_struct
*handle
, SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*tag_type_p
)
1927 return sys_acl_get_tag_type(entry_d
, tag_type_p
);
1930 static int vfswrap_sys_acl_get_permset(vfs_handle_struct
*handle
, SMB_ACL_ENTRY_T entry_d
, SMB_ACL_PERMSET_T
*permset_p
)
1932 return sys_acl_get_permset(entry_d
, permset_p
);
1935 static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct
*handle
, SMB_ACL_ENTRY_T entry_d
)
1937 return sys_acl_get_qualifier(entry_d
);
1940 static SMB_ACL_T
vfswrap_sys_acl_get_file(vfs_handle_struct
*handle
, const char *path_p
, SMB_ACL_TYPE_T type
)
1942 return sys_acl_get_file(handle
, path_p
, type
);
1945 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
, files_struct
*fsp
)
1947 return sys_acl_get_fd(handle
, fsp
);
1950 static int vfswrap_sys_acl_clear_perms(vfs_handle_struct
*handle
, SMB_ACL_PERMSET_T permset
)
1952 return sys_acl_clear_perms(permset
);
1955 static int vfswrap_sys_acl_add_perm(vfs_handle_struct
*handle
, SMB_ACL_PERMSET_T permset
, SMB_ACL_PERM_T perm
)
1957 return sys_acl_add_perm(permset
, perm
);
1960 static char * vfswrap_sys_acl_to_text(vfs_handle_struct
*handle
, SMB_ACL_T theacl
, ssize_t
*plen
)
1962 return sys_acl_to_text(theacl
, plen
);
1965 static SMB_ACL_T
vfswrap_sys_acl_init(vfs_handle_struct
*handle
, int count
)
1967 return sys_acl_init(count
);
1970 static int vfswrap_sys_acl_create_entry(vfs_handle_struct
*handle
, SMB_ACL_T
*pacl
, SMB_ACL_ENTRY_T
*pentry
)
1972 return sys_acl_create_entry(pacl
, pentry
);
1975 static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct
*handle
, SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tagtype
)
1977 return sys_acl_set_tag_type(entry
, tagtype
);
1980 static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct
*handle
, SMB_ACL_ENTRY_T entry
, void *qual
)
1982 return sys_acl_set_qualifier(entry
, qual
);
1985 static int vfswrap_sys_acl_set_permset(vfs_handle_struct
*handle
, SMB_ACL_ENTRY_T entry
, SMB_ACL_PERMSET_T permset
)
1987 return sys_acl_set_permset(entry
, permset
);
1990 static int vfswrap_sys_acl_valid(vfs_handle_struct
*handle
, SMB_ACL_T theacl
)
1992 return sys_acl_valid(theacl
);
1995 static int vfswrap_sys_acl_set_file(vfs_handle_struct
*handle
, const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
1997 return sys_acl_set_file(handle
, name
, acltype
, theacl
);
2000 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_ACL_T theacl
)
2002 return sys_acl_set_fd(handle
, fsp
, theacl
);
2005 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct
*handle
, const char *path
)
2007 return sys_acl_delete_def_file(handle
, path
);
2010 static int vfswrap_sys_acl_get_perm(vfs_handle_struct
*handle
, SMB_ACL_PERMSET_T permset
, SMB_ACL_PERM_T perm
)
2012 return sys_acl_get_perm(permset
, perm
);
2015 static int vfswrap_sys_acl_free_text(vfs_handle_struct
*handle
, char *text
)
2017 return sys_acl_free_text(text
);
2020 static int vfswrap_sys_acl_free_acl(vfs_handle_struct
*handle
, SMB_ACL_T posix_acl
)
2022 return sys_acl_free_acl(posix_acl
);
2025 static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct
*handle
, void *qualifier
, SMB_ACL_TAG_T tagtype
)
2027 return sys_acl_free_qualifier(qualifier
, tagtype
);
2030 /****************************************************************
2031 Extended attribute operations.
2032 *****************************************************************/
2034 static ssize_t
vfswrap_getxattr(struct vfs_handle_struct
*handle
,const char *path
, const char *name
, void *value
, size_t size
)
2036 return getxattr(path
, name
, value
, size
);
2039 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
2041 return fgetxattr(fsp
->fh
->fd
, name
, value
, size
);
2044 static ssize_t
vfswrap_listxattr(struct vfs_handle_struct
*handle
, const char *path
, char *list
, size_t size
)
2046 return listxattr(path
, list
, size
);
2049 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
2051 return flistxattr(fsp
->fh
->fd
, list
, size
);
2054 static int vfswrap_removexattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
)
2056 return removexattr(path
, name
);
2059 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
2061 return fremovexattr(fsp
->fh
->fd
, name
);
2064 static int vfswrap_setxattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
2066 return setxattr(path
, name
, value
, size
, flags
);
2069 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
2071 return fsetxattr(fsp
->fh
->fd
, name
, value
, size
, flags
);
2074 static int vfswrap_aio_read(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, SMB_STRUCT_AIOCB
*aiocb
)
2077 if (!initialize_async_io_handler()) {
2082 * aio_read must be done as root, because in the glibc aio
2083 * implementation the helper thread needs to be able to send a signal
2084 * to the main thread, even when it has done a seteuid() to a
2088 ret
= sys_aio_read(aiocb
);
2093 static int vfswrap_aio_write(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, SMB_STRUCT_AIOCB
*aiocb
)
2096 if (!initialize_async_io_handler()) {
2101 * aio_write must be done as root, because in the glibc aio
2102 * implementation the helper thread needs to be able to send a signal
2103 * to the main thread, even when it has done a seteuid() to a
2107 ret
= sys_aio_write(aiocb
);
2112 static ssize_t
vfswrap_aio_return(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, SMB_STRUCT_AIOCB
*aiocb
)
2114 return sys_aio_return(aiocb
);
2117 static int vfswrap_aio_cancel(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, SMB_STRUCT_AIOCB
*aiocb
)
2119 return sys_aio_cancel(fsp
->fh
->fd
, aiocb
);
2122 static int vfswrap_aio_error(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, SMB_STRUCT_AIOCB
*aiocb
)
2124 return sys_aio_error(aiocb
);
2127 static int vfswrap_aio_fsync(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, int op
, SMB_STRUCT_AIOCB
*aiocb
)
2129 return sys_aio_fsync(op
, aiocb
);
2132 static int vfswrap_aio_suspend(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const SMB_STRUCT_AIOCB
* const aiocb
[], int n
, const struct timespec
*timeout
)
2134 return sys_aio_suspend(aiocb
, n
, timeout
);
2137 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
2142 static bool vfswrap_is_offline(struct vfs_handle_struct
*handle
,
2143 const struct smb_filename
*fname
,
2144 SMB_STRUCT_STAT
*sbuf
)
2148 bool offline
= false;
2150 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
2154 if (!lp_dmapi_support(SNUM(handle
->conn
)) || !dmapi_have_session()) {
2155 #if defined(ENOTSUP)
2161 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
2162 if (!NT_STATUS_IS_OK(status
)) {
2163 errno
= map_errno_from_nt_status(status
);
2167 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
2174 static int vfswrap_set_offline(struct vfs_handle_struct
*handle
,
2175 const struct smb_filename
*fname
)
2177 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2178 #if defined(ENOTSUP)
2184 static struct vfs_fn_pointers vfs_default_fns
= {
2185 /* Disk operations */
2187 .connect_fn
= vfswrap_connect
,
2188 .disconnect_fn
= vfswrap_disconnect
,
2189 .disk_free_fn
= vfswrap_disk_free
,
2190 .get_quota_fn
= vfswrap_get_quota
,
2191 .set_quota_fn
= vfswrap_set_quota
,
2192 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
2193 .statvfs_fn
= vfswrap_statvfs
,
2194 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
2195 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
2197 /* Directory operations */
2199 .opendir_fn
= vfswrap_opendir
,
2200 .fdopendir_fn
= vfswrap_fdopendir
,
2201 .readdir_fn
= vfswrap_readdir
,
2202 .seekdir_fn
= vfswrap_seekdir
,
2203 .telldir_fn
= vfswrap_telldir
,
2204 .rewind_dir_fn
= vfswrap_rewinddir
,
2205 .mkdir_fn
= vfswrap_mkdir
,
2206 .rmdir_fn
= vfswrap_rmdir
,
2207 .closedir_fn
= vfswrap_closedir
,
2208 .init_search_op_fn
= vfswrap_init_search_op
,
2210 /* File operations */
2212 .open_fn
= vfswrap_open
,
2213 .create_file_fn
= vfswrap_create_file
,
2214 .close_fn
= vfswrap_close
,
2215 .read_fn
= vfswrap_read
,
2216 .pread_fn
= vfswrap_pread
,
2217 .write_fn
= vfswrap_write
,
2218 .pwrite_fn
= vfswrap_pwrite
,
2219 .lseek_fn
= vfswrap_lseek
,
2220 .sendfile_fn
= vfswrap_sendfile
,
2221 .recvfile_fn
= vfswrap_recvfile
,
2222 .rename_fn
= vfswrap_rename
,
2223 .fsync_fn
= vfswrap_fsync
,
2224 .stat_fn
= vfswrap_stat
,
2225 .fstat_fn
= vfswrap_fstat
,
2226 .lstat_fn
= vfswrap_lstat
,
2227 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
2228 .unlink_fn
= vfswrap_unlink
,
2229 .chmod_fn
= vfswrap_chmod
,
2230 .fchmod_fn
= vfswrap_fchmod
,
2231 .chown_fn
= vfswrap_chown
,
2232 .fchown_fn
= vfswrap_fchown
,
2233 .lchown_fn
= vfswrap_lchown
,
2234 .chdir_fn
= vfswrap_chdir
,
2235 .getwd_fn
= vfswrap_getwd
,
2236 .ntimes_fn
= vfswrap_ntimes
,
2237 .ftruncate_fn
= vfswrap_ftruncate
,
2238 .fallocate_fn
= vfswrap_fallocate
,
2239 .lock_fn
= vfswrap_lock
,
2240 .kernel_flock_fn
= vfswrap_kernel_flock
,
2241 .linux_setlease_fn
= vfswrap_linux_setlease
,
2242 .getlock_fn
= vfswrap_getlock
,
2243 .symlink_fn
= vfswrap_symlink
,
2244 .readlink_fn
= vfswrap_readlink
,
2245 .link_fn
= vfswrap_link
,
2246 .mknod_fn
= vfswrap_mknod
,
2247 .realpath_fn
= vfswrap_realpath
,
2248 .notify_watch_fn
= vfswrap_notify_watch
,
2249 .chflags_fn
= vfswrap_chflags
,
2250 .file_id_create_fn
= vfswrap_file_id_create
,
2251 .streaminfo_fn
= vfswrap_streaminfo
,
2252 .get_real_filename_fn
= vfswrap_get_real_filename
,
2253 .connectpath_fn
= vfswrap_connectpath
,
2254 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
2255 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
2256 .brl_cancel_windows_fn
= vfswrap_brl_cancel_windows
,
2257 .strict_lock_fn
= vfswrap_strict_lock
,
2258 .strict_unlock_fn
= vfswrap_strict_unlock
,
2259 .translate_name_fn
= vfswrap_translate_name
,
2260 .fsctl_fn
= vfswrap_fsctl
,
2262 /* NT ACL operations. */
2264 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
2265 .get_nt_acl_fn
= vfswrap_get_nt_acl
,
2266 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
2267 .audit_file_fn
= vfswrap_audit_file
,
2269 /* POSIX ACL operations. */
2271 .chmod_acl_fn
= vfswrap_chmod_acl
,
2272 .fchmod_acl_fn
= vfswrap_fchmod_acl
,
2274 .sys_acl_get_entry_fn
= vfswrap_sys_acl_get_entry
,
2275 .sys_acl_get_tag_type_fn
= vfswrap_sys_acl_get_tag_type
,
2276 .sys_acl_get_permset_fn
= vfswrap_sys_acl_get_permset
,
2277 .sys_acl_get_qualifier_fn
= vfswrap_sys_acl_get_qualifier
,
2278 .sys_acl_get_file_fn
= vfswrap_sys_acl_get_file
,
2279 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
2280 .sys_acl_clear_perms_fn
= vfswrap_sys_acl_clear_perms
,
2281 .sys_acl_add_perm_fn
= vfswrap_sys_acl_add_perm
,
2282 .sys_acl_to_text_fn
= vfswrap_sys_acl_to_text
,
2283 .sys_acl_init_fn
= vfswrap_sys_acl_init
,
2284 .sys_acl_create_entry_fn
= vfswrap_sys_acl_create_entry
,
2285 .sys_acl_set_tag_type_fn
= vfswrap_sys_acl_set_tag_type
,
2286 .sys_acl_set_qualifier_fn
= vfswrap_sys_acl_set_qualifier
,
2287 .sys_acl_set_permset_fn
= vfswrap_sys_acl_set_permset
,
2288 .sys_acl_valid_fn
= vfswrap_sys_acl_valid
,
2289 .sys_acl_set_file_fn
= vfswrap_sys_acl_set_file
,
2290 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
2291 .sys_acl_delete_def_file_fn
= vfswrap_sys_acl_delete_def_file
,
2292 .sys_acl_get_perm_fn
= vfswrap_sys_acl_get_perm
,
2293 .sys_acl_free_text_fn
= vfswrap_sys_acl_free_text
,
2294 .sys_acl_free_acl_fn
= vfswrap_sys_acl_free_acl
,
2295 .sys_acl_free_qualifier_fn
= vfswrap_sys_acl_free_qualifier
,
2297 /* EA operations. */
2298 .getxattr_fn
= vfswrap_getxattr
,
2299 .fgetxattr_fn
= vfswrap_fgetxattr
,
2300 .listxattr_fn
= vfswrap_listxattr
,
2301 .flistxattr_fn
= vfswrap_flistxattr
,
2302 .removexattr_fn
= vfswrap_removexattr
,
2303 .fremovexattr_fn
= vfswrap_fremovexattr
,
2304 .setxattr_fn
= vfswrap_setxattr
,
2305 .fsetxattr_fn
= vfswrap_fsetxattr
,
2307 /* aio operations */
2308 .aio_read_fn
= vfswrap_aio_read
,
2309 .aio_write_fn
= vfswrap_aio_write
,
2310 .aio_return_fn
= vfswrap_aio_return
,
2311 .aio_cancel_fn
= vfswrap_aio_cancel
,
2312 .aio_error_fn
= vfswrap_aio_error
,
2313 .aio_fsync_fn
= vfswrap_aio_fsync
,
2314 .aio_suspend_fn
= vfswrap_aio_suspend
,
2315 .aio_force_fn
= vfswrap_aio_force
,
2317 /* offline operations */
2318 .is_offline_fn
= vfswrap_is_offline
,
2319 .set_offline_fn
= vfswrap_set_offline
2322 NTSTATUS
vfs_default_init(void);
2323 NTSTATUS
vfs_default_init(void)
2325 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
2326 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);