vfs: Convert vfswrap_fs_capabilities to synthetic_smb_fname
[Samba/bjacke.git] / source3 / modules / vfs_default.c
blob8804e623acf8fc01e41481297ed1cfb8898ec642
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 /* Default Posix readdir() does not give us stat info.
380 * Set to invalid to indicate we didn't return this info. */
381 if (sbuf)
382 SET_STAT_INVALID(*sbuf);
383 END_PROFILE(syscall_readdir);
384 return result;
387 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
389 START_PROFILE(syscall_seekdir);
390 seekdir(dirp, offset);
391 END_PROFILE(syscall_seekdir);
394 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
396 long result;
397 START_PROFILE(syscall_telldir);
398 result = telldir(dirp);
399 END_PROFILE(syscall_telldir);
400 return result;
403 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
405 START_PROFILE(syscall_rewinddir);
406 rewinddir(dirp);
407 END_PROFILE(syscall_rewinddir);
410 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
412 int result;
413 bool has_dacl = False;
414 char *parent = NULL;
416 START_PROFILE(syscall_mkdir);
418 if (lp_inherit_acls(SNUM(handle->conn))
419 && parent_dirname(talloc_tos(), path, &parent, NULL)
420 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
421 mode = (0777 & lp_dir_mask(SNUM(handle->conn)));
423 TALLOC_FREE(parent);
425 result = mkdir(path, mode);
427 if (result == 0 && !has_dacl) {
429 * We need to do this as the default behavior of POSIX ACLs
430 * is to set the mask to be the requested group permission
431 * bits, not the group permission bits to be the requested
432 * group permission bits. This is not what we want, as it will
433 * mess up any inherited ACL bits that were set. JRA.
435 int saved_errno = errno; /* We may get ENOSYS */
436 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
437 errno = saved_errno;
440 END_PROFILE(syscall_mkdir);
441 return result;
444 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
446 int result;
448 START_PROFILE(syscall_rmdir);
449 result = rmdir(path);
450 END_PROFILE(syscall_rmdir);
451 return result;
454 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
456 int result;
458 START_PROFILE(syscall_closedir);
459 result = closedir(dirp);
460 END_PROFILE(syscall_closedir);
461 return result;
464 static void vfswrap_init_search_op(vfs_handle_struct *handle,
465 DIR *dirp)
467 /* Default behavior is a NOOP */
470 /* File operations */
472 static int vfswrap_open(vfs_handle_struct *handle,
473 struct smb_filename *smb_fname,
474 files_struct *fsp, int flags, mode_t mode)
476 int result = -1;
478 START_PROFILE(syscall_open);
480 if (smb_fname->stream_name) {
481 errno = ENOENT;
482 goto out;
485 result = open(smb_fname->base_name, flags, mode);
486 out:
487 END_PROFILE(syscall_open);
488 return result;
491 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
492 struct smb_request *req,
493 uint16_t root_dir_fid,
494 struct smb_filename *smb_fname,
495 uint32_t access_mask,
496 uint32_t share_access,
497 uint32_t create_disposition,
498 uint32_t create_options,
499 uint32_t file_attributes,
500 uint32_t oplock_request,
501 uint64_t allocation_size,
502 uint32_t private_flags,
503 struct security_descriptor *sd,
504 struct ea_list *ea_list,
505 files_struct **result,
506 int *pinfo)
508 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
509 access_mask, share_access,
510 create_disposition, create_options,
511 file_attributes, oplock_request,
512 allocation_size, private_flags,
513 sd, ea_list, result,
514 pinfo);
517 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
519 int result;
521 START_PROFILE(syscall_close);
522 result = fd_close_posix(fsp);
523 END_PROFILE(syscall_close);
524 return result;
527 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
529 ssize_t result;
531 START_PROFILE_BYTES(syscall_read, n);
532 result = sys_read(fsp->fh->fd, data, n);
533 END_PROFILE(syscall_read);
534 return result;
537 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
538 size_t n, off_t offset)
540 ssize_t result;
542 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
543 START_PROFILE_BYTES(syscall_pread, n);
544 result = sys_pread(fsp->fh->fd, data, n, offset);
545 END_PROFILE(syscall_pread);
547 if (result == -1 && errno == ESPIPE) {
548 /* Maintain the fiction that pipes can be seeked (sought?) on. */
549 result = SMB_VFS_READ(fsp, data, n);
550 fsp->fh->pos = 0;
553 #else /* HAVE_PREAD */
554 off_t curr;
555 int lerrno;
557 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
558 if (curr == -1 && errno == ESPIPE) {
559 /* Maintain the fiction that pipes can be seeked (sought?) on. */
560 result = SMB_VFS_READ(fsp, data, n);
561 fsp->fh->pos = 0;
562 return result;
565 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
566 return -1;
569 errno = 0;
570 result = SMB_VFS_READ(fsp, data, n);
571 lerrno = errno;
573 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
574 errno = lerrno;
576 #endif /* HAVE_PREAD */
578 return result;
581 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
583 ssize_t result;
585 START_PROFILE_BYTES(syscall_write, n);
586 result = sys_write(fsp->fh->fd, data, n);
587 END_PROFILE(syscall_write);
588 return result;
591 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
592 size_t n, off_t offset)
594 ssize_t result;
596 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
597 START_PROFILE_BYTES(syscall_pwrite, n);
598 result = sys_pwrite(fsp->fh->fd, data, n, offset);
599 END_PROFILE(syscall_pwrite);
601 if (result == -1 && errno == ESPIPE) {
602 /* Maintain the fiction that pipes can be sought on. */
603 result = SMB_VFS_WRITE(fsp, data, n);
606 #else /* HAVE_PWRITE */
607 off_t curr;
608 int lerrno;
610 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
611 if (curr == -1) {
612 return -1;
615 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
616 return -1;
619 result = SMB_VFS_WRITE(fsp, data, n);
620 lerrno = errno;
622 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
623 errno = lerrno;
625 #endif /* HAVE_PWRITE */
627 return result;
630 static void vfswrap_asys_finished(struct tevent_context *ev,
631 struct tevent_fd *fde,
632 uint16_t flags, void *p);
634 static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
636 int ret;
637 int fd;
639 if (conn->asys_ctx != NULL) {
640 return true;
642 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
643 if (ret != 0) {
644 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
645 return false;
648 fd = asys_signalfd(conn->asys_ctx);
650 set_blocking(fd, false);
652 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
653 TEVENT_FD_READ,
654 vfswrap_asys_finished,
655 conn->asys_ctx);
656 if (conn->asys_fde == NULL) {
657 DEBUG(1, ("tevent_add_fd failed\n"));
658 asys_context_destroy(conn->asys_ctx);
659 conn->asys_ctx = NULL;
660 return false;
662 return true;
665 struct vfswrap_asys_state {
666 struct asys_context *asys_ctx;
667 struct tevent_req *req;
668 ssize_t ret;
669 int err;
672 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
674 asys_cancel(s->asys_ctx, s->req);
675 return 0;
678 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
679 TALLOC_CTX *mem_ctx,
680 struct tevent_context *ev,
681 struct files_struct *fsp,
682 void *data,
683 size_t n, off_t offset)
685 struct tevent_req *req;
686 struct vfswrap_asys_state *state;
687 int ret;
689 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
690 if (req == NULL) {
691 return NULL;
693 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
694 tevent_req_oom(req);
695 return tevent_req_post(req, ev);
697 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
698 state->req = req;
700 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
701 if (ret != 0) {
702 tevent_req_error(req, ret);
703 return tevent_req_post(req, ev);
705 talloc_set_destructor(state, vfswrap_asys_state_destructor);
707 return req;
710 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
711 TALLOC_CTX *mem_ctx,
712 struct tevent_context *ev,
713 struct files_struct *fsp,
714 const 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->conn)) {
726 tevent_req_oom(req);
727 return tevent_req_post(req, ev);
729 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
730 state->req = req;
732 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
733 if (ret != 0) {
734 tevent_req_error(req, ret);
735 return tevent_req_post(req, ev);
737 talloc_set_destructor(state, vfswrap_asys_state_destructor);
739 return req;
742 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
743 TALLOC_CTX *mem_ctx,
744 struct tevent_context *ev,
745 struct files_struct *fsp)
747 struct tevent_req *req;
748 struct vfswrap_asys_state *state;
749 int ret;
751 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
752 if (req == NULL) {
753 return NULL;
755 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
756 tevent_req_oom(req);
757 return tevent_req_post(req, ev);
759 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
760 state->req = req;
762 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
763 if (ret != 0) {
764 tevent_req_error(req, ret);
765 return tevent_req_post(req, ev);
767 talloc_set_destructor(state, vfswrap_asys_state_destructor);
769 return req;
772 static void vfswrap_asys_finished(struct tevent_context *ev,
773 struct tevent_fd *fde,
774 uint16_t flags, void *p)
776 struct asys_context *asys_ctx = (struct asys_context *)p;
777 struct tevent_req *req;
778 struct vfswrap_asys_state *state;
779 int res;
780 ssize_t ret;
781 int err;
782 void *private_data;
784 if ((flags & TEVENT_FD_READ) == 0) {
785 return;
788 while (true) {
789 res = asys_result(asys_ctx, &ret, &err, &private_data);
790 if (res == EINTR || res == EAGAIN) {
791 return;
793 #ifdef EWOULDBLOCK
794 if (res == EWOULDBLOCK) {
795 return;
797 #endif
799 if (res == ECANCELED) {
800 return;
803 if (res != 0) {
804 DEBUG(1, ("asys_result returned %s\n", strerror(res)));
805 return;
808 req = talloc_get_type_abort(private_data, struct tevent_req);
809 state = tevent_req_data(req, struct vfswrap_asys_state);
811 talloc_set_destructor(state, NULL);
813 state->ret = ret;
814 state->err = err;
815 tevent_req_defer_callback(req, ev);
816 tevent_req_done(req);
820 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
822 struct vfswrap_asys_state *state = tevent_req_data(
823 req, struct vfswrap_asys_state);
825 if (tevent_req_is_unix_error(req, err)) {
826 return -1;
828 *err = state->err;
829 return state->ret;
832 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
834 struct vfswrap_asys_state *state = tevent_req_data(
835 req, struct vfswrap_asys_state);
837 if (tevent_req_is_unix_error(req, err)) {
838 return -1;
840 *err = state->err;
841 return state->ret;
844 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
846 off_t result = 0;
848 START_PROFILE(syscall_lseek);
850 /* Cope with 'stat' file opens. */
851 if (fsp->fh->fd != -1)
852 result = lseek(fsp->fh->fd, offset, whence);
855 * We want to maintain the fiction that we can seek
856 * on a fifo for file system purposes. This allows
857 * people to set up UNIX fifo's that feed data to Windows
858 * applications. JRA.
861 if((result == -1) && (errno == ESPIPE)) {
862 result = 0;
863 errno = 0;
866 END_PROFILE(syscall_lseek);
867 return result;
870 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
871 off_t offset, size_t n)
873 ssize_t result;
875 START_PROFILE_BYTES(syscall_sendfile, n);
876 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
877 END_PROFILE(syscall_sendfile);
878 return result;
881 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
882 int fromfd,
883 files_struct *tofsp,
884 off_t offset,
885 size_t n)
887 ssize_t result;
889 START_PROFILE_BYTES(syscall_recvfile, n);
890 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
891 END_PROFILE(syscall_recvfile);
892 return result;
895 static int vfswrap_rename(vfs_handle_struct *handle,
896 const struct smb_filename *smb_fname_src,
897 const struct smb_filename *smb_fname_dst)
899 int result = -1;
901 START_PROFILE(syscall_rename);
903 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
904 errno = ENOENT;
905 goto out;
908 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
910 out:
911 END_PROFILE(syscall_rename);
912 return result;
915 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
917 #ifdef HAVE_FSYNC
918 int result;
920 START_PROFILE(syscall_fsync);
921 result = fsync(fsp->fh->fd);
922 END_PROFILE(syscall_fsync);
923 return result;
924 #else
925 return 0;
926 #endif
929 static int vfswrap_stat(vfs_handle_struct *handle,
930 struct smb_filename *smb_fname)
932 int result = -1;
934 START_PROFILE(syscall_stat);
936 if (smb_fname->stream_name) {
937 errno = ENOENT;
938 goto out;
941 result = sys_stat(smb_fname->base_name, &smb_fname->st,
942 lp_fake_dir_create_times(SNUM(handle->conn)));
943 out:
944 END_PROFILE(syscall_stat);
945 return result;
948 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
950 int result;
952 START_PROFILE(syscall_fstat);
953 result = sys_fstat(fsp->fh->fd,
954 sbuf, lp_fake_dir_create_times(SNUM(handle->conn)));
955 END_PROFILE(syscall_fstat);
956 return result;
959 static int vfswrap_lstat(vfs_handle_struct *handle,
960 struct smb_filename *smb_fname)
962 int result = -1;
964 START_PROFILE(syscall_lstat);
966 if (smb_fname->stream_name) {
967 errno = ENOENT;
968 goto out;
971 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
972 lp_fake_dir_create_times(SNUM(handle->conn)));
973 out:
974 END_PROFILE(syscall_lstat);
975 return result;
978 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
979 const char *name,
980 enum vfs_translate_direction direction,
981 TALLOC_CTX *mem_ctx,
982 char **mapped_name)
984 return NT_STATUS_NONE_MAPPED;
988 * Implement the default fsctl operation.
990 static bool vfswrap_logged_ioctl_message = false;
992 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
993 struct files_struct *fsp,
994 TALLOC_CTX *ctx,
995 uint32_t function,
996 uint16_t req_flags, /* Needed for UNICODE ... */
997 const uint8_t *_in_data,
998 uint32_t in_len,
999 uint8_t **_out_data,
1000 uint32_t max_out_len,
1001 uint32_t *out_len)
1003 const char *in_data = (const char *)_in_data;
1004 char **out_data = (char **)_out_data;
1006 switch (function) {
1007 case FSCTL_SET_SPARSE:
1009 bool set_sparse = true;
1010 NTSTATUS status;
1012 if (in_len >= 1 && in_data[0] == 0) {
1013 set_sparse = false;
1016 status = file_set_sparse(handle->conn, fsp, set_sparse);
1018 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1019 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1020 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1021 nt_errstr(status)));
1023 return status;
1026 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1028 unsigned char objid[16];
1029 char *return_data = NULL;
1031 /* This should return the object-id on this file.
1032 * I think I'll make this be the inode+dev. JRA.
1035 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1036 fsp_fnum_dbg(fsp)));
1038 *out_len = (max_out_len >= 64) ? 64 : max_out_len;
1039 /* Hmmm, will this cause problems if less data asked for? */
1040 return_data = talloc_array(ctx, char, 64);
1041 if (return_data == NULL) {
1042 return NT_STATUS_NO_MEMORY;
1045 /* For backwards compatibility only store the dev/inode. */
1046 push_file_id_16(return_data, &fsp->file_id);
1047 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1048 push_file_id_16(return_data+32, &fsp->file_id);
1049 *out_data = return_data;
1050 return NT_STATUS_OK;
1053 case FSCTL_GET_REPARSE_POINT:
1055 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1056 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1057 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1058 return NT_STATUS_NOT_A_REPARSE_POINT;
1061 case FSCTL_SET_REPARSE_POINT:
1063 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1064 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1065 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1066 return NT_STATUS_NOT_A_REPARSE_POINT;
1069 case FSCTL_GET_SHADOW_COPY_DATA:
1072 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1073 * and return their volume names. If max_data_count is 16, then it is just
1074 * asking for the number of volumes and length of the combined names.
1076 * pdata is the data allocated by our caller, but that uses
1077 * total_data_count (which is 0 in our case) rather than max_data_count.
1078 * Allocate the correct amount and return the pointer to let
1079 * it be deallocated when we return.
1081 struct shadow_copy_data *shadow_data = NULL;
1082 bool labels = False;
1083 uint32 labels_data_count = 0;
1084 uint32 i;
1085 char *cur_pdata = NULL;
1087 if (max_out_len < 16) {
1088 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1089 max_out_len));
1090 return NT_STATUS_INVALID_PARAMETER;
1093 if (max_out_len > 16) {
1094 labels = True;
1097 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1098 if (shadow_data == NULL) {
1099 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1100 return NT_STATUS_NO_MEMORY;
1104 * Call the VFS routine to actually do the work.
1106 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1107 TALLOC_FREE(shadow_data);
1108 if (errno == ENOSYS) {
1109 DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n",
1110 fsp->conn->connectpath));
1111 return NT_STATUS_NOT_SUPPORTED;
1112 } else {
1113 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n",
1114 fsp->conn->connectpath));
1115 return NT_STATUS_UNSUCCESSFUL;
1119 labels_data_count = (shadow_data->num_volumes * 2 *
1120 sizeof(SHADOW_COPY_LABEL)) + 2;
1122 if (!labels) {
1123 *out_len = 16;
1124 } else {
1125 *out_len = 12 + labels_data_count + 4;
1128 if (max_out_len < *out_len) {
1129 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1130 max_out_len, *out_len));
1131 TALLOC_FREE(shadow_data);
1132 return NT_STATUS_BUFFER_TOO_SMALL;
1135 cur_pdata = talloc_array(ctx, char, *out_len);
1136 if (cur_pdata == NULL) {
1137 TALLOC_FREE(shadow_data);
1138 return NT_STATUS_NO_MEMORY;
1141 *out_data = cur_pdata;
1143 /* num_volumes 4 bytes */
1144 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1146 if (labels) {
1147 /* num_labels 4 bytes */
1148 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1151 /* needed_data_count 4 bytes */
1152 SIVAL(cur_pdata, 8, labels_data_count + 4);
1154 cur_pdata += 12;
1156 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1157 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1158 if (labels && shadow_data->labels) {
1159 for (i=0; i<shadow_data->num_volumes; i++) {
1160 srvstr_push(cur_pdata, req_flags,
1161 cur_pdata, shadow_data->labels[i],
1162 2 * sizeof(SHADOW_COPY_LABEL),
1163 STR_UNICODE|STR_TERMINATE);
1164 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1165 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1169 TALLOC_FREE(shadow_data);
1171 return NT_STATUS_OK;
1174 case FSCTL_FIND_FILES_BY_SID:
1176 /* pretend this succeeded -
1178 * we have to send back a list with all files owned by this SID
1180 * but I have to check that --metze
1182 struct dom_sid sid;
1183 uid_t uid;
1184 size_t sid_len;
1186 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1187 fsp_fnum_dbg(fsp)));
1189 if (in_len < 8) {
1190 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1191 return NT_STATUS_INVALID_PARAMETER;
1194 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1196 /* unknown 4 bytes: this is not the length of the sid :-( */
1197 /*unknown = IVAL(pdata,0);*/
1199 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1200 return NT_STATUS_INVALID_PARAMETER;
1202 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1204 if (!sid_to_uid(&sid, &uid)) {
1205 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1206 sid_string_dbg(&sid),
1207 (unsigned long)sid_len));
1208 uid = (-1);
1211 /* we can take a look at the find source :-)
1213 * find ./ -uid $uid -name '*' is what we need here
1216 * and send 4bytes len and then NULL terminated unicode strings
1217 * for each file
1219 * but I don't know how to deal with the paged results
1220 * (maybe we can hang the result anywhere in the fsp struct)
1222 * but I don't know how to deal with the paged results
1223 * (maybe we can hang the result anywhere in the fsp struct)
1225 * we don't send all files at once
1226 * and at the next we should *not* start from the beginning,
1227 * so we have to cache the result
1229 * --metze
1232 /* this works for now... */
1233 return NT_STATUS_OK;
1236 case FSCTL_QUERY_ALLOCATED_RANGES:
1238 /* FIXME: This is just a dummy reply, telling that all of the
1239 * file is allocated. MKS cp needs that.
1240 * Adding the real allocated ranges via FIEMAP on Linux
1241 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1242 * this FSCTL correct for sparse files.
1244 NTSTATUS status;
1245 uint64_t offset, length;
1246 char *out_data_tmp = NULL;
1248 if (in_len != 16) {
1249 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1250 in_len));
1251 return NT_STATUS_INVALID_PARAMETER;
1254 if (max_out_len < 16) {
1255 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1256 max_out_len));
1257 return NT_STATUS_INVALID_PARAMETER;
1260 offset = BVAL(in_data,0);
1261 length = BVAL(in_data,8);
1263 if (offset + length < offset) {
1264 /* No 64-bit integer wrap. */
1265 return NT_STATUS_INVALID_PARAMETER;
1268 /* Shouldn't this be SMB_VFS_STAT ... ? */
1269 status = vfs_stat_fsp(fsp);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 return status;
1274 *out_len = 16;
1275 out_data_tmp = talloc_array(ctx, char, *out_len);
1276 if (out_data_tmp == NULL) {
1277 DEBUG(10, ("unable to allocate memory for response\n"));
1278 return NT_STATUS_NO_MEMORY;
1281 if (offset > fsp->fsp_name->st.st_ex_size ||
1282 fsp->fsp_name->st.st_ex_size == 0 ||
1283 length == 0) {
1284 memset(out_data_tmp, 0, *out_len);
1285 } else {
1286 uint64_t end = offset + length;
1287 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1288 SBVAL(out_data_tmp, 0, 0);
1289 SBVAL(out_data_tmp, 8, end);
1292 *out_data = out_data_tmp;
1294 return NT_STATUS_OK;
1297 case FSCTL_IS_VOLUME_DIRTY:
1299 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1300 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1302 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1303 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1305 return NT_STATUS_INVALID_PARAMETER;
1308 default:
1310 * Only print once ... unfortunately there could be lots of
1311 * different FSCTLs that are called.
1313 if (!vfswrap_logged_ioctl_message) {
1314 vfswrap_logged_ioctl_message = true;
1315 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1316 __func__, function));
1320 return NT_STATUS_NOT_SUPPORTED;
1323 struct vfs_cc_state {
1324 off_t copied;
1325 uint8_t buf[65536];
1328 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1329 TALLOC_CTX *mem_ctx,
1330 struct tevent_context *ev,
1331 struct files_struct *src_fsp,
1332 off_t src_off,
1333 struct files_struct *dest_fsp,
1334 off_t dest_off,
1335 off_t num)
1337 struct tevent_req *req;
1338 struct vfs_cc_state *vfs_cc_state;
1339 NTSTATUS status;
1341 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1342 (unsigned long)num));
1344 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1345 if (req == NULL) {
1346 return NULL;
1349 status = vfs_stat_fsp(src_fsp);
1350 if (tevent_req_nterror(req, status)) {
1351 return tevent_req_post(req, ev);
1354 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1356 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1357 * If the SourceOffset or SourceOffset + Length extends beyond
1358 * the end of file, the server SHOULD<240> treat this as a
1359 * STATUS_END_OF_FILE error.
1360 * ...
1361 * <240> Section 3.3.5.15.6: Windows servers will return
1362 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1364 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1365 return tevent_req_post(req, ev);
1368 /* could use 2.6.33+ sendfile here to do this in kernel */
1369 while (vfs_cc_state->copied < num) {
1370 ssize_t ret;
1371 struct lock_struct lck;
1372 int saved_errno;
1374 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1375 num - vfs_cc_state->copied);
1377 init_strict_lock_struct(src_fsp,
1378 src_fsp->op->global->open_persistent_id,
1379 src_off,
1380 this_num,
1381 READ_LOCK,
1382 &lck);
1384 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1385 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1386 return tevent_req_post(req, ev);
1389 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1390 this_num, src_off);
1391 if (ret == -1) {
1392 saved_errno = errno;
1395 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1397 if (ret == -1) {
1398 errno = saved_errno;
1399 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1400 return tevent_req_post(req, ev);
1402 if (ret != this_num) {
1403 /* zero tolerance for short reads */
1404 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1405 return tevent_req_post(req, ev);
1408 src_off += ret;
1410 init_strict_lock_struct(dest_fsp,
1411 dest_fsp->op->global->open_persistent_id,
1412 dest_off,
1413 this_num,
1414 WRITE_LOCK,
1415 &lck);
1417 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1418 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1419 return tevent_req_post(req, ev);
1422 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1423 this_num, dest_off);
1424 if (ret == -1) {
1425 saved_errno = errno;
1428 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1430 if (ret == -1) {
1431 errno = saved_errno;
1432 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1433 return tevent_req_post(req, ev);
1435 if (ret != this_num) {
1436 /* zero tolerance for short writes */
1437 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1438 return tevent_req_post(req, ev);
1440 dest_off += ret;
1442 vfs_cc_state->copied += this_num;
1445 tevent_req_done(req);
1446 return tevent_req_post(req, ev);
1449 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1450 struct tevent_req *req,
1451 off_t *copied)
1453 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1454 struct vfs_cc_state);
1455 NTSTATUS status;
1457 if (tevent_req_is_nterror(req, &status)) {
1458 DEBUG(2, ("server side copy chunk failed: %s\n",
1459 nt_errstr(status)));
1460 *copied = 0;
1461 tevent_req_received(req);
1462 return status;
1465 *copied = vfs_cc_state->copied;
1466 DEBUG(10, ("server side copy chunk copied %lu\n",
1467 (unsigned long)*copied));
1468 tevent_req_received(req);
1470 return NT_STATUS_OK;
1473 /********************************************************************
1474 Given a stat buffer return the allocated size on disk, taking into
1475 account sparse files.
1476 ********************************************************************/
1477 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1478 struct files_struct *fsp,
1479 const SMB_STRUCT_STAT *sbuf)
1481 uint64_t result;
1483 START_PROFILE(syscall_get_alloc_size);
1485 if(S_ISDIR(sbuf->st_ex_mode)) {
1486 result = 0;
1487 goto out;
1490 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1491 /* The type of st_blocksize is blkcnt_t which *MUST* be
1492 signed (according to POSIX) and can be less than 64-bits.
1493 Ensure when we're converting to 64 bits wide we don't
1494 sign extend. */
1495 #if defined(SIZEOF_BLKCNT_T_8)
1496 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1497 #elif defined(SIZEOF_BLKCNT_T_4)
1499 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1500 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1502 #else
1503 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1504 #endif
1505 #else
1506 result = get_file_size_stat(sbuf);
1507 #endif
1509 if (fsp && fsp->initial_allocation_size)
1510 result = MAX(result,fsp->initial_allocation_size);
1512 result = smb_roundup(handle->conn, result);
1514 out:
1515 END_PROFILE(syscall_get_alloc_size);
1516 return result;
1519 static int vfswrap_unlink(vfs_handle_struct *handle,
1520 const struct smb_filename *smb_fname)
1522 int result = -1;
1524 START_PROFILE(syscall_unlink);
1526 if (smb_fname->stream_name) {
1527 errno = ENOENT;
1528 goto out;
1530 result = unlink(smb_fname->base_name);
1532 out:
1533 END_PROFILE(syscall_unlink);
1534 return result;
1537 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1539 int result;
1541 START_PROFILE(syscall_chmod);
1544 * We need to do this due to the fact that the default POSIX ACL
1545 * chmod modifies the ACL *mask* for the group owner, not the
1546 * group owner bits directly. JRA.
1551 int saved_errno = errno; /* We might get ENOSYS */
1552 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1553 END_PROFILE(syscall_chmod);
1554 return result;
1556 /* Error - return the old errno. */
1557 errno = saved_errno;
1560 result = chmod(path, mode);
1561 END_PROFILE(syscall_chmod);
1562 return result;
1565 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1567 int result;
1569 START_PROFILE(syscall_fchmod);
1572 * We need to do this due to the fact that the default POSIX ACL
1573 * chmod modifies the ACL *mask* for the group owner, not the
1574 * group owner bits directly. JRA.
1578 int saved_errno = errno; /* We might get ENOSYS */
1579 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1580 END_PROFILE(syscall_fchmod);
1581 return result;
1583 /* Error - return the old errno. */
1584 errno = saved_errno;
1587 #if defined(HAVE_FCHMOD)
1588 result = fchmod(fsp->fh->fd, mode);
1589 #else
1590 result = -1;
1591 errno = ENOSYS;
1592 #endif
1594 END_PROFILE(syscall_fchmod);
1595 return result;
1598 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1600 int result;
1602 START_PROFILE(syscall_chown);
1603 result = chown(path, uid, gid);
1604 END_PROFILE(syscall_chown);
1605 return result;
1608 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1610 #ifdef HAVE_FCHOWN
1611 int result;
1613 START_PROFILE(syscall_fchown);
1614 result = fchown(fsp->fh->fd, uid, gid);
1615 END_PROFILE(syscall_fchown);
1616 return result;
1617 #else
1618 errno = ENOSYS;
1619 return -1;
1620 #endif
1623 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1625 int result;
1627 START_PROFILE(syscall_lchown);
1628 result = lchown(path, uid, gid);
1629 END_PROFILE(syscall_lchown);
1630 return result;
1633 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1635 int result;
1637 START_PROFILE(syscall_chdir);
1638 result = chdir(path);
1639 END_PROFILE(syscall_chdir);
1640 return result;
1643 static char *vfswrap_getwd(vfs_handle_struct *handle)
1645 char *result;
1647 START_PROFILE(syscall_getwd);
1648 result = sys_getwd();
1649 END_PROFILE(syscall_getwd);
1650 return result;
1653 /*********************************************************************
1654 nsec timestamp resolution call. Convert down to whatever the underlying
1655 system will support.
1656 **********************************************************************/
1658 static int vfswrap_ntimes(vfs_handle_struct *handle,
1659 const struct smb_filename *smb_fname,
1660 struct smb_file_time *ft)
1662 int result = -1;
1664 START_PROFILE(syscall_ntimes);
1666 if (smb_fname->stream_name) {
1667 errno = ENOENT;
1668 goto out;
1671 if (ft != NULL) {
1672 if (null_timespec(ft->atime)) {
1673 ft->atime= smb_fname->st.st_ex_atime;
1676 if (null_timespec(ft->mtime)) {
1677 ft->mtime = smb_fname->st.st_ex_mtime;
1680 if (!null_timespec(ft->create_time)) {
1681 set_create_timespec_ea(handle->conn,
1682 smb_fname,
1683 ft->create_time);
1686 if ((timespec_compare(&ft->atime,
1687 &smb_fname->st.st_ex_atime) == 0) &&
1688 (timespec_compare(&ft->mtime,
1689 &smb_fname->st.st_ex_mtime) == 0)) {
1690 return 0;
1694 #if defined(HAVE_UTIMENSAT)
1695 if (ft != NULL) {
1696 struct timespec ts[2];
1697 ts[0] = ft->atime;
1698 ts[1] = ft->mtime;
1699 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1700 } else {
1701 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1703 if (!((result == -1) && (errno == ENOSYS))) {
1704 goto out;
1706 #endif
1707 #if defined(HAVE_UTIMES)
1708 if (ft != NULL) {
1709 struct timeval tv[2];
1710 tv[0] = convert_timespec_to_timeval(ft->atime);
1711 tv[1] = convert_timespec_to_timeval(ft->mtime);
1712 result = utimes(smb_fname->base_name, tv);
1713 } else {
1714 result = utimes(smb_fname->base_name, NULL);
1716 if (!((result == -1) && (errno == ENOSYS))) {
1717 goto out;
1719 #endif
1720 #if defined(HAVE_UTIME)
1721 if (ft != NULL) {
1722 struct utimbuf times;
1723 times.actime = convert_timespec_to_time_t(ft->atime);
1724 times.modtime = convert_timespec_to_time_t(ft->mtime);
1725 result = utime(smb_fname->base_name, &times);
1726 } else {
1727 result = utime(smb_fname->base_name, NULL);
1729 if (!((result == -1) && (errno == ENOSYS))) {
1730 goto out;
1732 #endif
1733 errno = ENOSYS;
1734 result = -1;
1736 out:
1737 END_PROFILE(syscall_ntimes);
1738 return result;
1741 /*********************************************************************
1742 A version of ftruncate that will write the space on disk if strict
1743 allocate is set.
1744 **********************************************************************/
1746 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1748 off_t space_to_write;
1749 uint64_t space_avail;
1750 uint64_t bsize,dfree,dsize;
1751 int ret;
1752 NTSTATUS status;
1753 SMB_STRUCT_STAT *pst;
1755 status = vfs_stat_fsp(fsp);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 return -1;
1759 pst = &fsp->fsp_name->st;
1761 #ifdef S_ISFIFO
1762 if (S_ISFIFO(pst->st_ex_mode))
1763 return 0;
1764 #endif
1766 if (pst->st_ex_size == len)
1767 return 0;
1769 /* Shrink - just ftruncate. */
1770 if (pst->st_ex_size > len)
1771 return ftruncate(fsp->fh->fd, len);
1773 space_to_write = len - pst->st_ex_size;
1775 /* for allocation try fallocate first. This can fail on some
1776 platforms e.g. when the filesystem doesn't support it and no
1777 emulation is being done by the libc (like on AIX with JFS1). In that
1778 case we do our own emulation. fallocate implementations can
1779 return ENOTSUP or EINVAL in cases like that. */
1780 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1781 pst->st_ex_size, space_to_write);
1782 if (ret == ENOSPC) {
1783 errno = ENOSPC;
1784 return -1;
1786 if (ret == 0) {
1787 return 0;
1789 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1790 "error %d. Falling back to slow manual allocation\n", ret));
1792 /* available disk space is enough or not? */
1793 space_avail = get_dfree_info(fsp->conn,
1794 fsp->fsp_name->base_name, false,
1795 &bsize,&dfree,&dsize);
1796 /* space_avail is 1k blocks */
1797 if (space_avail == (uint64_t)-1 ||
1798 ((uint64_t)space_to_write/1024 > space_avail) ) {
1799 errno = ENOSPC;
1800 return -1;
1803 /* Write out the real space on disk. */
1804 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1805 if (ret != 0) {
1806 errno = ret;
1807 ret = -1;
1810 return 0;
1813 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1815 int result = -1;
1816 SMB_STRUCT_STAT *pst;
1817 NTSTATUS status;
1818 char c = 0;
1820 START_PROFILE(syscall_ftruncate);
1822 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1823 result = strict_allocate_ftruncate(handle, fsp, len);
1824 END_PROFILE(syscall_ftruncate);
1825 return result;
1828 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1829 ftruncate if the system supports it. Then I discovered that
1830 you can have some filesystems that support ftruncate
1831 expansion and some that don't! On Linux fat can't do
1832 ftruncate extend but ext2 can. */
1834 result = ftruncate(fsp->fh->fd, len);
1835 if (result == 0)
1836 goto done;
1838 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1839 extend a file with ftruncate. Provide alternate implementation
1840 for this */
1842 /* Do an fstat to see if the file is longer than the requested
1843 size in which case the ftruncate above should have
1844 succeeded or shorter, in which case seek to len - 1 and
1845 write 1 byte of zero */
1846 status = vfs_stat_fsp(fsp);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 goto done;
1850 pst = &fsp->fsp_name->st;
1852 #ifdef S_ISFIFO
1853 if (S_ISFIFO(pst->st_ex_mode)) {
1854 result = 0;
1855 goto done;
1857 #endif
1859 if (pst->st_ex_size == len) {
1860 result = 0;
1861 goto done;
1864 if (pst->st_ex_size > len) {
1865 /* the ftruncate should have worked */
1866 goto done;
1869 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1870 goto done;
1873 result = 0;
1875 done:
1877 END_PROFILE(syscall_ftruncate);
1878 return result;
1881 static int vfswrap_fallocate(vfs_handle_struct *handle,
1882 files_struct *fsp,
1883 enum vfs_fallocate_mode mode,
1884 off_t offset,
1885 off_t len)
1887 int result;
1889 START_PROFILE(syscall_fallocate);
1890 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1891 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1892 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1893 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1894 } else {
1895 errno = EINVAL;
1896 result = -1;
1898 END_PROFILE(syscall_fallocate);
1899 return result;
1902 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1904 bool result;
1906 START_PROFILE(syscall_fcntl_lock);
1907 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1908 END_PROFILE(syscall_fcntl_lock);
1909 return result;
1912 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1913 uint32 share_mode, uint32 access_mask)
1915 START_PROFILE(syscall_kernel_flock);
1916 kernel_flock(fsp->fh->fd, share_mode, access_mask);
1917 END_PROFILE(syscall_kernel_flock);
1918 return 0;
1921 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1923 bool result;
1925 START_PROFILE(syscall_fcntl_getlock);
1926 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1927 END_PROFILE(syscall_fcntl_getlock);
1928 return result;
1931 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1932 int leasetype)
1934 int result = -1;
1936 START_PROFILE(syscall_linux_setlease);
1938 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1939 result = linux_setlease(fsp->fh->fd, leasetype);
1940 #else
1941 errno = ENOSYS;
1942 #endif
1943 END_PROFILE(syscall_linux_setlease);
1944 return result;
1947 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1949 int result;
1951 START_PROFILE(syscall_symlink);
1952 result = symlink(oldpath, newpath);
1953 END_PROFILE(syscall_symlink);
1954 return result;
1957 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
1959 int result;
1961 START_PROFILE(syscall_readlink);
1962 result = readlink(path, buf, bufsiz);
1963 END_PROFILE(syscall_readlink);
1964 return result;
1967 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1969 int result;
1971 START_PROFILE(syscall_link);
1972 result = link(oldpath, newpath);
1973 END_PROFILE(syscall_link);
1974 return result;
1977 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
1979 int result;
1981 START_PROFILE(syscall_mknod);
1982 result = sys_mknod(pathname, mode, dev);
1983 END_PROFILE(syscall_mknod);
1984 return result;
1987 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
1989 char *result;
1991 START_PROFILE(syscall_realpath);
1992 #ifdef REALPATH_TAKES_NULL
1993 result = realpath(path, NULL);
1994 #else
1995 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
1996 if (result) {
1997 char *resolved_path = realpath(path, result);
1998 if (!resolved_path) {
1999 SAFE_FREE(result);
2000 } else {
2001 /* SMB_ASSERT(result == resolved_path) ? */
2002 result = resolved_path;
2005 #endif
2006 END_PROFILE(syscall_realpath);
2007 return result;
2010 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2011 struct sys_notify_context *ctx,
2012 const char *path,
2013 uint32_t *filter,
2014 uint32_t *subdir_filter,
2015 void (*callback)(struct sys_notify_context *ctx,
2016 void *private_data,
2017 struct notify_event *ev),
2018 void *private_data, void *handle)
2021 * So far inotify is the only supported default notify mechanism. If
2022 * another platform like the the BSD's or a proprietary Unix comes
2023 * along and wants another default, we can play the same trick we
2024 * played with Posix ACLs.
2026 * Until that is the case, hard-code inotify here.
2028 #ifdef HAVE_INOTIFY
2029 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2030 return inotify_watch(ctx, path, filter, subdir_filter,
2031 callback, private_data, handle);
2033 #endif
2035 * Do nothing, leave everything to notify_internal.c
2037 return NT_STATUS_OK;
2040 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2041 unsigned int flags)
2043 #ifdef HAVE_CHFLAGS
2044 return chflags(path, flags);
2045 #else
2046 errno = ENOSYS;
2047 return -1;
2048 #endif
2051 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2052 const SMB_STRUCT_STAT *sbuf)
2054 struct file_id key;
2056 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2057 * blob */
2058 ZERO_STRUCT(key);
2060 key.devid = sbuf->st_ex_dev;
2061 key.inode = sbuf->st_ex_ino;
2062 /* key.extid is unused by default. */
2064 return key;
2067 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2068 struct files_struct *fsp,
2069 const char *fname,
2070 TALLOC_CTX *mem_ctx,
2071 unsigned int *pnum_streams,
2072 struct stream_struct **pstreams)
2074 SMB_STRUCT_STAT sbuf;
2075 struct stream_struct *tmp_streams = NULL;
2076 int ret;
2078 if ((fsp != NULL) && (fsp->is_directory)) {
2080 * No default streams on directories
2082 goto done;
2085 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2086 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2088 else {
2089 struct smb_filename smb_fname;
2091 ZERO_STRUCT(smb_fname);
2092 smb_fname.base_name = discard_const_p(char, fname);
2094 if (lp_posix_pathnames()) {
2095 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2096 } else {
2097 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2099 sbuf = smb_fname.st;
2102 if (ret == -1) {
2103 return map_nt_error_from_unix(errno);
2106 if (S_ISDIR(sbuf.st_ex_mode)) {
2107 goto done;
2110 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2111 (*pnum_streams) + 1);
2112 if (tmp_streams == NULL) {
2113 return NT_STATUS_NO_MEMORY;
2115 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2116 if (tmp_streams[*pnum_streams].name == NULL) {
2117 return NT_STATUS_NO_MEMORY;
2119 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2120 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2122 *pnum_streams += 1;
2123 *pstreams = tmp_streams;
2124 done:
2125 return NT_STATUS_OK;
2128 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2129 const char *path,
2130 const char *name,
2131 TALLOC_CTX *mem_ctx,
2132 char **found_name)
2135 * Don't fall back to get_real_filename so callers can differentiate
2136 * between a full directory scan and an actual case-insensitive stat.
2138 errno = EOPNOTSUPP;
2139 return -1;
2142 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2143 const char *fname)
2145 return handle->conn->connectpath;
2148 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2149 struct byte_range_lock *br_lck,
2150 struct lock_struct *plock,
2151 bool blocking_lock,
2152 struct blocking_lock_record *blr)
2154 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2156 /* Note: blr is not used in the default implementation. */
2157 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2160 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2161 struct messaging_context *msg_ctx,
2162 struct byte_range_lock *br_lck,
2163 const struct lock_struct *plock)
2165 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2167 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2170 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2171 struct byte_range_lock *br_lck,
2172 struct lock_struct *plock,
2173 struct blocking_lock_record *blr)
2175 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2177 /* Note: blr is not used in the default implementation. */
2178 return brl_lock_cancel_default(br_lck, plock);
2181 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2182 files_struct *fsp,
2183 struct lock_struct *plock)
2185 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2186 plock->lock_type == WRITE_LOCK);
2188 return strict_lock_default(fsp, plock);
2191 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2192 files_struct *fsp,
2193 struct lock_struct *plock)
2195 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2196 plock->lock_type == WRITE_LOCK);
2198 strict_unlock_default(fsp, plock);
2201 /* NT ACL operations. */
2203 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2204 files_struct *fsp,
2205 uint32 security_info,
2206 TALLOC_CTX *mem_ctx,
2207 struct security_descriptor **ppdesc)
2209 NTSTATUS result;
2211 START_PROFILE(fget_nt_acl);
2212 result = posix_fget_nt_acl(fsp, security_info,
2213 mem_ctx, ppdesc);
2214 END_PROFILE(fget_nt_acl);
2215 return result;
2218 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2219 const char *name,
2220 uint32 security_info,
2221 TALLOC_CTX *mem_ctx,
2222 struct security_descriptor **ppdesc)
2224 NTSTATUS result;
2226 START_PROFILE(get_nt_acl);
2227 result = posix_get_nt_acl(handle->conn, name, security_info,
2228 mem_ctx, ppdesc);
2229 END_PROFILE(get_nt_acl);
2230 return result;
2233 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2235 NTSTATUS result;
2237 START_PROFILE(fset_nt_acl);
2238 result = set_nt_acl(fsp, security_info_sent, psd);
2239 END_PROFILE(fset_nt_acl);
2240 return result;
2243 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2244 struct smb_filename *file,
2245 struct security_acl *sacl,
2246 uint32_t access_requested,
2247 uint32_t access_denied)
2249 return NT_STATUS_OK; /* Nothing to do here ... */
2252 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2254 #ifdef HAVE_NO_ACL
2255 errno = ENOSYS;
2256 return -1;
2257 #else
2258 int result;
2260 START_PROFILE(chmod_acl);
2261 result = chmod_acl(handle->conn, name, mode);
2262 END_PROFILE(chmod_acl);
2263 return result;
2264 #endif
2267 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2269 #ifdef HAVE_NO_ACL
2270 errno = ENOSYS;
2271 return -1;
2272 #else
2273 int result;
2275 START_PROFILE(fchmod_acl);
2276 result = fchmod_acl(fsp, mode);
2277 END_PROFILE(fchmod_acl);
2278 return result;
2279 #endif
2282 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2283 const char *path_p,
2284 SMB_ACL_TYPE_T type,
2285 TALLOC_CTX *mem_ctx)
2287 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2290 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2291 files_struct *fsp,
2292 TALLOC_CTX *mem_ctx)
2294 return sys_acl_get_fd(handle, fsp, mem_ctx);
2297 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2299 return sys_acl_set_file(handle, name, acltype, theacl);
2302 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2304 return sys_acl_set_fd(handle, fsp, theacl);
2307 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2309 return sys_acl_delete_def_file(handle, path);
2312 /****************************************************************
2313 Extended attribute operations.
2314 *****************************************************************/
2316 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2318 return getxattr(path, name, value, size);
2321 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2323 return fgetxattr(fsp->fh->fd, name, value, size);
2326 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2328 return listxattr(path, list, size);
2331 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2333 return flistxattr(fsp->fh->fd, list, size);
2336 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2338 return removexattr(path, name);
2341 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2343 return fremovexattr(fsp->fh->fd, name);
2346 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2348 return setxattr(path, name, value, size, flags);
2351 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2353 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2356 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2358 return false;
2361 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2362 const struct smb_filename *fname,
2363 SMB_STRUCT_STAT *sbuf)
2365 NTSTATUS status;
2366 char *path;
2367 bool offline = false;
2369 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2370 return false;
2373 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2374 #if defined(ENOTSUP)
2375 errno = ENOTSUP;
2376 #endif
2377 return false;
2380 status = get_full_smb_filename(talloc_tos(), fname, &path);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 errno = map_errno_from_nt_status(status);
2383 return false;
2386 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2388 TALLOC_FREE(path);
2390 return offline;
2393 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2394 const struct smb_filename *fname)
2396 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2397 #if defined(ENOTSUP)
2398 errno = ENOTSUP;
2399 #endif
2400 return -1;
2403 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2404 struct files_struct *fsp,
2405 TALLOC_CTX *mem_ctx,
2406 DATA_BLOB *cookie)
2408 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2411 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2412 struct files_struct *fsp,
2413 const DATA_BLOB old_cookie,
2414 TALLOC_CTX *mem_ctx,
2415 DATA_BLOB *new_cookie)
2417 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2418 new_cookie);
2421 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2422 struct smb_request *smb1req,
2423 struct smbXsrv_open *op,
2424 const DATA_BLOB old_cookie,
2425 TALLOC_CTX *mem_ctx,
2426 struct files_struct **fsp,
2427 DATA_BLOB *new_cookie)
2429 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2430 old_cookie, mem_ctx,
2431 fsp, new_cookie);
2434 static struct vfs_fn_pointers vfs_default_fns = {
2435 /* Disk operations */
2437 .connect_fn = vfswrap_connect,
2438 .disconnect_fn = vfswrap_disconnect,
2439 .disk_free_fn = vfswrap_disk_free,
2440 .get_quota_fn = vfswrap_get_quota,
2441 .set_quota_fn = vfswrap_set_quota,
2442 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2443 .statvfs_fn = vfswrap_statvfs,
2444 .fs_capabilities_fn = vfswrap_fs_capabilities,
2445 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2447 /* Directory operations */
2449 .opendir_fn = vfswrap_opendir,
2450 .fdopendir_fn = vfswrap_fdopendir,
2451 .readdir_fn = vfswrap_readdir,
2452 .seekdir_fn = vfswrap_seekdir,
2453 .telldir_fn = vfswrap_telldir,
2454 .rewind_dir_fn = vfswrap_rewinddir,
2455 .mkdir_fn = vfswrap_mkdir,
2456 .rmdir_fn = vfswrap_rmdir,
2457 .closedir_fn = vfswrap_closedir,
2458 .init_search_op_fn = vfswrap_init_search_op,
2460 /* File operations */
2462 .open_fn = vfswrap_open,
2463 .create_file_fn = vfswrap_create_file,
2464 .close_fn = vfswrap_close,
2465 .read_fn = vfswrap_read,
2466 .pread_fn = vfswrap_pread,
2467 .pread_send_fn = vfswrap_pread_send,
2468 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2469 .write_fn = vfswrap_write,
2470 .pwrite_fn = vfswrap_pwrite,
2471 .pwrite_send_fn = vfswrap_pwrite_send,
2472 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2473 .lseek_fn = vfswrap_lseek,
2474 .sendfile_fn = vfswrap_sendfile,
2475 .recvfile_fn = vfswrap_recvfile,
2476 .rename_fn = vfswrap_rename,
2477 .fsync_fn = vfswrap_fsync,
2478 .fsync_send_fn = vfswrap_fsync_send,
2479 .fsync_recv_fn = vfswrap_asys_int_recv,
2480 .stat_fn = vfswrap_stat,
2481 .fstat_fn = vfswrap_fstat,
2482 .lstat_fn = vfswrap_lstat,
2483 .get_alloc_size_fn = vfswrap_get_alloc_size,
2484 .unlink_fn = vfswrap_unlink,
2485 .chmod_fn = vfswrap_chmod,
2486 .fchmod_fn = vfswrap_fchmod,
2487 .chown_fn = vfswrap_chown,
2488 .fchown_fn = vfswrap_fchown,
2489 .lchown_fn = vfswrap_lchown,
2490 .chdir_fn = vfswrap_chdir,
2491 .getwd_fn = vfswrap_getwd,
2492 .ntimes_fn = vfswrap_ntimes,
2493 .ftruncate_fn = vfswrap_ftruncate,
2494 .fallocate_fn = vfswrap_fallocate,
2495 .lock_fn = vfswrap_lock,
2496 .kernel_flock_fn = vfswrap_kernel_flock,
2497 .linux_setlease_fn = vfswrap_linux_setlease,
2498 .getlock_fn = vfswrap_getlock,
2499 .symlink_fn = vfswrap_symlink,
2500 .readlink_fn = vfswrap_readlink,
2501 .link_fn = vfswrap_link,
2502 .mknod_fn = vfswrap_mknod,
2503 .realpath_fn = vfswrap_realpath,
2504 .notify_watch_fn = vfswrap_notify_watch,
2505 .chflags_fn = vfswrap_chflags,
2506 .file_id_create_fn = vfswrap_file_id_create,
2507 .streaminfo_fn = vfswrap_streaminfo,
2508 .get_real_filename_fn = vfswrap_get_real_filename,
2509 .connectpath_fn = vfswrap_connectpath,
2510 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2511 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2512 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2513 .strict_lock_fn = vfswrap_strict_lock,
2514 .strict_unlock_fn = vfswrap_strict_unlock,
2515 .translate_name_fn = vfswrap_translate_name,
2516 .fsctl_fn = vfswrap_fsctl,
2517 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2518 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2520 /* NT ACL operations. */
2522 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2523 .get_nt_acl_fn = vfswrap_get_nt_acl,
2524 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2525 .audit_file_fn = vfswrap_audit_file,
2527 /* POSIX ACL operations. */
2529 .chmod_acl_fn = vfswrap_chmod_acl,
2530 .fchmod_acl_fn = vfswrap_fchmod_acl,
2532 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2533 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2534 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2535 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2536 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2537 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2538 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2540 /* EA operations. */
2541 .getxattr_fn = vfswrap_getxattr,
2542 .fgetxattr_fn = vfswrap_fgetxattr,
2543 .listxattr_fn = vfswrap_listxattr,
2544 .flistxattr_fn = vfswrap_flistxattr,
2545 .removexattr_fn = vfswrap_removexattr,
2546 .fremovexattr_fn = vfswrap_fremovexattr,
2547 .setxattr_fn = vfswrap_setxattr,
2548 .fsetxattr_fn = vfswrap_fsetxattr,
2550 /* aio operations */
2551 .aio_force_fn = vfswrap_aio_force,
2553 /* offline operations */
2554 .is_offline_fn = vfswrap_is_offline,
2555 .set_offline_fn = vfswrap_set_offline,
2557 /* durable handle operations */
2558 .durable_cookie_fn = vfswrap_durable_cookie,
2559 .durable_disconnect_fn = vfswrap_durable_disconnect,
2560 .durable_reconnect_fn = vfswrap_durable_reconnect,
2563 NTSTATUS vfs_default_init(void);
2564 NTSTATUS vfs_default_init(void)
2566 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2567 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);