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