testprogs: Set functional domain level to 2003.
[Samba.git] / source3 / modules / vfs_default.c
blob613101a09a95292c64a63b755b9721f93ec14cb3
1 /*
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/>.
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.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"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_VFS
39 /* Check for NULL pointer parameters in vfswrap_* functions */
41 /* We don't want to have NULL function pointers lying around. Someone
42 is sure to try and execute them. These stubs are used to prevent
43 this possibility. */
45 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
47 return 0; /* Return >= 0 for success */
50 static void vfswrap_disconnect(vfs_handle_struct *handle)
54 /* Disk operations */
56 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path, bool small_query, uint64_t *bsize,
57 uint64_t *dfree, uint64_t *dsize)
59 uint64_t result;
61 result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
62 return result;
65 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
67 #ifdef HAVE_SYS_QUOTAS
68 int result;
70 START_PROFILE(syscall_get_quota);
71 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
72 END_PROFILE(syscall_get_quota);
73 return result;
74 #else
75 errno = ENOSYS;
76 return -1;
77 #endif
80 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
82 #ifdef HAVE_SYS_QUOTAS
83 int result;
85 START_PROFILE(syscall_set_quota);
86 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
87 END_PROFILE(syscall_set_quota);
88 return result;
89 #else
90 errno = ENOSYS;
91 return -1;
92 #endif
95 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
96 struct files_struct *fsp,
97 struct shadow_copy_data *shadow_copy_data,
98 bool labels)
100 errno = ENOSYS;
101 return -1; /* Not implemented. */
104 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
106 return sys_statvfs(path, statbuf);
109 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
110 enum timestamp_set_resolution *p_ts_res)
112 connection_struct *conn = handle->conn;
113 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
114 struct smb_filename *smb_fname_cpath = NULL;
115 struct vfs_statvfs_struct statbuf;
116 int ret;
118 ZERO_STRUCT(statbuf);
119 ret = sys_statvfs(conn->connectpath, &statbuf);
120 if (ret == 0) {
121 caps = statbuf.FsCapabilities;
124 *p_ts_res = TIMESTAMP_SET_SECONDS;
126 /* Work out what timestamp resolution we can
127 * use when setting a timestamp. */
129 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
130 NULL, NULL);
131 if (smb_fname_cpath == NULL) {
132 return caps;
135 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
136 if (ret == -1) {
137 TALLOC_FREE(smb_fname_cpath);
138 return caps;
141 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
142 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
143 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
144 /* If any of the normal UNIX directory timestamps
145 * have a non-zero tv_nsec component assume
146 * we might be able to set sub-second timestamps.
147 * See what filetime set primitives we have.
149 #if defined(HAVE_UTIMENSAT)
150 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
151 #elif defined(HAVE_UTIMES)
152 /* utimes allows msec timestamps to be set. */
153 *p_ts_res = TIMESTAMP_SET_MSEC;
154 #elif defined(HAVE_UTIME)
155 /* utime only allows sec timestamps to be set. */
156 *p_ts_res = TIMESTAMP_SET_SECONDS;
157 #endif
159 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
160 "resolution of %s "
161 "available on share %s, directory %s\n",
162 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
163 lp_servicename(talloc_tos(), conn->params->service),
164 conn->connectpath ));
166 TALLOC_FREE(smb_fname_cpath);
167 return caps;
170 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
171 struct dfs_GetDFSReferral *r)
173 struct junction_map *junction = NULL;
174 int consumedcnt = 0;
175 bool self_referral = false;
176 char *pathnamep = NULL;
177 char *local_dfs_path = NULL;
178 NTSTATUS status;
179 int i;
180 uint16_t max_referral_level = r->in.req.max_referral_level;
182 if (DEBUGLVL(10)) {
183 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
186 /* get the junction entry */
187 if (r->in.req.servername == NULL) {
188 return NT_STATUS_NOT_FOUND;
192 * Trim pathname sent by client so it begins with only one backslash.
193 * Two backslashes confuse some dfs clients
196 local_dfs_path = talloc_strdup(r, r->in.req.servername);
197 if (local_dfs_path == NULL) {
198 return NT_STATUS_NO_MEMORY;
200 pathnamep = local_dfs_path;
201 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
202 IS_DIRECTORY_SEP(pathnamep[1])) {
203 pathnamep++;
206 junction = talloc_zero(r, struct junction_map);
207 if (junction == NULL) {
208 return NT_STATUS_NO_MEMORY;
211 /* The following call can change cwd. */
212 status = get_referred_path(r, pathnamep,
213 !handle->conn->sconn->using_smb2,
214 junction, &consumedcnt, &self_referral);
215 if (!NT_STATUS_IS_OK(status)) {
216 vfs_ChDir(handle->conn, handle->conn->connectpath);
217 return status;
219 vfs_ChDir(handle->conn, handle->conn->connectpath);
221 if (!self_referral) {
222 pathnamep[consumedcnt] = '\0';
224 if (DEBUGLVL(3)) {
225 dbgtext("setup_dfs_referral: Path %s to "
226 "alternate path(s):",
227 pathnamep);
228 for (i=0; i < junction->referral_count; i++) {
229 dbgtext(" %s",
230 junction->referral_list[i].alternate_path);
232 dbgtext(".\n");
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;
252 if (self_referral) {
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) {
264 case 2:
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;
272 t->version = 2;
273 v2->size = VERSION2_REFERRAL_SIZE;
274 if (self_referral) {
275 v2->server_type = DFS_SERVER_ROOT;
276 } else {
277 v2->server_type = DFS_SERVER_NON_ROOT;
279 v2->entry_flags = 0;
280 v2->proximity = ref->proximity;
281 v2->ttl = ref->ttl;
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;
297 break;
298 case 3:
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;
307 t->version = 3;
308 v3->size = VERSION3_REFERRAL_SIZE;
309 if (self_referral) {
310 v3->server_type = DFS_SERVER_ROOT;
311 } else {
312 v3->server_type = DFS_SERVER_NON_ROOT;
314 v3->entry_flags = 0;
315 v3->ttl = ref->ttl;
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;
330 break;
331 default:
332 DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
333 "version: %d\n",
334 max_referral_level));
335 return NT_STATUS_INVALID_LEVEL;
338 if (DEBUGLVL(10)) {
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
342 return NT_STATUS_OK;
345 /* Directory operations */
347 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
349 DIR *result;
351 START_PROFILE(syscall_opendir);
352 result = opendir(fname);
353 END_PROFILE(syscall_opendir);
354 return result;
357 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
358 files_struct *fsp,
359 const char *mask,
360 uint32 attr)
362 DIR *result;
364 START_PROFILE(syscall_fdopendir);
365 result = sys_fdopendir(fsp->fh->fd);
366 END_PROFILE(syscall_fdopendir);
367 return result;
371 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
372 DIR *dirp,
373 SMB_STRUCT_STAT *sbuf)
375 struct dirent *result;
377 START_PROFILE(syscall_readdir);
378 result = readdir(dirp);
379 END_PROFILE(syscall_readdir);
380 if (sbuf) {
381 /* Default Posix readdir() does not give us stat info.
382 * Set to invalid to indicate we didn't return this info. */
383 SET_STAT_INVALID(*sbuf);
384 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
385 if (result != NULL) {
386 /* See if we can efficiently return this. */
387 struct stat st;
388 int flags = (lp_posix_pathnames() ?
389 AT_SYMLINK_NOFOLLOW : 0);
390 int ret = fstatat(dirfd(dirp),
391 result->d_name,
392 &st,
393 flags);
394 if (ret == 0) {
395 init_stat_ex_from_stat(sbuf,
396 &st,
397 lp_fake_directory_create_times(
398 SNUM(handle->conn)));
401 #endif
403 return result;
406 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
407 const struct smb_filename *fname,
408 TALLOC_CTX *mem_ctx,
409 struct readdir_attr_data **attr_data)
411 return NT_STATUS_NOT_SUPPORTED;
414 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
416 START_PROFILE(syscall_seekdir);
417 seekdir(dirp, offset);
418 END_PROFILE(syscall_seekdir);
421 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
423 long result;
424 START_PROFILE(syscall_telldir);
425 result = telldir(dirp);
426 END_PROFILE(syscall_telldir);
427 return result;
430 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
432 START_PROFILE(syscall_rewinddir);
433 rewinddir(dirp);
434 END_PROFILE(syscall_rewinddir);
437 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
439 int result;
440 bool has_dacl = False;
441 char *parent = NULL;
443 START_PROFILE(syscall_mkdir);
445 if (lp_inherit_acls(SNUM(handle->conn))
446 && parent_dirname(talloc_tos(), path, &parent, NULL)
447 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
448 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
450 TALLOC_FREE(parent);
452 result = mkdir(path, mode);
454 if (result == 0 && !has_dacl) {
456 * We need to do this as the default behavior of POSIX ACLs
457 * is to set the mask to be the requested group permission
458 * bits, not the group permission bits to be the requested
459 * group permission bits. This is not what we want, as it will
460 * mess up any inherited ACL bits that were set. JRA.
462 int saved_errno = errno; /* We may get ENOSYS */
463 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
464 errno = saved_errno;
467 END_PROFILE(syscall_mkdir);
468 return result;
471 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
473 int result;
475 START_PROFILE(syscall_rmdir);
476 result = rmdir(path);
477 END_PROFILE(syscall_rmdir);
478 return result;
481 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
483 int result;
485 START_PROFILE(syscall_closedir);
486 result = closedir(dirp);
487 END_PROFILE(syscall_closedir);
488 return result;
491 static void vfswrap_init_search_op(vfs_handle_struct *handle,
492 DIR *dirp)
494 /* Default behavior is a NOOP */
497 /* File operations */
499 static int vfswrap_open(vfs_handle_struct *handle,
500 struct smb_filename *smb_fname,
501 files_struct *fsp, int flags, mode_t mode)
503 int result = -1;
505 START_PROFILE(syscall_open);
507 if (smb_fname->stream_name) {
508 errno = ENOENT;
509 goto out;
512 result = open(smb_fname->base_name, flags, mode);
513 out:
514 END_PROFILE(syscall_open);
515 return result;
518 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
519 struct smb_request *req,
520 uint16_t root_dir_fid,
521 struct smb_filename *smb_fname,
522 uint32_t access_mask,
523 uint32_t share_access,
524 uint32_t create_disposition,
525 uint32_t create_options,
526 uint32_t file_attributes,
527 uint32_t oplock_request,
528 struct smb2_lease *lease,
529 uint64_t allocation_size,
530 uint32_t private_flags,
531 struct security_descriptor *sd,
532 struct ea_list *ea_list,
533 files_struct **result,
534 int *pinfo,
535 const struct smb2_create_blobs *in_context_blobs,
536 struct smb2_create_blobs *out_context_blobs)
538 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
539 access_mask, share_access,
540 create_disposition, create_options,
541 file_attributes, oplock_request, lease,
542 allocation_size, private_flags,
543 sd, ea_list, result,
544 pinfo, in_context_blobs, out_context_blobs);
547 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
549 int result;
551 START_PROFILE(syscall_close);
552 result = fd_close_posix(fsp);
553 END_PROFILE(syscall_close);
554 return result;
557 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
559 ssize_t result;
561 START_PROFILE_BYTES(syscall_read, n);
562 result = sys_read(fsp->fh->fd, data, n);
563 END_PROFILE_BYTES(syscall_read);
564 return result;
567 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
568 size_t n, off_t offset)
570 ssize_t result;
572 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
573 START_PROFILE_BYTES(syscall_pread, n);
574 result = sys_pread(fsp->fh->fd, data, n, offset);
575 END_PROFILE_BYTES(syscall_pread);
577 if (result == -1 && errno == ESPIPE) {
578 /* Maintain the fiction that pipes can be seeked (sought?) on. */
579 result = SMB_VFS_READ(fsp, data, n);
580 fsp->fh->pos = 0;
583 #else /* HAVE_PREAD */
584 off_t curr;
585 int lerrno;
587 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
588 if (curr == -1 && errno == ESPIPE) {
589 /* Maintain the fiction that pipes can be seeked (sought?) on. */
590 result = SMB_VFS_READ(fsp, data, n);
591 fsp->fh->pos = 0;
592 return result;
595 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
596 return -1;
599 errno = 0;
600 result = SMB_VFS_READ(fsp, data, n);
601 lerrno = errno;
603 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
604 errno = lerrno;
606 #endif /* HAVE_PREAD */
608 return result;
611 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
613 ssize_t result;
615 START_PROFILE_BYTES(syscall_write, n);
616 result = sys_write(fsp->fh->fd, data, n);
617 END_PROFILE_BYTES(syscall_write);
618 return result;
621 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
622 size_t n, off_t offset)
624 ssize_t result;
626 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
627 START_PROFILE_BYTES(syscall_pwrite, n);
628 result = sys_pwrite(fsp->fh->fd, data, n, offset);
629 END_PROFILE_BYTES(syscall_pwrite);
631 if (result == -1 && errno == ESPIPE) {
632 /* Maintain the fiction that pipes can be sought on. */
633 result = SMB_VFS_WRITE(fsp, data, n);
636 #else /* HAVE_PWRITE */
637 off_t curr;
638 int lerrno;
640 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
641 if (curr == -1) {
642 return -1;
645 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
646 return -1;
649 result = SMB_VFS_WRITE(fsp, data, n);
650 lerrno = errno;
652 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
653 errno = lerrno;
655 #endif /* HAVE_PWRITE */
657 return result;
660 static void vfswrap_asys_finished(struct tevent_context *ev,
661 struct tevent_fd *fde,
662 uint16_t flags, void *p);
664 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
666 int ret;
667 int fd;
669 if (conn->asys_ctx != NULL) {
670 return true;
672 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
673 if (ret != 0) {
674 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
675 return false;
678 fd = asys_signalfd(conn->asys_ctx);
680 set_blocking(fd, false);
682 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
683 TEVENT_FD_READ,
684 vfswrap_asys_finished,
685 conn->asys_ctx);
686 if (conn->asys_fde == NULL) {
687 DEBUG(1, ("tevent_add_fd failed\n"));
688 asys_context_destroy(conn->asys_ctx);
689 conn->asys_ctx = NULL;
690 return false;
692 return true;
695 struct vfswrap_asys_state {
696 struct asys_context *asys_ctx;
697 struct tevent_req *req;
698 ssize_t ret;
699 int err;
700 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
701 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
704 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
706 asys_cancel(s->asys_ctx, s->req);
707 return 0;
710 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
711 TALLOC_CTX *mem_ctx,
712 struct tevent_context *ev,
713 struct files_struct *fsp,
714 void *data,
715 size_t n, off_t offset)
717 struct tevent_req *req;
718 struct vfswrap_asys_state *state;
719 int ret;
721 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
722 if (req == NULL) {
723 return NULL;
725 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
726 tevent_req_oom(req);
727 return tevent_req_post(req, ev);
729 state->asys_ctx = handle->conn->sconn->asys_ctx;
730 state->req = req;
732 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
733 state->profile_bytes, n);
734 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
735 if (ret != 0) {
736 tevent_req_error(req, ret);
737 return tevent_req_post(req, ev);
739 talloc_set_destructor(state, vfswrap_asys_state_destructor);
741 return req;
744 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
745 TALLOC_CTX *mem_ctx,
746 struct tevent_context *ev,
747 struct files_struct *fsp,
748 const void *data,
749 size_t n, off_t offset)
751 struct tevent_req *req;
752 struct vfswrap_asys_state *state;
753 int ret;
755 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
756 if (req == NULL) {
757 return NULL;
759 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
760 tevent_req_oom(req);
761 return tevent_req_post(req, ev);
763 state->asys_ctx = handle->conn->sconn->asys_ctx;
764 state->req = req;
766 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
767 state->profile_bytes, n);
768 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
769 if (ret != 0) {
770 tevent_req_error(req, ret);
771 return tevent_req_post(req, ev);
773 talloc_set_destructor(state, vfswrap_asys_state_destructor);
775 return req;
778 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
779 TALLOC_CTX *mem_ctx,
780 struct tevent_context *ev,
781 struct files_struct *fsp)
783 struct tevent_req *req;
784 struct vfswrap_asys_state *state;
785 int ret;
787 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
788 if (req == NULL) {
789 return NULL;
791 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
792 tevent_req_oom(req);
793 return tevent_req_post(req, ev);
795 state->asys_ctx = handle->conn->sconn->asys_ctx;
796 state->req = req;
798 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
799 state->profile_basic);
800 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
801 if (ret != 0) {
802 tevent_req_error(req, ret);
803 return tevent_req_post(req, ev);
805 talloc_set_destructor(state, vfswrap_asys_state_destructor);
807 return req;
810 static void vfswrap_asys_finished(struct tevent_context *ev,
811 struct tevent_fd *fde,
812 uint16_t flags, void *p)
814 struct asys_context *asys_ctx = (struct asys_context *)p;
815 struct asys_result results[outstanding_aio_calls];
816 int i, ret;
818 if ((flags & TEVENT_FD_READ) == 0) {
819 return;
822 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
823 if (ret < 0) {
824 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
825 return;
828 for (i=0; i<ret; i++) {
829 struct asys_result *result = &results[i];
830 struct tevent_req *req;
831 struct vfswrap_asys_state *state;
833 if ((result->ret == -1) && (result->err == ECANCELED)) {
834 continue;
837 req = talloc_get_type_abort(result->private_data,
838 struct tevent_req);
839 state = tevent_req_data(req, struct vfswrap_asys_state);
841 talloc_set_destructor(state, NULL);
843 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
844 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
845 state->ret = result->ret;
846 state->err = result->err;
847 tevent_req_defer_callback(req, ev);
848 tevent_req_done(req);
852 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
854 struct vfswrap_asys_state *state = tevent_req_data(
855 req, struct vfswrap_asys_state);
857 if (tevent_req_is_unix_error(req, err)) {
858 return -1;
860 *err = state->err;
861 return state->ret;
864 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
866 struct vfswrap_asys_state *state = tevent_req_data(
867 req, struct vfswrap_asys_state);
869 if (tevent_req_is_unix_error(req, err)) {
870 return -1;
872 *err = state->err;
873 return state->ret;
876 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
878 off_t result = 0;
880 START_PROFILE(syscall_lseek);
882 /* Cope with 'stat' file opens. */
883 if (fsp->fh->fd != -1)
884 result = lseek(fsp->fh->fd, offset, whence);
887 * We want to maintain the fiction that we can seek
888 * on a fifo for file system purposes. This allows
889 * people to set up UNIX fifo's that feed data to Windows
890 * applications. JRA.
893 if((result == -1) && (errno == ESPIPE)) {
894 result = 0;
895 errno = 0;
898 END_PROFILE(syscall_lseek);
899 return result;
902 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
903 off_t offset, size_t n)
905 ssize_t result;
907 START_PROFILE_BYTES(syscall_sendfile, n);
908 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
909 END_PROFILE_BYTES(syscall_sendfile);
910 return result;
913 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
914 int fromfd,
915 files_struct *tofsp,
916 off_t offset,
917 size_t n)
919 ssize_t result;
921 START_PROFILE_BYTES(syscall_recvfile, n);
922 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
923 END_PROFILE_BYTES(syscall_recvfile);
924 return result;
927 static int vfswrap_rename(vfs_handle_struct *handle,
928 const struct smb_filename *smb_fname_src,
929 const struct smb_filename *smb_fname_dst)
931 int result = -1;
933 START_PROFILE(syscall_rename);
935 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
936 errno = ENOENT;
937 goto out;
940 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
942 out:
943 END_PROFILE(syscall_rename);
944 return result;
947 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
949 #ifdef HAVE_FSYNC
950 int result;
952 START_PROFILE(syscall_fsync);
953 result = fsync(fsp->fh->fd);
954 END_PROFILE(syscall_fsync);
955 return result;
956 #else
957 return 0;
958 #endif
961 static int vfswrap_stat(vfs_handle_struct *handle,
962 struct smb_filename *smb_fname)
964 int result = -1;
966 START_PROFILE(syscall_stat);
968 if (smb_fname->stream_name) {
969 errno = ENOENT;
970 goto out;
973 result = sys_stat(smb_fname->base_name, &smb_fname->st,
974 lp_fake_directory_create_times(SNUM(handle->conn)));
975 out:
976 END_PROFILE(syscall_stat);
977 return result;
980 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
982 int result;
984 START_PROFILE(syscall_fstat);
985 result = sys_fstat(fsp->fh->fd,
986 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
987 END_PROFILE(syscall_fstat);
988 return result;
991 static int vfswrap_lstat(vfs_handle_struct *handle,
992 struct smb_filename *smb_fname)
994 int result = -1;
996 START_PROFILE(syscall_lstat);
998 if (smb_fname->stream_name) {
999 errno = ENOENT;
1000 goto out;
1003 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1004 lp_fake_directory_create_times(SNUM(handle->conn)));
1005 out:
1006 END_PROFILE(syscall_lstat);
1007 return result;
1010 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1011 const char *name,
1012 enum vfs_translate_direction direction,
1013 TALLOC_CTX *mem_ctx,
1014 char **mapped_name)
1016 return NT_STATUS_NONE_MAPPED;
1020 * Implement the default fsctl operation.
1022 static bool vfswrap_logged_ioctl_message = false;
1024 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1025 struct files_struct *fsp,
1026 TALLOC_CTX *ctx,
1027 uint32_t function,
1028 uint16_t req_flags, /* Needed for UNICODE ... */
1029 const uint8_t *_in_data,
1030 uint32_t in_len,
1031 uint8_t **_out_data,
1032 uint32_t max_out_len,
1033 uint32_t *out_len)
1035 const char *in_data = (const char *)_in_data;
1036 char **out_data = (char **)_out_data;
1037 NTSTATUS status;
1039 switch (function) {
1040 case FSCTL_SET_SPARSE:
1042 bool set_sparse = true;
1044 if (in_len >= 1 && in_data[0] == 0) {
1045 set_sparse = false;
1048 status = file_set_sparse(handle->conn, fsp, set_sparse);
1050 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1051 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1052 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1053 nt_errstr(status)));
1055 return status;
1058 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1060 unsigned char objid[16];
1061 char *return_data = NULL;
1063 /* This should return the object-id on this file.
1064 * I think I'll make this be the inode+dev. JRA.
1067 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1068 fsp_fnum_dbg(fsp)));
1070 *out_len = MIN(max_out_len, 64);
1072 /* Hmmm, will this cause problems if less data asked for? */
1073 return_data = talloc_array(ctx, char, 64);
1074 if (return_data == NULL) {
1075 return NT_STATUS_NO_MEMORY;
1078 /* For backwards compatibility only store the dev/inode. */
1079 push_file_id_16(return_data, &fsp->file_id);
1080 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1081 push_file_id_16(return_data+32, &fsp->file_id);
1082 memset(return_data+48, 0, 16);
1083 *out_data = return_data;
1084 return NT_STATUS_OK;
1087 case FSCTL_GET_REPARSE_POINT:
1089 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1090 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1091 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1092 return NT_STATUS_NOT_A_REPARSE_POINT;
1095 case FSCTL_SET_REPARSE_POINT:
1097 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1098 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1099 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1100 return NT_STATUS_NOT_A_REPARSE_POINT;
1103 case FSCTL_GET_SHADOW_COPY_DATA:
1106 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1107 * and return their volume names. If max_data_count is 16, then it is just
1108 * asking for the number of volumes and length of the combined names.
1110 * pdata is the data allocated by our caller, but that uses
1111 * total_data_count (which is 0 in our case) rather than max_data_count.
1112 * Allocate the correct amount and return the pointer to let
1113 * it be deallocated when we return.
1115 struct shadow_copy_data *shadow_data = NULL;
1116 bool labels = False;
1117 uint32 labels_data_count = 0;
1118 uint32 i;
1119 char *cur_pdata = NULL;
1121 if (max_out_len < 16) {
1122 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1123 max_out_len));
1124 return NT_STATUS_INVALID_PARAMETER;
1127 if (max_out_len > 16) {
1128 labels = True;
1131 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1132 if (shadow_data == NULL) {
1133 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1134 return NT_STATUS_NO_MEMORY;
1138 * Call the VFS routine to actually do the work.
1140 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1141 int log_lev = 0;
1142 if (errno == 0) {
1143 /* broken module didn't set errno on error */
1144 status = NT_STATUS_UNSUCCESSFUL;
1145 } else {
1146 status = map_nt_error_from_unix(errno);
1147 if (NT_STATUS_EQUAL(status,
1148 NT_STATUS_NOT_SUPPORTED)) {
1149 log_lev = 5;
1152 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1153 "connectpath %s, failed - %s.\n",
1154 fsp->conn->connectpath,
1155 nt_errstr(status)));
1156 TALLOC_FREE(shadow_data);
1157 return status;
1160 labels_data_count = (shadow_data->num_volumes * 2 *
1161 sizeof(SHADOW_COPY_LABEL)) + 2;
1163 if (!labels) {
1164 *out_len = 16;
1165 } else {
1166 *out_len = 12 + labels_data_count;
1169 if (max_out_len < *out_len) {
1170 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1171 max_out_len, *out_len));
1172 TALLOC_FREE(shadow_data);
1173 return NT_STATUS_BUFFER_TOO_SMALL;
1176 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1177 if (cur_pdata == NULL) {
1178 TALLOC_FREE(shadow_data);
1179 return NT_STATUS_NO_MEMORY;
1182 *out_data = cur_pdata;
1184 /* num_volumes 4 bytes */
1185 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1187 if (labels) {
1188 /* num_labels 4 bytes */
1189 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1192 /* needed_data_count 4 bytes */
1193 SIVAL(cur_pdata, 8, labels_data_count);
1195 cur_pdata += 12;
1197 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1198 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1199 if (labels && shadow_data->labels) {
1200 for (i=0; i<shadow_data->num_volumes; i++) {
1201 size_t len = 0;
1202 status = srvstr_push(cur_pdata, req_flags,
1203 cur_pdata, shadow_data->labels[i],
1204 2 * sizeof(SHADOW_COPY_LABEL),
1205 STR_UNICODE|STR_TERMINATE, &len);
1206 if (!NT_STATUS_IS_OK(status)) {
1207 TALLOC_FREE(*out_data);
1208 TALLOC_FREE(shadow_data);
1209 return status;
1211 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1212 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1216 TALLOC_FREE(shadow_data);
1218 return NT_STATUS_OK;
1221 case FSCTL_FIND_FILES_BY_SID:
1223 /* pretend this succeeded -
1225 * we have to send back a list with all files owned by this SID
1227 * but I have to check that --metze
1229 struct dom_sid sid;
1230 uid_t uid;
1231 size_t sid_len;
1233 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1234 fsp_fnum_dbg(fsp)));
1236 if (in_len < 8) {
1237 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1238 return NT_STATUS_INVALID_PARAMETER;
1241 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1243 /* unknown 4 bytes: this is not the length of the sid :-( */
1244 /*unknown = IVAL(pdata,0);*/
1246 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1247 return NT_STATUS_INVALID_PARAMETER;
1249 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1251 if (!sid_to_uid(&sid, &uid)) {
1252 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1253 sid_string_dbg(&sid),
1254 (unsigned long)sid_len));
1255 uid = (-1);
1258 /* we can take a look at the find source :-)
1260 * find ./ -uid $uid -name '*' is what we need here
1263 * and send 4bytes len and then NULL terminated unicode strings
1264 * for each file
1266 * but I don't know how to deal with the paged results
1267 * (maybe we can hang the result anywhere in the fsp struct)
1269 * but I don't know how to deal with the paged results
1270 * (maybe we can hang the result anywhere in the fsp struct)
1272 * we don't send all files at once
1273 * and at the next we should *not* start from the beginning,
1274 * so we have to cache the result
1276 * --metze
1279 /* this works for now... */
1280 return NT_STATUS_OK;
1283 case FSCTL_QUERY_ALLOCATED_RANGES:
1285 /* FIXME: This is just a dummy reply, telling that all of the
1286 * file is allocated. MKS cp needs that.
1287 * Adding the real allocated ranges via FIEMAP on Linux
1288 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1289 * this FSCTL correct for sparse files.
1291 uint64_t offset, length;
1292 char *out_data_tmp = NULL;
1294 if (in_len != 16) {
1295 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1296 in_len));
1297 return NT_STATUS_INVALID_PARAMETER;
1300 if (max_out_len < 16) {
1301 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1302 max_out_len));
1303 return NT_STATUS_INVALID_PARAMETER;
1306 offset = BVAL(in_data,0);
1307 length = BVAL(in_data,8);
1309 if (offset + length < offset) {
1310 /* No 64-bit integer wrap. */
1311 return NT_STATUS_INVALID_PARAMETER;
1314 /* Shouldn't this be SMB_VFS_STAT ... ? */
1315 status = vfs_stat_fsp(fsp);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 return status;
1320 *out_len = 16;
1321 out_data_tmp = talloc_array(ctx, char, *out_len);
1322 if (out_data_tmp == NULL) {
1323 DEBUG(10, ("unable to allocate memory for response\n"));
1324 return NT_STATUS_NO_MEMORY;
1327 if (offset > fsp->fsp_name->st.st_ex_size ||
1328 fsp->fsp_name->st.st_ex_size == 0 ||
1329 length == 0) {
1330 memset(out_data_tmp, 0, *out_len);
1331 } else {
1332 uint64_t end = offset + length;
1333 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1334 SBVAL(out_data_tmp, 0, 0);
1335 SBVAL(out_data_tmp, 8, end);
1338 *out_data = out_data_tmp;
1340 return NT_STATUS_OK;
1343 case FSCTL_IS_VOLUME_DIRTY:
1345 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1346 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1348 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1349 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1351 return NT_STATUS_INVALID_PARAMETER;
1354 default:
1356 * Only print once ... unfortunately there could be lots of
1357 * different FSCTLs that are called.
1359 if (!vfswrap_logged_ioctl_message) {
1360 vfswrap_logged_ioctl_message = true;
1361 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1362 __func__, function));
1366 return NT_STATUS_NOT_SUPPORTED;
1369 struct vfs_cc_state {
1370 off_t copied;
1371 uint8_t buf[65536];
1374 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1375 TALLOC_CTX *mem_ctx,
1376 struct tevent_context *ev,
1377 struct files_struct *src_fsp,
1378 off_t src_off,
1379 struct files_struct *dest_fsp,
1380 off_t dest_off,
1381 off_t num)
1383 struct tevent_req *req;
1384 struct vfs_cc_state *vfs_cc_state;
1385 NTSTATUS status;
1387 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1388 (unsigned long)num));
1390 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1391 if (req == NULL) {
1392 return NULL;
1395 status = vfs_stat_fsp(src_fsp);
1396 if (tevent_req_nterror(req, status)) {
1397 return tevent_req_post(req, ev);
1400 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1402 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1403 * If the SourceOffset or SourceOffset + Length extends beyond
1404 * the end of file, the server SHOULD<240> treat this as a
1405 * STATUS_END_OF_FILE error.
1406 * ...
1407 * <240> Section 3.3.5.15.6: Windows servers will return
1408 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1410 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1411 return tevent_req_post(req, ev);
1414 /* could use 2.6.33+ sendfile here to do this in kernel */
1415 while (vfs_cc_state->copied < num) {
1416 ssize_t ret;
1417 struct lock_struct lck;
1418 int saved_errno;
1420 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1421 num - vfs_cc_state->copied);
1423 if (src_fsp->op == NULL) {
1424 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1425 return tevent_req_post(req, ev);
1427 init_strict_lock_struct(src_fsp,
1428 src_fsp->op->global->open_persistent_id,
1429 src_off,
1430 this_num,
1431 READ_LOCK,
1432 &lck);
1434 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1435 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1436 return tevent_req_post(req, ev);
1439 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1440 this_num, src_off);
1441 if (ret == -1) {
1442 saved_errno = errno;
1445 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1447 if (ret == -1) {
1448 errno = saved_errno;
1449 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1450 return tevent_req_post(req, ev);
1452 if (ret != this_num) {
1453 /* zero tolerance for short reads */
1454 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1455 return tevent_req_post(req, ev);
1458 src_off += ret;
1460 if (dest_fsp->op == NULL) {
1461 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1462 return tevent_req_post(req, ev);
1465 init_strict_lock_struct(dest_fsp,
1466 dest_fsp->op->global->open_persistent_id,
1467 dest_off,
1468 this_num,
1469 WRITE_LOCK,
1470 &lck);
1472 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1473 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1474 return tevent_req_post(req, ev);
1477 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1478 this_num, dest_off);
1479 if (ret == -1) {
1480 saved_errno = errno;
1483 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1485 if (ret == -1) {
1486 errno = saved_errno;
1487 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1488 return tevent_req_post(req, ev);
1490 if (ret != this_num) {
1491 /* zero tolerance for short writes */
1492 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1493 return tevent_req_post(req, ev);
1495 dest_off += ret;
1497 vfs_cc_state->copied += this_num;
1500 tevent_req_done(req);
1501 return tevent_req_post(req, ev);
1504 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1505 struct tevent_req *req,
1506 off_t *copied)
1508 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1509 struct vfs_cc_state);
1510 NTSTATUS status;
1512 if (tevent_req_is_nterror(req, &status)) {
1513 DEBUG(2, ("server side copy chunk failed: %s\n",
1514 nt_errstr(status)));
1515 *copied = 0;
1516 tevent_req_received(req);
1517 return status;
1520 *copied = vfs_cc_state->copied;
1521 DEBUG(10, ("server side copy chunk copied %lu\n",
1522 (unsigned long)*copied));
1523 tevent_req_received(req);
1525 return NT_STATUS_OK;
1528 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1529 TALLOC_CTX *mem_ctx,
1530 struct files_struct *fsp,
1531 struct smb_filename *smb_fname,
1532 uint16_t *_compression_fmt)
1534 return NT_STATUS_INVALID_DEVICE_REQUEST;
1537 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1538 TALLOC_CTX *mem_ctx,
1539 struct files_struct *fsp,
1540 uint16_t compression_fmt)
1542 return NT_STATUS_INVALID_DEVICE_REQUEST;
1545 /********************************************************************
1546 Given a stat buffer return the allocated size on disk, taking into
1547 account sparse files.
1548 ********************************************************************/
1549 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1550 struct files_struct *fsp,
1551 const SMB_STRUCT_STAT *sbuf)
1553 uint64_t result;
1555 START_PROFILE(syscall_get_alloc_size);
1557 if(S_ISDIR(sbuf->st_ex_mode)) {
1558 result = 0;
1559 goto out;
1562 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1563 /* The type of st_blocksize is blkcnt_t which *MUST* be
1564 signed (according to POSIX) and can be less than 64-bits.
1565 Ensure when we're converting to 64 bits wide we don't
1566 sign extend. */
1567 #if defined(SIZEOF_BLKCNT_T_8)
1568 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1569 #elif defined(SIZEOF_BLKCNT_T_4)
1571 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1572 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1574 #else
1575 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1576 #endif
1577 if (result == 0) {
1579 * Some file systems do not allocate a block for very
1580 * small files. But for non-empty file should report a
1581 * positive size.
1584 uint64_t filesize = get_file_size_stat(sbuf);
1585 if (filesize > 0) {
1586 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1589 #else
1590 result = get_file_size_stat(sbuf);
1591 #endif
1593 if (fsp && fsp->initial_allocation_size)
1594 result = MAX(result,fsp->initial_allocation_size);
1596 result = smb_roundup(handle->conn, result);
1598 out:
1599 END_PROFILE(syscall_get_alloc_size);
1600 return result;
1603 static int vfswrap_unlink(vfs_handle_struct *handle,
1604 const struct smb_filename *smb_fname)
1606 int result = -1;
1608 START_PROFILE(syscall_unlink);
1610 if (smb_fname->stream_name) {
1611 errno = ENOENT;
1612 goto out;
1614 result = unlink(smb_fname->base_name);
1616 out:
1617 END_PROFILE(syscall_unlink);
1618 return result;
1621 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1623 int result;
1625 START_PROFILE(syscall_chmod);
1628 * We need to do this due to the fact that the default POSIX ACL
1629 * chmod modifies the ACL *mask* for the group owner, not the
1630 * group owner bits directly. JRA.
1635 int saved_errno = errno; /* We might get ENOSYS */
1636 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1637 END_PROFILE(syscall_chmod);
1638 return result;
1640 /* Error - return the old errno. */
1641 errno = saved_errno;
1644 result = chmod(path, mode);
1645 END_PROFILE(syscall_chmod);
1646 return result;
1649 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1651 int result;
1653 START_PROFILE(syscall_fchmod);
1656 * We need to do this due to the fact that the default POSIX ACL
1657 * chmod modifies the ACL *mask* for the group owner, not the
1658 * group owner bits directly. JRA.
1662 int saved_errno = errno; /* We might get ENOSYS */
1663 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1664 END_PROFILE(syscall_fchmod);
1665 return result;
1667 /* Error - return the old errno. */
1668 errno = saved_errno;
1671 #if defined(HAVE_FCHMOD)
1672 result = fchmod(fsp->fh->fd, mode);
1673 #else
1674 result = -1;
1675 errno = ENOSYS;
1676 #endif
1678 END_PROFILE(syscall_fchmod);
1679 return result;
1682 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1684 int result;
1686 START_PROFILE(syscall_chown);
1687 result = chown(path, uid, gid);
1688 END_PROFILE(syscall_chown);
1689 return result;
1692 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1694 #ifdef HAVE_FCHOWN
1695 int result;
1697 START_PROFILE(syscall_fchown);
1698 result = fchown(fsp->fh->fd, uid, gid);
1699 END_PROFILE(syscall_fchown);
1700 return result;
1701 #else
1702 errno = ENOSYS;
1703 return -1;
1704 #endif
1707 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1709 int result;
1711 START_PROFILE(syscall_lchown);
1712 result = lchown(path, uid, gid);
1713 END_PROFILE(syscall_lchown);
1714 return result;
1717 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1719 int result;
1721 START_PROFILE(syscall_chdir);
1722 result = chdir(path);
1723 END_PROFILE(syscall_chdir);
1724 return result;
1727 static char *vfswrap_getwd(vfs_handle_struct *handle)
1729 char *result;
1731 START_PROFILE(syscall_getwd);
1732 result = sys_getwd();
1733 END_PROFILE(syscall_getwd);
1734 return result;
1737 /*********************************************************************
1738 nsec timestamp resolution call. Convert down to whatever the underlying
1739 system will support.
1740 **********************************************************************/
1742 static int vfswrap_ntimes(vfs_handle_struct *handle,
1743 const struct smb_filename *smb_fname,
1744 struct smb_file_time *ft)
1746 int result = -1;
1748 START_PROFILE(syscall_ntimes);
1750 if (smb_fname->stream_name) {
1751 errno = ENOENT;
1752 goto out;
1755 if (ft != NULL) {
1756 if (null_timespec(ft->atime)) {
1757 ft->atime= smb_fname->st.st_ex_atime;
1760 if (null_timespec(ft->mtime)) {
1761 ft->mtime = smb_fname->st.st_ex_mtime;
1764 if (!null_timespec(ft->create_time)) {
1765 set_create_timespec_ea(handle->conn,
1766 smb_fname,
1767 ft->create_time);
1770 if ((timespec_compare(&ft->atime,
1771 &smb_fname->st.st_ex_atime) == 0) &&
1772 (timespec_compare(&ft->mtime,
1773 &smb_fname->st.st_ex_mtime) == 0)) {
1774 return 0;
1778 #if defined(HAVE_UTIMENSAT)
1779 if (ft != NULL) {
1780 struct timespec ts[2];
1781 ts[0] = ft->atime;
1782 ts[1] = ft->mtime;
1783 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1784 } else {
1785 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1787 if (!((result == -1) && (errno == ENOSYS))) {
1788 goto out;
1790 #endif
1791 #if defined(HAVE_UTIMES)
1792 if (ft != NULL) {
1793 struct timeval tv[2];
1794 tv[0] = convert_timespec_to_timeval(ft->atime);
1795 tv[1] = convert_timespec_to_timeval(ft->mtime);
1796 result = utimes(smb_fname->base_name, tv);
1797 } else {
1798 result = utimes(smb_fname->base_name, NULL);
1800 if (!((result == -1) && (errno == ENOSYS))) {
1801 goto out;
1803 #endif
1804 #if defined(HAVE_UTIME)
1805 if (ft != NULL) {
1806 struct utimbuf times;
1807 times.actime = convert_timespec_to_time_t(ft->atime);
1808 times.modtime = convert_timespec_to_time_t(ft->mtime);
1809 result = utime(smb_fname->base_name, &times);
1810 } else {
1811 result = utime(smb_fname->base_name, NULL);
1813 if (!((result == -1) && (errno == ENOSYS))) {
1814 goto out;
1816 #endif
1817 errno = ENOSYS;
1818 result = -1;
1820 out:
1821 END_PROFILE(syscall_ntimes);
1822 return result;
1825 /*********************************************************************
1826 A version of ftruncate that will write the space on disk if strict
1827 allocate is set.
1828 **********************************************************************/
1830 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1832 off_t space_to_write;
1833 uint64_t space_avail;
1834 uint64_t bsize,dfree,dsize;
1835 int ret;
1836 NTSTATUS status;
1837 SMB_STRUCT_STAT *pst;
1839 status = vfs_stat_fsp(fsp);
1840 if (!NT_STATUS_IS_OK(status)) {
1841 return -1;
1843 pst = &fsp->fsp_name->st;
1845 #ifdef S_ISFIFO
1846 if (S_ISFIFO(pst->st_ex_mode))
1847 return 0;
1848 #endif
1850 if (pst->st_ex_size == len)
1851 return 0;
1853 /* Shrink - just ftruncate. */
1854 if (pst->st_ex_size > len)
1855 return ftruncate(fsp->fh->fd, len);
1857 space_to_write = len - pst->st_ex_size;
1859 /* for allocation try fallocate first. This can fail on some
1860 platforms e.g. when the filesystem doesn't support it and no
1861 emulation is being done by the libc (like on AIX with JFS1). In that
1862 case we do our own emulation. fallocate implementations can
1863 return ENOTSUP or EINVAL in cases like that. */
1864 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1865 pst->st_ex_size, space_to_write);
1866 if (ret == ENOSPC) {
1867 errno = ENOSPC;
1868 return -1;
1870 if (ret == 0) {
1871 return 0;
1873 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1874 "error %d. Falling back to slow manual allocation\n", ret));
1876 /* available disk space is enough or not? */
1877 space_avail = get_dfree_info(fsp->conn,
1878 fsp->fsp_name->base_name, false,
1879 &bsize,&dfree,&dsize);
1880 /* space_avail is 1k blocks */
1881 if (space_avail == (uint64_t)-1 ||
1882 ((uint64_t)space_to_write/1024 > space_avail) ) {
1883 errno = ENOSPC;
1884 return -1;
1887 /* Write out the real space on disk. */
1888 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1889 if (ret != 0) {
1890 errno = ret;
1891 ret = -1;
1894 return 0;
1897 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1899 int result = -1;
1900 SMB_STRUCT_STAT *pst;
1901 NTSTATUS status;
1902 char c = 0;
1904 START_PROFILE(syscall_ftruncate);
1906 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1907 result = strict_allocate_ftruncate(handle, fsp, len);
1908 END_PROFILE(syscall_ftruncate);
1909 return result;
1912 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1913 ftruncate if the system supports it. Then I discovered that
1914 you can have some filesystems that support ftruncate
1915 expansion and some that don't! On Linux fat can't do
1916 ftruncate extend but ext2 can. */
1918 result = ftruncate(fsp->fh->fd, len);
1919 if (result == 0)
1920 goto done;
1922 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1923 extend a file with ftruncate. Provide alternate implementation
1924 for this */
1926 /* Do an fstat to see if the file is longer than the requested
1927 size in which case the ftruncate above should have
1928 succeeded or shorter, in which case seek to len - 1 and
1929 write 1 byte of zero */
1930 status = vfs_stat_fsp(fsp);
1931 if (!NT_STATUS_IS_OK(status)) {
1932 goto done;
1934 pst = &fsp->fsp_name->st;
1936 #ifdef S_ISFIFO
1937 if (S_ISFIFO(pst->st_ex_mode)) {
1938 result = 0;
1939 goto done;
1941 #endif
1943 if (pst->st_ex_size == len) {
1944 result = 0;
1945 goto done;
1948 if (pst->st_ex_size > len) {
1949 /* the ftruncate should have worked */
1950 goto done;
1953 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1954 goto done;
1957 result = 0;
1959 done:
1961 END_PROFILE(syscall_ftruncate);
1962 return result;
1965 static int vfswrap_fallocate(vfs_handle_struct *handle,
1966 files_struct *fsp,
1967 enum vfs_fallocate_mode mode,
1968 off_t offset,
1969 off_t len)
1971 int result;
1973 START_PROFILE(syscall_fallocate);
1974 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1975 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1976 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1977 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1978 } else {
1979 errno = EINVAL;
1980 result = -1;
1982 END_PROFILE(syscall_fallocate);
1983 return result;
1986 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1988 bool result;
1990 START_PROFILE(syscall_fcntl_lock);
1991 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1992 END_PROFILE(syscall_fcntl_lock);
1993 return result;
1996 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1997 uint32 share_mode, uint32 access_mask)
1999 START_PROFILE(syscall_kernel_flock);
2000 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2001 END_PROFILE(syscall_kernel_flock);
2002 return 0;
2005 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2007 bool result;
2009 START_PROFILE(syscall_fcntl_getlock);
2010 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2011 END_PROFILE(syscall_fcntl_getlock);
2012 return result;
2015 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2016 int leasetype)
2018 int result = -1;
2020 START_PROFILE(syscall_linux_setlease);
2022 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2023 result = linux_setlease(fsp->fh->fd, leasetype);
2024 #else
2025 errno = ENOSYS;
2026 #endif
2027 END_PROFILE(syscall_linux_setlease);
2028 return result;
2031 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2033 int result;
2035 START_PROFILE(syscall_symlink);
2036 result = symlink(oldpath, newpath);
2037 END_PROFILE(syscall_symlink);
2038 return result;
2041 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2043 int result;
2045 START_PROFILE(syscall_readlink);
2046 result = readlink(path, buf, bufsiz);
2047 END_PROFILE(syscall_readlink);
2048 return result;
2051 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2053 int result;
2055 START_PROFILE(syscall_link);
2056 result = link(oldpath, newpath);
2057 END_PROFILE(syscall_link);
2058 return result;
2061 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2063 int result;
2065 START_PROFILE(syscall_mknod);
2066 result = sys_mknod(pathname, mode, dev);
2067 END_PROFILE(syscall_mknod);
2068 return result;
2071 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2073 char *result;
2075 START_PROFILE(syscall_realpath);
2076 #ifdef REALPATH_TAKES_NULL
2077 result = realpath(path, NULL);
2078 #else
2079 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2080 if (result) {
2081 char *resolved_path = realpath(path, result);
2082 if (!resolved_path) {
2083 SAFE_FREE(result);
2084 } else {
2085 /* SMB_ASSERT(result == resolved_path) ? */
2086 result = resolved_path;
2089 #endif
2090 END_PROFILE(syscall_realpath);
2091 return result;
2094 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2095 struct sys_notify_context *ctx,
2096 const char *path,
2097 uint32_t *filter,
2098 uint32_t *subdir_filter,
2099 void (*callback)(struct sys_notify_context *ctx,
2100 void *private_data,
2101 struct notify_event *ev),
2102 void *private_data, void *handle)
2105 * So far inotify is the only supported default notify mechanism. If
2106 * another platform like the the BSD's or a proprietary Unix comes
2107 * along and wants another default, we can play the same trick we
2108 * played with Posix ACLs.
2110 * Until that is the case, hard-code inotify here.
2112 #ifdef HAVE_INOTIFY
2113 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2114 return inotify_watch(ctx, path, filter, subdir_filter,
2115 callback, private_data, handle);
2117 #endif
2119 * Do nothing, leave everything to notify_internal.c
2121 return NT_STATUS_OK;
2124 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2125 unsigned int flags)
2127 #ifdef HAVE_CHFLAGS
2128 return chflags(path, flags);
2129 #else
2130 errno = ENOSYS;
2131 return -1;
2132 #endif
2135 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2136 const SMB_STRUCT_STAT *sbuf)
2138 struct file_id key;
2140 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2141 * blob */
2142 ZERO_STRUCT(key);
2144 key.devid = sbuf->st_ex_dev;
2145 key.inode = sbuf->st_ex_ino;
2146 /* key.extid is unused by default. */
2148 return key;
2151 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2152 struct files_struct *fsp,
2153 const char *fname,
2154 TALLOC_CTX *mem_ctx,
2155 unsigned int *pnum_streams,
2156 struct stream_struct **pstreams)
2158 SMB_STRUCT_STAT sbuf;
2159 struct stream_struct *tmp_streams = NULL;
2160 int ret;
2162 if ((fsp != NULL) && (fsp->is_directory)) {
2164 * No default streams on directories
2166 goto done;
2169 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2170 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2172 else {
2173 struct smb_filename smb_fname;
2175 ZERO_STRUCT(smb_fname);
2176 smb_fname.base_name = discard_const_p(char, fname);
2178 if (lp_posix_pathnames()) {
2179 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2180 } else {
2181 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2183 sbuf = smb_fname.st;
2186 if (ret == -1) {
2187 return map_nt_error_from_unix(errno);
2190 if (S_ISDIR(sbuf.st_ex_mode)) {
2191 goto done;
2194 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2195 (*pnum_streams) + 1);
2196 if (tmp_streams == NULL) {
2197 return NT_STATUS_NO_MEMORY;
2199 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2200 if (tmp_streams[*pnum_streams].name == NULL) {
2201 return NT_STATUS_NO_MEMORY;
2203 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2204 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2206 *pnum_streams += 1;
2207 *pstreams = tmp_streams;
2208 done:
2209 return NT_STATUS_OK;
2212 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2213 const char *path,
2214 const char *name,
2215 TALLOC_CTX *mem_ctx,
2216 char **found_name)
2219 * Don't fall back to get_real_filename so callers can differentiate
2220 * between a full directory scan and an actual case-insensitive stat.
2222 errno = EOPNOTSUPP;
2223 return -1;
2226 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2227 const char *fname)
2229 return handle->conn->connectpath;
2232 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2233 struct byte_range_lock *br_lck,
2234 struct lock_struct *plock,
2235 bool blocking_lock)
2237 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2239 /* Note: blr is not used in the default implementation. */
2240 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2243 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2244 struct messaging_context *msg_ctx,
2245 struct byte_range_lock *br_lck,
2246 const struct lock_struct *plock)
2248 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2250 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2253 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2254 struct byte_range_lock *br_lck,
2255 struct lock_struct *plock)
2257 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2259 /* Note: blr is not used in the default implementation. */
2260 return brl_lock_cancel_default(br_lck, plock);
2263 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2264 files_struct *fsp,
2265 struct lock_struct *plock)
2267 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2268 plock->lock_type == WRITE_LOCK);
2270 return strict_lock_default(fsp, plock);
2273 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2274 files_struct *fsp,
2275 struct lock_struct *plock)
2277 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2278 plock->lock_type == WRITE_LOCK);
2280 strict_unlock_default(fsp, plock);
2283 /* NT ACL operations. */
2285 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2286 files_struct *fsp,
2287 uint32 security_info,
2288 TALLOC_CTX *mem_ctx,
2289 struct security_descriptor **ppdesc)
2291 NTSTATUS result;
2293 START_PROFILE(fget_nt_acl);
2294 result = posix_fget_nt_acl(fsp, security_info,
2295 mem_ctx, ppdesc);
2296 END_PROFILE(fget_nt_acl);
2297 return result;
2300 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2301 const char *name,
2302 uint32 security_info,
2303 TALLOC_CTX *mem_ctx,
2304 struct security_descriptor **ppdesc)
2306 NTSTATUS result;
2308 START_PROFILE(get_nt_acl);
2309 result = posix_get_nt_acl(handle->conn, name, security_info,
2310 mem_ctx, ppdesc);
2311 END_PROFILE(get_nt_acl);
2312 return result;
2315 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2317 NTSTATUS result;
2319 START_PROFILE(fset_nt_acl);
2320 result = set_nt_acl(fsp, security_info_sent, psd);
2321 END_PROFILE(fset_nt_acl);
2322 return result;
2325 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2326 struct smb_filename *file,
2327 struct security_acl *sacl,
2328 uint32_t access_requested,
2329 uint32_t access_denied)
2331 return NT_STATUS_OK; /* Nothing to do here ... */
2334 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2336 #ifdef HAVE_NO_ACL
2337 errno = ENOSYS;
2338 return -1;
2339 #else
2340 int result;
2342 START_PROFILE(chmod_acl);
2343 result = chmod_acl(handle->conn, name, mode);
2344 END_PROFILE(chmod_acl);
2345 return result;
2346 #endif
2349 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2351 #ifdef HAVE_NO_ACL
2352 errno = ENOSYS;
2353 return -1;
2354 #else
2355 int result;
2357 START_PROFILE(fchmod_acl);
2358 result = fchmod_acl(fsp, mode);
2359 END_PROFILE(fchmod_acl);
2360 return result;
2361 #endif
2364 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2365 const char *path_p,
2366 SMB_ACL_TYPE_T type,
2367 TALLOC_CTX *mem_ctx)
2369 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2372 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2373 files_struct *fsp,
2374 TALLOC_CTX *mem_ctx)
2376 return sys_acl_get_fd(handle, fsp, mem_ctx);
2379 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2381 return sys_acl_set_file(handle, name, acltype, theacl);
2384 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2386 return sys_acl_set_fd(handle, fsp, theacl);
2389 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2391 return sys_acl_delete_def_file(handle, path);
2394 /****************************************************************
2395 Extended attribute operations.
2396 *****************************************************************/
2398 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2400 return getxattr(path, name, value, size);
2403 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2405 return fgetxattr(fsp->fh->fd, name, value, size);
2408 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2410 return listxattr(path, list, size);
2413 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2415 return flistxattr(fsp->fh->fd, list, size);
2418 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2420 return removexattr(path, name);
2423 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2425 return fremovexattr(fsp->fh->fd, name);
2428 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2430 return setxattr(path, name, value, size, flags);
2433 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2435 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2438 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2440 return false;
2443 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2444 const struct smb_filename *fname,
2445 SMB_STRUCT_STAT *sbuf)
2447 NTSTATUS status;
2448 char *path;
2449 bool offline = false;
2451 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2452 return false;
2455 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2456 #if defined(ENOTSUP)
2457 errno = ENOTSUP;
2458 #endif
2459 return false;
2462 status = get_full_smb_filename(talloc_tos(), fname, &path);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 errno = map_errno_from_nt_status(status);
2465 return false;
2468 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2470 TALLOC_FREE(path);
2472 return offline;
2475 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2476 const struct smb_filename *fname)
2478 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2479 #if defined(ENOTSUP)
2480 errno = ENOTSUP;
2481 #endif
2482 return -1;
2485 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2486 struct files_struct *fsp,
2487 TALLOC_CTX *mem_ctx,
2488 DATA_BLOB *cookie)
2490 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2493 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2494 struct files_struct *fsp,
2495 const DATA_BLOB old_cookie,
2496 TALLOC_CTX *mem_ctx,
2497 DATA_BLOB *new_cookie)
2499 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2500 new_cookie);
2503 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2504 struct smb_request *smb1req,
2505 struct smbXsrv_open *op,
2506 const DATA_BLOB old_cookie,
2507 TALLOC_CTX *mem_ctx,
2508 struct files_struct **fsp,
2509 DATA_BLOB *new_cookie)
2511 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2512 old_cookie, mem_ctx,
2513 fsp, new_cookie);
2516 static struct vfs_fn_pointers vfs_default_fns = {
2517 /* Disk operations */
2519 .connect_fn = vfswrap_connect,
2520 .disconnect_fn = vfswrap_disconnect,
2521 .disk_free_fn = vfswrap_disk_free,
2522 .get_quota_fn = vfswrap_get_quota,
2523 .set_quota_fn = vfswrap_set_quota,
2524 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2525 .statvfs_fn = vfswrap_statvfs,
2526 .fs_capabilities_fn = vfswrap_fs_capabilities,
2527 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2529 /* Directory operations */
2531 .opendir_fn = vfswrap_opendir,
2532 .fdopendir_fn = vfswrap_fdopendir,
2533 .readdir_fn = vfswrap_readdir,
2534 .readdir_attr_fn = vfswrap_readdir_attr,
2535 .seekdir_fn = vfswrap_seekdir,
2536 .telldir_fn = vfswrap_telldir,
2537 .rewind_dir_fn = vfswrap_rewinddir,
2538 .mkdir_fn = vfswrap_mkdir,
2539 .rmdir_fn = vfswrap_rmdir,
2540 .closedir_fn = vfswrap_closedir,
2541 .init_search_op_fn = vfswrap_init_search_op,
2543 /* File operations */
2545 .open_fn = vfswrap_open,
2546 .create_file_fn = vfswrap_create_file,
2547 .close_fn = vfswrap_close,
2548 .read_fn = vfswrap_read,
2549 .pread_fn = vfswrap_pread,
2550 .pread_send_fn = vfswrap_pread_send,
2551 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2552 .write_fn = vfswrap_write,
2553 .pwrite_fn = vfswrap_pwrite,
2554 .pwrite_send_fn = vfswrap_pwrite_send,
2555 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2556 .lseek_fn = vfswrap_lseek,
2557 .sendfile_fn = vfswrap_sendfile,
2558 .recvfile_fn = vfswrap_recvfile,
2559 .rename_fn = vfswrap_rename,
2560 .fsync_fn = vfswrap_fsync,
2561 .fsync_send_fn = vfswrap_fsync_send,
2562 .fsync_recv_fn = vfswrap_asys_int_recv,
2563 .stat_fn = vfswrap_stat,
2564 .fstat_fn = vfswrap_fstat,
2565 .lstat_fn = vfswrap_lstat,
2566 .get_alloc_size_fn = vfswrap_get_alloc_size,
2567 .unlink_fn = vfswrap_unlink,
2568 .chmod_fn = vfswrap_chmod,
2569 .fchmod_fn = vfswrap_fchmod,
2570 .chown_fn = vfswrap_chown,
2571 .fchown_fn = vfswrap_fchown,
2572 .lchown_fn = vfswrap_lchown,
2573 .chdir_fn = vfswrap_chdir,
2574 .getwd_fn = vfswrap_getwd,
2575 .ntimes_fn = vfswrap_ntimes,
2576 .ftruncate_fn = vfswrap_ftruncate,
2577 .fallocate_fn = vfswrap_fallocate,
2578 .lock_fn = vfswrap_lock,
2579 .kernel_flock_fn = vfswrap_kernel_flock,
2580 .linux_setlease_fn = vfswrap_linux_setlease,
2581 .getlock_fn = vfswrap_getlock,
2582 .symlink_fn = vfswrap_symlink,
2583 .readlink_fn = vfswrap_readlink,
2584 .link_fn = vfswrap_link,
2585 .mknod_fn = vfswrap_mknod,
2586 .realpath_fn = vfswrap_realpath,
2587 .notify_watch_fn = vfswrap_notify_watch,
2588 .chflags_fn = vfswrap_chflags,
2589 .file_id_create_fn = vfswrap_file_id_create,
2590 .streaminfo_fn = vfswrap_streaminfo,
2591 .get_real_filename_fn = vfswrap_get_real_filename,
2592 .connectpath_fn = vfswrap_connectpath,
2593 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2594 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2595 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2596 .strict_lock_fn = vfswrap_strict_lock,
2597 .strict_unlock_fn = vfswrap_strict_unlock,
2598 .translate_name_fn = vfswrap_translate_name,
2599 .fsctl_fn = vfswrap_fsctl,
2600 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2601 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2602 .get_compression_fn = vfswrap_get_compression,
2603 .set_compression_fn = vfswrap_set_compression,
2605 /* NT ACL operations. */
2607 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2608 .get_nt_acl_fn = vfswrap_get_nt_acl,
2609 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2610 .audit_file_fn = vfswrap_audit_file,
2612 /* POSIX ACL operations. */
2614 .chmod_acl_fn = vfswrap_chmod_acl,
2615 .fchmod_acl_fn = vfswrap_fchmod_acl,
2617 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2618 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2619 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2620 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2621 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2622 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2623 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2625 /* EA operations. */
2626 .getxattr_fn = vfswrap_getxattr,
2627 .fgetxattr_fn = vfswrap_fgetxattr,
2628 .listxattr_fn = vfswrap_listxattr,
2629 .flistxattr_fn = vfswrap_flistxattr,
2630 .removexattr_fn = vfswrap_removexattr,
2631 .fremovexattr_fn = vfswrap_fremovexattr,
2632 .setxattr_fn = vfswrap_setxattr,
2633 .fsetxattr_fn = vfswrap_fsetxattr,
2635 /* aio operations */
2636 .aio_force_fn = vfswrap_aio_force,
2638 /* offline operations */
2639 .is_offline_fn = vfswrap_is_offline,
2640 .set_offline_fn = vfswrap_set_offline,
2642 /* durable handle operations */
2643 .durable_cookie_fn = vfswrap_durable_cookie,
2644 .durable_disconnect_fn = vfswrap_durable_disconnect,
2645 .durable_reconnect_fn = vfswrap_durable_reconnect,
2648 NTSTATUS vfs_default_init(void);
2649 NTSTATUS vfs_default_init(void)
2651 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2652 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);