vfs_default: Fix passing of errno from async calls
[Samba.git] / source3 / modules / vfs_default.c
blobce1b6e2569306ccf01564dcbd0752264aef171cc
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/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
44 this possibility. */
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
55 /* Disk operations */
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
59 uint64_t *dsize)
61 if (sys_fsusage(path, dfree, dsize) != 0) {
62 return (uint64_t)-1;
65 *bsize = 512;
66 return *dfree / 2;
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
71 SMB_DISK_QUOTA *qt)
73 #ifdef HAVE_SYS_QUOTAS
74 int result;
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
79 return result;
80 #else
81 errno = ENOSYS;
82 return -1;
83 #endif
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
89 int result;
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
94 return result;
95 #else
96 errno = ENOSYS;
97 return -1;
98 #endif
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
104 bool labels)
106 errno = ENOSYS;
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
122 int ret;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
126 if (ret == 0) {
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
136 NULL, NULL, 0);
137 if (smb_fname_cpath == NULL) {
138 return caps;
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
142 if (ret == -1) {
143 TALLOC_FREE(smb_fname_cpath);
144 return caps;
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
163 #endif
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
166 "resolution of %s "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
173 return caps;
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
180 int consumedcnt = 0;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
184 NTSTATUS status;
185 int i;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
188 if (DEBUGLVL(10)) {
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
209 pathnamep++;
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 handle->conn->sconn->remote_address,
220 handle->conn->sconn->local_address,
221 !handle->conn->sconn->using_smb2,
222 junction, &consumedcnt, &self_referral);
223 if (!NT_STATUS_IS_OK(status)) {
224 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 return status;
227 vfs_ChDir(handle->conn, handle->conn->connectpath);
229 if (!self_referral) {
230 pathnamep[consumedcnt] = '\0';
232 if (DEBUGLVL(3)) {
233 dbgtext("Path %s to alternate path(s):",
234 pathnamep);
235 for (i=0; i < junction->referral_count; i++) {
236 dbgtext(" %s",
237 junction->referral_list[i].alternate_path);
239 dbgtext(".\n");
243 if (r->in.req.max_referral_level <= 2) {
244 max_referral_level = 2;
246 if (r->in.req.max_referral_level >= 3) {
247 max_referral_level = 3;
250 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
251 if (r->out.resp == NULL) {
252 return NT_STATUS_NO_MEMORY;
255 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
256 r->out.resp->nb_referrals = junction->referral_count;
258 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
259 if (self_referral) {
260 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
263 r->out.resp->referral_entries = talloc_zero_array(r,
264 struct dfs_referral_type,
265 r->out.resp->nb_referrals);
266 if (r->out.resp->referral_entries == NULL) {
267 return NT_STATUS_NO_MEMORY;
270 switch (max_referral_level) {
271 case 2:
272 for(i=0; i < junction->referral_count; i++) {
273 struct referral *ref = &junction->referral_list[i];
274 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
275 struct dfs_referral_type *t =
276 &r->out.resp->referral_entries[i];
277 struct dfs_referral_v2 *v2 = &t->referral.v2;
279 t->version = 2;
280 v2->size = VERSION2_REFERRAL_SIZE;
281 if (self_referral) {
282 v2->server_type = DFS_SERVER_ROOT;
283 } else {
284 v2->server_type = DFS_SERVER_NON_ROOT;
286 v2->entry_flags = 0;
287 v2->proximity = ref->proximity;
288 v2->ttl = ref->ttl;
289 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
290 if (v2->DFS_path == NULL) {
291 return NT_STATUS_NO_MEMORY;
293 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
294 if (v2->DFS_alt_path == NULL) {
295 return NT_STATUS_NO_MEMORY;
297 v2->netw_address = talloc_strdup(mem_ctx,
298 ref->alternate_path);
299 if (v2->netw_address == NULL) {
300 return NT_STATUS_NO_MEMORY;
304 break;
305 case 3:
306 for(i=0; i < junction->referral_count; i++) {
307 struct referral *ref = &junction->referral_list[i];
308 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
309 struct dfs_referral_type *t =
310 &r->out.resp->referral_entries[i];
311 struct dfs_referral_v3 *v3 = &t->referral.v3;
312 struct dfs_normal_referral *r1 = &v3->referrals.r1;
314 t->version = 3;
315 v3->size = VERSION3_REFERRAL_SIZE;
316 if (self_referral) {
317 v3->server_type = DFS_SERVER_ROOT;
318 } else {
319 v3->server_type = DFS_SERVER_NON_ROOT;
321 v3->entry_flags = 0;
322 v3->ttl = ref->ttl;
323 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
324 if (r1->DFS_path == NULL) {
325 return NT_STATUS_NO_MEMORY;
327 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
328 if (r1->DFS_alt_path == NULL) {
329 return NT_STATUS_NO_MEMORY;
331 r1->netw_address = talloc_strdup(mem_ctx,
332 ref->alternate_path);
333 if (r1->netw_address == NULL) {
334 return NT_STATUS_NO_MEMORY;
337 break;
338 default:
339 DEBUG(0,("Invalid dfs referral version: %d\n",
340 max_referral_level));
341 return NT_STATUS_INVALID_LEVEL;
344 if (DEBUGLVL(10)) {
345 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
348 return NT_STATUS_OK;
351 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
352 TALLOC_CTX *mem_ctx,
353 const char *service_path,
354 char **base_volume)
356 return NT_STATUS_NOT_SUPPORTED;
359 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
360 TALLOC_CTX *mem_ctx,
361 const char *base_volume,
362 time_t *tstamp,
363 bool rw,
364 char **base_path,
365 char **snap_path)
367 return NT_STATUS_NOT_SUPPORTED;
370 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
371 TALLOC_CTX *mem_ctx,
372 char *base_path,
373 char *snap_path)
375 return NT_STATUS_NOT_SUPPORTED;
378 /* Directory operations */
380 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
381 const struct smb_filename *smb_fname,
382 const char *mask,
383 uint32_t attr)
385 DIR *result;
387 START_PROFILE(syscall_opendir);
388 result = opendir(smb_fname->base_name);
389 END_PROFILE(syscall_opendir);
390 return result;
393 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
394 files_struct *fsp,
395 const char *mask,
396 uint32_t attr)
398 DIR *result;
400 START_PROFILE(syscall_fdopendir);
401 result = sys_fdopendir(fsp->fh->fd);
402 END_PROFILE(syscall_fdopendir);
403 return result;
407 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
408 DIR *dirp,
409 SMB_STRUCT_STAT *sbuf)
411 struct dirent *result;
413 START_PROFILE(syscall_readdir);
414 result = readdir(dirp);
415 END_PROFILE(syscall_readdir);
416 if (sbuf) {
417 /* Default Posix readdir() does not give us stat info.
418 * Set to invalid to indicate we didn't return this info. */
419 SET_STAT_INVALID(*sbuf);
420 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
421 if (result != NULL) {
422 /* See if we can efficiently return this. */
423 struct stat st;
424 int flags = AT_SYMLINK_NOFOLLOW;
425 int ret = fstatat(dirfd(dirp),
426 result->d_name,
427 &st,
428 flags);
430 * As this is an optimization,
431 * ignore it if we stat'ed a
432 * symlink. Make the caller
433 * do it again as we don't
434 * know if they wanted the link
435 * info, or its target info.
437 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
438 init_stat_ex_from_stat(sbuf,
439 &st,
440 lp_fake_directory_create_times(
441 SNUM(handle->conn)));
444 #endif
446 return result;
449 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
450 const struct smb_filename *fname,
451 TALLOC_CTX *mem_ctx,
452 struct readdir_attr_data **attr_data)
454 return NT_STATUS_NOT_SUPPORTED;
457 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
459 START_PROFILE(syscall_seekdir);
460 seekdir(dirp, offset);
461 END_PROFILE(syscall_seekdir);
464 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
466 long result;
467 START_PROFILE(syscall_telldir);
468 result = telldir(dirp);
469 END_PROFILE(syscall_telldir);
470 return result;
473 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
475 START_PROFILE(syscall_rewinddir);
476 rewinddir(dirp);
477 END_PROFILE(syscall_rewinddir);
480 static int vfswrap_mkdir(vfs_handle_struct *handle,
481 const struct smb_filename *smb_fname,
482 mode_t mode)
484 int result;
485 bool has_dacl = False;
486 const char *path = smb_fname->base_name;
487 char *parent = NULL;
489 START_PROFILE(syscall_mkdir);
491 if (lp_inherit_acls(SNUM(handle->conn))
492 && parent_dirname(talloc_tos(), path, &parent, NULL)
493 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
494 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
497 TALLOC_FREE(parent);
499 result = mkdir(path, mode);
501 if (result == 0 && !has_dacl) {
503 * We need to do this as the default behavior of POSIX ACLs
504 * is to set the mask to be the requested group permission
505 * bits, not the group permission bits to be the requested
506 * group permission bits. This is not what we want, as it will
507 * mess up any inherited ACL bits that were set. JRA.
509 int saved_errno = errno; /* We may get ENOSYS */
510 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
511 (errno == ENOSYS)) {
512 errno = saved_errno;
516 END_PROFILE(syscall_mkdir);
517 return result;
520 static int vfswrap_rmdir(vfs_handle_struct *handle,
521 const struct smb_filename *smb_fname)
523 int result;
525 START_PROFILE(syscall_rmdir);
526 result = rmdir(smb_fname->base_name);
527 END_PROFILE(syscall_rmdir);
528 return result;
531 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
533 int result;
535 START_PROFILE(syscall_closedir);
536 result = closedir(dirp);
537 END_PROFILE(syscall_closedir);
538 return result;
541 static void vfswrap_init_search_op(vfs_handle_struct *handle,
542 DIR *dirp)
544 /* Default behavior is a NOOP */
547 /* File operations */
549 static int vfswrap_open(vfs_handle_struct *handle,
550 struct smb_filename *smb_fname,
551 files_struct *fsp, int flags, mode_t mode)
553 int result = -1;
555 START_PROFILE(syscall_open);
557 if (smb_fname->stream_name) {
558 errno = ENOENT;
559 goto out;
562 result = open(smb_fname->base_name, flags, mode);
563 out:
564 END_PROFILE(syscall_open);
565 return result;
568 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
569 struct smb_request *req,
570 uint16_t root_dir_fid,
571 struct smb_filename *smb_fname,
572 uint32_t access_mask,
573 uint32_t share_access,
574 uint32_t create_disposition,
575 uint32_t create_options,
576 uint32_t file_attributes,
577 uint32_t oplock_request,
578 struct smb2_lease *lease,
579 uint64_t allocation_size,
580 uint32_t private_flags,
581 struct security_descriptor *sd,
582 struct ea_list *ea_list,
583 files_struct **result,
584 int *pinfo,
585 const struct smb2_create_blobs *in_context_blobs,
586 struct smb2_create_blobs *out_context_blobs)
588 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
589 access_mask, share_access,
590 create_disposition, create_options,
591 file_attributes, oplock_request, lease,
592 allocation_size, private_flags,
593 sd, ea_list, result,
594 pinfo, in_context_blobs, out_context_blobs);
597 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
599 int result;
601 START_PROFILE(syscall_close);
602 result = fd_close_posix(fsp);
603 END_PROFILE(syscall_close);
604 return result;
607 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
609 ssize_t result;
611 START_PROFILE_BYTES(syscall_read, n);
612 result = sys_read(fsp->fh->fd, data, n);
613 END_PROFILE_BYTES(syscall_read);
614 return result;
617 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
618 size_t n, off_t offset)
620 ssize_t result;
622 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
623 START_PROFILE_BYTES(syscall_pread, n);
624 result = sys_pread(fsp->fh->fd, data, n, offset);
625 END_PROFILE_BYTES(syscall_pread);
627 if (result == -1 && errno == ESPIPE) {
628 /* Maintain the fiction that pipes can be seeked (sought?) on. */
629 result = SMB_VFS_READ(fsp, data, n);
630 fsp->fh->pos = 0;
633 #else /* HAVE_PREAD */
634 off_t curr;
635 int lerrno;
637 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
638 if (curr == -1 && errno == ESPIPE) {
639 /* Maintain the fiction that pipes can be seeked (sought?) on. */
640 result = SMB_VFS_READ(fsp, data, n);
641 fsp->fh->pos = 0;
642 return result;
645 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
646 return -1;
649 errno = 0;
650 result = SMB_VFS_READ(fsp, data, n);
651 lerrno = errno;
653 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
654 errno = lerrno;
656 #endif /* HAVE_PREAD */
658 return result;
661 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
663 ssize_t result;
665 START_PROFILE_BYTES(syscall_write, n);
666 result = sys_write(fsp->fh->fd, data, n);
667 END_PROFILE_BYTES(syscall_write);
668 return result;
671 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
672 size_t n, off_t offset)
674 ssize_t result;
676 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
677 START_PROFILE_BYTES(syscall_pwrite, n);
678 result = sys_pwrite(fsp->fh->fd, data, n, offset);
679 END_PROFILE_BYTES(syscall_pwrite);
681 if (result == -1 && errno == ESPIPE) {
682 /* Maintain the fiction that pipes can be sought on. */
683 result = SMB_VFS_WRITE(fsp, data, n);
686 #else /* HAVE_PWRITE */
687 off_t curr;
688 int lerrno;
690 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
691 if (curr == -1) {
692 return -1;
695 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
696 return -1;
699 result = SMB_VFS_WRITE(fsp, data, n);
700 lerrno = errno;
702 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
703 errno = lerrno;
705 #endif /* HAVE_PWRITE */
707 return result;
710 static int vfswrap_init_pool(struct smbd_server_connection *conn)
712 int ret;
714 if (conn->pool != NULL) {
715 return 0;
718 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
719 &conn->pool);
720 return ret;
723 struct vfswrap_pread_state {
724 ssize_t ret;
725 int fd;
726 void *buf;
727 size_t count;
728 off_t offset;
730 struct vfs_aio_state vfs_aio_state;
731 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
734 static void vfs_pread_do(void *private_data);
735 static void vfs_pread_done(struct tevent_req *subreq);
736 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
738 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
739 TALLOC_CTX *mem_ctx,
740 struct tevent_context *ev,
741 struct files_struct *fsp,
742 void *data,
743 size_t n, off_t offset)
745 struct tevent_req *req, *subreq;
746 struct vfswrap_pread_state *state;
747 int ret;
749 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
750 if (req == NULL) {
751 return NULL;
754 ret = vfswrap_init_pool(handle->conn->sconn);
755 if (tevent_req_error(req, ret)) {
756 return tevent_req_post(req, ev);
759 state->ret = -1;
760 state->fd = fsp->fh->fd;
761 state->buf = data;
762 state->count = n;
763 state->offset = offset;
765 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
766 state->profile_bytes, n);
767 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
769 subreq = pthreadpool_tevent_job_send(
770 state, ev, handle->conn->sconn->pool,
771 vfs_pread_do, state);
772 if (tevent_req_nomem(subreq, req)) {
773 return tevent_req_post(req, ev);
775 tevent_req_set_callback(subreq, vfs_pread_done, req);
777 talloc_set_destructor(state, vfs_pread_state_destructor);
779 return req;
782 static void vfs_pread_do(void *private_data)
784 struct vfswrap_pread_state *state = talloc_get_type_abort(
785 private_data, struct vfswrap_pread_state);
786 struct timespec start_time;
787 struct timespec end_time;
789 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
791 PROFILE_TIMESTAMP(&start_time);
793 do {
794 state->ret = pread(state->fd, state->buf, state->count,
795 state->offset);
796 } while ((state->ret == -1) && (errno == EINTR));
798 if (state->ret == -1) {
799 state->vfs_aio_state.error = errno;
802 PROFILE_TIMESTAMP(&end_time);
804 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
806 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
809 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
811 return -1;
814 static void vfs_pread_done(struct tevent_req *subreq)
816 struct tevent_req *req = tevent_req_callback_data(
817 subreq, struct tevent_req);
818 struct vfswrap_pread_state *state = tevent_req_data(
819 req, struct vfswrap_pread_state);
820 int ret;
822 ret = pthreadpool_tevent_job_recv(subreq);
823 TALLOC_FREE(subreq);
824 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
825 talloc_set_destructor(state, NULL);
826 if (tevent_req_error(req, ret)) {
827 return;
830 tevent_req_done(req);
833 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
834 struct vfs_aio_state *vfs_aio_state)
836 struct vfswrap_pread_state *state = tevent_req_data(
837 req, struct vfswrap_pread_state);
839 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
840 return -1;
843 *vfs_aio_state = state->vfs_aio_state;
844 return state->ret;
847 struct vfswrap_pwrite_state {
848 ssize_t ret;
849 int fd;
850 const void *buf;
851 size_t count;
852 off_t offset;
854 struct vfs_aio_state vfs_aio_state;
855 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
858 static void vfs_pwrite_do(void *private_data);
859 static void vfs_pwrite_done(struct tevent_req *subreq);
860 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
862 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
863 TALLOC_CTX *mem_ctx,
864 struct tevent_context *ev,
865 struct files_struct *fsp,
866 const void *data,
867 size_t n, off_t offset)
869 struct tevent_req *req, *subreq;
870 struct vfswrap_pwrite_state *state;
871 int ret;
873 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
874 if (req == NULL) {
875 return NULL;
878 ret = vfswrap_init_pool(handle->conn->sconn);
879 if (tevent_req_error(req, ret)) {
880 return tevent_req_post(req, ev);
883 state->ret = -1;
884 state->fd = fsp->fh->fd;
885 state->buf = data;
886 state->count = n;
887 state->offset = offset;
889 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
890 state->profile_bytes, n);
891 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
893 subreq = pthreadpool_tevent_job_send(
894 state, ev, handle->conn->sconn->pool,
895 vfs_pwrite_do, state);
896 if (tevent_req_nomem(subreq, req)) {
897 return tevent_req_post(req, ev);
899 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
901 talloc_set_destructor(state, vfs_pwrite_state_destructor);
903 return req;
906 static void vfs_pwrite_do(void *private_data)
908 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
909 private_data, struct vfswrap_pwrite_state);
910 struct timespec start_time;
911 struct timespec end_time;
913 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
915 PROFILE_TIMESTAMP(&start_time);
917 do {
918 state->ret = pwrite(state->fd, state->buf, state->count,
919 state->offset);
920 } while ((state->ret == -1) && (errno == EINTR));
922 if (state->ret == -1) {
923 state->vfs_aio_state.error = errno;
926 PROFILE_TIMESTAMP(&end_time);
928 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
930 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
933 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
935 return -1;
938 static void vfs_pwrite_done(struct tevent_req *subreq)
940 struct tevent_req *req = tevent_req_callback_data(
941 subreq, struct tevent_req);
942 struct vfswrap_pwrite_state *state = tevent_req_data(
943 req, struct vfswrap_pwrite_state);
944 int ret;
946 ret = pthreadpool_tevent_job_recv(subreq);
947 TALLOC_FREE(subreq);
948 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
949 talloc_set_destructor(state, NULL);
950 if (tevent_req_error(req, ret)) {
951 return;
954 tevent_req_done(req);
957 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
958 struct vfs_aio_state *vfs_aio_state)
960 struct vfswrap_pwrite_state *state = tevent_req_data(
961 req, struct vfswrap_pwrite_state);
963 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
964 return -1;
967 *vfs_aio_state = state->vfs_aio_state;
968 return state->ret;
971 struct vfswrap_fsync_state {
972 ssize_t ret;
973 int fd;
975 struct vfs_aio_state vfs_aio_state;
976 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
979 static void vfs_fsync_do(void *private_data);
980 static void vfs_fsync_done(struct tevent_req *subreq);
981 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
983 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
984 TALLOC_CTX *mem_ctx,
985 struct tevent_context *ev,
986 struct files_struct *fsp)
988 struct tevent_req *req, *subreq;
989 struct vfswrap_fsync_state *state;
990 int ret;
992 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
993 if (req == NULL) {
994 return NULL;
997 ret = vfswrap_init_pool(handle->conn->sconn);
998 if (tevent_req_error(req, ret)) {
999 return tevent_req_post(req, ev);
1002 state->ret = -1;
1003 state->fd = fsp->fh->fd;
1005 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1006 state->profile_basic);
1008 subreq = pthreadpool_tevent_job_send(
1009 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1010 if (tevent_req_nomem(subreq, req)) {
1011 return tevent_req_post(req, ev);
1013 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1015 talloc_set_destructor(state, vfs_fsync_state_destructor);
1017 return req;
1020 static void vfs_fsync_do(void *private_data)
1022 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1023 private_data, struct vfswrap_fsync_state);
1024 struct timespec start_time;
1025 struct timespec end_time;
1027 PROFILE_TIMESTAMP(&start_time);
1029 do {
1030 state->ret = fsync(state->fd);
1031 } while ((state->ret == -1) && (errno == EINTR));
1033 if (state->ret == -1) {
1034 state->vfs_aio_state.error = errno;
1037 PROFILE_TIMESTAMP(&end_time);
1039 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1042 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1044 return -1;
1047 static void vfs_fsync_done(struct tevent_req *subreq)
1049 struct tevent_req *req = tevent_req_callback_data(
1050 subreq, struct tevent_req);
1051 struct vfswrap_fsync_state *state = tevent_req_data(
1052 req, struct vfswrap_fsync_state);
1053 int ret;
1055 ret = pthreadpool_tevent_job_recv(subreq);
1056 TALLOC_FREE(subreq);
1057 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1058 talloc_set_destructor(state, NULL);
1059 if (tevent_req_error(req, ret)) {
1060 return;
1063 tevent_req_done(req);
1066 static int vfswrap_fsync_recv(struct tevent_req *req,
1067 struct vfs_aio_state *vfs_aio_state)
1069 struct vfswrap_fsync_state *state = tevent_req_data(
1070 req, struct vfswrap_fsync_state);
1072 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1073 return -1;
1076 *vfs_aio_state = state->vfs_aio_state;
1077 return state->ret;
1080 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1082 off_t result = 0;
1084 START_PROFILE(syscall_lseek);
1086 /* Cope with 'stat' file opens. */
1087 if (fsp->fh->fd != -1)
1088 result = lseek(fsp->fh->fd, offset, whence);
1091 * We want to maintain the fiction that we can seek
1092 * on a fifo for file system purposes. This allows
1093 * people to set up UNIX fifo's that feed data to Windows
1094 * applications. JRA.
1097 if((result == -1) && (errno == ESPIPE)) {
1098 result = 0;
1099 errno = 0;
1102 END_PROFILE(syscall_lseek);
1103 return result;
1106 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1107 off_t offset, size_t n)
1109 ssize_t result;
1111 START_PROFILE_BYTES(syscall_sendfile, n);
1112 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1113 END_PROFILE_BYTES(syscall_sendfile);
1114 return result;
1117 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1118 int fromfd,
1119 files_struct *tofsp,
1120 off_t offset,
1121 size_t n)
1123 ssize_t result;
1125 START_PROFILE_BYTES(syscall_recvfile, n);
1126 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1127 END_PROFILE_BYTES(syscall_recvfile);
1128 return result;
1131 static int vfswrap_rename(vfs_handle_struct *handle,
1132 const struct smb_filename *smb_fname_src,
1133 const struct smb_filename *smb_fname_dst)
1135 int result = -1;
1137 START_PROFILE(syscall_rename);
1139 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1140 errno = ENOENT;
1141 goto out;
1144 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1146 out:
1147 END_PROFILE(syscall_rename);
1148 return result;
1151 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1153 #ifdef HAVE_FSYNC
1154 int result;
1156 START_PROFILE(syscall_fsync);
1157 result = fsync(fsp->fh->fd);
1158 END_PROFILE(syscall_fsync);
1159 return result;
1160 #else
1161 return 0;
1162 #endif
1165 static int vfswrap_stat(vfs_handle_struct *handle,
1166 struct smb_filename *smb_fname)
1168 int result = -1;
1170 START_PROFILE(syscall_stat);
1172 if (smb_fname->stream_name) {
1173 errno = ENOENT;
1174 goto out;
1177 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1178 lp_fake_directory_create_times(SNUM(handle->conn)));
1179 out:
1180 END_PROFILE(syscall_stat);
1181 return result;
1184 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1186 int result;
1188 START_PROFILE(syscall_fstat);
1189 result = sys_fstat(fsp->fh->fd,
1190 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1191 END_PROFILE(syscall_fstat);
1192 return result;
1195 static int vfswrap_lstat(vfs_handle_struct *handle,
1196 struct smb_filename *smb_fname)
1198 int result = -1;
1200 START_PROFILE(syscall_lstat);
1202 if (smb_fname->stream_name) {
1203 errno = ENOENT;
1204 goto out;
1207 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1208 lp_fake_directory_create_times(SNUM(handle->conn)));
1209 out:
1210 END_PROFILE(syscall_lstat);
1211 return result;
1214 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1215 const char *name,
1216 enum vfs_translate_direction direction,
1217 TALLOC_CTX *mem_ctx,
1218 char **mapped_name)
1220 return NT_STATUS_NONE_MAPPED;
1224 * Implement the default fsctl operation.
1226 static bool vfswrap_logged_ioctl_message = false;
1228 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1229 struct files_struct *fsp,
1230 TALLOC_CTX *ctx,
1231 uint32_t function,
1232 uint16_t req_flags, /* Needed for UNICODE ... */
1233 const uint8_t *_in_data,
1234 uint32_t in_len,
1235 uint8_t **_out_data,
1236 uint32_t max_out_len,
1237 uint32_t *out_len)
1239 const char *in_data = (const char *)_in_data;
1240 char **out_data = (char **)_out_data;
1241 NTSTATUS status;
1243 switch (function) {
1244 case FSCTL_SET_SPARSE:
1246 bool set_sparse = true;
1248 if (in_len >= 1 && in_data[0] == 0) {
1249 set_sparse = false;
1252 status = file_set_sparse(handle->conn, fsp, set_sparse);
1254 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1255 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1256 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1257 nt_errstr(status)));
1259 return status;
1262 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1264 unsigned char objid[16];
1265 char *return_data = NULL;
1267 /* This should return the object-id on this file.
1268 * I think I'll make this be the inode+dev. JRA.
1271 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1272 fsp_fnum_dbg(fsp)));
1274 *out_len = MIN(max_out_len, 64);
1276 /* Hmmm, will this cause problems if less data asked for? */
1277 return_data = talloc_array(ctx, char, 64);
1278 if (return_data == NULL) {
1279 return NT_STATUS_NO_MEMORY;
1282 /* For backwards compatibility only store the dev/inode. */
1283 push_file_id_16(return_data, &fsp->file_id);
1284 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1285 push_file_id_16(return_data+32, &fsp->file_id);
1286 memset(return_data+48, 0, 16);
1287 *out_data = return_data;
1288 return NT_STATUS_OK;
1291 case FSCTL_GET_REPARSE_POINT:
1293 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1294 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1295 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1296 return NT_STATUS_NOT_A_REPARSE_POINT;
1299 case FSCTL_SET_REPARSE_POINT:
1301 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1302 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1303 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1304 return NT_STATUS_NOT_A_REPARSE_POINT;
1307 case FSCTL_GET_SHADOW_COPY_DATA:
1310 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1311 * and return their volume names. If max_data_count is 16, then it is just
1312 * asking for the number of volumes and length of the combined names.
1314 * pdata is the data allocated by our caller, but that uses
1315 * total_data_count (which is 0 in our case) rather than max_data_count.
1316 * Allocate the correct amount and return the pointer to let
1317 * it be deallocated when we return.
1319 struct shadow_copy_data *shadow_data = NULL;
1320 bool labels = False;
1321 uint32_t labels_data_count = 0;
1322 uint32_t i;
1323 char *cur_pdata = NULL;
1325 if (max_out_len < 16) {
1326 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1327 max_out_len));
1328 return NT_STATUS_INVALID_PARAMETER;
1331 if (max_out_len > 16) {
1332 labels = True;
1335 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1336 if (shadow_data == NULL) {
1337 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1338 return NT_STATUS_NO_MEMORY;
1342 * Call the VFS routine to actually do the work.
1344 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1345 int log_lev = 0;
1346 if (errno == 0) {
1347 /* broken module didn't set errno on error */
1348 status = NT_STATUS_UNSUCCESSFUL;
1349 } else {
1350 status = map_nt_error_from_unix(errno);
1351 if (NT_STATUS_EQUAL(status,
1352 NT_STATUS_NOT_SUPPORTED)) {
1353 log_lev = 5;
1356 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1357 "connectpath %s, failed - %s.\n",
1358 fsp->conn->connectpath,
1359 nt_errstr(status)));
1360 TALLOC_FREE(shadow_data);
1361 return status;
1364 labels_data_count = (shadow_data->num_volumes * 2 *
1365 sizeof(SHADOW_COPY_LABEL)) + 2;
1367 if (!labels) {
1368 *out_len = 16;
1369 } else {
1370 *out_len = 12 + labels_data_count;
1373 if (max_out_len < *out_len) {
1374 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1375 max_out_len, *out_len));
1376 TALLOC_FREE(shadow_data);
1377 return NT_STATUS_BUFFER_TOO_SMALL;
1380 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1381 if (cur_pdata == NULL) {
1382 TALLOC_FREE(shadow_data);
1383 return NT_STATUS_NO_MEMORY;
1386 *out_data = cur_pdata;
1388 /* num_volumes 4 bytes */
1389 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1391 if (labels) {
1392 /* num_labels 4 bytes */
1393 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1396 /* needed_data_count 4 bytes */
1397 SIVAL(cur_pdata, 8, labels_data_count);
1399 cur_pdata += 12;
1401 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1402 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1403 if (labels && shadow_data->labels) {
1404 for (i=0; i<shadow_data->num_volumes; i++) {
1405 size_t len = 0;
1406 status = srvstr_push(cur_pdata, req_flags,
1407 cur_pdata, shadow_data->labels[i],
1408 2 * sizeof(SHADOW_COPY_LABEL),
1409 STR_UNICODE|STR_TERMINATE, &len);
1410 if (!NT_STATUS_IS_OK(status)) {
1411 TALLOC_FREE(*out_data);
1412 TALLOC_FREE(shadow_data);
1413 return status;
1415 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1416 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1420 TALLOC_FREE(shadow_data);
1422 return NT_STATUS_OK;
1425 case FSCTL_FIND_FILES_BY_SID:
1427 /* pretend this succeeded -
1429 * we have to send back a list with all files owned by this SID
1431 * but I have to check that --metze
1433 struct dom_sid sid;
1434 uid_t uid;
1435 size_t sid_len;
1437 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1438 fsp_fnum_dbg(fsp)));
1440 if (in_len < 8) {
1441 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1442 return NT_STATUS_INVALID_PARAMETER;
1445 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1447 /* unknown 4 bytes: this is not the length of the sid :-( */
1448 /*unknown = IVAL(pdata,0);*/
1450 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1451 return NT_STATUS_INVALID_PARAMETER;
1453 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1455 if (!sid_to_uid(&sid, &uid)) {
1456 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1457 sid_string_dbg(&sid),
1458 (unsigned long)sid_len));
1459 uid = (-1);
1462 /* we can take a look at the find source :-)
1464 * find ./ -uid $uid -name '*' is what we need here
1467 * and send 4bytes len and then NULL terminated unicode strings
1468 * for each file
1470 * but I don't know how to deal with the paged results
1471 * (maybe we can hang the result anywhere in the fsp struct)
1473 * but I don't know how to deal with the paged results
1474 * (maybe we can hang the result anywhere in the fsp struct)
1476 * we don't send all files at once
1477 * and at the next we should *not* start from the beginning,
1478 * so we have to cache the result
1480 * --metze
1483 /* this works for now... */
1484 return NT_STATUS_OK;
1487 case FSCTL_QUERY_ALLOCATED_RANGES:
1489 /* FIXME: This is just a dummy reply, telling that all of the
1490 * file is allocated. MKS cp needs that.
1491 * Adding the real allocated ranges via FIEMAP on Linux
1492 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1493 * this FSCTL correct for sparse files.
1495 uint64_t offset, length;
1496 char *out_data_tmp = NULL;
1498 if (in_len != 16) {
1499 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1500 in_len));
1501 return NT_STATUS_INVALID_PARAMETER;
1504 if (max_out_len < 16) {
1505 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1506 max_out_len));
1507 return NT_STATUS_INVALID_PARAMETER;
1510 offset = BVAL(in_data,0);
1511 length = BVAL(in_data,8);
1513 if (offset + length < offset) {
1514 /* No 64-bit integer wrap. */
1515 return NT_STATUS_INVALID_PARAMETER;
1518 /* Shouldn't this be SMB_VFS_STAT ... ? */
1519 status = vfs_stat_fsp(fsp);
1520 if (!NT_STATUS_IS_OK(status)) {
1521 return status;
1524 *out_len = 16;
1525 out_data_tmp = talloc_array(ctx, char, *out_len);
1526 if (out_data_tmp == NULL) {
1527 DEBUG(10, ("unable to allocate memory for response\n"));
1528 return NT_STATUS_NO_MEMORY;
1531 if (offset > fsp->fsp_name->st.st_ex_size ||
1532 fsp->fsp_name->st.st_ex_size == 0 ||
1533 length == 0) {
1534 memset(out_data_tmp, 0, *out_len);
1535 } else {
1536 uint64_t end = offset + length;
1537 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1538 SBVAL(out_data_tmp, 0, 0);
1539 SBVAL(out_data_tmp, 8, end);
1542 *out_data = out_data_tmp;
1544 return NT_STATUS_OK;
1547 case FSCTL_IS_VOLUME_DIRTY:
1549 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1550 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1552 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1553 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1555 return NT_STATUS_INVALID_PARAMETER;
1558 default:
1560 * Only print once ... unfortunately there could be lots of
1561 * different FSCTLs that are called.
1563 if (!vfswrap_logged_ioctl_message) {
1564 vfswrap_logged_ioctl_message = true;
1565 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1566 __func__, function));
1570 return NT_STATUS_NOT_SUPPORTED;
1573 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1574 const struct smb_filename *fname,
1575 SMB_STRUCT_STAT *sbuf);
1577 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1578 struct smb_filename *smb_fname,
1579 uint32_t *dosmode)
1581 bool offline;
1583 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1584 if (offline) {
1585 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1588 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1591 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1592 struct files_struct *fsp,
1593 uint32_t *dosmode)
1595 bool offline;
1597 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1598 if (offline) {
1599 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1602 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1605 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1606 const struct smb_filename *smb_fname,
1607 uint32_t dosmode)
1609 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1612 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1613 struct files_struct *fsp,
1614 uint32_t dosmode)
1616 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1619 struct vfs_cc_state {
1620 off_t copied;
1621 uint8_t *buf;
1624 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1625 TALLOC_CTX *mem_ctx,
1626 struct tevent_context *ev,
1627 struct files_struct *src_fsp,
1628 off_t src_off,
1629 struct files_struct *dest_fsp,
1630 off_t dest_off,
1631 off_t num)
1633 struct tevent_req *req;
1634 struct vfs_cc_state *vfs_cc_state;
1635 NTSTATUS status;
1637 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1638 (unsigned long)num));
1640 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1641 if (req == NULL) {
1642 return NULL;
1645 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1646 MIN(num, 8*1024*1024));
1647 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1648 return tevent_req_post(req, ev);
1651 status = vfs_stat_fsp(src_fsp);
1652 if (tevent_req_nterror(req, status)) {
1653 return tevent_req_post(req, ev);
1656 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1658 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1659 * If the SourceOffset or SourceOffset + Length extends beyond
1660 * the end of file, the server SHOULD<240> treat this as a
1661 * STATUS_END_OF_FILE error.
1662 * ...
1663 * <240> Section 3.3.5.15.6: Windows servers will return
1664 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1666 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1667 return tevent_req_post(req, ev);
1670 /* could use 2.6.33+ sendfile here to do this in kernel */
1671 while (vfs_cc_state->copied < num) {
1672 ssize_t ret;
1673 struct lock_struct lck;
1674 int saved_errno;
1676 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1677 num - vfs_cc_state->copied);
1679 if (src_fsp->op == NULL) {
1680 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1681 return tevent_req_post(req, ev);
1683 init_strict_lock_struct(src_fsp,
1684 src_fsp->op->global->open_persistent_id,
1685 src_off,
1686 this_num,
1687 READ_LOCK,
1688 &lck);
1690 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1691 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1692 return tevent_req_post(req, ev);
1695 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1696 this_num, src_off);
1697 if (ret == -1) {
1698 saved_errno = errno;
1701 SMB_VFS_STRICT_UNLOCK(dest_fsp->conn, dest_fsp, &lck);
1703 if (ret == -1) {
1704 errno = saved_errno;
1705 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1706 return tevent_req_post(req, ev);
1708 if (ret != this_num) {
1709 /* zero tolerance for short reads */
1710 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1711 return tevent_req_post(req, ev);
1714 src_off += ret;
1716 if (dest_fsp->op == NULL) {
1717 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1718 return tevent_req_post(req, ev);
1721 init_strict_lock_struct(dest_fsp,
1722 dest_fsp->op->global->open_persistent_id,
1723 dest_off,
1724 this_num,
1725 WRITE_LOCK,
1726 &lck);
1728 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1729 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1730 return tevent_req_post(req, ev);
1733 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1734 this_num, dest_off);
1735 if (ret == -1) {
1736 saved_errno = errno;
1739 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1741 if (ret == -1) {
1742 errno = saved_errno;
1743 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1744 return tevent_req_post(req, ev);
1746 if (ret != this_num) {
1747 /* zero tolerance for short writes */
1748 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1749 return tevent_req_post(req, ev);
1751 dest_off += ret;
1753 vfs_cc_state->copied += this_num;
1756 tevent_req_done(req);
1757 return tevent_req_post(req, ev);
1760 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1761 struct tevent_req *req,
1762 off_t *copied)
1764 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1765 struct vfs_cc_state);
1766 NTSTATUS status;
1768 if (tevent_req_is_nterror(req, &status)) {
1769 DEBUG(2, ("server side copy chunk failed: %s\n",
1770 nt_errstr(status)));
1771 *copied = 0;
1772 tevent_req_received(req);
1773 return status;
1776 *copied = vfs_cc_state->copied;
1777 DEBUG(10, ("server side copy chunk copied %lu\n",
1778 (unsigned long)*copied));
1779 tevent_req_received(req);
1781 return NT_STATUS_OK;
1784 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1785 TALLOC_CTX *mem_ctx,
1786 struct files_struct *fsp,
1787 struct smb_filename *smb_fname,
1788 uint16_t *_compression_fmt)
1790 return NT_STATUS_INVALID_DEVICE_REQUEST;
1793 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1794 TALLOC_CTX *mem_ctx,
1795 struct files_struct *fsp,
1796 uint16_t compression_fmt)
1798 return NT_STATUS_INVALID_DEVICE_REQUEST;
1801 /********************************************************************
1802 Given a stat buffer return the allocated size on disk, taking into
1803 account sparse files.
1804 ********************************************************************/
1805 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1806 struct files_struct *fsp,
1807 const SMB_STRUCT_STAT *sbuf)
1809 uint64_t result;
1811 START_PROFILE(syscall_get_alloc_size);
1813 if(S_ISDIR(sbuf->st_ex_mode)) {
1814 result = 0;
1815 goto out;
1818 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1819 /* The type of st_blocksize is blkcnt_t which *MUST* be
1820 signed (according to POSIX) and can be less than 64-bits.
1821 Ensure when we're converting to 64 bits wide we don't
1822 sign extend. */
1823 #if defined(SIZEOF_BLKCNT_T_8)
1824 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1825 #elif defined(SIZEOF_BLKCNT_T_4)
1827 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1828 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1830 #else
1831 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1832 #endif
1833 if (result == 0) {
1835 * Some file systems do not allocate a block for very
1836 * small files. But for non-empty file should report a
1837 * positive size.
1840 uint64_t filesize = get_file_size_stat(sbuf);
1841 if (filesize > 0) {
1842 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1845 #else
1846 result = get_file_size_stat(sbuf);
1847 #endif
1849 if (fsp && fsp->initial_allocation_size)
1850 result = MAX(result,fsp->initial_allocation_size);
1852 result = smb_roundup(handle->conn, result);
1854 out:
1855 END_PROFILE(syscall_get_alloc_size);
1856 return result;
1859 static int vfswrap_unlink(vfs_handle_struct *handle,
1860 const struct smb_filename *smb_fname)
1862 int result = -1;
1864 START_PROFILE(syscall_unlink);
1866 if (smb_fname->stream_name) {
1867 errno = ENOENT;
1868 goto out;
1870 result = unlink(smb_fname->base_name);
1872 out:
1873 END_PROFILE(syscall_unlink);
1874 return result;
1877 static int vfswrap_chmod(vfs_handle_struct *handle,
1878 const struct smb_filename *smb_fname,
1879 mode_t mode)
1881 int result;
1883 START_PROFILE(syscall_chmod);
1886 * We need to do this due to the fact that the default POSIX ACL
1887 * chmod modifies the ACL *mask* for the group owner, not the
1888 * group owner bits directly. JRA.
1893 int saved_errno = errno; /* We might get ENOSYS */
1894 result = SMB_VFS_CHMOD_ACL(handle->conn,
1895 smb_fname,
1896 mode);
1897 if (result == 0) {
1898 END_PROFILE(syscall_chmod);
1899 return result;
1901 /* Error - return the old errno. */
1902 errno = saved_errno;
1905 result = chmod(smb_fname->base_name, mode);
1906 END_PROFILE(syscall_chmod);
1907 return result;
1910 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1912 int result;
1914 START_PROFILE(syscall_fchmod);
1917 * We need to do this due to the fact that the default POSIX ACL
1918 * chmod modifies the ACL *mask* for the group owner, not the
1919 * group owner bits directly. JRA.
1923 int saved_errno = errno; /* We might get ENOSYS */
1924 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1925 END_PROFILE(syscall_fchmod);
1926 return result;
1928 /* Error - return the old errno. */
1929 errno = saved_errno;
1932 #if defined(HAVE_FCHMOD)
1933 result = fchmod(fsp->fh->fd, mode);
1934 #else
1935 result = -1;
1936 errno = ENOSYS;
1937 #endif
1939 END_PROFILE(syscall_fchmod);
1940 return result;
1943 static int vfswrap_chown(vfs_handle_struct *handle,
1944 const struct smb_filename *smb_fname,
1945 uid_t uid,
1946 gid_t gid)
1948 int result;
1950 START_PROFILE(syscall_chown);
1951 result = chown(smb_fname->base_name, uid, gid);
1952 END_PROFILE(syscall_chown);
1953 return result;
1956 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1958 #ifdef HAVE_FCHOWN
1959 int result;
1961 START_PROFILE(syscall_fchown);
1962 result = fchown(fsp->fh->fd, uid, gid);
1963 END_PROFILE(syscall_fchown);
1964 return result;
1965 #else
1966 errno = ENOSYS;
1967 return -1;
1968 #endif
1971 static int vfswrap_lchown(vfs_handle_struct *handle,
1972 const struct smb_filename *smb_fname,
1973 uid_t uid,
1974 gid_t gid)
1976 int result;
1978 START_PROFILE(syscall_lchown);
1979 result = lchown(smb_fname->base_name, uid, gid);
1980 END_PROFILE(syscall_lchown);
1981 return result;
1984 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1986 int result;
1988 START_PROFILE(syscall_chdir);
1989 result = chdir(path);
1990 END_PROFILE(syscall_chdir);
1991 return result;
1994 static char *vfswrap_getwd(vfs_handle_struct *handle)
1996 char *result;
1998 START_PROFILE(syscall_getwd);
1999 result = sys_getwd();
2000 END_PROFILE(syscall_getwd);
2001 return result;
2004 /*********************************************************************
2005 nsec timestamp resolution call. Convert down to whatever the underlying
2006 system will support.
2007 **********************************************************************/
2009 static int vfswrap_ntimes(vfs_handle_struct *handle,
2010 const struct smb_filename *smb_fname,
2011 struct smb_file_time *ft)
2013 int result = -1;
2015 START_PROFILE(syscall_ntimes);
2017 if (smb_fname->stream_name) {
2018 errno = ENOENT;
2019 goto out;
2022 if (ft != NULL) {
2023 if (null_timespec(ft->atime)) {
2024 ft->atime= smb_fname->st.st_ex_atime;
2027 if (null_timespec(ft->mtime)) {
2028 ft->mtime = smb_fname->st.st_ex_mtime;
2031 if (!null_timespec(ft->create_time)) {
2032 set_create_timespec_ea(handle->conn,
2033 smb_fname,
2034 ft->create_time);
2037 if ((timespec_compare(&ft->atime,
2038 &smb_fname->st.st_ex_atime) == 0) &&
2039 (timespec_compare(&ft->mtime,
2040 &smb_fname->st.st_ex_mtime) == 0)) {
2041 return 0;
2045 #if defined(HAVE_UTIMENSAT)
2046 if (ft != NULL) {
2047 struct timespec ts[2];
2048 ts[0] = ft->atime;
2049 ts[1] = ft->mtime;
2050 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2051 } else {
2052 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2054 if (!((result == -1) && (errno == ENOSYS))) {
2055 goto out;
2057 #endif
2058 #if defined(HAVE_UTIMES)
2059 if (ft != NULL) {
2060 struct timeval tv[2];
2061 tv[0] = convert_timespec_to_timeval(ft->atime);
2062 tv[1] = convert_timespec_to_timeval(ft->mtime);
2063 result = utimes(smb_fname->base_name, tv);
2064 } else {
2065 result = utimes(smb_fname->base_name, NULL);
2067 if (!((result == -1) && (errno == ENOSYS))) {
2068 goto out;
2070 #endif
2071 #if defined(HAVE_UTIME)
2072 if (ft != NULL) {
2073 struct utimbuf times;
2074 times.actime = convert_timespec_to_time_t(ft->atime);
2075 times.modtime = convert_timespec_to_time_t(ft->mtime);
2076 result = utime(smb_fname->base_name, &times);
2077 } else {
2078 result = utime(smb_fname->base_name, NULL);
2080 if (!((result == -1) && (errno == ENOSYS))) {
2081 goto out;
2083 #endif
2084 errno = ENOSYS;
2085 result = -1;
2087 out:
2088 END_PROFILE(syscall_ntimes);
2089 return result;
2092 /*********************************************************************
2093 A version of ftruncate that will write the space on disk if strict
2094 allocate is set.
2095 **********************************************************************/
2097 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2099 off_t space_to_write;
2100 uint64_t space_avail;
2101 uint64_t bsize,dfree,dsize;
2102 int ret;
2103 NTSTATUS status;
2104 SMB_STRUCT_STAT *pst;
2106 status = vfs_stat_fsp(fsp);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 return -1;
2110 pst = &fsp->fsp_name->st;
2112 #ifdef S_ISFIFO
2113 if (S_ISFIFO(pst->st_ex_mode))
2114 return 0;
2115 #endif
2117 if (pst->st_ex_size == len)
2118 return 0;
2120 /* Shrink - just ftruncate. */
2121 if (pst->st_ex_size > len)
2122 return ftruncate(fsp->fh->fd, len);
2124 space_to_write = len - pst->st_ex_size;
2126 /* for allocation try fallocate first. This can fail on some
2127 platforms e.g. when the filesystem doesn't support it and no
2128 emulation is being done by the libc (like on AIX with JFS1). In that
2129 case we do our own emulation. fallocate implementations can
2130 return ENOTSUP or EINVAL in cases like that. */
2131 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2132 if (ret == -1 && errno == ENOSPC) {
2133 return -1;
2135 if (ret == 0) {
2136 return 0;
2138 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2139 "error %d. Falling back to slow manual allocation\n", errno));
2141 /* available disk space is enough or not? */
2142 space_avail =
2143 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2144 /* space_avail is 1k blocks */
2145 if (space_avail == (uint64_t)-1 ||
2146 ((uint64_t)space_to_write/1024 > space_avail) ) {
2147 errno = ENOSPC;
2148 return -1;
2151 /* Write out the real space on disk. */
2152 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2153 if (ret != 0) {
2154 return -1;
2157 return 0;
2160 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2162 int result = -1;
2163 SMB_STRUCT_STAT *pst;
2164 NTSTATUS status;
2165 char c = 0;
2167 START_PROFILE(syscall_ftruncate);
2169 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2170 result = strict_allocate_ftruncate(handle, fsp, len);
2171 END_PROFILE(syscall_ftruncate);
2172 return result;
2175 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2176 ftruncate if the system supports it. Then I discovered that
2177 you can have some filesystems that support ftruncate
2178 expansion and some that don't! On Linux fat can't do
2179 ftruncate extend but ext2 can. */
2181 result = ftruncate(fsp->fh->fd, len);
2183 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2184 extend a file with ftruncate. Provide alternate implementation
2185 for this */
2187 /* Do an fstat to see if the file is longer than the requested
2188 size in which case the ftruncate above should have
2189 succeeded or shorter, in which case seek to len - 1 and
2190 write 1 byte of zero */
2191 status = vfs_stat_fsp(fsp);
2192 if (!NT_STATUS_IS_OK(status)) {
2193 goto done;
2196 /* We need to update the files_struct after successful ftruncate */
2197 if (result == 0) {
2198 goto done;
2201 pst = &fsp->fsp_name->st;
2203 #ifdef S_ISFIFO
2204 if (S_ISFIFO(pst->st_ex_mode)) {
2205 result = 0;
2206 goto done;
2208 #endif
2210 if (pst->st_ex_size == len) {
2211 result = 0;
2212 goto done;
2215 if (pst->st_ex_size > len) {
2216 /* the ftruncate should have worked */
2217 goto done;
2220 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2221 goto done;
2224 result = 0;
2226 done:
2228 END_PROFILE(syscall_ftruncate);
2229 return result;
2232 static int vfswrap_fallocate(vfs_handle_struct *handle,
2233 files_struct *fsp,
2234 uint32_t mode,
2235 off_t offset,
2236 off_t len)
2238 int result;
2240 START_PROFILE(syscall_fallocate);
2241 if (mode == 0) {
2242 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2244 * posix_fallocate returns 0 on success, errno on error
2245 * and doesn't set errno. Make it behave like fallocate()
2246 * which returns -1, and sets errno on failure.
2248 if (result != 0) {
2249 errno = result;
2250 result = -1;
2252 } else {
2253 /* sys_fallocate handles filtering of unsupported mode flags */
2254 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2256 END_PROFILE(syscall_fallocate);
2257 return result;
2260 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2262 bool result;
2264 START_PROFILE(syscall_fcntl_lock);
2266 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2267 "smbd",
2268 "force process locks",
2269 false)) {
2270 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2273 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2274 END_PROFILE(syscall_fcntl_lock);
2275 return result;
2278 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2279 uint32_t share_mode, uint32_t access_mask)
2281 START_PROFILE(syscall_kernel_flock);
2282 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2283 END_PROFILE(syscall_kernel_flock);
2284 return 0;
2287 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2289 bool result;
2290 int op = F_GETLK;
2292 START_PROFILE(syscall_fcntl_getlock);
2294 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2295 "smbd",
2296 "force process locks",
2297 false)) {
2298 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2301 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2302 END_PROFILE(syscall_fcntl_getlock);
2303 return result;
2306 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2307 int leasetype)
2309 int result = -1;
2311 START_PROFILE(syscall_linux_setlease);
2313 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2314 result = linux_setlease(fsp->fh->fd, leasetype);
2315 #else
2316 errno = ENOSYS;
2317 #endif
2318 END_PROFILE(syscall_linux_setlease);
2319 return result;
2322 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2324 int result;
2326 START_PROFILE(syscall_symlink);
2327 result = symlink(oldpath, newpath);
2328 END_PROFILE(syscall_symlink);
2329 return result;
2332 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2334 int result;
2336 START_PROFILE(syscall_readlink);
2337 result = readlink(path, buf, bufsiz);
2338 END_PROFILE(syscall_readlink);
2339 return result;
2342 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2344 int result;
2346 START_PROFILE(syscall_link);
2347 result = link(oldpath, newpath);
2348 END_PROFILE(syscall_link);
2349 return result;
2352 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2354 int result;
2356 START_PROFILE(syscall_mknod);
2357 result = sys_mknod(pathname, mode, dev);
2358 END_PROFILE(syscall_mknod);
2359 return result;
2362 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2364 char *result;
2366 START_PROFILE(syscall_realpath);
2367 result = sys_realpath(path);
2368 END_PROFILE(syscall_realpath);
2369 return result;
2372 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2373 unsigned int flags)
2375 #ifdef HAVE_CHFLAGS
2376 return chflags(path, flags);
2377 #else
2378 errno = ENOSYS;
2379 return -1;
2380 #endif
2383 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2384 const SMB_STRUCT_STAT *sbuf)
2386 struct file_id key;
2388 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2389 * blob */
2390 ZERO_STRUCT(key);
2392 key.devid = sbuf->st_ex_dev;
2393 key.inode = sbuf->st_ex_ino;
2394 /* key.extid is unused by default. */
2396 return key;
2399 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2400 struct files_struct *fsp,
2401 const struct smb_filename *smb_fname,
2402 TALLOC_CTX *mem_ctx,
2403 unsigned int *pnum_streams,
2404 struct stream_struct **pstreams)
2406 SMB_STRUCT_STAT sbuf;
2407 struct stream_struct *tmp_streams = NULL;
2408 int ret;
2410 if ((fsp != NULL) && (fsp->is_directory)) {
2412 * No default streams on directories
2414 goto done;
2417 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2418 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2420 else {
2421 struct smb_filename smb_fname_cp;
2423 ZERO_STRUCT(smb_fname_cp);
2424 smb_fname_cp.base_name = discard_const_p(char,
2425 smb_fname->base_name);
2426 smb_fname_cp.flags = smb_fname->flags;
2428 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2429 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2430 } else {
2431 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2433 sbuf = smb_fname_cp.st;
2436 if (ret == -1) {
2437 return map_nt_error_from_unix(errno);
2440 if (S_ISDIR(sbuf.st_ex_mode)) {
2441 goto done;
2444 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2445 (*pnum_streams) + 1);
2446 if (tmp_streams == NULL) {
2447 return NT_STATUS_NO_MEMORY;
2449 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2450 if (tmp_streams[*pnum_streams].name == NULL) {
2451 return NT_STATUS_NO_MEMORY;
2453 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2454 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2456 *pnum_streams += 1;
2457 *pstreams = tmp_streams;
2458 done:
2459 return NT_STATUS_OK;
2462 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2463 const char *path,
2464 const char *name,
2465 TALLOC_CTX *mem_ctx,
2466 char **found_name)
2469 * Don't fall back to get_real_filename so callers can differentiate
2470 * between a full directory scan and an actual case-insensitive stat.
2472 errno = EOPNOTSUPP;
2473 return -1;
2476 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2477 const char *fname)
2479 return handle->conn->connectpath;
2482 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2483 struct byte_range_lock *br_lck,
2484 struct lock_struct *plock,
2485 bool blocking_lock)
2487 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2489 /* Note: blr is not used in the default implementation. */
2490 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2493 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2494 struct messaging_context *msg_ctx,
2495 struct byte_range_lock *br_lck,
2496 const struct lock_struct *plock)
2498 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2500 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2503 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2504 struct byte_range_lock *br_lck,
2505 struct lock_struct *plock)
2507 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2509 /* Note: blr is not used in the default implementation. */
2510 return brl_lock_cancel_default(br_lck, plock);
2513 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2514 files_struct *fsp,
2515 struct lock_struct *plock)
2517 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2518 plock->lock_type == WRITE_LOCK);
2520 return strict_lock_default(fsp, plock);
2523 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2524 files_struct *fsp,
2525 struct lock_struct *plock)
2527 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2528 plock->lock_type == WRITE_LOCK);
2530 strict_unlock_default(fsp, plock);
2533 /* NT ACL operations. */
2535 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2536 files_struct *fsp,
2537 uint32_t security_info,
2538 TALLOC_CTX *mem_ctx,
2539 struct security_descriptor **ppdesc)
2541 NTSTATUS result;
2543 START_PROFILE(fget_nt_acl);
2544 result = posix_fget_nt_acl(fsp, security_info,
2545 mem_ctx, ppdesc);
2546 END_PROFILE(fget_nt_acl);
2547 return result;
2550 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2551 const struct smb_filename *smb_fname,
2552 uint32_t security_info,
2553 TALLOC_CTX *mem_ctx,
2554 struct security_descriptor **ppdesc)
2556 NTSTATUS result;
2558 START_PROFILE(get_nt_acl);
2559 result = posix_get_nt_acl(handle->conn,
2560 smb_fname,
2561 security_info,
2562 mem_ctx,
2563 ppdesc);
2564 END_PROFILE(get_nt_acl);
2565 return result;
2568 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2570 NTSTATUS result;
2572 START_PROFILE(fset_nt_acl);
2573 result = set_nt_acl(fsp, security_info_sent, psd);
2574 END_PROFILE(fset_nt_acl);
2575 return result;
2578 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2579 struct smb_filename *file,
2580 struct security_acl *sacl,
2581 uint32_t access_requested,
2582 uint32_t access_denied)
2584 return NT_STATUS_OK; /* Nothing to do here ... */
2587 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2588 const struct smb_filename *smb_fname,
2589 mode_t mode)
2591 #ifdef HAVE_NO_ACL
2592 errno = ENOSYS;
2593 return -1;
2594 #else
2595 int result;
2597 START_PROFILE(chmod_acl);
2598 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2599 END_PROFILE(chmod_acl);
2600 return result;
2601 #endif
2604 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2606 #ifdef HAVE_NO_ACL
2607 errno = ENOSYS;
2608 return -1;
2609 #else
2610 int result;
2612 START_PROFILE(fchmod_acl);
2613 result = fchmod_acl(fsp, mode);
2614 END_PROFILE(fchmod_acl);
2615 return result;
2616 #endif
2619 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2620 const char *path_p,
2621 SMB_ACL_TYPE_T type,
2622 TALLOC_CTX *mem_ctx)
2624 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2627 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2628 files_struct *fsp,
2629 TALLOC_CTX *mem_ctx)
2631 return sys_acl_get_fd(handle, fsp, mem_ctx);
2634 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2636 return sys_acl_set_file(handle, name, acltype, theacl);
2639 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2641 return sys_acl_set_fd(handle, fsp, theacl);
2644 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2646 return sys_acl_delete_def_file(handle, path);
2649 /****************************************************************
2650 Extended attribute operations.
2651 *****************************************************************/
2653 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2655 return getxattr(path, name, value, size);
2658 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2660 return fgetxattr(fsp->fh->fd, name, value, size);
2663 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2665 return listxattr(path, list, size);
2668 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2670 return flistxattr(fsp->fh->fd, list, size);
2673 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2675 return removexattr(path, name);
2678 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2680 return fremovexattr(fsp->fh->fd, name);
2683 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2685 return setxattr(path, name, value, size, flags);
2688 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2690 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2693 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2695 return false;
2698 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2699 const struct smb_filename *fname,
2700 SMB_STRUCT_STAT *sbuf)
2702 NTSTATUS status;
2703 char *path;
2704 bool offline = false;
2706 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2707 return false;
2710 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2711 #if defined(ENOTSUP)
2712 errno = ENOTSUP;
2713 #endif
2714 return false;
2717 status = get_full_smb_filename(talloc_tos(), fname, &path);
2718 if (!NT_STATUS_IS_OK(status)) {
2719 errno = map_errno_from_nt_status(status);
2720 return false;
2723 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2725 TALLOC_FREE(path);
2727 return offline;
2730 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2731 struct files_struct *fsp,
2732 TALLOC_CTX *mem_ctx,
2733 DATA_BLOB *cookie)
2735 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2738 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2739 struct files_struct *fsp,
2740 const DATA_BLOB old_cookie,
2741 TALLOC_CTX *mem_ctx,
2742 DATA_BLOB *new_cookie)
2744 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2745 new_cookie);
2748 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2749 struct smb_request *smb1req,
2750 struct smbXsrv_open *op,
2751 const DATA_BLOB old_cookie,
2752 TALLOC_CTX *mem_ctx,
2753 struct files_struct **fsp,
2754 DATA_BLOB *new_cookie)
2756 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2757 old_cookie, mem_ctx,
2758 fsp, new_cookie);
2761 static struct vfs_fn_pointers vfs_default_fns = {
2762 /* Disk operations */
2764 .connect_fn = vfswrap_connect,
2765 .disconnect_fn = vfswrap_disconnect,
2766 .disk_free_fn = vfswrap_disk_free,
2767 .get_quota_fn = vfswrap_get_quota,
2768 .set_quota_fn = vfswrap_set_quota,
2769 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2770 .statvfs_fn = vfswrap_statvfs,
2771 .fs_capabilities_fn = vfswrap_fs_capabilities,
2772 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2773 .snap_check_path_fn = vfswrap_snap_check_path,
2774 .snap_create_fn = vfswrap_snap_create,
2775 .snap_delete_fn = vfswrap_snap_delete,
2777 /* Directory operations */
2779 .opendir_fn = vfswrap_opendir,
2780 .fdopendir_fn = vfswrap_fdopendir,
2781 .readdir_fn = vfswrap_readdir,
2782 .readdir_attr_fn = vfswrap_readdir_attr,
2783 .seekdir_fn = vfswrap_seekdir,
2784 .telldir_fn = vfswrap_telldir,
2785 .rewind_dir_fn = vfswrap_rewinddir,
2786 .mkdir_fn = vfswrap_mkdir,
2787 .rmdir_fn = vfswrap_rmdir,
2788 .closedir_fn = vfswrap_closedir,
2789 .init_search_op_fn = vfswrap_init_search_op,
2791 /* File operations */
2793 .open_fn = vfswrap_open,
2794 .create_file_fn = vfswrap_create_file,
2795 .close_fn = vfswrap_close,
2796 .read_fn = vfswrap_read,
2797 .pread_fn = vfswrap_pread,
2798 .pread_send_fn = vfswrap_pread_send,
2799 .pread_recv_fn = vfswrap_pread_recv,
2800 .write_fn = vfswrap_write,
2801 .pwrite_fn = vfswrap_pwrite,
2802 .pwrite_send_fn = vfswrap_pwrite_send,
2803 .pwrite_recv_fn = vfswrap_pwrite_recv,
2804 .lseek_fn = vfswrap_lseek,
2805 .sendfile_fn = vfswrap_sendfile,
2806 .recvfile_fn = vfswrap_recvfile,
2807 .rename_fn = vfswrap_rename,
2808 .fsync_fn = vfswrap_fsync,
2809 .fsync_send_fn = vfswrap_fsync_send,
2810 .fsync_recv_fn = vfswrap_fsync_recv,
2811 .stat_fn = vfswrap_stat,
2812 .fstat_fn = vfswrap_fstat,
2813 .lstat_fn = vfswrap_lstat,
2814 .get_alloc_size_fn = vfswrap_get_alloc_size,
2815 .unlink_fn = vfswrap_unlink,
2816 .chmod_fn = vfswrap_chmod,
2817 .fchmod_fn = vfswrap_fchmod,
2818 .chown_fn = vfswrap_chown,
2819 .fchown_fn = vfswrap_fchown,
2820 .lchown_fn = vfswrap_lchown,
2821 .chdir_fn = vfswrap_chdir,
2822 .getwd_fn = vfswrap_getwd,
2823 .ntimes_fn = vfswrap_ntimes,
2824 .ftruncate_fn = vfswrap_ftruncate,
2825 .fallocate_fn = vfswrap_fallocate,
2826 .lock_fn = vfswrap_lock,
2827 .kernel_flock_fn = vfswrap_kernel_flock,
2828 .linux_setlease_fn = vfswrap_linux_setlease,
2829 .getlock_fn = vfswrap_getlock,
2830 .symlink_fn = vfswrap_symlink,
2831 .readlink_fn = vfswrap_readlink,
2832 .link_fn = vfswrap_link,
2833 .mknod_fn = vfswrap_mknod,
2834 .realpath_fn = vfswrap_realpath,
2835 .chflags_fn = vfswrap_chflags,
2836 .file_id_create_fn = vfswrap_file_id_create,
2837 .streaminfo_fn = vfswrap_streaminfo,
2838 .get_real_filename_fn = vfswrap_get_real_filename,
2839 .connectpath_fn = vfswrap_connectpath,
2840 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2841 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2842 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2843 .strict_lock_fn = vfswrap_strict_lock,
2844 .strict_unlock_fn = vfswrap_strict_unlock,
2845 .translate_name_fn = vfswrap_translate_name,
2846 .fsctl_fn = vfswrap_fsctl,
2847 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2848 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2849 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2850 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2851 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2852 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2853 .get_compression_fn = vfswrap_get_compression,
2854 .set_compression_fn = vfswrap_set_compression,
2856 /* NT ACL operations. */
2858 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2859 .get_nt_acl_fn = vfswrap_get_nt_acl,
2860 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2861 .audit_file_fn = vfswrap_audit_file,
2863 /* POSIX ACL operations. */
2865 .chmod_acl_fn = vfswrap_chmod_acl,
2866 .fchmod_acl_fn = vfswrap_fchmod_acl,
2868 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2869 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2870 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2871 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2872 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2873 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2874 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2876 /* EA operations. */
2877 .getxattr_fn = vfswrap_getxattr,
2878 .fgetxattr_fn = vfswrap_fgetxattr,
2879 .listxattr_fn = vfswrap_listxattr,
2880 .flistxattr_fn = vfswrap_flistxattr,
2881 .removexattr_fn = vfswrap_removexattr,
2882 .fremovexattr_fn = vfswrap_fremovexattr,
2883 .setxattr_fn = vfswrap_setxattr,
2884 .fsetxattr_fn = vfswrap_fsetxattr,
2886 /* aio operations */
2887 .aio_force_fn = vfswrap_aio_force,
2889 /* durable handle operations */
2890 .durable_cookie_fn = vfswrap_durable_cookie,
2891 .durable_disconnect_fn = vfswrap_durable_disconnect,
2892 .durable_reconnect_fn = vfswrap_durable_reconnect,
2895 NTSTATUS vfs_default_init(void);
2896 NTSTATUS vfs_default_init(void)
2898 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2899 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);