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