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