smbd: Remove unused blocking_lock_record* from VFS_BRL_LOCK_WINDOWS
[samba.git] / source3 / modules / vfs_default.c
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
6
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.
11
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.
16
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/>.
19 */
20
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"
35
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_VFS
38
39 /* Check for NULL pointer parameters in vfswrap_* functions */
40
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. */
44
45 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
46 {
47     return 0;    /* Return >= 0 for success */
48 }
49
50 static void vfswrap_disconnect(vfs_handle_struct *handle)
51 {
52 }
53
54 /* Disk operations */
55
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)
58 {
59         uint64_t result;
60
61         result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
62         return result;
63 }
64
65 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
66 {
67 #ifdef HAVE_SYS_QUOTAS
68         int result;
69
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
78 }
79
80 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
81 {
82 #ifdef HAVE_SYS_QUOTAS
83         int result;
84
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
93 }
94
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)
99 {
100         errno = ENOSYS;
101         return -1;  /* Not implemented. */
102 }
103
104 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
105 {
106         return sys_statvfs(path, statbuf);
107 }
108
109 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
110                 enum timestamp_set_resolution *p_ts_res)
111 {
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;
117
118         ZERO_STRUCT(statbuf);
119         ret = sys_statvfs(conn->connectpath, &statbuf);
120         if (ret == 0) {
121                 caps = statbuf.FsCapabilities;
122         }
123
124         *p_ts_res = TIMESTAMP_SET_SECONDS;
125
126         /* Work out what timestamp resolution we can
127          * use when setting a timestamp. */
128
129         smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
130                                               NULL, NULL);
131         if (smb_fname_cpath == NULL) {
132                 return caps;
133         }
134
135         ret = SMB_VFS_STAT(conn, smb_fname_cpath);
136         if (ret == -1) {
137                 TALLOC_FREE(smb_fname_cpath);
138                 return caps;
139         }
140
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.
148                  */
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
158
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 ));
165         }
166         TALLOC_FREE(smb_fname_cpath);
167         return caps;
168 }
169
170 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
171                                           struct dfs_GetDFSReferral *r)
172 {
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;
181
182         if (DEBUGLVL(10)) {
183                 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
184         }
185
186         /* get the junction entry */
187         if (r->in.req.servername == NULL) {
188                 return NT_STATUS_NOT_FOUND;
189         }
190
191         /*
192          * Trim pathname sent by client so it begins with only one backslash.
193          * Two backslashes confuse some dfs clients
194          */
195
196         local_dfs_path = talloc_strdup(r, r->in.req.servername);
197         if (local_dfs_path == NULL) {
198                 return NT_STATUS_NO_MEMORY;
199         }
200         pathnamep = local_dfs_path;
201         while (IS_DIRECTORY_SEP(pathnamep[0]) &&
202                IS_DIRECTORY_SEP(pathnamep[1])) {
203                 pathnamep++;
204         }
205
206         junction = talloc_zero(r, struct junction_map);
207         if (junction == NULL) {
208                 return NT_STATUS_NO_MEMORY;
209         }
210
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;
218         }
219         vfs_ChDir(handle->conn, handle->conn->connectpath);
220
221         if (!self_referral) {
222                 pathnamep[consumedcnt] = '\0';
223
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);
231                         }
232                         dbgtext(".\n");
233                 }
234         }
235
236         if (r->in.req.max_referral_level <= 2) {
237                 max_referral_level = 2;
238         }
239         if (r->in.req.max_referral_level >= 3) {
240                 max_referral_level = 3;
241         }
242
243         r->out.resp = talloc_zero(r, struct dfs_referral_resp);
244         if (r->out.resp == NULL) {
245                 return NT_STATUS_NO_MEMORY;
246         }
247
248         r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
249         r->out.resp->nb_referrals = junction->referral_count;
250
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;
254         }
255
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;
261         }
262
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;
271
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;
278                         }
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;
285                         }
286                         v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
287                         if (v2->DFS_alt_path == NULL) {
288                                 return NT_STATUS_NO_MEMORY;
289                         }
290                         v2->netw_address = talloc_strdup(mem_ctx,
291                                                          ref->alternate_path);
292                         if (v2->netw_address == NULL) {
293                                 return NT_STATUS_NO_MEMORY;
294                         }
295                 }
296
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;
306
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;
313                         }
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;
319                         }
320                         r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321                         if (r1->DFS_alt_path == NULL) {
322                                 return NT_STATUS_NO_MEMORY;
323                         }
324                         r1->netw_address = talloc_strdup(mem_ctx,
325                                                          ref->alternate_path);
326                         if (r1->netw_address == NULL) {
327                                 return NT_STATUS_NO_MEMORY;
328                         }
329                 }
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;
336         }
337
338         if (DEBUGLVL(10)) {
339                 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
340         }
341
342         return NT_STATUS_OK;
343 }
344
345 /* Directory operations */
346
347 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
348 {
349         DIR *result;
350
351         START_PROFILE(syscall_opendir);
352         result = opendir(fname);
353         END_PROFILE(syscall_opendir);
354         return result;
355 }
356
357 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
358                         files_struct *fsp,
359                         const char *mask,
360                         uint32 attr)
361 {
362         DIR *result;
363
364         START_PROFILE(syscall_fdopendir);
365         result = sys_fdopendir(fsp->fh->fd);
366         END_PROFILE(syscall_fdopendir);
367         return result;
368 }
369
370
371 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
372                                           DIR *dirp,
373                                           SMB_STRUCT_STAT *sbuf)
374 {
375         struct dirent *result;
376
377         START_PROFILE(syscall_readdir);
378         result = readdir(dirp);
379         END_PROFILE(syscall_readdir);
380         if (sbuf) {
381                 /* Default Posix readdir() does not give us stat info.
382                  * Set to invalid to indicate we didn't return this info. */
383                 SET_STAT_INVALID(*sbuf);
384 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
385                 if (result != NULL) {
386                         /* See if we can efficiently return this. */
387                         struct stat st;
388                         int flags = (lp_posix_pathnames() ?
389                                 AT_SYMLINK_NOFOLLOW : 0);
390                         int ret = fstatat(dirfd(dirp),
391                                         result->d_name,
392                                         &st,
393                                         flags);
394                         if (ret == 0) {
395                                 init_stat_ex_from_stat(sbuf,
396                                         &st,
397                                         lp_fake_directory_create_times(
398                                                 SNUM(handle->conn)));
399                         }
400                 }
401 #endif
402         }
403         return result;
404 }
405
406 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
407 {
408         START_PROFILE(syscall_seekdir);
409         seekdir(dirp, offset);
410         END_PROFILE(syscall_seekdir);
411 }
412
413 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
414 {
415         long result;
416         START_PROFILE(syscall_telldir);
417         result = telldir(dirp);
418         END_PROFILE(syscall_telldir);
419         return result;
420 }
421
422 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
423 {
424         START_PROFILE(syscall_rewinddir);
425         rewinddir(dirp);
426         END_PROFILE(syscall_rewinddir);
427 }
428
429 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
430 {
431         int result;
432         bool has_dacl = False;
433         char *parent = NULL;
434
435         START_PROFILE(syscall_mkdir);
436
437         if (lp_inherit_acls(SNUM(handle->conn))
438             && parent_dirname(talloc_tos(), path, &parent, NULL)
439             && (has_dacl = directory_has_default_acl(handle->conn, parent)))
440                 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
441
442         TALLOC_FREE(parent);
443
444         result = mkdir(path, mode);
445
446         if (result == 0 && !has_dacl) {
447                 /*
448                  * We need to do this as the default behavior of POSIX ACLs
449                  * is to set the mask to be the requested group permission
450                  * bits, not the group permission bits to be the requested
451                  * group permission bits. This is not what we want, as it will
452                  * mess up any inherited ACL bits that were set. JRA.
453                  */
454                 int saved_errno = errno; /* We may get ENOSYS */
455                 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
456                         errno = saved_errno;
457         }
458
459         END_PROFILE(syscall_mkdir);
460         return result;
461 }
462
463 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
464 {
465         int result;
466
467         START_PROFILE(syscall_rmdir);
468         result = rmdir(path);
469         END_PROFILE(syscall_rmdir);
470         return result;
471 }
472
473 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
474 {
475         int result;
476
477         START_PROFILE(syscall_closedir);
478         result = closedir(dirp);
479         END_PROFILE(syscall_closedir);
480         return result;
481 }
482
483 static void vfswrap_init_search_op(vfs_handle_struct *handle,
484                                    DIR *dirp)
485 {
486         /* Default behavior is a NOOP */
487 }
488
489 /* File operations */
490
491 static int vfswrap_open(vfs_handle_struct *handle,
492                         struct smb_filename *smb_fname,
493                         files_struct *fsp, int flags, mode_t mode)
494 {
495         int result = -1;
496
497         START_PROFILE(syscall_open);
498
499         if (smb_fname->stream_name) {
500                 errno = ENOENT;
501                 goto out;
502         }
503
504         result = open(smb_fname->base_name, flags, mode);
505  out:
506         END_PROFILE(syscall_open);
507         return result;
508 }
509
510 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
511                                     struct smb_request *req,
512                                     uint16_t root_dir_fid,
513                                     struct smb_filename *smb_fname,
514                                     uint32_t access_mask,
515                                     uint32_t share_access,
516                                     uint32_t create_disposition,
517                                     uint32_t create_options,
518                                     uint32_t file_attributes,
519                                     uint32_t oplock_request,
520                                     uint64_t allocation_size,
521                                     uint32_t private_flags,
522                                     struct security_descriptor *sd,
523                                     struct ea_list *ea_list,
524                                     files_struct **result,
525                                     int *pinfo)
526 {
527         return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
528                                    access_mask, share_access,
529                                    create_disposition, create_options,
530                                    file_attributes, oplock_request,
531                                    allocation_size, private_flags,
532                                    sd, ea_list, result,
533                                    pinfo);
534 }
535
536 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
537 {
538         int result;
539
540         START_PROFILE(syscall_close);
541         result = fd_close_posix(fsp);
542         END_PROFILE(syscall_close);
543         return result;
544 }
545
546 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
547 {
548         ssize_t result;
549
550         START_PROFILE_BYTES(syscall_read, n);
551         result = sys_read(fsp->fh->fd, data, n);
552         END_PROFILE(syscall_read);
553         return result;
554 }
555
556 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
557                         size_t n, off_t offset)
558 {
559         ssize_t result;
560
561 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
562         START_PROFILE_BYTES(syscall_pread, n);
563         result = sys_pread(fsp->fh->fd, data, n, offset);
564         END_PROFILE(syscall_pread);
565
566         if (result == -1 && errno == ESPIPE) {
567                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
568                 result = SMB_VFS_READ(fsp, data, n);
569                 fsp->fh->pos = 0;
570         }
571
572 #else /* HAVE_PREAD */
573         off_t   curr;
574         int lerrno;
575
576         curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
577         if (curr == -1 && errno == ESPIPE) {
578                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
579                 result = SMB_VFS_READ(fsp, data, n);
580                 fsp->fh->pos = 0;
581                 return result;
582         }
583
584         if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
585                 return -1;
586         }
587
588         errno = 0;
589         result = SMB_VFS_READ(fsp, data, n);
590         lerrno = errno;
591
592         SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
593         errno = lerrno;
594
595 #endif /* HAVE_PREAD */
596
597         return result;
598 }
599
600 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
601 {
602         ssize_t result;
603
604         START_PROFILE_BYTES(syscall_write, n);
605         result = sys_write(fsp->fh->fd, data, n);
606         END_PROFILE(syscall_write);
607         return result;
608 }
609
610 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
611                         size_t n, off_t offset)
612 {
613         ssize_t result;
614
615 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
616         START_PROFILE_BYTES(syscall_pwrite, n);
617         result = sys_pwrite(fsp->fh->fd, data, n, offset);
618         END_PROFILE(syscall_pwrite);
619
620         if (result == -1 && errno == ESPIPE) {
621                 /* Maintain the fiction that pipes can be sought on. */
622                 result = SMB_VFS_WRITE(fsp, data, n);
623         }
624
625 #else /* HAVE_PWRITE */
626         off_t   curr;
627         int         lerrno;
628
629         curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
630         if (curr == -1) {
631                 return -1;
632         }
633
634         if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
635                 return -1;
636         }
637
638         result = SMB_VFS_WRITE(fsp, data, n);
639         lerrno = errno;
640
641         SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
642         errno = lerrno;
643
644 #endif /* HAVE_PWRITE */
645
646         return result;
647 }
648
649 static void vfswrap_asys_finished(struct tevent_context *ev,
650                                   struct tevent_fd *fde,
651                                   uint16_t flags, void *p);
652
653 static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
654 {
655         int ret;
656         int fd;
657
658         if (conn->asys_ctx != NULL) {
659                 return true;
660         }
661         ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
662         if (ret != 0) {
663                 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
664                 return false;
665         }
666
667         fd = asys_signalfd(conn->asys_ctx);
668
669         set_blocking(fd, false);
670
671         conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
672                                        TEVENT_FD_READ,
673                                        vfswrap_asys_finished,
674                                        conn->asys_ctx);
675         if (conn->asys_fde == NULL) {
676                 DEBUG(1, ("tevent_add_fd failed\n"));
677                 asys_context_destroy(conn->asys_ctx);
678                 conn->asys_ctx = NULL;
679                 return false;
680         }
681         return true;
682 }
683
684 struct vfswrap_asys_state {
685         struct asys_context *asys_ctx;
686         struct tevent_req *req;
687         ssize_t ret;
688         int err;
689 };
690
691 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
692 {
693         asys_cancel(s->asys_ctx, s->req);
694         return 0;
695 }
696
697 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
698                                              TALLOC_CTX *mem_ctx,
699                                              struct tevent_context *ev,
700                                              struct files_struct *fsp,
701                                              void *data,
702                                              size_t n, off_t offset)
703 {
704         struct tevent_req *req;
705         struct vfswrap_asys_state *state;
706         int ret;
707
708         req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
709         if (req == NULL) {
710                 return NULL;
711         }
712         if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
713                 tevent_req_oom(req);
714                 return tevent_req_post(req, ev);
715         }
716         state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
717         state->req = req;
718
719         ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
720         if (ret != 0) {
721                 tevent_req_error(req, ret);
722                 return tevent_req_post(req, ev);
723         }
724         talloc_set_destructor(state, vfswrap_asys_state_destructor);
725
726         return req;
727 }
728
729 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
730                                               TALLOC_CTX *mem_ctx,
731                                               struct tevent_context *ev,
732                                               struct files_struct *fsp,
733                                               const void *data,
734                                               size_t n, off_t offset)
735 {
736         struct tevent_req *req;
737         struct vfswrap_asys_state *state;
738         int ret;
739
740         req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
741         if (req == NULL) {
742                 return NULL;
743         }
744         if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
745                 tevent_req_oom(req);
746                 return tevent_req_post(req, ev);
747         }
748         state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
749         state->req = req;
750
751         ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
752         if (ret != 0) {
753                 tevent_req_error(req, ret);
754                 return tevent_req_post(req, ev);
755         }
756         talloc_set_destructor(state, vfswrap_asys_state_destructor);
757
758         return req;
759 }
760
761 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
762                                              TALLOC_CTX *mem_ctx,
763                                              struct tevent_context *ev,
764                                              struct files_struct *fsp)
765 {
766         struct tevent_req *req;
767         struct vfswrap_asys_state *state;
768         int ret;
769
770         req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
771         if (req == NULL) {
772                 return NULL;
773         }
774         if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
775                 tevent_req_oom(req);
776                 return tevent_req_post(req, ev);
777         }
778         state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
779         state->req = req;
780
781         ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
782         if (ret != 0) {
783                 tevent_req_error(req, ret);
784                 return tevent_req_post(req, ev);
785         }
786         talloc_set_destructor(state, vfswrap_asys_state_destructor);
787
788         return req;
789 }
790
791 static void vfswrap_asys_finished(struct tevent_context *ev,
792                                         struct tevent_fd *fde,
793                                         uint16_t flags, void *p)
794 {
795         struct asys_context *asys_ctx = (struct asys_context *)p;
796         struct asys_result results[outstanding_aio_calls];
797         int i, ret;
798
799         if ((flags & TEVENT_FD_READ) == 0) {
800                 return;
801         }
802
803         ret = asys_results(asys_ctx, results, outstanding_aio_calls);
804         if (ret < 0) {
805                 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
806                 return;
807         }
808
809         for (i=0; i<ret; i++) {
810                 struct asys_result *result = &results[i];
811                 struct tevent_req *req;
812                 struct vfswrap_asys_state *state;
813
814                 if ((result->ret == -1) && (result->err == ECANCELED)) {
815                         continue;
816                 }
817
818                 req = talloc_get_type_abort(result->private_data,
819                                             struct tevent_req);
820                 state = tevent_req_data(req, struct vfswrap_asys_state);
821
822                 talloc_set_destructor(state, NULL);
823
824                 state->ret = result->ret;
825                 state->err = result->err;
826                 tevent_req_defer_callback(req, ev);
827                 tevent_req_done(req);
828         }
829 }
830
831 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
832 {
833         struct vfswrap_asys_state *state = tevent_req_data(
834                 req, struct vfswrap_asys_state);
835
836         if (tevent_req_is_unix_error(req, err)) {
837                 return -1;
838         }
839         *err = state->err;
840         return state->ret;
841 }
842
843 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
844 {
845         struct vfswrap_asys_state *state = tevent_req_data(
846                 req, struct vfswrap_asys_state);
847
848         if (tevent_req_is_unix_error(req, err)) {
849                 return -1;
850         }
851         *err = state->err;
852         return state->ret;
853 }
854
855 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
856 {
857         off_t result = 0;
858
859         START_PROFILE(syscall_lseek);
860
861         /* Cope with 'stat' file opens. */
862         if (fsp->fh->fd != -1)
863                 result = lseek(fsp->fh->fd, offset, whence);
864
865         /*
866          * We want to maintain the fiction that we can seek
867          * on a fifo for file system purposes. This allows
868          * people to set up UNIX fifo's that feed data to Windows
869          * applications. JRA.
870          */
871
872         if((result == -1) && (errno == ESPIPE)) {
873                 result = 0;
874                 errno = 0;
875         }
876
877         END_PROFILE(syscall_lseek);
878         return result;
879 }
880
881 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
882                         off_t offset, size_t n)
883 {
884         ssize_t result;
885
886         START_PROFILE_BYTES(syscall_sendfile, n);
887         result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
888         END_PROFILE(syscall_sendfile);
889         return result;
890 }
891
892 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
893                         int fromfd,
894                         files_struct *tofsp,
895                         off_t offset,
896                         size_t n)
897 {
898         ssize_t result;
899
900         START_PROFILE_BYTES(syscall_recvfile, n);
901         result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
902         END_PROFILE(syscall_recvfile);
903         return result;
904 }
905
906 static int vfswrap_rename(vfs_handle_struct *handle,
907                           const struct smb_filename *smb_fname_src,
908                           const struct smb_filename *smb_fname_dst)
909 {
910         int result = -1;
911
912         START_PROFILE(syscall_rename);
913
914         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
915                 errno = ENOENT;
916                 goto out;
917         }
918
919         result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
920
921  out:
922         END_PROFILE(syscall_rename);
923         return result;
924 }
925
926 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
927 {
928 #ifdef HAVE_FSYNC
929         int result;
930
931         START_PROFILE(syscall_fsync);
932         result = fsync(fsp->fh->fd);
933         END_PROFILE(syscall_fsync);
934         return result;
935 #else
936         return 0;
937 #endif
938 }
939
940 static int vfswrap_stat(vfs_handle_struct *handle,
941                         struct smb_filename *smb_fname)
942 {
943         int result = -1;
944
945         START_PROFILE(syscall_stat);
946
947         if (smb_fname->stream_name) {
948                 errno = ENOENT;
949                 goto out;
950         }
951
952         result = sys_stat(smb_fname->base_name, &smb_fname->st,
953                           lp_fake_directory_create_times(SNUM(handle->conn)));
954  out:
955         END_PROFILE(syscall_stat);
956         return result;
957 }
958
959 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
960 {
961         int result;
962
963         START_PROFILE(syscall_fstat);
964         result = sys_fstat(fsp->fh->fd,
965                            sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
966         END_PROFILE(syscall_fstat);
967         return result;
968 }
969
970 static int vfswrap_lstat(vfs_handle_struct *handle,
971                          struct smb_filename *smb_fname)
972 {
973         int result = -1;
974
975         START_PROFILE(syscall_lstat);
976
977         if (smb_fname->stream_name) {
978                 errno = ENOENT;
979                 goto out;
980         }
981
982         result = sys_lstat(smb_fname->base_name, &smb_fname->st,
983                            lp_fake_directory_create_times(SNUM(handle->conn)));
984  out:
985         END_PROFILE(syscall_lstat);
986         return result;
987 }
988
989 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
990                                        const char *name,
991                                        enum vfs_translate_direction direction,
992                                        TALLOC_CTX *mem_ctx,
993                                        char **mapped_name)
994 {
995         return NT_STATUS_NONE_MAPPED;
996 }
997
998 /*
999  * Implement the default fsctl operation.
1000  */
1001 static bool vfswrap_logged_ioctl_message = false;
1002
1003 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1004                               struct files_struct *fsp,
1005                               TALLOC_CTX *ctx,
1006                               uint32_t function,
1007                               uint16_t req_flags, /* Needed for UNICODE ... */
1008                               const uint8_t *_in_data,
1009                               uint32_t in_len,
1010                               uint8_t **_out_data,
1011                               uint32_t max_out_len,
1012                               uint32_t *out_len)
1013 {
1014         const char *in_data = (const char *)_in_data;
1015         char **out_data = (char **)_out_data;
1016         NTSTATUS status;
1017
1018         switch (function) {
1019         case FSCTL_SET_SPARSE:
1020         {
1021                 bool set_sparse = true;
1022
1023                 if (in_len >= 1 && in_data[0] == 0) {
1024                         set_sparse = false;
1025                 }
1026
1027                 status = file_set_sparse(handle->conn, fsp, set_sparse);
1028
1029                 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1030                       ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1031                        smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1032                        nt_errstr(status)));
1033
1034                 return status;
1035         }
1036
1037         case FSCTL_CREATE_OR_GET_OBJECT_ID:
1038         {
1039                 unsigned char objid[16];
1040                 char *return_data = NULL;
1041
1042                 /* This should return the object-id on this file.
1043                  * I think I'll make this be the inode+dev. JRA.
1044                  */
1045
1046                 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1047                           fsp_fnum_dbg(fsp)));
1048
1049                 *out_len = MIN(max_out_len, 64);
1050
1051                 /* Hmmm, will this cause problems if less data asked for? */
1052                 return_data = talloc_array(ctx, char, 64);
1053                 if (return_data == NULL) {
1054                         return NT_STATUS_NO_MEMORY;
1055                 }
1056
1057                 /* For backwards compatibility only store the dev/inode. */
1058                 push_file_id_16(return_data, &fsp->file_id);
1059                 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1060                 push_file_id_16(return_data+32, &fsp->file_id);
1061                 memset(return_data+48, 0, 16);
1062                 *out_data = return_data;
1063                 return NT_STATUS_OK;
1064         }
1065
1066         case FSCTL_GET_REPARSE_POINT:
1067         {
1068                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1069                 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1070                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1071                 return NT_STATUS_NOT_A_REPARSE_POINT;
1072         }
1073
1074         case FSCTL_SET_REPARSE_POINT:
1075         {
1076                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1077                 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1078                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1079                 return NT_STATUS_NOT_A_REPARSE_POINT;
1080         }
1081
1082         case FSCTL_GET_SHADOW_COPY_DATA:
1083         {
1084                 /*
1085                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1086                  * and return their volume names.  If max_data_count is 16, then it is just
1087                  * asking for the number of volumes and length of the combined names.
1088                  *
1089                  * pdata is the data allocated by our caller, but that uses
1090                  * total_data_count (which is 0 in our case) rather than max_data_count.
1091                  * Allocate the correct amount and return the pointer to let
1092                  * it be deallocated when we return.
1093                  */
1094                 struct shadow_copy_data *shadow_data = NULL;
1095                 bool labels = False;
1096                 uint32 labels_data_count = 0;
1097                 uint32 i;
1098                 char *cur_pdata = NULL;
1099
1100                 if (max_out_len < 16) {
1101                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1102                                 max_out_len));
1103                         return NT_STATUS_INVALID_PARAMETER;
1104                 }
1105
1106                 if (max_out_len > 16) {
1107                         labels = True;
1108                 }
1109
1110                 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1111                 if (shadow_data == NULL) {
1112                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
1113                         return NT_STATUS_NO_MEMORY;
1114                 }
1115
1116                 /*
1117                  * Call the VFS routine to actually do the work.
1118                  */
1119                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1120                         int log_lev = 0;
1121                         if (errno == 0) {
1122                                 /* broken module didn't set errno on error */
1123                                 status = NT_STATUS_UNSUCCESSFUL;
1124                         } else {
1125                                 status = map_nt_error_from_unix(errno);
1126                                 if (NT_STATUS_EQUAL(status,
1127                                                     NT_STATUS_NOT_SUPPORTED)) {
1128                                         log_lev = 5;
1129                                 }
1130                         }
1131                         DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1132                                         "connectpath %s, failed - %s.\n",
1133                                         fsp->conn->connectpath,
1134                                         nt_errstr(status)));
1135                         TALLOC_FREE(shadow_data);
1136                         return status;
1137                 }
1138
1139                 labels_data_count = (shadow_data->num_volumes * 2 *
1140                                         sizeof(SHADOW_COPY_LABEL)) + 2;
1141
1142                 if (!labels) {
1143                         *out_len = 16;
1144                 } else {
1145                         *out_len = 12 + labels_data_count;
1146                 }
1147
1148                 if (max_out_len < *out_len) {
1149                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1150                                 max_out_len, *out_len));
1151                         TALLOC_FREE(shadow_data);
1152                         return NT_STATUS_BUFFER_TOO_SMALL;
1153                 }
1154
1155                 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1156                 if (cur_pdata == NULL) {
1157                         TALLOC_FREE(shadow_data);
1158                         return NT_STATUS_NO_MEMORY;
1159                 }
1160
1161                 *out_data = cur_pdata;
1162
1163                 /* num_volumes 4 bytes */
1164                 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1165
1166                 if (labels) {
1167                         /* num_labels 4 bytes */
1168                         SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1169                 }
1170
1171                 /* needed_data_count 4 bytes */
1172                 SIVAL(cur_pdata, 8, labels_data_count);
1173
1174                 cur_pdata += 12;
1175
1176                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1177                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
1178                 if (labels && shadow_data->labels) {
1179                         for (i=0; i<shadow_data->num_volumes; i++) {
1180                                 srvstr_push(cur_pdata, req_flags,
1181                                             cur_pdata, shadow_data->labels[i],
1182                                             2 * sizeof(SHADOW_COPY_LABEL),
1183                                             STR_UNICODE|STR_TERMINATE);
1184                                 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1185                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1186                         }
1187                 }
1188
1189                 TALLOC_FREE(shadow_data);
1190
1191                 return NT_STATUS_OK;
1192         }
1193
1194         case FSCTL_FIND_FILES_BY_SID:
1195         {
1196                 /* pretend this succeeded -
1197                  *
1198                  * we have to send back a list with all files owned by this SID
1199                  *
1200                  * but I have to check that --metze
1201                  */
1202                 struct dom_sid sid;
1203                 uid_t uid;
1204                 size_t sid_len;
1205
1206                 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1207                            fsp_fnum_dbg(fsp)));
1208
1209                 if (in_len < 8) {
1210                         /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1211                         return NT_STATUS_INVALID_PARAMETER;
1212                 }
1213
1214                 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1215
1216                 /* unknown 4 bytes: this is not the length of the sid :-(  */
1217                 /*unknown = IVAL(pdata,0);*/
1218
1219                 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1220                         return NT_STATUS_INVALID_PARAMETER;
1221                 }
1222                 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1223
1224                 if (!sid_to_uid(&sid, &uid)) {
1225                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1226                                  sid_string_dbg(&sid),
1227                                  (unsigned long)sid_len));
1228                         uid = (-1);
1229                 }
1230
1231                 /* we can take a look at the find source :-)
1232                  *
1233                  * find ./ -uid $uid  -name '*'   is what we need here
1234                  *
1235                  *
1236                  * and send 4bytes len and then NULL terminated unicode strings
1237                  * for each file
1238                  *
1239                  * but I don't know how to deal with the paged results
1240                  * (maybe we can hang the result anywhere in the fsp struct)
1241                  *
1242                  * but I don't know how to deal with the paged results
1243                  * (maybe we can hang the result anywhere in the fsp struct)
1244                  *
1245                  * we don't send all files at once
1246                  * and at the next we should *not* start from the beginning,
1247                  * so we have to cache the result
1248                  *
1249                  * --metze
1250                  */
1251
1252                 /* this works for now... */
1253                 return NT_STATUS_OK;
1254         }
1255
1256         case FSCTL_QUERY_ALLOCATED_RANGES:
1257         {
1258                 /* FIXME: This is just a dummy reply, telling that all of the
1259                  * file is allocated. MKS cp needs that.
1260                  * Adding the real allocated ranges via FIEMAP on Linux
1261                  * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1262                  * this FSCTL correct for sparse files.
1263                  */
1264                 uint64_t offset, length;
1265                 char *out_data_tmp = NULL;
1266
1267                 if (in_len != 16) {
1268                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1269                                 in_len));
1270                         return NT_STATUS_INVALID_PARAMETER;
1271                 }
1272
1273                 if (max_out_len < 16) {
1274                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1275                                 max_out_len));
1276                         return NT_STATUS_INVALID_PARAMETER;
1277                 }
1278
1279                 offset = BVAL(in_data,0);
1280                 length = BVAL(in_data,8);
1281
1282                 if (offset + length < offset) {
1283                         /* No 64-bit integer wrap. */
1284                         return NT_STATUS_INVALID_PARAMETER;
1285                 }
1286
1287                 /* Shouldn't this be SMB_VFS_STAT ... ? */
1288                 status = vfs_stat_fsp(fsp);
1289                 if (!NT_STATUS_IS_OK(status)) {
1290                         return status;
1291                 }
1292
1293                 *out_len = 16;
1294                 out_data_tmp = talloc_array(ctx, char, *out_len);
1295                 if (out_data_tmp == NULL) {
1296                         DEBUG(10, ("unable to allocate memory for response\n"));
1297                         return NT_STATUS_NO_MEMORY;
1298                 }
1299
1300                 if (offset > fsp->fsp_name->st.st_ex_size ||
1301                                 fsp->fsp_name->st.st_ex_size == 0 ||
1302                                 length == 0) {
1303                         memset(out_data_tmp, 0, *out_len);
1304                 } else {
1305                         uint64_t end = offset + length;
1306                         end = MIN(end, fsp->fsp_name->st.st_ex_size);
1307                         SBVAL(out_data_tmp, 0, 0);
1308                         SBVAL(out_data_tmp, 8, end);
1309                 }
1310
1311                 *out_data = out_data_tmp;
1312
1313                 return NT_STATUS_OK;
1314         }
1315
1316         case FSCTL_IS_VOLUME_DIRTY:
1317         {
1318                 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1319                           "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1320                 /*
1321                  * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1322                  * says we have to respond with NT_STATUS_INVALID_PARAMETER
1323                  */
1324                 return NT_STATUS_INVALID_PARAMETER;
1325         }
1326
1327         default:
1328                 /*
1329                  * Only print once ... unfortunately there could be lots of
1330                  * different FSCTLs that are called.
1331                  */
1332                 if (!vfswrap_logged_ioctl_message) {
1333                         vfswrap_logged_ioctl_message = true;
1334                         DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1335                         __func__, function));
1336                 }
1337         }
1338
1339         return NT_STATUS_NOT_SUPPORTED;
1340 }
1341
1342 struct vfs_cc_state {
1343         off_t copied;
1344         uint8_t buf[65536];
1345 };
1346
1347 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1348                                                   TALLOC_CTX *mem_ctx,
1349                                                   struct tevent_context *ev,
1350                                                   struct files_struct *src_fsp,
1351                                                   off_t src_off,
1352                                                   struct files_struct *dest_fsp,
1353                                                   off_t dest_off,
1354                                                   off_t num)
1355 {
1356         struct tevent_req *req;
1357         struct vfs_cc_state *vfs_cc_state;
1358         NTSTATUS status;
1359
1360         DEBUG(10, ("performing server side copy chunk of length %lu\n",
1361                    (unsigned long)num));
1362
1363         req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1364         if (req == NULL) {
1365                 return NULL;
1366         }
1367
1368         status = vfs_stat_fsp(src_fsp);
1369         if (tevent_req_nterror(req, status)) {
1370                 return tevent_req_post(req, ev);
1371         }
1372
1373         if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1374                 /*
1375                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1376                  *   If the SourceOffset or SourceOffset + Length extends beyond
1377                  *   the end of file, the server SHOULD<240> treat this as a
1378                  *   STATUS_END_OF_FILE error.
1379                  * ...
1380                  *   <240> Section 3.3.5.15.6: Windows servers will return
1381                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1382                  */
1383                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1384                 return tevent_req_post(req, ev);
1385         }
1386
1387         /* could use 2.6.33+ sendfile here to do this in kernel */
1388         while (vfs_cc_state->copied < num) {
1389                 ssize_t ret;
1390                 struct lock_struct lck;
1391                 int saved_errno;
1392
1393                 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1394                                      num - vfs_cc_state->copied);
1395
1396                 if (src_fsp->op == NULL) {
1397                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1398                         return tevent_req_post(req, ev);
1399                 }
1400                 init_strict_lock_struct(src_fsp,
1401                                         src_fsp->op->global->open_persistent_id,
1402                                         src_off,
1403                                         this_num,
1404                                         READ_LOCK,
1405                                         &lck);
1406
1407                 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1408                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1409                         return tevent_req_post(req, ev);
1410                 }
1411
1412                 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1413                                     this_num, src_off);
1414                 if (ret == -1) {
1415                         saved_errno = errno;
1416                 }
1417
1418                 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1419
1420                 if (ret == -1) {
1421                         errno = saved_errno;
1422                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1423                         return tevent_req_post(req, ev);
1424                 }
1425                 if (ret != this_num) {
1426                         /* zero tolerance for short reads */
1427                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1428                         return tevent_req_post(req, ev);
1429                 }
1430
1431                 src_off += ret;
1432
1433                 if (dest_fsp->op == NULL) {
1434                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1435                         return tevent_req_post(req, ev);
1436                 }
1437
1438                 init_strict_lock_struct(dest_fsp,
1439                                         dest_fsp->op->global->open_persistent_id,
1440                                         dest_off,
1441                                         this_num,
1442                                         WRITE_LOCK,
1443                                         &lck);
1444
1445                 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1446                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1447                         return tevent_req_post(req, ev);
1448                 }
1449
1450                 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1451                                      this_num, dest_off);
1452                 if (ret == -1) {
1453                         saved_errno = errno;
1454                 }
1455
1456                 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1457
1458                 if (ret == -1) {
1459                         errno = saved_errno;
1460                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1461                         return tevent_req_post(req, ev);
1462                 }
1463                 if (ret != this_num) {
1464                         /* zero tolerance for short writes */
1465                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1466                         return tevent_req_post(req, ev);
1467                 }
1468                 dest_off += ret;
1469
1470                 vfs_cc_state->copied += this_num;
1471         }
1472
1473         tevent_req_done(req);
1474         return tevent_req_post(req, ev);
1475 }
1476
1477 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1478                                         struct tevent_req *req,
1479                                         off_t *copied)
1480 {
1481         struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1482                                                         struct vfs_cc_state);
1483         NTSTATUS status;
1484
1485         if (tevent_req_is_nterror(req, &status)) {
1486                 DEBUG(2, ("server side copy chunk failed: %s\n",
1487                           nt_errstr(status)));
1488                 *copied = 0;
1489                 tevent_req_received(req);
1490                 return status;
1491         }
1492
1493         *copied = vfs_cc_state->copied;
1494         DEBUG(10, ("server side copy chunk copied %lu\n",
1495                    (unsigned long)*copied));
1496         tevent_req_received(req);
1497
1498         return NT_STATUS_OK;
1499 }
1500
1501 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1502                                         TALLOC_CTX *mem_ctx,
1503                                         struct files_struct *fsp,
1504                                         struct smb_filename *smb_fname,
1505                                         uint16_t *_compression_fmt)
1506 {
1507         return NT_STATUS_INVALID_DEVICE_REQUEST;
1508 }
1509
1510 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1511                                         TALLOC_CTX *mem_ctx,
1512                                         struct files_struct *fsp,
1513                                         uint16_t compression_fmt)
1514 {
1515         return NT_STATUS_INVALID_DEVICE_REQUEST;
1516 }
1517
1518 /********************************************************************
1519  Given a stat buffer return the allocated size on disk, taking into
1520  account sparse files.
1521 ********************************************************************/
1522 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1523                                        struct files_struct *fsp,
1524                                        const SMB_STRUCT_STAT *sbuf)
1525 {
1526         uint64_t result;
1527
1528         START_PROFILE(syscall_get_alloc_size);
1529
1530         if(S_ISDIR(sbuf->st_ex_mode)) {
1531                 result = 0;
1532                 goto out;
1533         }
1534
1535 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1536         /* The type of st_blocksize is blkcnt_t which *MUST* be
1537            signed (according to POSIX) and can be less than 64-bits.
1538            Ensure when we're converting to 64 bits wide we don't
1539            sign extend. */
1540 #if defined(SIZEOF_BLKCNT_T_8)
1541         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1542 #elif defined(SIZEOF_BLKCNT_T_4)
1543         {
1544                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1545                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1546         }
1547 #else
1548 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1549 #endif
1550         if (result == 0) {
1551                 /*
1552                  * Some file systems do not allocate a block for very
1553                  * small files. But for non-empty file should report a
1554                  * positive size.
1555                  */
1556
1557                 uint64_t filesize = get_file_size_stat(sbuf);
1558                 if (filesize > 0) {
1559                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1560                 }
1561         }
1562 #else
1563         result = get_file_size_stat(sbuf);
1564 #endif
1565
1566         if (fsp && fsp->initial_allocation_size)
1567                 result = MAX(result,fsp->initial_allocation_size);
1568
1569         result = smb_roundup(handle->conn, result);
1570
1571  out:
1572         END_PROFILE(syscall_get_alloc_size);
1573         return result;
1574 }
1575
1576 static int vfswrap_unlink(vfs_handle_struct *handle,
1577                           const struct smb_filename *smb_fname)
1578 {
1579         int result = -1;
1580
1581         START_PROFILE(syscall_unlink);
1582
1583         if (smb_fname->stream_name) {
1584                 errno = ENOENT;
1585                 goto out;
1586         }
1587         result = unlink(smb_fname->base_name);
1588
1589  out:
1590         END_PROFILE(syscall_unlink);
1591         return result;
1592 }
1593
1594 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1595 {
1596         int result;
1597
1598         START_PROFILE(syscall_chmod);
1599
1600         /*
1601          * We need to do this due to the fact that the default POSIX ACL
1602          * chmod modifies the ACL *mask* for the group owner, not the
1603          * group owner bits directly. JRA.
1604          */
1605
1606
1607         {
1608                 int saved_errno = errno; /* We might get ENOSYS */
1609                 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1610                         END_PROFILE(syscall_chmod);
1611                         return result;
1612                 }
1613                 /* Error - return the old errno. */
1614                 errno = saved_errno;
1615         }
1616
1617         result = chmod(path, mode);
1618         END_PROFILE(syscall_chmod);
1619         return result;
1620 }
1621
1622 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1623 {
1624         int result;
1625
1626         START_PROFILE(syscall_fchmod);
1627
1628         /*
1629          * We need to do this due to the fact that the default POSIX ACL
1630          * chmod modifies the ACL *mask* for the group owner, not the
1631          * group owner bits directly. JRA.
1632          */
1633
1634         {
1635                 int saved_errno = errno; /* We might get ENOSYS */
1636                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1637                         END_PROFILE(syscall_fchmod);
1638                         return result;
1639                 }
1640                 /* Error - return the old errno. */
1641                 errno = saved_errno;
1642         }
1643
1644 #if defined(HAVE_FCHMOD)
1645         result = fchmod(fsp->fh->fd, mode);
1646 #else
1647         result = -1;
1648         errno = ENOSYS;
1649 #endif
1650
1651         END_PROFILE(syscall_fchmod);
1652         return result;
1653 }
1654
1655 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1656 {
1657         int result;
1658
1659         START_PROFILE(syscall_chown);
1660         result = chown(path, uid, gid);
1661         END_PROFILE(syscall_chown);
1662         return result;
1663 }
1664
1665 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1666 {
1667 #ifdef HAVE_FCHOWN
1668         int result;
1669
1670         START_PROFILE(syscall_fchown);
1671         result = fchown(fsp->fh->fd, uid, gid);
1672         END_PROFILE(syscall_fchown);
1673         return result;
1674 #else
1675         errno = ENOSYS;
1676         return -1;
1677 #endif
1678 }
1679
1680 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1681 {
1682         int result;
1683
1684         START_PROFILE(syscall_lchown);
1685         result = lchown(path, uid, gid);
1686         END_PROFILE(syscall_lchown);
1687         return result;
1688 }
1689
1690 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1691 {
1692         int result;
1693
1694         START_PROFILE(syscall_chdir);
1695         result = chdir(path);
1696         END_PROFILE(syscall_chdir);
1697         return result;
1698 }
1699
1700 static char *vfswrap_getwd(vfs_handle_struct *handle)
1701 {
1702         char *result;
1703
1704         START_PROFILE(syscall_getwd);
1705         result = sys_getwd();
1706         END_PROFILE(syscall_getwd);
1707         return result;
1708 }
1709
1710 /*********************************************************************
1711  nsec timestamp resolution call. Convert down to whatever the underlying
1712  system will support.
1713 **********************************************************************/
1714
1715 static int vfswrap_ntimes(vfs_handle_struct *handle,
1716                           const struct smb_filename *smb_fname,
1717                           struct smb_file_time *ft)
1718 {
1719         int result = -1;
1720
1721         START_PROFILE(syscall_ntimes);
1722
1723         if (smb_fname->stream_name) {
1724                 errno = ENOENT;
1725                 goto out;
1726         }
1727
1728         if (ft != NULL) {
1729                 if (null_timespec(ft->atime)) {
1730                         ft->atime= smb_fname->st.st_ex_atime;
1731                 }
1732
1733                 if (null_timespec(ft->mtime)) {
1734                         ft->mtime = smb_fname->st.st_ex_mtime;
1735                 }
1736
1737                 if (!null_timespec(ft->create_time)) {
1738                         set_create_timespec_ea(handle->conn,
1739                                                smb_fname,
1740                                                ft->create_time);
1741                 }
1742
1743                 if ((timespec_compare(&ft->atime,
1744                                       &smb_fname->st.st_ex_atime) == 0) &&
1745                     (timespec_compare(&ft->mtime,
1746                                       &smb_fname->st.st_ex_mtime) == 0)) {
1747                         return 0;
1748                 }
1749         }
1750
1751 #if defined(HAVE_UTIMENSAT)
1752         if (ft != NULL) {
1753                 struct timespec ts[2];
1754                 ts[0] = ft->atime;
1755                 ts[1] = ft->mtime;
1756                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1757         } else {
1758                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1759         }
1760         if (!((result == -1) && (errno == ENOSYS))) {
1761                 goto out;
1762         }
1763 #endif
1764 #if defined(HAVE_UTIMES)
1765         if (ft != NULL) {
1766                 struct timeval tv[2];
1767                 tv[0] = convert_timespec_to_timeval(ft->atime);
1768                 tv[1] = convert_timespec_to_timeval(ft->mtime);
1769                 result = utimes(smb_fname->base_name, tv);
1770         } else {
1771                 result = utimes(smb_fname->base_name, NULL);
1772         }
1773         if (!((result == -1) && (errno == ENOSYS))) {
1774                 goto out;
1775         }
1776 #endif
1777 #if defined(HAVE_UTIME)
1778         if (ft != NULL) {
1779                 struct utimbuf times;
1780                 times.actime = convert_timespec_to_time_t(ft->atime);
1781                 times.modtime = convert_timespec_to_time_t(ft->mtime);
1782                 result = utime(smb_fname->base_name, &times);
1783         } else {
1784                 result = utime(smb_fname->base_name, NULL);
1785         }
1786         if (!((result == -1) && (errno == ENOSYS))) {
1787                 goto out;
1788         }
1789 #endif
1790         errno = ENOSYS;
1791         result = -1;
1792
1793  out:
1794         END_PROFILE(syscall_ntimes);
1795         return result;
1796 }
1797
1798 /*********************************************************************
1799  A version of ftruncate that will write the space on disk if strict
1800  allocate is set.
1801 **********************************************************************/
1802
1803 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1804 {
1805         off_t space_to_write;
1806         uint64_t space_avail;
1807         uint64_t bsize,dfree,dsize;
1808         int ret;
1809         NTSTATUS status;
1810         SMB_STRUCT_STAT *pst;
1811
1812         status = vfs_stat_fsp(fsp);
1813         if (!NT_STATUS_IS_OK(status)) {
1814                 return -1;
1815         }
1816         pst = &fsp->fsp_name->st;
1817
1818 #ifdef S_ISFIFO
1819         if (S_ISFIFO(pst->st_ex_mode))
1820                 return 0;
1821 #endif
1822
1823         if (pst->st_ex_size == len)
1824                 return 0;
1825
1826         /* Shrink - just ftruncate. */
1827         if (pst->st_ex_size > len)
1828                 return ftruncate(fsp->fh->fd, len);
1829
1830         space_to_write = len - pst->st_ex_size;
1831
1832         /* for allocation try fallocate first. This can fail on some
1833            platforms e.g. when the filesystem doesn't support it and no
1834            emulation is being done by the libc (like on AIX with JFS1). In that
1835            case we do our own emulation. fallocate implementations can
1836            return ENOTSUP or EINVAL in cases like that. */
1837         ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1838                                 pst->st_ex_size, space_to_write);
1839         if (ret == ENOSPC) {
1840                 errno = ENOSPC;
1841                 return -1;
1842         }
1843         if (ret == 0) {
1844                 return 0;
1845         }
1846         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1847                 "error %d. Falling back to slow manual allocation\n", ret));
1848
1849         /* available disk space is enough or not? */
1850         space_avail = get_dfree_info(fsp->conn,
1851                                      fsp->fsp_name->base_name, false,
1852                                      &bsize,&dfree,&dsize);
1853         /* space_avail is 1k blocks */
1854         if (space_avail == (uint64_t)-1 ||
1855                         ((uint64_t)space_to_write/1024 > space_avail) ) {
1856                 errno = ENOSPC;
1857                 return -1;
1858         }
1859
1860         /* Write out the real space on disk. */
1861         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1862         if (ret != 0) {
1863                 errno = ret;
1864                 ret = -1;
1865         }
1866
1867         return 0;
1868 }
1869
1870 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1871 {
1872         int result = -1;
1873         SMB_STRUCT_STAT *pst;
1874         NTSTATUS status;
1875         char c = 0;
1876
1877         START_PROFILE(syscall_ftruncate);
1878
1879         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1880                 result = strict_allocate_ftruncate(handle, fsp, len);
1881                 END_PROFILE(syscall_ftruncate);
1882                 return result;
1883         }
1884
1885         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1886            ftruncate if the system supports it. Then I discovered that
1887            you can have some filesystems that support ftruncate
1888            expansion and some that don't! On Linux fat can't do
1889            ftruncate extend but ext2 can. */
1890
1891         result = ftruncate(fsp->fh->fd, len);
1892         if (result == 0)
1893                 goto done;
1894
1895         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1896            extend a file with ftruncate. Provide alternate implementation
1897            for this */
1898
1899         /* Do an fstat to see if the file is longer than the requested
1900            size in which case the ftruncate above should have
1901            succeeded or shorter, in which case seek to len - 1 and
1902            write 1 byte of zero */
1903         status = vfs_stat_fsp(fsp);
1904         if (!NT_STATUS_IS_OK(status)) {
1905                 goto done;
1906         }
1907         pst = &fsp->fsp_name->st;
1908
1909 #ifdef S_ISFIFO
1910         if (S_ISFIFO(pst->st_ex_mode)) {
1911                 result = 0;
1912                 goto done;
1913         }
1914 #endif
1915
1916         if (pst->st_ex_size == len) {
1917                 result = 0;
1918                 goto done;
1919         }
1920
1921         if (pst->st_ex_size > len) {
1922                 /* the ftruncate should have worked */
1923                 goto done;
1924         }
1925
1926         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1927                 goto done;
1928         }
1929
1930         result = 0;
1931
1932   done:
1933
1934         END_PROFILE(syscall_ftruncate);
1935         return result;
1936 }
1937
1938 static int vfswrap_fallocate(vfs_handle_struct *handle,
1939                         files_struct *fsp,
1940                         enum vfs_fallocate_mode mode,
1941                         off_t offset,
1942                         off_t len)
1943 {
1944         int result;
1945
1946         START_PROFILE(syscall_fallocate);
1947         if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1948                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1949         } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1950                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1951         } else {
1952                 errno = EINVAL;
1953                 result = -1;
1954         }
1955         END_PROFILE(syscall_fallocate);
1956         return result;
1957 }
1958
1959 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1960 {
1961         bool result;
1962
1963         START_PROFILE(syscall_fcntl_lock);
1964         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
1965         END_PROFILE(syscall_fcntl_lock);
1966         return result;
1967 }
1968
1969 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1970                                 uint32 share_mode, uint32 access_mask)
1971 {
1972         START_PROFILE(syscall_kernel_flock);
1973         kernel_flock(fsp->fh->fd, share_mode, access_mask);
1974         END_PROFILE(syscall_kernel_flock);
1975         return 0;
1976 }
1977
1978 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1979 {
1980         bool result;
1981
1982         START_PROFILE(syscall_fcntl_getlock);
1983         result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1984         END_PROFILE(syscall_fcntl_getlock);
1985         return result;
1986 }
1987
1988 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1989                                 int leasetype)
1990 {
1991         int result = -1;
1992
1993         START_PROFILE(syscall_linux_setlease);
1994
1995 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1996         result = linux_setlease(fsp->fh->fd, leasetype);
1997 #else
1998         errno = ENOSYS;
1999 #endif
2000         END_PROFILE(syscall_linux_setlease);
2001         return result;
2002 }
2003
2004 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2005 {
2006         int result;
2007
2008         START_PROFILE(syscall_symlink);
2009         result = symlink(oldpath, newpath);
2010         END_PROFILE(syscall_symlink);
2011         return result;
2012 }
2013
2014 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2015 {
2016         int result;
2017
2018         START_PROFILE(syscall_readlink);
2019         result = readlink(path, buf, bufsiz);
2020         END_PROFILE(syscall_readlink);
2021         return result;
2022 }
2023
2024 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2025 {
2026         int result;
2027
2028         START_PROFILE(syscall_link);
2029         result = link(oldpath, newpath);
2030         END_PROFILE(syscall_link);
2031         return result;
2032 }
2033
2034 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2035 {
2036         int result;
2037
2038         START_PROFILE(syscall_mknod);
2039         result = sys_mknod(pathname, mode, dev);
2040         END_PROFILE(syscall_mknod);
2041         return result;
2042 }
2043
2044 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2045 {
2046         char *result;
2047
2048         START_PROFILE(syscall_realpath);
2049 #ifdef REALPATH_TAKES_NULL
2050         result = realpath(path, NULL);
2051 #else
2052         result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2053         if (result) {
2054                 char *resolved_path = realpath(path, result);
2055                 if (!resolved_path) {
2056                         SAFE_FREE(result);
2057                 } else {
2058                         /* SMB_ASSERT(result == resolved_path) ? */
2059                         result = resolved_path;
2060                 }
2061         }
2062 #endif
2063         END_PROFILE(syscall_realpath);
2064         return result;
2065 }
2066
2067 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2068                                      struct sys_notify_context *ctx,
2069                                      const char *path,
2070                                      uint32_t *filter,
2071                                      uint32_t *subdir_filter,
2072                                      void (*callback)(struct sys_notify_context *ctx, 
2073                                                       void *private_data,
2074                                                       struct notify_event *ev),
2075                                      void *private_data, void *handle)
2076 {
2077         /*
2078          * So far inotify is the only supported default notify mechanism. If
2079          * another platform like the the BSD's or a proprietary Unix comes
2080          * along and wants another default, we can play the same trick we
2081          * played with Posix ACLs.
2082          *
2083          * Until that is the case, hard-code inotify here.
2084          */
2085 #ifdef HAVE_INOTIFY
2086         if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2087                 return inotify_watch(ctx, path, filter, subdir_filter,
2088                                      callback, private_data, handle);
2089         }
2090 #endif
2091         /*
2092          * Do nothing, leave everything to notify_internal.c
2093          */
2094         return NT_STATUS_OK;
2095 }
2096
2097 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2098                            unsigned int flags)
2099 {
2100 #ifdef HAVE_CHFLAGS
2101         return chflags(path, flags);
2102 #else
2103         errno = ENOSYS;
2104         return -1;
2105 #endif
2106 }
2107
2108 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2109                                              const SMB_STRUCT_STAT *sbuf)
2110 {
2111         struct file_id key;
2112
2113         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2114          * blob */
2115         ZERO_STRUCT(key);
2116
2117         key.devid = sbuf->st_ex_dev;
2118         key.inode = sbuf->st_ex_ino;
2119         /* key.extid is unused by default. */
2120
2121         return key;
2122 }
2123
2124 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2125                                    struct files_struct *fsp,
2126                                    const char *fname,
2127                                    TALLOC_CTX *mem_ctx,
2128                                    unsigned int *pnum_streams,
2129                                    struct stream_struct **pstreams)
2130 {
2131         SMB_STRUCT_STAT sbuf;
2132         struct stream_struct *tmp_streams = NULL;
2133         int ret;
2134
2135         if ((fsp != NULL) && (fsp->is_directory)) {
2136                 /*
2137                  * No default streams on directories
2138                  */
2139                 goto done;
2140         }
2141
2142         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2143                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2144         }
2145         else {
2146                 struct smb_filename smb_fname;
2147
2148                 ZERO_STRUCT(smb_fname);
2149                 smb_fname.base_name = discard_const_p(char, fname);
2150
2151                 if (lp_posix_pathnames()) {
2152                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2153                 } else {
2154                         ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2155                 }
2156                 sbuf = smb_fname.st;
2157         }
2158
2159         if (ret == -1) {
2160                 return map_nt_error_from_unix(errno);
2161         }
2162
2163         if (S_ISDIR(sbuf.st_ex_mode)) {
2164                 goto done;
2165         }
2166
2167         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2168                                         (*pnum_streams) + 1);
2169         if (tmp_streams == NULL) {
2170                 return NT_STATUS_NO_MEMORY;
2171         }
2172         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2173         if (tmp_streams[*pnum_streams].name == NULL) {
2174                 return NT_STATUS_NO_MEMORY;
2175         }
2176         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2177         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2178
2179         *pnum_streams += 1;
2180         *pstreams = tmp_streams;
2181  done:
2182         return NT_STATUS_OK;
2183 }
2184
2185 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2186                                      const char *path,
2187                                      const char *name,
2188                                      TALLOC_CTX *mem_ctx,
2189                                      char **found_name)
2190 {
2191         /*
2192          * Don't fall back to get_real_filename so callers can differentiate
2193          * between a full directory scan and an actual case-insensitive stat.
2194          */
2195         errno = EOPNOTSUPP;
2196         return -1;
2197 }
2198
2199 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2200                                        const char *fname)
2201 {
2202         return handle->conn->connectpath;
2203 }
2204
2205 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2206                                          struct byte_range_lock *br_lck,
2207                                          struct lock_struct *plock,
2208                                          bool blocking_lock)
2209 {
2210         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2211
2212         /* Note: blr is not used in the default implementation. */
2213         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2214 }
2215
2216 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2217                                        struct messaging_context *msg_ctx,
2218                                        struct byte_range_lock *br_lck,
2219                                        const struct lock_struct *plock)
2220 {
2221         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2222
2223         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2224 }
2225
2226 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2227                                        struct byte_range_lock *br_lck,
2228                                        struct lock_struct *plock,
2229                                        struct blocking_lock_record *blr)
2230 {
2231         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2232
2233         /* Note: blr is not used in the default implementation. */
2234         return brl_lock_cancel_default(br_lck, plock);
2235 }
2236
2237 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2238                                 files_struct *fsp,
2239                                 struct lock_struct *plock)
2240 {
2241         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2242             plock->lock_type == WRITE_LOCK);
2243
2244         return strict_lock_default(fsp, plock);
2245 }
2246
2247 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2248                                 files_struct *fsp,
2249                                 struct lock_struct *plock)
2250 {
2251         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2252             plock->lock_type == WRITE_LOCK);
2253
2254         strict_unlock_default(fsp, plock);
2255 }
2256
2257 /* NT ACL operations. */
2258
2259 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2260                                     files_struct *fsp,
2261                                     uint32 security_info,
2262                                     TALLOC_CTX *mem_ctx,
2263                                     struct security_descriptor **ppdesc)
2264 {
2265         NTSTATUS result;
2266
2267         START_PROFILE(fget_nt_acl);
2268         result = posix_fget_nt_acl(fsp, security_info,
2269                                    mem_ctx, ppdesc);
2270         END_PROFILE(fget_nt_acl);
2271         return result;
2272 }
2273
2274 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2275                                    const char *name,
2276                                    uint32 security_info,
2277                                    TALLOC_CTX *mem_ctx,
2278                                    struct security_descriptor **ppdesc)
2279 {
2280         NTSTATUS result;
2281
2282         START_PROFILE(get_nt_acl);
2283         result = posix_get_nt_acl(handle->conn, name, security_info,
2284                                   mem_ctx, ppdesc);
2285         END_PROFILE(get_nt_acl);
2286         return result;
2287 }
2288
2289 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2290 {
2291         NTSTATUS result;
2292
2293         START_PROFILE(fset_nt_acl);
2294         result = set_nt_acl(fsp, security_info_sent, psd);
2295         END_PROFILE(fset_nt_acl);
2296         return result;
2297 }
2298
2299 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2300                                    struct smb_filename *file,
2301                                    struct security_acl *sacl,
2302                                    uint32_t access_requested,
2303                                    uint32_t access_denied)
2304 {
2305         return NT_STATUS_OK; /* Nothing to do here ... */
2306 }
2307
2308 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2309 {
2310 #ifdef HAVE_NO_ACL
2311         errno = ENOSYS;
2312         return -1;
2313 #else
2314         int result;
2315
2316         START_PROFILE(chmod_acl);
2317         result = chmod_acl(handle->conn, name, mode);
2318         END_PROFILE(chmod_acl);
2319         return result;
2320 #endif
2321 }
2322
2323 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2324 {
2325 #ifdef HAVE_NO_ACL
2326         errno = ENOSYS;
2327         return -1;
2328 #else
2329         int result;
2330
2331         START_PROFILE(fchmod_acl);
2332         result = fchmod_acl(fsp, mode);
2333         END_PROFILE(fchmod_acl);
2334         return result;
2335 #endif
2336 }
2337
2338 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2339                                           const char *path_p,
2340                                           SMB_ACL_TYPE_T type,
2341                                           TALLOC_CTX *mem_ctx)
2342 {
2343         return sys_acl_get_file(handle, path_p, type, mem_ctx);
2344 }
2345
2346 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2347                                         files_struct *fsp,
2348                                         TALLOC_CTX *mem_ctx)
2349 {
2350         return sys_acl_get_fd(handle, fsp, mem_ctx);
2351 }
2352
2353 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2354 {
2355         return sys_acl_set_file(handle, name, acltype, theacl);
2356 }
2357
2358 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2359 {
2360         return sys_acl_set_fd(handle, fsp, theacl);
2361 }
2362
2363 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2364 {
2365         return sys_acl_delete_def_file(handle, path);
2366 }
2367
2368 /****************************************************************
2369  Extended attribute operations.
2370 *****************************************************************/
2371
2372 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2373 {
2374         return getxattr(path, name, value, size);
2375 }
2376
2377 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2378 {
2379         return fgetxattr(fsp->fh->fd, name, value, size);
2380 }
2381
2382 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2383 {
2384         return listxattr(path, list, size);
2385 }
2386
2387 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2388 {
2389         return flistxattr(fsp->fh->fd, list, size);
2390 }
2391
2392 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2393 {
2394         return removexattr(path, name);
2395 }
2396
2397 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2398 {
2399         return fremovexattr(fsp->fh->fd, name);
2400 }
2401
2402 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2403 {
2404         return setxattr(path, name, value, size, flags);
2405 }
2406
2407 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2408 {
2409         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2410 }
2411
2412 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2413 {
2414         return false;
2415 }
2416
2417 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2418                                const struct smb_filename *fname,
2419                                SMB_STRUCT_STAT *sbuf)
2420 {
2421         NTSTATUS status;
2422         char *path;
2423         bool offline = false;
2424
2425         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2426                 return false;
2427         }
2428
2429         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2430 #if defined(ENOTSUP)
2431                 errno = ENOTSUP;
2432 #endif
2433                 return false;
2434         }
2435
2436         status = get_full_smb_filename(talloc_tos(), fname, &path);
2437         if (!NT_STATUS_IS_OK(status)) {
2438                 errno = map_errno_from_nt_status(status);
2439                 return false;
2440         }
2441
2442         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2443
2444         TALLOC_FREE(path);
2445
2446         return offline;
2447 }
2448
2449 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2450                                const struct smb_filename *fname)
2451 {
2452         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2453 #if defined(ENOTSUP)
2454         errno = ENOTSUP;
2455 #endif
2456         return -1;
2457 }
2458
2459 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2460                                        struct files_struct *fsp,
2461                                        TALLOC_CTX *mem_ctx,
2462                                        DATA_BLOB *cookie)
2463 {
2464         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2465 }
2466
2467 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2468                                            struct files_struct *fsp,
2469                                            const DATA_BLOB old_cookie,
2470                                            TALLOC_CTX *mem_ctx,
2471                                            DATA_BLOB *new_cookie)
2472 {
2473         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2474                                               new_cookie);
2475 }
2476
2477 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2478                                           struct smb_request *smb1req,
2479                                           struct smbXsrv_open *op,
2480                                           const DATA_BLOB old_cookie,
2481                                           TALLOC_CTX *mem_ctx,
2482                                           struct files_struct **fsp,
2483                                           DATA_BLOB *new_cookie)
2484 {
2485         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2486                                              old_cookie, mem_ctx,
2487                                              fsp, new_cookie);
2488 }
2489
2490 static struct vfs_fn_pointers vfs_default_fns = {
2491         /* Disk operations */
2492
2493         .connect_fn = vfswrap_connect,
2494         .disconnect_fn = vfswrap_disconnect,
2495         .disk_free_fn = vfswrap_disk_free,
2496         .get_quota_fn = vfswrap_get_quota,
2497         .set_quota_fn = vfswrap_set_quota,
2498         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2499         .statvfs_fn = vfswrap_statvfs,
2500         .fs_capabilities_fn = vfswrap_fs_capabilities,
2501         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2502
2503         /* Directory operations */
2504
2505         .opendir_fn = vfswrap_opendir,
2506         .fdopendir_fn = vfswrap_fdopendir,
2507         .readdir_fn = vfswrap_readdir,
2508         .seekdir_fn = vfswrap_seekdir,
2509         .telldir_fn = vfswrap_telldir,
2510         .rewind_dir_fn = vfswrap_rewinddir,
2511         .mkdir_fn = vfswrap_mkdir,
2512         .rmdir_fn = vfswrap_rmdir,
2513         .closedir_fn = vfswrap_closedir,
2514         .init_search_op_fn = vfswrap_init_search_op,
2515
2516         /* File operations */
2517
2518         .open_fn = vfswrap_open,
2519         .create_file_fn = vfswrap_create_file,
2520         .close_fn = vfswrap_close,
2521         .read_fn = vfswrap_read,
2522         .pread_fn = vfswrap_pread,
2523         .pread_send_fn = vfswrap_pread_send,
2524         .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2525         .write_fn = vfswrap_write,
2526         .pwrite_fn = vfswrap_pwrite,
2527         .pwrite_send_fn = vfswrap_pwrite_send,
2528         .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2529         .lseek_fn = vfswrap_lseek,
2530         .sendfile_fn = vfswrap_sendfile,
2531         .recvfile_fn = vfswrap_recvfile,
2532         .rename_fn = vfswrap_rename,
2533         .fsync_fn = vfswrap_fsync,
2534         .fsync_send_fn = vfswrap_fsync_send,
2535         .fsync_recv_fn = vfswrap_asys_int_recv,
2536         .stat_fn = vfswrap_stat,
2537         .fstat_fn = vfswrap_fstat,
2538         .lstat_fn = vfswrap_lstat,
2539         .get_alloc_size_fn = vfswrap_get_alloc_size,
2540         .unlink_fn = vfswrap_unlink,
2541         .chmod_fn = vfswrap_chmod,
2542         .fchmod_fn = vfswrap_fchmod,
2543         .chown_fn = vfswrap_chown,
2544         .fchown_fn = vfswrap_fchown,
2545         .lchown_fn = vfswrap_lchown,
2546         .chdir_fn = vfswrap_chdir,
2547         .getwd_fn = vfswrap_getwd,
2548         .ntimes_fn = vfswrap_ntimes,
2549         .ftruncate_fn = vfswrap_ftruncate,
2550         .fallocate_fn = vfswrap_fallocate,
2551         .lock_fn = vfswrap_lock,
2552         .kernel_flock_fn = vfswrap_kernel_flock,
2553         .linux_setlease_fn = vfswrap_linux_setlease,
2554         .getlock_fn = vfswrap_getlock,
2555         .symlink_fn = vfswrap_symlink,
2556         .readlink_fn = vfswrap_readlink,
2557         .link_fn = vfswrap_link,
2558         .mknod_fn = vfswrap_mknod,
2559         .realpath_fn = vfswrap_realpath,
2560         .notify_watch_fn = vfswrap_notify_watch,
2561         .chflags_fn = vfswrap_chflags,
2562         .file_id_create_fn = vfswrap_file_id_create,
2563         .streaminfo_fn = vfswrap_streaminfo,
2564         .get_real_filename_fn = vfswrap_get_real_filename,
2565         .connectpath_fn = vfswrap_connectpath,
2566         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2567         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2568         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2569         .strict_lock_fn = vfswrap_strict_lock,
2570         .strict_unlock_fn = vfswrap_strict_unlock,
2571         .translate_name_fn = vfswrap_translate_name,
2572         .fsctl_fn = vfswrap_fsctl,
2573         .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2574         .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2575         .get_compression_fn = vfswrap_get_compression,
2576         .set_compression_fn = vfswrap_set_compression,
2577
2578         /* NT ACL operations. */
2579
2580         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2581         .get_nt_acl_fn = vfswrap_get_nt_acl,
2582         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2583         .audit_file_fn = vfswrap_audit_file,
2584
2585         /* POSIX ACL operations. */
2586
2587         .chmod_acl_fn = vfswrap_chmod_acl,
2588         .fchmod_acl_fn = vfswrap_fchmod_acl,
2589
2590         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2591         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2592         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2593         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2594         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2595         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2596         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2597
2598         /* EA operations. */
2599         .getxattr_fn = vfswrap_getxattr,
2600         .fgetxattr_fn = vfswrap_fgetxattr,
2601         .listxattr_fn = vfswrap_listxattr,
2602         .flistxattr_fn = vfswrap_flistxattr,
2603         .removexattr_fn = vfswrap_removexattr,
2604         .fremovexattr_fn = vfswrap_fremovexattr,
2605         .setxattr_fn = vfswrap_setxattr,
2606         .fsetxattr_fn = vfswrap_fsetxattr,
2607
2608         /* aio operations */
2609         .aio_force_fn = vfswrap_aio_force,
2610
2611         /* offline operations */
2612         .is_offline_fn = vfswrap_is_offline,
2613         .set_offline_fn = vfswrap_set_offline,
2614
2615         /* durable handle operations */
2616         .durable_cookie_fn = vfswrap_durable_cookie,
2617         .durable_disconnect_fn = vfswrap_durable_disconnect,
2618         .durable_reconnect_fn = vfswrap_durable_reconnect,
2619 };
2620
2621 NTSTATUS vfs_default_init(void);
2622 NTSTATUS vfs_default_init(void)
2623 {
2624         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2625                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
2626 }
2627
2628