source: vendor/current/source3/modules/vfs_default.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

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