Bug found by Herb. blkcnt_t st_ex_blksize is defined as a signed value. When it is
[samba.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "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 DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
347 {
348         DIR *result;
349
350         START_PROFILE(syscall_opendir);
351         result = opendir(fname);
352         END_PROFILE(syscall_opendir);
353         return result;
354 }
355
356 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
357                         files_struct *fsp,
358                         const char *mask,
359                         uint32 attr)
360 {
361         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 struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
371                                           DIR *dirp,
372                                           SMB_STRUCT_STAT *sbuf)
373 {
374         struct dirent *result;
375
376         START_PROFILE(syscall_readdir);
377         result = 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,  DIR *dirp, long offset)
387 {
388         START_PROFILE(syscall_seekdir);
389         seekdir(dirp, offset);
390         END_PROFILE(syscall_seekdir);
391 }
392
393 static long vfswrap_telldir(vfs_handle_struct *handle,  DIR *dirp)
394 {
395         long result;
396         START_PROFILE(syscall_telldir);
397         result = telldir(dirp);
398         END_PROFILE(syscall_telldir);
399         return result;
400 }
401
402 static void vfswrap_rewinddir(vfs_handle_struct *handle,  DIR *dirp)
403 {
404         START_PROFILE(syscall_rewinddir);
405         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,  DIR *dirp)
454 {
455         int result;
456
457         START_PROFILE(syscall_closedir);
458         result = closedir(dirp);
459         END_PROFILE(syscall_closedir);
460         return result;
461 }
462
463 static void vfswrap_init_search_op(vfs_handle_struct *handle,
464                                    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, 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         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, 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         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 off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
630 {
631         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                         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                         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         /* The type of st_blocksize is blkcnt_t which *MUST* be
1123            signed (according to POSIX) and can be less than 64-bits.
1124            Ensure when we're converting to 64 bits wide we don't
1125            sign extend. */
1126 #if defined(SIZEOF_BLKCNT_T_8)
1127         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1128 #elif defined(SIZEOF_BLKCNT_T_4)
1129         {
1130                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1131                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1132         }
1133 #else
1134 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1135 #endif
1136 #else
1137         result = get_file_size_stat(sbuf);
1138 #endif
1139
1140         if (fsp && fsp->initial_allocation_size)
1141                 result = MAX(result,fsp->initial_allocation_size);
1142
1143         result = smb_roundup(handle->conn, result);
1144
1145  out:
1146         END_PROFILE(syscall_get_alloc_size);
1147         return result;
1148 }
1149
1150 static int vfswrap_unlink(vfs_handle_struct *handle,
1151                           const struct smb_filename *smb_fname)
1152 {
1153         int result = -1;
1154
1155         START_PROFILE(syscall_unlink);
1156
1157         if (smb_fname->stream_name) {
1158                 errno = ENOENT;
1159                 goto out;
1160         }
1161         result = unlink(smb_fname->base_name);
1162
1163  out:
1164         END_PROFILE(syscall_unlink);
1165         return result;
1166 }
1167
1168 static int vfswrap_chmod(vfs_handle_struct *handle,  const char *path, mode_t mode)
1169 {
1170         int result;
1171
1172         START_PROFILE(syscall_chmod);
1173
1174         /*
1175          * We need to do this due to the fact that the default POSIX ACL
1176          * chmod modifies the ACL *mask* for the group owner, not the
1177          * group owner bits directly. JRA.
1178          */
1179
1180
1181         {
1182                 int saved_errno = errno; /* We might get ENOSYS */
1183                 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1184                         END_PROFILE(syscall_chmod);
1185                         return result;
1186                 }
1187                 /* Error - return the old errno. */
1188                 errno = saved_errno;
1189         }
1190
1191         result = chmod(path, mode);
1192         END_PROFILE(syscall_chmod);
1193         return result;
1194 }
1195
1196 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1197 {
1198         int result;
1199
1200         START_PROFILE(syscall_fchmod);
1201
1202         /*
1203          * We need to do this due to the fact that the default POSIX ACL
1204          * chmod modifies the ACL *mask* for the group owner, not the
1205          * group owner bits directly. JRA.
1206          */
1207
1208         {
1209                 int saved_errno = errno; /* We might get ENOSYS */
1210                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1211                         END_PROFILE(syscall_fchmod);
1212                         return result;
1213                 }
1214                 /* Error - return the old errno. */
1215                 errno = saved_errno;
1216         }
1217
1218 #if defined(HAVE_FCHMOD)
1219         result = fchmod(fsp->fh->fd, mode);
1220 #else
1221         result = -1;
1222         errno = ENOSYS;
1223 #endif
1224
1225         END_PROFILE(syscall_fchmod);
1226         return result;
1227 }
1228
1229 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1230 {
1231         int result;
1232
1233         START_PROFILE(syscall_chown);
1234         result = chown(path, uid, gid);
1235         END_PROFILE(syscall_chown);
1236         return result;
1237 }
1238
1239 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1240 {
1241 #ifdef HAVE_FCHOWN
1242         int result;
1243
1244         START_PROFILE(syscall_fchown);
1245         result = fchown(fsp->fh->fd, uid, gid);
1246         END_PROFILE(syscall_fchown);
1247         return result;
1248 #else
1249         errno = ENOSYS;
1250         return -1;
1251 #endif
1252 }
1253
1254 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1255 {
1256         int result;
1257
1258         START_PROFILE(syscall_lchown);
1259         result = lchown(path, uid, gid);
1260         END_PROFILE(syscall_lchown);
1261         return result;
1262 }
1263
1264 static int vfswrap_chdir(vfs_handle_struct *handle,  const char *path)
1265 {
1266         int result;
1267
1268         START_PROFILE(syscall_chdir);
1269         result = chdir(path);
1270         END_PROFILE(syscall_chdir);
1271         return result;
1272 }
1273
1274 static char *vfswrap_getwd(vfs_handle_struct *handle)
1275 {
1276         char *result;
1277
1278         START_PROFILE(syscall_getwd);
1279         result = sys_getwd();
1280         END_PROFILE(syscall_getwd);
1281         return result;
1282 }
1283
1284 /*********************************************************************
1285  nsec timestamp resolution call. Convert down to whatever the underlying
1286  system will support.
1287 **********************************************************************/
1288
1289 static int vfswrap_ntimes(vfs_handle_struct *handle,
1290                           const struct smb_filename *smb_fname,
1291                           struct smb_file_time *ft)
1292 {
1293         int result = -1;
1294
1295         START_PROFILE(syscall_ntimes);
1296
1297         if (smb_fname->stream_name) {
1298                 errno = ENOENT;
1299                 goto out;
1300         }
1301
1302         if (ft != NULL) {
1303                 if (null_timespec(ft->atime)) {
1304                         ft->atime= smb_fname->st.st_ex_atime;
1305                 }
1306
1307                 if (null_timespec(ft->mtime)) {
1308                         ft->mtime = smb_fname->st.st_ex_mtime;
1309                 }
1310
1311                 if (!null_timespec(ft->create_time)) {
1312                         set_create_timespec_ea(handle->conn,
1313                                                smb_fname,
1314                                                ft->create_time);
1315                 }
1316
1317                 if ((timespec_compare(&ft->atime,
1318                                       &smb_fname->st.st_ex_atime) == 0) &&
1319                     (timespec_compare(&ft->mtime,
1320                                       &smb_fname->st.st_ex_mtime) == 0)) {
1321                         return 0;
1322                 }
1323         }
1324
1325 #if defined(HAVE_UTIMENSAT)
1326         if (ft != NULL) {
1327                 struct timespec ts[2];
1328                 ts[0] = ft->atime;
1329                 ts[1] = ft->mtime;
1330                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1331         } else {
1332                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1333         }
1334         if (!((result == -1) && (errno == ENOSYS))) {
1335                 goto out;
1336         }
1337 #endif
1338 #if defined(HAVE_UTIMES)
1339         if (ft != NULL) {
1340                 struct timeval tv[2];
1341                 tv[0] = convert_timespec_to_timeval(ft->atime);
1342                 tv[1] = convert_timespec_to_timeval(ft->mtime);
1343                 result = utimes(smb_fname->base_name, tv);
1344         } else {
1345                 result = utimes(smb_fname->base_name, NULL);
1346         }
1347         if (!((result == -1) && (errno == ENOSYS))) {
1348                 goto out;
1349         }
1350 #endif
1351 #if defined(HAVE_UTIME)
1352         if (ft != NULL) {
1353                 struct utimbuf times;
1354                 times.actime = convert_timespec_to_time_t(ft->atime);
1355                 times.modtime = convert_timespec_to_time_t(ft->mtime);
1356                 result = utime(smb_fname->base_name, &times);
1357         } else {
1358                 result = utime(smb_fname->base_name, NULL);
1359         }
1360         if (!((result == -1) && (errno == ENOSYS))) {
1361                 goto out;
1362         }
1363 #endif
1364         errno = ENOSYS;
1365         result = -1;
1366
1367  out:
1368         END_PROFILE(syscall_ntimes);
1369         return result;
1370 }
1371
1372 /*********************************************************************
1373  A version of ftruncate that will write the space on disk if strict
1374  allocate is set.
1375 **********************************************************************/
1376
1377 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1378 {
1379         off_t space_to_write;
1380         uint64_t space_avail;
1381         uint64_t bsize,dfree,dsize;
1382         int ret;
1383         NTSTATUS status;
1384         SMB_STRUCT_STAT *pst;
1385
1386         status = vfs_stat_fsp(fsp);
1387         if (!NT_STATUS_IS_OK(status)) {
1388                 return -1;
1389         }
1390         pst = &fsp->fsp_name->st;
1391
1392 #ifdef S_ISFIFO
1393         if (S_ISFIFO(pst->st_ex_mode))
1394                 return 0;
1395 #endif
1396
1397         if (pst->st_ex_size == len)
1398                 return 0;
1399
1400         /* Shrink - just ftruncate. */
1401         if (pst->st_ex_size > len)
1402                 return ftruncate(fsp->fh->fd, len);
1403
1404         space_to_write = len - pst->st_ex_size;
1405
1406         /* for allocation try fallocate first. This can fail on some
1407            platforms e.g. when the filesystem doesn't support it and no
1408            emulation is being done by the libc (like on AIX with JFS1). In that
1409            case we do our own emulation. fallocate implementations can
1410            return ENOTSUP or EINVAL in cases like that. */
1411         ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1412                                 pst->st_ex_size, space_to_write);
1413         if (ret == ENOSPC) {
1414                 errno = ENOSPC;
1415                 return -1;
1416         }
1417         if (ret == 0) {
1418                 return 0;
1419         }
1420         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1421                 "error %d. Falling back to slow manual allocation\n", ret));
1422
1423         /* available disk space is enough or not? */
1424         space_avail = get_dfree_info(fsp->conn,
1425                                      fsp->fsp_name->base_name, false,
1426                                      &bsize,&dfree,&dsize);
1427         /* space_avail is 1k blocks */
1428         if (space_avail == (uint64_t)-1 ||
1429                         ((uint64_t)space_to_write/1024 > space_avail) ) {
1430                 errno = ENOSPC;
1431                 return -1;
1432         }
1433
1434         /* Write out the real space on disk. */
1435         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1436         if (ret != 0) {
1437                 errno = ret;
1438                 ret = -1;
1439         }
1440
1441         return 0;
1442 }
1443
1444 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1445 {
1446         int result = -1;
1447         SMB_STRUCT_STAT *pst;
1448         NTSTATUS status;
1449         char c = 0;
1450
1451         START_PROFILE(syscall_ftruncate);
1452
1453         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1454                 result = strict_allocate_ftruncate(handle, fsp, len);
1455                 END_PROFILE(syscall_ftruncate);
1456                 return result;
1457         }
1458
1459         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1460            ftruncate if the system supports it. Then I discovered that
1461            you can have some filesystems that support ftruncate
1462            expansion and some that don't! On Linux fat can't do
1463            ftruncate extend but ext2 can. */
1464
1465         result = ftruncate(fsp->fh->fd, len);
1466         if (result == 0)
1467                 goto done;
1468
1469         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1470            extend a file with ftruncate. Provide alternate implementation
1471            for this */
1472
1473         /* Do an fstat to see if the file is longer than the requested
1474            size in which case the ftruncate above should have
1475            succeeded or shorter, in which case seek to len - 1 and
1476            write 1 byte of zero */
1477         status = vfs_stat_fsp(fsp);
1478         if (!NT_STATUS_IS_OK(status)) {
1479                 goto done;
1480         }
1481         pst = &fsp->fsp_name->st;
1482
1483 #ifdef S_ISFIFO
1484         if (S_ISFIFO(pst->st_ex_mode)) {
1485                 result = 0;
1486                 goto done;
1487         }
1488 #endif
1489
1490         if (pst->st_ex_size == len) {
1491                 result = 0;
1492                 goto done;
1493         }
1494
1495         if (pst->st_ex_size > len) {
1496                 /* the ftruncate should have worked */
1497                 goto done;
1498         }
1499
1500         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1501                 goto done;
1502         }
1503
1504         result = 0;
1505
1506   done:
1507
1508         END_PROFILE(syscall_ftruncate);
1509         return result;
1510 }
1511
1512 static int vfswrap_fallocate(vfs_handle_struct *handle,
1513                         files_struct *fsp,
1514                         enum vfs_fallocate_mode mode,
1515                         off_t offset,
1516                         off_t len)
1517 {
1518         int result;
1519
1520         START_PROFILE(syscall_fallocate);
1521         if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1522                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1523         } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1524                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1525         } else {
1526                 errno = EINVAL;
1527                 result = -1;
1528         }
1529         END_PROFILE(syscall_fallocate);
1530         return result;
1531 }
1532
1533 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1534 {
1535         bool result;
1536
1537         START_PROFILE(syscall_fcntl_lock);
1538         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
1539         END_PROFILE(syscall_fcntl_lock);
1540         return result;
1541 }
1542
1543 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1544                                 uint32 share_mode, uint32 access_mask)
1545 {
1546         START_PROFILE(syscall_kernel_flock);
1547         kernel_flock(fsp->fh->fd, share_mode, access_mask);
1548         END_PROFILE(syscall_kernel_flock);
1549         return 0;
1550 }
1551
1552 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1553 {
1554         bool result;
1555
1556         START_PROFILE(syscall_fcntl_getlock);
1557         result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1558         END_PROFILE(syscall_fcntl_getlock);
1559         return result;
1560 }
1561
1562 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1563                                 int leasetype)
1564 {
1565         int result = -1;
1566
1567         START_PROFILE(syscall_linux_setlease);
1568
1569 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1570         /* first set the signal handler */
1571         if(linux_set_lease_sighandler(fsp->fh->fd) == -1) {
1572                 return -1;
1573         }
1574
1575         result = linux_setlease(fsp->fh->fd, leasetype);
1576 #else
1577         errno = ENOSYS;
1578 #endif
1579         END_PROFILE(syscall_linux_setlease);
1580         return result;
1581 }
1582
1583 static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1584 {
1585         int result;
1586
1587         START_PROFILE(syscall_symlink);
1588         result = symlink(oldpath, newpath);
1589         END_PROFILE(syscall_symlink);
1590         return result;
1591 }
1592
1593 static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
1594 {
1595         int result;
1596
1597         START_PROFILE(syscall_readlink);
1598         result = readlink(path, buf, bufsiz);
1599         END_PROFILE(syscall_readlink);
1600         return result;
1601 }
1602
1603 static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1604 {
1605         int result;
1606
1607         START_PROFILE(syscall_link);
1608         result = link(oldpath, newpath);
1609         END_PROFILE(syscall_link);
1610         return result;
1611 }
1612
1613 static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
1614 {
1615         int result;
1616
1617         START_PROFILE(syscall_mknod);
1618         result = sys_mknod(pathname, mode, dev);
1619         END_PROFILE(syscall_mknod);
1620         return result;
1621 }
1622
1623 static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path)
1624 {
1625         char *result;
1626
1627         START_PROFILE(syscall_realpath);
1628 #ifdef REALPATH_TAKES_NULL
1629         result = realpath(path, NULL);
1630 #else
1631         result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
1632         if (result) {
1633                 char *resolved_path = realpath(path, result);
1634                 if (!resolved_path) {
1635                         SAFE_FREE(result);
1636                 } else {
1637                         /* SMB_ASSERT(result == resolved_path) ? */
1638                         result = resolved_path;
1639                 }
1640         }
1641 #endif
1642         END_PROFILE(syscall_realpath);
1643         return result;
1644 }
1645
1646 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
1647                                      struct sys_notify_context *ctx,
1648                                      const char *path,
1649                                      uint32_t *filter,
1650                                      uint32_t *subdir_filter,
1651                                      void (*callback)(struct sys_notify_context *ctx, 
1652                                                       void *private_data,
1653                                                       struct notify_event *ev),
1654                                      void *private_data, void *handle)
1655 {
1656         /*
1657          * So far inotify is the only supported default notify mechanism. If
1658          * another platform like the the BSD's or a proprietary Unix comes
1659          * along and wants another default, we can play the same trick we
1660          * played with Posix ACLs.
1661          *
1662          * Until that is the case, hard-code inotify here.
1663          */
1664 #ifdef HAVE_INOTIFY
1665         if (lp_kernel_change_notify(vfs_handle->conn->params)) {
1666                 return inotify_watch(ctx, path, filter, subdir_filter,
1667                                      callback, private_data, handle);
1668         }
1669 #endif
1670         /*
1671          * Do nothing, leave everything to notify_internal.c
1672          */
1673         return NT_STATUS_OK;
1674 }
1675
1676 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
1677                            unsigned int flags)
1678 {
1679 #ifdef HAVE_CHFLAGS
1680         return chflags(path, flags);
1681 #else
1682         errno = ENOSYS;
1683         return -1;
1684 #endif
1685 }
1686
1687 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
1688                                              const SMB_STRUCT_STAT *sbuf)
1689 {
1690         struct file_id key;
1691
1692         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
1693          * blob */
1694         ZERO_STRUCT(key);
1695
1696         key.devid = sbuf->st_ex_dev;
1697         key.inode = sbuf->st_ex_ino;
1698         /* key.extid is unused by default. */
1699
1700         return key;
1701 }
1702
1703 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
1704                                    struct files_struct *fsp,
1705                                    const char *fname,
1706                                    TALLOC_CTX *mem_ctx,
1707                                    unsigned int *pnum_streams,
1708                                    struct stream_struct **pstreams)
1709 {
1710         SMB_STRUCT_STAT sbuf;
1711         struct stream_struct *tmp_streams = NULL;
1712         int ret;
1713
1714         if ((fsp != NULL) && (fsp->is_directory)) {
1715                 /*
1716                  * No default streams on directories
1717                  */
1718                 goto done;
1719         }
1720
1721         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
1722                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
1723         }
1724         else {
1725                 struct smb_filename smb_fname;
1726
1727                 ZERO_STRUCT(smb_fname);
1728                 smb_fname.base_name = discard_const_p(char, fname);
1729
1730                 if (lp_posix_pathnames()) {
1731                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
1732                 } else {
1733                         ret = SMB_VFS_STAT(handle->conn, &smb_fname);
1734                 }
1735                 sbuf = smb_fname.st;
1736         }
1737
1738         if (ret == -1) {
1739                 return map_nt_error_from_unix(errno);
1740         }
1741
1742         if (S_ISDIR(sbuf.st_ex_mode)) {
1743                 goto done;
1744         }
1745
1746         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
1747                                         (*pnum_streams) + 1);
1748         if (tmp_streams == NULL) {
1749                 return NT_STATUS_NO_MEMORY;
1750         }
1751         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
1752         if (tmp_streams[*pnum_streams].name == NULL) {
1753                 return NT_STATUS_NO_MEMORY;
1754         }
1755         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
1756         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
1757
1758         *pnum_streams += 1;
1759         *pstreams = tmp_streams;
1760  done:
1761         return NT_STATUS_OK;
1762 }
1763
1764 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
1765                                      const char *path,
1766                                      const char *name,
1767                                      TALLOC_CTX *mem_ctx,
1768                                      char **found_name)
1769 {
1770         /*
1771          * Don't fall back to get_real_filename so callers can differentiate
1772          * between a full directory scan and an actual case-insensitive stat.
1773          */
1774         errno = EOPNOTSUPP;
1775         return -1;
1776 }
1777
1778 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
1779                                        const char *fname)
1780 {
1781         return handle->conn->connectpath;
1782 }
1783
1784 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
1785                                          struct byte_range_lock *br_lck,
1786                                          struct lock_struct *plock,
1787                                          bool blocking_lock,
1788                                          struct blocking_lock_record *blr)
1789 {
1790         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1791
1792         /* Note: blr is not used in the default implementation. */
1793         return brl_lock_windows_default(br_lck, plock, blocking_lock);
1794 }
1795
1796 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
1797                                        struct messaging_context *msg_ctx,
1798                                        struct byte_range_lock *br_lck,
1799                                        const struct lock_struct *plock)
1800 {
1801         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1802
1803         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
1804 }
1805
1806 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
1807                                        struct byte_range_lock *br_lck,
1808                                        struct lock_struct *plock,
1809                                        struct blocking_lock_record *blr)
1810 {
1811         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1812
1813         /* Note: blr is not used in the default implementation. */
1814         return brl_lock_cancel_default(br_lck, plock);
1815 }
1816
1817 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
1818                                 files_struct *fsp,
1819                                 struct lock_struct *plock)
1820 {
1821         SMB_ASSERT(plock->lock_type == READ_LOCK ||
1822             plock->lock_type == WRITE_LOCK);
1823
1824         return strict_lock_default(fsp, plock);
1825 }
1826
1827 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
1828                                 files_struct *fsp,
1829                                 struct lock_struct *plock)
1830 {
1831         SMB_ASSERT(plock->lock_type == READ_LOCK ||
1832             plock->lock_type == WRITE_LOCK);
1833
1834         strict_unlock_default(fsp, plock);
1835 }
1836
1837 /* NT ACL operations. */
1838
1839 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
1840                                     files_struct *fsp,
1841                                     uint32 security_info,
1842                                     struct security_descriptor **ppdesc)
1843 {
1844         NTSTATUS result;
1845
1846         START_PROFILE(fget_nt_acl);
1847         result = posix_fget_nt_acl(fsp, security_info, ppdesc);
1848         END_PROFILE(fget_nt_acl);
1849         return result;
1850 }
1851
1852 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
1853                                    const char *name,
1854                                    uint32 security_info,
1855                                    struct security_descriptor **ppdesc)
1856 {
1857         NTSTATUS result;
1858
1859         START_PROFILE(get_nt_acl);
1860         result = posix_get_nt_acl(handle->conn, name, security_info, ppdesc);
1861         END_PROFILE(get_nt_acl);
1862         return result;
1863 }
1864
1865 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
1866 {
1867         NTSTATUS result;
1868
1869         START_PROFILE(fset_nt_acl);
1870         result = set_nt_acl(fsp, security_info_sent, psd);
1871         END_PROFILE(fset_nt_acl);
1872         return result;
1873 }
1874
1875 static int vfswrap_chmod_acl(vfs_handle_struct *handle,  const char *name, mode_t mode)
1876 {
1877 #ifdef HAVE_NO_ACL
1878         errno = ENOSYS;
1879         return -1;
1880 #else
1881         int result;
1882
1883         START_PROFILE(chmod_acl);
1884         result = chmod_acl(handle->conn, name, mode);
1885         END_PROFILE(chmod_acl);
1886         return result;
1887 #endif
1888 }
1889
1890 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1891 {
1892 #ifdef HAVE_NO_ACL
1893         errno = ENOSYS;
1894         return -1;
1895 #else
1896         int result;
1897
1898         START_PROFILE(fchmod_acl);
1899         result = fchmod_acl(fsp, mode);
1900         END_PROFILE(fchmod_acl);
1901         return result;
1902 #endif
1903 }
1904
1905 static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle,  SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1906 {
1907         return sys_acl_get_entry(theacl, entry_id, entry_p);
1908 }
1909
1910 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)
1911 {
1912         return sys_acl_get_tag_type(entry_d, tag_type_p);
1913 }
1914
1915 static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1916 {
1917         return sys_acl_get_permset(entry_d, permset_p);
1918 }
1919
1920 static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
1921 {
1922         return sys_acl_get_qualifier(entry_d);
1923 }
1924
1925 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
1926 {
1927         return sys_acl_get_file(handle, path_p, type);
1928 }
1929
1930 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
1931 {
1932         return sys_acl_get_fd(handle, fsp);
1933 }
1934
1935 static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset)
1936 {
1937         return sys_acl_clear_perms(permset);
1938 }
1939
1940 static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1941 {
1942         return sys_acl_add_perm(permset, perm);
1943 }
1944
1945 static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle,  SMB_ACL_T theacl, ssize_t *plen)
1946 {
1947         return sys_acl_to_text(theacl, plen);
1948 }
1949
1950 static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle,  int count)
1951 {
1952         return sys_acl_init(count);
1953 }
1954
1955 static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle,  SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1956 {
1957         return sys_acl_create_entry(pacl, pentry);
1958 }
1959
1960 static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1961 {
1962         return sys_acl_set_tag_type(entry, tagtype);
1963 }
1964
1965 static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, void *qual)
1966 {
1967         return sys_acl_set_qualifier(entry, qual);
1968 }
1969
1970 static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1971 {
1972         return sys_acl_set_permset(entry, permset);
1973 }
1974
1975 static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
1976 {
1977         return sys_acl_valid(theacl );
1978 }
1979
1980 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1981 {
1982         return sys_acl_set_file(handle, name, acltype, theacl);
1983 }
1984
1985 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
1986 {
1987         return sys_acl_set_fd(handle, fsp, theacl);
1988 }
1989
1990 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const char *path)
1991 {
1992         return sys_acl_delete_def_file(handle, path);
1993 }
1994
1995 static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1996 {
1997         return sys_acl_get_perm(permset, perm);
1998 }
1999
2000 static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle,  char *text)
2001 {
2002         return sys_acl_free_text(text);
2003 }
2004
2005 static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle,  SMB_ACL_T posix_acl)
2006 {
2007         return sys_acl_free_acl(posix_acl);
2008 }
2009
2010 static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle,  void *qualifier, SMB_ACL_TAG_T tagtype)
2011 {
2012         return sys_acl_free_qualifier(qualifier, tagtype);
2013 }
2014
2015 /****************************************************************
2016  Extended attribute operations.
2017 *****************************************************************/
2018
2019 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2020 {
2021         return sys_getxattr(path, name, value, size);
2022 }
2023
2024 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2025 {
2026         return sys_fgetxattr(fsp->fh->fd, name, value, size);
2027 }
2028
2029 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2030 {
2031         return sys_listxattr(path, list, size);
2032 }
2033
2034 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2035 {
2036         return sys_flistxattr(fsp->fh->fd, list, size);
2037 }
2038
2039 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2040 {
2041         return sys_removexattr(path, name);
2042 }
2043
2044 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2045 {
2046         return sys_fremovexattr(fsp->fh->fd, name);
2047 }
2048
2049 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2050 {
2051         return sys_setxattr(path, name, value, size, flags);
2052 }
2053
2054 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2055 {
2056         return sys_fsetxattr(fsp->fh->fd, name, value, size, flags);
2057 }
2058
2059 static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
2060 {
2061         int ret;
2062         /*
2063          * aio_read must be done as root, because in the glibc aio
2064          * implementation the helper thread needs to be able to send a signal
2065          * to the main thread, even when it has done a seteuid() to a
2066          * different user.
2067          */
2068         become_root();
2069         ret = sys_aio_read(aiocb);
2070         unbecome_root();
2071         return ret;
2072 }
2073
2074 static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
2075 {
2076         int ret;
2077         /*
2078          * aio_write must be done as root, because in the glibc aio
2079          * implementation the helper thread needs to be able to send a signal
2080          * to the main thread, even when it has done a seteuid() to a
2081          * different user.
2082          */
2083         become_root();
2084         ret = sys_aio_write(aiocb);
2085         unbecome_root();
2086         return ret;
2087 }
2088
2089 static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
2090 {
2091         return sys_aio_return(aiocb);
2092 }
2093
2094 static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
2095 {
2096         return sys_aio_cancel(fsp->fh->fd, aiocb);
2097 }
2098
2099 static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
2100 {
2101         return sys_aio_error(aiocb);
2102 }
2103
2104 static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
2105 {
2106         return sys_aio_fsync(op, aiocb);
2107 }
2108
2109 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)
2110 {
2111         return sys_aio_suspend(aiocb, n, timeout);
2112 }
2113
2114 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2115 {
2116         return false;
2117 }
2118
2119 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2120                                const struct smb_filename *fname,
2121                                SMB_STRUCT_STAT *sbuf)
2122 {
2123         NTSTATUS status;
2124         char *path;
2125         bool offline = false;
2126
2127         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2128                 return false;
2129         }
2130
2131         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2132 #if defined(ENOTSUP)
2133                 errno = ENOTSUP;
2134 #endif
2135                 return false;
2136         }
2137
2138         status = get_full_smb_filename(talloc_tos(), fname, &path);
2139         if (!NT_STATUS_IS_OK(status)) {
2140                 errno = map_errno_from_nt_status(status);
2141                 return false;
2142         }
2143
2144         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2145
2146         TALLOC_FREE(path);
2147
2148         return offline;
2149 }
2150
2151 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2152                                const struct smb_filename *fname)
2153 {
2154         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2155 #if defined(ENOTSUP)
2156         errno = ENOTSUP;
2157 #endif
2158         return -1;
2159 }
2160
2161 static struct vfs_fn_pointers vfs_default_fns = {
2162         /* Disk operations */
2163
2164         .connect_fn = vfswrap_connect,
2165         .disconnect_fn = vfswrap_disconnect,
2166         .disk_free_fn = vfswrap_disk_free,
2167         .get_quota_fn = vfswrap_get_quota,
2168         .set_quota_fn = vfswrap_set_quota,
2169         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2170         .statvfs_fn = vfswrap_statvfs,
2171         .fs_capabilities_fn = vfswrap_fs_capabilities,
2172         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2173
2174         /* Directory operations */
2175
2176         .opendir_fn = vfswrap_opendir,
2177         .fdopendir_fn = vfswrap_fdopendir,
2178         .readdir_fn = vfswrap_readdir,
2179         .seekdir_fn = vfswrap_seekdir,
2180         .telldir_fn = vfswrap_telldir,
2181         .rewind_dir_fn = vfswrap_rewinddir,
2182         .mkdir_fn = vfswrap_mkdir,
2183         .rmdir_fn = vfswrap_rmdir,
2184         .closedir_fn = vfswrap_closedir,
2185         .init_search_op_fn = vfswrap_init_search_op,
2186
2187         /* File operations */
2188
2189         .open_fn = vfswrap_open,
2190         .create_file_fn = vfswrap_create_file,
2191         .close_fn = vfswrap_close,
2192         .read_fn = vfswrap_read,
2193         .pread_fn = vfswrap_pread,
2194         .write_fn = vfswrap_write,
2195         .pwrite_fn = vfswrap_pwrite,
2196         .lseek_fn = vfswrap_lseek,
2197         .sendfile_fn = vfswrap_sendfile,
2198         .recvfile_fn = vfswrap_recvfile,
2199         .rename_fn = vfswrap_rename,
2200         .fsync_fn = vfswrap_fsync,
2201         .stat_fn = vfswrap_stat,
2202         .fstat_fn = vfswrap_fstat,
2203         .lstat_fn = vfswrap_lstat,
2204         .get_alloc_size_fn = vfswrap_get_alloc_size,
2205         .unlink_fn = vfswrap_unlink,
2206         .chmod_fn = vfswrap_chmod,
2207         .fchmod_fn = vfswrap_fchmod,
2208         .chown_fn = vfswrap_chown,
2209         .fchown_fn = vfswrap_fchown,
2210         .lchown_fn = vfswrap_lchown,
2211         .chdir_fn = vfswrap_chdir,
2212         .getwd_fn = vfswrap_getwd,
2213         .ntimes_fn = vfswrap_ntimes,
2214         .ftruncate_fn = vfswrap_ftruncate,
2215         .fallocate_fn = vfswrap_fallocate,
2216         .lock_fn = vfswrap_lock,
2217         .kernel_flock_fn = vfswrap_kernel_flock,
2218         .linux_setlease_fn = vfswrap_linux_setlease,
2219         .getlock_fn = vfswrap_getlock,
2220         .symlink_fn = vfswrap_symlink,
2221         .readlink_fn = vfswrap_readlink,
2222         .link_fn = vfswrap_link,
2223         .mknod_fn = vfswrap_mknod,
2224         .realpath_fn = vfswrap_realpath,
2225         .notify_watch_fn = vfswrap_notify_watch,
2226         .chflags_fn = vfswrap_chflags,
2227         .file_id_create_fn = vfswrap_file_id_create,
2228         .streaminfo_fn = vfswrap_streaminfo,
2229         .get_real_filename_fn = vfswrap_get_real_filename,
2230         .connectpath_fn = vfswrap_connectpath,
2231         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2232         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2233         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2234         .strict_lock_fn = vfswrap_strict_lock,
2235         .strict_unlock_fn = vfswrap_strict_unlock,
2236         .translate_name_fn = vfswrap_translate_name,
2237         .fsctl_fn = vfswrap_fsctl,
2238
2239         /* NT ACL operations. */
2240
2241         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2242         .get_nt_acl_fn = vfswrap_get_nt_acl,
2243         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2244
2245         /* POSIX ACL operations. */
2246
2247         .chmod_acl_fn = vfswrap_chmod_acl,
2248         .fchmod_acl_fn = vfswrap_fchmod_acl,
2249
2250         .sys_acl_get_entry_fn = vfswrap_sys_acl_get_entry,
2251         .sys_acl_get_tag_type_fn = vfswrap_sys_acl_get_tag_type,
2252         .sys_acl_get_permset_fn = vfswrap_sys_acl_get_permset,
2253         .sys_acl_get_qualifier_fn = vfswrap_sys_acl_get_qualifier,
2254         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2255         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2256         .sys_acl_clear_perms_fn = vfswrap_sys_acl_clear_perms,
2257         .sys_acl_add_perm_fn = vfswrap_sys_acl_add_perm,
2258         .sys_acl_to_text_fn = vfswrap_sys_acl_to_text,
2259         .sys_acl_init_fn = vfswrap_sys_acl_init,
2260         .sys_acl_create_entry_fn = vfswrap_sys_acl_create_entry,
2261         .sys_acl_set_tag_type_fn = vfswrap_sys_acl_set_tag_type,
2262         .sys_acl_set_qualifier_fn = vfswrap_sys_acl_set_qualifier,
2263         .sys_acl_set_permset_fn = vfswrap_sys_acl_set_permset,
2264         .sys_acl_valid_fn = vfswrap_sys_acl_valid,
2265         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2266         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2267         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2268         .sys_acl_get_perm_fn = vfswrap_sys_acl_get_perm,
2269         .sys_acl_free_text_fn = vfswrap_sys_acl_free_text,
2270         .sys_acl_free_acl_fn = vfswrap_sys_acl_free_acl,
2271         .sys_acl_free_qualifier_fn = vfswrap_sys_acl_free_qualifier,
2272
2273         /* EA operations. */
2274         .getxattr_fn = vfswrap_getxattr,
2275         .fgetxattr_fn = vfswrap_fgetxattr,
2276         .listxattr_fn = vfswrap_listxattr,
2277         .flistxattr_fn = vfswrap_flistxattr,
2278         .removexattr_fn = vfswrap_removexattr,
2279         .fremovexattr_fn = vfswrap_fremovexattr,
2280         .setxattr_fn = vfswrap_setxattr,
2281         .fsetxattr_fn = vfswrap_fsetxattr,
2282
2283         /* aio operations */
2284         .aio_read_fn = vfswrap_aio_read,
2285         .aio_write_fn = vfswrap_aio_write,
2286         .aio_return_fn = vfswrap_aio_return,
2287         .aio_cancel_fn = vfswrap_aio_cancel,
2288         .aio_error_fn = vfswrap_aio_error,
2289         .aio_fsync_fn = vfswrap_aio_fsync,
2290         .aio_suspend_fn = vfswrap_aio_suspend,
2291         .aio_force_fn = vfswrap_aio_force,
2292
2293         /* offline operations */
2294         .is_offline_fn = vfswrap_is_offline,
2295         .set_offline_fn = vfswrap_set_offline
2296 };
2297
2298 NTSTATUS vfs_default_init(void);
2299 NTSTATUS vfs_default_init(void)
2300 {
2301         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2302                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
2303 }
2304
2305