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