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