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