vfs: propagate snapshot enumeration errors
[kai/samba-autobuild/.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 tevent_req *req;
797         struct vfswrap_asys_state *state;
798         int res;
799         ssize_t ret;
800         int err;
801         void *private_data;
802
803         if ((flags & TEVENT_FD_READ) == 0) {
804                 return;
805         }
806
807         while (true) {
808                 res = asys_result(asys_ctx, &ret, &err, &private_data);
809                 if (res == EINTR || res == EAGAIN) {
810                         return;
811                 }
812 #ifdef EWOULDBLOCK
813                 if (res == EWOULDBLOCK) {
814                         return;
815                 }
816 #endif
817
818                 if (res == ECANCELED) {
819                         return;
820                 }
821
822                 if (res != 0) {
823                         DEBUG(1, ("asys_result returned %s\n", strerror(res)));
824                         return;
825                 }
826
827                 req = talloc_get_type_abort(private_data, struct tevent_req);
828                 state = tevent_req_data(req, struct vfswrap_asys_state);
829
830                 talloc_set_destructor(state, NULL);
831
832                 state->ret = ret;
833                 state->err = err;
834                 tevent_req_defer_callback(req, ev);
835                 tevent_req_done(req);
836         }
837 }
838
839 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
840 {
841         struct vfswrap_asys_state *state = tevent_req_data(
842                 req, struct vfswrap_asys_state);
843
844         if (tevent_req_is_unix_error(req, err)) {
845                 return -1;
846         }
847         *err = state->err;
848         return state->ret;
849 }
850
851 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
852 {
853         struct vfswrap_asys_state *state = tevent_req_data(
854                 req, struct vfswrap_asys_state);
855
856         if (tevent_req_is_unix_error(req, err)) {
857                 return -1;
858         }
859         *err = state->err;
860         return state->ret;
861 }
862
863 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
864 {
865         off_t result = 0;
866
867         START_PROFILE(syscall_lseek);
868
869         /* Cope with 'stat' file opens. */
870         if (fsp->fh->fd != -1)
871                 result = lseek(fsp->fh->fd, offset, whence);
872
873         /*
874          * We want to maintain the fiction that we can seek
875          * on a fifo for file system purposes. This allows
876          * people to set up UNIX fifo's that feed data to Windows
877          * applications. JRA.
878          */
879
880         if((result == -1) && (errno == ESPIPE)) {
881                 result = 0;
882                 errno = 0;
883         }
884
885         END_PROFILE(syscall_lseek);
886         return result;
887 }
888
889 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
890                         off_t offset, size_t n)
891 {
892         ssize_t result;
893
894         START_PROFILE_BYTES(syscall_sendfile, n);
895         result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
896         END_PROFILE(syscall_sendfile);
897         return result;
898 }
899
900 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
901                         int fromfd,
902                         files_struct *tofsp,
903                         off_t offset,
904                         size_t n)
905 {
906         ssize_t result;
907
908         START_PROFILE_BYTES(syscall_recvfile, n);
909         result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
910         END_PROFILE(syscall_recvfile);
911         return result;
912 }
913
914 static int vfswrap_rename(vfs_handle_struct *handle,
915                           const struct smb_filename *smb_fname_src,
916                           const struct smb_filename *smb_fname_dst)
917 {
918         int result = -1;
919
920         START_PROFILE(syscall_rename);
921
922         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
923                 errno = ENOENT;
924                 goto out;
925         }
926
927         result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
928
929  out:
930         END_PROFILE(syscall_rename);
931         return result;
932 }
933
934 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
935 {
936 #ifdef HAVE_FSYNC
937         int result;
938
939         START_PROFILE(syscall_fsync);
940         result = fsync(fsp->fh->fd);
941         END_PROFILE(syscall_fsync);
942         return result;
943 #else
944         return 0;
945 #endif
946 }
947
948 static int vfswrap_stat(vfs_handle_struct *handle,
949                         struct smb_filename *smb_fname)
950 {
951         int result = -1;
952
953         START_PROFILE(syscall_stat);
954
955         if (smb_fname->stream_name) {
956                 errno = ENOENT;
957                 goto out;
958         }
959
960         result = sys_stat(smb_fname->base_name, &smb_fname->st,
961                           lp_fake_directory_create_times(SNUM(handle->conn)));
962  out:
963         END_PROFILE(syscall_stat);
964         return result;
965 }
966
967 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
968 {
969         int result;
970
971         START_PROFILE(syscall_fstat);
972         result = sys_fstat(fsp->fh->fd,
973                            sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
974         END_PROFILE(syscall_fstat);
975         return result;
976 }
977
978 static int vfswrap_lstat(vfs_handle_struct *handle,
979                          struct smb_filename *smb_fname)
980 {
981         int result = -1;
982
983         START_PROFILE(syscall_lstat);
984
985         if (smb_fname->stream_name) {
986                 errno = ENOENT;
987                 goto out;
988         }
989
990         result = sys_lstat(smb_fname->base_name, &smb_fname->st,
991                            lp_fake_directory_create_times(SNUM(handle->conn)));
992  out:
993         END_PROFILE(syscall_lstat);
994         return result;
995 }
996
997 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
998                                        const char *name,
999                                        enum vfs_translate_direction direction,
1000                                        TALLOC_CTX *mem_ctx,
1001                                        char **mapped_name)
1002 {
1003         return NT_STATUS_NONE_MAPPED;
1004 }
1005
1006 /*
1007  * Implement the default fsctl operation.
1008  */
1009 static bool vfswrap_logged_ioctl_message = false;
1010
1011 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1012                               struct files_struct *fsp,
1013                               TALLOC_CTX *ctx,
1014                               uint32_t function,
1015                               uint16_t req_flags, /* Needed for UNICODE ... */
1016                               const uint8_t *_in_data,
1017                               uint32_t in_len,
1018                               uint8_t **_out_data,
1019                               uint32_t max_out_len,
1020                               uint32_t *out_len)
1021 {
1022         const char *in_data = (const char *)_in_data;
1023         char **out_data = (char **)_out_data;
1024         NTSTATUS status;
1025
1026         switch (function) {
1027         case FSCTL_SET_SPARSE:
1028         {
1029                 bool set_sparse = true;
1030
1031                 if (in_len >= 1 && in_data[0] == 0) {
1032                         set_sparse = false;
1033                 }
1034
1035                 status = file_set_sparse(handle->conn, fsp, set_sparse);
1036
1037                 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1038                       ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1039                        smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1040                        nt_errstr(status)));
1041
1042                 return status;
1043         }
1044
1045         case FSCTL_CREATE_OR_GET_OBJECT_ID:
1046         {
1047                 unsigned char objid[16];
1048                 char *return_data = NULL;
1049
1050                 /* This should return the object-id on this file.
1051                  * I think I'll make this be the inode+dev. JRA.
1052                  */
1053
1054                 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1055                           fsp_fnum_dbg(fsp)));
1056
1057                 *out_len = MIN(max_out_len, 64);
1058
1059                 /* Hmmm, will this cause problems if less data asked for? */
1060                 return_data = talloc_array(ctx, char, 64);
1061                 if (return_data == NULL) {
1062                         return NT_STATUS_NO_MEMORY;
1063                 }
1064
1065                 /* For backwards compatibility only store the dev/inode. */
1066                 push_file_id_16(return_data, &fsp->file_id);
1067                 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1068                 push_file_id_16(return_data+32, &fsp->file_id);
1069                 memset(return_data+48, 0, 16);
1070                 *out_data = return_data;
1071                 return NT_STATUS_OK;
1072         }
1073
1074         case FSCTL_GET_REPARSE_POINT:
1075         {
1076                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1077                 DEBUG(10, ("FSCTL_GET_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_SET_REPARSE_POINT:
1083         {
1084                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1085                 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1086                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1087                 return NT_STATUS_NOT_A_REPARSE_POINT;
1088         }
1089
1090         case FSCTL_GET_SHADOW_COPY_DATA:
1091         {
1092                 /*
1093                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1094                  * and return their volume names.  If max_data_count is 16, then it is just
1095                  * asking for the number of volumes and length of the combined names.
1096                  *
1097                  * pdata is the data allocated by our caller, but that uses
1098                  * total_data_count (which is 0 in our case) rather than max_data_count.
1099                  * Allocate the correct amount and return the pointer to let
1100                  * it be deallocated when we return.
1101                  */
1102                 struct shadow_copy_data *shadow_data = NULL;
1103                 bool labels = False;
1104                 uint32 labels_data_count = 0;
1105                 uint32 i;
1106                 char *cur_pdata = NULL;
1107
1108                 if (max_out_len < 16) {
1109                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1110                                 max_out_len));
1111                         return NT_STATUS_INVALID_PARAMETER;
1112                 }
1113
1114                 if (max_out_len > 16) {
1115                         labels = True;
1116                 }
1117
1118                 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1119                 if (shadow_data == NULL) {
1120                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
1121                         return NT_STATUS_NO_MEMORY;
1122                 }
1123
1124                 /*
1125                  * Call the VFS routine to actually do the work.
1126                  */
1127                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1128                         int log_lev = 0;
1129                         if (errno == 0) {
1130                                 /* broken module didn't set errno on error */
1131                                 status = NT_STATUS_UNSUCCESSFUL;
1132                         } else {
1133                                 status = map_nt_error_from_unix(errno);
1134                                 if (NT_STATUS_EQUAL(status,
1135                                                     NT_STATUS_NOT_SUPPORTED)) {
1136                                         log_lev = 5;
1137                                 }
1138                         }
1139                         DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1140                                         "connectpath %s, failed - %s.\n",
1141                                         fsp->conn->connectpath,
1142                                         nt_errstr(status)));
1143                         TALLOC_FREE(shadow_data);
1144                         return status;
1145                 }
1146
1147                 labels_data_count = (shadow_data->num_volumes * 2 *
1148                                         sizeof(SHADOW_COPY_LABEL)) + 2;
1149
1150                 if (!labels) {
1151                         *out_len = 16;
1152                 } else {
1153                         *out_len = 12 + labels_data_count;
1154                 }
1155
1156                 if (max_out_len < *out_len) {
1157                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1158                                 max_out_len, *out_len));
1159                         TALLOC_FREE(shadow_data);
1160                         return NT_STATUS_BUFFER_TOO_SMALL;
1161                 }
1162
1163                 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1164                 if (cur_pdata == NULL) {
1165                         TALLOC_FREE(shadow_data);
1166                         return NT_STATUS_NO_MEMORY;
1167                 }
1168
1169                 *out_data = cur_pdata;
1170
1171                 /* num_volumes 4 bytes */
1172                 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1173
1174                 if (labels) {
1175                         /* num_labels 4 bytes */
1176                         SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1177                 }
1178
1179                 /* needed_data_count 4 bytes */
1180                 SIVAL(cur_pdata, 8, labels_data_count);
1181
1182                 cur_pdata += 12;
1183
1184                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1185                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
1186                 if (labels && shadow_data->labels) {
1187                         for (i=0; i<shadow_data->num_volumes; i++) {
1188                                 srvstr_push(cur_pdata, req_flags,
1189                                             cur_pdata, shadow_data->labels[i],
1190                                             2 * sizeof(SHADOW_COPY_LABEL),
1191                                             STR_UNICODE|STR_TERMINATE);
1192                                 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1193                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1194                         }
1195                 }
1196
1197                 TALLOC_FREE(shadow_data);
1198
1199                 return NT_STATUS_OK;
1200         }
1201
1202         case FSCTL_FIND_FILES_BY_SID:
1203         {
1204                 /* pretend this succeeded -
1205                  *
1206                  * we have to send back a list with all files owned by this SID
1207                  *
1208                  * but I have to check that --metze
1209                  */
1210                 struct dom_sid sid;
1211                 uid_t uid;
1212                 size_t sid_len;
1213
1214                 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1215                            fsp_fnum_dbg(fsp)));
1216
1217                 if (in_len < 8) {
1218                         /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1219                         return NT_STATUS_INVALID_PARAMETER;
1220                 }
1221
1222                 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1223
1224                 /* unknown 4 bytes: this is not the length of the sid :-(  */
1225                 /*unknown = IVAL(pdata,0);*/
1226
1227                 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1228                         return NT_STATUS_INVALID_PARAMETER;
1229                 }
1230                 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1231
1232                 if (!sid_to_uid(&sid, &uid)) {
1233                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1234                                  sid_string_dbg(&sid),
1235                                  (unsigned long)sid_len));
1236                         uid = (-1);
1237                 }
1238
1239                 /* we can take a look at the find source :-)
1240                  *
1241                  * find ./ -uid $uid  -name '*'   is what we need here
1242                  *
1243                  *
1244                  * and send 4bytes len and then NULL terminated unicode strings
1245                  * for each file
1246                  *
1247                  * but I don't know how to deal with the paged results
1248                  * (maybe we can hang the result anywhere in the fsp struct)
1249                  *
1250                  * but I don't know how to deal with the paged results
1251                  * (maybe we can hang the result anywhere in the fsp struct)
1252                  *
1253                  * we don't send all files at once
1254                  * and at the next we should *not* start from the beginning,
1255                  * so we have to cache the result
1256                  *
1257                  * --metze
1258                  */
1259
1260                 /* this works for now... */
1261                 return NT_STATUS_OK;
1262         }
1263
1264         case FSCTL_QUERY_ALLOCATED_RANGES:
1265         {
1266                 /* FIXME: This is just a dummy reply, telling that all of the
1267                  * file is allocated. MKS cp needs that.
1268                  * Adding the real allocated ranges via FIEMAP on Linux
1269                  * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1270                  * this FSCTL correct for sparse files.
1271                  */
1272                 uint64_t offset, length;
1273                 char *out_data_tmp = NULL;
1274
1275                 if (in_len != 16) {
1276                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1277                                 in_len));
1278                         return NT_STATUS_INVALID_PARAMETER;
1279                 }
1280
1281                 if (max_out_len < 16) {
1282                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1283                                 max_out_len));
1284                         return NT_STATUS_INVALID_PARAMETER;
1285                 }
1286
1287                 offset = BVAL(in_data,0);
1288                 length = BVAL(in_data,8);
1289
1290                 if (offset + length < offset) {
1291                         /* No 64-bit integer wrap. */
1292                         return NT_STATUS_INVALID_PARAMETER;
1293                 }
1294
1295                 /* Shouldn't this be SMB_VFS_STAT ... ? */
1296                 status = vfs_stat_fsp(fsp);
1297                 if (!NT_STATUS_IS_OK(status)) {
1298                         return status;
1299                 }
1300
1301                 *out_len = 16;
1302                 out_data_tmp = talloc_array(ctx, char, *out_len);
1303                 if (out_data_tmp == NULL) {
1304                         DEBUG(10, ("unable to allocate memory for response\n"));
1305                         return NT_STATUS_NO_MEMORY;
1306                 }
1307
1308                 if (offset > fsp->fsp_name->st.st_ex_size ||
1309                                 fsp->fsp_name->st.st_ex_size == 0 ||
1310                                 length == 0) {
1311                         memset(out_data_tmp, 0, *out_len);
1312                 } else {
1313                         uint64_t end = offset + length;
1314                         end = MIN(end, fsp->fsp_name->st.st_ex_size);
1315                         SBVAL(out_data_tmp, 0, 0);
1316                         SBVAL(out_data_tmp, 8, end);
1317                 }
1318
1319                 *out_data = out_data_tmp;
1320
1321                 return NT_STATUS_OK;
1322         }
1323
1324         case FSCTL_IS_VOLUME_DIRTY:
1325         {
1326                 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1327                           "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1328                 /*
1329                  * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1330                  * says we have to respond with NT_STATUS_INVALID_PARAMETER
1331                  */
1332                 return NT_STATUS_INVALID_PARAMETER;
1333         }
1334
1335         default:
1336                 /*
1337                  * Only print once ... unfortunately there could be lots of
1338                  * different FSCTLs that are called.
1339                  */
1340                 if (!vfswrap_logged_ioctl_message) {
1341                         vfswrap_logged_ioctl_message = true;
1342                         DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1343                         __func__, function));
1344                 }
1345         }
1346
1347         return NT_STATUS_NOT_SUPPORTED;
1348 }
1349
1350 struct vfs_cc_state {
1351         off_t copied;
1352         uint8_t buf[65536];
1353 };
1354
1355 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1356                                                   TALLOC_CTX *mem_ctx,
1357                                                   struct tevent_context *ev,
1358                                                   struct files_struct *src_fsp,
1359                                                   off_t src_off,
1360                                                   struct files_struct *dest_fsp,
1361                                                   off_t dest_off,
1362                                                   off_t num)
1363 {
1364         struct tevent_req *req;
1365         struct vfs_cc_state *vfs_cc_state;
1366         NTSTATUS status;
1367
1368         DEBUG(10, ("performing server side copy chunk of length %lu\n",
1369                    (unsigned long)num));
1370
1371         req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1372         if (req == NULL) {
1373                 return NULL;
1374         }
1375
1376         status = vfs_stat_fsp(src_fsp);
1377         if (tevent_req_nterror(req, status)) {
1378                 return tevent_req_post(req, ev);
1379         }
1380
1381         if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1382                 /*
1383                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1384                  *   If the SourceOffset or SourceOffset + Length extends beyond
1385                  *   the end of file, the server SHOULD<240> treat this as a
1386                  *   STATUS_END_OF_FILE error.
1387                  * ...
1388                  *   <240> Section 3.3.5.15.6: Windows servers will return
1389                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1390                  */
1391                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1392                 return tevent_req_post(req, ev);
1393         }
1394
1395         /* could use 2.6.33+ sendfile here to do this in kernel */
1396         while (vfs_cc_state->copied < num) {
1397                 ssize_t ret;
1398                 struct lock_struct lck;
1399                 int saved_errno;
1400
1401                 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1402                                      num - vfs_cc_state->copied);
1403
1404                 init_strict_lock_struct(src_fsp,
1405                                         src_fsp->op->global->open_persistent_id,
1406                                         src_off,
1407                                         this_num,
1408                                         READ_LOCK,
1409                                         &lck);
1410
1411                 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1412                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1413                         return tevent_req_post(req, ev);
1414                 }
1415
1416                 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1417                                     this_num, src_off);
1418                 if (ret == -1) {
1419                         saved_errno = errno;
1420                 }
1421
1422                 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1423
1424                 if (ret == -1) {
1425                         errno = saved_errno;
1426                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1427                         return tevent_req_post(req, ev);
1428                 }
1429                 if (ret != this_num) {
1430                         /* zero tolerance for short reads */
1431                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1432                         return tevent_req_post(req, ev);
1433                 }
1434
1435                 src_off += ret;
1436
1437                 init_strict_lock_struct(dest_fsp,
1438                                         dest_fsp->op->global->open_persistent_id,
1439                                         dest_off,
1440                                         this_num,
1441                                         WRITE_LOCK,
1442                                         &lck);
1443
1444                 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1445                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1446                         return tevent_req_post(req, ev);
1447                 }
1448
1449                 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1450                                      this_num, dest_off);
1451                 if (ret == -1) {
1452                         saved_errno = errno;
1453                 }
1454
1455                 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1456
1457                 if (ret == -1) {
1458                         errno = saved_errno;
1459                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1460                         return tevent_req_post(req, ev);
1461                 }
1462                 if (ret != this_num) {
1463                         /* zero tolerance for short writes */
1464                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1465                         return tevent_req_post(req, ev);
1466                 }
1467                 dest_off += ret;
1468
1469                 vfs_cc_state->copied += this_num;
1470         }
1471
1472         tevent_req_done(req);
1473         return tevent_req_post(req, ev);
1474 }
1475
1476 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1477                                         struct tevent_req *req,
1478                                         off_t *copied)
1479 {
1480         struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1481                                                         struct vfs_cc_state);
1482         NTSTATUS status;
1483
1484         if (tevent_req_is_nterror(req, &status)) {
1485                 DEBUG(2, ("server side copy chunk failed: %s\n",
1486                           nt_errstr(status)));
1487                 *copied = 0;
1488                 tevent_req_received(req);
1489                 return status;
1490         }
1491
1492         *copied = vfs_cc_state->copied;
1493         DEBUG(10, ("server side copy chunk copied %lu\n",
1494                    (unsigned long)*copied));
1495         tevent_req_received(req);
1496
1497         return NT_STATUS_OK;
1498 }
1499
1500 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1501                                         TALLOC_CTX *mem_ctx,
1502                                         struct files_struct *fsp,
1503                                         struct smb_filename *smb_fname,
1504                                         uint16_t *_compression_fmt)
1505 {
1506         return NT_STATUS_INVALID_DEVICE_REQUEST;
1507 }
1508
1509 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1510                                         TALLOC_CTX *mem_ctx,
1511                                         struct files_struct *fsp,
1512                                         uint16_t compression_fmt)
1513 {
1514         return NT_STATUS_INVALID_DEVICE_REQUEST;
1515 }
1516
1517 /********************************************************************
1518  Given a stat buffer return the allocated size on disk, taking into
1519  account sparse files.
1520 ********************************************************************/
1521 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1522                                        struct files_struct *fsp,
1523                                        const SMB_STRUCT_STAT *sbuf)
1524 {
1525         uint64_t result;
1526
1527         START_PROFILE(syscall_get_alloc_size);
1528
1529         if(S_ISDIR(sbuf->st_ex_mode)) {
1530                 result = 0;
1531                 goto out;
1532         }
1533
1534 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1535         /* The type of st_blocksize is blkcnt_t which *MUST* be
1536            signed (according to POSIX) and can be less than 64-bits.
1537            Ensure when we're converting to 64 bits wide we don't
1538            sign extend. */
1539 #if defined(SIZEOF_BLKCNT_T_8)
1540         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1541 #elif defined(SIZEOF_BLKCNT_T_4)
1542         {
1543                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1544                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1545         }
1546 #else
1547 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1548 #endif
1549 #else
1550         result = get_file_size_stat(sbuf);
1551 #endif
1552
1553         if (fsp && fsp->initial_allocation_size)
1554                 result = MAX(result,fsp->initial_allocation_size);
1555
1556         result = smb_roundup(handle->conn, result);
1557
1558  out:
1559         END_PROFILE(syscall_get_alloc_size);
1560         return result;
1561 }
1562
1563 static int vfswrap_unlink(vfs_handle_struct *handle,
1564                           const struct smb_filename *smb_fname)
1565 {
1566         int result = -1;
1567
1568         START_PROFILE(syscall_unlink);
1569
1570         if (smb_fname->stream_name) {
1571                 errno = ENOENT;
1572                 goto out;
1573         }
1574         result = unlink(smb_fname->base_name);
1575
1576  out:
1577         END_PROFILE(syscall_unlink);
1578         return result;
1579 }
1580
1581 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1582 {
1583         int result;
1584
1585         START_PROFILE(syscall_chmod);
1586
1587         /*
1588          * We need to do this due to the fact that the default POSIX ACL
1589          * chmod modifies the ACL *mask* for the group owner, not the
1590          * group owner bits directly. JRA.
1591          */
1592
1593
1594         {
1595                 int saved_errno = errno; /* We might get ENOSYS */
1596                 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1597                         END_PROFILE(syscall_chmod);
1598                         return result;
1599                 }
1600                 /* Error - return the old errno. */
1601                 errno = saved_errno;
1602         }
1603
1604         result = chmod(path, mode);
1605         END_PROFILE(syscall_chmod);
1606         return result;
1607 }
1608
1609 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1610 {
1611         int result;
1612
1613         START_PROFILE(syscall_fchmod);
1614
1615         /*
1616          * We need to do this due to the fact that the default POSIX ACL
1617          * chmod modifies the ACL *mask* for the group owner, not the
1618          * group owner bits directly. JRA.
1619          */
1620
1621         {
1622                 int saved_errno = errno; /* We might get ENOSYS */
1623                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1624                         END_PROFILE(syscall_fchmod);
1625                         return result;
1626                 }
1627                 /* Error - return the old errno. */
1628                 errno = saved_errno;
1629         }
1630
1631 #if defined(HAVE_FCHMOD)
1632         result = fchmod(fsp->fh->fd, mode);
1633 #else
1634         result = -1;
1635         errno = ENOSYS;
1636 #endif
1637
1638         END_PROFILE(syscall_fchmod);
1639         return result;
1640 }
1641
1642 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1643 {
1644         int result;
1645
1646         START_PROFILE(syscall_chown);
1647         result = chown(path, uid, gid);
1648         END_PROFILE(syscall_chown);
1649         return result;
1650 }
1651
1652 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1653 {
1654 #ifdef HAVE_FCHOWN
1655         int result;
1656
1657         START_PROFILE(syscall_fchown);
1658         result = fchown(fsp->fh->fd, uid, gid);
1659         END_PROFILE(syscall_fchown);
1660         return result;
1661 #else
1662         errno = ENOSYS;
1663         return -1;
1664 #endif
1665 }
1666
1667 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1668 {
1669         int result;
1670
1671         START_PROFILE(syscall_lchown);
1672         result = lchown(path, uid, gid);
1673         END_PROFILE(syscall_lchown);
1674         return result;
1675 }
1676
1677 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1678 {
1679         int result;
1680
1681         START_PROFILE(syscall_chdir);
1682         result = chdir(path);
1683         END_PROFILE(syscall_chdir);
1684         return result;
1685 }
1686
1687 static char *vfswrap_getwd(vfs_handle_struct *handle)
1688 {
1689         char *result;
1690
1691         START_PROFILE(syscall_getwd);
1692         result = sys_getwd();
1693         END_PROFILE(syscall_getwd);
1694         return result;
1695 }
1696
1697 /*********************************************************************
1698  nsec timestamp resolution call. Convert down to whatever the underlying
1699  system will support.
1700 **********************************************************************/
1701
1702 static int vfswrap_ntimes(vfs_handle_struct *handle,
1703                           const struct smb_filename *smb_fname,
1704                           struct smb_file_time *ft)
1705 {
1706         int result = -1;
1707
1708         START_PROFILE(syscall_ntimes);
1709
1710         if (smb_fname->stream_name) {
1711                 errno = ENOENT;
1712                 goto out;
1713         }
1714
1715         if (ft != NULL) {
1716                 if (null_timespec(ft->atime)) {
1717                         ft->atime= smb_fname->st.st_ex_atime;
1718                 }
1719
1720                 if (null_timespec(ft->mtime)) {
1721                         ft->mtime = smb_fname->st.st_ex_mtime;
1722                 }
1723
1724                 if (!null_timespec(ft->create_time)) {
1725                         set_create_timespec_ea(handle->conn,
1726                                                smb_fname,
1727                                                ft->create_time);
1728                 }
1729
1730                 if ((timespec_compare(&ft->atime,
1731                                       &smb_fname->st.st_ex_atime) == 0) &&
1732                     (timespec_compare(&ft->mtime,
1733                                       &smb_fname->st.st_ex_mtime) == 0)) {
1734                         return 0;
1735                 }
1736         }
1737
1738 #if defined(HAVE_UTIMENSAT)
1739         if (ft != NULL) {
1740                 struct timespec ts[2];
1741                 ts[0] = ft->atime;
1742                 ts[1] = ft->mtime;
1743                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1744         } else {
1745                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1746         }
1747         if (!((result == -1) && (errno == ENOSYS))) {
1748                 goto out;
1749         }
1750 #endif
1751 #if defined(HAVE_UTIMES)
1752         if (ft != NULL) {
1753                 struct timeval tv[2];
1754                 tv[0] = convert_timespec_to_timeval(ft->atime);
1755                 tv[1] = convert_timespec_to_timeval(ft->mtime);
1756                 result = utimes(smb_fname->base_name, tv);
1757         } else {
1758                 result = utimes(smb_fname->base_name, NULL);
1759         }
1760         if (!((result == -1) && (errno == ENOSYS))) {
1761                 goto out;
1762         }
1763 #endif
1764 #if defined(HAVE_UTIME)
1765         if (ft != NULL) {
1766                 struct utimbuf times;
1767                 times.actime = convert_timespec_to_time_t(ft->atime);
1768                 times.modtime = convert_timespec_to_time_t(ft->mtime);
1769                 result = utime(smb_fname->base_name, &times);
1770         } else {
1771                 result = utime(smb_fname->base_name, NULL);
1772         }
1773         if (!((result == -1) && (errno == ENOSYS))) {
1774                 goto out;
1775         }
1776 #endif
1777         errno = ENOSYS;
1778         result = -1;
1779
1780  out:
1781         END_PROFILE(syscall_ntimes);
1782         return result;
1783 }
1784
1785 /*********************************************************************
1786  A version of ftruncate that will write the space on disk if strict
1787  allocate is set.
1788 **********************************************************************/
1789
1790 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1791 {
1792         off_t space_to_write;
1793         uint64_t space_avail;
1794         uint64_t bsize,dfree,dsize;
1795         int ret;
1796         NTSTATUS status;
1797         SMB_STRUCT_STAT *pst;
1798
1799         status = vfs_stat_fsp(fsp);
1800         if (!NT_STATUS_IS_OK(status)) {
1801                 return -1;
1802         }
1803         pst = &fsp->fsp_name->st;
1804
1805 #ifdef S_ISFIFO
1806         if (S_ISFIFO(pst->st_ex_mode))
1807                 return 0;
1808 #endif
1809
1810         if (pst->st_ex_size == len)
1811                 return 0;
1812
1813         /* Shrink - just ftruncate. */
1814         if (pst->st_ex_size > len)
1815                 return ftruncate(fsp->fh->fd, len);
1816
1817         space_to_write = len - pst->st_ex_size;
1818
1819         /* for allocation try fallocate first. This can fail on some
1820            platforms e.g. when the filesystem doesn't support it and no
1821            emulation is being done by the libc (like on AIX with JFS1). In that
1822            case we do our own emulation. fallocate implementations can
1823            return ENOTSUP or EINVAL in cases like that. */
1824         ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1825                                 pst->st_ex_size, space_to_write);
1826         if (ret == ENOSPC) {
1827                 errno = ENOSPC;
1828                 return -1;
1829         }
1830         if (ret == 0) {
1831                 return 0;
1832         }
1833         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1834                 "error %d. Falling back to slow manual allocation\n", ret));
1835
1836         /* available disk space is enough or not? */
1837         space_avail = get_dfree_info(fsp->conn,
1838                                      fsp->fsp_name->base_name, false,
1839                                      &bsize,&dfree,&dsize);
1840         /* space_avail is 1k blocks */
1841         if (space_avail == (uint64_t)-1 ||
1842                         ((uint64_t)space_to_write/1024 > space_avail) ) {
1843                 errno = ENOSPC;
1844                 return -1;
1845         }
1846
1847         /* Write out the real space on disk. */
1848         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1849         if (ret != 0) {
1850                 errno = ret;
1851                 ret = -1;
1852         }
1853
1854         return 0;
1855 }
1856
1857 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1858 {
1859         int result = -1;
1860         SMB_STRUCT_STAT *pst;
1861         NTSTATUS status;
1862         char c = 0;
1863
1864         START_PROFILE(syscall_ftruncate);
1865
1866         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1867                 result = strict_allocate_ftruncate(handle, fsp, len);
1868                 END_PROFILE(syscall_ftruncate);
1869                 return result;
1870         }
1871
1872         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1873            ftruncate if the system supports it. Then I discovered that
1874            you can have some filesystems that support ftruncate
1875            expansion and some that don't! On Linux fat can't do
1876            ftruncate extend but ext2 can. */
1877
1878         result = ftruncate(fsp->fh->fd, len);
1879         if (result == 0)
1880                 goto done;
1881
1882         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1883            extend a file with ftruncate. Provide alternate implementation
1884            for this */
1885
1886         /* Do an fstat to see if the file is longer than the requested
1887            size in which case the ftruncate above should have
1888            succeeded or shorter, in which case seek to len - 1 and
1889            write 1 byte of zero */
1890         status = vfs_stat_fsp(fsp);
1891         if (!NT_STATUS_IS_OK(status)) {
1892                 goto done;
1893         }
1894         pst = &fsp->fsp_name->st;
1895
1896 #ifdef S_ISFIFO
1897         if (S_ISFIFO(pst->st_ex_mode)) {
1898                 result = 0;
1899                 goto done;
1900         }
1901 #endif
1902
1903         if (pst->st_ex_size == len) {
1904                 result = 0;
1905                 goto done;
1906         }
1907
1908         if (pst->st_ex_size > len) {
1909                 /* the ftruncate should have worked */
1910                 goto done;
1911         }
1912
1913         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1914                 goto done;
1915         }
1916
1917         result = 0;
1918
1919   done:
1920
1921         END_PROFILE(syscall_ftruncate);
1922         return result;
1923 }
1924
1925 static int vfswrap_fallocate(vfs_handle_struct *handle,
1926                         files_struct *fsp,
1927                         enum vfs_fallocate_mode mode,
1928                         off_t offset,
1929                         off_t len)
1930 {
1931         int result;
1932
1933         START_PROFILE(syscall_fallocate);
1934         if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1935                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1936         } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1937                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1938         } else {
1939                 errno = EINVAL;
1940                 result = -1;
1941         }
1942         END_PROFILE(syscall_fallocate);
1943         return result;
1944 }
1945
1946 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1947 {
1948         bool result;
1949
1950         START_PROFILE(syscall_fcntl_lock);
1951         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
1952         END_PROFILE(syscall_fcntl_lock);
1953         return result;
1954 }
1955
1956 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1957                                 uint32 share_mode, uint32 access_mask)
1958 {
1959         START_PROFILE(syscall_kernel_flock);
1960         kernel_flock(fsp->fh->fd, share_mode, access_mask);
1961         END_PROFILE(syscall_kernel_flock);
1962         return 0;
1963 }
1964
1965 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1966 {
1967         bool result;
1968
1969         START_PROFILE(syscall_fcntl_getlock);
1970         result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1971         END_PROFILE(syscall_fcntl_getlock);
1972         return result;
1973 }
1974
1975 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1976                                 int leasetype)
1977 {
1978         int result = -1;
1979
1980         START_PROFILE(syscall_linux_setlease);
1981
1982 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1983         result = linux_setlease(fsp->fh->fd, leasetype);
1984 #else
1985         errno = ENOSYS;
1986 #endif
1987         END_PROFILE(syscall_linux_setlease);
1988         return result;
1989 }
1990
1991 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1992 {
1993         int result;
1994
1995         START_PROFILE(syscall_symlink);
1996         result = symlink(oldpath, newpath);
1997         END_PROFILE(syscall_symlink);
1998         return result;
1999 }
2000
2001 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2002 {
2003         int result;
2004
2005         START_PROFILE(syscall_readlink);
2006         result = readlink(path, buf, bufsiz);
2007         END_PROFILE(syscall_readlink);
2008         return result;
2009 }
2010
2011 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2012 {
2013         int result;
2014
2015         START_PROFILE(syscall_link);
2016         result = link(oldpath, newpath);
2017         END_PROFILE(syscall_link);
2018         return result;
2019 }
2020
2021 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2022 {
2023         int result;
2024
2025         START_PROFILE(syscall_mknod);
2026         result = sys_mknod(pathname, mode, dev);
2027         END_PROFILE(syscall_mknod);
2028         return result;
2029 }
2030
2031 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2032 {
2033         char *result;
2034
2035         START_PROFILE(syscall_realpath);
2036 #ifdef REALPATH_TAKES_NULL
2037         result = realpath(path, NULL);
2038 #else
2039         result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2040         if (result) {
2041                 char *resolved_path = realpath(path, result);
2042                 if (!resolved_path) {
2043                         SAFE_FREE(result);
2044                 } else {
2045                         /* SMB_ASSERT(result == resolved_path) ? */
2046                         result = resolved_path;
2047                 }
2048         }
2049 #endif
2050         END_PROFILE(syscall_realpath);
2051         return result;
2052 }
2053
2054 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2055                                      struct sys_notify_context *ctx,
2056                                      const char *path,
2057                                      uint32_t *filter,
2058                                      uint32_t *subdir_filter,
2059                                      void (*callback)(struct sys_notify_context *ctx, 
2060                                                       void *private_data,
2061                                                       struct notify_event *ev),
2062                                      void *private_data, void *handle)
2063 {
2064         /*
2065          * So far inotify is the only supported default notify mechanism. If
2066          * another platform like the the BSD's or a proprietary Unix comes
2067          * along and wants another default, we can play the same trick we
2068          * played with Posix ACLs.
2069          *
2070          * Until that is the case, hard-code inotify here.
2071          */
2072 #ifdef HAVE_INOTIFY
2073         if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2074                 return inotify_watch(ctx, path, filter, subdir_filter,
2075                                      callback, private_data, handle);
2076         }
2077 #endif
2078         /*
2079          * Do nothing, leave everything to notify_internal.c
2080          */
2081         return NT_STATUS_OK;
2082 }
2083
2084 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2085                            unsigned int flags)
2086 {
2087 #ifdef HAVE_CHFLAGS
2088         return chflags(path, flags);
2089 #else
2090         errno = ENOSYS;
2091         return -1;
2092 #endif
2093 }
2094
2095 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2096                                              const SMB_STRUCT_STAT *sbuf)
2097 {
2098         struct file_id key;
2099
2100         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2101          * blob */
2102         ZERO_STRUCT(key);
2103
2104         key.devid = sbuf->st_ex_dev;
2105         key.inode = sbuf->st_ex_ino;
2106         /* key.extid is unused by default. */
2107
2108         return key;
2109 }
2110
2111 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2112                                    struct files_struct *fsp,
2113                                    const char *fname,
2114                                    TALLOC_CTX *mem_ctx,
2115                                    unsigned int *pnum_streams,
2116                                    struct stream_struct **pstreams)
2117 {
2118         SMB_STRUCT_STAT sbuf;
2119         struct stream_struct *tmp_streams = NULL;
2120         int ret;
2121
2122         if ((fsp != NULL) && (fsp->is_directory)) {
2123                 /*
2124                  * No default streams on directories
2125                  */
2126                 goto done;
2127         }
2128
2129         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2130                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2131         }
2132         else {
2133                 struct smb_filename smb_fname;
2134
2135                 ZERO_STRUCT(smb_fname);
2136                 smb_fname.base_name = discard_const_p(char, fname);
2137
2138                 if (lp_posix_pathnames()) {
2139                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2140                 } else {
2141                         ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2142                 }
2143                 sbuf = smb_fname.st;
2144         }
2145
2146         if (ret == -1) {
2147                 return map_nt_error_from_unix(errno);
2148         }
2149
2150         if (S_ISDIR(sbuf.st_ex_mode)) {
2151                 goto done;
2152         }
2153
2154         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2155                                         (*pnum_streams) + 1);
2156         if (tmp_streams == NULL) {
2157                 return NT_STATUS_NO_MEMORY;
2158         }
2159         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2160         if (tmp_streams[*pnum_streams].name == NULL) {
2161                 return NT_STATUS_NO_MEMORY;
2162         }
2163         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2164         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2165
2166         *pnum_streams += 1;
2167         *pstreams = tmp_streams;
2168  done:
2169         return NT_STATUS_OK;
2170 }
2171
2172 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2173                                      const char *path,
2174                                      const char *name,
2175                                      TALLOC_CTX *mem_ctx,
2176                                      char **found_name)
2177 {
2178         /*
2179          * Don't fall back to get_real_filename so callers can differentiate
2180          * between a full directory scan and an actual case-insensitive stat.
2181          */
2182         errno = EOPNOTSUPP;
2183         return -1;
2184 }
2185
2186 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2187                                        const char *fname)
2188 {
2189         return handle->conn->connectpath;
2190 }
2191
2192 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2193                                          struct byte_range_lock *br_lck,
2194                                          struct lock_struct *plock,
2195                                          bool blocking_lock,
2196                                          struct blocking_lock_record *blr)
2197 {
2198         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2199
2200         /* Note: blr is not used in the default implementation. */
2201         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2202 }
2203
2204 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2205                                        struct messaging_context *msg_ctx,
2206                                        struct byte_range_lock *br_lck,
2207                                        const struct lock_struct *plock)
2208 {
2209         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2210
2211         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2212 }
2213
2214 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2215                                        struct byte_range_lock *br_lck,
2216                                        struct lock_struct *plock,
2217                                        struct blocking_lock_record *blr)
2218 {
2219         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2220
2221         /* Note: blr is not used in the default implementation. */
2222         return brl_lock_cancel_default(br_lck, plock);
2223 }
2224
2225 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2226                                 files_struct *fsp,
2227                                 struct lock_struct *plock)
2228 {
2229         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2230             plock->lock_type == WRITE_LOCK);
2231
2232         return strict_lock_default(fsp, plock);
2233 }
2234
2235 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2236                                 files_struct *fsp,
2237                                 struct lock_struct *plock)
2238 {
2239         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2240             plock->lock_type == WRITE_LOCK);
2241
2242         strict_unlock_default(fsp, plock);
2243 }
2244
2245 /* NT ACL operations. */
2246
2247 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2248                                     files_struct *fsp,
2249                                     uint32 security_info,
2250                                     TALLOC_CTX *mem_ctx,
2251                                     struct security_descriptor **ppdesc)
2252 {
2253         NTSTATUS result;
2254
2255         START_PROFILE(fget_nt_acl);
2256         result = posix_fget_nt_acl(fsp, security_info,
2257                                    mem_ctx, ppdesc);
2258         END_PROFILE(fget_nt_acl);
2259         return result;
2260 }
2261
2262 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2263                                    const char *name,
2264                                    uint32 security_info,
2265                                    TALLOC_CTX *mem_ctx,
2266                                    struct security_descriptor **ppdesc)
2267 {
2268         NTSTATUS result;
2269
2270         START_PROFILE(get_nt_acl);
2271         result = posix_get_nt_acl(handle->conn, name, security_info,
2272                                   mem_ctx, ppdesc);
2273         END_PROFILE(get_nt_acl);
2274         return result;
2275 }
2276
2277 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2278 {
2279         NTSTATUS result;
2280
2281         START_PROFILE(fset_nt_acl);
2282         result = set_nt_acl(fsp, security_info_sent, psd);
2283         END_PROFILE(fset_nt_acl);
2284         return result;
2285 }
2286
2287 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2288                                    struct smb_filename *file,
2289                                    struct security_acl *sacl,
2290                                    uint32_t access_requested,
2291                                    uint32_t access_denied)
2292 {
2293         return NT_STATUS_OK; /* Nothing to do here ... */
2294 }
2295
2296 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2297 {
2298 #ifdef HAVE_NO_ACL
2299         errno = ENOSYS;
2300         return -1;
2301 #else
2302         int result;
2303
2304         START_PROFILE(chmod_acl);
2305         result = chmod_acl(handle->conn, name, mode);
2306         END_PROFILE(chmod_acl);
2307         return result;
2308 #endif
2309 }
2310
2311 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2312 {
2313 #ifdef HAVE_NO_ACL
2314         errno = ENOSYS;
2315         return -1;
2316 #else
2317         int result;
2318
2319         START_PROFILE(fchmod_acl);
2320         result = fchmod_acl(fsp, mode);
2321         END_PROFILE(fchmod_acl);
2322         return result;
2323 #endif
2324 }
2325
2326 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2327                                           const char *path_p,
2328                                           SMB_ACL_TYPE_T type,
2329                                           TALLOC_CTX *mem_ctx)
2330 {
2331         return sys_acl_get_file(handle, path_p, type, mem_ctx);
2332 }
2333
2334 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2335                                         files_struct *fsp,
2336                                         TALLOC_CTX *mem_ctx)
2337 {
2338         return sys_acl_get_fd(handle, fsp, mem_ctx);
2339 }
2340
2341 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2342 {
2343         return sys_acl_set_file(handle, name, acltype, theacl);
2344 }
2345
2346 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2347 {
2348         return sys_acl_set_fd(handle, fsp, theacl);
2349 }
2350
2351 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2352 {
2353         return sys_acl_delete_def_file(handle, path);
2354 }
2355
2356 /****************************************************************
2357  Extended attribute operations.
2358 *****************************************************************/
2359
2360 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2361 {
2362         return getxattr(path, name, value, size);
2363 }
2364
2365 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2366 {
2367         return fgetxattr(fsp->fh->fd, name, value, size);
2368 }
2369
2370 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2371 {
2372         return listxattr(path, list, size);
2373 }
2374
2375 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2376 {
2377         return flistxattr(fsp->fh->fd, list, size);
2378 }
2379
2380 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2381 {
2382         return removexattr(path, name);
2383 }
2384
2385 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2386 {
2387         return fremovexattr(fsp->fh->fd, name);
2388 }
2389
2390 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2391 {
2392         return setxattr(path, name, value, size, flags);
2393 }
2394
2395 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2396 {
2397         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2398 }
2399
2400 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2401 {
2402         return false;
2403 }
2404
2405 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2406                                const struct smb_filename *fname,
2407                                SMB_STRUCT_STAT *sbuf)
2408 {
2409         NTSTATUS status;
2410         char *path;
2411         bool offline = false;
2412
2413         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2414                 return false;
2415         }
2416
2417         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2418 #if defined(ENOTSUP)
2419                 errno = ENOTSUP;
2420 #endif
2421                 return false;
2422         }
2423
2424         status = get_full_smb_filename(talloc_tos(), fname, &path);
2425         if (!NT_STATUS_IS_OK(status)) {
2426                 errno = map_errno_from_nt_status(status);
2427                 return false;
2428         }
2429
2430         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2431
2432         TALLOC_FREE(path);
2433
2434         return offline;
2435 }
2436
2437 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2438                                const struct smb_filename *fname)
2439 {
2440         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2441 #if defined(ENOTSUP)
2442         errno = ENOTSUP;
2443 #endif
2444         return -1;
2445 }
2446
2447 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2448                                        struct files_struct *fsp,
2449                                        TALLOC_CTX *mem_ctx,
2450                                        DATA_BLOB *cookie)
2451 {
2452         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2453 }
2454
2455 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2456                                            struct files_struct *fsp,
2457                                            const DATA_BLOB old_cookie,
2458                                            TALLOC_CTX *mem_ctx,
2459                                            DATA_BLOB *new_cookie)
2460 {
2461         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2462                                               new_cookie);
2463 }
2464
2465 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2466                                           struct smb_request *smb1req,
2467                                           struct smbXsrv_open *op,
2468                                           const DATA_BLOB old_cookie,
2469                                           TALLOC_CTX *mem_ctx,
2470                                           struct files_struct **fsp,
2471                                           DATA_BLOB *new_cookie)
2472 {
2473         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2474                                              old_cookie, mem_ctx,
2475                                              fsp, new_cookie);
2476 }
2477
2478 static struct vfs_fn_pointers vfs_default_fns = {
2479         /* Disk operations */
2480
2481         .connect_fn = vfswrap_connect,
2482         .disconnect_fn = vfswrap_disconnect,
2483         .disk_free_fn = vfswrap_disk_free,
2484         .get_quota_fn = vfswrap_get_quota,
2485         .set_quota_fn = vfswrap_set_quota,
2486         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2487         .statvfs_fn = vfswrap_statvfs,
2488         .fs_capabilities_fn = vfswrap_fs_capabilities,
2489         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2490
2491         /* Directory operations */
2492
2493         .opendir_fn = vfswrap_opendir,
2494         .fdopendir_fn = vfswrap_fdopendir,
2495         .readdir_fn = vfswrap_readdir,
2496         .seekdir_fn = vfswrap_seekdir,
2497         .telldir_fn = vfswrap_telldir,
2498         .rewind_dir_fn = vfswrap_rewinddir,
2499         .mkdir_fn = vfswrap_mkdir,
2500         .rmdir_fn = vfswrap_rmdir,
2501         .closedir_fn = vfswrap_closedir,
2502         .init_search_op_fn = vfswrap_init_search_op,
2503
2504         /* File operations */
2505
2506         .open_fn = vfswrap_open,
2507         .create_file_fn = vfswrap_create_file,
2508         .close_fn = vfswrap_close,
2509         .read_fn = vfswrap_read,
2510         .pread_fn = vfswrap_pread,
2511         .pread_send_fn = vfswrap_pread_send,
2512         .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2513         .write_fn = vfswrap_write,
2514         .pwrite_fn = vfswrap_pwrite,
2515         .pwrite_send_fn = vfswrap_pwrite_send,
2516         .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2517         .lseek_fn = vfswrap_lseek,
2518         .sendfile_fn = vfswrap_sendfile,
2519         .recvfile_fn = vfswrap_recvfile,
2520         .rename_fn = vfswrap_rename,
2521         .fsync_fn = vfswrap_fsync,
2522         .fsync_send_fn = vfswrap_fsync_send,
2523         .fsync_recv_fn = vfswrap_asys_int_recv,
2524         .stat_fn = vfswrap_stat,
2525         .fstat_fn = vfswrap_fstat,
2526         .lstat_fn = vfswrap_lstat,
2527         .get_alloc_size_fn = vfswrap_get_alloc_size,
2528         .unlink_fn = vfswrap_unlink,
2529         .chmod_fn = vfswrap_chmod,
2530         .fchmod_fn = vfswrap_fchmod,
2531         .chown_fn = vfswrap_chown,
2532         .fchown_fn = vfswrap_fchown,
2533         .lchown_fn = vfswrap_lchown,
2534         .chdir_fn = vfswrap_chdir,
2535         .getwd_fn = vfswrap_getwd,
2536         .ntimes_fn = vfswrap_ntimes,
2537         .ftruncate_fn = vfswrap_ftruncate,
2538         .fallocate_fn = vfswrap_fallocate,
2539         .lock_fn = vfswrap_lock,
2540         .kernel_flock_fn = vfswrap_kernel_flock,
2541         .linux_setlease_fn = vfswrap_linux_setlease,
2542         .getlock_fn = vfswrap_getlock,
2543         .symlink_fn = vfswrap_symlink,
2544         .readlink_fn = vfswrap_readlink,
2545         .link_fn = vfswrap_link,
2546         .mknod_fn = vfswrap_mknod,
2547         .realpath_fn = vfswrap_realpath,
2548         .notify_watch_fn = vfswrap_notify_watch,
2549         .chflags_fn = vfswrap_chflags,
2550         .file_id_create_fn = vfswrap_file_id_create,
2551         .streaminfo_fn = vfswrap_streaminfo,
2552         .get_real_filename_fn = vfswrap_get_real_filename,
2553         .connectpath_fn = vfswrap_connectpath,
2554         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2555         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2556         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2557         .strict_lock_fn = vfswrap_strict_lock,
2558         .strict_unlock_fn = vfswrap_strict_unlock,
2559         .translate_name_fn = vfswrap_translate_name,
2560         .fsctl_fn = vfswrap_fsctl,
2561         .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2562         .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2563         .get_compression_fn = vfswrap_get_compression,
2564         .set_compression_fn = vfswrap_set_compression,
2565
2566         /* NT ACL operations. */
2567
2568         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2569         .get_nt_acl_fn = vfswrap_get_nt_acl,
2570         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2571         .audit_file_fn = vfswrap_audit_file,
2572
2573         /* POSIX ACL operations. */
2574
2575         .chmod_acl_fn = vfswrap_chmod_acl,
2576         .fchmod_acl_fn = vfswrap_fchmod_acl,
2577
2578         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2579         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2580         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2581         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2582         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2583         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2584         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2585
2586         /* EA operations. */
2587         .getxattr_fn = vfswrap_getxattr,
2588         .fgetxattr_fn = vfswrap_fgetxattr,
2589         .listxattr_fn = vfswrap_listxattr,
2590         .flistxattr_fn = vfswrap_flistxattr,
2591         .removexattr_fn = vfswrap_removexattr,
2592         .fremovexattr_fn = vfswrap_fremovexattr,
2593         .setxattr_fn = vfswrap_setxattr,
2594         .fsetxattr_fn = vfswrap_fsetxattr,
2595
2596         /* aio operations */
2597         .aio_force_fn = vfswrap_aio_force,
2598
2599         /* offline operations */
2600         .is_offline_fn = vfswrap_is_offline,
2601         .set_offline_fn = vfswrap_set_offline,
2602
2603         /* durable handle operations */
2604         .durable_cookie_fn = vfswrap_durable_cookie,
2605         .durable_disconnect_fn = vfswrap_durable_disconnect,
2606         .durable_reconnect_fn = vfswrap_durable_reconnect,
2607 };
2608
2609 NTSTATUS vfs_default_init(void);
2610 NTSTATUS vfs_default_init(void)
2611 {
2612         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2613                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
2614 }
2615
2616